/* Hero: a Slack-identical window with clickable channels. Each channel is one problem Teddo
   solves. Reuses the .slack / .msg / .card / .dots / .stream / .caret vocabulary from otto.css;
   everything here is scoped to .sd so the lower demos are untouched. Slack UI uses the system
   stack (Slack itself uses Lato; we never load it). No new colours: the aubergine sidebar is
   --slack-side, the pane is --slack-bg, highlights are white alphas over the sidebar. */
.slack.sd {
  --sd-font: Lato, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --sd-h: 37rem;
  font-family: var(--sd-font); font-size: .9375rem; line-height: 1.46;
  display: flex; flex-direction: column; min-width: 0;
}
.sd *:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sd .sd-side *:focus-visible { outline-color: #fff; outline-offset: -2px; }

/* Window bar: traffic lights, search pill, the one "Example" mark. */
.sd-bar { display: flex; align-items: center; gap: .75rem; padding: .45rem .75rem; background: var(--slack-side); color: #fff; }
.sd-lights { display: flex; gap: .35rem; flex: 0 0 auto; }
.sd-lights i { width: .6rem; height: .6rem; border-radius: 50%; background: rgba(255,255,255,.28); }
.sd-search { flex: 1 1 auto; min-width: 0; max-width: 22rem; margin-inline: auto; padding: .2rem .7rem; border-radius: .35rem; background: rgba(255,255,255,.14); color: rgba(255,255,255,.78); font-size: .75rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center; }
.sd-example { flex: 0 0 auto; padding: .1rem .45rem; border: 1px solid rgba(255,255,255,.4); border-radius: .25rem; font-size: .6875rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #fff; }

.sd-app { display: grid; grid-template-columns: minmax(9.5rem, 32%) minmax(0, 1fr); height: var(--sd-h); min-height: 0; }

/* Sidebar */
.sd-side { background: var(--slack-side); color: rgba(255,255,255,.72); padding: .6rem 0 1rem; overflow-y: auto; border-top: 1px solid rgba(255,255,255,.12); min-width: 0; }
.sd-ws { display: flex; align-items: center; gap: .3rem; padding: .15rem 1rem .7rem; color: #fff; font-weight: 800; font-size: 1.0625rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sd-ws svg { width: .8rem; height: .8rem; flex: 0 0 auto; stroke: currentColor; fill: none; stroke-width: 2.5; }
.sd-tabs { display: flex; flex-direction: column; }
.sd-sec { display: flex; align-items: center; gap: .35rem; padding: .7rem 1rem .25rem; font-size: .875rem; color: rgba(255,255,255,.72); }
.sd-sec::before { content: ""; width: 0; height: 0; border-left: .28rem solid transparent; border-right: .28rem solid transparent; border-top: .36rem solid currentColor; }
.sd-tab { display: flex; align-items: center; gap: .5rem; width: calc(100% - 1rem); margin: 0 .5rem; padding: .22rem .5rem; border: 0; border-radius: .35rem; background: transparent; color: inherit; font: inherit; font-size: .9375rem; text-align: left; cursor: pointer; white-space: nowrap; min-height: 1.9rem; -webkit-tap-highlight-color: transparent; }
.sd-tab:hover { background: rgba(255,255,255,.1); }
.sd-tab .sd-hash { width: 1rem; text-align: center; opacity: .8; flex: 0 0 auto; }
.sd-tab .sd-name { overflow: hidden; text-overflow: ellipsis; }
.sd-tab.is-unread { color: #fff; font-weight: 800; }
.sd-tab[aria-selected="true"] { background: rgba(255,255,255,.24); color: #fff; font-weight: 700; }
.sd-dm-av { position: relative; width: 1.25rem; height: 1.25rem; flex: 0 0 auto; border-radius: .25rem; background: var(--accent); color: var(--on-accent); display: grid; place-items: center; font-size: .6875rem; font-weight: 800; }
.sd-dm-av::after { content: ""; position: absolute; right: -.2rem; bottom: -.2rem; width: .5rem; height: .5rem; border-radius: 50%; background: #2bac76; box-shadow: 0 0 0 2px var(--slack-side); }
.sd-app-tag { margin-left: auto; font-size: .625rem; font-weight: 700; opacity: .7; letter-spacing: .04em; }

/* Main column: one tabpanel per channel = header, message pane, composer. */
.sd-main { min-width: 0; min-height: 0; display: flex; flex-direction: column; background: var(--slack-bg); }
.sd-panel { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.sd-panel[hidden] { display: none; }
.sd-panel:focus-visible { outline-offset: -2px; }
.sd-head { display: flex; align-items: center; gap: .5rem; padding: .55rem 1rem; border-bottom: 1px solid var(--rule); min-height: 2.9rem; }
.sd-head b { font-weight: 800; font-size: 1.0625rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sd-head .app-badge { margin-left: .1rem; padding: .05em .35em; border-radius: .25rem; background: var(--paper-2); color: var(--ink-3); font-size: .625rem; font-weight: 700; letter-spacing: .04em; }
.sd-members { margin-left: auto; display: inline-flex; align-items: center; gap: .3rem; padding: .15rem .45rem; border: 1px solid var(--rule); border-radius: .35rem; color: var(--ink-2); font-size: .8125rem; font-weight: 700; font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.sd-members svg { width: .9rem; height: .9rem; stroke: currentColor; fill: none; stroke-width: 2; }

.sd-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: .5rem 1rem .75rem; display: flex; flex-direction: column; gap: .9rem; }
.sd-scroll > :first-child { margin-top: auto; }
.sd-day { display: flex; align-items: center; gap: .6rem; color: var(--ink-2); font-size: .75rem; font-weight: 700; }
.sd-day::before, .sd-day::after { content: ""; flex: 1; height: 1px; background: var(--rule); }
.sd-day span { padding: .1rem .6rem; border: 1px solid var(--rule); border-radius: 999px; }
.sd .msg .txt { overflow-wrap: anywhere; }

/* Composer */
.sd-composer { margin: 0 1rem 1rem; border: 1px solid var(--rule); border-radius: .5rem; background: var(--slack-bg); }
.sd-input { position: relative; min-height: 2.5rem; padding: .6rem .75rem .3rem; color: var(--ink); overflow-wrap: anywhere; }
.sd-ph { color: var(--ink-3); }
.sd-composer.has-text .sd-ph { display: none; }
.sd-tools { display: flex; align-items: center; gap: .6rem; padding: .25rem .5rem .4rem; color: var(--ink-3); }
.sd-tools svg { width: 1rem; height: 1rem; stroke: currentColor; fill: none; stroke-width: 2; }
.sd-send { margin-left: auto; width: 1.9rem; height: 1.6rem; border-radius: .3rem; display: grid; place-items: center; color: var(--ink-3); }
.sd-composer.has-text .sd-send { background: var(--accent); color: var(--on-accent); }

/* Animation states: only when JS runs the choreography (.sd-js). Without JS or with reduced
   motion every panel is its finished conversation, nothing hidden. */
.sd .caret { display: none; width: 2px; height: 1em; margin-left: 1px; background: var(--ink); vertical-align: text-bottom; }
.sd.sd-js .sd-composer.is-typing .caret { display: inline-block; animation: blink .9s steps(1) infinite; }
.sd.sd-js .msg.sd-wait { display: none; }
.sd.sd-js .msg.is-shown { animation: rise .35s var(--ease) both; }
.sd.sd-js .chunk { opacity: 0; transition: opacity .25s var(--ease); }
.sd.sd-js .chunk.in { opacity: 1; }
.sd.sd-js .card.sd-wait { display: none; }
.sd.sd-js .card.is-shown { animation: rise .3s var(--ease) both; }

/* Result cards inside the pane. */
.sd .card { max-width: 26rem; }
.sd .redlines li { font-size: .75rem; }
.sd .card .row span:first-child { color: var(--ink-2); }
.sd .card .row > span:last-child { text-align: right; }
.sd .card .src { margin-top: .4rem; color: var(--ink-3); font-size: .75rem; }
.sd .mail { margin-top: .5rem; padding-top: .45rem; border-top: 1px solid var(--rule-2); font-size: .8125rem; }
.sd .mail dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: .1rem .6rem; }
.sd .mail dt { color: var(--ink-3); }
.sd .mail dd { margin: 0; }
.sd .mail p { margin: .45rem 0 0; color: var(--ink-2); }
.sd .ext { display: inline-block; margin-left: .3em; padding: 0 .35em; border-radius: .25rem; background: var(--warn-tint); color: var(--warn); font-size: .6875rem; font-weight: 700; }
.sd .msg .acts span { cursor: default; }
.sd .cal .row b { display: inline; font-weight: 600; }
.sd .cal .row .t { flex: 0 0 4.2rem; color: var(--ink-2); }
.sd .cal .row > span.w { flex: 1 1 auto; text-align: left; }
.sd .cal .row.free .w { color: var(--accent); font-weight: 600; }
/* Ranked list inside a result card (e.g. top complaints with ticket counts). */
.sd .sd-rank { list-style: none; counter-reset: sd-rank; margin: .5rem 0 0; padding: 0; font-size: .8125rem; }
.sd .sd-rank li { counter-increment: sd-rank; display: flex; align-items: baseline; gap: .6rem; padding: .2rem 0; border-top: 1px solid var(--rule-2); font-variant-numeric: tabular-nums; }
.sd .sd-rank li::before { content: counter(sd-rank); flex: 0 0 .8rem; color: var(--ink-3); font-weight: 600; }
.sd .sd-rank li span:first-child { flex: 1 1 auto; min-width: 0; color: var(--ink); }
.sd .sd-rank li span:last-child { flex: 0 0 auto; color: var(--ink-2); font-weight: 600; }

.sd-sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Touch screens and phones: a vertical swipe anywhere over a Slack window scrolls the PAGE.
   The message pane stops being an inner scroller: it sizes to its conversation (never shorter
   than the window height, so nothing jumps) and only accepts vertical pans, which it hands to
   the page. The channel list keeps its own sideways scroll but never holds a vertical pan
   (touch-action: pan-x alone would block page scrolling, so both axes are allowed and it has
   no vertical overflow to consume them). Applies to the hero (#demo) and the merged demo. */
@media (max-width: 40rem), (hover: none) and (pointer: coarse) {
  .sd-app { height: auto; min-height: var(--sd-h); }
  .sd-main, .sd-panel, .sd-scroll { touch-action: pan-y; }
  .sd-scroll { overflow: visible; overscroll-behavior: auto; }
  .sd-side { overflow-y: hidden; touch-action: pan-x pan-y; overscroll-behavior-x: contain; }
}

/* Phones: the sidebar becomes a horizontal channel strip above the pane (it scrolls sideways
   inside itself; the page never does). */
@media (max-width: 40rem) {
  .slack.sd { --sd-h: 30rem; font-size: .875rem; }
  .sd-search { display: none; }
  .sd-example { margin-left: auto; }
  .sd-app { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); height: auto; min-height: 0; }
  .sd-side { padding: .35rem 0; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
  .sd-side::-webkit-scrollbar { display: none; }
  .sd-ws, .sd-sec { display: none; }
  .sd-tabs { flex-direction: row; gap: .25rem; padding: 0 .5rem; width: max-content; }
  .sd-tab { width: auto; margin: 0; padding: .35rem .6rem; min-height: 2.25rem; }
  .sd-app-tag { display: none; }
  .sd-main { min-height: var(--sd-h); }
  .sd-scroll { padding-inline: .75rem; }
  .sd-head { padding-inline: .75rem; }
  .sd-composer { margin: 0 .75rem .75rem; }
}

/* Action buttons under a result: now a sibling of the message body (so Telegram can hang them
   under the bubble as an inline keyboard). Slack keeps them in the content column. */
.sd .msg > .acts { grid-column: 2; margin-top: -.15rem; }
.sd.sd-js .acts.sd-wait { display: none; }
.sd.sd-js .acts.is-shown { animation: rise .3s var(--ease) both; }

/* ================= Slack / Telegram switch ================= */
.sd-stage { min-width: 0; }
.chat-switch { display: flex; width: max-content; max-width: 100%; margin: 1rem auto 0; padding: 3px; gap: 2px; border: 1px solid var(--rule); border-radius: .6rem; background: var(--paper); }
.chat-switch[hidden] { display: none; }
.chat-switch button { display: inline-flex; align-items: center; justify-content: center; gap: .5rem; min-height: 2.75rem; min-width: 7.5rem; padding: 0 1.1rem; border: 0; border-radius: .45rem; background: transparent; color: var(--ink-2); font: 600 .9375rem/1 var(--font); cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background-color .18s var(--ease), color .18s var(--ease); }
.chat-switch button:hover { color: var(--ink); background: var(--paper-2); }
.chat-switch button[aria-checked="true"] { background: var(--ink); color: var(--paper); }
.chat-switch button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.chat-switch .cs-mark { width: 1rem; height: 1rem; flex: 0 0 auto; fill: currentColor; }
.otto-demo .chat-switch { margin-top: 1.25rem; }
@media (prefers-reduced-motion: reduce) { .chat-switch button { transition: none; } }

/* ================= Telegram skin (.is-tg) =================
   Telegram Desktop, light theme, on the same markup as the Slack window. Brand colours are
   scoped --tg-* tokens used only inside this mock (as --slack-side is for Slack); a few are a
   shade deeper than Telegram's own so small text keeps 4.5:1. Night theme follows the page. */
.slack.sd {
  --tg-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Open Sans", "Helvetica Neue", Arial, sans-serif;
  --tg-side: #ffffff; --tg-chat: #e6ebee; --tg-in: #ffffff; --tg-out: #effdde; --tg-ink: #15181a; --tg-ink-2: #6b7075;
  --tg-line: #e1e5e8; --tg-blue: #3390ec; --tg-sel: #2574c4; --tg-link: #1a6fb4; --tg-out-meta: #2f7d34; --tg-name: #2f7d34;
  --tg-teddo: #34893a; --tg-pill: rgba(44, 62, 80, .7); --tg-kb: rgba(255, 255, 255, .92); --tg-hover: #f4f4f5; --tg-search: #f1f3f4; --tg-row-sel: #3390ec; --tg-badge: #3390ec; --tg-tab: #3390ec;
  --tg-shadow: 0 1px 2px rgba(16, 35, 47, .15);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .slack.sd {
    --tg-side: #17212b; --tg-chat: #0e1621; --tg-in: #182533; --tg-out: #2b5278; --tg-ink: #f5f5f5; --tg-ink-2: #8a9aa9;
    --tg-line: #0b1118; --tg-blue: #3e8ed8; --tg-sel: #2b5278; --tg-link: #6ab3f3; --tg-out-meta: #9cc8f0; --tg-name: #7fcf8a;
    --tg-teddo: #34893a; --tg-pill: rgba(0, 0, 0, .45); --tg-kb: #243447; --tg-hover: #202b36; --tg-search: #242f3d; --tg-row-sel: #2b5278; --tg-badge: #4082bc; --tg-tab: #5eb5f7;
    --tg-shadow: 0 1px 2px rgba(0, 0, 0, .35);
  }
}
:root[data-theme="dark"] .slack.sd {
  --tg-side: #17212b; --tg-chat: #0e1621; --tg-in: #182533; --tg-out: #2b5278; --tg-ink: #f5f5f5; --tg-ink-2: #8a9aa9;
  --tg-line: #0b1118; --tg-blue: #3e8ed8; --tg-sel: #2b5278; --tg-link: #6ab3f3; --tg-out-meta: #9cc8f0; --tg-name: #7fcf8a;
  --tg-teddo: #34893a; --tg-pill: rgba(0, 0, 0, .45); --tg-kb: #243447; --tg-hover: #202b36; --tg-search: #242f3d; --tg-row-sel: #2b5278; --tg-badge: #4082bc; --tg-tab: #5eb5f7;
  --tg-shadow: 0 1px 2px rgba(0, 0, 0, .35);
}
.sd:not(.is-tg) .tg-only { display: none !important; }
.sd.is-tg .sk-only { display: none !important; }

.slack.sd.is-tg { font-family: var(--tg-font); background: var(--tg-side); color: var(--tg-ink); }
.sd.is-tg *:focus-visible { outline-color: var(--tg-link); }
.sd.is-tg svg { stroke-linecap: round; stroke-linejoin: round; }
.sd.is-tg .tg-fill { fill: currentColor; stroke: none !important; }

/* Window bar */
.sd.is-tg .sd-bar { background: var(--tg-side); color: var(--tg-ink); border-bottom: 1px solid var(--tg-line); }
.sd.is-tg .sd-lights i { background: #c9ced3; }
.sd.is-tg .sd-search { display: none; }
.tg-wintitle { flex: 1 1 auto; text-align: center; font-size: .8125rem; font-weight: 600; color: var(--tg-ink-2); }
.sd.is-tg .sd-example { border-color: var(--tg-line); color: var(--tg-ink-2); }

/* Chat list: Telegram Desktop's left column. Search row (menu + rounded field), then 64px chat
   rows: 54px two-tone round avatar, name and time on line one, "Teddo: preview…" and the unread
   pill on line two. No rules between rows; the open chat is a solid blue row. */
.sd.is-tg .sd-app { grid-template-columns: minmax(15.25rem, 42%) minmax(0, 1fr); }
.sd.is-tg .sd-side { background: var(--tg-side); color: var(--tg-ink); border-top: 0; border-right: 1px solid var(--tg-line); padding: 0 0 .5rem; }
.sd.is-tg .sd-ws, .sd.is-tg .sd-sec { display: none; }
.tg-search { display: flex; align-items: center; gap: .75rem; padding: .5rem .75rem .5rem .875rem; color: var(--tg-ink-2); }
.tg-search > svg { width: 1.375rem; height: 1.375rem; flex: 0 0 auto; stroke: currentColor; fill: none; stroke-width: 1.9; }
.tg-field { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: .5rem; height: 2.25rem; padding: 0 .75rem; border-radius: 1.125rem; background: var(--tg-search); font-size: .875rem; }
.tg-field svg { width: 1.125rem; height: 1.125rem; flex: 0 0 auto; stroke: currentColor; fill: none; stroke-width: 2; }
.sd.is-tg .sd-tab { display: grid; grid-template-columns: 3.375rem minmax(0, 1fr); gap: .75rem; align-items: center; width: 100%; margin: 0; padding: .3125rem .75rem; border-radius: 0; min-height: 4rem; color: var(--tg-ink); font-weight: 400; line-height: 1.3; transition: background-color .12s ease-out; }
.sd.is-tg .sd-tab:hover { background: var(--tg-hover); }
.sd.is-tg .sd-tab[aria-selected="true"] { background: var(--tg-row-sel); color: #fff; font-weight: 400; }
.sd.is-tg .sd-tab.is-unread { color: var(--tg-ink); font-weight: 400; }
.sd.is-tg .sd-side *:focus-visible { outline-color: var(--tg-link); outline-offset: -2px; }
.sd.is-tg .sd-side .sd-tab[aria-selected="true"]:focus-visible { outline-color: #fff; outline-offset: -3px; }
.tg-av { --av: #65aadd; display: grid; place-items: center; width: 3.375rem; height: 3.375rem; border-radius: 50%; background-color: var(--av); background-image: linear-gradient(to bottom, color-mix(in srgb, var(--av) 86%, #fff), color-mix(in srgb, var(--av) 90%, #000)); color: #fff; font-size: 1.25rem; font-weight: 600; line-height: 1; }
.tg-c0 { --av: #e17076; } .tg-c1 { --av: #faa774; } .tg-c2 { --av: #a695e7; } .tg-c3 { --av: #7bc862; }
.tg-c4 { --av: #6ec9cb; } .tg-c5 { --av: #65aadd; } .tg-c6 { --av: #ee7aae; }
.tg-av.tg-teddo { --av: var(--tg-teddo); }
.tg-body { min-width: 0; display: grid; gap: .125rem; }
.tg-l1, .tg-l2 { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.tg-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; font-size: .9375rem; }
.tg-time { flex: 0 0 auto; font-size: .75rem; color: var(--tg-ink-2); font-variant-numeric: tabular-nums; }
.tg-prev { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .875rem; color: var(--tg-ink-2); }
.tg-from { color: var(--tg-ink); }
.tg-badge { flex: 0 0 auto; min-width: 1.375rem; height: 1.375rem; padding: 0 .4rem; border-radius: 999px; background: var(--tg-badge); color: #fff; font-size: .75rem; font-weight: 600; line-height: 1; display: grid; place-items: center; font-variant-numeric: tabular-nums; }
.sd-tab:not(.is-unread) .tg-badge { display: none; }
.sd.is-tg .sd-tab[aria-selected="true"] .tg-time, .sd.is-tg .sd-tab[aria-selected="true"] .tg-prev, .sd.is-tg .sd-tab[aria-selected="true"] .tg-from { color: #fff; }
.sd.is-tg .sd-tab[aria-selected="true"] .tg-badge { background: #fff; color: var(--tg-row-sel); }
@media (prefers-reduced-motion: reduce) { .sd.is-tg .sd-tab { transition: none; } }
/* Chat area */
.sd.is-tg .sd-main { background: var(--tg-chat); }
.sd.is-tg .sd-head { background: var(--tg-side); border-bottom: 1px solid var(--tg-line); padding: .4rem 1rem; min-height: 3.375rem; }
.tg-head { display: grid; min-width: 0; line-height: 1.25; }
.tg-hname { font-weight: 600; font-size: 1rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tg-hsub { margin-top: .0625rem; font-size: .8125rem; color: var(--tg-ink-2); white-space: nowrap; }
.tg-typing { display: none; color: var(--tg-link); }
.sd.is-tg .sd-panel:has(.msg.is-typing) .tg-idle { display: none; }
.sd.is-tg .sd-panel:has(.msg.is-typing) .tg-typing { display: inline; }
.tg-ell { display: inline-flex; gap: 2px; margin-left: 2px; }
.tg-ell i { width: 3px; height: 3px; border-radius: 50%; background: currentColor; animation: blink 1s infinite; }
.tg-ell i:nth-child(2) { animation-delay: .15s; } .tg-ell i:nth-child(3) { animation-delay: .3s; }
.tg-hicons { margin-left: auto; display: inline-flex; gap: .9rem; color: var(--tg-ink-2); flex: 0 0 auto; }
.tg-hicons svg { width: 1.2rem; height: 1.2rem; stroke: currentColor; fill: none; stroke-width: 2; }

.sd.is-tg .sd-scroll { gap: .45rem; padding: .6rem .9rem .75rem; }
.sd.is-tg .sd-day { justify-content: center; color: #fff; font-weight: 600; }
.sd.is-tg .sd-day::before, .sd.is-tg .sd-day::after { display: none; }
.sd.is-tg .sd-day span { border: 0; padding: .15rem .6rem; background: var(--tg-pill); }

/* Messages: the person asking is "you" (outgoing, right); Teddo is incoming (left). */
.sd.is-tg .msg { grid-template-columns: 2.1rem minmax(0, 1fr); gap: .15rem .45rem; }
.sd.is-tg .msg:not(.otto) { grid-template-columns: minmax(0, 1fr); }
.sd.is-tg .msg:not(.otto) > .av { display: none; }
.sd.is-tg .msg .av { width: 2.1rem; height: 2.1rem; border-radius: 50%; align-self: end; background: var(--tg-teddo); color: #fff; font-size: .875rem; font-weight: 600; }
.sd.is-tg .tg-dm .msg { grid-template-columns: minmax(0, 1fr); }
.sd.is-tg .tg-dm .msg > .av { display: none; }
.sd.is-tg .tg-bub { display: flex; flex-direction: column; min-width: 0; max-width: min(100%, 27rem); justify-self: start; padding: .35rem .65rem .3rem; border-radius: .9rem .9rem .9rem .3rem; background: var(--tg-in); box-shadow: var(--tg-shadow); }
.sd.is-tg .msg:not(.otto) > .tg-bub { justify-self: end; border-radius: .9rem .9rem .3rem .9rem; background: var(--tg-out); max-width: min(88%, 27rem); }
.sd.is-tg .msg > .tg-bub:has(.card) { width: min(100%, 24rem); }
.sd.is-tg .tg-bub .who { order: 0; font-size: .8125rem; font-weight: 600; color: var(--tg-name); }
.sd.is-tg .msg:not(.otto) .who, .sd.is-tg .tg-dm .who, .sd.is-tg .tg-bub .app-badge { display: none; }
.sd.is-tg .tg-bub .txt { order: 1; margin: 0; line-height: 1.4; }
.sd.is-tg .tg-bub .card, .sd.is-tg .tg-bub .pa-chips { order: 2; }
.sd.is-tg .tg-bub .when { order: 5; align-self: flex-end; margin: .05rem -.1rem 0 .75rem; font-size: .6875rem; line-height: 1.2; color: var(--tg-ink-2); display: inline-flex; align-items: center; gap: .2rem; }
.sd.is-tg .msg:not(.otto) .tg-bub .when { color: var(--tg-out-meta); }
.sd.is-tg .msg:not(.otto) .tg-bub .when::after { content: ""; width: 1rem; height: .7rem; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 11'%3E%3Cpath d='M1 5.8 4 8.8 10.5 2.2M6.6 8.4l.5.5 7-7' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 11'%3E%3Cpath d='M1 5.8 4 8.8 10.5 2.2M6.6 8.4l.5.5 7-7' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
.sd.is-tg .mention { display: inline; padding: 0; background: none; color: var(--tg-link); font-weight: 400; }
/* No dots in the bubble: Telegram says "typing..." in the chat header instead, and the bubble
   appears when the first words arrive. */
.sd.is-tg .msg.is-typing { display: none; }

/* Result cards become document attachments: round file icon, name, size, then the caption. */
.sd.is-tg .card { margin-top: .35rem; padding: 0; border: 0; background: none; max-width: none; font-size: .8125rem; }
.sd.is-tg .card-head { display: grid; grid-template-columns: 2.75rem minmax(0, 1fr); gap: .65rem; align-items: center; margin-bottom: .35rem; }
.sd.is-tg .card-head .card-icon { width: 2.75rem; height: 2.75rem; margin: 0; padding: .7rem; border-radius: 50%; background: var(--tg-blue); color: #fff; stroke: #fff; }
.sd.is-tg .card-head b { display: block; font-size: .875rem; font-weight: 600; overflow-wrap: anywhere; line-height: 1.25; }
.sd.is-tg .card-head span { color: var(--tg-ink-2); font-size: .75rem; }
.sd.is-tg .card .row { border-top-color: var(--tg-line); padding: .15rem 0; }
.sd.is-tg .card .row span:first-child, .sd.is-tg .card .src, .sd.is-tg .mail dt { color: var(--tg-ink-2); }
.sd.is-tg .card .up { color: var(--tg-out-meta); }
.sd.is-tg .mail { border-top-color: var(--tg-line); }
.sd.is-tg .mail p { color: var(--tg-ink); }
.sd.is-tg .sd-rank li { border-top-color: var(--tg-line); }
.sd.is-tg .sd-rank li::before, .sd.is-tg .sd-rank li span:last-child { color: var(--tg-ink-2); }
.sd.is-tg .pa-chips { flex-direction: column; gap: .35rem; }
.sd.is-tg .pa-chips span { padding: 0; border: 0; background: none; color: var(--tg-ink); font-size: .875rem; font-weight: 600; gap: .65rem; }
.sd.is-tg .pa-chips svg { width: 2.5rem; height: 2.5rem; padding: .6rem; border-radius: 50%; background: var(--tg-blue); stroke: #fff; }

/* Send / Edit: an inline keyboard hanging under the bubble. */
.sd.is-tg .msg > .acts { grid-column: 2; margin: 0; gap: .25rem; width: min(100%, 24rem); }
.sd.is-tg .tg-dm .msg > .acts { grid-column: 1; }
.sd.is-tg .msg .acts span, .sd.is-tg .msg .acts span.go { flex: 1 1 0; text-align: center; padding: .5rem .6rem; border: 0; border-radius: .55rem; background: var(--tg-kb); color: var(--tg-link); font-size: .8125rem; font-weight: 600; box-shadow: var(--tg-shadow); }

/* Composer: "Write a message..." with attach on the left, emoji and send / mic on the right. */
.sd.is-tg .sd-composer { display: flex; align-items: center; gap: .25rem; margin: 0; padding: .2rem .5rem; border: 0; border-top: 1px solid var(--tg-line); border-radius: 0; background: var(--tg-side); }
.sd.is-tg .sd-input { flex: 1 1 auto; min-width: 0; padding: .55rem .35rem; min-height: 2.6rem; color: var(--tg-ink); }
.sd.is-tg .sd-ph { display: block; color: var(--tg-ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sd.is-tg .sd-composer.has-text .sd-ph { display: none; }
.sd.is-tg .caret { background: var(--tg-blue); }
.tg-cright { display: inline-flex; align-items: center; gap: .25rem; flex: 0 0 auto; }
.tg-cicon { display: grid; place-items: center; width: 2.1rem; height: 2.1rem; flex: 0 0 auto; color: var(--tg-ink-2); }
.tg-cicon svg { width: 1.35rem; height: 1.35rem; stroke: currentColor; fill: none; stroke-width: 1.8; }
.tg-send { display: none; color: var(--tg-blue); }
.sd-composer.has-text .tg-send { display: grid; }
.sd-composer.has-text .tg-mic { display: none; }

/* Phones: Telegram mobile shows one screen at a time, so the chat list becomes its folder tabs:
   a white bar of text tabs (scrolls sideways inside itself), the open one blue with a 3px
   underline; the chat fills the rest. Same buttons, same tab semantics. */
@media (max-width: 40rem) {
  .sd.is-tg .sd-app { grid-template-columns: minmax(0, 1fr); }
  .sd.is-tg .sd-side { padding: 0; border-right: 0; border-bottom: 1px solid var(--tg-line); }
  .sd.is-tg .tg-search { display: none; }
  .sd.is-tg .sd-tabs { gap: 0; padding: 0 .375rem; }
  .sd.is-tg .sd-tab { position: relative; display: flex; align-items: center; width: auto; min-height: 2.75rem; padding: 0 .75rem; border-radius: 0; background: transparent; color: var(--tg-ink-2); font-size: .875rem; font-weight: 500; transition: color .15s ease-out; }
  .sd.is-tg .sd-tab:hover { background: transparent; color: var(--tg-ink); }
  .sd.is-tg .sd-tab[aria-selected="true"] { background: transparent; color: var(--tg-tab); }
  .sd.is-tg .sd-tab[aria-selected="true"]::after { content: ""; position: absolute; left: .75rem; right: .75rem; bottom: 0; height: 3px; border-radius: 3px 3px 0 0; background: var(--tg-tab); }
  .sd.is-tg .sd-tab.is-unread:not([aria-selected="true"]) { color: var(--tg-ink-2); }
  .sd.is-tg .sd-side .sd-tab[aria-selected="true"]:focus-visible { outline-color: var(--tg-link); outline-offset: -2px; }
  .sd.is-tg .tg-av, .sd.is-tg .tg-l2, .sd.is-tg .tg-time { display: none; }
  .sd.is-tg .tg-body, .sd.is-tg .tg-l1 { display: contents; }
  .sd.is-tg .tg-title { flex: 0 0 auto; overflow: visible; font-size: .875rem; font-weight: 500; }
  .sd.is-tg .sd-head { padding-inline: .75rem; }
  .sd.is-tg .sd-scroll { padding-inline: .6rem; }
  .sd.is-tg .tg-hicons { gap: .6rem; }
  .chat-switch button { min-width: 0; flex: 1 1 0; }
  .chat-switch { width: 100%; max-width: 20rem; }
}
/* Consecutive Teddo messages group like Telegram's: one name on top, one avatar at the bottom. */
.sd.is-tg .msg.otto:has(+ .msg.otto:not(.od-wait):not(.pa-wait):not(.sd-wait):not(.is-typing)) > .av { visibility: hidden; }
.sd.is-tg .msg.otto + .msg.otto .who { display: none; }
