/* =========================================================================
   Derslik — chat slice (slice 5): the channel header, live strip, message
   list, message row, poll card and composer. v5:552-670.

   Loaded after tokens.css → styles.css → base.css → shell-extra.css, so most
   of what is here is either (a) a piece base.css does not declare because it
   is chat-specific, or (b) a targeted neutralisation of the pre-reskin rule in
   styles.css that would otherwise fight the dk-* primitive underneath it. The
   legacy class names are all kept: `public/chat.js`, `public/guild.js` and
   `public/voice.js` read them (spec §1.4 / §3.3).

   Anything marked "candidate for base.css" is a primitive the component
   catalogue implies but base.css does not declare yet.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. The pane itself
   `styles.css` padded `.message-panel` and gave `.channel-topic` its own
   border + margin. The dk pane owns that spacing now (`.dk-pane__head`), so
   the panel becomes a plain column and every child sets its own gutter.
   ------------------------------------------------------------------------- */
.message-panel {
  flex: 1;
  padding: 0;
  background: transparent;
  /* The header has to respond to the *pane*, not the window: with the channel
     panel open the pane is ~1030px of a 1440px viewport, and a media query
     cannot tell those apart. All the absolutely-positioned things inside the
     pane (poll bar, search icon, E2EE popover) sit in their own
     `position:relative` boxes, so the containment this turns on is inert. */
  container-type: inline-size;
  container-name: chatpane;
}

/* `nowrap` on purpose: with `wrap`, flexbox breaks the line *instead of*
   shrinking, so the whole tool row dropped below the title when the header was
   one pixel too wide. Nowrap lets the topic truncate first. */
.message-panel > .dk-pane__head.channel-topic {
  justify-content: flex-start;
  flex-wrap: nowrap;
  gap: var(--sp-4);
  margin-bottom: 0;
  padding: var(--sp-6) var(--sp-9);
}

/* One header row for as long as possible: the title block takes the slack and
   the topic truncates, instead of the whole tool row dropping to a second line
   the moment the channel panel narrows the pane. */
/* nowrap here too, for the same reason as the header: the topic must truncate
   (it has ellipsis) rather than push the chips onto a second line. */
.channel-topic-main {
  flex: 0 1 auto;
  min-width: 0;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: nowrap;
}
/* The tool row shrinks by squeezing the search field (down to ~7rem) before
   anything wraps: with the channel panel open the pane is ~1030px and v5's
   single-row header only fits because v5 has no search, no Materyaller and no
   Sınavlar — those are ours (spec §4.4). */
.message-panel > .dk-pane__head .channel-tools {
  flex: 0 1 auto;
  min-width: 0;
  margin-left: auto;
}
.message-panel > .dk-pane__head .channel-tools > .tool-btn,
.message-panel > .dk-pane__head .channel-tools > .dk-ibtn { flex: none; }
.channel-topic .dk-pane__title { font-size: var(--fs-2xl); }
/* v5:558 — a 28px accent-soft box holds the channel glyph. */
.message-panel .channel-hash {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: var(--r-xs);
  background: var(--accSoft);
  color: var(--accText); /* H-87: the accent as text, >= 4.5:1 on --accSoft in every theme */
}
.channel-topic-text {
  flex: 0 1 auto;
  min-width: 3ch;
  max-width: 28ch;
  font-size: var(--fs-sm);
}
.channel-topic-text::before { content: "— "; }

.channel-tools { gap: var(--sp-3); flex-wrap: nowrap; }

/* The search box is just a positioning wrapper now — the border, radius and
   focus ring come from `.dk-input--sm` on the field itself. */
.search-box {
  position: relative;
  display: block;
  flex: 0 1 auto;
  min-width: 7rem;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: 0;
}
.search-box .search-icon {
  position: absolute;
  top: 50%;
  left: var(--sp-5);
  transform: translateY(-50%);
  display: flex;
  color: var(--mut);
  pointer-events: none;
  opacity: 1;
  font-size: inherit;
}
.search-box .search-input {
  width: 100%;
  max-width: 11.5rem;
  padding-left: calc(var(--sp-6) + 18px);
  background: var(--panel2);
}

/* -------------------------------------------------------------------------
   2. Live strip (v5:571-581) — this view renders the empty `[data-live-strip]`
   container; `public/voice.js` fills it and owns the class names of what goes
   inside (`.ls-dot`/`.ls-label`/`.ls-text`/`.ls-stack`), which `dk/voice.css`
   styles next to the rest of the voice surface. Keeping a second, differently
   named set of children here only invited the two to drift, so the inner rules
   live in one place. `.dk-livestrip` itself (plate + `[hidden]`) is base.css.

   What stays here is the one thing that is a *chat-pane* concern: the plate is
   hardcoded dark (v5:572), so a theme's soft badge tints would land light-on-
   dark. Re-tint them against #1B1826 the way v5:580 does.
   ------------------------------------------------------------------------- */
.dk-livestrip .dk-badge { background: rgba(255, 255, 255, 0.12); color: #efeff8; }
.dk-livestrip .dk-badge.is-warn { background: rgba(217, 169, 74, 0.15); color: #d9a94a; }
.dk-livestrip .dk-badge.is-ok { background: rgba(127, 242, 184, 0.15); color: #7ff2b8; }

/* -------------------------------------------------------------------------
   3. Message list + rows
   ------------------------------------------------------------------------- */
.dk-msglist.message-list {
  gap: var(--sp-7);
  padding: var(--sp-8) var(--sp-10);
}
.dk-msglist.message-list[hidden] { display: none; }

/* `styles.css` gave `.message` a padded, hover-tinted block; v5 draws the row
   itself with no ground at all, so only the toolbar needs a hover state. */
.dk-msg.message {
  padding: 0;
  border-radius: 0;
  align-items: flex-start;
  gap: var(--sp-5);
}
.dk-msg.message:hover { background: transparent; }
.dk-msg.message.flash .dk-bubble {
  animation: dkFlash 1.4s var(--ease);
}
@keyframes dkFlash {
  from { box-shadow: 0 0 0 3px var(--accSoft); }
  to { box-shadow: var(--shadow-bubble); }
}

.dk-msg__body.msg-body { flex: 0 1 auto; max-width: 72%; }
.dk-msg__meta.msg-meta { gap: var(--sp-4); flex-wrap: wrap; }
.dk-msg__time.msg-time { font-size: var(--fs-2xs); }
.msg-edited { margin-left: 0; font-size: var(--fs-3xs); }

/* v5:617 — the author's highest derslik role, next to the name. The role's own
   colour comes from the API and can be anything, so the label is mixed toward
   the theme's --ink (the same recipe as --accInkSoft, §6.3): that keeps it
   legible on a light *and* a dark palette instead of trusting the raw hex. */
.msg-role {
  background: color-mix(in srgb, var(--role-color, var(--acc)) 16%, transparent);
  color: color-mix(in srgb, var(--role-color, var(--acc)) 72%, var(--ink));
}

.dk-bubble.msg-content { color: inherit; word-wrap: break-word; overflow-wrap: anywhere; }
.dk-bubble.msg-content .mention { background: color-mix(in srgb, var(--acc) 18%, transparent); color: var(--accText); } /* H-87 */
.dk-bubble--mine.msg-content { color: var(--accInk); }
.dk-bubble--mine.msg-content .mention {
  background: rgba(255, 255, 255, 0.22);
  color: var(--accInk);
}
.dk-bubble.msg-content .i { vertical-align: -2px; }

/* v5:589-591 — a system message is a centred pill, not a row. */
.dk-sysmsg.message {
  display: block;
  width: fit-content;
  max-width: 80%;
  padding: var(--sp-3) var(--sp-7);
}
.dk-sysmsg.message:hover { background: var(--panel2); }
/* `base.css` sizes `.msg-content` from `--chat-fs` ("Sohbet metni boyutu").
   A join/leave pill is chrome, not chat text, so it keeps the pill's own
   `--fs-sm` from `.dk-sysmsg` instead of growing with the setting. */
.dk-sysmsg .msg-content { color: var(--mut); font-size: var(--fs-sm); }

.msg-reply {
  font-size: var(--fs-xs);
  gap: var(--sp-3);
  padding-left: var(--sp-4);
  margin-bottom: var(--sp-2);
  border-left: 2px solid var(--acc);
  max-width: 100%;
}

/* Hover toolbar — v5 has nowhere for edit/delete/report, so it lives on the
   row (spec §4.4). It sits in the flex row next to the bubble rather than
   absolutely at the pane's right edge, so it reads as belonging to the message
   even on a short one; `.dk-msg__body` is `flex: 0 1 auto`, so revealing it
   cannot reflow the bubble. Focus inside it keeps it open for keyboard users. */
.dk-msg .msg-actions {
  position: static;
  flex: none;
  align-self: flex-start;
  margin-top: var(--sp-5);
  gap: var(--sp-1);
  padding: var(--sp-1);
  background: var(--panel);
  border: var(--bw-thin) solid var(--line);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-row);
}
.dk-msg:hover .msg-actions,
.dk-msg:focus-within .msg-actions { display: flex; }
/* D-13: the row itself is the keyboard target now (arrow keys), so it needs a
   ring of its own and has to reveal its actions when it takes focus. */
.dk-msglist:focus-visible,
.dk-msg:focus-visible,
.dk-sysmsg:focus-visible { outline: 2px solid var(--acc); outline-offset: -2px; }
/* A mouse/programmatic focus draws no ring, a KEYBOARD focus does: the old `.dk-msglist:focus { outline: none }` had the same
   specificity as the :focus-visible rule above and came later, so the ring never showed (WCAG 2.4.7, phase-5 ux-msglist-focus-ring). */
.dk-msglist:focus:not(:focus-visible) { outline: none; }
.dk-msg:focus .msg-actions { display: flex; }
.msg-act {
  font: 700 var(--fs-xs) / 1 var(--font);
  color: var(--mut);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-2xs);
}
.msg-act:hover { background: var(--accSoft); color: var(--accInkSoft); }
.msg-act.danger:hover { background: var(--badSoft); color: var(--bad); }
.msg-act:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }

/* -------------------------------------------------------------------------
   4. Reactions + attachments
   ------------------------------------------------------------------------- */
.msg-reactions { gap: var(--sp-3); margin-top: var(--sp-4); }
/* v5 has no reactions at all, so a bare "+" under every single message is pure
   noise the design never asked for: keep the bar in the DOM (chat.js inserts
   live chips into it) but only show the opener while the row has focus or the
   pointer. Browsers without :has() drop the rule and simply keep it visible. */
.dk-msg .msg-reactions:not(:has(.reaction-chip)) { margin-top: 0; }
.dk-msg .msg-reactions:not(:has(.reaction-chip)) .reaction-add {
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease);
}
.dk-msg:hover .msg-reactions .reaction-add,
.dk-msg:focus-within .msg-reactions .reaction-add { opacity: 1; }
.reaction-chip,
.reaction-add {
  border: var(--bw-thin) solid var(--line);
  border-radius: var(--r-2xs);
  background: var(--panel2);
  color: var(--ink);
  font: 700 var(--fs-xs) / 1 var(--font);
  padding: var(--sp-3) var(--sp-4);
  cursor: pointer;
}
.reaction-chip.mine { background: var(--accSoft); border-color: var(--acc); color: var(--accInkSoft); }
.reaction-chip:hover,
.reaction-add:hover { border-color: var(--acc); color: var(--acc); }
.reaction-chip:focus-visible,
.reaction-add:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }

.msg-attachments { gap: var(--sp-4); margin-top: var(--sp-4); align-items: flex-start; }
/* The upstream `width`/`height` on an attachment are always 0 (spec §4.4), so
   an image thumb has to be capped here or a 4000px photo owns the channel. */
.att-image {
  display: block;
  max-width: min(320px, 100%);
  max-height: 220px;
  width: auto;
  height: auto;
  object-fit: cover;
  border-radius: var(--r-md);
  border: var(--bw-thin) solid var(--line);
  background: var(--panel2);
}
.att-image-link:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.att-file {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-6);
  border-radius: var(--r-sm);
  border: var(--bw-thin) solid var(--line);
  background: var(--panel2);
  color: var(--ink);
  font: 700 var(--fs-sm) / 1.2 var(--font);
  text-decoration: none;
}
.att-file:hover { border-color: var(--acc); color: var(--acc); }
.att-file .att-file-size { font-weight: 400; font-size: var(--fs-xs); }

/* -------------------------------------------------------------------------
   5. Poll card — `.dk-poll` is declared in base.css; only the bar fill and the
   two inner spans (which base.css does not know about) live here.
   ------------------------------------------------------------------------- */
.dk-poll.poll {
  max-width: 480px;
  margin-top: var(--sp-4);
  padding: var(--sp-7);
}
.dk-poll .poll-opts { display: flex; flex-direction: column; gap: 0; }
.dk-poll .dk-poll__opt {
  position: relative;
  overflow: hidden;
  justify-content: space-between;
  font: 700 var(--fs-sm) / 1.2 var(--font);
  color: var(--ink);
  text-align: left;
}
.dk-poll .dk-poll__opt:disabled { cursor: default; }
.dk-poll .dk-poll__opt:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
/* The count bar the design drops (v5 shows a bare number); keeping it is the
   one deliberate divergence in this card — spec §3.3 asks for it by name. */
.dk-poll .poll-bar {
  position: absolute;
  inset: 0 auto 0 0;
  z-index: 0;
  background: var(--accSoft);
  transition: width var(--dur-3) var(--ease);
}
.dk-poll .dk-poll__opt.voted { background: var(--accSoft); border-color: var(--acc); }
.dk-poll .dk-poll__opt.voted .poll-bar { background: color-mix(in srgb, var(--acc) 26%, transparent); }
.dk-poll .poll-opt-text { position: relative; z-index: 1; flex: 1; }
.dk-poll .poll-opt-count {
  position: relative;
  z-index: 1;
  color: var(--mut);
  font: 700 var(--fs-xs) / 1 var(--font);
  font-variant-numeric: tabular-nums;
}
.dk-poll .dk-poll__q .i { vertical-align: -2px; }
.dk-poll .dk-poll__foot { margin-top: var(--sp-4); }

/* -------------------------------------------------------------------------
   6. Composer zone (v5:628-668)
   `.dk-composer` (base.css) is the padded footer; the form inside it is the
   row. It cannot carry `.dk-composer__row` as well, because `.composer` is
   matched as a whole class attribute by the hook test — so the row rules are
   applied through the descendant selector instead.
   ------------------------------------------------------------------------- */
.dk-composer > .composer {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  width: 100%;
  margin: 0;
  padding: 0;
  border-top: 0;
  background: transparent;
}
.dk-composer--centered > .composer,
.dk-composer--centered > .reply-bar,
.dk-composer--centered > .attach-preview,
.dk-composer--centered > .poll-composer,
.dk-composer--centered > .dk-notice {
  max-width: 760px;
  margin-inline: auto;
}
.dk-composer .composer-send { flex: none; border-radius: var(--r-md); }
.dk-composer .attach-btn,
.dk-composer .composer-tool {
  /* they are `.dk-ibtn--bare`; only the file input's label needs the pointer */
  cursor: pointer;
  font-size: inherit;
}
.dk-composer .attach-btn:focus-within { outline: 2px solid var(--acc); outline-offset: 2px; }

.dk-composer > .reply-bar {
  margin: 0 0 var(--sp-4);
  padding: var(--sp-4) var(--sp-6);
  border: var(--bw-thin) solid var(--line);
  border-radius: var(--r-sm);
  background: var(--panel2);
  font-size: var(--fs-sm);
}
.dk-composer > .reply-bar .reply-bar-target { color: var(--acc); }
.dk-composer > .attach-preview { margin: 0 0 var(--sp-4); }
.dk-composer .attach-chip {
  border-radius: var(--r-2xs);
  border-color: var(--line);
  background: var(--panel2);
  font-size: var(--fs-xs);
}
.dk-composer > .poll-composer {
  margin: 0 0 var(--sp-4);
  border-radius: var(--r-lg);
  border: var(--bw) solid var(--acc);
  background: var(--panel2);
  padding: var(--sp-6);
  gap: var(--sp-4);
}
.dk-composer > .poll-composer .drawer-head { font: 800 var(--fs-sm) / 1.3 var(--font); color: var(--acc); }
.dk-composer > .poll-composer .poll-answers { gap: var(--sp-3); }
.dk-composer > .poll-composer .perm-check { font-size: var(--fs-sm); color: var(--mut); }
.dk-composer > .poll-composer .link-btn { align-self: flex-start; font-size: var(--fs-sm); }

/* v5:630-635 — the channel is read-only for this viewer. */
.dk-composer > .dk-notice.composer-locked { margin: 0; }
.dk-composer > .dk-notice .i { flex: none; }

.typing-indicator {
  flex: none;
  padding: 0 var(--sp-10) var(--sp-3);
  min-height: var(--sp-8);
  font: 400 var(--fs-sm) / 1.3 var(--font);
  font-style: italic;
  color: var(--mut);
}
.typing-indicator[hidden] { display: none; }

/* -------------------------------------------------------------------------
   7. Search results + threads drawer (chat.js builds both)
   ------------------------------------------------------------------------- */
.search-results,
.threads-drawer {
  flex: none;
  margin: var(--sp-5) var(--sp-9) 0;
  padding: var(--sp-6) var(--sp-7);
  border-radius: var(--r-lg);
  border: var(--bw-thin) solid var(--line);
  background: var(--panel2);
  max-height: 45vh;
  overflow-y: auto;
}
.search-results[hidden],
.threads-drawer[hidden] { display: none; }
/* `justify-content: space-between` (styles.css) scattered the head's text
   nodes across the whole width — each bare word is its own flex item. Pack
   them and push only the close button to the end. */
.drawer-head {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--sp-2);
  font: 700 var(--fs-sm) / 1.3 var(--font);
  margin-bottom: var(--sp-4);
}
.drawer-head .drawer-close { margin-left: auto; }
.search-list { display: flex; flex-direction: column; gap: var(--sp-2); }
.search-result {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-5);
  width: 100%;
  padding: var(--sp-4) var(--sp-5);
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.search-result:hover { background: var(--panel); }
.search-result:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.search-result .msg-body { display: block; min-width: 0; }
.search-result .msg-meta { display: flex; align-items: baseline; gap: var(--sp-4); }
.search-result .msg-content { display: block; font-size: var(--fs-sm); }
.thread-item {
  border-radius: var(--r-sm);
  border-color: var(--line);
  font-size: var(--fs-sm);
}
.thread-create { gap: var(--sp-4); margin-top: var(--sp-5); }

/* -------------------------------------------------------------------------
   8. Emoji picker — chat.js appends it to <body>, so it is outside every pane.
   ------------------------------------------------------------------------- */
.emoji-picker {
  border-radius: var(--r-lg);
  border: var(--bw-thin) solid var(--line);
  background: var(--panel);
  box-shadow: var(--golge);
  z-index: var(--z-popover);
}
.emoji-opt { border-radius: var(--r-2xs); }
.emoji-opt:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }

/* -------------------------------------------------------------------------
   9. Narrow panes: the tool row gives before anything else.
   Ordered by what the user can most afford to lose — the search field's width,
   then the tool labels, then the topic, then the single-row header itself.
   ------------------------------------------------------------------------- */
@container chatpane (max-width: 880px) {
  .channel-tools .tool-btn span { display: none; }
  .channel-tools .tool-btn { padding-inline: var(--sp-5); }
}
@container chatpane (max-width: 620px) {
  .channel-topic-text { display: none; }
}
@container chatpane (max-width: 460px) {
  .message-panel > .dk-pane__head.channel-topic { flex-wrap: wrap; }
  .message-panel > .dk-pane__head .channel-tools { margin-left: 0; }

  /* The composer is the last thing to give, and it has to. In the zoom stage's
     330px lesson rail, three tool buttons + a labelled "Gönder" leave the text
     field ~75px — narrower than its own placeholder, which then renders as
     "#ge". `flex: 1; min-width: 0` (base.css) is doing the right thing; there
     simply is no room. So the field takes a row of its own and the buttons sit
     under it, send pushed to the right. */
  .dk-composer > .composer { flex-wrap: wrap; }
  .dk-composer > .composer > .dk-composer__input { order: -1; flex: 1 0 100%; }
  .dk-composer > .composer > .composer-send { margin-left: auto; }
}

@media (max-width: 900px) {
  .dk-msg__body.msg-body { max-width: 100%; }
  .dk-msglist.message-list { padding: var(--sp-6) var(--sp-7); }
}

/* --- C-23: the "Bildir" reason dialog (replaces window.prompt, dead in Electron) ---
   Built by public/chat.js askReportReason() on the shared scrim/dialog (.dk-scrim, .dk-dialog,
   .dk-input, .dk-btn); only its own parts are here. */
.report-dialog { gap: var(--sp-5); }
.report-dialog__form { display: flex; flex-direction: column; gap: var(--sp-5); }
.report-dialog__input { width: 100%; }
.report-dialog__actions { display: flex; justify-content: flex-end; gap: var(--sp-4); }

/* --- C-26: link / rich embeds under a message (server renderer and live builder emit the same tree) --- */
.msg-embeds { display: flex; flex-direction: column; gap: var(--sp-3); margin-top: var(--sp-3); max-width: 440px; }
.msg-embed {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-5);
  border-left: 3px solid var(--acc);
  border-radius: var(--r-md);
  background: var(--panel2);
}
.msg-embed .embed-title { font: 800 var(--fs-sm) / 1.3 var(--font); color: var(--acc); overflow-wrap: anywhere; }
.msg-embed .embed-desc { font: 400 var(--fs-sm) / 1.4 var(--font); color: var(--mut); overflow-wrap: anywhere; }
.msg-embed .embed-img { max-width: 100%; max-height: 220px; border-radius: var(--r-sm); object-fit: cover; }

/* --- C-07: the guild's custom emojis, drawn in text and in reaction chips ("Derslik emojileri") --- */
/* The box is square-bounded whatever the image is: quedu-api accepts any image URL, and a 1500x14 px emoji with `width:auto`
   rendered 2250 px wide (the bubble 2284, the reaction chip 1607) and ran the message off screen (phase-5
   ux-custom-emoji-aspect). `object-fit: contain` keeps the picture whole inside the box. */
.custom-emoji { height: 1.5em; width: auto; max-width: 1.5em; object-fit: contain; vertical-align: -0.35em; }
.reaction-chip .custom-emoji { height: 1.25em; max-width: 1.25em; vertical-align: -0.25em; }

/* OD-18 (phase 9): a thread in the Konular drawer: its link, and the staff buttons (Arşivle / Kilitle) on the same row. */
.thread-row { display: flex; align-items: center; gap: var(--sp-4); }
.thread-row .thread-item { flex: 1; min-width: 0; }
.thread-actions { display: flex; flex: none; gap: var(--sp-3); }
