/* ============================================================
   TRYCORD — application stylesheet (rebuilt UI)
   ============================================================
   Single stylesheet for the Trycord client.

   Composition:
     Desktop : Presence Spine -> Main Environment. Full viewport,
               fluid from 1280x720 through ultrawide.
     Mobile  : MobileShell, a separate purpose-built presentation.

   Theme contract:
     - Every visual surface consumes semantic `--t-*` tokens.
     - Built-in themes are immutable token blocks.
     - `html[data-theme="custom"]` maps `--c-*` values injected by
       js/theme.js (guided builder + validated advanced CSS).
     - Layout-critical rules carry `!important` so validated custom
       CSS (which may never use `!important`) cannot break required
       structure, navigation, or safety surfaces.

   Layout contract:
     - `.shell--desktop` owns the two top-level columns.
     - `.app-rail` owns rail + navigation internals.
     - `.main-content` is always grid column 2, so hiding the
       spine releases its track instead of trapping content.
     - `.chat-environment` gives the member rail an `auto` track and
       the sidebar a fixed token width, so a hidden member sidebar
       releases its column instead of leaving a phantom rail.
   ============================================================ */

/* ============================================================
   1. DESIGN TOKENS
   ============================================================ */

:root {
  color-scheme: dark;

  /* Layout geometry (single source for the desktop frame) */
  --ui-rail: 64px;
  --ui-sidebar: 240px;
  --ui-members: 260px;
  --ui-header: 58px;
  --ui-auth-width: 520px;
  --ui-page-width: 1180px;
  --t-content-width: 1180px;

  /* Palette */
  --t-pg:        #100b08;
  --t-base:      #181110;
  --t-base2:     #221510;
  --t-elev:      #2c1b13;
  --t-sur2:      #2a2d31;
  --t-line:      rgba(255, 190, 150, 0.14);
  --t-line-hi:   rgba(255, 190, 150, 0.28);
  --t-txt:       #fff6ec;
  --t-txt2:      #e3c9b4;
  --t-mut:       #a5856d;
  --t-accent:    #ff8a24;
  --t-accent-2:  #e95718;
  --t-ok:        #58c97a;
  --t-warn:      #e2b03c;
  --t-err:       #e06a5e;

  /* Typography */
  --t-font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --t-mono: ui-monospace, "Cascadia Code", "Segoe UI Mono", Consolas, monospace;
  --t-fs-xs: 0.72rem;
  --t-fs-s: 0.8rem;
  --t-fs-m: 0.9rem;
  --t-fs-l: 1.05rem;
  --t-fs-xl: clamp(1.4rem, 2vw, 1.9rem);
  --t-fs-2xl: clamp(2rem, 3.2vw, 2.9rem);

  /* Motion */
  --t-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --t-fast: 120ms;
  --t-med: 220ms;
  --t-slow: 420ms;
  --t-spin: 0.7s;

  /* Radii */
  --t-r-s: 8px;
  --t-r-m: 12px;
  --t-r-l: 18px;

  /* Avatar sizes */
  --t-avatar-sm: 28px;
  --t-avatar-md: 36px;
  --t-avatar-lg: 64px;
  --t-avatar-xl: 72px;

  /* Density */
  --t-d-2: 4px;
  --t-d-3: 8px;
  --t-d-4: 12px;
  --t-d-5: 16px;
  --t-d-6: 24px;

  /* Derived glyph tokens — text/accents on fills (never raw hex) */
  --t-on-accent:  #1d1008;
  --t-accent-hi:  #ffc27d;
  --t-on-danger:  #1a1312;
  --t-err-fg:     #ffb4a8;
  --t-ok-fg:      #b9f0c9;
  --t-warn-bg:    #3a2c13;
  --t-warn-fg:    #f6e7c8;
  --t-warn-brd:   #5c461b;
  --t-backdrop:   rgba(10, 5, 2, 0.62);
  --t-img-mat:    rgba(0, 0, 0, 0.3);
  --t-avatar-ring: rgba(255, 255, 255, 0.18);

  /* Ambient environment — themes re-tint the whole scene */
  --t-env-base:   #100b08;
  --t-shell-gradient: linear-gradient(180deg, rgba(64, 36, 22, 0.82), rgba(22, 15, 11, 0.7));
  --t-shell-edge: rgba(255, 190, 150, 0.18);
  --t-env-glow-a: rgba(255, 115, 35, 0.16);
  --t-env-glow-b: rgba(193, 61, 16, 0.1);
  --t-env-depth:  linear-gradient(132deg, #100b08 8%, #181110 54%, #120b08 100%);
  --t-header-fade: linear-gradient(180deg, rgba(16, 11, 8, 0.7), transparent);
  --t-title-glow: rgba(255, 138, 36, 0.14);
  --t-hero-edge:  rgba(255, 205, 165, 0.14);
  --t-hero-top:   rgba(255, 176, 111, 0.08);
  --t-hero-bottom: rgba(40, 19, 10, 0.3);

  /* Glass */
  --t-blur-s: 14px;  --t-sat-s: 120%;
  --t-blur-m: 26px;  --t-sat-m: 130%;
  --t-blur-l: 28px;  --t-sat-l: 135%;
  --t-inset-hi:   inset 0 1px 0 rgba(255, 255, 255, 0.12);
  --t-inset-glass: inset 0 1px 0 rgba(255, 255, 255, 0.06);

  /* Shadows */
  --t-sh-edge:   18px 0 48px rgba(0, 0, 0, 0.18);
  --t-sh-drawer: 24px 0 48px rgba(0, 0, 0, 0.45);
  --t-sh-1:      0 18px 44px rgba(0, 0, 0, 0.48);
  --t-sh-2:      0 24px 60px rgba(0, 0, 0, 0.5);
  --t-sh-3:      0 12px 32px rgba(0, 0, 0, 0.35);
  --t-sh-4:      0 10px 30px rgba(0, 0, 0, 0.4);
  --t-sh-hero:   0 24px 80px rgba(0, 0, 0, 0.26);

  /* Layer opacity */
  --t-op-mid: 0.55;
  --t-op-fade: 0.5;
  --t-op-dim: 0.6;

  /* Elevation */
  --z-inline: 2;
  --z-header: 20;
  --z-drawer-back: 40;
  --z-drawer: 50;
  --z-popover: 900;
  --z-modal: 1000;
  --z-toast: 1200;
  --z-status: 1300;
  --z-skip: 2000;

  /* BREAKPOINTS (single source — mirrors js/presentation.js):
     1200px+ — full desktop (sidebar + context sidebar + main)
     900–1199px — compact desktop (narrower sidebar)
     600–899px — tablet / compact navigation (collapsible sidebar)
     <600px — mobile (bottom tabs, no sidebar)
     Media queries cannot consume custom properties, so these stay in
     the matching @media rules and the JS constant. */
}

html[data-density="compact"] {
  --t-d-3: 5px; --t-d-4: 8px; --t-d-5: 11px; --t-d-6: 16px;
}
html[data-density="roomy"] {
  --t-d-3: 12px; --t-d-4: 18px; --t-d-5: 24px; --t-d-6: 34px;
}
html[data-motion="reduced"] {
  --t-fast: 0.001s; --t-med: 0.001s; --t-slow: 0.001s; --t-spin: 0.001s;
}

/* ============================================================
   2. THEME BLOCKS (immutable; token overrides only)
   ============================================================ */

/* --- Orthocord: cool steel on neutral charcoal --- */
html[data-theme="orthocord"] {
  color-scheme: dark;
  --t-pg: #0e0e10;  --t-base: #151518;  --t-base2: #1f1f24;  --t-elev: #28282e;
  --t-sur2: #26262c;
  --t-line: rgba(224, 228, 240, 0.14);  --t-line-hi: rgba(224, 228, 240, 0.24);
  --t-txt: #f2f0ea;  --t-txt2: #c8c5bd;  --t-mut: #8e8b83;
  --t-accent: #6ea8ff;  --t-accent-2: #2f6fd6;
  --t-ok: #5cc98a;  --t-warn: #e0b64d;  --t-err: #e0675f;
  --t-on-accent: #0c1320;  --t-accent-hi: #a9c9ff;
  --t-err-fg: #ffb0a6;  --t-ok-fg: #b9f1cd;
  --t-warn-bg: #333022;  --t-warn-fg: #efe6c8;  --t-warn-brd: #5a5133;
  --t-backdrop: rgba(8, 10, 16, 0.62);  --t-img-mat: rgba(0, 0, 0, 0.3);
  --t-avatar-ring: rgba(255, 255, 255, 0.16);
  --t-env-base: #0e0e10;
  --t-shell-gradient: linear-gradient(180deg, rgba(38, 48, 72, 0.72), rgba(16, 17, 22, 0.66));
  --t-shell-edge: rgba(160, 192, 255, 0.14);
  --t-env-glow-a: rgba(78, 120, 255, 0.22);
  --t-env-glow-b: rgba(28, 44, 110, 0.18);
  --t-env-depth: linear-gradient(132deg, #0b0c10 8%, #13141a 54%, #0e0f14 100%);
  --t-header-fade: linear-gradient(180deg, rgba(14, 14, 16, 0.68), transparent);
  --t-title-glow: rgba(110, 168, 255, 0.16);
  --t-hero-edge: rgba(200, 218, 255, 0.14);
  --t-hero-top: rgba(160, 190, 255, 0.09);
  --t-hero-bottom: rgba(12, 16, 26, 0.38);
}

/* --- Midnight: deep indigo-blue, dim and focused --- */
html[data-theme="midnight"] {
  color-scheme: dark;
  --t-pg: #070810;  --t-base: #0d0f1a;  --t-base2: #161930;  --t-elev: #1d2138;
  --t-sur2: #20243c;
  --t-line: rgba(190, 200, 255, 0.13);  --t-line-hi: rgba(190, 200, 255, 0.22);
  --t-txt: #e6e9ff;  --t-txt2: #b6bccf;  --t-mut: #79809a;
  --t-accent: #a78bfa;  --t-accent-2: #6d5ae6;
  --t-ok: #5cc98a;  --t-warn: #ddb64e;  --t-err: #e0675f;
  --t-on-accent: #150f2e;  --t-accent-hi: #cab9ff;
  --t-err-fg: #ffb0a6;  --t-ok-fg: #b9f1cd;
  --t-warn-bg: #28241e;  --t-warn-fg: #efe7cf;  --t-warn-brd: #4c4430;
  --t-backdrop: rgba(5, 6, 14, 0.66);  --t-img-mat: rgba(0, 0, 0, 0.34);
  --t-avatar-ring: rgba(255, 255, 255, 0.18);
  --t-env-base: #070810;
  --t-shell-gradient: linear-gradient(180deg, rgba(34, 30, 72, 0.74), rgba(13, 14, 26, 0.66));
  --t-shell-edge: rgba(176, 160, 255, 0.14);
  --t-env-glow-a: rgba(122, 80, 255, 0.24);
  --t-env-glow-b: rgba(40, 30, 120, 0.2);
  --t-env-depth: linear-gradient(132deg, #05060d 8%, #0c0d1a 54%, #080911 100%);
  --t-header-fade: linear-gradient(180deg, rgba(7, 8, 16, 0.7), transparent);
  --t-title-glow: rgba(167, 139, 250, 0.18);
  --t-hero-edge: rgba(190, 180, 255, 0.16);
  --t-hero-top: rgba(170, 150, 255, 0.1);
  --t-hero-bottom: rgba(8, 8, 20, 0.4);
}

/* --- Ember (default): hotter, saturated amber foreground --- */
html[data-theme="ember"] {
  color-scheme: dark;
  --t-pg: #130b07;  --t-base: #1c120b;  --t-base2: #2b1a10;  --t-elev: #391f11;
  --t-sur2: #33241a;
  --t-line: rgba(255, 196, 150, 0.16);  --t-line-hi: rgba(255, 196, 150, 0.28);
  --t-txt: #fff2e6;  --t-txt2: #e2c2ab;  --t-mut: #b0846c;
  --t-accent: #ff8a1f;  --t-accent-2: #ff4d1f;
  --t-ok: #58c97a;  --t-warn: #e2b03c;  --t-err: #e06a5e;
  --t-on-accent: #180f08;  --t-accent-hi: #ffc38a;
  --t-err-fg: #ffb49e;  --t-ok-fg: #b9f0c9;
  --t-warn-bg: #3d2c15;  --t-warn-fg: #f8eccb;  --t-warn-brd: #6a4f1e;
  --t-backdrop: rgba(24, 8, 2, 0.62);  --t-img-mat: rgba(0, 0, 0, 0.34);
  --t-avatar-ring: rgba(255, 255, 255, 0.2);
  --t-env-base: #130b07;
  --t-shell-gradient: linear-gradient(180deg, rgba(90, 44, 18, 0.82), rgba(30, 17, 10, 0.72));
  --t-shell-edge: rgba(255, 178, 122, 0.2);
  --t-env-glow-a: rgba(255, 112, 26, 0.38);
  --t-env-glow-b: rgba(180, 58, 12, 0.24);
  --t-env-depth: linear-gradient(132deg, #100904 8%, #1c110a 54%, #140c08 100%);
  --t-header-fade: linear-gradient(180deg, rgba(19, 11, 7, 0.7), transparent);
  --t-title-glow: rgba(255, 120, 40, 0.2);
  --t-hero-edge: rgba(255, 196, 150, 0.2);
  --t-hero-top: rgba(255, 166, 92, 0.14);
  --t-hero-bottom: rgba(36, 16, 8, 0.42);
}

/* --- Light: warm pale surfaces with dark text --- */
html[data-theme="light"] {
  color-scheme: light;
  --t-pg: #f6f0e7;  --t-base: #f0e9dc;  --t-base2: #e6dcc9;  --t-elev: #dccfb8;
  --t-sur2: #ddd2bd;
  --t-line: rgba(92, 60, 30, 0.16);  --t-line-hi: rgba(92, 60, 30, 0.3);
  --t-txt: #2b211a;  --t-txt2: #5a4a3d;  --t-mut: #8a7766;
  --t-accent: #c84f12;  --t-accent-2: #a8381b;
  --t-ok: #2f8d50;  --t-warn: #8f6a16;  --t-err: #c03a2b;
  --t-on-accent: #ffffff;  --t-accent-hi: #e26a28;
  --t-err-fg: #a62a1f;  --t-ok-fg: #1f6b3a;
  --t-warn-bg: #f4e6c0;  --t-warn-fg: #4d3d10;  --t-warn-brd: #c9a94f;
  --t-backdrop: rgba(70, 48, 30, 0.32);  --t-img-mat: rgba(70, 50, 30, 0.22);
  --t-avatar-ring: rgba(0, 0, 0, 0.24);
  --t-env-base: #f6f0e7;
  --t-shell-gradient: linear-gradient(180deg, rgba(255, 246, 232, 0.78), rgba(244, 233, 214, 0.62));
  --t-shell-edge: rgba(160, 104, 58, 0.2);
  --t-env-glow-a: rgba(255, 168, 92, 0.24);
  --t-env-glow-b: rgba(216, 140, 82, 0.16);
  --t-env-depth: linear-gradient(132deg, #f8f3eb 8%, #f2e9da 54%, #f0e7d4 100%);
  --t-header-fade: linear-gradient(180deg, rgba(246, 240, 231, 0.72), transparent);
  --t-title-glow: rgba(200, 104, 42, 0.14);
  --t-hero-edge: rgba(150, 104, 58, 0.18);
  --t-hero-top: rgba(255, 230, 205, 0.5);
  --t-hero-bottom: rgba(214, 184, 150, 0.3);
  --t-blur-s: 8px;   --t-sat-s: 106%;
  --t-blur-m: 12px;  --t-sat-m: 104%;
  --t-blur-l: 14px;  --t-sat-l: 102%;
  --t-inset-hi: inset 0 1px 0 rgba(255, 255, 255, 0.6);
  --t-inset-glass: inset 0 1px 0 rgba(255, 255, 255, 0.35);
  --t-sh-1: 0 16px 36px rgba(90, 60, 30, 0.2);
  --t-sh-2: 0 22px 52px rgba(90, 60, 30, 0.24);
  --t-sh-3: 0 10px 26px rgba(90, 60, 30, 0.18);
  --t-sh-4: 0 8px 24px rgba(90, 60, 30, 0.2);
  --t-sh-edge: 12px 0 36px rgba(90, 60, 30, 0.16);
  --t-sh-drawer: 24px 0 48px rgba(90, 60, 30, 0.4);
  --t-sh-hero: 0 20px 60px rgba(90, 60, 30, 0.16);
}

/* --- High Contrast: maximum readability --- */
html[data-theme="high-contrast"] {
  color-scheme: dark;
  --t-pg: #000000;  --t-base: #0b0b0d;  --t-base2: #16161a;  --t-elev: #212126;
  --t-sur2: #26262c;
  --t-line: #5d5d66;  --t-line-hi: #9a9aa4;
  --t-txt: #ffffff;  --t-txt2: #f2f2f5;  --t-mut: #c8c8cf;
  --t-accent: #ffb054;  --t-accent-2: #ff7a1f;
  --t-ok: #4fd98a;  --t-warn: #ffd75e;  --t-err: #ff7d7d;
  --t-on-accent: #241605;  --t-accent-hi: #ffc98c;
  --t-err-fg: #ffa0a0;  --t-ok-fg: #9ef2c0;
  --t-warn-bg: #3a2f14;  --t-warn-fg: #ffecad;  --t-warn-brd: #8a7432;
  --t-backdrop: rgba(0, 0, 0, 0.78);  --t-img-mat: rgba(0, 0, 0, 0.5);
  --t-avatar-ring: rgba(255, 255, 255, 0.32);
  --t-env-base: #000000;
  --t-shell-gradient: linear-gradient(180deg, rgba(40, 36, 28, 0.9), rgba(10, 10, 12, 0.9));
  --t-shell-edge: rgba(255, 176, 84, 0.26);
  --t-env-glow-a: rgba(255, 150, 60, 0.16);
  --t-env-glow-b: rgba(120, 70, 20, 0.1);
  --t-env-depth: linear-gradient(132deg, #000 8%, #0a0a0c 54%, #050506 100%);
  --t-header-fade: linear-gradient(180deg, rgba(0, 0, 0, 0.78), transparent);
  --t-title-glow: rgba(255, 176, 84, 0.2);
  --t-hero-edge: rgba(255, 190, 120, 0.22);
  --t-hero-top: rgba(255, 200, 140, 0.12);
  --t-hero-bottom: rgba(10, 6, 2, 0.5);
  --t-blur-s: 0px;  --t-sat-s: 100%;
  --t-blur-m: 0px;  --t-sat-m: 100%;
  --t-blur-l: 0px;  --t-sat-l: 100%;
  --t-inset-hi: none;  --t-inset-glass: none;
  --t-op-mid: 0.75;  --t-op-fade: 0.7;  --t-op-dim: 0.8;
}

/* High Contrast focus must be unmistakable. */
html[data-theme="high-contrast"] button:focus-visible,
html[data-theme="high-contrast"] a:focus-visible,
html[data-theme="high-contrast"] input:focus-visible,
html[data-theme="high-contrast"] select:focus-visible,
html[data-theme="high-contrast"] textarea:focus-visible,
html[data-theme="high-contrast"] [tabindex]:focus-visible {
  outline: 3px solid #7fd6ff !important;
  outline-offset: 2px !important;
}

/* --- Custom: values injected as --c-* by js/theme.js --- */
html[data-theme="custom"] {
  --t-pg: var(--c-pg);          --t-base: var(--c-base);
  --t-base2: var(--c-base2);    --t-elev: var(--c-elev);
  --t-txt: var(--c-txt);        --t-txt2: var(--c-txt2);  --t-mut: var(--c-mut);
  --t-accent: var(--c-accent);  --t-accent-2: var(--c-accent2);
  --t-accent-hi: var(--c-accent-hi);  --t-on-accent: var(--c-on-accent);
  --t-line: var(--c-line);      --t-line-hi: var(--c-line-hi);
  --t-env-base: var(--c-pg);
  --t-shell-gradient: var(--c-shell);
  --t-shell-edge: var(--c-shell-edge);
  --t-env-glow-a: var(--c-glow-a);
  --t-env-glow-b: var(--c-glow-b);
  --t-env-depth: var(--c-depth);
  --t-header-fade: var(--c-header-fade);
  --t-title-glow: var(--c-title-glow);
  --t-hero-edge: var(--c-hero-edge);
  --t-hero-top: var(--c-hero-top);
  --t-hero-bottom: var(--c-hero-bottom);
  --t-ok: var(--c-ok); --t-warn: var(--c-warn); --t-err: var(--c-err);
  --t-err-fg: var(--c-err-fg); --t-ok-fg: var(--c-ok-fg);
  --t-warn-bg: var(--c-warn-bg); --t-warn-fg: var(--c-warn-fg); --t-warn-brd: var(--c-warn-brd);
  --t-backdrop: var(--c-backdrop); --t-img-mat: var(--c-img-mat);
  --t-avatar-ring: var(--c-avatar-ring); --t-on-danger: var(--c-on-danger);
}

/* ============================================================
   3. BASE
   ============================================================ */

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  background: var(--t-pg);
  color: var(--t-txt);
  font-family: var(--t-font);
  font-size: var(--t-fs-m);
  line-height: 1.45;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

#app, .trycord-app {
  height: 100dvh;
  width: 100vw;
  max-width: 100vw;
  overflow: hidden;
  background: var(--t-pg);
  display: flex;
}

a { color: var(--t-accent-hi); text-decoration: none; }
a:hover { text-decoration: underline; }

button {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
  padding: 0;
}
button:disabled { cursor: not-allowed; opacity: var(--t-op-mid); }

input, select, textarea {
  font-family: inherit;
  font-size: var(--t-fs-m);
  color: var(--t-txt);
}

img { max-width: 100%; }

::selection { background: color-mix(in srgb, var(--t-accent) 40%, transparent); }

* { scrollbar-width: thin; scrollbar-color: var(--t-line-hi) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--t-line-hi); border-radius: 6px; border: 2px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-track { background: transparent; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: var(--z-skip);
  background: var(--t-elev);
  color: var(--t-txt);
  padding: var(--t-d-3) var(--t-d-4);
  border-radius: 0 0 var(--t-r-s) 0;
}
.skip-link:focus { left: 0; }

/* ============================================================
   4. SHELL LAYOUT (structural; protected from custom CSS)
   ============================================================ */

.shell {
  flex: 1 1 100% !important;
  min-width: 0 !important;
  min-height: 0 !important;
}

.shell--desktop {
  display: grid !important;
  /* Three-column layout: rail + context sidebar + main content */
  grid-template-columns: var(--ui-rail) var(--ui-sidebar) minmax(0, 1fr) !important;
  height: 100dvh !important;
  width: 100% !important;
  overflow: hidden !important;
  background:
    radial-gradient(circle at 72% -8%, color-mix(in srgb, var(--t-accent) 14%, transparent), transparent 30%),
    var(--t-pg);
}

.app-rail {
  display: contents !important;
}
.rail-identity {
  display: none !important;
}
.rail-global-nav {
  display: none !important;
}
/* Ultrawide: 1920px and beyond.
   The frame keeps using the full viewport (rail + sidebar hug the left
   edge, member list hugs the right), but the CONTENT column is capped so
   conversation measure, settings forms and tables stay readable instead of
   one line of text stretching across 3000px. */
@media (min-width: 1920px) { :root { --ui-content-max: 1680px; } }
@media (min-width: 2560px) { :root { --ui-content-max: 2040px; } }
@media (min-width: 3440px) { :root { --ui-content-max: 2400px; } }

/* Content column: centre the readable measure inside the main column. */
.view-root > .page,
.view-root > .conversation,
.view-root > .home-environment,
.view-root > .settings-layout {
  max-width: var(--ui-content-max, none);
  margin-inline: auto;
  width: 100%;
}

/* Application rail: the global navigation column. */
.app-rail__items {
  grid-column: 1 !important;
  grid-row: 1 / 4 !important;
  min-height: 0 !important;
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
  gap: 6px !important;
  padding: 12px 8px !important;
  overflow-y: auto !important;
  overflow-x: hidden !important;
  border-right: 1px solid var(--t-line);
  background: color-mix(in srgb, var(--t-base) 96%, var(--t-accent));
}

/* Context sidebar: routes the rail selection to its own navigation. */



/* User bar pinned to the bottom of the context sidebar. One component for
   every context: identity left, session controls right. */
/* Pinned session bar at the foot of the context sidebar.
   The margins must not be negative. The sidebar is `overflow: hidden` and has
   no padding of its own (the padding lives on .ctx-scroll), so a negative
   bottom margin did not bleed the card to the edge - it pushed it past the
   sidebar's bottom border and the overflow clipped the name and status. */
.user-controls {
  display: flex;
  align-items: center;
  gap: var(--t-d-2);
  flex: 0 0 auto;
  margin: 0;
  padding: var(--t-d-3);
  border-top: 1px solid var(--t-line);
  background: color-mix(in srgb, var(--t-base2) 70%, var(--t-base));
  min-width: 0;
}
.user-controls__identity {
  display: flex;
  align-items: center;
  gap: var(--t-d-3);
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--t-d-2);
  border-radius: var(--t-r-s);
  text-align: left;
}
.user-controls__identity:hover { background: color-mix(in srgb, var(--t-txt) 6%, transparent); }
.user-controls__avatar { display: flex; flex: 0 0 auto; }
.user-controls__info { display: flex; flex-direction: column; min-width: 0; }
.user-controls__name {
  font-size: var(--t-fs-s);
  font-weight: 700;
  color: var(--t-txt);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.user-controls__status { color: var(--t-mut); font-size: var(--t-fs-xs); }
.user-controls__buttons { display: flex; gap: 2px; flex: 0 0 auto; }
.user-controls__btn {
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--t-r-s);
  color: var(--t-mut);
  font-size: 0.95rem;
}
.user-controls__btn:hover { background: var(--t-txt); color: var(--t-base); }
.desktop-backdrop {
  position: fixed !important;
  inset: 0 !important;
  z-index: 55 !important;
  background: rgba(0, 0, 0, 0.55) !important;
}
.desktop-backdrop[hidden] { display: none !important; }
.nav-toggle {
  flex: 0 0 auto !important;
  width: 34px !important;
  height: 34px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  border-radius: 6px !important;
  color: var(--t-mut) !important;
  background: transparent !important;
  font-size: 1.1rem !important;
}
.nav-toggle:hover { background: var(--t-base2) !important; color: var(--t-txt) !important; }
@media (prefers-reduced-motion: reduce) {
  .shell--desktop .app-rail { transition: none !important; }
}

/* ---- collapsible sidebar -------------------------------------------------- */
/* Collapsed: the icon rail stays, the context sidebar is released, and the
   main content column takes the freed width immediately. The stored
   preference only decides the default state; the context-header hamburger
   still opens it on demand. Nothing opens on hover any more. */
.shell--desktop.sidebar-collapsed {
  grid-template-columns: var(--ui-rail) minmax(0, 1fr) !important;
}
.shell--desktop.sidebar-collapsed .main-content {
  grid-column: 2 !important;
}
.shell--desktop.sidebar-collapsed .rail-identity,
.shell--desktop.sidebar-collapsed .context-sidebar {
  display: none !important;
}
/* Collapsed: the rail stays, the context sidebar is released, and the main
   content column takes the freed width immediately (no reserved track left
   behind). The stored preference only decides the default state; the
   hamburger still opens it on demand. */
.shell--desktop.sidebar-collapsed {
  grid-template-columns: var(--ui-rail) minmax(0, 1fr) !important;
}
.shell--desktop.sidebar-collapsed .main-content {
  grid-column: 2 !important;
  width: 100% !important;
}
.shell--desktop.sidebar-collapsed .context-sidebar,
.shell--desktop.sidebar-collapsed .rail-identity {
  display: none !important;
}
/* Collapsing must not cap the content measure: give the extra width back. */
.shell--desktop.sidebar-collapsed .view-root > .page,
.shell--desktop.sidebar-collapsed .view-root > .conversation,
.shell--desktop.sidebar-collapsed .view-root > .home-environment {
  max-width: none;
  margin-inline: 0;
}
/* Explicit toggle: the context-header hamburger (.nav-toggle) flips
   .nav-open, which slides the context sidebar in as an overlay drawer.
   This is the accessible, touch-friendly path and the only one on mobile
   pointer devices. */
.shell--desktop.nav-open .context-sidebar {
  display: flex !important;
  position: fixed !important;
  left: var(--ui-rail) !important;
  top: 0 !important;
  bottom: 0 !important;
  width: var(--ui-sidebar) !important;
  z-index: 60 !important;
  box-shadow: var(--t-sh-drawer) !important;
}
.shell--desktop.nav-open .context-sidebar,
.shell--desktop.nav-open .app-rail__items {
  animation: none;
}
/* The hamburger is only meaningful while the sidebar is not already docked. */
/* The hamburger is always available: it is the keyboard/touch path to the
   context sidebar when the sidebar is collapsed or off-canvas. */
/* Collapse toggle button — visible in both expanded and collapsed states */
.sidebar-collapse-toggle {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  color: var(--t-mut);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  background: transparent;
  border: 1px solid var(--t-line);
  cursor: pointer;
  flex: 0 0 auto;
}
.sidebar-collapse-toggle:hover {
  background: var(--t-base2);
  color: var(--t-txt);
  border-color: var(--t-line-hi);
}
/* When collapsed, the rail-foot toggle gets a divider */
.shell--desktop.sidebar-collapsed .rail-foot .sidebar-collapse-toggle {
  margin-top: 8px;
  position: relative;
}
.shell--desktop.sidebar-collapsed .rail-foot .sidebar-collapse-toggle::before {
  content: "";
  position: absolute;
  top: -8px;
  left: 50%;
  transform: translateX(-50%);
  width: 32px;
  height: 1px;
  background: var(--t-line);
}
/* Profile editor. Only layout lives here — inputs, labels, hints and
   dividers all come from the shared control primitives, so a field in
   Settings looks identical to a field during registration. */
.profile-editor {
  width: 100%;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--t-d-5);
}

/* Home/DM context sidebar: search, new message, conversation list. */

.main-content {
  grid-column: 3 !important;
  min-width: 0 !important;
  min-height: 0 !important;
  height: 100dvh !important;
  display: flex !important;
  flex-direction: column !important;
  overflow: hidden !important;
  position: relative !important;
  background: var(--t-env-depth);
}
.main-content::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(700px 320px at 80% -10%, var(--t-env-glow-a), transparent 65%),
    radial-gradient(600px 280px at 10% 110%, var(--t-env-glow-b), transparent 68%);
}

.context-header {
  flex: 0 0 auto !important;
  min-height: 58px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  gap: 12px !important;
  padding: 0 18px !important;
  border-bottom: 1px solid var(--t-line);
  background: color-mix(in srgb, var(--t-base) 90%, transparent);
  backdrop-filter: blur(18px);
  position: relative !important;
  z-index: var(--z-inline) !important;
}
.context-header__titles {
  min-width: 0 !important;
  flex: 1 1 auto !important;
  display: flex !important;
  align-items: center !important;
  gap: 10px !important;
}
.context-title {
  font-size: var(--t-fs-l);
  font-weight: 800;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0;
  flex: 0 0 auto;
  max-width: 40%;
}
.context-sub {
  color: var(--t-mut);
  font-size: var(--t-fs-s);
  font-weight: 400;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
}
.context-header__icon {
  display: none;
  width: 40px; height: 40px;
  flex: 0 0 auto;
  border-radius: 9px;
  background: var(--t-base2);
  color: var(--t-accent);
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
  font-weight: 800;
}
.context-header[data-has-icon="true"] .context-header__icon { display: inline-flex; }
.context-actions {
  flex: 0 0 auto !important;
  display: flex !important;
  align-items: center !important;
  gap: 6px !important;
  margin-left: auto !important;
}
/* Chat-header icon buttons: every contextual header action renders as a
   34px quiet icon button (reference chat-actions pattern). */
.context-actions button {
  width: 34px !important;
  height: 34px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  border-radius: 6px !important;
  color: var(--t-mut) !important;
  background: transparent !important;
  font-size: 1rem !important;
}
.context-actions button:hover { background: var(--t-base2) !important; color: var(--t-txt) !important; }

.chat-environment {
  flex: 1 1 auto !important;
  min-height: 0 !important;
  display: grid !important;
  /* The member track follows the rendered sidebar: a hidden member
     sidebar releases its column instead of leaving a phantom rail. */
  grid-template-columns: minmax(0, 1fr) auto !important;
  position: relative !important;
  z-index: 1 !important;
}
.view-root {
  grid-column: 1 !important;
  min-width: 0 !important;
  min-height: 0 !important;
  overflow-y: auto !important;
  overflow-x: hidden !important;
  padding: 0;
}
.chat-environment > .member-sidebar {
  grid-column: 2 !important;
  width: var(--ui-members) !important;
  max-width: var(--ui-members) !important;
  min-width: 0 !important;
  min-height: 0 !important;
  overflow-y: auto !important;
  overflow-x: hidden !important;
  border-left: 1px solid var(--t-line);
  background: color-mix(in srgb, var(--t-base) 88%, var(--t-pg));
  padding: var(--t-d-5) 12px 20px;
}
.member-sidebar__header {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: -2px 0 12px;
  padding: 4px 8px 10px;
  background: color-mix(in srgb, var(--t-base) 94%, transparent);
  backdrop-filter: blur(12px);
  color: var(--t-txt2);
  font-size: var(--t-fs-xs);
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.member-count { color: var(--t-mut); font-weight: 700; flex-shrink: 0; white-space: nowrap; }
.member-group { margin: 0 0 16px; }
.member-group__label {
  padding: 0 8px 6px;
  color: var(--t-mut);
  font-size: var(--t-fs-xs);
  letter-spacing: 0.11em;
  font-weight: 850;
}
.row--member .member-item__info { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; }
.row--member .member-item__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-fs-m); font-weight: 700; }
.row--member .member-item__role { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--t-mut); font-size: var(--t-fs-xs); }
.member-sidebar__empty { color: var(--t-mut); padding: 20px 8px; font-size: 0.8rem; }
.member-list { display: flex; flex-direction: column; gap: 2px; }

/* Self-assignable roles on the member list.
   The row itself is a <button> that navigates to the profile, so the "Roles"
   pill is a SIBLING inside a wrapper rather than a child of it: nesting a
   button in a button is invalid and every click would also fire the row's
   navigation. Revealed on hover/focus like the rest of the row affordances,
   but never display:none - a keyboard user must be able to tab to it. */
.member-row-wrap { position: relative; display: flex; align-items: center; gap: 4px; }
.member-row-wrap > .row--member { flex: 1 1 auto; min-width: 0; }
.member-roles-pill {
  flex: 0 0 auto;
  padding: 2px 9px;
  border: 1px solid var(--t-line-hi);
  border-radius: 999px;
  background: var(--t-base2);
  color: var(--t-txt2);
  font-size: var(--t-fs-xs);
  font-weight: 600;
  line-height: 1.6;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s ease;
}
.member-row-wrap:hover .member-roles-pill,
.member-row-wrap:focus-within .member-roles-pill { opacity: 1; }
.member-roles-pill:hover { border-color: var(--t-accent); color: var(--t-txt); }
.member-roles-pill:focus-visible { opacity: 1; outline: 2px solid var(--t-accent); outline-offset: 1px; }
/* Touch and narrow sidebars have no hover, so keep it permanently visible
   rather than leaving the only self-assign entry point unreachable. */
@media (hover: none), (max-width: 900px) { .member-roles-pill { opacity: 1; } }

.self-role-list { display: flex; flex-direction: column; gap: 2px; margin-top: var(--t-d-3); }
.self-role {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: var(--t-r-s);
  cursor: pointer;
}
.self-role:hover { background: var(--t-base2); }
.self-role input { flex: 0 0 auto; }
.self-role__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.self-role input:disabled { cursor: progress; }

.role-selfassign {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--t-line);
  border-radius: var(--t-r-s);
  background: var(--t-base2);
  cursor: pointer;
}
.role-selfassign input { flex: 0 0 auto; margin-top: 3px; }
.role-selfassign__text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.role-selfassign__text small { color: var(--t-mut); font-size: var(--t-fs-xs); line-height: 1.45; }

/* The UA hides [hidden]; layout rules must never override it. */
.shell[hidden],
[hidden] { display: none !important; }

/* Focus must always remain visible, in every theme. */
button:focus-visible, a:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--t-accent) !important;
  outline-offset: 1px !important;
}

/* ============================================================
   5. NAVIGATION ELEMENTS
   ============================================================ */

.realm-title {
  font-size: var(--t-fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--t-mut);
  padding: var(--t-d-3) var(--t-d-4) var(--t-d-2);
}
.app-rail__items .realm-title { display: none; }

.row--nav {
  min-width: 0;
}
.row--nav:hover { background: color-mix(in srgb, var(--t-txt) 6%, transparent); color: var(--t-txt); }
.row--nav.active {
  color: var(--t-txt);
  background: color-mix(in srgb, var(--t-accent) 12%, transparent);
  box-shadow: inset 2px 0 0 var(--t-accent);
}
.row--nav .nv-icon {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  border-radius: 9px;
  background: color-mix(in srgb, var(--t-txt) 5%, transparent);
  color: var(--t-mut);
  display: flex; align-items: center; justify-content: center;
  font-size: 1rem;
}
.row--nav.active .nv-icon {
  color: var(--t-accent);
  background: color-mix(in srgb, var(--t-accent) 16%, transparent);
}
.row--nav .nv-label {
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: 650;
  font-size: 0.88rem;
}
.row--nav .nv-count {
  flex: 0 0 auto;
  background: var(--t-accent);
  color: var(--t-on-accent);
  font-size: var(--t-fs-xs);
  font-weight: 700;
  border-radius: 999px;
  min-width: 20px;
  padding: 1px 7px;
  text-align: center;
}


.server-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 7px 10px;
  border-radius: 12px;
  color: var(--t-txt2);
  text-align: left;
}
.server-chip:hover { background: color-mix(in srgb, var(--t-txt) 6%, transparent); color: var(--t-txt); }
.server-chip.active {
  background: color-mix(in srgb, var(--t-accent) 13%, var(--t-base2));
  color: var(--t-txt);
  box-shadow: inset 2px 0 0 var(--t-accent);
}
.server-chip .chip-badge {
  flex: 0 0 auto;
  width: 36px; height: 36px;
  border-radius: 11px;
  background: linear-gradient(145deg, var(--t-accent), var(--t-accent-2));
  color: var(--t-on-accent);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800;
}
.server-chip .chip-name { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 650; }
.server-chip .chip-live { flex: 0 0 auto; color: var(--t-accent); }

/* ============================================================
   Application rail
   One shape system for every rail entry (global destination,
   community, create, account). Idle entries stay quiet; hover and
   the active route morph into a filled rounded square so the
   current destination is unmistakable without a glowing slab.
   Every entry also mirrors its label into data-label, which is the
   only affordance the collapsed rail has besides the icon.
   ============================================================ */
.app-rail__items .rail-nav-item,
.app-rail__items .server-chip,
.app-rail__items .community-action {
  width: 44px;
  height: 44px;
  min-height: 44px;
  margin: 0;
  padding: 0;
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  flex: 0 0 auto;
  background: transparent;
  border: 1px solid transparent;
  color: var(--t-mut);
  cursor: pointer;
  text-decoration: none;
  transition:
    border-radius var(--t-fast) var(--t-ease),
    background var(--t-fast) var(--t-ease),
    color var(--t-fast) var(--t-ease);
}
.app-rail__items .community-action { border-style: dashed; border-color: var(--t-line); }
.app-rail__items .chip-name,
.app-rail__items .chip-live,
.app-rail__items .nv-label { display: none; }
.app-rail__items .nv-icon {
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
}

.app-rail__items .rail-nav-item:hover,
.app-rail__items .server-chip:hover,
.app-rail__items .community-action:hover {
  background: var(--t-accent);
  border-color: transparent;
  border-radius: 12px;
  color: var(--t-on-accent);
}
.app-rail__items .server-chip:hover { transform: translateY(-1px); }

.app-rail__items .rail-nav-item.active,
.app-rail__items .server-chip.active {
  background: var(--t-accent);
  border-color: transparent;
  border-radius: 12px;
  color: var(--t-on-accent);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--t-accent) 26%, transparent);
}
.app-rail__items .community-action:active { transform: scale(0.94); }

.rail-nav-icon { font-size: 1.15rem; line-height: 1; }
.rail-nav-badge {
  position: absolute;
  top: -1px;
  right: -1px;
  min-width: 17px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--t-accent);
  color: var(--t-on-accent);
  border: 2px solid var(--t-base);
  font-size: 0.6rem;
  font-weight: 800;
  line-height: 1.5;
  text-align: center;
}
.rail-nav-item.active .rail-nav-badge,
.server-chip.active .rail-nav-badge {
  background: var(--t-on-accent);
  color: var(--t-accent);
  border-color: var(--t-accent);
}

/* Rail tooltips. CSS cannot read the title attribute, so shell.js mirrors
   the label into data-label; this renders it on hover and keyboard focus.
   The button already carries aria-label, so this is decoration only. */
.app-rail__items [data-label]:hover::after,
.app-rail__items [data-label]:focus-visible::after {
  content: attr(data-label);
  position: absolute;
  left: calc(100% + 12px);
  top: 50%;
  transform: translateY(-50%);
  z-index: 70;
  padding: 5px 9px;
  border-radius: 7px;
  background: var(--t-elev);
  border: 1px solid var(--t-line-hi);
  color: var(--t-txt);
  box-shadow: var(--t-sh-3);
  font-size: var(--t-fs-s);
  font-weight: 650;
  white-space: nowrap;
  pointer-events: none;
}

.rail-divider {
  width: 28px;
  height: 1px;
  flex: 0 0 auto;
  margin: 6px 0;
  background: var(--t-line);
}
/* Rail foot: account + collapse toggle, pinned to the column bottom. */
.app-rail__items .rail-foot {
  margin-top: auto;
  padding-top: 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  position: relative;
}
.app-rail__items .rail-foot::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 32px;
  height: 1px;
  background: var(--t-line);
}
.app-rail__items .rail-foot-btn { position: relative; }
.app-rail__items .rail-foot-btn .nv-count.rail-badge {
  position: absolute;
  top: 2px;
  right: 2px;
}

.row--channel {
  min-height: 40px;
  margin: 1px 0;
  color: var(--t-mut);
}
.row--channel:hover { background: color-mix(in srgb, var(--t-txt) 5%, transparent); color: var(--t-txt2); }
.row--channel.active {
  color: var(--t-txt);
  background: color-mix(in srgb, var(--t-accent) 13%, transparent);
  box-shadow: inset 2px 0 0 var(--t-accent);
}
.row--channel .ch-prefix { font-weight: 800; color: var(--t-mut); }
.row--channel.active .ch-prefix { color: var(--t-accent); }
.row--channel .ch-name { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }



.presence-dot {
  flex: 0 0 auto;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--t-mut);
}
.presence-dot.online { background: var(--t-ok); }

.community-action { justify-content: center; border: 1px dashed var(--t-line); }
.app-rail__items .community-actions { width: 100%; }
.app-rail__items .community-action { width: 48px; }



/* ============================================================
   6. OVERLAYS
   ============================================================ */

.modal-root { position: relative; z-index: var(--z-modal); }
.backdrop {
  position: fixed !important;
  inset: 0 !important;
  background: var(--t-backdrop);
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  padding: var(--t-d-4);
  z-index: var(--z-modal) !important;
  backdrop-filter: blur(2px);
}
.modal {
  width: min(92vw, 460px);
  max-height: 85dvh;
  overflow-y: auto;
  background: var(--t-elev);
  border: 1px solid var(--t-line-hi);
  border-radius: var(--t-r-l);
  padding: var(--t-d-5);
  box-shadow: var(--t-sh-2);
  animation: rise var(--t-med) var(--t-ease);
}
.modal h2, .modal h3 { margin: 0 0 var(--t-d-3); letter-spacing: -0.01em; }
.modal p { color: var(--t-txt2); }
@keyframes rise {
  from { opacity: 0.4; transform: translateY(14px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.popover-root { position: relative; z-index: var(--z-popover); }
.popover {
  position: fixed !important;
  z-index: var(--z-popover) !important;
  min-width: 200px;
  max-width: 320px;
  background: var(--t-elev);
  border: 1px solid var(--t-line-hi);
  border-radius: var(--t-r-m);
  padding: 6px;
  box-shadow: var(--t-sh-1);
  animation: rise var(--t-fast) var(--t-ease);
}
/* Context menu: a popover carrying menu semantics. Items align in a single
   column and support keyboard focus traversal. */
.popover.ctx-menu { min-width: 190px; padding: 5px; }
.popover.ctx-menu .pop-item {
  width: 100%;
  text-align: left;
  white-space: nowrap;
}
.popover.ctx-menu .pop-item[aria-disabled="true"],
.popover.ctx-menu .pop-item:disabled { opacity: 0.45; cursor: default; }
.popover.ctx-menu .pop-item[aria-disabled="true"]:hover,
.popover.ctx-menu .pop-item:disabled:hover { background: transparent; }

.pop-item {
  display: flex;
  align-items: center;
  gap: var(--t-d-3);
  width: 100%;
  padding: 8px var(--t-d-3);
  border-radius: var(--t-r-s);
  color: var(--t-txt);
  text-align: left;
  font-size: var(--t-fs-m);
}
.pop-item:hover { background: var(--t-base2); }
.pop-item .pop-desc { display: block; font-size: var(--t-fs-xs); color: var(--t-mut); }
.pop-item.danger { color: var(--t-err); }
.pop-item.danger:hover { background: color-mix(in srgb, var(--t-err) 14%, transparent); }
.pop-sep { height: 1px; background: var(--t-line); margin: 6px 0; }
.pop-item[disabled] { opacity: 0.45; cursor: default; }
.pop-item[disabled]:hover { background: transparent; }
/* Session footer pinned to the bottom of the place navigation
   (reference sidebar-user pattern): live identity + settings shortcut. */
/* User popup card (Checkpoint C, reference user-popup pattern): banner
   with overlapping avatar, name + handle, Message/Profile actions. */
.user-card { min-width: 240px; width: 300px; max-width: calc(100vw - 32px); padding: 0 0 6px; overflow: hidden; }
.user-card__banner {
  height: 72px;
  margin: 0;
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--t-base2) 60%, transparent),
    color-mix(in srgb, var(--t-accent) 38%, var(--t-base2)));
}
.popover.user-card .user-card__head { align-items: flex-end; padding: 0 14px; }
.popover.user-card .user-card__head .avatar { width: 72px; height: 72px; font-size: 1.5rem; margin-top: -36px; border: 6px solid var(--t-elev); flex-shrink: 0; }
.user-card__body { padding: 8px 14px 4px; display: flex; flex-direction: column; gap: 2px; }
.user-card__head { display: flex; gap: var(--t-d-3); align-items: center; padding: var(--t-d-2); }

.user-card__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-card__status { font-size: var(--t-fs-s); color: var(--t-mut); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-card__actions { display: flex; gap: var(--t-d-2); flex-wrap: wrap; padding: var(--t-d-2); border-top: 1px solid var(--t-line); }
/* Engagement surfaces (G milestone): reactions, pins, search, mute. */
.msg-reactions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.msg-reactions[hidden] { display: none; }
.react-pill {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--t-line);
  background: var(--t-base2);
  color: var(--t-txt2);
  font-size: var(--t-fs-s);
  line-height: 1.4;
}
.react-pill:hover:not([disabled]) { border-color: var(--t-accent); }
.react-pill.mine { border-color: var(--t-accent); background: color-mix(in srgb, var(--t-accent) 14%, transparent); color: var(--t-txt); }
.react-pill[disabled] { cursor: default; opacity: 0.9; }
.msg-pinned { margin-left: 6px; font-size: var(--t-fs-s); }
.row--channel.muted { opacity: 0.55; }
.row--channel.muted .ch-name { text-decoration: line-through; text-decoration-thickness: 1px; }
.emoji-btn { color: var(--t-mut); font-size: 1.15rem; padding: 6px 8px; border-radius: var(--t-r-s); background: transparent; }
.emoji-btn:hover { color: var(--t-txt); background: var(--t-base2); }
.popover.emoji-picker {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 2px;
  padding: 8px;
  width: 300px;
  max-width: calc(100vw - 32px);
}
.emoji-cell { font-size: 1.3rem; padding: 4px; border-radius: 6px; background: transparent; line-height: 1.2; }
.emoji-cell:hover { background: var(--t-base2); }
.search-panel {
  position: fixed;
  top: 64px;
  right: 16px;
  width: min(420px, calc(100vw - 32px));
  max-height: min(70vh, 560px);
  display: flex; flex-direction: column; gap: 8px;
  padding: 12px;
  border-radius: 12px;
  border: 1px solid var(--t-line-hi);
  background: var(--t-elev);
  box-shadow: var(--t-sh-1);
  z-index: var(--z-popover);
}
.search-results { overflow-y: auto; display: flex; flex-direction: column; gap: 6px; }
.search-hit {
  text-align: left;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--t-line);
  background: var(--t-base2);
  color: var(--t-txt);
  display: flex; flex-direction: column; gap: 2px;
  width: 100%;
}
.search-hit:hover { border-color: var(--t-accent); }
.search-hit__meta { font-size: var(--t-fs-xs); color: var(--t-mut); }
.search-hit__text { font-size: var(--t-fs-m); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg.flash { animation: msg-flash 1.6s ease; }
@keyframes msg-flash {
  0%, 40% { background: color-mix(in srgb, var(--t-accent) 22%, transparent); }
  100% { background: transparent; }
}
.verify-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--t-d-3);
  flex-wrap: wrap;
  padding: 8px 16px;
  background: color-mix(in srgb, var(--t-accent) 14%, var(--t-base));
  border-bottom: 1px solid color-mix(in srgb, var(--t-accent) 40%, var(--t-line));
  color: var(--t-txt);
  font-size: var(--t-fs-s);
  font-weight: 600;
  z-index: 5;
}
.verify-banner__text { margin-right: 4px; }
.modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: var(--t-d-2); }
.modal-head h2 { margin: 0; }
.eyebrow { margin: 0 0 2px; font-size: var(--t-fs-xs); font-weight: 800; letter-spacing: 0.09em; text-transform: uppercase; color: var(--t-accent); }
.modal-close {
  flex: 0 0 auto;
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px;
  color: var(--t-mut);
  font-size: 1.2rem;
  line-height: 1;
}
.modal-close:hover { background: var(--t-base2); color: var(--t-txt); }

.notif-row { align-items: center; }
.notif-row.unread { border-color: color-mix(in srgb, var(--t-accent) 55%, var(--t-line)); }
.unread-dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; background: var(--t-accent); }

.toast-root {
  position: fixed !important;
  right: var(--t-d-4) !important;
  bottom: var(--t-d-4) !important;
  display: flex !important;
  flex-direction: column !important;
  gap: var(--t-d-2);
  z-index: var(--z-toast) !important;
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  background: var(--t-elev);
  border: 1px solid var(--t-line-hi);
  border-left: 3px solid var(--t-accent);
  border-radius: var(--t-r-m);
  padding: var(--t-d-3) var(--t-d-4);
  min-width: 240px;
  max-width: 360px;
  box-shadow: var(--t-sh-4);
  font-size: var(--t-fs-m);
  animation: rise var(--t-med) var(--t-ease);
}
.toast.error { border-left-color: var(--t-err); }
.toast.ok   { border-left-color: var(--t-ok); }
.toast.warn { border-left-color: var(--t-warn); }

.connection-status {
  position: fixed !important;
  top: 0 !important;
  left: 50% !important;
  transform: translateX(-50%) !important;
  z-index: var(--z-status) !important;
  background: var(--t-warn-bg);
  color: var(--t-warn-fg);
  border: 1px solid var(--t-warn-brd);
  border-radius: 0 0 var(--t-r-m) var(--t-r-m);
  font-size: var(--t-fs-s);
  padding: 5px var(--t-d-4);
  display: none;
  align-items: center;
  gap: var(--t-d-2);
}
.connection-status.show { display: flex !important; animation: rise var(--t-fast); }


/* ============================================================
   7. CONTROLS

   Button hierarchy. A screen should make its intent obvious, so the
   levels are visually distinct rather than all being filled chips:

     (default)  SECONDARY - neutral surface, neutral hover
     .primary   PRIMARY   - solid accent. One per view; the main action.
     .ghost     GHOST     - no surface until hovered. Cancel, dismiss.
     .quiet     TERTIARY  - text only, no chrome at all.
     .danger    DESTRUCTIVE - red outline, fills only on hover.

   Sizing (.sm/.block/.icon) is orthogonal to emphasis, so the two
   axes never fight each other.
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--t-d-2);
  min-height: 36px;
  padding: 7px var(--t-d-4);
  border-radius: 10px;
  font-weight: 650;
  font-size: var(--t-fs-m);
  line-height: 1.2;
  white-space: nowrap;
  color: var(--t-txt);
  background: var(--t-base2);
  border: 1px solid var(--t-line-hi);
  transition:
    background var(--t-fast) var(--t-ease),
    border-color var(--t-fast) var(--t-ease),
    color var(--t-fast) var(--t-ease),
    opacity var(--t-fast) var(--t-ease);
}
/* Secondary hover stays neutral. An accent border on every button was
   flattening the hierarchy and spreading amber across the whole app. */
.btn:hover { background: var(--t-elev); border-color: var(--t-txt); }
.btn:active { transform: translateY(1px); }

.btn.primary {
  background: var(--t-accent);
  border-color: var(--t-accent);
  color: var(--t-on-accent);
  font-weight: 700;
}
.btn.primary:hover { background: var(--t-accent-hi); border-color: var(--t-accent-hi); color: var(--t-on-accent); }

/* Ghost keeps a hairline border: without it these read as plain text links
   rather than controls. `.quiet` is the genuinely borderless tier. */
.btn.ghost { background: transparent; border-color: var(--t-line); color: var(--t-txt2); }
.btn.ghost:hover { background: color-mix(in srgb, var(--t-txt) 8%, transparent); border-color: var(--t-line-hi); color: var(--t-txt); }

.btn.quiet { background: transparent; border-color: transparent; color: var(--t-mut); padding-inline: var(--t-d-2); }
.btn.quiet:hover { background: color-mix(in srgb, var(--t-txt) 8%, transparent); color: var(--t-txt); }

.btn.danger {
  background: transparent;
  border-color: color-mix(in srgb, var(--t-err) 55%, transparent);
  color: var(--t-err);
}
.btn.danger:hover { background: var(--t-err); border-color: var(--t-err); color: var(--t-on-danger); }
.btn.danger.ghost { border-color: transparent; }

/* Sizing (orthogonal to emphasis). */
.btn.sm { min-height: 28px; padding: 4px var(--t-d-3); font-size: var(--t-fs-s); }
.btn.lg { min-height: 42px; padding: 10px var(--t-d-5); font-size: var(--t-fs-l); }
.btn.block { width: 100%; }
.btn.icon { width: 36px; min-height: 36px; padding: 0; color: var(--t-txt2); }
.btn.icon.sm { width: 28px; min-height: 28px; }

/* Selected / pressed state for toggle-style buttons (update channel,
   theme pickers). Communicates state by fill + border + weight, not
   colour alone. */
.btn.active,
.btn[aria-pressed="true"] {
  background: color-mix(in srgb, var(--t-accent) 16%, transparent);
  border-color: var(--t-accent);
  color: var(--t-accent-hi);
  font-weight: 700;
}

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}
.btn[aria-busy="true"] { pointer-events: none; }
.btn[aria-busy="true"]::before {
  content: "";
  width: 12px; height: 12px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin var(--t-spin) linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--t-d-4); }
.field label { font-size: var(--t-fs-s); font-weight: 650; color: var(--t-txt2); }
.field .hint, .hint { font-size: var(--t-fs-xs); color: var(--t-mut); }
.field.is-disabled { opacity: 0.68; }
.field.row-line { flex-direction: row; align-items: center; }

.input, .select, .textarea, select.input {
  width: 100%;
  background: var(--t-base2);
  border: 1px solid var(--t-line-hi);
  border-radius: 10px;
  padding: 9px var(--t-d-3);
  color: var(--t-txt);
  transition: border-color var(--t-fast);
}
.input:focus, .select:focus, .textarea:focus, select.input:focus {
  border-color: color-mix(in srgb, var(--t-accent) 72%, var(--t-line));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--t-accent) 12%, transparent);
  outline: none;
}
.input::placeholder, .textarea::placeholder { color: var(--t-mut); }
.textarea { resize: vertical; min-height: 72px; }
.input.invalid, .textarea.invalid { border-color: var(--t-err); }
.input.sm { padding: 5px 8px; font-size: var(--t-fs-s); }
select.input { appearance: auto; }

.form-error {
  background: color-mix(in srgb, var(--t-err) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--t-err) 40%, transparent);
  color: var(--t-err-fg);
  border-radius: var(--t-r-s);
  padding: var(--t-d-3) var(--t-d-4);
  font-size: var(--t-fs-s);
  margin-bottom: var(--t-d-4);
}
.form-success {
  background: color-mix(in srgb, var(--t-ok) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--t-ok) 40%, transparent);
  color: var(--t-ok-fg);
  border-radius: var(--t-r-s);
  padding: var(--t-d-3) var(--t-d-4);
  font-size: var(--t-fs-s);
  margin-bottom: var(--t-d-4);
}

.switch { display: inline-flex; align-items: center; gap: var(--t-d-3); cursor: pointer; user-select: none; }
.switch input { accent-color: var(--t-accent); }

.badge.ok { color: var(--t-ok); border-color: color-mix(in srgb, var(--t-ok) 45%, transparent); }
.badge.warn { color: var(--t-warn); border-color: color-mix(in srgb, var(--t-warn) 45%, transparent); }
.badge.err { color: var(--t-err); border-color: color-mix(in srgb, var(--t-err) 45%, transparent); }

/* ============================================================
   8. PAGE SURFACES
   ============================================================ */

.page { width: 100%; max-width: var(--ui-page-width); margin: 0 auto; padding: 24px clamp(16px, 3vw, 42px) 40px; }
.page.atrium { display: flex; flex-direction: column; gap: var(--t-d-4); }


.section-label {
  font-size: var(--t-fs-xs);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--t-mut);
  margin: var(--t-d-5) 0 var(--t-d-3);
}
.section-label:first-child { margin-top: 0; }

.stack { display: flex; flex-direction: column; gap: var(--t-d-3); }
.row-line { display: flex; align-items: center; gap: var(--t-d-3); flex-wrap: wrap; }
.spacer { flex: 1 1 auto; }
.grow { flex: 1 1 auto; min-width: 0; }
.hr { height: 1px; background: var(--t-line); margin: var(--t-d-4) 0; border: 0; }
.muted { color: var(--t-mut); }
.small { font-size: var(--t-fs-xs); }
.mono { font-family: var(--t-mono); }

/* ============================================================
   List row
   `.row` is the shared geometry for every clickable line in the
   product. It is deliberately FLAT, because most rows live in the
   rail and the context sidebar where a raised surface per row would
   read as noise.

   Content lists (Discover servers, DM conversations, notifications,
   friend requests, admin entries) opt into a real surface with
   `.row--surface`, so a list of results reads as a list of objects
   rather than loose text on the page background.
   ============================================================ */
.row {
  display: flex;
  align-items: center;
  gap: var(--t-d-3);
  width: 100%;
  min-height: 44px;
  padding: var(--t-d-2) var(--t-d-3);
  border-radius: var(--t-r-s);
  color: var(--t-txt2);
  text-align: left;
  border: 1px solid transparent;
  background: transparent;
  transition: background var(--t-fast) var(--t-ease), border-color var(--t-fast) var(--t-ease);
}
.row:hover { background: color-mix(in srgb, var(--t-txt) 5%, transparent); color: var(--t-txt); }
.row.active { background: color-mix(in srgb, var(--t-accent) 13%, transparent); color: var(--t-txt); }

/* Content-list surface: Discover, DMs, notifications, friends, admin. */
.row--surface {
  min-height: 56px;
  padding: var(--t-d-3) var(--t-d-4);
  gap: var(--t-d-4);
  background: var(--t-base);
  border-color: var(--t-line);
  border-radius: var(--t-r-m);
  color: var(--t-txt);
}
.row--surface:hover {
  background: var(--t-base2);
  border-color: var(--t-line-hi);
  color: var(--t-txt);
}
.row--surface.active {
  background: color-mix(in srgb, var(--t-accent) 12%, var(--t-base));
  border-color: color-mix(in srgb, var(--t-accent) 55%, var(--t-line));
  color: var(--t-txt);
}

.row--dm .dm-row__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.row--dm .dm-row__top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--t-d-2); }
.row--dm .dm-row__name { font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: var(--t-fs-m); }
.row--dm .dm-row__time { color: var(--t-mut); font-size: var(--t-fs-xs); flex: 0 0 auto; }
.row--dm .dm-row__sub { color: var(--t-mut); font-size: var(--t-fs-s); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row--dm.unread .dm-row__name { color: var(--t-accent); }

.row .row-main { flex: 1 1 auto; min-width: 0; }
.row .row-title { font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: var(--t-d-2); }
.row .row-sub { color: var(--t-mut); font-size: var(--t-fs-s); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row .row-meta { flex: 0 0 auto; color: var(--t-mut); font-size: var(--t-fs-xs); text-align: right; }

.row.home-event { cursor: pointer; }

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--t-d-2);
  text-align: center;
  padding: var(--t-d-6) var(--t-d-4);
  color: var(--t-mut);
}
.empty-state .es-icon { font-size: 2rem; opacity: var(--t-op-dim); }

/* ============================================================
   9. AVATARS
   ============================================================ */

.avatar {
  flex: 0 0 auto;
  width: var(--t-avatar-md); height: var(--t-avatar-md);
  border-radius: 50%;
  background: linear-gradient(135deg, var(--t-accent), var(--t-accent-2));
  color: var(--t-on-accent);
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--t-fs-m);
  border: 1px solid var(--t-avatar-ring);
  position: relative;
}
.avatar.sm { width: var(--t-avatar-sm); height: var(--t-avatar-sm); font-size: var(--t-fs-xs); }
.avatar.lg { width: var(--t-avatar-lg); height: var(--t-avatar-lg); font-size: 1.5rem; }
.avatar.xl { width: var(--t-avatar-xl); height: var(--t-avatar-xl); font-size: 1.75rem; }
.avatar .presence-dot { position: absolute; right: 0; bottom: 0; border: 2px solid var(--t-base); }
.avatar.has-img { background: var(--t-sur2); border-color: var(--t-line); }
.avatar-img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block; }

/* ============================================================
   10. HOME
   ============================================================ */

.home-environment {
  width: 100%;
  min-height: 60dvh;
  display: flex;
  align-items: stretch;
}
.home-stream {
  width: 100%;
  min-height: 100%;
  overflow: auto;
  padding: 24px clamp(16px, 3vw, 42px) 40px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
}
.home-event { padding: var(--t-d-4); border-radius: 18px; }
.home-event + .home-event { margin-top: 2px; }
.home-stream .empty-state { min-height: min(54dvh, 460px); }
.home-empty-actions { display: flex; gap: var(--t-d-3); flex-wrap: wrap; justify-content: center; margin-top: var(--t-d-3); }

/* ============================================================
   11. CONVERSATION
   ============================================================ */

.conversation {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 16px clamp(16px, 3vw, 42px) 0;
}
.conversation .thread {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--t-d-2);
  padding-top: var(--t-d-2);
  padding-bottom: var(--t-d-5);
  scroll-padding-bottom: var(--t-d-5);
}
.conversation .feed {
  display: flex;
  flex-direction: column;
  gap: 1px;
  max-width: 100%;
  /* Bottom-anchored feed: short conversations rest on the composer
     instead of dangling from the top with a void below. When content
     exceeds the viewport the margin collapses to zero and normal
     scrolling takes over (no unreachable content, unlike
     justify-content: flex-end). */
  margin-top: auto;
  min-height: min-content;
}

.feed-loading { padding: 32px 8px; text-align: center; color: var(--t-mut); font-size: var(--t-fs-m); }
/* Channel intro: anchors the top of the feed with identity. Always
   rendered (scrolls away with history); doubles as the empty state. */
.channel-intro { padding: 26px 10px 18px; border-bottom: 1px solid var(--t-line); margin-bottom: 10px; }
.channel-intro__mark {
  width: 52px; height: 52px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 14px;
  background: var(--t-base2);
  color: var(--t-accent);
  font-size: 1.7rem;
  font-weight: 800;
  margin-bottom: 10px;
}
.channel-intro__title { margin: 0 0 4px; font-size: var(--t-fs-xl); font-weight: 800; letter-spacing: -0.01em; }
.channel-intro__sub { margin: 0; color: var(--t-txt2); }
.channel-intro__cta { margin: 10px 0 0; color: var(--t-mut); font-size: var(--t-fs-s); }

.msg {
  display: flex;
  gap: 12px;
  padding: 8px;
  margin: 2px 0;
  border-radius: 6px;
  width: 100%;
  text-align: left;
  position: relative;
}
.msg:hover { background: color-mix(in srgb, var(--t-txt) 4%, transparent); }
.msg .msg-body { flex: 1 1 auto; min-width: 0; }
.msg .msg-head { display: flex; align-items: baseline; gap: var(--t-d-2); flex-wrap: wrap; }
/* A <button>, so it needs its chrome stripped and a real hover/focus state -
   it must not read as a link by colour alone, and it must be visibly
   focusable for keyboard users. */
.msg .msg-author {
  font-weight: 700;
  font-size: var(--t-fs-m);
  color: var(--t-txt);
  letter-spacing: 0.002em;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: 4px;
}
.msg .msg-author:hover:not(:disabled) { text-decoration: underline; }
.msg .msg-author:focus-visible { outline: 2px solid var(--t-accent); outline-offset: 2px; }
.msg .msg-author:disabled { cursor: default; }

/* A username rendered as a <button> must look exactly like the text it
   replaced, while staying focusable and hoverable. Shared by the member
   list, the message author and anywhere else a name is actionable. */
.member-name-btn,
.user-name-btn {
  font: inherit;
  font-weight: 700;
  color: var(--t-txt);
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  text-align: left;
  cursor: pointer;
  border-radius: 4px;
}
.member-name-btn:hover:not(:disabled),
.user-name-btn:hover:not(:disabled) { text-decoration: underline; }
.member-name-btn:focus-visible,
.user-name-btn:focus-visible { outline: 2px solid var(--t-accent); outline-offset: 2px; }
.member-name-btn:disabled,
.user-name-btn:disabled { cursor: default; }
.msg .msg-time { color: var(--t-mut); font-size: var(--t-fs-xs); font-weight: 500; }
/* Hover actions are absolutely positioned rather than sitting in the flex
   flow. They were `opacity: 0` but still laid out, so every message reserved
   a ~19px row for buttons nobody could see - which is most of the vertical
   gap between consecutive grouped messages. .msg is already position:relative,
   so this costs nothing and stops reserving space. */
.msg .msg-actions {
  position: absolute;
  top: 2px;
  right: 8px;
  margin-left: 0;
  opacity: 0;
  transition: opacity var(--t-fast);
  display: flex;
  gap: 2px;
  background: var(--t-base);
  border-radius: var(--t-r-s);
}
.msg:hover .msg-actions,
.msg:focus-within .msg-actions { opacity: 1; }
.msg .msg-actions button { color: var(--t-mut); font-size: var(--t-fs-xs); padding: 2px 6px; border-radius: var(--t-r-s); }
.msg .msg-actions button:hover { color: var(--t-txt); background: var(--t-base2); }
.msg .msg-actions button:focus-visible { opacity: 1; }
/* Hover toolbar: quick react + full menu without occupying layout. */
.msg-hoverbar {
  position: absolute;
  top: 2px;
  right: 8px;
  display: none;
  align-items: center;
  gap: 2px;
  padding: 3px 4px;
  border-radius: 8px;
  border: 1px solid var(--t-line-hi);
  background: var(--t-elev);
  box-shadow: var(--t-sh-1);
  z-index: 3;
}
.msg:hover .msg-hoverbar,
.msg:focus-within .msg-hoverbar { display: inline-flex; }
.msg-hoverbar button {
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px;
  color: var(--t-txt2);
  font-size: 0.95rem;
}
.msg-hoverbar button:hover { background: var(--t-base2); color: var(--t-txt); }
/* Locked composer (no permission / unverified): visible, inert, explained. */
.composer.locked { opacity: 0.75; }
.btn:disabled, .btn[disabled], button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.msg .msg-text { color: var(--t-txt2); white-space: pre-wrap; word-break: break-word; margin: 2px 0 0; font-size: 0.92rem; line-height: 1.52; }
.msg.grouped { padding-top: 2px; padding-bottom: 2px; }
/* A grouped message keeps the avatar column so its text stays aligned with the
   message above, but the avatar itself must not set the row height. The
   placeholder is padding rather than a visibility:hidden element, because a
   hidden element still occupies 28px and was the other half of the gap. */
.msg.grouped > .avatar { display: none; }
.msg.grouped { padding-left: calc(var(--t-avatar-sm) + 12px + 8px); }
.msg.grouped .msg-author,
.msg.grouped .msg-time,
.msg.grouped .msg-edited { display: none; }
.msg .msg-edited { color: var(--t-mut); font-size: var(--t-fs-xs); font-style: italic; margin-left: 4px; }
.msg .msg-mention {
  background: color-mix(in srgb, var(--t-accent) 18%, transparent);
  color: var(--t-accent);
  border-radius: 3px;
  padding: 0 3px;
}
.msg.deleted { opacity: var(--t-op-fade); }
.msg.deleted .msg-text { font-style: italic; color: var(--t-mut); }
.msg.system { color: var(--t-mut); font-size: var(--t-fs-s); justify-content: center; padding: var(--t-d-2); }


.msg-files { display: flex; flex-wrap: wrap; gap: var(--t-d-2); margin-top: var(--t-d-2); }
.msg-file {
  border: 1px solid var(--t-line);
  border-radius: var(--t-r-s);
  background: var(--t-base);
  padding: 6px var(--t-d-3);
  font-size: var(--t-fs-xs);
  color: var(--t-txt2);
  max-width: 280px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.msg-file a { color: inherit; }
.msg-file.image { border: 0; padding: 0; background: none; }
.msg-file.image img {
  display: block;
  border-radius: var(--t-r-s);
  border: 1px solid var(--t-line);
  max-width: min(100%, 480px);
  max-height: 320px;
  object-fit: contain;
  background: var(--t-img-mat);
  cursor: zoom-in;
}
.msg-file.image.is-loading {
  border: 1px dashed var(--t-line-hi);
  padding: 14px var(--t-d-4);
  max-width: 280px;
  color: var(--t-mut);
  font-style: italic;
  white-space: normal;
}

.composer {
  flex: 0 0 auto;
  width: auto;
  max-width: none;
  margin: 4px clamp(16px, 3vw, 42px) 16px;
  border: 1px solid var(--t-line-hi);
  border-radius: var(--t-r-m);
  background: color-mix(in srgb, var(--t-elev) 78%, transparent);
  backdrop-filter: blur(var(--t-blur-s)) saturate(var(--t-sat-s));
  box-shadow: var(--t-sh-3), var(--t-inset-glass);
  display: flex;
  align-items: flex-end;
  gap: var(--t-d-2);
  padding: var(--t-d-3) var(--t-d-3) var(--t-d-3) var(--t-d-2);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.composer:focus-within {
  border-color: color-mix(in srgb, var(--t-accent) 65%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--t-accent) 45%, transparent),
    var(--t-sh-3), var(--t-inset-glass);
}
.composer textarea {
  flex: 1 1 auto;
  min-height: 44px;
  max-height: 160px;
  background: transparent;
  border: 0;
  resize: none;
  padding: var(--t-d-2);
  color: var(--t-txt);
  font-size: var(--t-fs-m);
  line-height: 1.5;
  font-family: inherit;
}
.composer textarea:focus { outline: none; }
.composer .composer-actions { display: flex; align-items: center; gap: var(--t-d-2); flex: 0 0 auto; padding-bottom: 2px; }
.composer button.file-btn { color: var(--t-mut); font-size: 1.15rem; padding: 6px 8px; border-radius: var(--t-r-s); }
.composer button.file-btn:hover { color: var(--t-txt); background: var(--t-base2); }
.composer .btn.primary { border-radius: 10px; min-height: 36px; }

/* ============================================================
   12. AUTH
   ============================================================ */

.auth-wrap {
  width: min(var(--ui-auth-width), 100%);
  margin: 0 auto;
  min-height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
}
.card {
  background: var(--t-base);
  border: 1px solid var(--t-line-hi);
  border-radius: var(--t-r-l);
  box-shadow: var(--t-sh-2);
  padding: 24px;
}
.card--auth { width: min(var(--ui-auth-width), 100%); }
.card--profile { width: 100%; max-width: 860px; }
/* Card heading + action row. Shared by every card surface so a card never
   has to hand-roll a font-size or stack its own button row.
   --t-fs-l, not --t-fs-xl/-2xl: those are page-title sizes and reach ~46px
   at ultrawide, which turns a short card heading into three wrapped lines. */
.card-title { margin: 0 0 var(--t-d-2); font-size: var(--t-fs-l); line-height: 1.3; }
.card-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--t-d-2);
  margin-top: var(--t-d-4);
}
.card-actions > .btn { flex: 0 0 auto; }
/* Content-card grid for hub/support-style pages: a few equal cards that fill
   the available page width. Deliberately NOT .theme-grid, which is a
   theme-picker grid (minmax 220px) and squeezes text cards too narrow.
   The 420px ceiling matters: with only a minmax() the tracks grow to fill
   whatever width they are given, so on an ultrawide main column a short
   "Community rules" card stretched to 644px and read as mostly emptiness. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 420px));
  gap: var(--t-d-4);
  align-items: stretch;
  justify-content: start;
}
.card-grid > .card { width: 100%; display: flex; flex-direction: column; }
.card-grid > .card > .card-actions { margin-top: auto; padding-top: var(--t-d-4); }
.card--list { padding: 12px; }
.card--auth h1 { margin: 0 0 4px; font-size: var(--t-fs-2xl); letter-spacing: -0.025em; }
.card--auth .auth-sub { color: var(--t-mut); margin: 0 0 var(--t-d-5); font-size: var(--t-fs-s); }
.auth-alt { text-align: center; margin-top: var(--t-d-4); color: var(--t-mut); font-size: var(--t-fs-s); }


/* ============================================================
   12b. PUBLIC / STATIC PAGES
   ------------------------------------------------------------
   Login, signup, password recovery, Support, Appeals, Terms and
   Privacy are public-facing pages, not application views. The reference
   for how they should look is the server-served marketing site in
   public/ (site.css) - a constrained, left-aligned column with
   generous vertical rhythm on the page background.

   They are explicitly NOT "the client with the navigation hidden".
   Hiding the rail still leaves the shell's 304px of grid tracks, its
   vertical dividers and its context header, which reads as an empty
   application rather than a page of a website. So below the chrome is
   removed *and* the content is restyled onto the public-site metrics.

   Metrics mirrored from public/css/site.css:
     --content-w: 1080px   (site .wrap / .page)
     --header-h: 64px
     prose column 760px, h1 at --fs-xl, vertical padding clamp(32px,6vw,72px)
   ============================================================ */

:root {
  --pub-content-w: 1080px;
  --pub-prose-w: 760px;
  --pub-pad-y: clamp(32px, 6vw, 72px);
  --pub-pad-x: 20px;
}

/* The route list. :is() keeps this to one place - the previous version
   repeated the same five-route list on six rules, which is how the appeal
   form and legal pages were missed while looking identical in intent. */
html:is(
  [data-route="/login"],
  [data-route="/register"],
  [data-route="/forgot"],
  [data-route^="/reset-password"],
  [data-route^="/verify-email"],
  [data-route^="/legal"],
  [data-route^="/support"]
) {
  --is-public-page: 1;
}

/* No application navigation on a public page. */
html:is(
  [data-route="/login"],
  [data-route="/register"],
  [data-route="/forgot"],
  [data-route^="/reset-password"],
  [data-route^="/verify-email"],
  [data-route^="/legal"],
  [data-route^="/support"]
) .app-rail,
html:is(
  [data-route="/login"],
  [data-route="/register"],
  [data-route="/forgot"],
  [data-route^="/reset-password"],
  [data-route^="/verify-email"],
  [data-route^="/legal"],
  [data-route^="/support"]
) .context-sidebar,
html:is(
  [data-route="/login"],
  [data-route="/register"],
  [data-route="/forgot"],
  [data-route^="/reset-password"],
  [data-route^="/verify-email"],
  [data-route^="/legal"],
  [data-route^="/support"]
) .context-header,
html:is(
  [data-route="/login"],
  [data-route="/register"],
  [data-route="/forgot"],
  [data-route^="/reset-password"],
  [data-route^="/verify-email"],
  [data-route^="/legal"],
  [data-route^="/support"]
) #member-sidebar { display: none !important; }

/* Collapse the desktop shell to one column.
   Hiding the rail and sidebar is NOT enough: a display:none grid item does
   not collapse its track. The shell is still
   `var(--ui-rail) var(--ui-sidebar) minmax(0,1fr)` with .main-content
   pinned to grid-column 3, so it began 64px + 240px = 304px in from the
   left and every centred element sat ~152px right of the true viewport
   centre. `width: 100%` on .main-content cannot fix this - it fills
   column 3 rather than moving to column 1. */
html:is(
  [data-route="/login"],
  [data-route="/register"],
  [data-route="/forgot"],
  [data-route^="/reset-password"],
  [data-route^="/verify-email"],
  [data-route^="/legal"],
  [data-route^="/support"]
) .shell--desktop { grid-template-columns: minmax(0, 1fr) !important; }
html:is(
  [data-route="/login"],
  [data-route="/register"],
  [data-route="/forgot"],
  [data-route^="/reset-password"],
  [data-route^="/verify-email"],
  [data-route^="/legal"],
  [data-route^="/support"]
) .shell--desktop > .main-content {
  grid-column: 1 !important;
  width: 100% !important;
  background: var(--pg) !important;
}
html:is(
  [data-route="/login"],
  [data-route="/register"],
  [data-route="/forgot"],
  [data-route^="/reset-password"],
  [data-route^="/verify-email"],
  [data-route^="/legal"],
  [data-route^="/support"]
) .chat-environment { display: block !important; }

/* Public content sits in a constrained, top-aligned column with the
   marketing site's rhythm - not vertically centred in a void. Centring was
   the other half of the "floating form" problem: a short form pinned to the
   middle of a tall viewport reads as a mistake, whereas a real page starts
   near the top with the title leading. */
html:is(
  [data-route="/login"],
  [data-route="/register"],
  [data-route="/forgot"],
  [data-route^="/reset-password"],
  [data-route^="/verify-email"],
  [data-route^="/legal"],
  [data-route^="/support"]
) .view-root {
  display: block !important;
  align-content: normal !important;
  justify-items: normal !important;
  min-height: 100% !important;
  margin: 0 !important;
  padding: 0 !important;
  overflow-y: auto !important;
}

/* The public column. Same max-width and vertical rhythm as site.css .page. */
.pub-page {
  width: 100%;
  max-width: var(--pub-content-w);
  margin: 0 auto;
  padding: var(--pub-pad-y) var(--pub-pad-x) clamp(40px, 6vw, 80px);
}
.pub-page--narrow { max-width: calc(var(--pub-prose-w) + 2 * var(--pub-pad-x)); }

/* Left-aligned page title at the site's display scale, not an auth-card
   heading. */
.pub-title {
  margin: 0 0 8px;
  font-size: clamp(1.9rem, 4vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--t-txt);
}
.pub-lede {
  margin: 0 0 var(--t-d-5);
  color: var(--t-txt2);
  font-size: var(--t-fs-l);
  line-height: 1.5;
}
.pub-section {
  margin-top: clamp(40px, 6vw, 64px);
  padding-top: 20px;
  border-top: 1px solid var(--t-line);
}
.pub-section:first-of-type { border-top: 0; padding-top: 0; margin-top: var(--t-d-5); }
.pub-section__title { margin: 0 0 10px; font-size: var(--t-fs-l); color: var(--t-txt); }
.pub-prose { max-width: var(--pub-prose-w); }
.pub-prose p, .pub-prose li { color: var(--t-txt2); }
.pub-prose h2 { font-size: var(--t-fs-l); margin: 40px 0 10px; padding-top: 20px; border-top: 1px solid var(--t-line); }
.pub-prose h3 { font-size: var(--t-fs-m); margin: 24px 0 6px; color: var(--t-txt); }
.pub-prose ul, .pub-prose ol { padding-left: 22px; }

/* Link groups (Support, legal index) use the site's flat bordered rows
   rather than app cards, so the page reads as a page. */
.pub-links { display: grid; gap: 12px; margin-top: var(--t-d-4); }
.pub-link {
  display: block;
  padding: 18px 20px;
  border: 1px solid var(--t-line-hi);
  border-radius: var(--t-r-m);
  background: var(--t-base);
  color: var(--t-txt);
  text-decoration: none;
}
.pub-link:hover { border-color: var(--t-accent); text-decoration: none; }
.pub-link__title { font-weight: 600; margin-bottom: 4px; }
.pub-link__desc { color: var(--t-txt2); font-size: var(--t-fs-s); }

@media (max-width: 760px) {
  .pub-page { padding-top: 28px; }
  .pub-title { font-size: 1.9rem; }
  .pub-lede { font-size: var(--t-fs-m); }
}

/* ============================================================
   12c. DEDICATED AUTH PAGES
   ------------------------------------------------------------
   Login, signup, recovery, reset and verification share one shell:
   the supplied background image baked in behind a centred card with
   an optional side panel.

   This is a fixed full-viewport surface rather than a normal view
   region child on purpose. These routes render inside the app shell,
   and every "just hide the chrome" approach still leaves the shell's
   grid tracks behind - the card ends up ~152px off centre on a wide
   window, and any shell element that paints above the overlay shows
   through. Taking the viewport outright is what makes it a dedicated
   auth page instead of a themed app screen.
   ============================================================ */

.auth-page {
  position: fixed;
  inset: 0;
  z-index: 70;                 /* above rail/sidebar (60) and popovers (55) */
  overflow-y: auto;
  overscroll-behavior: contain;
  background: #16151a;         /* charcoal base, matches the image's own tone */
  color: var(--t-txt);
}
.auth-background {
  position: fixed;
  inset: 0;
  /* The real asset from the repo root, copied to trycord-client/assets/.
     Not a gradient or generated artwork - it is the supplied image. */
  background-image: url('/assets/trycord-login-bg.png');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  /* Keep a touch of the image legible under text without hiding it. */
  box-shadow: inset 0 0 0 100vmax rgba(18, 17, 21, 0.62);
}
.auth-page__inner {
  position: relative;
  min-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  padding: clamp(20px, 5vh, 48px) 20px;
}

.auth-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--t-txt);
}
.auth-brand:hover { text-decoration: none; }
.auth-brand__mark { width: 38px; height: 38px; border-radius: 10px; object-fit: cover; }
.auth-brand__word { font-size: 1.35rem; font-weight: 800; letter-spacing: -0.02em; }

.auth-card {
  width: min(880px, 100%);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  background: var(--t-base);
  border: 1px solid var(--t-line-hi);
  border-radius: var(--t-r-l);
  box-shadow: var(--t-sh-2);
  overflow: hidden;
}
/* Two-panel only when there is actually a side panel to show. */
.auth-card:has(> .auth-secondary) { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); }

.auth-main { padding: clamp(22px, 3.4vw, 34px); min-width: 0; }
.auth-title {
  margin: 0 0 6px;
  font-size: clamp(1.5rem, 2.4vw, 1.85rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
}
.auth-lede { margin: 0 0 var(--t-d-5); color: var(--t-txt2); font-size: var(--t-fs-s); line-height: 1.55; }
.auth-form { display: flex; flex-direction: column; gap: var(--t-d-4); }

.auth-secondary {
  padding: clamp(22px, 3.4vw, 34px);
  min-width: 0;
  background: var(--t-base2);
  border-left: 1px solid var(--t-line-hi);
}
.auth-secondary__title { margin: 0 0 6px; font-size: 1.02rem; font-weight: 700; }
.auth-secondary__lede { margin: 0 0 var(--t-d-4); color: var(--t-txt2); font-size: var(--t-fs-xs); line-height: 1.5; }
.auth-secondary__body .section-label { margin-top: 0; }

.auth-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 6px 16px;
  margin-top: var(--t-d-5);
  padding-top: var(--t-d-4);
  border-top: 1px solid var(--t-line);
  color: var(--t-mut);
  font-size: var(--t-fs-xs);
}

/* Below the two-panel breakpoint the side panel stacks under the form
   instead of squeezing it, so the fields never get narrower than the
   card. */
@media (max-width: 760px) {
  .auth-card:has(> .auth-secondary) { grid-template-columns: minmax(0, 1fr); }
  .auth-secondary { border-left: 0; border-top: 1px solid var(--t-line-hi); }
  .auth-footer { flex-direction: column; align-items: center; text-align: center; }
  .auth-page__inner { gap: 16px; padding: 18px 14px 28px; }
}

/* Keep the auth page visible on phones. Under 600px the app swaps to the
   mobile shell and sets .shell--desktop to display:none - which also hides this
   page, because it renders inside the desktop view region. A position:fixed
   element escapes the grid but NOT an ancestor's display:none, so the sign-in
   screen would simply not exist on a phone. Show the desktop shell instead:
   the page is a fixed full-viewport overlay, so the shell's own chrome,
   columns and height are all underneath it and never seen. */
@media (max-width: 599px) {
  html[data-auth-page] .shell--mobile { display: none !important; }
  html[data-auth-page] .shell--desktop { display: grid !important; }
  /* Nothing to tap back to from a sign-in screen. */
  html[data-auth-page] .mobile-tab-navigation,
  html[data-auth-page] .mobile-header { display: none !important; }
}



.settings-nav { display: flex; gap: var(--t-d-2); flex-wrap: wrap; margin-bottom: var(--t-d-5); padding: 4px; background: var(--t-base); border: 1px solid var(--t-line); border-radius: 9px; width: max-content; max-width: 100%; }
.settings-nav .btn { border: 0; background: transparent; }
.settings-nav .btn.active { background: var(--t-accent); color: var(--t-on-accent); }
/* Two-column settings layout: sticky sidebar nav + content.
   Specificity must beat .page.atrium (0,2,0) to keep display:grid. */
.page.atrium.settings-layout { display: grid; grid-template-columns: var(--ui-sidebar) minmax(0, 1fr); gap: var(--t-d-5); align-items: start; }
.settings-layout > .settings-nav {
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  width: 100%;
  margin-bottom: 0;
  padding: 0;
  background: transparent;
  border: 0;
  position: sticky;
  top: var(--t-d-4);
}
.settings-layout > .settings-nav .btn {
  justify-content: flex-start;
  width: 100%;
  padding: 9px 12px;
  border-radius: 8px;
  color: var(--t-txt2);
  font-weight: 600;
}
.settings-layout > .settings-nav .btn:hover { background: var(--t-base2); color: var(--t-txt); }
.settings-layout > .settings-nav .btn.active { background: color-mix(in srgb, var(--t-accent) 16%, transparent); color: var(--t-txt); }
.settings-layout > .settings-nav .settings-signout { margin-top: 10px; color: var(--t-err); }
.settings-layout > .settings-nav .settings-signout:hover { background: color-mix(in srgb, var(--t-err) 12%, transparent); color: var(--t-err); }
.settings-body { min-width: 0; display: flex; flex-direction: column; gap: var(--t-d-5); }
.settings-body > .card--auth:first-child { margin-top: 0; }
/* Profile editor uses full content width — no narrow card--auth constraint. */
.settings-body .profile-editor {
  width: 100%;
  max-width: 100%;
}
.section-label.danger { color: var(--t-err); }
@media (max-width: 900px) {
  .settings-layout { grid-template-columns: 1fr; }
  .settings-layout > .settings-nav {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
    gap: 4px;
  }
  .settings-layout > .settings-nav .btn { width: auto; }
  .settings-layout > .settings-nav .settings-signout { margin-top: 0; margin-left: auto; }
}

.theme-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--t-d-3); }
.theme-chip {
  display: flex;
  align-items: center;
  gap: var(--t-d-3);
  text-align: left;
  padding: var(--t-d-3);
  border-radius: var(--t-r-m);
  border: 1px solid var(--t-line);
  background: var(--t-base2);
  color: var(--t-txt);
  cursor: pointer;
  transition: border-color var(--t-fast) var(--t-ease), background var(--t-fast) var(--t-ease);
}
.theme-chip:hover { border-color: var(--t-line-hi); }
.theme-chip.active { border-color: var(--t-accent); background: var(--t-base); box-shadow: 0 0 0 2px color-mix(in srgb, var(--t-accent) 8%, transparent); }
.theme-chip-swatch {
  flex: 0 0 44px;
  height: 30px;
  border-radius: var(--t-r-s);
  border: 1px solid var(--t-line-hi);
  background: var(--t-pg);
}
.theme-chip-swatch[data-theme="system"] { background: linear-gradient(120deg, #130b07 30%, #f6f0e7 70%); }
.theme-chip-swatch[data-theme="trycord"] { background: linear-gradient(120deg, #0d0b0a 35%, #32211a 65%, #ff914d); }
.theme-chip-swatch[data-theme="orthocord"] { background: linear-gradient(120deg, #0e0e10 35%, #28282e 65%, #6ea8ff); }
.theme-chip-swatch[data-theme="midnight"] { background: linear-gradient(120deg, #070810 35%, #1d2138 65%, #a78bfa); }
.theme-chip-swatch[data-theme="ember"] { background: linear-gradient(120deg, #130b07 35%, #391f11 65%, #ff8a1f); }
.theme-chip-swatch[data-theme="light"] { background: linear-gradient(120deg, #f6f0e7 35%, #dccfb8 65%, #c84f12); }
.theme-chip-swatch[data-theme="high-contrast"] { background: linear-gradient(120deg, #000 35%, #212126 65%, #ffb054); }
.theme-chip-swatch[data-theme="custom"] { background: linear-gradient(120deg, var(--t-base), var(--t-accent)); }
.theme-chip-label { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.theme-custom { margin-top: var(--t-d-5); max-width: 560px; display: flex; flex-direction: column; gap: var(--t-d-4); }
.theme-studio { display: flex; flex-direction: column; gap: var(--t-d-4); margin-top: var(--t-d-5); padding: var(--t-d-4); border: 1px solid var(--t-line); border-radius: var(--t-r-m); background: var(--t-base); }
.theme-studio__row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--t-d-3); }
.theme-studio__css { width: 100%; min-height: 160px; font-family: var(--t-mono); font-size: var(--t-fs-s); background: var(--t-pg); color: var(--t-txt); border: 1px solid var(--t-line-hi); border-radius: var(--t-r-s); padding: var(--t-d-3); }
.theme-studio__errors { display: flex; flex-direction: column; gap: 4px; }
.theme-studio__errors .form-error { margin-bottom: 0; }

.stat-inline { display: flex; gap: var(--t-d-4); color: var(--t-mut); font-size: var(--t-fs-s); margin-top: var(--t-d-2); }

.prof-banner { height: 72px; border-radius: var(--t-r-m) var(--t-r-m) 0 0; background: linear-gradient(135deg, var(--t-accent), var(--t-accent-2)); margin: -18px -18px 0; background-size: cover; background-position: center; }
.card--auth .prof-banner { margin: -18px -18px 0; }
.prof-banner.has-banner { background-color: var(--t-sur2); }
.prof-avatar { margin-top: -26px; margin-left: 6px; position: relative; z-index: 1; }
.prof-avatar.lg { margin-right: 12px; }
.prof-preview { display: flex; flex-direction: column; gap: 2px; }
.prof-preview-body { padding: 8px 0 4px; display: flex; flex-direction: column; gap: 2px; overflow-wrap: anywhere; }
.prof-name { font-size: 1.15rem; color: var(--t-txt); }
.prof-status { color: var(--t-mut); font-size: var(--t-fs-xs); }
.prof-bio { color: var(--t-txt2); white-space: pre-wrap; overflow-wrap: anywhere; }
.prof-presence { font-size: var(--t-fs-xs); color: var(--t-mut); }


.community-manager { width: min(var(--ui-page-width), calc(100% - 32px)); margin: 0 auto; padding: 24px 0 40px; }
.settings-form { display: flex; flex-direction: column; gap: var(--t-d-4); max-width: 720px; }
.settings-form .btn.block { width: 100%; }
.community-manager__head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 12px; padding: 18px 20px; border: 1px solid var(--t-line); border-radius: 14px; background: var(--t-base); }
.community-manager__head h1 { font-size: var(--t-fs-xl); margin: 0 0 3px; }
.community-manager__head p { margin: 0; color: var(--t-mut); }
.community-manager__toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; padding: 10px; border: 1px solid var(--t-line); border-radius: 10px; background: color-mix(in srgb, var(--t-base) 88%, transparent); }
.community-manager__toolbar .input { flex: 1; }
.community-list { display: grid; gap: 8px; }
.community-role-card,
.community-category-card {
  display: flex; align-items: center; gap: 12px;
  padding: 12px;
  border: 1px solid var(--t-line);
  border-radius: 12px;
  background: var(--t-base);
  box-shadow: var(--t-inset-glass);
  transition: border-color var(--t-fast), transform var(--t-fast), background var(--t-fast);
}
.community-role-card:hover,
.community-category-card:hover {
  border-color: var(--t-line-hi);
  background: color-mix(in srgb, var(--t-base2) 55%, var(--t-base));
  transform: translateY(-1px);
}
.card--list__info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.card--list__actions { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; }
.community-role-card__main,
.community-category-card__main { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.community-role-editor { margin-bottom: 20px; padding: 14px; border: 1px solid var(--t-line); border-radius: 12px; background: var(--t-base); }
.role-pills { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.role-pill {
  display: inline-flex; align-items: center;
  min-height: 21px; padding: 2px 7px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--t-accent) 32%, var(--t-line));
  background: color-mix(in srgb, var(--t-accent) 10%, transparent);
  color: var(--t-accent-hi);
  font-size: 0.68rem; font-weight: 750;
}
.role-pill.owner { color: var(--t-accent); border-color: color-mix(in srgb, var(--t-accent) 45%, var(--t-line)); }
.role-pill.muted-role { color: var(--t-mut); border-color: var(--t-line); background: var(--t-base2); }
/* ---- community settings hub ---------------------------------------------
   Sectioned index over the pages that already do the work. Reuses
   .settings-nav from account settings rather than introducing a second
   navigation pattern. */
.settings-body { display: flex; flex-direction: column; gap: var(--t-d-4); min-width: 0; }
.settings-panel {
  display: flex;
  flex-direction: column;
  gap: var(--t-d-3);
  padding: var(--t-d-4);
  border: 1px solid var(--t-line);
  border-radius: var(--t-r-m);
  background: var(--t-base);
}
.settings-panel--danger { border-color: color-mix(in srgb, var(--t-err) 32%, var(--t-line)); }
.settings-panel__title {
  margin: 0;
  font-size: var(--t-fs-l);
  font-weight: 800;
  letter-spacing: -0.01em;
}
.settings-panel__blurb { margin: 0; max-width: 68ch; line-height: 1.55; }
/* A second heading inside one panel should not look like a peer section. */
.settings-panel__title + .field { margin-top: 0; }
.settings-panel form.field { margin: 0; }

@media (max-width: 760px) {
  .settings-body { gap: var(--t-d-3); }
  .settings-panel { padding: var(--t-d-3); }
}

/* ---- role hierarchy ------------------------------------------------------
   The roles page is a two-column layout: the ordered role list, and the editor
   for whichever role is selected. Position is shown as an explicit rank
   because it is the property that decides what a member may manage - burying
   it in up/down arrows made the hierarchy invisible. */
.roles-page { display: flex; flex-direction: column; gap: var(--t-d-4); }
.roles-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--t-d-4); flex-wrap: wrap; }
.roles-head__text { min-width: 0; }
.roles-head .page-title { margin: 0 0 4px; }
.roles-hint {
  margin: 0;
  padding: 9px 12px;
  border: 1px solid var(--t-line);
  border-left: 3px solid var(--t-accent);
  border-radius: var(--t-r-s);
  background: var(--t-base);
  color: var(--t-txt2);
  font-size: var(--t-fs-xs);
  line-height: 1.5;
}
.roles-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--t-d-5); align-items: start; }
@media (min-width: 1000px) { .roles-grid { grid-template-columns: minmax(0, 420px) minmax(0, 1fr); } }
.roles-list-col, .roles-detail-col { min-width: 0; }

.role-hierarchy {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--t-line);
  border-radius: var(--t-r-m);
  background: var(--t-base);
  overflow: hidden;
}
.role-row {
  display: grid;
  grid-template-columns: 18px 30px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 8px;
  padding: 9px 10px;
  border-bottom: 1px solid var(--t-line);
  cursor: pointer;
  transition: background 0.12s ease;
}
.role-row:last-child { border-bottom: 0; }
.role-row:hover { background: var(--t-base2); }
.role-row:focus-visible { outline: 2px solid var(--t-accent); outline-offset: -2px; }
.role-row.is-selected { background: color-mix(in srgb, var(--t-accent) 12%, var(--t-base)); box-shadow: inset 3px 0 0 var(--t-accent); }
.role-row.is-locked { opacity: 0.62; }
.role-row.is-locked:hover { background: transparent; }
.role-row.is-dragging { opacity: 0.4; }
.role-row.is-drop-target { box-shadow: inset 0 -2px 0 var(--t-accent); background: color-mix(in srgb, var(--t-accent) 8%, var(--t-base)); }
.role-row--owner { background: var(--t-base2); cursor: default; }
.role-row--owner:hover { background: var(--t-base2); }

.role-row__handle { color: var(--t-mut); font-size: 0.9rem; line-height: 1; cursor: grab; text-align: center; user-select: none; }
.role-row__handle:active { cursor: grabbing; }
.role-row__rank { color: var(--t-mut); font-size: var(--t-fs-xs); font-variant-numeric: tabular-nums; font-weight: 700; text-align: right; }
.role-row__name { display: flex; align-items: center; gap: 6px; min-width: 0; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.role-row__name > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.role-row__meta { color: var(--t-mut); font-size: var(--t-fs-xs); white-space: nowrap; }
.role-row__lock { color: var(--t-mut); font-size: var(--t-fs-xs); text-transform: uppercase; letter-spacing: 0.04em; }

.role-badge {
  flex: 0 0 auto;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid var(--t-line-hi);
  background: var(--t-base2);
  color: var(--t-mut);
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.role-badge--self { border-color: color-mix(in srgb, var(--t-accent) 40%, var(--t-line)); color: var(--t-accent-hi); }

/* ---- role detail pane ---------------------------------------------------- */
.role-detail {
  min-height: 160px;
  padding: var(--t-d-4);
  border: 1px solid var(--t-line);
  border-radius: var(--t-r-m);
  background: var(--t-base);
}
.role-detail__empty { padding: var(--t-d-5) 0; text-align: center; }
.role-detail__form { display: flex; flex-direction: column; gap: var(--t-d-3); }
.role-detail__summary { display: flex; flex-wrap: wrap; gap: 6px; }
.role-detail__summary > span {
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--t-base2);
  border: 1px solid var(--t-line);
  color: var(--t-txt2);
  font-size: var(--t-fs-xs);
  font-weight: 600;
}
.role-members { display: flex; flex-direction: column; gap: 4px; }
.role-holder { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border: 1px solid var(--t-line); border-radius: var(--t-r-s); background: var(--t-base2); }
.role-holder__name { min-width: 0; flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }

/* ---- grouped permissions ------------------------------------------------ */
.perm-groups { display: flex; flex-direction: column; gap: var(--t-d-4); }
.perm-group { border: 1px solid var(--t-line); border-radius: var(--t-r-s); background: var(--t-base2); padding: 10px 12px; }
.perm-group__head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.perm-group__title { font-weight: 800; font-size: var(--t-fs-s); letter-spacing: 0.01em; }
.perm-group .permission-grid { margin-bottom: 0; }
.permission-item__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.permission-item__name { font-weight: 650; color: var(--t-txt); }
.permission-item__desc { color: var(--t-mut); font-size: 0.7rem; line-height: 1.35; }

/* ---- role pills + assignment -------------------------------------------- */
.role-pill--sm { min-height: 20px; }
.role-pill__remove {
  margin-left: 4px;
  padding: 0 2px;
  border: 0;
  background: transparent;
  color: inherit;
  font-size: 0.85rem;
  line-height: 1;
  cursor: pointer;
  opacity: 0.7;
}
.role-pill__remove:hover { opacity: 1; }
.role-pill__remove:disabled { cursor: progress; opacity: 0.4; }

.role-assign { display: flex; flex-direction: column; gap: var(--t-d-3); }
.role-assign__head { display: flex; flex-direction: column; gap: 2px; }
.role-assign__member strong { font-size: 1.05rem; }
.role-add-list { display: flex; flex-direction: column; gap: 3px; max-height: 260px; overflow-y: auto; }
.role-add-row { display: flex; align-items: center; gap: 8px; padding: 7px 8px; border: 1px solid var(--t-line); border-radius: var(--t-r-s); background: var(--t-base2); }
.role-add-row__name { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1 1 auto; font-weight: 600; }

.permission-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 6px; margin: 8px 0 14px; }
.permission-item { display: flex; align-items: center; gap: 7px; padding: 7px 8px; border: 1px solid var(--t-line); border-radius: 8px; color: var(--t-txt2); background: var(--t-base2); font-size: 0.76rem; }
.permission-item:hover { border-color: var(--t-line-hi); color: var(--t-txt); }

/* ---- permission override editor (inherit / allow / deny) ----------------
   A row per permission with an explicit three-way choice. A checkbox grid
   cannot express this: "not granted by any role" and "explicitly denied"
   look identical in a checkbox, and they are not the same decision. */
.perm-overrides { display: block; }
.perm-overrides__list {
  display: grid;
  gap: 6px;
  margin: 10px 0 12px;
}
.perm-override-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 9px 10px;
  border: 1px solid var(--t-line);
  border-radius: 8px;
  background: var(--t-base2);
}
.perm-override-row__label {
  flex: 1 1 220px;
  min-width: 0;
  color: var(--t-txt2);
  font-size: 0.82rem;
}
.perm-override-row__opts { display: flex; gap: 4px; flex: 0 0 auto; }
.perm-override-opt {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 9px;
  border: 1px solid var(--t-line);
  border-radius: 999px;
  font-size: 0.74rem;
  color: var(--t-mut);
  cursor: pointer;
  user-select: none;
}
.perm-override-opt:hover { border-color: var(--t-line-hi); color: var(--t-txt); }
.perm-override-opt:has(input:checked) {
  border-color: var(--t-accent);
  color: var(--t-txt);
  background: color-mix(in srgb, var(--t-accent) 12%, transparent);
}
.perm-override-opt:has(input:disabled) { opacity: 0.55; cursor: default; }
.perm-override-opt input { margin: 0; accent-color: var(--t-accent); }

/* ============================================================
   Instance announcement banner
   Sits above the context header in both shells. Restrained by
   default: `info` is a low-key strip, and only `warning`/`critical`
   earn stronger emphasis, so a routine notice never competes with
   the app for attention.
   ============================================================ */
.announce-banner {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--t-d-3);
  flex-wrap: wrap;
  padding: var(--t-d-3) var(--t-d-4);
  border-bottom: 1px solid var(--t-line);
  background: color-mix(in srgb, var(--t-elev) 80%, var(--t-base));
  color: var(--t-txt2);
  font-size: var(--t-fs-s);
  line-height: 1.45;
}
.announce-banner__text { min-width: 0; overflow-wrap: anywhere; }
.announce-banner__link {
  flex: 0 0 auto;
  font-weight: 700;
  color: var(--t-accent-hi);
  text-decoration: none;
  padding: 2px 8px;
  border: 1px solid color-mix(in srgb, var(--t-accent) 40%, transparent);
  border-radius: 999px;
}
.announce-banner__link:hover { background: color-mix(in srgb, var(--t-accent) 14%, transparent); text-decoration: none; }

.announce-banner--warning {
  background: color-mix(in srgb, var(--t-warn) 12%, var(--t-base));
  border-bottom-color: color-mix(in srgb, var(--t-warn) 38%, var(--t-line));
  color: var(--t-warn-fg);
}
.announce-banner--critical {
  background: color-mix(in srgb, var(--t-err) 16%, var(--t-base));
  border-bottom-color: color-mix(in srgb, var(--t-err) 45%, var(--t-line));
  color: var(--t-err-fg);
  font-weight: 600;
}

/* ============================================================
   Administration
   A moderation console is a dense, table-like surface, so it uses the
   full content width rather than the reading measure, and it carries
   exactly one padding system (the page's own). Rows are a fixed
   three-part grid so identity, state and actions never reflow into a
   second line.
   ============================================================ */
.page.admin {
  max-width: var(--ui-content-max, none);
  display: flex;
  flex-direction: column;
  gap: var(--t-d-4);
}
.page.admin .page-head { margin-bottom: 0; }
.page-head__main { min-width: 0; }
.page-head__main h1 {
  margin: 0;
  font-size: var(--t-fs-xl);
  font-weight: 800;
  letter-spacing: -0.01em;
}

.admin-page { display: flex; flex-direction: column; gap: var(--t-d-5); }

/* A labelled group of console content. Owns its internal rhythm so the
   page container only has to space whole blocks. */
.admin-block { display: flex; flex-direction: column; gap: var(--t-d-3); }
/* Wider rhythm between whole console sections (stats -> activity, etc). */
.admin-block--sections { gap: var(--t-d-5); }
.admin-block > .section-label:first-child { margin-top: 0; }
.admin-block > .section-label { margin-bottom: 0; }

.admin-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--t-d-3);
}
.admin-stat {
  background: var(--t-base);
  border: 1px solid var(--t-line);
  border-radius: var(--t-r-m);
  padding: var(--t-d-4);
}
.admin-stat b { display: block; font-size: var(--t-fs-xl); line-height: 1.15; color: var(--t-txt); }
.admin-stat span { color: var(--t-mut); font-size: var(--t-fs-s); }

/* One toolbar row: search grows, filters sit right. */
.admin-toolbar {
  display: flex;
  align-items: center;
  gap: var(--t-d-3);
  flex-wrap: wrap;
}
.admin-toolbar .input { flex: 1 1 240px; min-width: 0; }
/* Filters keep their natural width; only the search field grows. */
.admin-toolbar select.input,
.admin-toolbar .select { flex: 0 1 auto; width: auto; min-width: 150px; max-width: 220px; }

.admin-list { display: flex; flex-direction: column; gap: var(--t-d-2); }

/* Row = identity | state | actions. Actions never wrap to their own line. */
.card--list--row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--t-d-4);
  padding: var(--t-d-3) var(--t-d-4);
  background: var(--t-base);
  border: 1px solid var(--t-line);
  border-radius: var(--t-r-m);
}
.card--list--row:hover { background: var(--t-base2); border-color: var(--t-line-hi); }
.card--list--row > .grow { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
/* Action cluster: right-aligned, self-contained, never stretches the row. */
.card--list--row > .row-line,
.card--list__actions {
  display: flex;
  align-items: center;
  gap: var(--t-d-2);
  flex-wrap: nowrap;
  justify-content: flex-end;
  margin: 0;
}
.admin-avatar {
  width: var(--t-avatar-md);
  height: var(--t-avatar-md);
  flex: 0 0 auto;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--t-accent);
  color: var(--t-on-accent);
  font-weight: 700;
  text-transform: uppercase;
}
.admin-name { font-weight: 650; color: var(--t-txt); overflow-wrap: anywhere; }
.admin-row-state { display: flex; gap: var(--t-d-2); margin-top: 2px; }
.admin-when { white-space: nowrap; }
.admin-confirm { gap: var(--t-d-3); align-items: center; }
.admin-more { margin-top: var(--t-d-3); }

.admin-chip { display: inline-block; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; padding: 2px 8px; border-radius: 99px; background: var(--t-mut); color: var(--t-txt); }
.admin-chip.open, .admin-chip.under-review, .admin-chip.investigating { background: var(--t-warn-bg); color: var(--t-warn-fg); }
.admin-chip.resolved, .admin-chip.approved { background: color-mix(in srgb, var(--t-ok) 16%, transparent); color: var(--t-ok); }
.admin-chip.dismissed { background: rgba(128, 128, 128, 0.18); color: var(--t-mut); }
.admin-chip.denied { background: rgba(224, 106, 94, 0.18); color: var(--t-err); }
.admin-chip.banned { background: rgba(224, 106, 94, 0.18); color: var(--t-err); }
.admin-chip.suspended { background: var(--t-warn-bg); color: var(--t-warn-fg); }
.admin-chip.warning { background: var(--t-warn-bg); color: var(--t-warn-fg); }
.admin-chip.moderated { background: rgba(128, 128, 128, 0.18); color: var(--t-mut); }
.admin-tag { display: inline-block; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase; padding: 1px 7px; border-radius: 6px; background: rgba(128, 128, 128, 0.16); color: var(--t-mut); }
.admin-history { border-left: 2px solid var(--t-line); margin: 0 12px 10px 22px; padding: 4px 12px; display: flex; flex-direction: column; gap: 6px; }
.admin-history-row { display: flex; gap: 8px; align-items: flex-start; padding: 6px 8px; border: 1px solid var(--t-line); border-radius: 8px; background: rgba(0, 0, 0, 0.12); overflow-wrap: anywhere; }
.admin-history-row .grow { flex: 1 1 200px; min-width: 0; }
.admin-detail { border: 1px solid var(--t-line); border-radius: 10px; background: rgba(0, 0, 0, 0.18); margin: 0 12px 12px; padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; overflow-wrap: anywhere; }
.admin-detail-head { display: flex; gap: 8px; align-items: center; }
.admin-form { display: flex; flex-direction: column; gap: 10px; }

/* ============================================================
   14. MOBILE SHELL (independent presentation)
   ============================================================ */

.shell--mobile {
  display: flex !important;
  flex-direction: column !important;
  height: 100dvh !important;
  width: 100% !important;
  overflow: hidden !important;
  position: relative !important;
  background: var(--t-pg);
}

.mobile-header {
  flex: 0 0 auto !important;
  display: flex !important;
  align-items: center !important;
  gap: 8px !important;
  height: calc(62px + env(safe-area-inset-top)) !important;
  padding: env(safe-area-inset-top) 12px 0 !important;
  background: color-mix(in srgb, var(--t-pg) 92%, transparent);
  border-bottom: 1px solid var(--t-line);
  backdrop-filter: blur(22px) saturate(130%);
  position: relative !important;
  z-index: 30 !important;
}
.mobile-header button {
  width: 42px; height: 42px;
  min-width: 42px;
  border-radius: 13px;
  border: 1px solid var(--t-line);
  background: var(--t-base);
  color: var(--t-txt);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.1rem;
}
.mobile-header button:active { transform: scale(0.96); }
.mobile-context { flex: 1 1 auto; min-width: 0; padding: 0 4px; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.mobile-context .context-title { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-fs-l); font-weight: 800; color: var(--t-txt); }

.mobile-main {
  flex: 1 1 auto !important;
  min-height: 0 !important;
  width: 100% !important;
  padding: 0 0 calc(68px + env(safe-area-inset-bottom)) !important;
  overflow-y: auto !important;
  overflow-x: hidden !important;
  background: transparent;
  position: relative !important;
  z-index: 1 !important;
}
.mobile-main .conversation { min-height: 100%; }
.mobile-main .conversation .thread { padding: 12px 10px 10px; }
.mobile-main .msg { padding: 7px 6px; }
.mobile-main .msg.grouped .msg-body { padding-left: 0; }
.mobile-main .composer { width: calc(100% - 18px); margin: 4px auto 10px; border-radius: 13px; }
.mobile-main .page.atrium { padding: 18px 14px 32px; }

.mobile-tab-navigation {
  flex: 0 0 auto !important;
  display: flex !important;
  min-height: calc(64px + env(safe-area-inset-bottom)) !important;
  background: color-mix(in srgb, var(--t-base) 96%, transparent);
  border-top: 1px solid var(--t-line);
  backdrop-filter: blur(18px);
  padding-bottom: env(safe-area-inset-bottom);
  z-index: var(--z-header);
  position: relative !important;
}
.mobile-tab-navigation button {
  flex: 1 1 0;
  min-width: 0;
  min-height: 58px;
  padding-top: 7px;
  color: var(--t-mut);
  font-size: var(--t-fs-xs);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
}
.mobile-tab-navigation button .micon { font-size: 1.15rem; line-height: 1; }
.mobile-tab-navigation button.active {
  color: var(--t-accent);
  background: color-mix(in srgb, var(--t-accent) 8%, transparent);
}


/* Authentication stays deliberately chrome-free on mobile. */
html[data-route="/login"] .mobile-header,
html[data-route="/register"] .mobile-header,
html[data-route="/forgot"] .mobile-header,
html[data-route^="/reset-password/"] .mobile-header,
html[data-route^="/verify-email/"] .mobile-header { display: none !important; }
html[data-route="/login"] .mobile-tab-navigation,
html[data-route="/register"] .mobile-tab-navigation,
html[data-route="/forgot"] .mobile-tab-navigation,
html[data-route^="/reset-password/"] .mobile-tab-navigation,
html[data-route^="/verify-email/"] .mobile-tab-navigation { display: none !important; }

/* ============================================================
   15. RESPONSIVE
   ============================================================ */

/* Compact desktop: 900–1199px — sidebar stays docked, just narrower. */
@media (max-width: 1199px) and (min-width: 900px) {
  :root { --ui-sidebar: 216px; --ui-members: 220px; }
}
/* Narrow desktop: 760–899px — still docked, at its narrowest. Losing
   navigation entirely around 900px is a usability cliff, so the
   off-canvas threshold sits near the phone range instead. */
@media (max-width: 899px) and (min-width: 760px) {
  :root { --ui-sidebar: 196px; --ui-members: 0px; }
}

/* Tablet: 600–759px — the rail stays, the context sidebar becomes an
   overlay drawer driven by the context-header hamburger. */
@media (max-width: 759px) and (min-width: 600px) {
  :root { --ui-sidebar: 232px; --ui-members: 0px; }
  .shell--desktop {
    grid-template-columns: var(--ui-rail) minmax(0, 1fr) !important;
  }
  .main-content {
    grid-column: 2 !important;
  }
  .rail-identity,
  .context-sidebar {
    display: none !important;
  }
}

/* Mobile: <600px */
@media (max-width: 599px) {
  body { overflow: hidden !important; }
  .shell--desktop { display: none !important; }
  .shell--mobile { display: flex !important; }
  .conversation { max-width: none; padding-left: 0; padding-right: 0; }
  .msg { padding-left: var(--t-d-2); padding-right: var(--t-d-2); }
  .msg-file.image img { max-height: 240px; }
  .permission-grid { grid-template-columns: 1fr; }
  .community-manager__head { align-items: flex-start; flex-direction: column; }
  .card--list__actions { width: 100%; justify-content: flex-end; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001s !important; transition-duration: 0.001s !important; }
}

/* ============================================================
   F1/F2 community surfaces: bot identity, persisted role colors,
   member management rows, channel rows, community profile block.
   ============================================================ */

.bot-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 5px;
  background: color-mix(in srgb, var(--t-accent) 18%, transparent);
  color: var(--t-accent);
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  vertical-align: middle;
}
.member-name-line { display: flex; align-items: center; min-width: 0; }
.member-name-line strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.role-color-dot {
  display: inline-block;
  width: 9px; height: 9px;
  flex: 0 0 auto;
  border-radius: 50%;
  margin-right: 6px;
  vertical-align: baseline;
}
.role-pill-wrap { display: inline-flex; align-items: center; gap: 2px; }
.role-unassign {
  display: inline-grid;
  place-items: center;
  width: 18px; height: 18px;
  border-radius: 50%;
  color: var(--t-mut);
  font-size: 0.8rem;
  line-height: 1;
}
.role-unassign:hover { color: var(--t-err); background: color-mix(in srgb, var(--t-err) 14%, transparent); }
.community-channel-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px 7px 22px;
  border-radius: 9px;
  color: var(--t-txt2);
}
.community-channel-row:hover { background: color-mix(in srgb, var(--t-txt) 4%, transparent); }
.community-channel-row .ch-name { flex: 0 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600; }
.prof-community { margin-top: var(--t-d-4); padding-top: var(--t-d-3); border-top: 1px solid var(--t-line); display: flex; flex-direction: column; gap: 6px; }

/* ============================================================
   Checkpoint A: Discord-style community presentation.
   Layout hooks and IDs are unchanged; this is presentation only.
   ============================================================ */

/* --- Community rail: icon morph + active pill --- */
.app-rail__items .server-chip {
  transition: border-radius var(--t-fast) var(--t-ease), background var(--t-fast), border-color var(--t-fast), transform var(--t-fast);
}
.app-rail__items .server-chip:hover { border-radius: 17px; transform: translateY(-1px); }
.app-rail__items .server-chip.active { border-radius: 17px; }
.app-rail__items .server-chip:hover::after { height: 14px; }
.app-rail__items .row--nav { transition: border-radius var(--t-fast) var(--t-ease), color var(--t-fast), border-color var(--t-fast); }
.app-rail__items .row--nav:hover { border-radius: 17px; }

/* --- Channel sidebar: header hierarchy --- */
.context-sidebar .place-header {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--t-base);
  padding: 12px 10px;
  margin: -12px -10px 8px;
  border-bottom: 1px solid var(--t-line);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
}

/* --- Community landing hero --- */
.community-hero {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 22px 22px;
  margin-bottom: 6px;
  border: 1px solid var(--t-line);
  border-radius: var(--t-r-l);
  background:
    radial-gradient(420px 160px at 12% 0%, color-mix(in srgb, var(--t-accent) 12%, transparent), transparent 70%),
    var(--t-base);
  box-shadow: var(--t-sh-1);
}
.community-hero__mark {
  flex: 0 0 auto;
  width: 72px; height: 72px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 22px;
  background: linear-gradient(145deg, var(--t-accent), var(--t-accent-2));
  color: var(--t-on-accent);
  font-size: 1.9rem;
  font-weight: 800;
  box-shadow: 0 10px 28px color-mix(in srgb, var(--t-accent) 30%, transparent);
}
.community-hero__text { min-width: 0; flex: 1 1 auto; }
.community-hero__name { margin: 0 0 4px; font-size: var(--t-fs-xl); letter-spacing: -0.02em; }
.community-hero__text .muted { margin: 0 0 8px; }

/* --- Profile: full-width card instead of card--auth constraint --- */
.card--profile {
  border: 1px solid var(--t-line);
  padding: 0 26px 26px;
  overflow: hidden;
}
.card--profile .prof-banner { height: 160px; margin: 0 -26px; border-radius: 0; }
.card--profile .prof-avatar { margin-top: -34px; }
.card--profile .prof-avatar .avatar.lg { width: 76px; height: 76px; border: 3px solid var(--t-base); }
@media (min-width: 901px) {
  .community-hero { padding: 26px 28px; }
}
@media (max-width: 640px) {
  .community-hero { flex-direction: column; align-items: flex-start; padding: 18px; }
  .community-hero__mark { width: 56px; height: 56px; border-radius: 17px; font-size: 1.5rem; }
  .card--profile { padding: 0 16px 18px; }
}

/* ============================================================
   Context sidebar
   Fixed three-band vertical layout:
     ctx-head      context identity, never scrolls
     ctx-scroll    the only scrolling region
     user-controls pinned session bar
   ============================================================ */

.context-sidebar {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  background: var(--t-base);
  border-right: 1px solid var(--t-line);
}
.ctx-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--t-d-3) var(--t-d-3) var(--t-d-4);
  display: flex;
  flex-direction: column;
  gap: var(--t-d-4);
}
.ctx-empty {
  padding: var(--t-d-5) var(--t-d-3);
  color: var(--t-mut);
  font-size: var(--t-fs-s);
  text-align: center;
}
.ctx-search { width: 100%; flex: 0 0 auto; }
.ctx-actions { display: flex; flex-direction: column; gap: var(--t-d-2); }
.ctx-list { display: flex; flex-direction: column; gap: 2px; }

/* --- context header ---------------------------------------------------- */
.ctx-head {
  flex: 0 0 auto;
  border-bottom: 1px solid var(--t-line);
  background: var(--t-base);
}
.ctx-head__bar {
  display: flex;
  align-items: center;
  gap: var(--t-d-3);
  min-height: 56px;
  padding: var(--t-d-3) var(--t-d-3) var(--t-d-3) var(--t-d-4);
}
/* Communities have no stored banner, so the header uses a restrained accent
   wash keyed to the community mark instead of an empty image well. */
.ctx-head--community {
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--t-accent) 12%, var(--t-base)),
      var(--t-base) 78%);
  border-bottom-color: color-mix(in srgb, var(--t-accent) 22%, var(--t-line));
}
.ctx-head__mark { display: flex; flex: 0 0 auto; }
.community-mark {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  color: #fff;
  font-weight: 800;
  font-size: 0.95rem;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
.ctx-head__text { min-width: 0; flex: 1 1 auto; }
.ctx-head__title {
  font-size: var(--t-fs-m);
  font-weight: 800;
  color: var(--t-txt);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ctx-head__sub {
  font-size: var(--t-fs-xs);
  color: var(--t-mut);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ctx-head__action {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 7px;
  color: var(--t-txt2);
}
.ctx-head__action:hover { background: color-mix(in srgb, var(--t-txt) 8%, transparent); color: var(--t-txt); }

/* --- anchored dropdown -------------------------------------------------- */
.ctx-dropdown {
  position: absolute;
  left: var(--t-d-3);
  right: var(--t-d-3);
  top: calc(100% - 6px);
  z-index: 40;
  padding: 5px;
  border-radius: var(--t-r-m);
  background: var(--t-elev);
  border: 1px solid var(--t-line-hi);
  box-shadow: var(--t-sh-1);
}
.ctx-head { position: relative; }
.ctx-dropdown__item {
  display: flex;
  align-items: center;
  gap: var(--t-d-3);
  width: 100%;
  padding: 7px var(--t-d-3);
  border-radius: var(--t-r-s);
  text-align: left;
  font-size: var(--t-fs-s);
  color: var(--t-txt2);
}
.ctx-dropdown__item:hover { background: color-mix(in srgb, var(--t-txt) 7%, transparent); color: var(--t-txt); }
.ctx-dropdown__item.is-danger { color: var(--t-err); }
.ctx-dropdown__item.is-danger:hover { background: color-mix(in srgb, var(--t-err) 14%, transparent); color: var(--t-err); }
.ctx-dropdown__icon { width: 16px; flex: 0 0 auto; text-align: center; color: var(--t-mut); }
.ctx-dropdown__item.is-danger .ctx-dropdown__icon { color: var(--t-err); }
.ctx-dropdown__sep { height: 1px; margin: 4px 2px; background: var(--t-line); }

/* --- nav groups --------------------------------------------------------- */
.nav-group { display: flex; flex-direction: column; }
.nav-group__head {
  display: flex;
  align-items: center;
  gap: var(--t-d-2);
  min-height: 26px;
  padding: var(--t-d-2) var(--t-d-2);
  border-radius: 6px;
  color: var(--t-mut);
  font-size: var(--t-fs-xs);
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  user-select: none;
}
.nav-group--collapsible .nav-group__head { cursor: pointer; }
.nav-group--collapsible .nav-group__head:hover { color: var(--t-txt2); background: color-mix(in srgb, var(--t-txt) 5%, transparent); }
.nav-group__caret { font-size: 0.7rem; transition: transform var(--t-fast) var(--t-ease); }
.nav-group.is-collapsed .nav-group__caret { transform: rotate(-90deg); }
.nav-group__label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-group__list { display: flex; flex-direction: column; gap: 1px; }
.nav-group.is-collapsed .nav-group__list { display: none; }
.nav-group__action {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
  color: var(--t-mut);
  font-size: 0.95rem;
  line-height: 1;
}
.nav-group__action:hover { background: var(--t-base2); color: var(--t-txt); }

/* --- sidebar nav rows ---------------------------------------------------- */
.row--nav {
  min-height: 34px;
  padding: 5px var(--t-d-2);
  border-radius: 6px;
  color: var(--t-txt2);
  font-size: var(--t-fs-s);
  gap: var(--t-d-3);
}
.row--nav:hover { background: color-mix(in srgb, var(--t-txt) 6%, transparent); color: var(--t-txt); }
.row--nav.active {
  color: var(--t-txt);
  background: color-mix(in srgb, var(--t-accent) 14%, transparent);
  box-shadow: inset 2px 0 0 var(--t-accent);
}
.row--nav .nv-icon { display: none; }
.row--nav .nv-label { font-weight: 600; }

/* --- channel rows -------------------------------------------------------- */
.row--channel { min-height: 34px; padding: 5px var(--t-d-2); border-radius: 6px; color: var(--t-mut); font-size: var(--t-fs-s); }
.row--channel:hover { background: color-mix(in srgb, var(--t-txt) 6%, transparent); color: var(--t-txt2); }
.row--channel.active {
  color: var(--t-txt);
  background: color-mix(in srgb, var(--t-accent) 14%, transparent);
  box-shadow: inset 2px 0 0 var(--t-accent);
}
.row--channel.muted .ch-name { opacity: 0.55; }
.row--channel.muted::after { content: "🔇"; font-size: 0.7rem; }

/* --- DM rows ------------------------------------------------------------- */
.row--dm { min-height: 44px; padding: 6px var(--t-d-2); border-radius: 8px; }
.row--dm .row__stack { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.row--dm .row__line { display: flex; align-items: baseline; gap: var(--t-d-2); }
.row--dm .row__title {
  flex: 1 1 auto; min-width: 0; font-size: var(--t-fs-s); font-weight: 650;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--t-txt);
}
.row--dm .row__time { flex: 0 0 auto; font-size: var(--t-fs-xs); color: var(--t-mut); }
.row--dm .row__sub {
  font-size: var(--t-fs-xs); color: var(--t-mut);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.row--dm.is-unread .row__title { font-weight: 800; }
.row--dm.is-unread .row__title::before {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  margin-right: 6px;
  border-radius: 50%;
  background: var(--t-accent);
  vertical-align: middle;
}
.row__count {
  flex: 0 0 auto;
  min-width: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--t-accent);
  color: var(--t-on-accent);
  font-size: 0.62rem;
  font-weight: 800;
  text-align: center;
}
