/* =========================================================================
   Derslik — dk-* component layer (slice 0).

   Every class here is declared in visual-system §2, with the declarations
   reverse-engineered from the inline styles of `design/Derslik v5.dc.html`.
   Cited line numbers are v5 lines.

   Three things the design does not have and this file adds on purpose:
     * real focus rings on every interactive element (§6.6 / C9) — the design
       has no :focus rule at all and 49 `outline:none`s;
     * an ink token instead of a hardcoded #fff on accent and status fills
       (§6.3 / §6.4);
     * a ::before hit-area expander on the controls that are under 44px
       (§6.8), which does not change a single painted pixel.

   Shell-level components (titlebar, tabstrip, workspace, pane, card, row,
   button, input, badge, avatar, notice, empty, scrim/dialog, swatch grid)
   are complete. Message / composer / voice classes are declared here at the
   level slices 4-6 will build on; their fine detail lands with those slices.

   Load order: tokens.css → styles.css → THIS FILE. Nothing here may be
   edited by the markup builder — new classes go in shell-extra.css.
   ========================================================================= */

/* =========================================================================
   1. Shell — app, title bar, tab strip, workspace
   ========================================================================= */

/* v5:35 — the backdrop is two accent-tinted radials over --bg. */
.dk-app {
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
  color: var(--ink);
  font-family: var(--font);
  background:
    radial-gradient(1100px 500px at 85% -8%, color-mix(in srgb, var(--acc) 6%, transparent), transparent 62%),
    radial-gradient(800px 420px at -10% 108%, color-mix(in srgb, var(--acc) 5%, transparent), transparent 55%),
    var(--bg);
}

/* v5:38 — in the browser build this is the logo lockup only; the three fake
   window buttons render only under <html data-desktop> (decision D1). */
.dk-titlebar {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  height: 38px;
  padding-left: var(--sp-6);
  background: var(--panel);
  border-bottom: var(--bw-thin) solid var(--line);
  user-select: none;
}
/* __logo and __brand are the same slot (the lockup); both names are accepted
   so the markup builder can use either. */
.dk-titlebar__logo,
.dk-titlebar__brand { display: flex; align-items: center; gap: var(--sp-4); }
.dk-titlebar__spacer { flex: 1 1 auto; }
/* --- desktop frame (quedu-desktop) ---------------------------------------
   The Electron shell loads this same BFF with " DerslikDesktop/<sürüm>" in
   its User-Agent; the server answers with <html data-desktop data-platform>
   and renders the three [data-win] buttons into the bar (views/shell.js).
   In the browser build they are not rendered, and if markup emits them
   anyway they stay hidden until <html data-desktop> says otherwise.
   `public/desktop.js` wires them up and mirrors the window state onto
   <html data-maximized>.
   ------------------------------------------------------------------------- */
.dk-titlebar__controls { display: flex; align-self: stretch; margin-left: auto; }
.dk-titlebar__win,
.dk-titlebar__btn { display: none; }

/* The bar is the window's drag handle; everything clickable on it is not. */
html[data-desktop] .dk-titlebar[data-drag-region] {
  -webkit-app-region: drag;
  app-region: drag;
  user-select: none;
}
html[data-desktop] .dk-titlebar a,
html[data-desktop] .dk-titlebar button,
html[data-desktop] .dk-titlebar input,
html[data-desktop] .dk-titlebar__controls {
  -webkit-app-region: no-drag;
  app-region: no-drag;
}

html[data-desktop] .dk-titlebar__win,
html[data-desktop] .dk-titlebar__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--hit-md); /* 44px — v5:123 */
  align-self: stretch;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--mut);
  cursor: default;
  font-family: inherit;
  font-size: var(--fs-sm);
  line-height: 1;
}
html[data-desktop] .dk-titlebar__win:hover,
html[data-desktop] .dk-titlebar__btn:hover { background: var(--panel2); color: var(--ink); }
html[data-desktop] .dk-titlebar__btn:focus-visible {
  outline: 2px solid var(--acc);
  outline-offset: -3px;
}
html[data-desktop] .dk-titlebar__win--close:hover,
html[data-desktop] .dk-titlebar__btn--close:hover { background: #e5484d; color: #fff; }

/* ▢ ⇄ ❐ — two glyphs, one shown at a time, so the swap needs no JS text. */
.dk-titlebar__glyph { pointer-events: none; }
.dk-titlebar__glyph--restore { display: none; }
html[data-maximized] .dk-titlebar__glyph--max { display: none; }
html[data-maximized] .dk-titlebar__glyph--restore { display: inline; }

/* macOS draws its own traffic lights over the top-left of the frame: drop our
   buttons and inset the lockup so the two never overlap. */
html[data-desktop][data-platform="darwin"] .dk-titlebar { padding-left: 78px; }
html[data-desktop][data-platform="darwin"] .dk-titlebar__controls { display: none; }

/* v5:103-134 — the browser-style tab strip that replaces the vertical rail. */
.dk-tabstrip {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-2) var(--sp-5);
}
.dk-tabstrip__scroller {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  overflow-x: auto;
  overflow-y: hidden;
  padding: var(--sp-2) 2px;
  scrollbar-width: none;
}
.dk-tabstrip__scroller::-webkit-scrollbar { width: 0; height: 0; display: none; }
.dk-tabstrip__sep { width: 1.5px; height: 26px; background: var(--line); flex: none; }

.dk-tab {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex: none;
  height: var(--hit-lg);
  padding: 0 var(--sp-8);
  border-radius: var(--r-lg);
  background: transparent;
  border: var(--bw) solid transparent;
  color: var(--ink);
  font: 800 var(--fs-lg) / 1 var(--font);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: transform var(--dur-3) var(--ease), background var(--dur-3), border-color var(--dur-3);
}
.dk-tab:hover { border-color: var(--acc); color: var(--ink); text-decoration: none; }
.dk-tab:active { transform: scale(0.96); }
.dk-tab:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.dk-tab.is-active,
.dk-tab[aria-current="page"] {
  background: var(--panel);
  border-color: var(--line);
  box-shadow: var(--golge);
  transform: scale(1.06);
}
/* v5:105 — the home tab fills with the accent gradient when active. */
.dk-tab--home.is-active,
.dk-tab--home[aria-current="page"] {
  background: linear-gradient(0deg, var(--heroScrim), var(--heroScrim)), linear-gradient(135deg, var(--acc), var(--acc2));
  border-color: transparent;
  color: var(--accInk);
}
.dk-tab__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* v5:118 — the dashed "+ Dersliğe katıl" affordance at the end of the strip. */
.dk-tabstrip__add {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex: none;
  height: var(--hit-lg);
  padding: 0 var(--sp-8);
  border-radius: var(--r-lg);
  border: var(--bw) dashed var(--acc);
  background: transparent;
  color: var(--accText);
  font: 800 var(--fs-md) / 1 var(--font);
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-3) var(--ease), transform var(--dur-3) var(--ease);
}
.dk-tabstrip__add:hover { background: var(--accSoft); color: var(--accText); text-decoration: none; }
.dk-tabstrip__add:active { transform: scale(0.96); }
.dk-tabstrip__add:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }

/* v5:115 — the "there is a live lesson in this derslik" dot. */
.dk-tab__live {
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: var(--r-full);
  background: var(--ok);
  animation: dkPulse 2s infinite;
}

/* v5:136 — the padded flex row that holds the rounded panes. */
.dk-workspace {
  flex: 1;
  display: flex;
  min-height: 0;
  gap: var(--sp-4);
  padding: var(--sp-4);
  position: relative;
}
/* v5:417 / spec §2.2 — the voice ("zoom") stage takes the whole workspace.
   THE canonical zoom block: everything that steps out of the way for a live
   lesson is declared here, in one place, so a reader can see the whole state
   at a glance. `dk/guild.css` used to carry a second copy of the channel-panel
   line, which meant half the state lived in a slice sheet. Add to this block,
   never to another file. */
.dk-workspace[data-stage="zoom"] { padding-top: 0; }
.dk-app:has(.dk-workspace[data-stage="zoom"]) > .dk-tabstrip { display: none; }
.dk-workspace[data-stage="zoom"] > .guild-layout > .channel-sidebar { display: none; }
/* The members panel deliberately stays: in zoom it is the in-room roster. */

/* =========================================================================
   2. Buttons — visual-system §2.1
   ========================================================================= */
.dk-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-9);
  border: var(--bw) solid transparent;
  border-radius: var(--r-md);
  background: var(--acc);
  color: var(--accInk);
  font: 800 var(--fs-md) / 1 var(--font);
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease),
    box-shadow var(--dur-2) var(--ease), transform var(--dur-1) var(--ease);
}
.dk-btn:hover { background: color-mix(in srgb, var(--acc) 88%, var(--ink)); color: var(--accInk); text-decoration: none; }
.dk-btn:active { transform: scale(0.97); }
.dk-btn:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.dk-btn[disabled],
.dk-btn[aria-disabled="true"] { opacity: 0.55; pointer-events: none; }

/* v5:278, v5:665, v5:728 — the "send" treatment. */
.dk-btn--gradient {
  background: linear-gradient(0deg, var(--heroScrim), var(--heroScrim)), linear-gradient(135deg, var(--acc), var(--acc2));
  box-shadow: 0 4px 14px color-mix(in srgb, var(--acc) 35%, transparent);
}
.dk-btn--gradient:hover {
  background: linear-gradient(0deg, var(--heroScrim), var(--heroScrim)), linear-gradient(135deg, var(--acc), var(--acc2));
  filter: brightness(1.06);
}

.dk-btn--ok {
  background: var(--ok);
  color: var(--okInk);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--ok) 35%, transparent);
}
.dk-btn--ok:hover { background: color-mix(in srgb, var(--ok) 88%, var(--ink)); color: var(--okInk); }

/* v5:350 — outline button. */
.dk-btn--secondary {
  background: transparent;
  border-color: var(--line);
  color: var(--ink);
  padding: var(--sp-4) var(--sp-8);
  border-radius: var(--r-xs);
  font-size: var(--fs-sm);
}
.dk-btn--secondary:hover { background: var(--panel); border-color: var(--acc); color: var(--acc); }

/* v5:688 — soft-tinted pill; .is-warn / .is-ok swap the tint pair. */
.dk-btn--ghost {
  background: var(--accSoft);
  color: var(--accInkSoft);
  border-color: transparent;
  padding: var(--sp-3) var(--sp-5);
  border-radius: var(--r-xs);
  font-size: var(--fs-xs);
}
.dk-btn--ghost:hover { background: var(--acc); color: var(--accInk); }
.dk-btn--ghost.is-warn { background: var(--warnSoft); color: var(--warn); }
.dk-btn--ghost.is-warn:hover { background: var(--warn); color: var(--warnInk); }
.dk-btn--ghost.is-ok { background: var(--okSoft); color: var(--ok); }
.dk-btn--ghost.is-ok:hover { background: var(--ok); color: var(--okInk); }

/* v5:349 — soft danger that solidifies on hover. */
.dk-btn--danger { background: var(--badSoft); color: var(--bad); border-color: transparent; }
.dk-btn--danger:hover { background: var(--bad); color: var(--badInk); }
.dk-btn--danger-solid { background: var(--bad); color: var(--badInk); }
.dk-btn--danger-solid:hover { background: color-mix(in srgb, var(--bad) 85%, #000); color: var(--badInk); }

/* v5:118, v5:306 — "add" affordances. */
.dk-btn--dashed { background: transparent; border: var(--bw) dashed var(--acc); color: var(--accText); }
.dk-btn--dashed:hover { background: var(--accSoft); color: var(--accText); }

/* v5:148 — a button sitting on the accent gradient. */
/* D-05: the film darkens or lightens with the palette (--glassBg) and the
   label takes the palette's accent ink. A white label on a white film over
   a light accent measured 3.36:1 on the default theme. */
.dk-btn--glass {
  background: var(--glassBg);
  border-color: var(--glassLine);
  color: var(--accInk);
}
.dk-btn--glass:hover { background: var(--glassBgHover); color: var(--accInk); }

.dk-btn--sm { padding: var(--sp-4) var(--sp-6); font-size: var(--fs-sm); border-radius: var(--r-sm); }
.dk-btn--xs { padding: var(--sp-2) var(--sp-4); font-size: var(--fs-xs); border-radius: var(--r-sm); }
.dk-btn--lg { padding: var(--sp-7) var(--sp-9); font-size: var(--fs-lg); border-radius: var(--r-lg); }
.dk-btn--block { width: 100%; }

/* v5:123 — icon-only, 44px. --bare is the 32px transparent variant (v5:294),
   --xs the 26px one (v5:326). */
.dk-ibtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: var(--hit-md);
  height: var(--hit-md);
  padding: 0;
  border-radius: var(--r-lg);
  background: var(--panel);
  border: var(--bw) solid var(--line);
  color: var(--mut);
  cursor: pointer;
  transition: color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease),
    background var(--dur-2) var(--ease);
}
.dk-ibtn:hover { color: var(--acc); border-color: var(--acc); }
.dk-ibtn:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.dk-ibtn[aria-expanded="true"] { color: var(--acc); border-color: var(--acc); background: var(--accSoft); }
.dk-ibtn--bare {
  width: var(--hit-sm);
  height: var(--hit-sm);
  border-radius: var(--r-md);
  background: transparent;
  border-color: transparent;
}
.dk-ibtn--bare:hover { background: var(--panel2); color: var(--acc); }
.dk-ibtn--xs { width: var(--hit-xs); height: var(--hit-xs); border-radius: var(--r-xs); }
.dk-ibtn--danger:hover { color: var(--bad); border-color: var(--bad); }
/* v5:129 — the 44px-tall pill with a label. */
.dk-ibtn--pill { width: auto; padding: 0 var(--sp-8); gap: var(--sp-3); font: 800 var(--fs-md) / 1 var(--font); }

/* =========================================================================
   3. Form controls — visual-system §2.2
   ========================================================================= */
.dk-input,
.dk-select,
.dk-textarea {
  width: 100%;
  padding: var(--sp-5) var(--sp-6);
  border: var(--bw) solid var(--lineStrong); /* §6.5 — --line is 1.3:1, invisible */
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
  font: 400 var(--fs-md) / 1.4 var(--font);
  outline: none;
  transition: border-color var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.dk-input::placeholder,
.dk-textarea::placeholder { color: var(--mut); }
.dk-input:focus,
.dk-select:focus,
.dk-textarea:focus,
.dk-input:focus-visible,
.dk-select:focus-visible,
.dk-textarea:focus-visible {
  border-color: var(--acc);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--acc) 22%, transparent);
}
.dk-input--xs { padding: var(--sp-4) var(--sp-5); border-radius: var(--r-xs); font-size: var(--fs-sm); }
.dk-input--sm { padding: var(--sp-4) var(--sp-6); border-radius: var(--r-sm); font-size: var(--fs-sm); }
.dk-input--lg { padding: var(--sp-6) var(--sp-8); font-size: var(--fs-lg); }
.dk-input--xl { padding: var(--sp-7) var(--sp-8); border-radius: var(--r-lg); font-size: var(--fs-xl); }
.dk-input--code { text-align: center; letter-spacing: var(--ls-code); }
.dk-input--onpanel2 { background: var(--panel2); } /* composer / settings forms, v5:664 */
.dk-textarea { resize: vertical; min-height: 5.25rem; }

.dk-label { display: block; font: 700 var(--fs-sm) / 1.2 var(--font); color: var(--mut); }
.dk-label--caps {
  font-size: var(--fs-2xs);
  font-weight: 800;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}
.dk-field { display: flex; flex-direction: column; gap: var(--sp-3); }

/* File picker (spec §5 G19 — v5 draws no file input at all). The browser's own
   widget is an untranslatable "Choose file / No file chosen" pair that ignores
   every token in this sheet, so the real `<input type="file">` is hidden
   *visually* and the `<label>` around it becomes the control: a `.dk-btn` for
   the affordance plus a slot `public/classroom.js` fills with the chosen name.
   The input keeps its place in the tab order and the label keeps forwarding
   clicks, so with scripting blocked the picker still opens and the form still
   posts — only the echoed name is missing. */
.dk-file {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-5);
  min-width: 0;
  cursor: pointer;
}
/* Clipped, not `display:none` — a hidden input is not focusable, and this one
   is still the control that owns the value and the focus ring. */
.dk-file__input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}
.dk-file__btn { flex: none; }
/* Focus lands on the clipped input, so the ring has to be drawn on the button
   standing in for it — the same ring every other control uses. */
.dk-file__input:focus-visible + .dk-file__btn {
  outline: 2px solid var(--acc);
  outline-offset: 2px;
}
.dk-file__name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 400 var(--fs-sm) / 1.3 var(--font);
  color: var(--mut);
}
.dk-file__name.is-chosen { color: var(--ink); font-weight: 700; }

/* v5:1002 — the track/knob toggle, as a real role="switch" button. */
.dk-switch {
  position: relative;
  flex: none;
  width: 38px;
  height: 22px;
  padding: 0;
  border: none;
  border-radius: var(--r-md);
  background: var(--lineStrong);
  cursor: pointer;
  transition: background var(--dur-2) var(--ease);
}
.dk-switch[aria-checked="true"] { background: var(--ok); }
.dk-switch::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 16px;
  height: 16px;
  border-radius: var(--r-full);
  background: #fff;
  transition: left var(--dur-2) var(--ease);
}
.dk-switch[aria-checked="true"]::after { left: 19px; }
.dk-switch:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }

/* =========================================================================
   4. Badges, subheads, notices, empty states — §2.4, §2.11, §2.12
   ========================================================================= */
.dk-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  flex: none;
  padding: 3px var(--sp-4);
  border-radius: var(--r-2xs);
  font: 800 var(--fs-3xs) / 1.4 var(--font);
  white-space: nowrap;
  text-transform: uppercase;
  background: var(--panel2);
  color: var(--mut);
}
.dk-badge--2xs { font-size: var(--fs-4xs); padding: 2px var(--sp-3); border-radius: 5px; }
.dk-badge--xs { font-size: var(--fs-3xs); padding: 2px var(--sp-4); border-radius: var(--r-2xs); }
.dk-badge--md { font-size: var(--fs-2xs); padding: 4px var(--sp-5); border-radius: 7px; }
.dk-badge--code {
  font-size: var(--fs-lg);
  padding: var(--sp-4) var(--sp-8);
  border-radius: var(--r-sm);
  letter-spacing: var(--ls-code);
  text-transform: none;
}
.dk-badge.is-ok { background: var(--okSoft); color: var(--ok); }
.dk-badge.is-warn { background: var(--warnSoft); color: var(--warn); }
.dk-badge.is-bad { background: var(--badSoft); color: var(--bad); }
.dk-badge.is-acc { background: var(--accSoft); color: var(--accInkSoft); }
.dk-badge.is-solid { background: var(--acc); color: var(--accInk); }
.dk-badge.is-live { animation: dkPulse 2s infinite; }
.dk-badge--on-dark { background: rgba(0, 0, 0, 0.45); color: #fff; }

/* v5:153 — 13 occurrences of the same uppercase section heading. */
.dk-subhead {
  margin: 0;
  font: 800 var(--fs-2xs) / 1.3 var(--font);
  color: var(--mut);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  padding: 0 var(--sp-4) var(--sp-3);
}
.dk-subhead.is-ok { color: var(--ok); }

/* v5:631, v5:637 — the composer's locked / voice-required strips. */
.dk-notice {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  margin: 0;
  padding: var(--sp-6) var(--sp-8);
  border-radius: var(--r-lg);
  background: var(--panel2);
  border: var(--bw) solid var(--line);
  font: 700 var(--fs-md) / 1.4 var(--font);
  color: var(--mut);
}
.dk-notice.is-warn { background: var(--warnSoft); border-color: var(--warn); color: var(--warn); }
.dk-notice.is-bad { background: var(--badSoft); border-color: var(--bad); color: var(--bad); }
.dk-notice.is-ok { background: var(--okSoft); border-color: var(--ok); color: var(--ok); }

/* v5:586 */
.dk-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-10);
  text-align: center;
  color: var(--mut);
  font-size: var(--fs-lg);
}

/* =========================================================================
   5. Avatars — §2.5
   ========================================================================= */
.dk-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  position: relative;
  width: var(--av, 32px);
  height: var(--av, 32px);
  border-radius: var(--r-md);
  background: var(--avatar-bg, var(--acc));
  /* The six .dk-tint-* backgrounds are fixed and dark, so they keep white
     (A19 darkened them for exactly that). An untinted avatar sits on --acc,
     which is mint on tahta and pale blue on gece, so there it has to take
     the palette's own accent ink (D-05). */
  color: var(--avatar-ink, var(--accInk));
  font: 800 calc(var(--av, 32px) * 0.36) / 1 var(--font);
  text-transform: uppercase;
  overflow: visible;
}
.dk-avatar--circle { border-radius: var(--r-full); }
.dk-avatar--26 { --av: 26px; border-radius: var(--r-xs); }
.dk-avatar--28 { --av: 28px; }
.dk-avatar--32 { --av: 32px; }
.dk-avatar--36 { --av: 36px; }
.dk-avatar--40 { --av: 40px; border-radius: var(--r-lg); }
.dk-avatar--42 { --av: 42px; border-radius: var(--r-lg); }
.dk-avatar--48 { --av: 48px; }
.dk-avatar.is-speaking { box-shadow: 0 0 0 2px var(--ok); }

/* v5:702 — presence dot; the ring matches the row ground (§6.10 A17). */
.dk-avatar__dot {
  position: absolute;
  bottom: -2px;
  right: -2px;
  width: 10px;
  height: 10px;
  border-radius: var(--r-full);
  background: var(--mut);
  border: 2px solid var(--panel2);
}
.dk-avatar__dot.is-online { background: var(--ok); }
.dk-avatar__dot.is-offline { background: var(--mut); }

/* The 7 hardcoded entity colours (v5:1220-1233), darkened per §6.10 A19 so
   white initials clear 4.5:1 at small sizes. */
.dk-tint-1 { --avatar-bg: #4a48b8; --avatar-ink: #fff; }
.dk-tint-2 { --avatar-bg: #227a52; --avatar-ink: #fff; } /* §6.10 A19 — was #2E9E6B (3.38:1) */
.dk-tint-3 { --avatar-bg: #8a6018; --avatar-ink: #fff; } /* §6.10 A19 — was #B07C1F (3.65:1) */
.dk-tint-4 { --avatar-bg: #8e1e5f; --avatar-ink: #fff; }
.dk-tint-5 { --avatar-bg: #1e7f8e; --avatar-ink: #fff; }
.dk-tint-6 { --avatar-bg: #4a7318; --avatar-ink: #fff; } /* §6.10 A19 — was #5B8E1E (3.94:1) */
.dk-tint-self { --avatar-bg: var(--acc); }

/* =========================================================================
   6. Surfaces — panes, cards, heroes, tiles — §2.3
   ========================================================================= */
.dk-pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  background: var(--panel);
  border-radius: var(--r-2xl);
  box-shadow: var(--golge);
}
.dk-pane--grow { flex: 1; }
/* A pane whose children sit side by side instead of stacking. `.chat-area` is
   the one shipping case — it is always [ stage | gutter | message panel ], and
   the two leading children ship `hidden`, so a row reads identically to the
   column it used to be while a call is off. `dk/voice.css` used to flip it back
   with `.chat-area:has(> .dk-stage:not([hidden]))`, a (0,3,0) selector that was
   painful to override and only true while the stage was open; the shape is a
   property of the markup, not of the call state. `views/guild.js` should carry
   the modifier itself once it is touched; until then the legacy hook is grouped
   in here rather than left in a slice sheet. */
.dk-pane--row,
.chat-area.dk-pane { flex-direction: row; }
.dk-pane__head {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  padding: var(--sp-7) var(--sp-10);
  border-bottom: var(--bw-thin) solid var(--line);
}
.dk-pane__title { margin: 0; font: 800 var(--fs-2xl) / 1.25 var(--font); }
.dk-pane__body { flex: 1; min-height: 0; overflow-y: auto; padding: var(--sp-8) var(--sp-10); }
.dk-pane__foot { flex: none; padding: var(--sp-5) var(--sp-8) var(--sp-7); }

/* v5:675-721 — the fixed-width roster column on the right of a derslik.
   visual-system §7 declares it a base primitive; it was living in
   `dk/guild.css` marked "candidate for base.css". The contents (`.members-*`)
   stay in guild.css — only the pane itself is shared. guild.css still drops it
   below 1100px, which wins on specificity regardless of load order. */
.dk-pane--members {
  flex: none;
  width: 236px;
  overflow-y: auto;
  padding: var(--sp-8) var(--sp-6);
}
.dk-pane--members[hidden] { display: none; }

.dk-card { background: var(--panel2); border-radius: var(--r-xl); padding: var(--sp-8); }
.dk-card--settings { border-radius: var(--r-lg); padding: var(--sp-9); }
.dk-card--accent {
  background: var(--accSoft);
  border: var(--bw) solid var(--acc);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.dk-card--edit {
  border: var(--bw) solid var(--acc);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
  gap: var(--sp-4);
  display: flex;
  flex-direction: column;
}
.dk-card--role {
  border-left: 4px solid var(--role-color, var(--acc));
  border-radius: var(--r-lg);
  padding: var(--sp-8);
}

/* v5:154 — the home class card. */
.dk-tile {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  background: var(--panel2);
  border: var(--bw) solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-6);
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease),
    border-color var(--dur-2) var(--ease);
}
.dk-tile:hover { border-color: var(--acc); box-shadow: var(--golge); transform: translateY(-2px); text-decoration: none; }
.dk-tile:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.dk-tile-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--sp-5); }

/* v5:142 */
/* D-05: white on the accent gradient measured 1.79:1 on tahta and 3.36:1 on
   the default palette, and axe cannot see it at all (gradient background).
   The ink is the palette's --accInk now, and --heroScrim darkens the ramp
   on the palettes where no solid ink clears 4.5:1 against both stops. */
.dk-hero {
  display: flex;
  align-items: center;
  gap: var(--sp-7);
  padding: var(--sp-9) var(--sp-10);
  border-radius: var(--r-xl);
  color: var(--accInk);
  background-image:
    linear-gradient(0deg, var(--heroScrim), var(--heroScrim)),
    linear-gradient(120deg, var(--acc), var(--acc2));
  box-shadow: 0 8px 24px color-mix(in srgb, var(--acc) 30%, transparent);
}
.dk-hero__title { margin: 0; font: 800 var(--fs-2xl) / 1.25 var(--font); }
/* The 0.88 opacity cost the sub-line 0.4:1 and hid it from every contrast
   tool; the same softening as a colour mix is computable. */
.dk-hero__sub {
  margin: 0;
  font: 400 var(--fs-md) / var(--lh-body) var(--font);
  color: color-mix(in srgb, var(--accInk) 88%, transparent);
}

/* =========================================================================
   7. Rows and tables — §2.7
   ========================================================================= */
.dk-row {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--r-md);
  cursor: pointer;
  color: var(--ink);
  background: transparent;
  border: 0;
  text-align: left;
  text-decoration: none;
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.dk-row:hover { background: var(--panel2); text-decoration: none; }
.dk-row:focus-visible { outline: 2px solid var(--acc); outline-offset: -2px; }
.dk-row.is-active { background: var(--accSoft); color: var(--accInkSoft); font-weight: 800; }
.dk-row__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 600 var(--fs-lg) / 1.3 var(--font);
}
.dk-row.is-active .dk-row__name { font-weight: 800; }
.dk-row__meta { font: 700 var(--fs-2xs) / 1.25 var(--font); color: var(--mut); }
.dk-row__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: var(--r-sm);
  background: var(--accSoft);
  color: var(--accInkSoft);
}
.dk-row.is-active .dk-row__icon { background: var(--acc); color: var(--accInk); }
.dk-row__icon.is-exam { background: var(--warnSoft); color: var(--warn); }

.dk-row--card { background: var(--panel2); padding: var(--sp-5); margin-bottom: var(--sp-3); }
.dk-row--dm { background: var(--panel); padding: var(--sp-4) var(--sp-5); }
.dk-row--dm:hover { background: var(--panel); box-shadow: var(--golge); }
.dk-row--tool {
  background: var(--panel2);
  border: var(--bw) solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-5) var(--sp-6);
  transition: transform var(--dur-2) var(--ease), background var(--dur-2), border-color var(--dur-2);
}
.dk-row--tool:hover { border-color: var(--acc); background: var(--accSoft); }
.dk-row--tool:active { transform: scale(0.97); }

/* v5:357 — sesli derslik card. */
.dk-voiceroom {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: var(--sp-7);
  border-radius: var(--r-lg);
  margin-bottom: var(--sp-3);
  background: transparent;
  border: var(--bw) solid var(--line);
  cursor: pointer;
}
.dk-voiceroom:hover { border-color: var(--acc); }
.dk-voiceroom:focus-within { border-color: var(--acc); }
.dk-voiceroom.is-active { background: var(--accSoft); border-color: var(--acc); }
.dk-voiceroom__meta {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  padding-left: 53px;
}

/* v5:1037 — attendance; a real <table> styled as a grid (§3.4). */
.dk-table { background: var(--panel2); border-radius: var(--r-lg); overflow: hidden; width: 100%; border-collapse: collapse; }
.dk-table__head,
.dk-table__row { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; padding: var(--sp-5) var(--sp-9); }
.dk-table__head {
  font: 800 var(--fs-2xs) / 1.3 var(--font);
  color: var(--mut);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  border-bottom: var(--bw-thin) solid var(--line);
}
.dk-table__row { border-top: var(--bw-thin) solid var(--line); font-size: var(--fs-md); align-items: center; }

/* =========================================================================
   8. Tabs, segmented controls, swatches — §2.6
   ========================================================================= */
.dk-vtab {
  display: block;
  width: 100%;
  padding: var(--sp-5) var(--sp-6);
  border: 0;
  border-radius: var(--r-sm);
  font: 800 var(--fs-md) / 1.2 var(--font);
  color: var(--ink);
  background: transparent;
  cursor: pointer;
  text-align: left;
  text-decoration: none;
}
.dk-vtab:hover { background: var(--panel2); text-decoration: none; }
.dk-vtab:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.dk-vtab.is-active { background: var(--accSoft); color: var(--accInkSoft); }

.dk-seg { display: flex; gap: var(--sp-3); }
.dk-seg__opt {
  flex: 1;
  position: relative;
  padding: var(--sp-4);
  border-radius: var(--r-xs);
  text-align: center;
  font: 800 var(--fs-sm) / 1.2 var(--font);
  cursor: pointer;
  border: var(--bw) solid var(--line);
  background: var(--panel);
  color: var(--mut);
}
.dk-seg__opt:hover { border-color: var(--acc); }
.dk-seg__opt:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.dk-seg__opt.is-active,
.dk-seg__opt[aria-pressed="true"],
.dk-seg__opt[aria-checked="true"] { border-color: var(--acc); background: var(--accSoft); color: var(--accInkSoft); }
.dk-seg--preview .dk-seg__opt { padding: var(--sp-5) var(--sp-3); border-width: 2px; border-radius: var(--r-md); }

/* v5:1010 — the 8-up theme picker, also rendered by theme.js into its popover. */
.dk-swatchgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-4); }
.dk-swatch {
  position: relative;
  border-radius: var(--r-md);
  padding: var(--sp-5);
  cursor: pointer;
  border: 2px solid var(--line);
  background: var(--swatch-bg, var(--panel));
  color: var(--swatch-ink, var(--ink));
  text-align: left;
  font: inherit;
}
.dk-swatch:hover { border-color: var(--acc); }
.dk-swatch:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.dk-swatch.is-active,
.dk-swatch[aria-pressed="true"] { border-color: var(--acc); }
/* §6.10 A21 — the selected theme must not be signalled by colour alone. */
.dk-swatch[aria-pressed="true"]::after {
  content: "✓";
  position: absolute;
  top: 4px;
  right: 7px;
  font: 800 var(--fs-xs) / 1 var(--font);
  color: var(--swatch-ink, var(--ink));
}
/* The two-stop preview bar. theme.js sets --swatch-a/-b/-bg/-ink inline from
   the live token set; static markup can instead put data-theme="<tema>" on
   the button itself and let the fallbacks below read that theme's palette. */
.dk-swatch__bar {
  display: block;
  height: 20px;
  border-radius: var(--r-2xs);
  background: linear-gradient(90deg, var(--swatch-a, var(--acc)) 35%, var(--swatch-b, var(--panel2)) 35%);
}
.dk-swatch__label { display: block; font: 800 var(--fs-xs) / 1.2 var(--font); margin-top: var(--sp-4); }

/* =========================================================================
   9. Scrim, dialog, popover — §2.9
   ========================================================================= */
.dk-scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(20, 20, 40, 0.45);
}
.dk-dialog {
  width: min(390px, calc(100vw - var(--sp-10)));
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
  background: var(--panel);
  border-radius: var(--r-2xl);
  padding: var(--sp-14);
  box-shadow: var(--shadow-modal);
}
.dk-dialog--wide { width: min(560px, calc(100vw - var(--sp-10))); }
.dk-dialog__title { margin: 0; font: 800 var(--fs-2xl) / 1.25 var(--font); text-align: center; }
.dk-dialog__sub {
  margin: calc(-1 * var(--sp-3)) 0 0;
  font: 400 var(--fs-md) / var(--lh-body) var(--font);
  color: var(--mut);
  text-align: center;
}
@media (prefers-reduced-motion: no-preference) {
  .dk-dialog { animation: dkPop var(--dur-3) var(--ease); }
}
@keyframes dkPop {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to { opacity: 1; transform: none; }
}

/* The theme picker popover theme.js renders into <body>. */
.dk-popover {
  position: absolute;
  z-index: var(--z-popover);
  min-width: 268px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: var(--sp-6);
  background: var(--panel);
  border: var(--bw) solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--golge);
}
.dk-popover__title {
  margin: 0;
  font: 800 var(--fs-2xs) / 1.3 var(--font);
  color: var(--mut);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

/* =========================================================================
   10. Messages, composer, voice — declared now, detailed in slices 4-6
   ========================================================================= */
.dk-msglist {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
  gap: var(--sp-7);
  padding: var(--sp-8) var(--sp-10);
}
/* Bottom-anchors a short history: the zero-height spacer soaks up the free
   space so the first message sits just above the composer instead of at the
   top of an empty pane. It is a flex item, so the list's own `gap` lands
   between it and the first row too — a phantom row of space above the oldest
   message that grew with the gap. Cancel exactly that one gap here; the
   negative margin is inert once the list overflows and the spacer collapses. */
.dk-msglist::before {
  content: "";
  margin-top: auto;
  margin-bottom: calc(-1 * var(--sp-7));
}
.dk-msglist--centered > * { width: 100%; max-width: 760px; margin-inline: auto; }

.dk-msg { display: flex; gap: var(--sp-5); }
.dk-msg__body { min-width: 0; max-width: 72%; display: flex; flex-direction: column; align-items: flex-start; }
.dk-msg__meta { display: flex; align-items: baseline; gap: var(--sp-4); padding-left: var(--sp-2); }
.dk-msg__author { font: 800 var(--fs-lg) / 1.2 var(--font); }
.dk-msg__time { font: 400 var(--fs-2xs) / 1.2 var(--font); color: var(--mut); }

.dk-bubble {
  display: inline-block;
  margin-top: var(--sp-2);
  padding: var(--sp-5) var(--sp-8);
  background: var(--panel2);
  border: var(--bw) solid var(--line);
  border-radius: var(--r-xs) var(--r-bubble) var(--r-bubble) var(--r-bubble);
  line-height: var(--lh-chat);
  text-wrap: pretty;
  box-shadow: var(--shadow-bubble);
}
.dk-bubble--mine {
  background: var(--acc);
  color: var(--accInk);
  border-color: transparent;
  border-radius: var(--r-bubble) var(--r-xs) var(--r-bubble) var(--r-bubble);
}
.dk-bubble__time { display: block; font-size: var(--fs-3xs); opacity: 0.65; margin-top: var(--sp-2); text-align: right; }

/* "Sohbet metni boyutu" (Ayarlar). `--chat-fs` is the one knob the setting
   turns (tokens.css maps `:root[data-sohbet-boyut]` onto it); this is the one
   place that spends it, so the bubble and the legacy `.msg-content` hook can
   never disagree about how big a message is. `styles.css` still sizes
   `.msg-content` from its own ramp — base.css loads after it, so this wins. */
.dk-bubble,
.msg-content { font-size: var(--chat-fs); }

.dk-sysmsg {
  align-self: center;
  text-align: center;
  font: 700 var(--fs-sm) / 1.4 var(--font);
  color: var(--mut);
  background: var(--panel2);
  padding: var(--sp-3) var(--sp-7);
  border-radius: var(--r-xs);
}

.dk-poll {
  display: block;
  margin-top: var(--sp-3);
  max-width: 480px;
  background: var(--panel2);
  border: var(--bw) solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-6);
}
.dk-poll__q { display: block; font: 800 var(--fs-xl) / 1.3 var(--font); margin-bottom: var(--sp-4); }
.dk-poll__opt {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-6);
  border-radius: var(--r-sm);
  margin-bottom: var(--sp-3);
  background: var(--panel);
  border: var(--bw) solid var(--line);
  cursor: pointer;
}
.dk-poll__opt:hover { border-color: var(--acc); }
.dk-poll__opt.is-mine { background: var(--accSoft); border-color: var(--acc); }
.dk-poll__opt.is-correct { background: var(--okSoft); border-color: var(--ok); }
.dk-poll__foot { display: block; font: 700 var(--fs-xs) / 1.3 var(--font); color: var(--mut); }

.dk-composer { flex: none; padding: var(--sp-5) var(--sp-8) var(--sp-7); }
.dk-composer__row { display: flex; gap: var(--sp-4); width: 100%; align-items: center; }
.dk-composer--centered .dk-composer__row { max-width: 760px; margin-inline: auto; }
.dk-composer__input {
  flex: 1;
  min-width: 0;
  padding: var(--sp-5) var(--sp-7);
  border: var(--bw) solid var(--lineStrong);
  border-radius: var(--r-md);
  background: var(--panel2);
  color: var(--ink);
  font: 400 var(--fs-xl) / 1.4 var(--font);
  outline: none;
}
.dk-composer__input:focus,
.dk-composer__input:focus-visible {
  border-color: var(--acc);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--acc) 22%, transparent);
}
.dk-composer__toggle {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex: none;
  padding: var(--sp-5) var(--sp-7);
  border-radius: var(--r-lg);
  background: var(--accSoft);
  color: var(--accInkSoft);
  border: var(--bw) solid var(--acc);
  font: 800 var(--fs-lg) / 1 var(--font);
  cursor: pointer;
}
.dk-composer__toggle:hover,
.dk-composer__toggle[aria-pressed="true"] { background: var(--acc); color: var(--accInk); }
.dk-composer__toggle:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }

/* v5:417-550 — the only surface that ignores the theme tokens on purpose
   (§2.13, C11): a fixed dark stage, scoped so it shadows nothing globally. */
.dk-stage {
  --st-bg: #17141f;
  --st-tile: #211d2e;
  --st-tile2: #2a2438;
  --st-line: #353449;
  --st-text: #efeff8;
  --st-mut: #9e9dbb;
  --st-speak: #7ff2b8;
  --st-rec: #e05252;
  --st-leave: #d64560;
  --st-warn: #d9a94a;
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--st-bg);
}
.dk-stage__screen {
  flex: 1;
  min-height: 0;
  margin: 0 var(--sp-7);
  border-radius: var(--r-lg);
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  background: linear-gradient(150deg, var(--st-tile), var(--st-tile2));
  color: var(--st-mut);
}
.dk-filmstrip {
  flex: none;
  display: flex;
  gap: var(--sp-4);
  padding: var(--sp-6) var(--sp-7);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}
.dk-filmstrip::-webkit-scrollbar { width: 0; height: 0; display: none; }

.dk-vtile {
  position: relative;
  flex: 1;
  min-width: 170px;
  max-width: 230px;
  height: 118px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  border-radius: var(--r-lg);
  background: var(--st-tile);
  border: var(--bw) solid var(--st-line);
}
.dk-vtile.is-speaking { border-color: var(--st-speak); }
.dk-vtile__name { font: 700 var(--fs-sm) / 1.2 var(--font); color: var(--st-text); }
.dk-vtile__actions {
  position: absolute;
  inset: auto 0 0 0;
  display: none;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-3);
  z-index: var(--z-raised);
  background: rgba(23, 20, 31, 0.94);
  border-radius: 0 0 var(--r-md) var(--r-md);
}
.dk-vtile:hover .dk-vtile__actions,
.dk-vtile:focus-within .dk-vtile__actions { display: flex; }
.dk-vtile__act {
  position: relative;
  width: var(--hit-sm);
  height: var(--hit-sm);
  border-radius: var(--r-xs);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border: none;
}
.dk-vtile__act:hover { filter: brightness(1.3); }
.dk-vtile__act:focus-visible { outline: 2px solid var(--st-speak); outline-offset: 2px; }
.dk-vtile__act--mute { background: #39322a; color: #e8c77a; }
.dk-vtile__act--mic { background: #1f3a2e; color: var(--st-speak); }
.dk-vtile__act--cam { background: #3b3555; color: #c9c4f2; }
.dk-vtile__act--kick { background: #c43333; color: #fff; }

.dk-vctrl {
  position: relative;
  min-width: 88px;
  padding: var(--sp-5) var(--sp-6);
  border-radius: var(--r-lg);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  cursor: pointer;
  background: var(--st-tile2, #2a2438);
  color: var(--st-text, #efeff8);
  border: none;
  font: 800 var(--fs-xs) / 1.2 var(--font);
  transition: transform var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
}
.dk-vctrl:hover { filter: brightness(1.15); }
.dk-vctrl:active { transform: scale(0.95); }
.dk-vctrl:focus-visible { outline: 2px solid var(--st-speak, #7ff2b8); outline-offset: 2px; }
.dk-vctrl.is-on { background: var(--acc); color: var(--accInk); }
.dk-vctrl.is-warn { background: var(--st-warn, #d9a94a); color: #17141f; } /* v5:1549 */
.dk-vctrl--leave { background: var(--st-leave, #d64560); color: #fff; }

/* v5:389 — the sidebar voice dock card. */
.dk-voicecard {
  flex: none;
  margin: var(--sp-5);
  padding: var(--sp-6);
  border-radius: var(--r-lg);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  color: #fff;
  background: linear-gradient(135deg, var(--acc), var(--acc2));
}
.dk-voicecard__btn {
  flex: 1;
  height: var(--hit-lg);
  border-radius: var(--r-md);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border: none;
  background: rgba(255, 255, 255, 0.2);
  color: #fff;
}
.dk-voicecard__btn:hover { filter: brightness(1.1); }
.dk-voicecard__btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.dk-voicecard__btn.is-off { background: #d64560; }
.dk-voicecard__btn.is-cam { background: #227a52; }
.dk-voicecard__btn.is-mode { background: #d9a94a; color: #17141f; }

/* --- the floating DM call dock ------------------------------------------
   `views/dm.js` renders the legacy `.voice-dock` pill as a direct child of
   `.dk-workspace`. `--dock-lift` is THE source for how far it floats:
   `styles.css` sets `bottom: var(--dock-lift, 1rem)` from this one value, and
   the message list's clearance is derived from it too.

   It used to be spread over three declarations, two of them keyed on
   `.app-shell >` — a wrapper the v5 shell deleted — so neither override
   applied any more and the pill sat on top of the composer at ordinary window
   heights. Anchoring it inside the workspace (which is `position: relative`)
   instead of the viewport also means the lift is measured from the pane's
   bottom edge, so it cannot drift with the window height again. */
/* 7rem clears the composer block *and* the two thin rows that can sit between
   it and the message list in a 1:1 DM — the typing indicator and the "Ekler
   uçtan uca şifrelenmez." hint. */
.dk-app { --dock-lift: 7rem; }
/* `.voice-dock` is centred with `left: 50%` + `translateX(-50%)` (styles.css), and an absolutely positioned box with `left: 50%`
   shrinks to fit the HALF of the pane that is left of that line: the controls wrapped at half the pane width, "Ayrıl" fell
   onto a row of its own and the pill was 131px tall (phase-5 ux-dm-dock-covers-chat). `max-content` takes the width the
   controls need on ONE row; the max-width keeps a gutter on each side and is what makes a narrow pane wrap, not the anchor. */
.dk-workspace > .voice-dock {
  position: absolute;
  bottom: var(--dock-lift);
  width: max-content;
  max-width: min(980px, calc(100% - var(--sp-10)));
}
/* Keep the newest message from hiding behind the pill. */
.dm-chat.chat-area.call-active .message-list {
  padding-bottom: calc(var(--dock-lift) - var(--sp-8));
}
@media (max-width: 680px) {
  /* Full-width down here (styles.css), so the dock wraps to two or three rows
     and needs to start higher. One value, one place. */
  .dk-app { --dock-lift: 9rem; }
}

/* v5:461 — the mic/camera picker that pops above the stage control bar.
   visual-system §7 declares it a base primitive; it was living in
   `dk/voice.css` marked "candidate for base.css". It is positioned against
   `.vctrl-devices` (voice.css), and its colours come from the stage's scoped
   `--st-*` set with dark literals as the fallback, so it reads correctly
   wherever it is anchored. */
.dk-devicebar {
  position: absolute;
  bottom: calc(100% + var(--sp-4));
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-popover);
  display: flex;
  gap: var(--sp-5);
  flex-wrap: wrap;
  align-items: flex-end;
  padding: var(--sp-6) var(--sp-7);
  border-radius: var(--r-lg);
  background: var(--st-tile, #211d2e);
  box-shadow: var(--shadow-modal);
}
.dk-devicebar[hidden] { display: none; }
.dk-devicebar__field { display: flex; flex-direction: column; gap: var(--sp-2); }
.dk-devicebar__field > span {
  font: 800 var(--fs-2xs) / 1.2 var(--font);
  color: var(--st-mut, #9e9dbb);
  letter-spacing: var(--ls-label);
}
.dk-devicebar__field .dk-select {
  min-width: 190px;
  background: var(--st-tile2, #2a2438);
  border-color: var(--st-line, #353449);
  color: var(--st-text, #efeff8);
}

/* v5:572 — the live strip inside a normal channel. */
.dk-livestrip {
  flex: none;
  margin: var(--sp-6) var(--sp-8) 0;
  padding: var(--sp-7) var(--sp-8);
  border-radius: var(--r-lg);
  background: #1b1826;
  color: #efeff8;
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  flex-wrap: wrap;
}
/* The container ships `hidden` and voice.js clears it, so the `display:flex`
   above has to yield to the attribute. Declared once here rather than in each
   sheet that happens to touch the strip. */
.dk-livestrip[hidden] { display: none; }

/* =========================================================================
   11. Tooltip (the design has none — 34 native title= attributes) — §2.8
   ========================================================================= */
.dk-tip { position: relative; }
.dk-tip::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%) translateY(2px);
  max-width: 260px;
  width: max-content;
  padding: var(--sp-3) var(--sp-5);
  border-radius: var(--r-xs);
  background: var(--ink);
  color: var(--panel);
  font: 700 var(--fs-xs) / 1.35 var(--font);
  text-align: center;
  text-wrap: pretty;
  opacity: 0;
  pointer-events: none;
  z-index: var(--z-tooltip);
  transition: opacity var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
}
.dk-tip:hover::after,
.dk-tip:focus-visible::after { opacity: 1; transform: translateX(-50%) translateY(0); }
@media (hover: none) {
  .dk-tip::after { display: none; }
}

/* =========================================================================
   12. Hit-area floor — §6.8. Grows the *pointer* target of the controls the
   design draws under 44px without moving a painted pixel.
   ========================================================================= */
.dk-ibtn--xs,
.dk-ibtn--bare,
.dk-switch,
.dk-btn--sm,
.dk-seg__opt,
.dk-vtile__act { position: relative; }
.dk-ibtn--xs::before,
.dk-ibtn--bare::before,
.dk-switch::before,
.dk-btn--sm::before,
.dk-seg__opt::before,
.dk-vtile__act::before {
  content: "";
  position: absolute;
  inset: calc((44px - 100%) / -2) calc((44px - 100%) / -2);
  min-width: 44px;
  min-height: 44px;
}

/* =========================================================================
   13. Utilities
   ========================================================================= */
/* --- skip links (D-34) ---------------------------------------------------
   13 tab strip stops plus a 94-row channel sidebar put the composer 50 tab
   presses from the top of the page. Two skip links sit before everything
   else in the DOM: the first jumps to <main>, the second (rendered only on
   pages that have one) straight into the composer. */
.dk-skiplinks { position: absolute; top: 0; left: 0; width: 0; height: 0; }
.dk-skiplink {
  position: absolute;
  left: -10000px;
  top: 0;
  z-index: 80;
  padding: var(--sp-5) var(--sp-7);
  border: var(--bw) solid var(--acc);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
  font: 600 var(--fs-md) / 1.2 var(--font);
  text-decoration: none;
  white-space: nowrap;
  box-shadow: var(--golge);
}
.dk-skiplink:focus,
.dk-skiplink:focus-visible {
  left: var(--sp-5);
  top: var(--sp-5);
  outline: 2px solid var(--acc);
  outline-offset: 2px;
}
/* <main> takes focus from the skip link but must never draw a ring on a
   plain click. */
.dk-workspace:focus { outline: none; }

/* --- connection state strip (D-03) ---------------------------------------
   A dead SSE stream used to look exactly like a quiet classroom. stream.js
   shows this bar while the stream is down and flips it to .is-ok for two
   seconds when it comes back. */
.dk-connbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  flex: none;
  padding: var(--sp-3) var(--sp-6);
  border-bottom: var(--bw) solid var(--line);
  background: var(--warnSoft);
  color: var(--warn);
  font: 600 var(--fs-sm) / 1.3 var(--font);
  text-align: center;
}
.dk-connbar[hidden] { display: none; }
.dk-connbar.is-ok { background: var(--okSoft); color: var(--ok); }
.dk-connbar__link { color: inherit; font-weight: 800; text-decoration: underline; }
.dk-connbar__dot {
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: var(--r-full);
  background: currentColor;
}
.dk-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.dk-spacer { flex: 1 1 auto; }
.dk-muted { color: var(--mut); }
.dk-stack { display: flex; flex-direction: column; gap: var(--sp-5); }
.dk-inline { display: flex; align-items: center; gap: var(--sp-4); }
