@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/Geist-latin.woff2) format('woff2');
}

/* Inter stays for the Claude theme only — every other theme reads Geist. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(fonts/Inter-latin.woff2) format('woff2');
}

/* Braille patterns (U+2800-28FF) — generated squares-on-a-grid glyphs
   (scripts/gen-braille-font.py), metrics matched to JetBrains Mono. The
   bundled webfonts are LATIN SUBSETS, so without this the CLI's braille
   art rendered as tofu in the terminal. unicode-range scopes it so it
   never touches anything but braille. */
@font-face {
  font-family: 'Glyphh Braille';
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url(fonts/GlyphhBraille.ttf) format('truetype');
  unicode-range: U+2800-28FF;
}

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(fonts/JetBrainsMono-latin.woff2) format('woff2');
}

/* ── Glyphh brand assets ───────────────────────────────────
   Full logo (character + wordmark) swaps by theme: black on light,
   white on dark. Implemented as two stacked <img> tags; CSS shows the
   one that reads on the active background. The character mark is a black
   creature on transparent — inverted on dark surfaces so it stays visible. */
.glyphh-logo {
  display: block;
  width: auto;
  height: auto;
  -webkit-user-drag: none;
  user-select: none;
}
/* glyphh-logo-black = dark backgrounds, glyphh-logo-white = light. EVERY
   dark-scheme theme swaps — not just "dark" (Modern Dark, GitHub, ChatGPT,
   Gemini, Dracula, Nord, Synthwave, Matrix, Purple/Aurora are all dark).
   "highvis" is the retired id of today's Dark — kept so a saved pref still
   resolves; Light keeps the logo the old light theme wore. */
.glyphh-logo--black { display: none; }
.glyphh-logo--white { display: block; }
html:is([data-theme="dark"], [data-theme="highvis"], [data-theme="modern-dark"], [data-theme="purple"],
  [data-theme="aurora"], [data-theme="github"], [data-theme="chatgpt"], [data-theme="gemini"],
  [data-theme="dracula"], [data-theme="nord"], [data-theme="synthwave"], [data-theme="matrix"]) .glyphh-logo--white { display: none; }
html:is([data-theme="dark"], [data-theme="highvis"], [data-theme="modern-dark"], [data-theme="purple"],
  [data-theme="aurora"], [data-theme="github"], [data-theme="chatgpt"], [data-theme="gemini"],
  [data-theme="dracula"], [data-theme="nord"], [data-theme="synthwave"], [data-theme="matrix"]) .glyphh-logo--black { display: block; }

.glyphh-mark {
  display: block;
  width: auto;
  height: auto;
  -webkit-user-drag: none;
  user-select: none;
}

/* ════════════════════════════════════════════════════════════════════════
   THE BASE (his order, 2026-09-22): the site, the app and the server console
   share one visual system — Geist + JetBrains Mono, and the High Vis palette
   as BOTH the default dark and the default light. The palettes that used to
   answer to "dark" and "light" are still here as Modern Dark / Modern Light.
   ════════════════════════════════════════════════════════════════════════ */
:root {
  --font-sans: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Courier New', monospace;
  /* --bg-2 is used across the app (streamed panels, skill explorer, attach
     rows) but was never DEFINED by any theme, so every use computed to
     transparent — which is how the Browser panel went white: the streamed
     panel's var(--bg-2) backing vanished and the holder's #fff showed
     through. One alias here serves every theme (var() resolves against the
     active theme's --surface-2 at use time). */
  --bg-2:        var(--surface-2);
}

/* ── Light — High Vis on a white ground. Black text, gray hairlines that
   step DARKER (the mirror of the dark theme's stepping lighter), the brand
   purple deepened to #8c3bf2 so it holds contrast on white. ─────────────── */
:root,
[data-theme="light"] {
  color-scheme: light;
  --mark-invert: 0;
  --bg: #ffffff; --bg-raised: #ffffff; --surface: #f7f7f7; --surface-2: #efefef; --surface-3: #e6e6e6;
  /* var() resolves at use time, so a theme that declares no --sidebar gets
     ITS OWN ground for the rail (before this, :root's white leaked into every
     dark theme that skipped the token). */
  --sidebar: var(--bg); --sidebar-border: var(--border);
  --border: #8a8a8a; --border-2: #6a6a6a; --border-3: #4a4a4a;
  --text: #000000; --text-bright: #000000; --text-2: #1a1a1a; --text-3: #333333; --text-muted: #4d4d4d; --text-faint: #6f6f6f;
  --white: #000000; --hover: #ececec; --active-bg: rgba(140, 59, 242, 0.14);
  --accent: #8c3bf2; --accent-hover: #7a2fe0; --accent-fg: #fff; --accent-text: #7a2fe0; --accent-dark: #6a22cc; --accent-bg: #f1e8ff;
  --danger: #d40000; --danger-soft: #e53535; --danger-bg: #ffe8e8; --warning: #c96a00; --success: #00873f; --blue: #0070d1; --purple: #8c3bf2;
  --overlay-bg: rgba(0, 0, 0, 0.45); --shadow: rgba(0, 0, 0, 0.20); --selection: rgba(140, 59, 242, 0.25);
  --scrollbar: #8a8a8a; --scrollbar-hover: #8c3bf2; --toast-bg: #ffffff; --code-inline: #7a2fe0;
  --input-bg: #ffffff; --card-bg: var(--surface); --grad-accent: linear-gradient(120deg, #8c3bf2, #af5fff);
}

/* ── Dark — High Vis: black, gray hairlines, white text, purple accent.
   "highvis" is this theme's retired id (renamed 2026-09-22); the alias keeps
   a saved pref painting the right palette on the very first frame. ─────── */
[data-theme="dark"], [data-theme="highvis"] {
  color-scheme: dark;
  --mark-invert: 1;   /* a black-on-transparent mark (GitHub) flips in dark */
  --bg: #000000; --bg-raised: #0a0a0a; --surface: #0d0d0d; --surface-2: #141414; --surface-3: #1a1a1a;
  --sidebar: #000000; --sidebar-border: #5a5a5a;
  --border: #5a5a5a; --border-2: #7a7a7a; --border-3: #9a9a9a;
  --text: #ffffff; --text-bright: #ffffff; --text-2: #eaeaea; --text-3: #c8c8c8; --text-muted: #b0b0b0; --text-faint: #909090;
  --white: #ffffff; --hover: #1f1f1f; --active-bg: rgba(176, 102, 255, 0.20);
  --accent: #b066ff; --accent-hover: #c68cff; --accent-fg: #fff; --accent-text: #c68cff; --accent-dark: #af5fff; --accent-bg: #221133;
  --danger: #ff2b2b; --danger-soft: #ff5555; --danger-bg: #2a0000; --warning: #ff9500; --success: #00e676; --blue: #00b0ff; --purple: #d500f9;
  --overlay-bg: rgba(0, 0, 0, 0.8); --shadow: rgba(0, 0, 0, 0.7); --selection: rgba(176, 102, 255, 0.35);
  --scrollbar: #5a5a5a; --scrollbar-hover: #b066ff; --toast-bg: #0d0d0d; --code-inline: #c68cff;
  --input-bg: #0d0d0d; --card-bg: var(--surface-2); --grad-accent: linear-gradient(120deg, #b066ff, #af5fff);
}

/* ── Modern Light — the light theme as it was before 2026-09-22: the server
   console's neutrals, verbatim (his order, 2026-09-18). ────────────────── */
[data-theme="modern-light"] {
  color-scheme: light;
  --mark-invert: 0;
  /* THE CONSOLE'S NEUTRALS, verbatim (his order, 2026-09-18: align the colors
     pervasively, nothing else). Every value below is a token from the server
     console's globals.css, so the rail and the pages read the same in both
     apps. --sidebar is its own ground there, which is what the rail takes. */
  --bg:          oklch(1 0 0);
  --bg-raised:   oklch(1 0 0);
  --surface:     oklch(1 0 0);
  --surface-2:   oklch(0.967 0.003 264.542);
  --surface-3:   oklch(0.967 0.003 264.542);
  --sidebar:     oklch(1 0 0);
  --sidebar-border: oklch(0.928 0.006 264.531);
  --border:      oklch(0.928 0.006 264.531);
  --border-2:    oklch(0.872 0.006 264.531);
  --border-3:    oklch(0.808 0.006 264.531);
  --text:        oklch(0.13 0.028 261.692);
  --text-bright: oklch(0.13 0.028 261.692);
  --text-2:      oklch(0.446 0.027 264.364);
  --text-3:      oklch(0.551 0.027 264.364);
  --text-muted:  oklch(0.551 0.027 264.364);
  --text-faint:  oklch(0.707 0.022 261.325);
  --white:       oklch(0.13 0.028 261.692);
  --hover:       oklch(0.967 0.003 264.542);
  --active-bg:   rgba(33, 41, 57, 0.06);
  /* The console's --primary / --primary-foreground, verbatim. Neutral wins and
     the app adopts it (his ruling, 2026-09-18); the other themes keep their
     own accents, only this base default moves. */
  --accent:      oklch(0.21 0.034 264.665);
  --accent-fg:   oklch(0.985 0.002 247.839);
  --accent-hover:oklch(0.28 0.034 264.665);
  --accent-text: oklch(0.21 0.034 264.665);
  --accent-dark: oklch(0.16 0.034 264.665);
  --accent-bg:   oklch(0.967 0.003 264.542);
  --danger:      #ef4444;
  --danger-soft: #f87171;
  --danger-bg:   #fef2f2;
  --warning:     #f59e0b;
  --success:     #16a34a;
  --blue:        #3b82f6;
  --purple:      #af5fff;
  --overlay-bg:  rgba(0, 0, 0, 0.3);
  --shadow:      rgba(0, 0, 0, 0.12);
  --selection:   rgba(33, 41, 57, 0.16);
  --scrollbar:   #d4d4d4;
  --scrollbar-hover: #9ca3af;
  --toast-bg:    #ffffff;
  --code-inline: #9333ea;
  --input-bg:    var(--surface-2);
  --card-bg:     var(--surface);
  --grad-accent: var(--accent);
}

/* ── Modern Dark — the dark theme as it was before 2026-09-22: the console's
   dark neutrals, near-white accent. ──────────────────────────────────────── */
[data-theme="modern-dark"] {
  color-scheme: dark;
  --mark-invert: 1;   /* a black-on-transparent mark (GitHub) flips in dark */
  /* The console's dark neutrals, verbatim. --sidebar is darker than the page
     there, which is what gives the rail its own ground. */
  --bg:          oklch(0.248 0 0);
  --bg-raised:   oklch(0.286 0 0);
  --surface:     oklch(0.248 0 0);
  --surface-2:   oklch(0.286 0 0);
  --surface-3:   oklch(0.209 0 0);
  --sidebar:     oklch(0.187 0 0);
  --sidebar-border: oklch(0.187 0 0);
  --border:      oklch(0.309 0 0);
  --border-2:    oklch(0.356 0 0);
  --border-3:    oklch(0.56 0 0);
  --text:        oklch(0.964 0 0);
  --text-bright: oklch(1 0 0);
  --text-2:      oklch(0.754 0 0);
  --text-3:      oklch(0.754 0 0);
  --text-muted:  oklch(0.65 0 0);
  --text-faint:  oklch(0.65 0 0);
  --white:       oklch(1 0 0);
  --hover:       oklch(0.309 0 0);
  --active-bg:   rgba(255, 255, 255, 0.08);
  /* The console's dark --primary / --primary-foreground. */
  --accent:      oklch(0.928 0 0);
  --accent-fg:   oklch(0.209 0 0);
  --accent-hover:oklch(0.86 0 0);
  --accent-text: oklch(0.928 0 0);
  --accent-dark: oklch(0.75 0 0);
  --accent-bg:   oklch(0.309 0 0);
  --danger:      #ff7a70;
  --danger-soft:  #ff958d;
  --danger-bg:   #2a1515;
  --warning:     #f0a030;
  --success:     #28c840;
  --blue:        #4A9EFF;
  --purple:      #af5fff;
  --overlay-bg:  rgba(0, 0, 0, 0.6);
  --shadow:      rgba(0, 0, 0, 0.4);
  --selection:   rgba(255, 255, 255, 0.22);
  --scrollbar:   #333;
  --scrollbar-hover: #555;
  --toast-bg:    #1a1a2e;
  --code-inline: #e0a0ff;
  --input-bg:    var(--surface);
  --card-bg:     var(--surface-3);
}

/* ── Midnight Purple + Aurora (purple-tinted dark themes) ──── */
[data-theme="purple"], [data-theme="aurora"] {
  color-scheme: dark;
  --mark-invert: 1;   /* a black-on-transparent mark (GitHub) flips in dark */
  --bg:          #140a1f;
  --bg-raised:   #1b1029;
  --surface:     #221634;
  --surface-2:   #2c1e42;
  --surface-3:   #281a3c;
  --border:      #3a2857;
  --border-2:    #46306a;
  --border-3:    #543a7e;
  --text:        #f1ecf8;
  --text-bright: #ffffff;
  --text-2:      #c4b6da;
  --text-3:      #9485ad;
  --text-muted:  #6e6188;
  --text-faint:  #544a6a;
  --white:       #ffffff;
  --hover:       #2e2046;
  --active-bg:   rgba(173, 93, 248, 0.12);
  --accent:      #ad5df8;
  --accent-hover:#b975f9;
  --accent-fg:   #fff;
  --accent-text: #c98ffb;
  --accent-dark: #7e22ce;
  --accent-bg:   #2a1a40;
  --danger:      #ff7a70;
  --danger-soft: #ff958d;
  --danger-bg:   #2a1515;
  --warning:     #f0a030;
  --success:     #28c840;
  --blue:        #4A9EFF;
  --purple:      #ad5df8;
  --overlay-bg:  rgba(10, 4, 20, 0.6);
  --shadow:      rgba(0, 0, 0, 0.5);
  --selection:   rgba(173, 93, 248, 0.35);
  --scrollbar:   #3a2857;
  --scrollbar-hover: #543a7e;
  --toast-bg:    #1b1029;
  --code-inline: #e0a0ff;
  --input-bg:    var(--surface);
  --card-bg:     var(--surface-3);
}

/* Aurora — the whole "outside" of the app is the Neon Orchid gradient,
   anchored bottom-left, blooming to fuchsia top-right. The gradient also
   backs the top-level content wrappers (so it WRAPS the content area rather
   than being hidden behind their solid --bg); cards/panels keep their surface. */
[data-theme="aurora"] { --bg: #0a0610; }
[data-theme="aurora"] body,
[data-theme="aurora"] #home-root,
[data-theme="aurora"] #help-overlay,
[data-theme="aurora"] .yo-panel,
[data-theme="aurora"] #onboarding-overlay {
  background:
    radial-gradient(130% 120% at 0% 100%, rgba(147, 51, 234, 0.40) 0%, transparent 55%),
    radial-gradient(100% 100% at 100% 0%, rgba(236, 72, 153, 0.26) 0%, transparent 52%),
    #0a0610;
  background-attachment: fixed;
}

/* ════════════════════════════════════════════════════════════════════════
   Extra themes. Each is a COMPLETE variable set (mirrors dark/light) so every
   surface stays consistent. Gradient-wrap themes (prism/gemini/synthwave) add a
   fixed radial bloom to the top-level wrappers, like aurora.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Prism — light, modern gradient (airy violet→cyan→rose bloom) ──────── */
[data-theme="prism"] {
  color-scheme: light;
  --mark-invert: 0;
  --bg: #f4f4fb; --bg-raised: #ffffff; --surface: #ffffff; --surface-2: #f6f5fd; --surface-3: #eef0fb;
  --border: #e6e5f2; --border-2: #d6d5ea; --border-3: #c4c3e0;
  --text: #1c1b2e; --text-bright: #0d0c1a; --text-2: #4a4866; --text-3: #6f6d8c; --text-muted: #6f6d8c; --text-faint: #9c9ab8;
  --white: #0d0c1a; --hover: #eeecfb; --active-bg: rgba(109, 94, 252, 0.09);
  --accent: #6d5efc; --accent-hover: #8a7dff; --accent-fg: #fff; --accent-text: #6d5efc; --accent-dark: #4b3fd6; --accent-bg: #edeafe;
  --danger: #e5484d; --danger-soft: #f16469; --danger-bg: #fdecec; --warning: #f59e0b; --success: #16a34a; --blue: #3b82f6; --purple: #6d5efc;
  --overlay-bg: rgba(28, 27, 46, 0.28); --shadow: rgba(76, 63, 214, 0.14); --selection: rgba(109, 94, 252, 0.20);
  --scrollbar: #d6d5ea; --scrollbar-hover: #6d5efc; --toast-bg: #ffffff; --code-inline: #6d28d9;
  --input-bg: var(--surface-2); --card-bg: var(--surface); --grad-accent: linear-gradient(120deg, #6d5efc, #22d3ee 55%, #f472b6);
}
[data-theme="prism"] body, [data-theme="prism"] #home-root, [data-theme="prism"] #help-overlay,
[data-theme="prism"] .yo-panel, [data-theme="prism"] #onboarding-overlay {
  background:
    radial-gradient(120% 120% at 0% 100%, rgba(109, 94, 252, 0.16) 0%, transparent 55%),
    radial-gradient(110% 110% at 100% 0%, rgba(34, 211, 238, 0.14) 0%, transparent 52%),
    radial-gradient(120% 120% at 100% 100%, rgba(244, 114, 182, 0.12) 0%, transparent 55%),
    #f4f4fb;
  background-attachment: fixed;
}

/* ── GitHub — GitHub Dark ("dark default") ────────────────────────────── */
[data-theme="github"] {
  color-scheme: dark;
  --mark-invert: 1;   /* a black-on-transparent mark (GitHub) flips in dark */
  --bg: #0d1117; --bg-raised: #161b22; --surface: #161b22; --surface-2: #1c2128; --surface-3: #21262d;
  --border: #30363d; --border-2: #3d444d; --border-3: #4a525b;
  --text: #e6edf3; --text-bright: #ffffff; --text-2: #adbac7; --text-3: #7d8590; --text-muted: #7d8590; --text-faint: #636c76;
  --white: #ffffff; --hover: #21262d; --active-bg: rgba(47, 129, 247, 0.12);
  --accent: #2f81f7; --accent-hover: #539bf5; --accent-fg: #fff; --accent-text: #6cb6ff; --accent-dark: #1f6feb; --accent-bg: #12233d;
  --danger: #f85149; --danger-soft: #ff6a63; --danger-bg: #2a1616; --warning: #d29922; --success: #3fb950; --blue: #2f81f7; --purple: #a371f7;
  --overlay-bg: rgba(1, 4, 9, 0.7); --shadow: rgba(1, 4, 9, 0.5); --selection: rgba(47, 129, 247, 0.30);
  --scrollbar: #30363d; --scrollbar-hover: #4a525b; --toast-bg: #161b22; --code-inline: #79c0ff;
  --input-bg: #0d1117; --card-bg: var(--surface-2); --grad-accent: linear-gradient(120deg, #2f81f7, #a371f7);
}

/* ── Claude — Anthropic warm cream + clay ─────────────────────────────── */
[data-theme="claude"] {
  color-scheme: light;
  --mark-invert: 0;
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --bg: #f0eee6; --bg-raised: #faf9f5; --surface: #ffffff; --surface-2: #f5f4ee; --surface-3: #eeece3;
  --border: #e3e1d6; --border-2: #d4d1c3; --border-3: #c2beac;
  --text: #3d3d3a; --text-bright: #1f1e1c; --text-2: #605d55; --text-3: #837f74; --text-muted: #837f74; --text-faint: #a8a496;
  --white: #1f1e1c; --hover: #eae8de; --active-bg: rgba(217, 119, 87, 0.10);
  --accent: #d97757; --accent-hover: #c96442; --accent-fg: #fff; --accent-text: #bd5d3a; --accent-dark: #a54e30; --accent-bg: #f7e9e2;
  --danger: #bf4d43; --danger-soft: #d46a60; --danger-bg: #f7e6e4; --warning: #cc8500; --success: #6a8f4e; --blue: #4b7fb5; --purple: #9b7bc4;
  --overlay-bg: rgba(61, 61, 58, 0.30); --shadow: rgba(61, 61, 58, 0.14); --selection: rgba(217, 119, 87, 0.22);
  --scrollbar: #d4d1c3; --scrollbar-hover: #d97757; --toast-bg: #ffffff; --code-inline: #a54e30;
  --input-bg: var(--surface-2); --card-bg: var(--surface); --grad-accent: linear-gradient(120deg, #d97757, #e0a06f);
}

/* ── ChatGPT — near-black + signal teal ───────────────────────────────── */
[data-theme="chatgpt"] {
  color-scheme: dark;
  --mark-invert: 1;   /* a black-on-transparent mark (GitHub) flips in dark */
  --bg: #212121; --bg-raised: #2a2a2a; --surface: #2f2f2f; --surface-2: #343434; --surface-3: #303030;
  --border: #424242; --border-2: #4d4d4d; --border-3: #5c5c5c;
  --text: #ececec; --text-bright: #ffffff; --text-2: #c5c5c5; --text-3: #9a9a9a; --text-muted: #8e8e8e; --text-faint: #6e6e6e;
  --white: #ffffff; --hover: #383838; --active-bg: rgba(16, 163, 127, 0.14);
  --accent: #10a37f; --accent-hover: #1ab896; --accent-fg: #fff; --accent-text: #2bd4ae; --accent-dark: #0d8268; --accent-bg: #10261f;
  --danger: #ef4146; --danger-soft: #f56b6f; --danger-bg: #2a1414; --warning: #e0a800; --success: #10a37f; --blue: #4a9eff; --purple: #ab68ff;
  --overlay-bg: rgba(0, 0, 0, 0.6); --shadow: rgba(0, 0, 0, 0.45); --selection: rgba(16, 163, 127, 0.30);
  --scrollbar: #4d4d4d; --scrollbar-hover: #6e6e6e; --toast-bg: #2f2f2f; --code-inline: #2bd4ae;
  --input-bg: #2f2f2f; --card-bg: var(--surface-2); --grad-accent: linear-gradient(120deg, #10a37f, #4a9eff);
}

/* ── Gemini — Google deep-space blue→violet gradient ──────────────────── */
[data-theme="gemini"] {
  color-scheme: dark;
  --mark-invert: 1;   /* a black-on-transparent mark (GitHub) flips in dark */
  --bg: #131314; --bg-raised: #1e1f20; --surface: #1e1f20; --surface-2: #282a2c; --surface-3: #232527;
  --border: #37393b; --border-2: #444649; --border-3: #545659;
  --text: #e3e3e3; --text-bright: #ffffff; --text-2: #c4c7c5; --text-3: #9aa0a6; --text-muted: #868b90; --text-faint: #6b6f73;
  --white: #ffffff; --hover: #2d2f31; --active-bg: rgba(138, 180, 248, 0.14);
  --accent: #8ab4f8; --accent-hover: #a6c6fa; --accent-fg: #fff; --accent-text: #a6c6fa; --accent-dark: #4285f4; --accent-bg: #1a2438;
  --danger: #f28b82; --danger-soft: #f6a49d; --danger-bg: #2a1614; --warning: #fdd663; --success: #81c995; --blue: #8ab4f8; --purple: #c58af9;
  --overlay-bg: rgba(0, 0, 0, 0.65); --shadow: rgba(0, 0, 0, 0.5); --selection: rgba(138, 180, 248, 0.30);
  --scrollbar: #444649; --scrollbar-hover: #8ab4f8; --toast-bg: #1e1f20; --code-inline: #c58af9;
  --input-bg: #1e1f20; --card-bg: var(--surface-2); --grad-accent: linear-gradient(120deg, #4285f4, #a142f4 55%, #f76aa0);
}
[data-theme="gemini"] body, [data-theme="gemini"] #home-root, [data-theme="gemini"] #help-overlay,
[data-theme="gemini"] .yo-panel, [data-theme="gemini"] #onboarding-overlay {
  background:
    radial-gradient(120% 120% at 0% 100%, rgba(66, 133, 244, 0.20) 0%, transparent 55%),
    radial-gradient(110% 110% at 100% 0%, rgba(161, 66, 244, 0.16) 0%, transparent 52%),
    #131314;
  background-attachment: fixed;
}

/* ── Dracula — the classic ────────────────────────────────────────────── */
[data-theme="dracula"] {
  color-scheme: dark;
  --mark-invert: 1;   /* a black-on-transparent mark (GitHub) flips in dark */
  --bg: #282a36; --bg-raised: #2f3140; --surface: #343746; --surface-2: #3c3f51; --surface-3: #383b4c;
  --border: #44475a; --border-2: #565a72; --border-3: #6272a4;
  --text: #f8f8f2; --text-bright: #ffffff; --text-2: #d5d5e0; --text-3: #a5abcc; --text-muted: #7c82a8; --text-faint: #6272a4;
  --white: #ffffff; --hover: #3c3f51; --active-bg: rgba(189, 147, 249, 0.14);
  --accent: #bd93f9; --accent-hover: #cba9fb; --accent-fg: #fff; --accent-text: #cba9fb; --accent-dark: #9d6ef0; --accent-bg: #2f2846;
  --danger: #ff5555; --danger-soft: #ff7b7b; --danger-bg: #2c1620; --warning: #ffb86c; --success: #50fa7b; --blue: #8be9fd; --purple: #bd93f9;
  --overlay-bg: rgba(20, 21, 28, 0.6); --shadow: rgba(0, 0, 0, 0.5); --selection: rgba(189, 147, 249, 0.32);
  --scrollbar: #44475a; --scrollbar-hover: #6272a4; --toast-bg: #343746; --code-inline: #ff79c6;
  --input-bg: #21222c; --card-bg: var(--surface-2); --grad-accent: linear-gradient(120deg, #bd93f9, #ff79c6 60%, #8be9fd);
}

/* ── Nord — arctic frost ──────────────────────────────────────────────── */
[data-theme="nord"] {
  color-scheme: dark;
  --mark-invert: 1;   /* a black-on-transparent mark (GitHub) flips in dark */
  --bg: #2e3440; --bg-raised: #333b4a; --surface: #3b4252; --surface-2: #434c5e; --surface-3: #3f485a;
  --border: #4c566a; --border-2: #5b667c; --border-3: #6b7689;
  --text: #eceff4; --text-bright: #ffffff; --text-2: #d8dee9; --text-3: #a9b2c3; --text-muted: #8b95a7; --text-faint: #6b7689;
  --white: #ffffff; --hover: #434c5e; --active-bg: rgba(136, 192, 208, 0.14);
  --accent: #88c0d0; --accent-hover: #8fbcbb; --accent-fg: #fff; --accent-text: #9fd3e0; --accent-dark: #5e81ac; --accent-bg: #2b3a44;
  --danger: #bf616a; --danger-soft: #cf757e; --danger-bg: #2f2024; --warning: #ebcb8b; --success: #a3be8c; --blue: #81a1c1; --purple: #b48ead;
  --overlay-bg: rgba(20, 24, 31, 0.6); --shadow: rgba(0, 0, 0, 0.45); --selection: rgba(136, 192, 208, 0.30);
  --scrollbar: #4c566a; --scrollbar-hover: #6b7689; --toast-bg: #3b4252; --code-inline: #8fbcbb;
  --input-bg: #2e3440; --card-bg: var(--surface-2); --grad-accent: linear-gradient(120deg, #88c0d0, #81a1c1 55%, #b48ead);
}

/* ── Synthwave — retro neon on indigo (gradient wrap) ─────────────────── */
[data-theme="synthwave"] {
  color-scheme: dark;
  --mark-invert: 1;   /* a black-on-transparent mark (GitHub) flips in dark */
  --bg: #1a1030; --bg-raised: #221641; --surface: #281a4a; --surface-2: #322058; --surface-3: #2c1d50;
  --border: #45307a; --border-2: #563e92; --border-3: #6a4fae;
  --text: #f5e9ff; --text-bright: #ffffff; --text-2: #d3c0ee; --text-3: #a892cf; --text-muted: #8570ad; --text-faint: #675588;
  --white: #ffffff; --hover: #32205a; --active-bg: rgba(255, 46, 151, 0.16);
  --accent: #ff2e97; --accent-hover: #ff5cae; --accent-fg: #fff; --accent-text: #ff77bd; --accent-dark: #d61f7c; --accent-bg: #3a1436;
  --danger: #ff4d5e; --danger-soft: #ff7280; --danger-bg: #331420; --warning: #ffb347; --success: #2bf5c8; --blue: #00e5ff; --purple: #b14dff;
  --overlay-bg: rgba(10, 5, 24, 0.65); --shadow: rgba(255, 46, 151, 0.18); --selection: rgba(0, 229, 255, 0.30);
  --scrollbar: #45307a; --scrollbar-hover: #ff2e97; --toast-bg: #221641; --code-inline: #00e5ff;
  --input-bg: #221641; --card-bg: var(--surface-2); --grad-accent: linear-gradient(120deg, #ff2e97, #b14dff 50%, #00e5ff);
}
[data-theme="synthwave"] body, [data-theme="synthwave"] #home-root, [data-theme="synthwave"] #help-overlay,
[data-theme="synthwave"] .yo-panel, [data-theme="synthwave"] #onboarding-overlay {
  background:
    radial-gradient(120% 120% at 0% 100%, rgba(255, 46, 151, 0.22) 0%, transparent 55%),
    radial-gradient(110% 110% at 100% 0%, rgba(0, 229, 255, 0.16) 0%, transparent 52%),
    #1a1030;
  background-attachment: fixed;
}

/* ── Matrix — phosphor green on black ─────────────────────────────────── */
[data-theme="matrix"] {
  color-scheme: dark;
  --mark-invert: 1;   /* a black-on-transparent mark (GitHub) flips in dark */
  --font-sans: 'JetBrains Mono', 'SF Mono', ui-monospace, monospace;
  --bg: #020a02; --bg-raised: #051005; --surface: #071507; --surface-2: #0b1f0b; --surface-3: #091a09;
  --border: #14371a; --border-2: #1d4d26; --border-3: #276634;
  --text: #b9ffc4; --text-bright: #e6ffe9; --text-2: #57e06f; --text-3: #3aa64f; --text-muted: #2c8a3f; --text-faint: #206630;
  --white: #e6ffe9; --hover: #0c220f; --active-bg: rgba(0, 255, 102, 0.14);
  --accent: #00ff66; --accent-hover: #4dff92; --accent-fg: #fff; --accent-text: #4dff92; --accent-dark: #00cc52; --accent-bg: #06240f;
  --danger: #ff3b3b; --danger-soft: #ff6161; --danger-bg: #250606; --warning: #d8ff00; --success: #00ff66; --blue: #00e0c0; --purple: #6bff8a;
  --overlay-bg: rgba(0, 8, 0, 0.75); --shadow: rgba(0, 255, 102, 0.14); --selection: rgba(0, 255, 102, 0.30);
  --scrollbar: #14371a; --scrollbar-hover: #00ff66; --toast-bg: #071507; --code-inline: #4dff92;
  --input-bg: #071507; --card-bg: var(--surface-2); --grad-accent: linear-gradient(120deg, #00ff66, #00e0c0);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

button, input, select, textarea {
  font-family: var(--font-sans);
}

/* Icon buttons are BARE ICONS — no chip, no border, no default button chrome.
   Work panels (Docs/Sheets/Slides/Drive/Media/Design/Memory) build their icon
   controls with `.ws-icon-btn`; without this base they'd fall back to the
   browser's default button box. Hover just brightens the glyph — no background.
   Surfaces that intentionally want a hover chip (Echo cards/top bar) override
   this with their own more-specific rules. */
.ws-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; margin: 0; padding: 3px;
  color: var(--text-2); cursor: pointer; border-radius: 6px; line-height: 1;
  transition: color 0.12s ease, opacity 0.12s ease;
  -webkit-appearance: none; appearance: none;
}
.ws-icon-btn:hover { color: var(--text); background: none; }
.ws-icon-btn:disabled { opacity: 0.4; cursor: default; }
.ws-icon-btn svg { display: block; }

html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Kill the default translucent tap-highlight flash Chromium applies on
     click — it reads as an unwanted color flicker on buttons. */
  -webkit-tap-highlight-color: transparent;
}

body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
  overflow: hidden;
  height: 100vh;
  --content-top: 72px;  /* 38px titlebar + 34px URL bar (default: shown) */
  /* Height of the desktop draggable title bar (#shell-drag-strip) and the top
     offset every panel opens below. On the web target there is no OS window to
     drag, so this collapses to 0 (see the .glyphh-web override below) — the
     empty surface-2 strip that produced the dark band at the top disappears and
     content sits flush under the browser chrome. */
  --titlebar-h: 30px;
}

::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent); }

.hidden { display: none !important; }

/* ── Splash screen ───────────────────────────────────────── */

#splash {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.5s ease;
  overflow: hidden;
}
/* The web home hero's flowing-streams backdrop, behind the copy. */
#splash-flow { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
#splash .splash-content { position: relative; z-index: 1; }
#splash .splash-close { z-index: 2; }

/* Update overlay reuses the splash layout — shown when the user relaunches to
   apply an update (see renderer.ts onUpdateStatus "restarting"). */
#updating-overlay {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
}
#updating-overlay.hidden { display: none; }

#splash.fade-out {
  opacity: 0;
  pointer-events: none;
}

.splash-close {
  position: absolute;
  top: 16px;
  left: 16px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #ff5f57;
  border: none;
  cursor: pointer;
  font-size: 0;
  padding: 0;
  -webkit-app-region: no-drag;
  z-index: 1;
  transition: opacity 0.15s;
}
.splash-close:hover::after {
  opacity: 1;
}
.splash-close::after {
  content: "×";
  font-size: 10px;
  font-weight: 700;
  color: #4a0002;
  opacity: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  line-height: 1;
}

.splash-content {
  text-align: center;
  animation: splash-in 0.6s ease-out;
}

/* Splash background follows the theme (var(--bg)) — let the logo swap. */
.splash-logo {
  margin-bottom: 24px;
  /* inline-flex so the box hugs the logo (centered by .splash-content's
     text-align) — that lets the Beta badge anchor to the LOGO's top-right
     corner rather than the full-width container edge. */
  display: inline-flex;
  justify-content: center;
  position: relative;
}
.splash-logo .glyphh-logo { height: 140px; }
/* Beta badge — above the logo, top-right. Theme-aware: the accent pill (with a
   brand-purple fallback for the pre-theme boot frame) + white text reads on both
   light and dark splash backgrounds. */
.splash-beta {
  position: absolute;
  top: -12px;
  right: -20px;
  z-index: 3;
  padding: 4px 12px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1;
  color: #fff;
  background: var(--accent, #af5fff);
  border-radius: 999px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.28);
}

.splash-tagline {
  font-size: 18px;
  font-weight: 500;
  color: var(--text-3);
  letter-spacing: 2px;
  margin-bottom: 8px;
}



/* The triad's gradient beat ("One workspace.") — used by the first-run
   tour's tagline; EXACTLY the web hero's rhero-accent gradient. */
.intro-accent {
  background: linear-gradient(115deg, #b36bfb, #9333ea 48%, #ec4899);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.splash-status {
  font-size: 12px;
  color: var(--text-faint);
  letter-spacing: 0.5px;
  min-height: 18px;
  transition: opacity 0.3s ease;
}

.splash-status.done {
  color: var(--text);
}

.splash-update {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
}

.splash-update-label {
  font-size: 12px;
  color: var(--text);
  letter-spacing: 0.5px;
}

.splash-update-bar {
  width: 200px;
  height: 4px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
}

.splash-update-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  border-radius: 2px;
  transition: width 0.3s ease;
}

@keyframes splash-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes dot-dance {
  0%   { transform: translate(0, 0) scale(1); }
  8%   { transform: translate(0, -18px) scale(1.1); }
  16%  { transform: translate(0, 0) scale(1); }
  24%  { transform: translate(0, -10px) scale(1.05); }
  32%  { transform: translate(0, 0) scale(1); }
  40%  { transform: translate(8px, -14px) scale(0.9); }
  48%  { transform: translate(16px, 0) scale(1); }
  56%  { transform: translate(8px, -6px) scale(1.15); }
  64%  { transform: translate(0, 0) scale(1); }
  72%  { transform: translate(-4px, -20px) scale(0.85); }
  80%  { transform: translate(-2px, -8px) scale(1.1); }
  88%  { transform: translate(0, -2px) scale(1); }
  100% { transform: translate(0, 0) scale(1); }
}

/* ── Empty state (no panels) ────────────────────────────── */

.empty-state {
  position: fixed;
  top: var(--content-top);
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  transition: opacity 0.3s ease;
}
.empty-state.hidden { display: none; }

.empty-state-logo {
  display: flex;
  justify-content: center;
}
.empty-state-logo .glyphh-logo { height: 84px; }

.empty-state-hint {
  font-size: 13px;
  color: var(--text-muted);
}

.empty-state-hint kbd {
  display: inline-block;
  padding: 2px 6px;
  font-size: 11px;
  font-family: var(--font-mono);
  color: var(--text-3);
  background: var(--surface-2);
  border: 1px solid var(--border-3);
  border-radius: 4px;
}

/* ── Onboarding ─────────────────────────────────────────────
   The onboarding overlay copies the yo-platform web auth page
   (the `auth-shell` system) verbatim. To match it pixel-for-pixel
   without disturbing the rest of the app, the platform color
   variables (--accent, --white, --text, --border, etc.) are
   re-declared scoped to #onboarding-overlay using the platform's
   literal :root hex values. Everything below consumes those
   scoped vars, so the styles render identically to the website
   regardless of the app's own (possibly light) theme. */

#onboarding-overlay {
  position: fixed;
  inset: 0;
  z-index: 9500;

  /* Colors inherit the app's global theme variables (--bg, --surface, --text,
     --white, --border, --accent, --danger, …) so the login + create-account
     screens match the rest of the app exactly in both light and dark. Only
     these tokens aren't defined globally, so they stay here. */
  --radius:      10px;
  --radius-sm:   8px;
  --transition:  160ms ease;
}

/* ── The split login: auth-shell (left) | the muse (right) ─────────────────
   Ada Lovelace panel — "the Analytical Engine weaves algebraic patterns" —
   rendered as slow CSS-woven threads in the brand purple. CSS-only (no script,
   no CSP surface); hidden under 980px so the login column is always primary;
   stills itself under prefers-reduced-motion. */
#onboarding-overlay {
  display: grid;
  /* Symmetry by CONSTRUCTION: the text column is exactly the content's
     width, and ONE margin value (--auth-gap) is the left edge, the center
     gutter, and the right edge. The video fills its whole column, so the
     page reads [gap][text][gap][video][gap] — equal every time. */
  --auth-gap: clamp(48px, 6vw, 104px);
  grid-template-columns: minmax(400px, 460px) minmax(0, 1fr);
  column-gap: var(--auth-gap);
  padding: 0 var(--auth-gap);
  background: var(--bg);
}
#onboarding-overlay.hidden { display: none; }
#onboarding-overlay .auth-shell { grid-column: 1; }
.auth-muse {
  grid-column: 2;
  position: relative;
  overflow: hidden;
  /* NO fallback treatment and NO seam: the right side is the same ground as
     the login column, with the hero footage floating as a centered card.
     Footage absent/failed → just the matching background. */
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* ── Hero footage: a PADDED, CENTERED **LANDSCAPE** card (not full-bleed,
   not the old portrait sliver that read as a phone). Width-driven with a
   16:10 frame, capped so it never touches the panel edges; portrait footage
   center-crops into it via object-fit. Invisible until it has real frames;
   the probe script removes it on error. The whole panel disappears under
   980px, so mobile never letterboxes a sliver. */
.auth-muse-video {
  /* A normal FLOW child — .auth-muse is a flex centering box, so the card
     centers both axes without the absolute inset/margin:auto dance (which
     read as pinned-right once the card grew). 16:9 frame, near-full width. */
  flex: 0 0 auto;
  /* Fills its grid column — the page's shared --auth-gap IS its framing.
     3:2 frame (taller than the 16:9 footage, which center-crops via
     object-fit); height capped so it never touches top/bottom. */
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  max-height: calc(100% - 112px);
  object-fit: cover;
  border-radius: 20px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28), 0 24px 64px rgba(0, 0, 0, 0.4);
  opacity: 0;
  transition: opacity 600ms ease;
  pointer-events: none;
}
.auth-muse.has-video .auth-muse-video { opacity: 1; }
@media (max-width: 979px) {
  #onboarding-overlay { grid-template-columns: 1fr; }
  .auth-muse { display: none; }
}

#onboarding-close {
  /* FIXED to the window, not the auth-shell: the shell is the LEFT column of
     the split login, so an absolute right-edge landed mid-page. The app's
     upper-right corner is free on mac (traffic lights live top-left). */
  position: fixed;
  top: 14px;
  right: 18px;
  z-index: 2;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 24px;
  cursor: pointer;
  padding: 4px 8px;
  line-height: 1;
  transition: color 0.15s;
  -webkit-app-region: no-drag;
}
#onboarding-close:hover { color: var(--white); }

#onboarding-status { display: none; }
.onboarding-error { color: var(--danger); }
.onboarding-success { color: var(--text); }

/* ── Device-flow confirmation code (square tiles) ─────────── */

/* "Waiting for approval" — a quiet status bubble (not a dead button) with a
   pulsing dot, shown while the browser half of the device grant is pending. */
#onboarding-overlay .device-waiting {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  margin: 0.25rem auto 0;
  padding: 0.6rem 1rem;
  border-radius: 999px;
  background: var(--surface, rgba(255, 255, 255, 0.04));
  border: 1px solid var(--border, rgba(255, 255, 255, 0.08));
  color: var(--text-2, #b6b6b6);
  font-size: 0.875rem;
}
#onboarding-overlay .device-waiting-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent, #af5fff);
  animation: device-waiting-pulse 1.2s ease-in-out infinite;
}
@keyframes device-waiting-pulse {
  0%, 100% { opacity: 0.35; transform: scale(0.85); }
  50% { opacity: 1; transform: scale(1); }
}

#onboarding-overlay .device-code-wrap {
  margin-top: 1.75rem;
  text-align: center;
}
#onboarding-overlay .device-code-wrap .auth-shell-lede {
  margin-bottom: 0.75rem;
}
#onboarding-overlay .device-code-grid {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
}
#onboarding-overlay .device-code-tile {
  width: 44px;
  height: 54px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--white);
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 1.5rem;
  font-weight: 600;
  user-select: text;
}
#onboarding-overlay .device-code-sep {
  display: flex;
  align-items: center;
  color: var(--text-muted);
  font-size: 1.25rem;
}
#onboarding-overlay .device-code-wrap .auth-shell-meta {
  margin-top: 1.75rem;
}

/* The "get a new code" button clears the fallback link — this block sits
   directly under it, so the generic .auth-shell-actions top margin is too
   tight to read as a separate step. */
#onboarding-overlay .device-code-wrap + .auth-shell-actions {
  margin-top: 2.25rem;
}

/* ── auth-shell (ported from yo-platform globals.css) ──────── */

#onboarding-overlay .auth-shell {
  /* SPLIT LOGIN (2026-08-03): the shell is a grid CHILD (login column) beside
     .auth-muse — was position:absolute/inset:0 full-screen, which ignored the
     overlay's grid columns and collided with the muse. */
  position: relative;
  min-height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  display: grid;
  grid-template-rows: auto 1fr auto;
  letter-spacing: -0.005em;
}

#onboarding-overlay .auth-shell-header {
  display: flex;
  justify-content: flex-start;
  padding: 1rem 2.5rem 0;
  -webkit-app-region: drag;
}

#onboarding-overlay .auth-shell-brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  -webkit-app-region: no-drag;
}

/* Wordmark follows the theme: the global .glyphh-logo--black/--white swap
   (by data-theme) controls which one shows; we only set the size here. */
#onboarding-overlay .onboarding-wordmark .glyphh-logo { height: 56px; }

#onboarding-overlay .auth-shell-body {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(2.5rem, 5vh, 4rem) 0;
}

#onboarding-overlay .auth-shell-content {
  width: 100%;
  max-width: 460px;
}

#onboarding-overlay .auth-shell-title {
  font-family: var(--font-sans);
  /* The WEB hero's scale + finish — in the THEME'S ink, not hardcoded white:
     a light background needs a dark header. */
  font-size: clamp(2.4rem, 3.2vw, 3.1rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.08;
  color: var(--text);
  margin-bottom: 0.75rem;
  /* The headline (and its tagline, below) sit CENTERED in the login column. */
  text-align: center;
}
#onboarding-overlay .auth-shell-lede { text-align: center; }

/* The desktop-download card between the headline and the form — token-driven
   so it sits naturally on the login's fixed ground. */
#onboarding-overlay .auth-download-card {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 1.75rem;
  padding: 13px 15px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  text-decoration: none;
  color: var(--text);
  transition: border-color 0.15s ease, background 0.15s ease;
}
#onboarding-overlay .auth-download-card:hover {
  border-color: var(--accent);
  background: var(--hover);
}
/* The mark sits on an APP-ICON tile that CONTRASTS the theme: white on every
   dark theme, black on light ones — the same :is() dark-theme list the
   header logo swap uses (the one source of truth for "is this theme dark"). */
#onboarding-overlay .auth-download-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: 9px;
  background: #000;
  border: 1px solid var(--border);
}
html:is([data-theme="dark"], [data-theme="highvis"], [data-theme="modern-dark"], [data-theme="purple"],
  [data-theme="aurora"], [data-theme="github"], [data-theme="chatgpt"], [data-theme="gemini"],
  [data-theme="dracula"], [data-theme="nord"], [data-theme="synthwave"], [data-theme="matrix"]) #onboarding-overlay .auth-download-ic { background: #fff; }
#onboarding-overlay .auth-download-ic img { width: 38px; height: 38px; object-fit: contain; }
#onboarding-overlay .auth-download-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
#onboarding-overlay .auth-download-title { font-size: 16px; font-weight: 600; color: var(--white); }
#onboarding-overlay .auth-download-sub { font-size: 13.5px; color: var(--text-2); }

#onboarding-overlay .auth-shell-lede {
  font-size: 0.9375rem;
  color: var(--text-2);
  line-height: 1.55;
  margin-bottom: 2.5rem;
}

#onboarding-overlay .auth-shell-form {
  display: flex;
  flex-direction: column;
  gap: 1.125rem;
}

#onboarding-overlay .auth-shell-field {
  display: flex;
  flex-direction: column;
  gap: 0.4375rem;
}

#onboarding-overlay .auth-shell-field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}

#onboarding-overlay .auth-shell-label {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-2);
  letter-spacing: 0.01em;
}

#onboarding-overlay .auth-shell-label .auth-shell-label-aside {
  color: var(--text-3);
  font-weight: 400;
  margin-left: 0.375rem;
}

#onboarding-overlay .auth-shell-input {
  width: 100%;
  padding: 0.875rem 1rem;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--white);
  font-size: 0.9375rem;
  font-family: var(--font-sans);
  outline: none;
  transition: border-color 200ms ease, background 200ms ease;
}
#onboarding-overlay .auth-shell-input:focus {
  border-color: #fff;
  box-shadow: 0 0 0 1px #fff;
  background: transparent;
}
#onboarding-overlay .auth-shell-input.has-error {
  border-color: var(--danger);
  background: rgba(239, 68, 68, 0.05);
}
#onboarding-overlay .auth-shell-input.has-error:focus {
  border-color: var(--danger);
  background: rgba(239, 68, 68, 0.06);
}
#onboarding-overlay .auth-shell-input::placeholder { color: var(--text-muted); }
#onboarding-overlay .auth-shell-input:disabled { opacity: 0.5; cursor: not-allowed; }
#onboarding-overlay .auth-shell-input:-webkit-autofill,
#onboarding-overlay .auth-shell-input:-webkit-autofill:hover,
#onboarding-overlay .auth-shell-input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--white);
  -webkit-box-shadow: 0 0 0 1000px var(--bg) inset;
  border-color: var(--border);
  transition: background-color 5000s ease-in-out 0s;
}

#onboarding-overlay .auth-shell-field-error {
  font-size: 0.75rem;
  color: var(--danger);
  margin-top: 0.375rem;
}

#onboarding-overlay .auth-shell-error {
  font-size: 0.8125rem;
  color: var(--danger);
  margin-top: -0.25rem;
}

#onboarding-overlay .auth-shell-loading {
  font-size: 0.8125rem;
  color: var(--text-2);
}

#onboarding-overlay .auth-shell-actions {
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
  margin-top: 0.5rem;
}

#onboarding-overlay .auth-shell-meta {
  margin-top: 1.75rem;
  font-size: 0.8125rem;
  color: var(--text-3);
}
#onboarding-overlay .auth-shell-meta a {
  color: var(--text);
  text-decoration: none;
  cursor: pointer;
  border-bottom: 1px solid var(--text-3);
  transition: border-color 200ms ease, color 200ms ease;
}
#onboarding-overlay .auth-shell-meta a:hover {
  color: var(--white);
  border-bottom-color: var(--white);
}

#onboarding-overlay .auth-shell-legal {
  /* Snug under the button (was 2rem — read as detached) and centered,
     mirroring the homepage's legal-line placement. Colors are the homepage's
     exact rules already (text-3 body / text-2 links / white hover). */
  margin-top: 0.25rem;
  font-size: 0.75rem;
  color: var(--text-3);
  line-height: 1.6;
  text-align: center;
}
#onboarding-overlay .auth-shell-legal a {
  color: var(--text-2);
  text-decoration: none;
  cursor: pointer;
  transition: color 200ms ease;
}
#onboarding-overlay .auth-shell-legal a:hover { color: var(--white); }

/* Device-approval page: the title one step smaller so "Approve this sign-in"
   holds ONE line in the auth column, and the button gets air after the code
   tiles instead of cramming against them. */
#onboarding-overlay .auth-device .auth-shell-title {
  font-size: clamp(1.75rem, 2.2vw, 2.25rem);
}
#onboarding-overlay .auth-device .auth-shell-actions { margin-top: 1.75rem; }
#onboarding-overlay .auth-device .auth-shell-legal { margin-top: 1.25rem; }

/* The tagline under the hero title — brand-gradient text, centered. */
#onboarding-overlay .auth-shell-slogan {
  margin: 0 0 2rem;
  font-size: clamp(1.25rem, 1.6vw, 1.5rem);
  font-weight: 600;
  letter-spacing: -0.015em;
  text-align: center;
  /* The web's --grad-text, verbatim. */
  color: var(--text);
}

/* Web login (web-login.js) appends the legal line INSIDE .auth-shell-form,
   whose 1.125rem flex gap stacks under the button before the margin even
   applies. Counteract the gap so it sits snug (net ~0.25rem), matching the
   desktop read where legal lives outside the form. */
#onboarding-overlay .auth-shell-form .auth-shell-legal { margin-top: -0.5rem; }

#onboarding-overlay .auth-shell-footer {
  padding: 1.5rem 2.5rem;
  font-size: 0.75rem;
  color: var(--text-muted);
  text-align: center;
}

@media (max-width: 640px) {
  #onboarding-overlay .auth-shell-header { padding: 0.75rem 1.5rem 0; }
  #onboarding-overlay .auth-shell-body { padding: 2.5rem 1.5rem; }
  #onboarding-overlay .auth-shell-field-row { grid-template-columns: 1fr; }
}

/* ── Buttons (ported from yo-platform globals.css) ─────────── */

#onboarding-overlay .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: var(--font-sans);
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), opacity var(--transition);
}
#onboarding-overlay .btn:disabled { opacity: 0.5; cursor: not-allowed; }
#onboarding-overlay .btn-full { width: 100%; }
#onboarding-overlay .btn-lg {
  padding: 0.875rem 1.25rem;
  font-size: 0.9375rem;
  border-radius: 10px;
}

#onboarding-overlay .btn-primary {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: var(--accent);
  color: var(--accent-fg, #fff);
  border: none;
  transition: background-color 220ms ease, opacity var(--transition);
}
#onboarding-overlay .btn-primary::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  /* The hover shade of the same accent, wiping across as before. */
  background: var(--accent-hover);
  transform: translateX(-100%);
  transition: none;
}
#onboarding-overlay .btn-primary:hover:not(:disabled)::before,
#onboarding-overlay .btn-primary:active:not(:disabled)::before,
#onboarding-overlay .btn-primary:focus-visible:not(:disabled)::before {
  transform: translateX(0);
  transition: transform 280ms ease;
}
#onboarding-overlay .btn-primary:disabled::before {
  transform: translateX(0);
  transition: none;
}
/* The wipe is the same accent, so the label colour no longer flips. */
#onboarding-overlay .btn-primary:hover:not(:disabled),
#onboarding-overlay .btn-primary:active:not(:disabled),
#onboarding-overlay .btn-primary:focus-visible:not(:disabled),
#onboarding-overlay .btn-primary:disabled {
  color: var(--accent-fg, #fff);
}

#onboarding-overlay .btn-secondary {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-2);
  transition: border-color 200ms ease, box-shadow 200ms ease;
}
#onboarding-overlay .btn-secondary:hover:not(:disabled) {
  border-color: var(--white);
  box-shadow: 0 0 0 1px var(--white);
}

/* ── Social sign-in (WEB target only — Google GIS + divider) ─────────────────
   Ported from yo-platform globals.css so the web login (web/src/web-login.js)
   matches the marketing/auth look. Only used under __GLYPHH_WEB__; the desktop
   device-flow onboarding doesn't render these. */

#onboarding-overlay .auth-shell-divider {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  margin: 1.375rem 0;
  color: var(--text-3);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
#onboarding-overlay .auth-shell-divider::before,
#onboarding-overlay .auth-shell-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

#onboarding-overlay .auth-shell-social {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

#onboarding-overlay .btn-social {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  background: transparent;
  color: var(--white);
  border: 1px solid var(--border);
  border-radius: 10px;
  font-weight: 500;
  transition: border-color 200ms ease, background 200ms ease;
}
#onboarding-overlay .btn-social:hover:not(:disabled) {
  border-color: var(--white);
  background: rgba(255, 255, 255, 0.03);
}

/* Google button: the real GIS button (click target) sits under our own face, which
   is overlaid pointer-events:none so clicks fall through to Google's. */
#onboarding-overlay .google-btn {
  position: relative;
  width: 100%;
  height: 48px;
}
#onboarding-overlay .google-btn-gis {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  overflow: hidden;
  color-scheme: light;
  --mark-invert: 0;
}
#onboarding-overlay .btn-social.google-btn-face {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: var(--bg);
}

/* ── Code input (ported from yo-platform globals.css) ──────── */

#onboarding-overlay .code-input-grid {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
  margin: 1.5rem 0;
}

#onboarding-overlay .code-input-box {
  width: 3rem;
  height: 3.5rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--white);
  font-family: var(--font-mono);
  font-size: 1.5rem;
  font-weight: 600;
  text-align: center;
  outline: none;
  transition: border-color 0.2s;
}
#onboarding-overlay .code-input-box:focus { border-color: #fff; box-shadow: 0 0 0 1px #fff; }

/* ── Lockout gate (trial expired / account disabled) ─────────── */

/* Starts below the 38px titlebar so window controls stay clickable —
   the user must always be able to quit, even while locked out. */
#lockout-overlay {
  position: fixed;
  top: var(--titlebar-h);
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9000;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
}

#lockout-overlay.hidden { display: none !important; }

/* While the account is locked the overlay covers everything below the 38px
   titlebar, but the titlebar's own workspace chrome would otherwise stay
   visible and clickable above it. Hide it — the bare titlebar (drag region +
   window controls, so the user can still quit) is all that remains. */
body.account-locked #tab-bar,
body.account-locked #files-rail-toggle,
body.account-locked #yo-rail-toggle,
body.account-locked #titlebar-refresh,
body.account-locked #dl-btn-wrap {
  display: none !important;
}

#lockout-content {
  text-align: center;
  max-width: 400px;
  width: 100%;
  padding: 0 24px;
}

.lockout-title {
  font-size: 20px;
  font-weight: 700;
  color: var(--white);
  margin: 4px 0 10px;
}

.lockout-message {
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-2);
  margin: 0 0 24px;
}

#lockout-status {
  margin-top: 12px;
  font-size: 12px;
  min-height: 18px;
}

.lockout-link {
  margin-top: 18px;
  background: none;
  border: none;
  color: var(--text-3);
  font-size: 12px;
  cursor: pointer;
  text-decoration: underline;
  transition: color 0.15s;
}
.lockout-link:hover { color: var(--text); }

/* ── Auth buttons — ported 1:1 from the platform (yo-platform globals.css)
   so the client's login / create-account / forgot-password buttons match
   it exactly. Primary = white resting, black text, accent→pink gradient
   wipes in left→right on hover; secondary = dark surface + ring. The
   onboarding forms already emit `btn btn-primary btn-lg btn-full` markup. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  font-size: 0.8125rem;
  font-weight: 600;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), opacity var(--transition);
}
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-full { width: 100%; }
.btn-lg {
  padding: 0.875rem 1.25rem;
  font-size: 0.9375rem;
  border-radius: 10px;
}
.btn-primary {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: var(--accent);
  color: var(--accent-fg, #fff);
  border: none;
  transition: background-color 220ms ease, opacity var(--transition);
}
.btn-primary::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  /* The hover shade of the same accent, wiping across as before. */
  background: var(--accent-hover);
  transform: translateX(-100%);
  transition: none;
}
.btn-primary:hover:not(:disabled)::before,
.btn-primary:active:not(:disabled)::before,
.btn-primary:focus-visible:not(:disabled)::before {
  transform: translateX(0);
  transition: transform 280ms ease;
}
.btn-primary:disabled::before {
  transform: translateX(0);
  transition: none;
}
.btn-primary:hover:not(:disabled),
.btn-primary:active:not(:disabled),
.btn-primary:focus-visible:not(:disabled) {
  /* The gradient wipe slides under the label — white text on the accent, not
     black. */
  color: #fff;
}
.btn-secondary {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-2);
  transition: border-color 200ms ease, box-shadow 200ms ease;
}
.btn-secondary:hover:not(:disabled) {
  border-color: var(--white);
  box-shadow: 0 0 0 1px var(--white);
}
.btn-secondary.danger {
  color: var(--danger);
  border-color: var(--danger);
}
.btn-secondary.danger:hover:not(:disabled) {
  border-color: var(--danger);
  box-shadow: 0 0 0 1px var(--danger);
  background: var(--danger-bg);
}

/* Lockout shares the old onboarding wordmark + button styling. These
   rules used to be global onboarding-* classes; the onboarding overlay
   was rebuilt on the platform auth-shell, so they're scoped here to the
   lockout screen which still uses the original markup classes. */
#lockout-overlay .onboarding-title {
  display: flex;
  justify-content: center;
  margin-bottom: 8px;
}
#lockout-overlay .onboarding-title .glyphh-logo { height: 72px; }

#lockout-overlay .onboarding-fields {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

#lockout-overlay .onboarding-signin-btn {
  height: 44px;
  background: linear-gradient(135deg, var(--accent), var(--accent-dark));
  border: none;
  border-radius: 8px;
  color: #000;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s;
}
#lockout-overlay .onboarding-signin-btn:hover { opacity: 0.9; }
#lockout-overlay .onboarding-signin-btn:disabled { opacity: 0.5; cursor: default; }

#lockout-overlay .onboarding-register-btn {
  height: 40px;
  background: none;
  border: 1px solid var(--border-3);
  border-radius: 8px;
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s ease;
}
#lockout-overlay .onboarding-register-btn:hover { border-color: var(--accent); color: var(--text); }
#lockout-overlay .onboarding-register-btn:disabled { opacity: 0.5; cursor: default; }

/* ── Window controls ─────────────────────────────────────── */

#window-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  -webkit-app-region: no-drag;
}

/* Web target: OS window controls (traffic lights) are meaningless in a browser
   tab — hide them. Gated by the .glyphh-web class the web bridge sets on <html>.
   .wc covers both the titlebar (#window-controls) and the home rail (#panel-wc). */
.glyphh-web .wc,
.glyphh-web #window-controls { display: none !important; }
/* MCP is a desktop-MACHINE feature (a 127.0.0.1 server) — a browser tab has no
   machine to run it on, so the whole tab hides on web, not just the local-MCP
   section inside it. Stale deep links fall back to General (navigation.ts
   settingsSubAlias). */
/* Drips is likewise a desktop-app surface — hidden on web the same way, with
   the same stale-deep-link fallback to General (settingsSubAlias). */
.glyphh-web .settings-nav > .settings-nav-item[data-sub="drips"],
.glyphh-web .settings-panel[data-sub="drips"] { display: none !important; }
/* Account leaves the WEB rail (his rule, 2026-08-25) — it opens from the
   user popup instead; the PANEL stays (only the nav item hides), centered
   like the Dashboard. */
.glyphh-web .settings-nav > .settings-nav-item[data-sub="account"] { display: none !important; }
body.platform-shell .settings-panel[data-sub="account"] { max-width: 880px; margin: 0 auto; }
body.platform-shell .settings-panel[data-sub="oauth"] { max-width: 880px; margin: 0 auto; }
/* Voice + Appearance are desktop-app surfaces too (his rule, 2026-08-25):
   the platform themes itself from the user popup's three modes instead. */
body.platform-shell .settings-nav > .settings-nav-item[data-sub="general"],
body.platform-shell .settings-panel[data-sub="general"],
body.platform-shell .settings-nav > .settings-nav-item[data-sub="voice"],
body.platform-shell .settings-panel[data-sub="voice"],
body.platform-shell .settings-nav > .settings-nav-item[data-sub="appearance"],
body.platform-shell .settings-panel[data-sub="appearance"] { display: none !important; }
/* The user-popup theme row: three icon modes — light / dark / system. */
#platform-user-menu .menu-theme-row { display: flex; gap: 6px; padding: 6px 8px 8px; }
#platform-user-menu .menu-theme-row button {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  padding: 7px 0;
  background: none;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-3);
  cursor: pointer;
}
#platform-user-menu .menu-theme-row button:hover { background: var(--hover); color: var(--text); }
#platform-user-menu .menu-theme-row button.active { border-color: var(--accent, #af5fff); color: var(--text); }
#platform-user-menu .menu-theme-row svg { width: 15px; height: 15px; }
/* Appearance → Browser homepage drives the DESKTOP app's built-in browser
   panel; a browser tab has none. Only this group hides — the rest of the
   Browser block (address-bar toggle, the tablet "mobile app" door) stays. */
.glyphh-web #browser-home-group { display: none !important; }

/* ── Web: neutralize OS window chrome, KEEP the app header ───────────────────
   The frameless-window TITLEBAR (#titlebar — the login/splash shell's desktop
   workspace chrome in index.html) is a desktop concept: on web that page is only
   the auth screen, so its empty 38px gutter must stay hidden. But the Chat tab's
   APP HEADER (home.html: #panel-wc's brand mark + rail toggle, riding on the
   full-width #shell-drag-strip bar) IS wanted on web — we only strip the OS
   traffic-light cluster (the .wc buttons, already hidden above) and the desktop
   window-drag behaviour, never the header itself. */
.glyphh-web #titlebar { display: none !important; }
.glyphh-web #btn-close,
.glyphh-web #btn-minimize,
.glyphh-web #btn-maximize,
.glyphh-web #panel-btn-close,
.glyphh-web #panel-btn-minimize,
.glyphh-web #panel-btn-maximize { display: none !important; }
/* #panel-wc (the header chrome cluster) STAYS VISIBLE on web — only its
   traffic-light buttons (.wc) are hidden. With the lights gone, the mark no
   longer needs the cluster's left inset that made room for them: pull it flush so
   the header reads as a clean native-web bar, not an off-set desktop strip. */
/* Web wordmark header: a bigger logo with a touch of top padding so it sits
   comfortably below the window edge (traffic lights are hidden, left inset
   pulled in). */
.glyphh-web #panel-wc { padding-left: 2px; padding-top: 10px; height: auto; }
/* The web header's brand mark (home.ts restores it into the cluster on web):
   32px tall, flush left, the rail's 50px top clearance was sized for it. */
.glyphh-web #panel-wc .app-rail-mark { display: block; height: 32px; width: auto; padding-left: 10px; }
/* A browser tab has no OS window to drag — kill every drag-region claim (incl.
   the header's drag band) so the splash/login/header behave like ordinary pages.
   The empty drag GAP right of the cluster (margin-left offsets sized to clear the
   now-hidden traffic lights) is collapsed so there's no dead band in the bar. */
.glyphh-web [style*="app-region"],
.glyphh-web #titlebar,
.glyphh-web #shell-drag-strip,
.glyphh-web #shell-drag-strip .shell-drag-area,
.glyphh-web .app-rail-top,
.glyphh-web .auth-shell-header,
.glyphh-web #onboarding-close { -webkit-app-region: no-drag !important; }
/* The web login has nothing to close — the X is a DESKTOP affordance (it
   dismisses the onboarding overlay back to the app). Hidden on web. */
.glyphh-web #onboarding-close { display: none !important; }
.glyphh-web #shell-drag-strip .shell-drag-area,
.glyphh-web .app-rail-top { margin-left: 0 !important; }

/* ── Web: COLLAPSE the desktop title-bar band entirely ───────────────────────
   On the desktop, #shell-drag-strip is a full-width 38px var(--surface-2) bar
   with a bottom border — the OS window-drag surface. #help-overlay opens 38px
   below it and the #panel-wc wordmark cluster rides on top. In a browser tab
   there is no window to drag, so that bar was EMPTY except for the ~200px
   cluster on its left; the remaining full-width strip read as an unwanted dark
   band across the very top (reported repeatedly). Recoloring it was not enough —
   the 38px band must be GONE so the app sits flush under the browser chrome.

   Collapse it: --titlebar-h → 0 zeroes the strip's height and pulls every top
   offset routed through it (#help-overlay, #panel-container, #lockout-overlay,
   .files-rail, .yo-panel, #drag-overlay) up to the very top; the strip itself is
   hidden so its bottom border can't leave a 1px line. The #panel-wc wordmark /
   rail-toggle / CC cluster (fixed at top:0, its own 38px) becomes the very top
   row, and the app rail below gets a matching top pad so + New session clears
   the cluster instead of sliding under it. Desktop is untouched — --titlebar-h
   stays 38px there and the draggable strip keeps painting.

   .echo-layout-bar (the "Close layout" pill) is re-parented INTO the strip by
   code-workbench.ts and absolute-centered within it; with the strip collapsed
   on web we re-pin it fixed to the top-center of the viewport so it stays
   visible + clickable. */
.glyphh-web {
  --titlebar-h: 0px;
}
/* CRITICAL: `body { --titlebar-h: 30px }` re-declares the var, and body is a
   CLOSER ancestor than html.glyphh-web — so the drag strip + every offset inside
   body inherited 30px, NOT 0. That shadow is why the web drag bar never collapsed.
   Set it on body itself so descendants actually inherit 0 on web. */
.glyphh-web body {
  --titlebar-h: 0px !important;
}
/* Height already collapses to 0 via --titlebar-h; strip its paint (surface-2
   fill + bottom border) so no band and no 1px line remain. NOT display:none —
   code-workbench.ts re-parents .echo-layout-bar INTO this strip, and a
   display:none parent would hide that child regardless of its own position. */
.glyphh-web #shell-drag-strip {
  height: 0 !important;
  min-height: 0 !important;
  background: transparent !important;
  border: 0 !important;
  padding: 0 !important;
  overflow: visible !important;
}
/* The app itself starts at the VERY top on web — no reserved band, no var
   dependence (the exposed body background above #help-overlay was the black
   bar in the report). TOP ONLY (his report, 2026-10-04: "the space always
   stays full screen under the left rail even when it is docked"): this was
   `inset: 0 !important`, and that !important beat the inline `left:
   var(--rail-w)` help/code.ts pins on the shell — the one thing that moves the
   workspace beside the sidebar on the desktop, and follows body.rail-collapsed
   (--rail-w → 0) and the rail's drag width (--rail-w-open). The left edge is
   the rail's, on web as on the desktop. */
.glyphh-web #help-overlay { top: 0 !important; right: 0 !important; bottom: 0 !important; }
.glyphh-web #panel-container { height: 100vh !important; }
/* THE RAIL DOCKS UNDER ITS OWN HEADER ON THE WEB TOO (his report, 2026-10-04:
   the rail rendered but did not dock). The 50px here dated from a wordmark
   header the web no longer has (#panel-wc is an empty box once the window
   controls are removed), so the rail's content started 12px below its 38px
   header strip instead of against it, as it does on the desktop. The same
   --rail-top-h as the desktop, and the header's left inset — room for the
   traffic lights — collapses with them. */
.glyphh-web #app-rail { padding-top: var(--rail-top-h); }
.glyphh-web #app-rail-top,
.glyphh-web #rail-collapsed-strip { padding-left: 6px; }
.glyphh-web #panel-wc { display: none !important; }
/* The Close-layout pill lives inside the now-zero-height strip; re-pin it fixed
   to the top-center of the viewport so it stays visible + clickable on web. */
.glyphh-web .echo-layout-bar {
  position: fixed !important;
  top: 6px !important;
  left: 50% !important;
  transform: translateX(-50%) !important;
  z-index: 320 !important;
}

.wc {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: none;
  padding: 0;
  cursor: pointer;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.wc::after {
  content: "";
  opacity: 1;
  transition: opacity 0.15s;
}

.wc-close    { background: #ff5f57; }
.wc-minimize { background: #febc2e; }
.wc-maximize { background: #28c840; }

.wc-close::after {
  content: "×";
  font-size: 10px;
  font-weight: 700;
  color: #4a0002;
  line-height: 1;
}

.wc-minimize::after {
  content: "−";
  font-size: 12px;
  font-weight: 700;
  color: #995700;
  line-height: 1;
  margin-top: -1px;
}

.wc-maximize::after {
  content: "";
  width: 6px;
  height: 6px;
  background-image:
    linear-gradient(45deg, #006500 50%, transparent 50%),
    linear-gradient(225deg, #006500 50%, transparent 50%);
  background-size: 4px 4px;
  background-position: top left, bottom right;
  background-repeat: no-repeat;
}

/* ── Titlebar ────────────────────────────────────────────── */

#titlebar {
  position: relative;
  z-index: 55;
  height: 38px;
  display: flex;
  align-items: center;
  /* Top padding leaves breathing room between the app header chrome
     (window controls / .Yo label) and the tabs that sit below — the
     tabs have `margin-top: auto` so they hug the bottom border. */
  padding: 6px 16px 0;
  background: var(--surface);
  /* Rail-color band between the tab strip and the content area so the
     active tab (also var(--surface-2)) flows continuously into the side
     rails with no dark divider line. Theme-aware via the token. */
  border-bottom: 4px solid var(--surface-2);
  -webkit-app-region: drag;
  gap: 12px;
}
/* Pull Command Center in tighter against the left-rail toggle than the
   titlebar's normal 12px gap — the pair reads as a related group. */

#titlebar-label {
  display: flex;
  align-items: center;
  cursor: pointer;
  -webkit-app-region: no-drag;
  user-select: none;
}

#titlebar-label:hover { color: var(--text); }

#titlebar-label .glyphh-mark { height: 24px; }

/* ── User menu ────────────────────────────────────────── */


/* ── Cmd+. overlay ─────────────────────────────────────── */

/* ── URL bar ──────────────────────────────────────────── */

.url-bar {
  position: fixed;
  top: 38px;
  left: var(--left-inset, 0px);
  right: var(--right-inset, 0px);
  /* 28px input + 4px top + 4px bottom = 36 outer (border-box). The
     4px top/bottom padding shows url-bar bg (surface-2) around the
     input — that's the "small gap above/below the url bar". */
  height: 36px;
  background: var(--surface-2);
  border: none;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px 4px 0;
  z-index: 50;
  transition: right 0.2s ease;
  -webkit-app-region: no-drag;
}

.url-bar.hidden { display: none !important; }

.url-bar-nav {
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--text-3);
  font-size: 16px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, color 0.15s;
  flex-shrink: 0;
  padding: 0;
}
.url-bar-nav:hover { background: var(--hover); color: var(--text); }
.url-bar-nav:active { background: var(--border-3); }
.url-bar-nav:disabled { opacity: 0.3; cursor: default; }
.url-bar-nav:disabled:hover { background: transparent; color: var(--text-3); }

.url-bar-favicon {
  flex-shrink: 0;
  border-radius: 2px;
  opacity: 0.8;
}
.url-bar-favicon[src=""],
.url-bar-favicon:not([src]) {
  display: none;
}

.url-bar-input {
  flex: 1;
  height: 28px;
  padding: 0 12px;
  font-size: 13px;
  color: var(--white);
  -webkit-text-fill-color: var(--white);
  background: var(--surface);
  border: 1px solid var(--border-3);
  border-radius: 8px;
  outline: none;
  font-family: var(--font-mono);
}
.url-bar-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(175, 95, 255, 0.15);
}
.url-bar-input::placeholder {
  color: var(--text-muted);
  -webkit-text-fill-color: var(--text-muted);
}
.url-bar-input::selection {
  background: var(--selection);
}

/* ── Cell URL bars (grid mode) ─────────────────────────── */

#cell-url-bars {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
  z-index: 49;
}

.cell-url-bar {
  position: absolute;
  height: 22px;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 6px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  pointer-events: auto;
  overflow: hidden;
}

.cell-url-bar-favicon {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  border-radius: 2px;
  opacity: 0.7;
}
.cell-url-bar-favicon[src=""],
.cell-url-bar-favicon:not([src]) { display: none; }

.cell-url-bar-text {
  flex: 1;
  font-size: 10px;
  font-family: var(--font-mono);
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  background: none;
  border: none;
  outline: none;
  padding: 2px 4px;
  border-radius: 3px;
  cursor: text;
  transition: background 0.15s, color 0.15s;
}
.cell-url-bar-text:hover {
  color: var(--text-2);
  background: var(--active-bg);
}
.cell-url-bar-text:focus {
  color: var(--text);
  background: var(--active-bg);
  text-overflow: clip;
  overflow: visible;
}

.cell-nav-btn {
  width: 18px;
  height: 18px;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: var(--text-3);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  padding: 0;
  transition: background 0.15s, color 0.15s;
}
.cell-nav-btn:hover { background: var(--hover); color: var(--text); }
.cell-nav-btn:active { background: var(--border-3); }

/* ── Tab bar ───────────────────────────────────────────── */

#tab-bar {
  display: flex;
  align-items: stretch;
  gap: 4px;
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-app-region: drag;
  scrollbar-width: none;
  /* When the left rail is open, push the first tab right so it lines up
     with the rail's right edge. --tabbar-chrome-w is set in renderer.ts
     from the actual measured x-offset of #tab-bar inside #titlebar, so
     this works regardless of label width / font / window controls width. */
  padding-left: max(0px, calc(var(--left-inset, 0px) - var(--tabbar-chrome-w, 172px)));
}

#tab-bar .tab,
#tab-bar .tab-new-btn {
  -webkit-app-region: no-drag;
}
#tab-bar::-webkit-scrollbar { display: none; }

.tab {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 8px 0 12px;
  /* Inactive tab matches the Dashboard page background. Theme-aware. */
  background: var(--bg);
  border: 1px solid var(--border-2);
  border-bottom: none;
  border-radius: 8px 8px 0 0;
  color: var(--text-3);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
  flex: 0 1 180px;
  min-width: 56px;
  max-width: 180px;
  margin-top: auto;
}

.tab:hover { background: var(--hover); color: var(--text); }

.tab-active {
  background: var(--surface-2);
  border-color: var(--border-2);
  color: var(--text);
}
.tab-active:hover { background: var(--surface-2); color: var(--text); }

.tab-favicon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  border-radius: 2px;
  object-fit: contain;
}
.tab-favicon[src=""],
.tab-favicon:not([src]) {
  display: none;
}

.tab-favicon-stack {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.tab-favicon-stacked {
  width: 12px;
  height: 12px;
  border-radius: 2px;
  border: 1px solid var(--border);
  object-fit: contain;
  position: relative;
}
.tab-active .tab-favicon-stacked {
  border-color: var(--accent);
}

.tab-label {
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
}

.tab-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  padding: 0;
  background: none;
  border: none;
  border-radius: 3px;
  color: inherit;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s, background 0.12s;
  flex-shrink: 0;
}

.tab:hover .tab-close { opacity: 0.6; }
.tab-close:hover { opacity: 1 !important; background: rgba(0,0,0,0.15); }
.tab-active .tab-close:hover { background: rgba(0,0,0,0.2); }

/* ── Home tab (pinned, leftmost) ─────────────────────────── */
.tab.tab-pinned {
  padding: 0 10px;
  min-width: 0;
  width: auto;
}
.tab-home-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: inherit;
  flex-shrink: 0;
}

/* ── Tab drag & drop visuals ─────────────────────────────── */
.tab[draggable="true"] { cursor: grab; }
.tab.tab-dragging { opacity: 0.4; cursor: grabbing; }
.tab.tab-drop-before { box-shadow: inset 2px 0 0 0 var(--accent); }
.tab.tab-drop-after { box-shadow: inset -2px 0 0 0 var(--accent); }

.tab-new-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--text-3);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  -webkit-app-region: no-drag;
  transition: all 0.12s;
  flex-shrink: 0;
  margin-left: 2px;
}

.tab-new-btn:hover { color: var(--text); background: var(--surface-2); border-color: var(--border-2); }

/* Dashboard shell (5a) — two-tab Apps / Settings chrome, shown in place of
   the tab-bar + files-rail after auth. */
.dashboard-tabs {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 100%;
  -webkit-app-region: no-drag;
}
.dashboard-tab {
  display: flex;
  align-items: center;
  height: 26px;
  padding: 0 14px;
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--text-3);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.12s;
}
.dashboard-tab:hover { color: var(--text); background: var(--surface-2); }
.dashboard-tab.active { color: var(--text); background: var(--surface-2); border-color: var(--border-2); }

/* Global, always-visible — sits at the far right of the titlebar regardless
   of which dashboard tab (Apps/Settings) is active. */
.titlebar-logout {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 12px;
  margin-left: auto;
  background: none;
  border: 1px solid var(--border-2);
  border-radius: 6px;
  color: var(--text-2);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.12s;
  -webkit-app-region: no-drag;
}
.titlebar-logout:hover { color: var(--text); background: var(--surface-2); border-color: var(--border-3); }

/* Command overlay launcher — icon button right of the Glyphh mark. */

/* MCP indicator */
.mcp-indicator {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  margin-right: 10px;
  background: none;
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text-2);
  font-size: 10px;
  font-weight: 600;
  font-family: 'SF Mono', 'Fira Code', monospace;
  cursor: pointer;
  transition: all 0.15s;
  flex-shrink: 0;
  -webkit-app-region: no-drag;
}
.mcp-indicator:hover { background: var(--surface-2); color: var(--text); }
.mcp-indicator-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-2);
  transition: background 0.2s;
}
.mcp-indicator.running .mcp-indicator-dot { background: var(--accent); }
.mcp-indicator.stopped .mcp-indicator-dot { background: var(--danger, #ef4444); }


/* ── Download button & dropdown ─────────────────────────── */

.dl-btn-wrap {
  position: relative;
  flex-shrink: 0;
  margin-right: 6px;
  -webkit-app-region: no-drag;
}

/* Working-directory chip — the project folder the app is focused on */
.workdir {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
  max-width: 220px;
  height: 26px;
  margin-right: 8px;
  padding: 0 9px;
  background: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-3);
  font-size: 11.5px;
  font-family: var(--font-sans);
  cursor: pointer;
  -webkit-app-region: no-drag;
  transition: all 0.15s;
}
.workdir:hover { color: var(--text); background: var(--hover); border-color: var(--border-2); }
.workdir svg { flex-shrink: 0; }
#workdir-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.dl-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--text-3);
  cursor: pointer;
  position: relative;
  transition: all 0.15s;
}
.dl-btn:hover { color: var(--text); background: var(--hover); border-color: var(--border); }
.dl-btn.dl-active { color: var(--text); }

.dl-badge-count {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 14px;
  height: 14px;
  padding: 0 3px;
  background: var(--accent);
  color: #000;
  font-size: 9px;
  font-weight: 700;
  line-height: 14px;
  text-align: center;
  border-radius: 7px;
  pointer-events: none;
}

.dl-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: 340px;
  max-height: 400px;
  background: var(--surface-2, var(--surface));
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 32px var(--shadow);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: dl-drop-in 0.15s ease-out;
}
.dl-dropdown.hidden { display: none; }

@keyframes dl-drop-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}

.dl-dropdown-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  border-bottom: 1px solid var(--border);
}

.dl-clear-all {
  background: none;
  border: none;
  color: var(--text-3);
  font-size: 11px;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
}
.dl-clear-all:hover { color: var(--text); background: var(--hover); }

.dl-list {
  overflow-y: auto;
  flex: 1;
  min-height: 60px;
}

.dl-empty {
  padding: 24px 14px;
  text-align: center;
  color: var(--text-3);
  font-size: 12px;
}

.dl-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--border-subtle, var(--border));
  cursor: pointer;
  transition: background 0.1s;
}
.dl-item:last-child { border-bottom: none; }
.dl-item:hover { background: var(--hover); }

.dl-item-icon {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: var(--accent-bg);
  color: var(--text);
  font-size: 13px;
}
.dl-item-icon.dl-error { background: rgba(255,80,80,0.12); color: #ff5050; }

.dl-item-info {
  flex: 1;
  min-width: 0;
}

.dl-item-name {
  font-size: 12px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dl-item-meta {
  font-size: 10px;
  color: var(--text-3);
  margin-top: 2px;
}

.dl-item-progress {
  height: 3px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
  margin-top: 4px;
}

.dl-item-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  border-radius: 2px;
  transition: width 0.2s ease;
}

.dl-item-actions {
  flex-shrink: 0;
  display: flex;
  gap: 4px;
}

.dl-item-action {
  background: none;
  border: none;
  color: var(--text-3);
  cursor: pointer;
  padding: 2px;
  border-radius: 4px;
  display: flex;
  align-items: center;
}
.dl-item-action:hover { color: var(--text); background: var(--hover); }

/* Tab + new menu dropdown */
.tab-new-menu {
  position: fixed;
  z-index: 9999;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-radius: 8px;
  padding: 4px;
  min-width: 200px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.4);
  display: flex;
  flex-direction: column;
}
.tab-new-menu-search {
  margin: 4px;
  padding: 6px 8px;
  font-size: 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text);
  outline: none;
}
.tab-new-menu-search:focus { border-color: var(--accent); }
.tab-new-menu-list {
  max-height: 280px;
  overflow-y: auto;
}
.tab-new-menu button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  color: var(--text);
  font-size: 13px;
  padding: 7px 10px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.12s;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tab-new-menu button:hover { background: var(--hover); }
.tab-new-menu-divider {
  height: 1px;
  background: var(--border);
  margin: 4px 6px;
}
.tab-new-menu-initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border-radius: 3px;
  background: var(--bg-2);
  color: var(--text-2);
  font-size: 10px;
  font-weight: 600;
  flex-shrink: 0;
}

/* ── Help Skills lists ────────────────────────────────────── */

.help-item-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 8px;
}
.help-item-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s;
}
.help-item-row:hover { background: var(--surface-2); }
.help-item-icon {
  flex-shrink: 0;
  color: var(--text-3);
  display: flex;
  align-items: center;
}
.help-item-name {
  flex: 1;
  font-size: 14px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.help-item-meta {
  font-size: 12px;
  color: var(--text-muted);
  flex-shrink: 0;
}
.help-item-actions {
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity 0.15s;
}
.help-item-row:hover .help-item-actions { opacity: 1; }
.help-item-action {
  width: 26px; height: 26px;
  border: none; border-radius: 4px;
  background: transparent;
  color: var(--text-3);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s, color 0.15s;
}
.help-item-action:hover { background: var(--border-3); color: var(--white); }
.help-item-action.danger:hover { background: #441111; color: var(--danger); }
.help-item-empty {
  padding: 24px 16px;
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
}
/* ── Skill editor (folder-based) ──────────────────────────── */
/* Split layout: form on the left, file tree + Monaco on the right.
   Override crud-inline-form's max-width cap so the right pane can breathe. */
.skill-editor-split.crud-inline-form {
  max-width: none !important;
}
.skill-split-body {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 16px;
  margin-top: 10px;
  min-height: 480px;
}
.skill-split-tree {
  display: flex;
  min-height: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  background: var(--bg-2);
}
.skill-split-tree .skill-code-tree {
  flex: 1;
  border-right: none;
  width: 100%;
}
.skill-split-tree .skill-tree-resize { display: none; }
.skill-split-overview {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}
.skill-file-viewer {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 420px;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  background: var(--surface-2);
  margin-top: 8px;
}
.skill-file-viewer.hidden { display: none; }
.skill-file-viewer-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.skill-file-viewer-path {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-2);
}
.skill-file-viewer-md {
  flex: 1;
  overflow-y: auto;
  padding: 16px 22px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text);
}
.skill-file-viewer-md.hidden { display: none; }
.skill-split-left {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.skill-left-topbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 8px;
}
.skill-left-form {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow-y: auto;
  padding-right: 4px;
}
.skill-left-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding-top: 10px;
  margin-top: 10px;
  border-top: 1px solid var(--border);
}
.skill-split-right {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}
.skill-split-right .skill-code-widget {
  flex: 1;
  min-height: 420px;
}

/* ── Layout editor split (mirrors skill-split) ────────────── */

.skill-code-widget {
  display: flex;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}
.skill-code-tree {
  background: var(--bg-2);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  min-height: 0;
  width: 200px;
  min-width: 120px;
  flex-shrink: 0;
}
.skill-tree-resize {
  flex: 0 0 4px;
  background: var(--border);
  cursor: col-resize;
  transition: background 0.1s;
}
.skill-tree-resize:hover,
.skill-tree-resize.dragging {
  background: var(--accent);
}
.skill-code-monaco {
  flex: 1;
  min-width: 0;
}
.skill-code-tree-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 4px 6px 4px 10px;
  border-bottom: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-2);
  font-family: var(--font-mono);
  min-width: 0;
}
#skill-editor-status {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.skill-tree-actions {
  display: flex;
  gap: 2px;
  flex-shrink: 0;
}
.skill-tree-action-btn {
  background: none;
  border: none;
  color: var(--text-2);
  padding: 4px 5px;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.1s, color 0.1s;
}
.skill-tree-action-btn:hover {
  background: var(--hover);
  color: var(--text);
}
.skill-code-monaco { background: #1e1e1e; }

/* Skill editor right-pane tabs (Code / Preview) */
.skill-right-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.skill-right-tab {
  background: none;
  border: none;
  padding: 7px 16px;
  font-size: 12px;
  font-family: var(--font-sans);
  color: var(--text-3);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: color 0.15s, border-color 0.15s;
}
.skill-right-tab:hover {
  color: var(--text);
}
.skill-right-tab.active {
  color: var(--text);
  border-bottom-color: var(--accent);
}
.skill-tab-content {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.skill-preview-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.skill-preview-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.skill-preview-note {
  font-size: 11px;
  color: var(--text-3);
  font-style: italic;
}
.skill-preview-webview {
  flex: 1;
  min-height: 0;
  border: none;
  background: var(--bg);
}

/* Skill type pills */
.skill-pill {
  display: inline-flex;
  align-items: center;
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  padding: 2px 6px;
  border-radius: 4px;
  line-height: 1;
  vertical-align: middle;
  white-space: nowrap;
}
.skill-pill-vibe {
  background: rgba(175, 95, 255, 0.12);
  color: var(--text);
}
.skill-pill-js {
  background: rgba(74, 158, 255, 0.12);
  color: var(--blue);
}
.skill-pill-prompt {
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-3);
}
.skill-pill-scheduled {
  background: rgba(240, 160, 48, 0.12);
  color: var(--warning);
}

/* File tree items with subfolder indent support */
.skill-file-list {
  flex: 1;
  overflow-y: auto;
  padding: 4px 0;
}
.skill-file-item {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  font-size: 12px;
  color: var(--text);
  cursor: pointer;
  font-family: var(--font-mono);
  border-left: 2px solid transparent;
  transition: background 0.1s;
}
.skill-file-item:hover { background: var(--hover); }
.skill-file-item.active {
  background: var(--hover);
  border-left-color: var(--accent);
  font-weight: 600;
}
.skill-file-item.folder { cursor: default; font-weight: 600; color: var(--text-2); }
.skill-file-item-icon {
  width: 10px;
  height: 10px;
  flex-shrink: 0;
  opacity: 0.6;
}
.skill-file-item-label {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.skill-file-item-delete {
  opacity: 0;
  background: none;
  border: none;
  color: var(--text-2);
  cursor: pointer;
  padding: 0 4px;
  font-size: 13px;
  line-height: 1;
}
.skill-file-item:hover .skill-file-item-delete { opacity: 0.5; }
.skill-file-item-delete:hover { opacity: 1 !important; color: var(--danger); }
.skill-file-item .skill-file-rename-input {
  flex: 1; background: var(--bg); border: 1px solid var(--accent); border-radius: 3px;
  color: var(--text); font-family: var(--font-mono); font-size: 12px; padding: 1px 4px;
  outline: none; min-width: 0;
}
.skill-file-item.folder.collapsible { cursor: pointer; }
.skill-file-item.folder .skill-folder-chevron {
  width: 8px; height: 8px; flex-shrink: 0; opacity: 0.5; transition: transform 0.15s;
}
.skill-file-item.folder.collapsed .skill-folder-chevron { transform: rotate(-90deg); }

/* Tool row list (allowed tools, dependencies) */
.skill-row-list { display: flex; flex-direction: column; gap: 4px; }
.skill-row {
  display: flex; align-items: center; gap: 6px;
  padding: 4px 0;
}
.skill-row select {
  flex: 1; min-width: 0; font-size: 12px;
  background: var(--bg); color: var(--text); border: 1px solid var(--border);
  border-radius: 4px; padding: 4px 6px; outline: none;
}
.skill-row select:focus { border-color: var(--accent); }
.skill-row .skill-row-remove {
  background: none; border: none; color: var(--text-2); cursor: pointer;
  padding: 2px 4px; font-size: 14px; line-height: 1; opacity: 0.5;
  transition: opacity 0.1s, color 0.1s;
}
.skill-row .skill-row-remove:hover { opacity: 1; color: var(--danger); }
.skill-row-add-btn {
  background: none; border: 1px dashed var(--border); border-radius: 4px;
  color: var(--text-2); cursor: pointer; padding: 4px 8px; font-size: 11px;
  transition: border-color 0.15s, color 0.15s; text-align: left; width: fit-content;
}
.skill-row-add-btn:hover { border-color: var(--accent); color: var(--text); }
.skill-row input[type="text"] {
  flex: 1; min-width: 0; font-size: 12px;
  background: var(--bg); color: var(--text); border: 1px solid var(--border);
  border-radius: 4px; padding: 4px 6px; outline: none;
}
.skill-row input[type="text"]:focus { border-color: var(--accent); }

.skill-run-output {
  margin-top: 12px; border: 1px solid var(--border); border-radius: 6px;
  background: var(--surface); display: flex; flex-direction: column; max-height: 300px;
}
.skill-run-output.error { border-color: var(--danger, #d44a4a); }
.skill-run-output-header {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; border-bottom: 1px solid var(--border);
  font-size: 12px; font-weight: 500; color: var(--text-2);
}
.skill-run-output-status-ok { color: var(--text); }
.skill-run-output-status-error { color: var(--danger, #d44a4a); }
.skill-run-output-status-running { color: var(--text-2); }
.skill-run-output-close {
  margin-left: auto; background: none; border: 0; color: var(--text-3);
  font-size: 18px; line-height: 1; cursor: pointer; padding: 0 4px;
}
.skill-run-output-close:hover { color: var(--text); }
.skill-run-output-body {
  margin: 0; padding: 8px 10px; font-family: var(--font-mono, monospace);
  font-size: 11px; line-height: 1.5; color: var(--text-2); overflow: auto;
  white-space: pre-wrap; word-break: break-word;
}

.agent-row-wrapper {
  display: flex; flex-direction: column; gap: 4px;
  padding-bottom: 8px; border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
}
.agent-row-wrapper:last-child { border-bottom: none; margin-bottom: 0; }
.agent-prompt {
  width: 100%; box-sizing: border-box; font-size: 11px; font-family: inherit;
  background: var(--bg); color: var(--text); border: 1px solid var(--border);
  border-radius: 4px; padding: 6px 8px; outline: none; resize: vertical;
  min-height: 32px;
}
.agent-prompt::placeholder { color: var(--text-2); }
.agent-prompt:focus { border-color: var(--accent); }
.agent-input-toggle {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--text-2); margin-top: 4px;
  cursor: pointer;
}
.agent-input-toggle input[type="checkbox"] {
  accent-color: var(--accent); width: 14px; height: 14px; cursor: pointer;
}

/* Yo agent build hint */
.yo-build-hint {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; margin: 6px 0 10px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: 8px; font-size: 12px; color: var(--text-2); line-height: 1.4;
}
.yo-build-hint strong { color: var(--text); }
.yo-build-hint-icon {
  flex-shrink: 0; width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  background: var(--white); color: var(--bg); border-radius: 8px;
  font-family: var(--font-mono); font-weight: 800; font-size: 13px;
  letter-spacing: -0.03em; line-height: 1;
}
.yo-build-hint-dot { color: var(--text); }

/* Schedule builder */
.skill-schedule-builder { display: flex; flex-direction: column; gap: 6px; }
.skill-sched-select { font-size: 12px; max-width: 220px; }
.sched-row { display: flex; align-items: center; gap: 6px; }
.sched-sel {
  font-size: 12px; background: var(--bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 4px; padding: 3px 6px;
  min-width: 50px;
}
.skill-schedule-opts {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  font-size: 12px; color: var(--text-2);
}
.sched-days { padding: 2px 0; }
.sched-day-chips { display: flex; gap: 4px; flex-wrap: wrap; }
.sched-day-chip {
  padding: 4px 10px; border-radius: 4px; font-size: 11px; font-weight: 500;
  border: 1px solid var(--border); background: var(--bg); color: var(--text-2);
  cursor: pointer; transition: all 0.15s; user-select: none;
}
.sched-day-chip:hover { border-color: var(--accent); color: var(--text); }
.sched-day-chip.active {
  background: var(--accent); color: var(--accent-fg); border-color: var(--accent);
}
.sched-time-row, .sched-dom-row, .sched-interval-row {
  display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-2);
}
.sched-time-row label, .sched-dom-row label, .sched-interval-row label {
  font-size: 11px; color: var(--text-2); min-width: 32px;
}
.sched-time-row span { color: var(--text-2); font-weight: 600; }
.sched-preview {
  font-size: 11px; color: var(--text-2); padding: 4px 0;
  font-style: italic;
}

/* Recent runs inline styling */
.skill-runs-section {
  margin-top: 8px;
  padding: 8px 10px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.skill-runs-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11px;
  text-transform: uppercase;
  color: var(--text-2);
  letter-spacing: 0.05em;
  margin-bottom: 6px;
  font-weight: 600;
}
.skill-runs-list { max-height: 200px; overflow-y: auto; }
.skill-run-item {
  padding: 6px 8px;
  border-radius: 4px;
  font-size: 12px;
  margin-bottom: 4px;
  background: var(--surface-2);
  cursor: pointer;
}
.skill-run-item:hover { background: var(--hover); }
.skill-run-item-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}
.skill-run-item-status {
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 3px;
  font-weight: 600;
  font-family: var(--font-mono);
}
.skill-run-status-success { background: rgba(175, 95, 255, 0.15); color: var(--text); }
.skill-run-status-error { background: rgba(255, 68, 68, 0.15); color: var(--danger); }
.skill-run-item-details {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 11px;
  white-space: pre-wrap;
  word-break: break-word;
  overflow-x: auto;
  max-height: 400px;
  overflow-y: auto;
}
.skill-run-event { padding: 2px 0; font-size: 11px; color: var(--text-2); }
.skill-run-event.status-error { color: var(--danger); }
.skill-run-event.status-success { color: var(--text); }

.skill-run-section { margin-bottom: 8px; }
.skill-run-section-header {
  font-size: 11px;
  color: var(--text-2);
  padding: 2px 0;
}
.skill-run-section-body {
  padding: 4px 0;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 12px;
  font-family: var(--font-mono);
  color: var(--text);
}

/* Skill create modal */

/* ── Detail view (skills + library split editor) ──────── */

/* ── Skill editor ────────────────────────────────────────── */

#skill-editor:not(.hidden) {
  display: flex;
  flex-direction: column;
}
.skill-field {
  margin-bottom: 14px;
}
.skill-label {
  display: block;
  font-size: 12px;
  color: var(--text-2);
  margin-bottom: 6px;
}
.skill-ai-icon {
  color: var(--text);
  vertical-align: -2px;
  margin-right: 4px;
}
.skill-generate-btn {
  margin-top: 8px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--text);
  border-color: var(--accent);
}
.skill-generate-btn:hover {
  background: rgba(175, 95, 255, 0.1);
}
.skill-input {
  width: 100%;
  padding: 10px 14px;
  font-size: 13px;
  color: var(--white);
  -webkit-text-fill-color: var(--white);
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 6px;
  outline: none;
  font-family: inherit;
  transition: border-color 0.15s;
  box-sizing: border-box;
  resize: vertical;
}
.skill-input:focus { border-color: var(--accent); }
.skill-input::placeholder { color: var(--text-muted); -webkit-text-fill-color: var(--text-muted); }
.skill-prompt-area {
  width: 100%;
  padding: 10px 14px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--white);
  -webkit-text-fill-color: var(--white);
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 6px;
  outline: none;
  resize: vertical;
  font-family: var(--font-mono);
  transition: border-color 0.15s;
}
.skill-prompt-area:focus { border-color: var(--accent); }
.skill-prompt-area::placeholder { color: var(--text-faint); -webkit-text-fill-color: var(--text-faint); }

/* Validation */
.invalid { border-color: var(--danger) !important; }
.invalid:focus { border-color: var(--danger) !important; }

/* ── Confirm modal ───────────────────────────────────────── */
.confirm-overlay {
  position: fixed;
  inset: 0;
  /* Confirms are raised FROM inside the settings modal (.yo-modal, z 99500) —
     revoking an API key, the Tabs page's Chrome import — so they must float
     ABOVE it. The settings overlay moved 9000 → 99500 on 2026-09-18 and this
     layer stayed at 9600, which put every such confirm behind the page that
     opened it (his report, 2026-09-23). Below the lightbox (100000). */
  z-index: 99600;
  background: var(--overlay-bg);
  display: flex;
  align-items: center;
  justify-content: center;
}
.confirm-overlay.hidden { display: none; }
.confirm-box {
  background: var(--surface-2);
  border: 1px solid var(--border-3);
  border-radius: 12px;
  padding: 0; /* head/body/foot own their padding */
  overflow: hidden;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
  /* Half the chat content width (composer maxes at 780px) — one
     consistent modal width everywhere. */
  width: min(420px, 86vw);
  box-sizing: border-box;
  text-align: left;
}
/* One dialog skeleton everywhere: head (title), body (detail / input),
   foot (Cancel + primary action, right-aligned). */
.confirm-head {
  padding: 14px 18px 12px;
  border-bottom: 1px solid var(--border);
}
.confirm-head h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-bright);
  line-height: 1.4;
}
.confirm-body { padding: 14px 18px; }
.confirm-body.hidden { display: none; }
.confirm-body p {
  margin: 0;
  font-size: 13px;
  color: var(--text-2);
  line-height: 1.55;
}
.confirm-body textarea { width: 100%; box-sizing: border-box; }
.confirm-foot {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  padding: 12px 18px 14px;
  border-top: 1px solid var(--border);
  background: var(--surface);
}
/* Destructive confirms get a filled red primary. */
#confirm-yes.danger {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
}
#confirm-yes.danger:hover { filter: brightness(1.1); }

/* ── Panel screenshots (freeze-frame) ────────────────────── */

#panel-screenshots {
  position: fixed;
  inset: 0;
  z-index: 40;
  pointer-events: none;
}

.panel-screenshot {
  position: absolute;
  background-size: cover;
  background-repeat: no-repeat;
  filter: brightness(0.6);
}

/* ── Split drag handle ───────────────────────────────────── */

#grid-handles {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 50;
}

.grid-col-handle {
  position: absolute;
  top: var(--content-top);
  bottom: 0;
  width: 8px;
  cursor: col-resize;
  transform: translateX(-50%);
  pointer-events: auto;
  background: var(--surface-2);
}

/* Thin vertical line the full height */
.grid-col-handle::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: var(--border-2);
  transform: translateX(-50%);
  transition: background 0.15s;
}

/* Grip dots at center */
.grid-col-handle::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 3px;
  height: 32px;
  background: var(--border-3);
  border-radius: 2px;
  transition: all 0.2s ease;
}

.grid-col-handle:hover::before {
  background: rgba(175, 95, 255, 0.19);
  width: 2px;
}

.grid-col-handle.dragging::before {
  background: var(--accent);
  width: 2px;
  box-shadow: 0 0 12px rgba(175, 95, 255, 0.5);
}

.grid-col-handle:hover::after {
  background: var(--accent);
  height: 48px;
  width: 4px;
  box-shadow: 0 0 10px rgba(175, 95, 255, 0.4);
}

.grid-col-handle.dragging::after {
  background: var(--accent);
  height: 100%;
  width: 2px;
  border-radius: 0;
  box-shadow: 0 0 12px rgba(175, 95, 255, 0.5);
}

.grid-row-handle {
  position: absolute;
  left: 0;
  right: 0;
  height: 8px;
  cursor: row-resize;
  transform: translateY(-50%);
  pointer-events: auto;
  background: var(--surface-2);
}

/* Thin horizontal line the full width */
.grid-row-handle::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--border-2);
  transform: translateY(-50%);
  transition: background 0.15s;
}

/* Grip bar at center */
.grid-row-handle::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 32px;
  height: 3px;
  background: var(--border-3);
  border-radius: 2px;
  transition: all 0.2s ease;
}

.grid-row-handle:hover::before {
  background: rgba(175, 95, 255, 0.19);
  height: 2px;
}

.grid-row-handle.dragging::before {
  background: var(--accent);
  height: 2px;
  box-shadow: 0 0 12px rgba(175, 95, 255, 0.5);
}

.grid-row-handle:hover::after {
  background: var(--accent);
  width: 48px;
  height: 4px;
  box-shadow: 0 0 10px rgba(175, 95, 255, 0.4);
}

.grid-row-handle.dragging::after {
  background: var(--accent);
  width: 100%;
  height: 2px;
  border-radius: 0;
  box-shadow: 0 0 12px rgba(175, 95, 255, 0.5);
}

#drag-overlay {
  position: fixed;
  inset: var(--titlebar-h) 0 0 0;
  z-index: 45;
  background: transparent;
}

#drag-overlay.drag-col { cursor: col-resize; }
#drag-overlay.drag-row { cursor: row-resize; }

/* ── Help overlay (docs layout) ─────────────────────────── */

#help-overlay {
  position: fixed;
  top: var(--titlebar-h);
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 100;
  background: var(--bg);
}

#help-layout {
  display: flex;
  height: 100%;
}

/* Sidebar nav */

.help-close-x {
  position: absolute;
  top: 12px;
  right: 16px;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
  transition: color 0.15s, background 0.15s;
  z-index: 1;
}
.help-close-x:hover { color: var(--white); background: var(--active-bg); }

/* Content area */
#help-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  position: relative;
}
#page-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 32px 40px;
  position: relative;
}

.help-section {
  display: none;
}

/* Hard guard: only the active section ever renders (prevents one section's
   content — e.g. Schedules — bleeding into another like Skills). */
.help-section:not(.active) {
  display: none !important;
}

.help-section.active {
  display: block;
}

/* The dashboard landing is RETIRED (the app boots into the new-session
   screen). Nothing routes here anymore — hard-hide it so a stale .active can
   never bleed "Welcome back" + the old mascot through an open layout. */
.help-section[data-section="dashboard"] { display: none !important; }

/* Sections with split detail views need full height */
.help-section[data-section="dashboard"].active,
.help-section[data-section="apps"].active,
.help-section[data-section="connections"].active,
.help-section[data-section="loops"].active,
.help-section[data-section="skills"].active,
.help-section[data-section="agents"].active,
.help-section[data-section="files"].active,
.help-section[data-section="layouts"].active,
.help-section[data-section="mcp"].active,
.help-section[data-section="library"].active,
.help-section[data-section="docs"].active,
.help-section[data-section="settings"].active {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow-y: auto;
}
/* The connections list + detail fill and scroll exactly like the Apps list +
   #app-detail (two-column .app-builder-split form). */
.help-section[data-section="connections"] #connections-list { flex: 1; min-height: 0; overflow-y: auto; }
.help-section[data-section="connections"] #conn-detail { flex: 1; display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.help-section[data-section="connections"] #conn-detail.hidden { display: none !important; }

/* ── Home dashboard (landing) ─────────────────────────────────────────── */
/* The dashboard renders INSIDE an echo card as often as full-page — media
   queries measure the window, so responsiveness keys off the SECTION's own
   width (container queries), like the lib tables. */
.help-section[data-section="dashboard"] { container-type: inline-size; container-name: dash; }
/* The glyphh.ai desktop page's MOVEMENT, ported: the faint drifting
   particle field behind the hero (slow upward drift, twinkle, a minority
   of accent dots). The canvas sits behind the landing content. */
.help-section[data-section="dashboard"].active { position: relative; }
.dash-particles { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.help-section[data-section="dashboard"] .dash-scroll { position: relative; z-index: 1; }
.dash-scroll {
  padding: 28px 36px 48px;
  max-width: 900px;
  margin: 0 auto;
  width: 100%;
  box-sizing: border-box;
  /* The landing column flows from the top; the hero's own top offset (18vh)
     drops the greeting+composer down the page, cards below (Landing.js). */
  min-height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}
@container dash (max-width: 720px) { .dash-scroll { padding: 18px 16px 32px; } }

/* HERO — greeting + composer as one unit, pushed DOWN the page (not centered
   high): a big top offset drops it lower, cards flow beneath (dash-hero). */
.dash-hero { display: flex; flex-direction: column; width: 100%; margin-top: 22vh; }
.dash-hero > .dash-header { margin-bottom: 18px; }
@container dash (max-width: 720px) { .dash-hero { margin-top: 12vh; } }
.dash-header {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 14px;
  margin-bottom: 18px;
  text-align: left;
}
.dash-mark { width: 56px; height: 56px; flex: none; border-radius: 12px; }
.dash-header-text { text-align: left; }

/* App notifications — a quiet slot under the welcome; apps fill it later. */
.dash-notifications {
  margin: 0 auto 16px;
  max-width: 640px;
}
.dash-notifications.hidden { display: none; }

/* the FULL agent footer, adopted — full column width (same as the two
   cowork cards), taller input, and it never moves */
/* Under-title line — one span per space, the rail tab picks which shows. */
.dash-subtitle { margin: 4px 0 0; font-size: 15px; color: var(--text-2); }
.dash-subtitle span { display: none; }
body[data-rail-space="chat"] .dash-sub-chat { display: inline; }
body[data-rail-space="cowork"] .dash-sub-cowork { display: inline; }
body[data-rail-space="code"] .dash-sub-code { display: inline; }

/* The landing's chip row above the composer's top-left. It shows in EVERY
   space — chat keeps the source chip alone (reading "Cloud"), and paints the
   folder/add chips `.hidden` itself; work and code fill the rest of the row. */
/* Chips row — the composer's snug top row. A comfortable gap ABOVE separates
   the whole composer unit from the two-column body; only 4px BELOW so the
   chips hug the input directly beneath them (one cohesive composer). */
.dash-wd-chips { display: flex; align-items: center; gap: 4px; margin: 22px 0 4px; }

/* A chip that states a fact rather than offering a choice (chat's source). */
.cl-chip-static .cl-runtime-btn { pointer-events: none; }
.cl-chip-static .ws-chev { display: none; }

/* ── Chat landing starters ─────────────────────────────────────────────
   Six characters, each a front door to a space. Chat only — Work and Code
   land on their own surfaces. */
/* Chat only. (Hidden with display, not visibility: a reserved-but-invisible
   block made the landing column taller than its container, and a centred
   flex column that overflows pushes its FIRST child out through the top —
   which is why the greeting kept sitting too high instead of centred.) */
.dash-starters {
  display: grid;
  /* Full-width strip above the two-column body — a compact single row, three
     cards across. Narrows to 2, then 1 in a tight panel. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  width: 100%;
  margin: 6px 0 18px;
}
@container dash (max-width: 780px) { .dash-starters { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@container dash (max-width: 520px) { .dash-starters { grid-template-columns: 1fr; } }

.dash-starter {
  position: relative;
  display: flex; flex-direction: column; gap: 4px;
  padding: 10px 12px 11px;
  text-align: left; cursor: pointer;
  border: 1px solid var(--border-2); border-radius: 12px;
  background:
    linear-gradient(160deg, color-mix(in srgb, var(--surface-3) 88%, transparent), var(--surface-2));
  color: var(--text);
  transition: transform .16s cubic-bezier(.2,.8,.2,1), border-color .16s, box-shadow .16s;
}
.dash-starter:hover {
  transform: translateY(-2px);
  /* the theme's highlight ink — WHITE on the default dark theme (same token
     as the echo tiles' hover ring) */
  border-color: var(--echo-tile-highlight, var(--text));
  box-shadow: 0 10px 26px rgba(0,0,0,.28);
}
.dash-starter-top { display: flex; align-items: center; gap: 8px; }
.dash-starter-mascot { width: 40px; height: 40px; flex: none; display: block; }
.dash-starter-mascot svg { width: 100%; height: 100%; display: block; }
.dash-starter-name { font-size: 12px; font-weight: 650; color: var(--text-2); letter-spacing: .01em; }
.dash-starter-top .space-pill { margin-left: auto; }
.dash-starter-title { font-size: 13px; font-weight: 650; }
.dash-starter-blurb { font-size: 11.5px; line-height: 1.4; color: var(--text-3); }

/* The space pill — the same badge language as the layout cards. */
.space-pill {
  display: inline-flex; align-items: center; gap: 4px; flex: none;
  padding: 2px 7px 2px 5px; border-radius: 999px;
  border: 1px solid var(--border-2); background: var(--surface);
  font-size: 10.5px; font-weight: 600; color: var(--text-2);
}
.space-pill svg { width: 10px; height: 10px; }

/* The composer is ONE unit: the chips row (#dash-wd-chips) hugs the input,
   which carries the mode/model/loop bar right beneath it. No top margin here —
   the chips row directly above owns the small gap to the input, so the input
   never floats detached from its buttons. */
.dash-composer-slot { width: 100%; margin: 0 0 26px; }
/* The Home composer stays CENTERED and CAPPED like the in-session one — a
   wide window must not stretch the input to the extents. (It used to run
   flush with the cowork columns via max-width:none.) */
.dash-composer-slot .code-composer { width: 100%; max-width: 880px; padding: 0; margin: 0 auto; }
/* The HOME landing input is roomier — it opens showing ~2 rows of text (a
   full extra row over the in-session composer's single line). autoGrow sets an
   inline height to scrollHeight, but min-height clamps the empty box up to two
   rows; the textarea still grows past this as you type (max-height 220px).
   Kept to a true 2 rows so the input doesn't balloon away from the mode bar
   below it. Scoped to Home so the in-session/layout composers keep one line. */
.dash-composer-slot .code-input,
body.composer-on-home .dash-composer-slot .code-input { min-height: 64px; }

/* Chat mode hides the cowork content but KEEPS its space — the composer
   stays fixed in the page; the toggle never makes the layout jump */
body.chat-only .dash-two-col { display: none; }

/* The agent's head chrome matches the session's TYPE (or the active tab before
   the first send creates the session) — TWO types since 2026-09-29:
   - WORK: folder (documents/downloads live there) but no git and no dev panel
     toggles — those are Code's options.
   - CODE: everything.
   The retired `chat` and `cowork` stamps are read as Work (help/code.ts's
   modeOf), and their old selectors are kept so a thread stamped before the
   rename still wears the right chrome. */
/* WORK CARRIES NO DEV CHROME (his choice, 2026-09-29): no folder picker, no git
   branch, no add-folder — a Work turn has no file or shell tools, so none of
   that would do anything. The + STAYS (his push-back the same day: "shouldn't
   it still have the + button to add files and photos etc") — a Work attachment
   arrives as CONTENT instead of as a path, which is the honest way to hand a
   file to a belt with no reader. Code keeps everything. */
body[data-session-space="work"] #code-workdir-btn,
body[data-session-space="work"] #code-workdir-add,
body[data-session-space="work"] #code-workdir-branch-wrap,
body[data-session-space="work"] .plus-folder-only,
body[data-session-space="work"] .code-view-toggles,
body[data-session-space="chat"] #code-workdir-btn,
body[data-session-space="chat"] #code-workdir-add,
body[data-session-space="chat"] #code-workdir-branch-wrap,
body[data-session-space="chat"] .plus-folder-only,
body[data-session-space="chat"] .code-view-toggles,
body[data-session-space="cowork"] #code-workdir-branch-wrap,
body[data-session-space="cowork"] .code-view-toggles { display: none !important; }
/* A locked chip reads disabled but still catches clicks so it can
   close other open popups. */
.code-chip.is-locked { opacity: 0.55; cursor: default; }
.code-chip.is-locked:hover { border-color: var(--border); color: var(--text-3); }
/* Inline CONNECT card — the agent offers an account connection in the
   thread; OAuth runs in-app, the user never leaves the chat. */
.code-connect-wrap { margin: 10px 0; }
.code-connect-card {
  display: flex; align-items: center; gap: 12px;
  max-width: 440px;
  padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface-3);
}
.code-connect-card .ccx-icon { width: 30px; height: 30px; border-radius: 7px; flex: none; }
.code-connect-card .ccx-initial {
  width: 30px; height: 30px; border-radius: 7px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--active-bg); color: var(--text); font-weight: 700;
}
.code-connect-card .ccx-info { flex: 1; min-width: 0; }
.code-connect-card .ccx-name { font-size: 13.5px; font-weight: 600; color: var(--text); }
.code-connect-card .ccx-sub { font-size: 12px; color: var(--text-3); margin-top: 2px; }
.code-connect-card .ccx-btn {
  flex: none; padding: 7px 16px;
  border: none; border-radius: 8px; cursor: pointer;
  background: var(--accent); color: var(--accent-fg); font-size: 12.5px; font-weight: 700;
}
.code-connect-card .ccx-btn:disabled { opacity: 0.75; cursor: default; }
.code-connect-card[data-status="connected"] .ccx-btn { background: var(--active-bg); color: var(--text); }
.code-connect-card[data-status="failed"] .ccx-sub { color: var(--danger); }

/* Both types carry a folder now (Work keeps documents/downloads, Code its
   repo), so the + menu's folder actions are never hidden — the rule that hid
   them for the retired Chat space went with it, 2026-09-29. */
.code-drop-sep { height: 1px; background: var(--border); margin: 4px 6px; }

/* session rows: the TYPE's icon when idle (the working pulse replaces it) */
.code-sess-ic { display: inline-flex; flex-shrink: 0; margin-left: 2px; color: var(--text-3); }
.code-sess-ic svg { width: 13px; height: 13px; }

/* The leading icon IS the pin control, so it has to read as pressable. */
.code-history-item .code-sess-ic,
.code-history-item .code-chat-dot { cursor: pointer; border-radius: 4px; }
.code-history-item .code-sess-ic:hover { color: var(--text); }

/* Pinned: a dot off the icon's top-right corner. Positioned on the row (which
   already establishes a stacking context) rather than the icon, so the pulse
   variant and the svg variant mark identically. */
.code-history-item .code-sess-ic,
.code-history-item .code-chat-dot { position: relative; }
.code-sess-ic.pinned::after,
.code-chat-dot.pinned::after {
  content: '';
  position: absolute;
  top: -2px;
  right: -3px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

/* Recents section heading — Cloud, then a heading per local folder. Quiet on
   purpose: it matches the rail's "More" disclosure exactly (same colour, same
   per-theme dimming), because both are chrome rather than destinations. */
.code-history-sec {
  padding: 0 10px;
  margin: 10px 0 3px;
  color: var(--text-2);
  opacity: 0.85;
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  user-select: none;
}
.code-history-sec:first-child { margin-top: 2px; }

[data-theme="dark"] .code-history-sec, [data-theme="modern-dark"] .code-history-sec { opacity: 0.55; }

/* Spaces are gone — every session is the Code agent, so the rail nav no
   longer scopes items by space (the Chat/Work/Code tabs were removed). */

/* Settings › Usage: the Add funds action above the metric cards */
.dash-usage-actions { display: flex; justify-content: flex-end; margin-bottom: 12px; }
.dash-greeting {
  font-family: var(--font-sans);
  font-size: 34px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0;
}
.dash-subtitle { font-size: 15px; color: var(--text-2); margin: 4px 0 0; }
.dash-header-actions { display: flex; gap: 8px; flex-shrink: 0; }

.dash-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
@container dash (max-width: 900px) { .dash-grid { grid-template-columns: repeat(2, 1fr); } }
@container dash (max-width: 620px) { .dash-grid { grid-template-columns: 1fr; } }
@container dash (max-width: 620px) { .dash-header { flex-wrap: wrap; } }

.dash-card {
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px 20px;
}
.dash-card-wide { margin-top: 14px; }

.dash-card-label { font-size: 12px; font-weight: 500; color: var(--text-3); margin-bottom: 10px; }
.dash-card-value {
  font-family: var(--font-sans);
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
  line-height: 1.1;
}
.dash-card-value-sm { font-size: 21px; }
.dash-card-sub { font-size: 12px; color: var(--text-3); margin-top: 6px; }
.dash-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.dash-chart-wrap { position: relative; height: 220px; }
.dash-chart-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--text-3);
  font-size: 13px;
  padding: 0 24px;
}
/* The usage chart's filter row: range, stack-by, and narrowing dropdowns. */
.dash-usage-filters { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: flex-end; flex: 1 1 auto; min-width: 0; }
/* The KPI column ("$3.40 · 10 calls") holds its line — the wide member
   filter was crushing it to a one-word-per-line stack on web. */
.dash-card-head > div:first-child { flex: 0 0 auto; }
.dash-card-head .dash-card-value { white-space: nowrap; }
.dash-usage-select { max-width: 220px; }
.dash-usage-select {
  background: var(--surface-2); color: var(--text-2);
  border: 1px solid var(--border); border-radius: 7px;
  font-size: 11.5px; padding: 4px 8px; cursor: pointer;
}
.dash-usage-select:hover { color: var(--text); border-color: var(--border-2); }

.dash-refresh {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-3);
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  transition: color 150ms ease, border-color 150ms ease, background 150ms ease;
}
.dash-refresh:hover { color: var(--text); border-color: var(--border-2); background: var(--hover); }


/* The library page wrapper (added for the My apps | Marketplace tabs) must
   pass the section's flex layout through — otherwise #app-detail's flex:1
   sits in a plain block and the editor's split pane never fills the page
   (right pane stops at its content instead of stretching). */
.help-section[data-section="apps"].active > #apps-library-page:not(.hidden) {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

/* The Marketplace (its own section now) has no split-detail pane, so it must
   NOT be its own nested scroll container — otherwise its scrollbar lands 40px
   inside #help-content's right padding. Letting the section grow lets
   #help-content scroll, putting the scrollbar at the pane edge. */
.help-section[data-section="marketplace"].active {
  height: auto;
  overflow: visible;
}
/* …but INSIDE a workbench section card the card body is the viewport — the
   override above out-specified the card's scroller and froze the page (his
   bug, 2026-08-20): vertical scroll comes back here. */
.ws-section-body > .help-section[data-section="marketplace"].active {
  flex: 1;
  min-height: 0;
  height: auto;
  overflow-y: auto;
}

.help-section[data-section="apps"] #app-detail,
.help-section[data-section="library"] #lib-detail,
.help-section[data-section="layouts"] #layout-editor {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.help-section[data-section="apps"] #app-detail.hidden,
.help-section[data-section="library"] #lib-detail.hidden {
  display: none !important;
}

.help-section h2 {
  font-size: 20px;
  font-weight: 600;
  color: var(--white);
  margin-bottom: 24px;
  letter-spacing: -0.02em;
}

.section-desc {
  font-size: 13px;
  color: var(--text-2);
  margin: -16px 0 20px;
}

.section-desc code {
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 12px;
}

.help-group {
  margin-bottom: 28px;
}

.help-group h3 {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-3);
  margin-bottom: 12px;
}

.cmd-row {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}

.cmd-row:last-child { border-bottom: none; }

.cmd-row code {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--white);
  min-width: 280px;
  flex-shrink: 0;
}

.cmd-row span {
  font-size: 13px;
  color: var(--text-2);
  line-height: 1.5;
}

.cmd-row em {
  color: var(--text);
  font-style: normal;
}

.cmd-desc {
  font-weight: 400;
  font-size: 14px;
  color: var(--text-2);
}

.cmd-intro {
  font-size: 13px;
  color: var(--text-2);
  margin-bottom: 8px;
}

.panels-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

.panel-chip {
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px;
  text-align: center;
}

.chip-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}

.panel-chip code {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-3);
}

/* ── Shared: toolbar, item list, editor ─────────────────── */

.tab-toolbar {
  display: flex;
  gap: 8px;
  padding: 0 0 16px;
}

.tab-toolbar input {
  flex: 1;
  height: 30px;
  background: var(--border);
  border: 1px solid var(--border-3);
  border-radius: 6px;
  padding: 0 10px;
  color: var(--text);
  font-size: 13px;
  font-family: var(--font-mono);
  outline: none;
  min-width: 0;
}

.tab-toolbar input:focus { border-color: var(--accent); }
.tab-toolbar input::placeholder { color: var(--text-3); }

.tab-toolbar .action-btn { white-space: nowrap; }

.item-list {
  overflow-y: auto;
  max-height: 260px;
}

.item-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.1s;
}

.item-row:hover { background: var(--border); }

.item-name {
  font-size: 13px;
  color: var(--text);
  font-family: var(--font-mono);
}

.item-meta {
  font-size: 11px;
  color: var(--text-muted);
}

/* ── Shared CRUD components ──────────────────────────────── */

.crud-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
}
/* A secondary input riding in the toolbar (e.g. Workspaces' new-name field)
   matches the search box's 34px line so the row reads as one bar. */
.crud-toolbar .settings-input {
  height: 34px;
  padding-top: 0;
  padding-bottom: 0;
  font-size: 13px;
}

.crud-search {
  flex: 1;
  height: 34px;
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  border-radius: 8px;
  padding: 0 12px;
  color: var(--text);
  font-size: 13px;
  outline: none;
  min-width: 0;
  transition: border-color 0.15s;
}
.crud-search:focus { border-color: var(--accent); }
.crud-search::placeholder { color: var(--text-muted); }

/* Clear (×) button on search boxes — injected by search-clear.ts. The wrap
   takes the input's place (preserving flex:1 in toolbars, full width elsewhere)
   and anchors the absolutely-positioned button at the input's right edge. */
/* Content-height by default (so the wrapper never grows in a flex COLUMN like
   the left rail). Only the crud-search toolbars — where the input was flex:1 —
   need the wrapper to grow and fill the row. */
.search-clear-wrap { position: relative; display: flex; align-items: center; flex: 0 0 auto; min-width: 0; }
.search-clear-wrap:has(> input.crud-search) { flex: 1 1 auto; }
/* In a crud toolbar the search ALWAYS takes the full remaining width (his
   spec: search full width, actions right) — explicit, not :has-dependent. */
.crud-toolbar .search-clear-wrap { flex: 1 1 auto; }
.search-clear-wrap > input { flex: 1 1 auto; width: 100%; min-width: 0; padding-right: 30px; }
.search-clear-btn {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  width: 16px; height: 16px; border-radius: 50%; border: none; padding: 0; margin: 0;
  display: none; align-items: center; justify-content: center; cursor: pointer;
  background: var(--surface-3); color: var(--text-muted); transition: background 0.12s, color 0.12s;
}
.search-clear-btn.visible { display: flex; }
.search-clear-btn:hover { background: var(--accent); color: var(--accent-fg); }
.search-clear-btn svg { width: 10px; height: 10px; }

/* App grid cards */
/* Apps tab: a flex column holding the card grid + a full-width pagination bar
   below it (the bar must not be a grid cell). */
.app-list-wrap {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 4px 0;
}
.app-list-wrap .app-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 140px));
  gap: 10px;
  align-content: start;
}
.app-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 14px 8px 10px;
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
  text-align: center;
}
.app-card:hover {
  background: var(--surface-2);
  border-color: var(--border-3);
}
.app-card-icon {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.app-card-icon img {
  /* contain in a fixed inset so every logo reads the same size (cc parity) */
  border-radius: 6px;
  width: 32px;
  height: 32px;
  object-fit: contain;
  padding: 4px;
  box-sizing: border-box;
}
.app-card-initial {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 6px;
  background: var(--hover);
  color: var(--text-2);
  font-size: 14px;
  font-weight: 600;
}
.app-card-name {
  font-size: 11px;
  font-weight: 500;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.app-card-id {
  font-size: 9px;
  color: var(--text-muted);
  font-family: var(--font-mono);
}

.crud-cards {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Empty-state — a rotating saying (peace/love/object) over a muted how-to.
   Left-aligned and pulled tight under the toolbar (its 16px margin already
   supplies the gap — no extra top padding). */
.crud-empty {
  margin-top: -4px;
  padding: 0 2px 24px;
  text-align: left;
  color: var(--text-2);
  font-size: 13px;
}

/* Theme-aware INFO CALLOUT — notices that must stand out from body copy
   (the Members seat gate). Tokens only, so every theme paints it right. */
.settings-callout {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 14px;
  padding: 10px 14px;
  border: 1px solid var(--border-2);
  border-left: 3px solid var(--accent, #af5fff);
  border-radius: 8px;
  background: var(--active-bg);
  color: var(--text);
  font-size: 12.5px;
  line-height: 1.45;
}
.settings-callout.hidden { display: none; }

.crud-card {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
  gap: 12px;
}
.crud-card:hover {
  background: var(--surface-2);
  border-color: var(--border-2);
}

/* ── Artifacts — grid of previews, or the library table (his order, 2026-09-18) */
.files-gallery { display: block; margin-top: 4px; }
/* The toggle sits in the tab strip, beside the count. */
.skills-tabs .artifact-view-toggle { margin-left: 10px; }
.artifact-view-toggle {
  display: inline-flex; align-items: center; gap: 2px; padding: 2px;
  border: 1px solid var(--border); border-radius: 9px; background: var(--surface-2);
}
.artifact-view-btn {
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 26px; border: none; border-radius: 7px;
  background: none; color: var(--text-3); cursor: pointer;
}
.artifact-view-btn svg { width: 15px; height: 15px; }
.artifact-view-btn:hover { color: var(--text); background: var(--hover); }
.artifact-view-btn.active { background: var(--surface); color: var(--text-bright); border: 1px solid var(--border); }
.artifact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(216px, 1fr));
  gap: 14px;
  align-content: start;
}
.artifact-card {
  display: flex; flex-direction: column;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface-3); overflow: hidden;
  transition: border-color 0.15s, background 0.15s;
}
.artifact-card:hover { border-color: var(--border-2); background: var(--surface-2); }
/* The tile IS the preview: the picture itself, or the opening lines of the
   text, because a wall of identical file icons says nothing about which
   artifact is which. */
.artifact-tile {
  position: relative; height: 132px; cursor: pointer; overflow: hidden;
  background: var(--surface); border-bottom: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
}
.artifact-tile-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.artifact-tile-pre {
  margin: 0; padding: 10px 12px; width: 100%; height: 100%;
  font-family: var(--font-mono); font-size: 9.5px; line-height: 1.5;
  color: var(--text-2); white-space: pre-wrap; word-break: break-word;
  overflow: hidden;
  /* The text fades out rather than being cut mid-glyph. */
  mask-image: linear-gradient(to bottom, #000 58%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 58%, transparent 100%);
}
.artifact-tile-glyph { color: var(--text-3); }
.artifact-tile-glyph svg { width: 34px; height: 34px; }
.artifact-card-foot {
  display: flex; align-items: center; gap: 9px; padding: 9px 10px; cursor: pointer; min-width: 0;
}
.artifact-card-icon { display: flex; flex: 0 0 auto; color: var(--text-3); }
.artifact-card-icon svg { width: 15px; height: 15px; }
.artifact-card-text { display: flex; flex-direction: column; min-width: 0; gap: 1px; flex: 1 1 auto; }
.artifact-card-name {
  font-size: 12.5px; font-weight: 500; color: var(--text-bright);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.artifact-card-meta {
  font-size: 10.5px; color: var(--text-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.artifact-row-icon { display: inline-flex; vertical-align: -3px; margin-right: 8px; color: var(--text-3); }
.artifact-row-icon svg { width: 14px; height: 14px; }
.file-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: 10px;
  cursor: pointer;
  text-align: left;
  color: var(--text);
  transition: background 0.15s, border-color 0.15s;
  font: inherit;
}
.file-card:hover { background: var(--surface-2); border-color: var(--border-2); }
.file-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.file-card-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--accent);
}
.file-card-icon svg { width: 20px; height: 20px; }
.file-card-icon-image, .file-card-icon-pdf { color: var(--text-2); }
.file-card-body { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
.file-card-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-bright);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.file-card-meta {
  font-size: 11px;
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Agent identicon — used in the Agents list cards. */
.agent-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.agent-avatar-initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 13px;
  line-height: 1;
}

/* Layout list card — a row of app-icon squares on the left, one per distinct
   app in the layout, using the exact same icon as the Apps page. */
.layout-card-icons {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
/* Overlapping stack of app-icon squares (layout list + layout/drip edit
   heads). No rings/backgrounds — just the icons themselves, overlapped. */
.layout-card-icons .layout-app-icon + .layout-app-icon,
.edit-head-icons .layout-app-icon + .layout-app-icon,
.edit-head-icons .drip-emoji-icon + .drip-emoji-icon {
  margin-left: -9px;
}
/* Drip emoji icons (drips list + drip edit head), overlapping stack — no
   chip background, just the emoji at the same sizes as connection icons. */
.drip-emoji-icon {
  width: 24px; height: 24px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 18px; line-height: 1;
}
.edit-head .drip-emoji-icon { width: 40px; height: 40px; font-size: 26px; }
.drip-card-icons { display: flex; align-items: center; flex-shrink: 0; margin-right: 4px; }
.drip-card-icons .drip-emoji-icon + .drip-emoji-icon { margin-left: -9px; }

/* Icon sizes match the Connections page: 32px in the list tiles, 40px in the
   edit-form heads — for both layout icon stacks and drip emoji stacks. */
.app-card .layout-app-icon,
.app-card .layout-app-icon img,
.app-card .layout-app-initial { width: 32px; height: 32px; border-radius: 7px; }
.app-card .drip-emoji-icon { width: 32px; height: 32px; font-size: 22px; }
.app-card .layout-card-icons,
.app-card .drip-card-icons { margin-right: 0; }
.app-card .layout-card-icons .layout-app-icon + .layout-app-icon,
.app-card .drip-card-icons .drip-emoji-icon + .drip-emoji-icon { margin-left: -11px; }
.edit-head .layout-app-icon,
.edit-head .layout-app-icon img,
.edit-head .layout-app-initial { width: 40px; height: 40px; border-radius: 8px; }
.edit-head-icons .layout-app-icon + .layout-app-icon,
.edit-head-icons .drip-emoji-icon + .drip-emoji-icon { margin-left: -12px; }
.layout-app-icon {
  width: 24px;
  height: 24px;
  border-radius: 6px;
  overflow: hidden;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.layout-app-icon img { width: 24px; height: 24px; display: block; border-radius: 6px; }
.layout-app-initial {
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: var(--hover);
  color: var(--text-2);
  font-size: 11px;
  font-weight: 600;
}
/* Built-in workbench tool panels (Files/Terminal/Browser/…) in a layout: the
   VIEW_META glyph on a chip. currentColor = var(--text), so the stroke is WHITE
   in dark mode and dark in light. The SVG fills most of the tile so it's legible
   at every size the tile takes (24 / 32 / 40px). */
.layout-tool-icon { background: var(--hover); color: var(--text-2); }
.layout-tool-icon svg { width: 60%; height: 60%; max-width: 18px; max-height: 18px; display: block; }

/* ── Schedules ──────────────────────────────────────────── */

.sched-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  margin-bottom: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-radius: 6px;
  font-size: 12.5px;
  color: var(--text-2);
}
.sched-banner-text { flex: 1; }
.sched-awake-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  color: var(--text-2);
  font-size: 12px;
}

.sched-badge {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 4px;
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  color: var(--text-2);
  font-size: 10.5px;
  margin-right: 4px;
}
.sched-badge.freq { color: var(--text); border-color: rgba(175, 95, 255, 0.3); }
.sched-badge.ask  { color: var(--text-3); }

.sched-toggle {
  position: relative;
  width: 30px;
  height: 16px;
  display: inline-block;
  flex-shrink: 0;
}
.sched-toggle input { opacity: 0; width: 0; height: 0; position: absolute; }
.sched-toggle-track {
  position: absolute;
  inset: 0;
  background: var(--border-3);
  border-radius: 10px;
  transition: background 0.15s;
}
.sched-toggle-thumb {
  position: absolute;
  top: 2px; left: 2px;
  width: 12px; height: 12px;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.15s;
}
.sched-toggle input:checked + .sched-toggle-track { background: var(--accent); }
.sched-toggle input:checked + .sched-toggle-track .sched-toggle-thumb { transform: translateX(14px); }
.sched-toggle input:disabled + .sched-toggle-track { opacity: 0.4; cursor: not-allowed; }

.sched-history-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-radius: 6px;
  font-size: 12px;
  color: var(--text-2);
  cursor: pointer;
  text-align: left;
  transition: background 0.15s;
}
.sched-history-row:hover { background: var(--hover); }
.sched-history-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-faint);
  flex-shrink: 0;
}
.sched-history-dot.ok  { background: var(--accent); }
.sched-history-dot.err { background: var(--danger); }
.sched-history-empty {
  padding: 12px;
  font-size: 12px;
  color: var(--text-muted);
}

/* Store stat cards */
.store-stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  text-align: center;
}
.store-stat-value {
  font-size: 20px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.store-stat-label {
  font-size: 11px;
  color: var(--text-3);
  margin-top: 2px;
}
.data-clear-group {
  display: flex;
  align-items: center;
  gap: 0;
  flex-shrink: 0;
}
.data-clear-select {
  height: 30px;
  padding: 0 8px;
  font-size: 11px;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-right: none;
  border-radius: 6px 0 0 6px;
  color: var(--text-2);
  cursor: pointer;
  width: auto;
  min-width: 120px;
}
.data-clear-select:focus { outline: none; border-color: var(--border-3); }
.data-clear-group .action-btn {
  border-radius: 0 6px 6px 0;
  height: 30px;
  font-size: 11px;
  padding: 0 12px;
}

/* Dashboard (help landing page) */
.dash-header { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.dash-header h2 { margin: 0; }
.dash-provider { font-size: 11px; color: var(--text-3); background: var(--hover); padding: 4px 10px; border-radius: 6px; margin-left: auto; }
.dash-header #dash-refresh { font-size: 16px; padding: 2px 8px; line-height: 1; }

/* Two-tab dashboard (Home | Dashboard) + cowork landing */
.dash-tabs { display: inline-flex; gap: 2px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px; padding: 2px; margin-bottom: 18px; }
.dash-tab { background: transparent; border: none; color: var(--text-2); font: inherit; font-size: 13px; font-weight: 500; padding: 6px 16px; border-radius: 6px; cursor: pointer; }
.dash-tab:hover { color: var(--text); }
.dash-tab.active { background: var(--surface); color: var(--text); }
.dash-pane { display: none; }
.dash-pane.active { display: block; }

.dash-cowork-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-top: 16px; }
.dash-cowork-card { text-align: left; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 16px; cursor: pointer; transition: border-color 160ms ease, transform 160ms ease; }
.dash-cowork-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.dash-cowork-title { font-size: 15px; font-weight: 600; color: var(--text); margin-bottom: 4px; }
.dash-cowork-desc { font-size: 12px; color: var(--text-3); }
.dash-stat-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px; }
.dash-stat-card { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 16px 18px; }
.dash-stat-label { font-size: 11px; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 10px; }
.dash-stat-values { display: flex; gap: 20px; }
.dash-stat-item { display: flex; flex-direction: column; }
.dash-stat-num { font-size: 22px; font-weight: 600; color: var(--white); line-height: 1.2; font-variant-numeric: tabular-nums; }
.dash-stat-num.green { color: var(--text); }
.dash-stat-sub { font-size: 10px; color: var(--text-muted); margin-top: 2px; }
.dash-chart-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px; }
.dash-chart-stack { display: flex; flex-direction: column; gap: 12px; margin-bottom: 16px; }
.dash-chart-container { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 18px; }
.dash-chart-box { height: 200px; position: relative; }
.dash-range-toggle { display: flex; gap: 0; }
.dash-range-btn { background: var(--hover); border: 1px solid var(--border); color: var(--text-3); font-size: 11px; padding: 3px 10px; cursor: pointer; transition: all 0.15s; }
.dash-range-btn:first-child { border-radius: 4px 0 0 4px; }
.dash-range-btn:last-child { border-radius: 0 4px 4px 0; }
.dash-range-btn.active { background: var(--accent-bg); border-color: rgba(175, 95, 255, 0.27); color: var(--text); }
.dash-range-btn:hover:not(.active) { color: var(--text-2); }
.dash-section-head { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; margin-top: 24px; }
.dash-section-title { font-size: 13px; font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.5px; }
.dash-apps-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.dash-app-card { display: flex; align-items: center; gap: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 12px 14px; transition: border-color 0.15s; }
.dash-app-card:hover { border-color: var(--border-3); }
.dash-app-info { flex: 1; min-width: 0; }
.dash-app-name { font-size: 13px; font-weight: 500; color: var(--text-bright); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-app-date { font-size: 10px; color: var(--text-muted); margin-top: 2px; }
.dash-app-actions { display: flex; gap: 6px; }
.dash-app-actions button { background: none; border: none; color: var(--text-muted); cursor: pointer; padding: 4px; border-radius: 4px; transition: all 0.15s; }
.dash-app-actions button:hover { color: var(--text); background: var(--accent-bg); }
.dash-app-actions .dash-app-delete:hover { color: var(--danger-soft); background: var(--danger-bg); }
.dash-reminders-list { display: flex; flex-direction: column; gap: 6px; }
.dash-reminder-row { display: flex; align-items: center; gap: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 10px 14px; }
.dash-reminder-msg { flex: 1; font-size: 13px; color: var(--text-bright); }
.dash-reminder-time { font-size: 11px; color: var(--text); font-variant-numeric: tabular-nums; }
.dash-reminder-cancel { background: none; border: none; color: var(--text-muted); cursor: pointer; padding: 4px; border-radius: 4px; transition: all 0.15s; }
.dash-reminder-cancel:hover { color: var(--danger-soft); background: var(--danger-bg); }
.dash-empty-hint { font-size: 12px; color: var(--text-faint); padding: 16px; text-align: center; }
.dash-sources-bar { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 16px; }

/* Dashboard split columns (Token Metrics + Store Metrics) */
.dash-split-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
@container dash (max-width: 780px) { .dash-split-row { grid-template-columns: 1fr; } }
.dash-split-col {
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 16px;
  min-height: 200px; min-width: 0; overflow: hidden;
}

/* Daily Activity — full-width line chart above the two metric columns. */
.dash-activity-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  padding: 16px; margin-bottom: 16px; min-width: 0;
}
.dash-activity-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 14px; padding-bottom: 10px; border-bottom: 1px solid var(--border);
}
.dash-activity-head .dash-split-header { margin-bottom: 0; padding-bottom: 0; border-bottom: none; }
.dash-activity-chart-box { height: 240px; position: relative; }
.dash-split-header {
  font-size: 13px; font-weight: 600; color: var(--text-2); text-transform: uppercase;
  letter-spacing: 0.5px; margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--border);
}
.dash-split-subhead {
  font-size: 12px; font-weight: 600; color: var(--text-3); text-transform: uppercase;
  letter-spacing: 0.4px; margin: 16px 0 10px; padding-top: 12px; border-top: 1px solid var(--border);
}
.dash-split-col .dash-stat-row { gap: 8px; margin-bottom: 12px; }
.dash-split-col .dash-stat-card { padding: 12px 14px; }
.dash-split-col .dash-stat-num { font-size: 18px; }
.dash-split-col .dash-stat-values { gap: 14px; }
.dash-split-col .dash-chart-container { padding: 14px; }
.dash-split-col .dash-chart-box { height: 160px; }
.dash-split-col .crud-toolbar { margin-bottom: 10px; }
.dash-split-col .crud-cards { gap: 3px; }
.dash-split-col .crud-card { padding: 8px 12px; }
.dash-split-col .crud-card-name { font-size: 12px; }
.dash-split-col .crud-card-meta { font-size: 11px; }
.dash-split-col .crud-inline-form { padding: 0; }
.dash-split-col .crud-inline-header { margin-bottom: 10px; }

/* Dashboard data triggers — subheads that open a modal */
.dash-data-trigger { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.dash-data-trigger .action-btn { font-size: 11px; padding: 3px 10px; }

/* Dashboard modals — keep the data lists out of the main view */
.dash-modal { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; }
.dash-modal.hidden { display: none; }
.dash-modal-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.55); }
.dash-modal-panel {
  position: relative; background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  width: min(760px, 92vw); max-height: 86vh; display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
}
.dash-modal-head {
  display: flex; align-items: center; gap: 10px; padding: 14px 18px;
  border-bottom: 1px solid var(--border); flex: 0 0 auto;
}
.dash-modal-title {
  font-size: 13px; font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.5px;
}
.dash-modal-x { margin-left: auto; font-size: 14px; line-height: 1; padding: 4px 8px; }
.dash-modal-body { padding: 16px 18px; overflow-y: auto; flex: 1 1 auto; }

/* yo-modal — theme-aware confirm dialog (replaces native confirm()). */
/* Above the Echo dock layer (99000). The dock floats over the page, never over
   a modal: it was sitting on top of the Settings dialog (his report,
   2026-09-18), covering the tab strip and its close button. */
.yo-modal { position: fixed; inset: 0; z-index: 99500; display: flex; align-items: center; justify-content: center; }
.yo-modal-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(2px); }
.yo-modal-panel {
  position: relative; background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  width: min(420px, 90vw); padding: 22px 22px 18px; display: flex; flex-direction: column; gap: 12px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45); animation: yo-modal-in 120ms ease-out;
}
@keyframes yo-modal-in { from { opacity: 0; transform: translateY(6px) scale(0.98); } to { opacity: 1; transform: none; } }
.yo-modal-title { font-size: 15px; font-weight: 600; color: var(--text-bright); }
.yo-modal-message { font-size: 13px; line-height: 1.5; color: var(--text-2); }
.yo-modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; }
.yo-modal-btn {
  font-size: 13px; font-weight: 500; padding: 8px 16px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--border); transition: background 120ms, border-color 120ms;
}
.yo-modal-btn-cancel { background: var(--surface-2); color: var(--text); }
.yo-modal-btn-cancel:hover { background: var(--surface-3); border-color: var(--border-2); }
.yo-modal-btn-confirm { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }
.yo-modal-btn-confirm:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.yo-modal-btn-confirm:focus-visible { outline: 2px solid var(--accent-dark); outline-offset: 2px; }
.yo-modal-btn-danger { background: #e5484d; border-color: var(--danger); }
.yo-modal-btn-danger:hover { background: #d93a3f; border-color: #d93a3f; }

/* ── Settings modal (A1) — the two-column settings UI in a centered overlay
   instead of a full-page workbench section. Extends the .yo-modal backdrop. */
.yo-settings-modal .settings-modal-panel {
  /* NEVER a drag surface: an OS drag region eats clicks at the compositor
     level regardless of z-index, and in short windows the panel's top strip
     (where close/expand live) can reach into the titlebar band. */
  -webkit-app-region: no-drag;
  /* Wide enough for the side-by-side editors (620px controls + a usable
     right pane) that Apps/Connections/Loops/Skills/Agents/Layouts carry —
     trimmed from 1240x848 so the modal doesn't loom over the whole app. */
  width: min(1120px, 92vw);
  height: min(800px, 90vh);
  max-width: min(1120px, 92vw);
  max-height: min(800px, 90vh);
  padding: 0;
  gap: 0;
  overflow: hidden;
  animation: yo-modal-in 130ms ease-out;
}
.settings-modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text-3);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.settings-modal-close:hover { background: var(--active-bg); color: var(--text); }
/* Expand/collapse (fullscreen) toggle — same icon-button voice as the X, one
   slot to its left (12px edge + 30px X + 8px gap). Session-local: the state
   lives on the panel node, which is removed on close. */
.settings-modal-max { right: 50px; }
/* Fullscreen is PINNED with fixed insets — flex-centering + margin math let
   the top/bottom drift out of bounds. It also stops BELOW the native titlebar:
   the drag strip is an OS drag region that eats clicks at the compositor level
   regardless of z-index (the expand/close buttons were unclickable inside it).
   Web (--titlebar-h: 0) gets true fullscreen. */
.yo-settings-modal .settings-modal-panel.fullscreen {
  position: fixed;
  inset: var(--titlebar-h, 0px) 0 0 0;
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  margin: 0;
  border-radius: 0;
}
/* The floating expand + close buttons own the modal's top-right corner — page
   toolbars AND inline-editor headers keep their right-edge primary action
   CLEAR of them (the Layouts list toolbar, and the layout EDITOR's "Open
   layout" button, both sat under the X). 84px = 12 edge + 30 X + 8 gap + 30
   expand + 4 breathing room. */
.settings-modal-body .crud-toolbar,
.settings-modal-body .crud-inline-header { padding-right: 84px; }
.settings-modal-close svg { width: 17px; height: 17px; }
.settings-modal-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  height: 100%;
}
/* The adopted .settings-layout fills the modal body; its inner .settings-panels
   keeps its own scroll, matching the full-page section. */
.settings-modal-body .settings-layout {
  flex: 1;
  min-height: 0;
  height: 100%;
}
.settings-modal-body .settings-nav {
  padding-top: 14px;
}
/* Keep the right column clear of the floating close button on its first row. */
.settings-modal-body .settings-panels {
  padding-top: 16px;
}

/* Adopted full-page sections in the modal (Apps, Connections, Loops, Skills,
   Agents, Layouts). The WHOLE .help-section node is adopted into the host, so
   the panel becomes a flex column that gives the section its full-height
   context. These rules make the adopted section read as a NATIVE settings
   panel: same gutters, left-aligned full-width content, ONE scroll container. */
.settings-modal-body .settings-panels .settings-panel-section {
  padding: 0;
  height: 100%;
}
.settings-modal-body .settings-panels .settings-panel-section.active {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.settings-modal-body .settings-panel-section > [id$="-host"] {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
/* The adopted section IS the scroll container — matches a native .settings-panel
   inside .settings-panels (padding: 8px 28px, top bumped to 16px for the close
   button). The outer .settings-panels padding is zeroed below so this is the
   ONLY gutter (no double edge) and the ONLY vertical scrollbar (no double bar). */
.settings-modal-body .settings-panel-section > [id$="-host"] > .help-section {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 16px 28px 20px;
  box-sizing: border-box;
}
/* When a full-width inline FORM is open (the agent form), the section stops
   scrolling and drops its right gutter — the form becomes the scroller, its
   own right padding restores the inset, and the scrollbar sits flush at the
   page's right edge instead of 28px inboard. */
.settings-modal-body .settings-panel-section > [id$="-host"] > .help-section:has(> #agent-form:not(.hidden)) {
  overflow: hidden;
  padding-right: 0;
  display: flex;
  flex-direction: column;
}
.settings-modal-body .help-section #agent-form.crud-inline-form {
  flex: 1;
  min-height: 0;
  padding-right: 28px;
}
/* Normalize the adopted section's page header to the NATIVE settings-panel
   grammar (18px title + 4px gap + 13px description) — one header voice on
   every page. (These h2s were previously display:none'd, which left the
   adopted pages the only headerless pages in the modal.) Only the DIRECT-child
   page header (and Apps' library heading) is restyled; deeper functional
   <h2>s (marketplace banner, editors) are untouched. */
.settings-modal-body .settings-panel-section > [id$="-host"] > .help-section > h2,
.settings-modal-body .settings-panel-section .apps-page-heading {
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: 0;
  margin: 0 0 4px;
}
.settings-modal-body .settings-panel-section > [id$="-host"] > .help-section > .section-desc,
.settings-modal-body .settings-panel-section #apps-library-page > .section-desc {
  margin: 0 0 16px;
}
.settings-modal-body .settings-panel-section .apps-page-heading { margin-top: 0; }
/* Editors align to the page gutter inside the modal — their legacy full-page
   16px inner insets would double the left edge here. The RIGHT edge keeps the
   floating-buttons clearance (this rule out-specifies the generic clearance
   above, so it must carry the 84px itself — padding-right:0 here was why the
   Layouts editor's "Open layout" button kept landing under the X). */
.settings-modal-body .settings-panel-section .crud-inline-header,
.settings-modal-body .settings-panel-section .edit-head {
  padding-left: 0;
  padding-right: 84px;
}
/* The adopted section owns the gutter + scroll now, so the panels wrapper adds
   neither when a section is active — no double padding, no double scrollbar. */
.settings-modal-body .settings-panels:has(.settings-panel-section.active) {
  padding: 0;
  overflow-y: hidden;
}
/* Narrow modal — below this the modal is viewport-bound (96vw) and the
   side-by-side editors (Apps/Connections builder split, the Loops/Skills/
   Agents lib splits, the Layouts builder) would squeeze their right pane
   into a sliver. Stack them vertically instead; the page scrolls as one
   column. The !importants out-rank the drag-divider's inline width. */
@media (max-width: 1140px) {
  #settings-modal .app-builder-split,
  #settings-modal .lib-split {
    flex-direction: column;
    align-items: stretch;
    overflow: visible;
  }
  #settings-modal .app-builder-controls {
    width: auto !important;
    overflow-y: visible;
    padding-right: 0;
  }
  #settings-modal .app-builder-divider,
  #settings-modal .lib-split-divider { display: none; }
  #settings-modal .lib-split-form {
    width: auto !important;
    padding-right: 0;
  }
  #settings-modal .lib-split-flow {
    position: static;
    height: 380px;
    margin-left: 0;
    flex: none;
  }
  #settings-modal .lib-split-side { margin-left: 0; }
  #settings-modal .app-builder-preview { min-height: 340px; }
  /* The connection detail wrapper clips (overflow:hidden) in the wide split;
     stacked, it becomes the scroller instead. */
  #settings-modal #conn-detail { overflow-y: auto; }
}

.pagination-bar {
  display: flex; align-items: center; justify-content: center; gap: 12px; padding: 8px 0;
}
.pagination-bar .action-btn { min-width: 32px; padding: 4px 8px; }
.pagination-bar .action-btn:disabled { opacity: 0.25; pointer-events: none; }
.pagination-label { font-size: 11px; color: var(--text-2); font-variant-numeric: tabular-nums; }

.dash-pre-block {
  background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 12px;
  color: var(--text); font-size: 12px; font-family: var(--font-mono);
  white-space: pre-wrap; word-break: break-word; max-height: 30vh; overflow-y: auto;
}

.dash-prompt-meta-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 6px; margin-bottom: 8px;
}
.dash-prompt-meta-grid .dash-meta-item {
  background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px;
}
.dash-prompt-meta-grid .dash-meta-label {
  font-size: 10px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.3px; margin-bottom: 3px;
}
.dash-prompt-meta-grid .dash-meta-value {
  font-size: 12px; color: var(--text-bright); font-weight: 500; font-variant-numeric: tabular-nums;
}

/* CRUD form */
.crud-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  flex: 1;
  min-height: 0;
}

.crud-form-error {
  background: var(--danger-bg);
  border: 1px solid var(--danger);
  border-radius: 8px;
  padding: 10px 14px;
  color: var(--danger-soft);
  font-size: 13px;
}

.crud-form-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.crud-form-field-grow {
  flex: 1;
  min-height: 0;
}

.crud-form-label {
  font-size: 12px;
  color: var(--text-2);
  font-weight: 500;
}

.crud-input {
  width: 100%;
  padding: 10px 14px;
  font-size: 13px;
  color: var(--white);
  -webkit-text-fill-color: var(--white);
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 6px;
  outline: none;
  font-family: inherit;
  transition: border-color 0.15s;
  box-sizing: border-box;
  resize: vertical;
}
.crud-input:focus { border-color: var(--accent); }
.crud-input::placeholder { color: var(--text-muted); -webkit-text-fill-color: var(--text-muted); }

.crud-textarea-grow {
  width: 100%;
  flex: 1;
  min-height: 80px;
  padding: 10px 14px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--white);
  -webkit-text-fill-color: var(--white);
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 6px;
  outline: none;
  resize: vertical;
  font-family: var(--font-mono);
  transition: border-color 0.15s;
}
.crud-textarea-grow:focus { border-color: var(--accent); }
.crud-textarea-grow::placeholder { color: var(--text-faint); -webkit-text-fill-color: var(--text-faint); }

.crud-form-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}

.crud-inline-form {
  max-width: 620px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
  min-height: 0;
}
.crud-inline-form .settings-actions,
#app-detail .settings-actions {
  justify-content: flex-end;
}
.crud-inline-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 0;   /* was -4px — pulled the breadcrumb above the form's scroll top and clipped it */
}

/* In a CRUD detail/edit view, hide the list page header (H2 + description) so
   only the form + its breadcrumb show. Skip dashboard (its inline detail sits
   under charts, not a plain list). */
.help-section:not([data-section="dashboard"]):has(.crud-inline-form:not(.hidden)) > h2,
.help-section:not([data-section="dashboard"]):has(.crud-inline-form:not(.hidden)) > .section-desc {
  display: none;
}
/* Same rule for SETTINGS PANELS whose h2/description are direct children (the
   super-admin Orgs page — his report, 2026-09-01: the list title must not show
   over the detail view). */
.settings-panel:has(.crud-inline-form:not(.hidden)) > h2,
.settings-panel:has(.crud-inline-form:not(.hidden)) > .section-desc {
  display: none;
}
.crud-breadcrumb-back {
  color: var(--text-2);
  cursor: pointer;
  transition: color 0.15s;
  text-decoration: none;
  font-size: 13px;
  font-weight: 400;
}
.crud-breadcrumb-back:hover { color: var(--white); }
.crud-spacer { flex: 1; }

.crud-form-status {
  font-size: 12px;
  color: var(--text-2);
  min-height: 18px;
}

/* Sub-list (collapsible steps/items) */
.crud-sub-list {
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

.crud-sub-header {
  display: flex;
  align-items: center;
  padding: 10px 14px;
  background: var(--surface-3);
  cursor: pointer;
  user-select: none;
  gap: 8px;
}

.crud-sub-title {
  font-size: 13px;
  color: var(--text);
  font-weight: 500;
}

.crud-sub-count {
  font-size: 11px;
  color: var(--text-muted);
  background: var(--surface-2);
  padding: 1px 7px;
  border-radius: 10px;
}

.crud-sub-body {
  border-top: 1px solid var(--border);
}

.crud-sub-body.collapsed {
  display: none;
}

.crud-sub-add-form {
  padding: 10px 14px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* ── Standard action buttons ────────────────────────────── */

.action-btns {
  display: flex;
  gap: 6px;
}

.action-btn {
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  color: var(--text-2);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  padding: 5px 14px;
  height: 30px;
  box-sizing: border-box;
  border-radius: 5px;
  transition: all 0.15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}

.action-btn:hover:not(:disabled) { color: var(--white); background: var(--hover); border-color: var(--text-faint); }
.action-btn:disabled { opacity: 0.3; cursor: default; }
.action-btn.secondary {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-2);
}
.action-btn.secondary:hover:not(:disabled) {
  background: var(--surface);
  color: var(--text);
  border-color: var(--white);
  box-shadow: 0 0 0 1px var(--white);
}
.action-btn.danger { color: var(--danger); border-color: var(--danger-bg); }
.action-btn.danger:hover { color: var(--danger); background: var(--danger-bg); border-color: var(--danger); }
/* The primary rests FILLED with the accent. The old law was WHITE TEXT IN
   EVERY THEME (2026-09-16); it is gone (his order, 2026-09-18), because the
   neutral dark accent is a light grey and white on it is unreadable, hover
   worst of all. The label takes the accent's own contrast colour, which every
   theme now declares. */
.action-btn.primary {
  background: var(--grad-accent);
  border: none;
  color: var(--accent-fg);
}
.action-btn.primary:hover:not(:disabled) { color: var(--accent-fg); background: var(--accent-hover); border-color: transparent; }
.action-btn.primary:disabled { color: var(--accent-fg); opacity: 0.45; }

.inline-empty {
  padding: 32px 16px;
  text-align: center;
  color: var(--text-3);
  font-size: 13px;
}

.editor-area {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-2);
  border-radius: 8px;
  overflow: hidden;
  margin-top: 12px;
}

.editor-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  color: var(--text-3);
}


.editor-area textarea {
  min-height: 180px;
  background: var(--surface-3);
  border: none;
  padding: 12px;
  color: var(--text);
  font-size: 13px;
  font-family: var(--font-mono);
  line-height: 1.6;
  resize: none;
  outline: none;
}

.editor-area textarea::placeholder { color: var(--text-3); }

/* ── Layout panel picker ─────────────────────────────────── */

/* ── Grid builder ──────────────────────────────────────────── */

.grid-builder {
  padding: 12px;
}

/* ── Loop detail: editable default-model pickers ── */
.task-model-list { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.task-model-row { display: flex; align-items: center; gap: 10px; }
.task-model-label {
  flex: 0 0 120px; font-size: 12px; color: var(--text-2);
  text-align: right; text-transform: capitalize;
}
.task-model-select { max-width: 300px; }
.settings-hint.danger { color: var(--danger, #f87171); }

/* ── Layout editor: the loop + its per-slot model pickers ── */
.layout-loop-row { display: flex; flex-direction: column; gap: 10px; }
/* App setup — the layout editor uses the Apps form's OWN split classes
   (.app-builder-split/-controls/-preview): fixed 620px form column left, the
   dynamic pane fills the right, full height. This pane just pads it. */
/* The editor container is a crud-inline-form, which caps at 620px — the very
   reason no right pane could ever exist. Full width like the Apps editor. */
#layout-editor.crud-inline-form { max-width: none !important; }
.layout-setup-pane { padding: 14px 16px; overflow-y: auto; flex: 1; min-height: 0; }
.layout-setup-pane .settings-hint { margin: 0; }
.layout-cell-config-row { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.layout-cell-config-label { font-size: 12px; color: var(--text-2); }
.layout-cell-config-row .settings-input { width: 100%; }
/* The setup pane reuses the Settings switch row (.settings-toggle) and its
   stack container — only the page-level margin/width caps come off, so the
   pane can never drift from the toggles everywhere else. */
.layout-cell-config-row .settings-toggles { margin-top: 2px; max-width: none; gap: 8px; }
.layout-cell-config-row .settings-toggle { padding: 8px 12px; }

/* Working-folder field — the picker + clear ride INSIDE the input's right edge. */
.layout-folder-row { position: relative; max-width: 480px; }
.layout-folder-row .settings-input { width: 100%; padding-right: 66px; text-overflow: ellipsis; }
.layout-folder-icon {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
  border: none; border-radius: 6px; background: transparent; color: var(--text-3); cursor: pointer;
}
.layout-folder-icon:hover { background: var(--surface-3); color: var(--text); }
#layout-folder-pick, .layout-folder-icon.pick { right: 34px; }
#layout-folder-clear, .layout-folder-icon.clear { right: 6px; }
.layout-loop-row > #layout-loop-select { max-width: 340px; }
.layout-loop-models { display: flex; flex-direction: column; gap: 8px; }
.layout-loop-model { display: flex; align-items: center; gap: 10px; }
.layout-loop-model-label {
  flex: 0 0 120px; font-size: 12px; color: var(--text-2);
  text-align: right; text-transform: capitalize;
}
.layout-loop-model select { max-width: 300px; }

.grid-dims {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}

.grid-dims label {
  font-size: 12px;
  color: var(--text-3);
  display: flex;
  align-items: center;
  gap: 4px;
}

.grid-dims select {
  background: var(--border);
  color: var(--text);
  border: 1px solid var(--border-3);
  border-radius: 4px;
  padding: 4px 6px;
  font-size: 12px;
  font-family: inherit;
}

.dim-sep {
  color: var(--text-3);
  font-size: 14px;
}

#grid-preview {
  display: grid;
  gap: 4px;
  min-height: 120px;
}

.grid-cell {
  /* Subtle gray transparent fill — works in both light and dark modes. */
  background: color-mix(in srgb, var(--text) 4%, transparent);
  border: 2px solid var(--border-3);
  border-radius: 6px;
  padding: 12px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-family: var(--font-mono);
  color: var(--text-2);
  min-height: 56px;
  transition: all 0.15s;
  user-select: none;
}

.grid-cell:hover {
  border-color: rgba(255, 255, 255, 0.55);
}

.grid-cell.selected {
  border-color: #fff;
  box-shadow: 0 0 0 1px #fff;
}

/* Assigned cells: white ring, same neutral fill. */
.grid-cell.assigned {
  color: var(--text);
  background: color-mix(in srgb, var(--text) 5%, transparent);
  border-color: #fff;
}
/* Sticky cell: the app-switch target — accent ring + a pin badge. */
.grid-cell.sticky {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
.grid-cell-sticky {
  position: absolute;
  top: 4px; left: 4px;
  display: inline-flex;
  color: var(--accent);
}
.grid-cell-sticky svg { width: 13px; height: 13px; }
/* The grip — drag a panel to another cell to swap the two. Hidden until the
   cell is hovered so the tiny cells stay legible. */
.grid-cell-handle {
  position: absolute; top: 0; left: 0; right: 0; height: 16px;
  display: flex; align-items: center; justify-content: center;
  cursor: grab; color: var(--text-3); opacity: 0; transition: opacity 0.12s;
}
.grid-cell-handle:active { cursor: grabbing; }
.grid-cell-handle svg { width: 16px; height: 16px; }
.grid-cell:hover .grid-cell-handle { opacity: 0.9; }
.grid-cell { user-select: none; }
.grid-cell.draggable-cell { cursor: grab; }
body.grid-cell-dragging, body.grid-cell-dragging * { cursor: grabbing !important; }
/* The dragged cell dims in place; its ghost rides the cursor. */
.grid-cell.dragging { opacity: 0.35; }
.grid-drag-ghost {
  position: fixed;
  z-index: 3000;
  pointer-events: none;
  opacity: 0.85;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
}
/* Drop zones: mid-cell = swap (full ring); the edges = insert before/after
   in reading order (an accent bar on the receiving edge). */
.grid-cell.drop-swap { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.grid-cell.drop-before { box-shadow: inset 3px 0 0 var(--accent); border-color: var(--accent); }
.grid-cell.drop-after { box-shadow: inset -3px 0 0 var(--accent); border-color: var(--accent); }
.grid-cell { position: relative; }

/* Cell panel picker dropdown */
.cell-panel-picker {
  /* The workspace editor lives INSIDE the settings modal now; a body-level
     picker with no stacking order landed under it and took no clicks
     (his report, 2026-09-19). Above the modal, below the toasts. */
  z-index: 999999;
  position: fixed;
  background: var(--surface-2);
  border: 1px solid var(--border-3);
  border-radius: 8px;
  padding: 4px;
  min-width: 160px;
  box-shadow: 0 8px 24px var(--overlay-bg);
  display: flex;
  flex-direction: column;
}

.cell-panel-search {
  display: block;
  width: calc(100% - 20px);
  margin: 4px;
  padding: 5px 8px;
  background: var(--hover);
  border: 1px solid var(--border-3);
  border-radius: 4px;
  color: var(--text);
  font-size: 12px;
  outline: none;
  font-family: inherit;
}

.cell-panel-search:focus {
  border-color: var(--text-muted);
}

.cell-panel-options {
  max-height: 200px;
  overflow-y: auto;
}

.cell-panel-option {
  padding: 8px 12px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  border-radius: 4px;
  font-family: var(--font-mono);
}

.cell-panel-option:hover {
  background: var(--hover);
  color: var(--white);
}

.cell-panel-option.empty {
  color: var(--text-3);
  font-family: inherit;
  font-style: italic;
}
/* Group headers in the cell picker (Workbench tools / Apps). */
.cell-panel-group-label {
  padding: 8px 12px 3px;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-3);
}
/* Sticky toggle in the cell picker — marks this panel as the app-switch target. */
.cell-panel-sticky {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  margin-top: 4px;
  padding: 8px 10px;
  border: none;
  border-top: 1px solid var(--border);
  background: none;
  color: var(--text-2);
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
}
.cell-panel-sticky svg { width: 15px; height: 15px; flex-shrink: 0; }
.cell-panel-sticky:hover { background: var(--hover); color: var(--text); }
.cell-panel-sticky.on { color: var(--accent); }

/* ── Apps ────────────────────────────────────────────────── */

#apps-list {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}


/* ── Pagination ─────────────────────────────────────────── */

.pagination-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 0 4px;
  border-top: 1px solid var(--border);
  margin-top: 12px;
}

.pagination-info {
  font-size: 12px;
  color: var(--text-3);
}

.pagination-nav {
  display: flex;
  align-items: center;
  gap: 2px;
}

.pagination-btn {
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
  color: var(--text-2);
  font-size: 12px;
  padding: 4px 8px;
  cursor: pointer;
  transition: all 0.15s;
  min-width: 28px;
  text-align: center;
}

.pagination-btn:hover:not(:disabled) {
  background: var(--surface-2);
  border-color: var(--border-2);
  color: var(--text);
}

.pagination-btn.active {
  background: var(--surface-2);
  border-color: var(--accent);
  color: var(--text);
}

.pagination-btn:disabled {
  opacity: 0.3;
  cursor: default;
}

.pagination-ellipsis {
  color: var(--text-faint);
  font-size: 12px;
  padding: 0 4px;
}

/* App detail view */

/* ── App builder split layout ───────────────────────────── */
.app-builder-split {
  display: flex;
  gap: 0;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.app-builder-controls {
  width: 620px;
  flex-shrink: 0;
  overflow-y: auto;
  /* Left edge on the page gutter (the tabs row above starts there too);
     right padding keeps a scrollbar gap from the divider. */
  padding: 12px 16px 12px 0;
}
/* Uniform vertical spacing for EVERY field in the edit forms (app editor +
   connection editor), including the nested Type/native sub-fields — 20px above
   each label, 6px below (label→input gap). First field sits snug to the top. */
.app-builder-controls .settings-label,
.app-builder-preview .settings-label { margin-top: 20px; margin-bottom: 6px; }
/* Conditional field groups (Type→browser/native, archetype, MCP transport,
   OIDC…) are plain block wrappers toggled with .hidden. As blocks, the first
   label's 20px top margin COLLAPSES through the wrapper edge and renders as a
   ~4px gap — the fields look jammed even though the margin computes at 20px.
   Laying the wrappers out as flex columns (same as the parent .app-tab-left)
   preserves every child margin. :not(.hidden) keeps the id selector from
   overriding the .hidden toggle. */
#app-add-browser-fields:not(.hidden), #app-add-native-fields:not(.hidden),
#app-add-terminal-fields:not(.hidden), #app-add-editor-fields:not(.hidden),
#app-add-generic-fields:not(.hidden),
#app-detail-browser-fields:not(.hidden), #app-detail-native-fields:not(.hidden),
#app-detail-terminal-fields:not(.hidden), #app-detail-editor-fields:not(.hidden),
#app-detail-generic-fields:not(.hidden),
#app-mcp-oauth-fields:not(.hidden), #app-mcp-sse-fields:not(.hidden),
#app-mcp-stdio-fields:not(.hidden),
#mcp-add-sse-fields:not(.hidden), #mcp-add-stdio-fields:not(.hidden),
#proxy-oidc-fields:not(.hidden), #proxy-visibility-wrap:not(.hidden) {
  display: flex;
  flex-direction: column;
}
.app-builder-controls .app-tab-left > .settings-label:first-child,
.app-builder-controls > .edit-head + .settings-label,
.app-builder-controls > .settings-label:first-child { margin-top: 4px; }
/* The General tab panel is a flex column with a 10px gap, which ADDED to the
   label margins — top-level fields sat 30px apart while nested (browser/
   native) fields sat 20px. Kill the gap so margins alone set one rhythm. */
.app-builder-controls .app-tab-left[data-tab="dashboard"] { gap: 0; }
.app-detail-preview-wrap {
  border: 1px solid var(--border-2);
  border-radius: 6px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: 320px;
}
.app-detail-preview-wrap webview {
  flex: 1;
  min-height: 0;
}

.app-builder-divider,
.lib-split-divider {
  width: 1px;
  background: var(--border-2);
  cursor: col-resize;
  position: relative;
  flex-shrink: 0;
}
.app-builder-divider::after,
.lib-split-divider::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -3px;
  width: 7px;
}
.app-builder-divider:hover,
.app-builder-divider.dragging,
.lib-split-divider:hover,
.lib-split-divider.dragging {
  /* Purple when grabbed — the affordance IS the highlight. */
  background: var(--accent);
}

.app-builder-preview {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* ── App detail tabs ─────────────────────────────────── */

.app-detail-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--border);
  /* No lead-in inset — tab rows start on the same left edge as the page
     header and form fields (one gutter everywhere: Apps/Layouts editors,
     Models, Workspaces). The tab button's own padding shapes the pill. */
  padding: 0;
  flex-shrink: 0;
}

.app-detail-tab {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-3);
  font-size: 13px;
  font-weight: 500;
  padding: 10px 16px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
  white-space: nowrap;
}

.app-detail-tab:hover { color: var(--text); }
.app-detail-tab.active { color: var(--text); border-bottom-color: var(--accent); }
.app-detail-tab.tab-hidden { display: none; }

.app-tab-left,
.app-tab-right {
  display: none;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
}

.app-tab-left.active,
.app-tab-right.active {
  display: flex;
  flex: 1;
}

/* General tab: separates the app form from the pick-elements/commands
   section rendered below it (was its own "Panel" tab). */
.app-detail-section-sep {
  border-top: 1px solid var(--border);
  margin: 16px 0;
}

/* Config Vars tab: one row per var — key, masked value, delete. Values are
   write-only (encrypted at save); the mask is a constant, not the length. */
.config-var-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 6px;
  background: var(--surface, transparent);
}
.config-var-key {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  overflow-wrap: anywhere;
}
.config-var-masked {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-3);
  letter-spacing: 2px;
}

/* ── Dashboard placeholder ────────────────────────────── */

/* App dashboard right panel — compact sizing like dash-split-col */
.app-tab-right[data-tab="dashboard"] { padding: 16px; gap: 0; }
.app-tab-right[data-tab="dashboard"] .dash-stat-row { gap: 8px; margin-bottom: 12px; }
.app-tab-right[data-tab="dashboard"] .dash-stat-card { padding: 12px 14px; }
.app-tab-right[data-tab="dashboard"] .dash-stat-num { font-size: 18px; }
.app-tab-right[data-tab="dashboard"] .dash-stat-values { gap: 14px; }
.app-tab-right[data-tab="dashboard"] .dash-chart-container { padding: 14px; }
.app-tab-right[data-tab="dashboard"] .dash-chart-box { height: 160px; }
.app-tab-right[data-tab="dashboard"] .crud-toolbar { margin-bottom: 10px; }
.app-tab-right[data-tab="dashboard"] .crud-cards { gap: 3px; }
.app-tab-right[data-tab="dashboard"] .crud-card { padding: 8px 12px; }
.app-tab-right[data-tab="dashboard"] .crud-card-name { font-size: 12px; }
.app-tab-right[data-tab="dashboard"] .crud-card-meta { font-size: 11px; }
.app-tab-right[data-tab="dashboard"] .crud-inline-form { padding: 0; }
.app-tab-right[data-tab="dashboard"] .crud-inline-header { margin-bottom: 10px; }
.app-tab-right[data-tab="dashboard"] .dash-split-header { margin-bottom: 12px; }
.app-tab-right[data-tab="dashboard"] .dash-split-subhead { margin: 16px 0 10px; padding-top: 12px; border-top: 1px solid var(--border); }
.app-tab-right[data-tab="dashboard"] .dash-chart-stack { margin-bottom: 0; }

.app-dash-icon {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  background: var(--hover);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 600;
  color: var(--text-2);
  overflow: hidden;
}

.app-dash-icon img {
  width: 100%;
  height: 100%;
  border-radius: 12px;
}

/* ── App card badge (MCP-only) ────────────────────────── */

.app-card { position: relative; }

.app-card-badge {
  position: absolute;
  top: 6px;
  right: 6px;
  font-size: 8px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding: 1px 5px;
  border-radius: 3px;
  background: rgba(74, 158, 255, 0.15);
  color: var(--blue);
}

.app-card-badge.badge-connection {
  background: rgba(175, 95, 255, 0.15);
  color: var(--text);
}
/* Governance: connected but the caller's agents can't use it. */
.app-card-badge.badge-blocked {
  background: rgba(212, 74, 74, 0.16);
  color: var(--text);
}

/* ── + New dropdown menu ──────────────────────────────── */

.apps-add-dropdown { position: relative; }

.apps-add-menu {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 4px;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-radius: 8px;
  padding: 4px;
  z-index: 10;
  min-width: 170px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.4);
}

.apps-add-menu button {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  color: var(--text);
  font-size: 13px;
  padding: 8px 12px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s;
}

.apps-add-menu button:hover { background: var(--hover); }

/* ── Connection tab ───────────────────────────────────── */

.connection-status {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 12px;
}

.connection-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.connection-status-dot.connected { background: var(--accent); }
.connection-status-dot.disconnected { background: var(--text-faint); }

.connection-status-info {
  flex: 1;
  min-width: 0;
}

.connection-status-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}

.connection-status-meta {
  font-size: 11px;
  color: var(--text-3);
}

/* ── Connection browse section ────────────────────────── */

.connection-browse {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.connector-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 8px;
}

.connector-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 14px 10px;
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color 0.15s;
  text-align: center;
}

.connector-card:hover { border-color: var(--accent); }

.connector-card-icon {
  width: 32px;
  height: 32px;
  border-radius: 6px;
  flex-shrink: 0;
}

.connector-card-initial {
  width: 32px;
  height: 32px;
  border-radius: 6px;
  background: var(--surface-2);
  color: var(--text-3);
  font-size: 14px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.connector-card-info { min-width: 0; width: 100%; }

.connector-card-name {
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
}

.connector-card-desc {
  font-size: 10px;
  color: var(--text-3);
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.connector-load-more {
  text-align: center;
  padding: 10px;
  color: var(--text);
  cursor: pointer;
  font-size: 12px;
  font-weight: 500;
  border: 1px dashed var(--border-3);
  border-radius: 8px;
  background: none;
  width: 100%;
}

.connector-load-more:hover { background: var(--active-bg); }

/* ── Connected apps list ─────────────────────────────── */

.connected-app-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 6px;
  cursor: pointer;
  transition: border-color 0.15s;
}

.connected-app-row:hover { border-color: var(--accent); }
.connected-app-row.active { border-color: var(--accent); background: var(--active-bg); }

.connected-app-icon {
  width: 24px;
  height: 24px;
  border-radius: 4px;
  flex-shrink: 0;
}

.connected-app-name {
  flex: 1;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}

.connected-app-status {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--accent);
}

.preview-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.preview-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}

.preview-action {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 11px;
  cursor: pointer;
  padding: 2px 8px;
  border-radius: 3px;
  transition: all 0.15s;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.preview-action:hover { color: var(--white); background: var(--border-2); }
.preview-action-visible {
  color: var(--text-2);
  border: 1px solid var(--border-3);
  padding: 3px 10px;
}
.preview-action-visible:hover { color: var(--white); border-color: var(--text-muted); }

#app-preview {
  flex: 1;
  border: none;
  background: var(--bg);
}
/* WEB surface app-editor preview — a browser has no <webview>, so the pane
   renders a sandboxed iframe (or an honest fallback card) in the same slot.
   The inert webview element is hidden outright on web. */
.glyphh-web #app-preview { display: none; }
.app-preview-frame {
  flex: 1;
  min-height: 0;
  width: 100%;
  border: none;
  background: var(--bg);
}
.app-preview-fallback {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.app-preview-fallback-card {
  max-width: 400px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
}
.app-preview-fallback-card p {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-2);
}

.app-detail-option {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-2);
  margin-top: 10px;
  cursor: pointer;
}
.app-detail-option input[type="checkbox"] { accent-color: var(--accent); }
.app-detail-option-hint { color: var(--text-muted); }

/* ── Help form inputs ──────────────────────────────────── */
.help-input {
  padding: 6px 10px;
  font-size: 13px;
  background: var(--bg);
  border: 1px solid var(--border-2);
  border-radius: 4px;
  color: var(--text);
  outline: none;
  font-family: var(--font-mono);
}
.help-input:focus { border-color: var(--accent); }
.help-input::placeholder { color: var(--text-muted); }

.help-select {
  padding: 6px 10px;
  font-size: 13px;
  background: var(--bg);
  border: 1px solid var(--border-2);
  border-radius: 4px;
  color: var(--text);
  outline: none;
  font-family: var(--font-mono);
}
.help-select:focus { border-color: var(--accent); }

/* ── Rips ─────────────────────────────────────────────── */

.rip-run-action {
  background: var(--blue);
  border-color: var(--blue);
  color: var(--white);
  flex-shrink: 0;
}
.rip-run-action:hover:not(:disabled) { background: var(--blue); border-color: var(--blue); opacity: 1; color: var(--white); }
.rip-run-action:disabled { opacity: 0.4; }

/* Step list */
#rip-steps-list { display: flex; flex-direction: column; gap: 4px; }

/* Collapsed step */
.rip-step {
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  cursor: grab;
  transition: opacity 0.15s, border-color 0.15s;
}
.rip-step:hover { border-color: var(--border-2); }
.rip-step.dragging { opacity: 0.3; }
.rip-step.drag-over { border-top: 2px solid var(--accent); }

.rip-step-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  cursor: pointer;
  user-select: none;
}
.rip-step-header:hover { background: var(--surface-2); }

.rip-step-num {
  font-size: 10px; color: var(--text-muted); font-weight: 600;
  min-width: 16px; height: 16px;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-2); border-radius: 3px; flex-shrink: 0;
}
.rip-step-summary { flex: 1; font-size: 12px; color: var(--text); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rip-step-summary .rip-step-type-tag { color: var(--text); font-weight: 500; }
.rip-step-summary .rip-step-meta { color: var(--text-muted); margin-left: 6px; font-size: 11px; }

.rip-step-remove {
  opacity: 0; transition: opacity 0.15s; flex-shrink: 0;
}
.rip-step-header:hover .rip-step-remove { opacity: 1; }

/* Expanded step body */
.rip-step-body {
  display: none;
  flex-direction: column;
  gap: 6px;
  padding: 0 10px 10px;
}
.rip-step.expanded .rip-step-body { display: flex; }

.rip-step-body .rip-step-row {
  display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
}
.rip-step-body select {
  height: 30px; min-width: 90px;
  background: var(--surface-2); border: 1px solid var(--border-2); border-radius: 5px;
  padding: 0 8px; color: var(--text); font-size: 12px; outline: none;
}
.rip-step-body select:focus { border-color: var(--accent); }
.rip-step-body input[type="number"] {
  height: 30px; width: 50px;
  background: var(--surface-2); border: 1px solid var(--border-2); border-radius: 5px;
  padding: 0 6px; color: var(--text); font-size: 12px; font-family: var(--font-mono);
  outline: none; text-align: right;
}
.rip-step-body input[type="number"]:focus { border-color: var(--accent); }
.rip-step-body input[type="number"]::placeholder { color: var(--text-muted); }
.rip-step-body textarea {
  width: 100%; background: var(--surface-2); border: 1px solid var(--border-2); border-radius: 5px;
  padding: 6px 8px; color: var(--text); font-size: 12px; font-family: var(--font-mono);
  outline: none; resize: vertical; box-sizing: border-box;
}
.rip-step-body textarea:focus { border-color: var(--accent); }
.rip-step-body textarea::placeholder { color: var(--text-muted); }

/* Output mapping rows */
.rs-outputs { padding-left: 14px; }
.rs-outputs-list {
  display: flex;
  flex-direction: column;
  border-left: 1px dotted var(--border-3);
  margin-left: 2px;
}
.rs-output-row {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 2px 0 2px 10px;
}
.rs-output-row .crud-card-btn { opacity: 0; transition: opacity 0.15s; }
.rs-output-row:hover .crud-card-btn { opacity: 1; }
.rs-out-add-form { padding-left: 12px; border-left: 1px dotted var(--border-3); margin-left: 2px; }
.rs-out-add-form .rip-step-row { display: flex; gap: 6px; align-items: center; }
.rs-outputs .rip-add-step-btn { margin-left: 14px; }

/* + Step button */
.rip-add-step-btn {
  align-self: flex-start;
  background: none; border: 1px dashed var(--border-2); border-radius: 6px;
  color: var(--text-3); font-size: 12px; padding: 6px 14px;
  cursor: pointer; transition: color 0.15s, border-color 0.15s;
}
.rip-add-step-btn:hover { color: var(--text-2); border-color: var(--text-faint); }

/* ── Panel container ─────────────────────────────────────── */

#panel-container {
  height: calc(100vh - var(--titlebar-h));
  background: var(--bg);
  position: relative;
}

/* A task's clock, on its Overview. (skill-overview-extra hosts these blocks;
   each one gets its own top gap so they read as separate facts.) */
.skill-overview-block { margin-top: 20px; }
/* A story event's own actions: copy the output, carry it on in a session. */
.task-event-head { display: flex; align-items: center; gap: 8px; }
.task-event-actions { margin-left: auto; display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.task-event-btn { background: none; border: 1px solid var(--border); border-radius: 6px; padding: 1px 7px; font: inherit; font-size: 11.5px; color: var(--text-3); cursor: pointer; }
.task-event-btn:hover { color: var(--text); border-color: var(--border-2); background: var(--hover); }

/* "Open schedule": a quiet link beside the control, not a second button. */
.skill-sched-open { background: none; border: none; padding: 0; font: inherit; font-size: 12.5px; color: var(--accent-text); cursor: pointer; }
.skill-sched-open:hover { text-decoration: underline; }

/* The run history, its own section at the bottom of a schedule's detail. */
.schedule-runs-section { margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--border); }
.schedule-runs-section .ws-task-runs { max-height: 420px; overflow-y: auto; }

/* Run, on the schedule card itself. Sits at the end of the head row. */
.ws-task-run { margin-left: 8px; padding: 3px 10px; font-size: 12px; flex-shrink: 0; }
.ws-task-run:disabled { opacity: .75; }

/* The agent row's controls: what it runs on, its model, its clock. */
.skill-model-select { min-width: 150px; max-width: 220px; }
.skill-tile-icon.own img { width: 24px; height: 24px; border-radius: 6px; object-fit: contain; }

/* The schedule modal: three dropdowns, never a cron field. Compact, and ABOVE
   the settings overlay — at .conn-modal's own z-index it opened behind it and
   the user could not see it at all (his report, 2026-09-17). Toasts still win,
   since they report what the modal just did. */
/* Both selectors carry the base class too: these rules sit ABOVE .conn-modal
   in this file, and at equal specificity the later rule wins — which is how
   the panel stayed 680x600 and opened behind the settings overlay after I
   "fixed" it (his report, 2026-09-17). */
.conn-modal.skill-sched-modal { z-index: 999000; }
.conn-modal-panel.skill-sched-panel {
  height: auto; max-height: 82vh; width: min(360px, 92vw);
  padding: 14px 14px 12px; border-radius: 12px;
}
.skill-sched-panel .conn-modal-header { margin-bottom: 10px; }
.skill-sched-panel .conn-modal-title { font-size: 14px; }
.conn-modal-panel.skill-sched-panel .settings-input { margin-bottom: 0; }
.skill-sched-form { display: flex; flex-direction: column; gap: 8px; }
.skill-sched-field { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 13px; color: var(--text-2); }
.skill-sched-field .settings-input { margin-bottom: 0; width: 170px; flex-shrink: 0; padding: 5px 8px; font-size: 13px; }
.skill-sched-preview { font-size: 12.5px; color: var(--text-3); padding-top: 8px; margin-top: 2px; border-top: 1px solid var(--border); }
.skill-sched-actions-row { display: flex; align-items: center; gap: 8px; margin-top: 14px; }

/* THE GITHUB MARK IS BLACK ON TRANSPARENT (his order, 2026-09-17): invisible
   on every dark theme, wherever it appears — the Copilot loop's tiles, the
   rail, the library rows, a connector's icon. Each theme says whether a mark
   like that should flip, so one rule covers all of them. */
img[src*="github.com"], img[src*="githubassets"], img[data-mark-src*="github.com"], img.cli-mark-copilot { filter: invert(var(--mark-invert, 0)); }

/* A share's verdict, on the bundle: waiting, declined, live. */
.skill-share-chip.pending { color: var(--warning); border-color: color-mix(in srgb, var(--warning) 45%, transparent); }
.skill-share-chip.declined { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, transparent); }

/* A model the catalog no longer carries: named, and marked. */
.code-chip.warn { color: var(--warning); border-color: color-mix(in srgb, var(--warning) 45%, transparent); }
/* The effort chip on a model that takes one effort: still there, dimmed. */
.code-chip.dim { opacity: .45; cursor: default; }

/* A slot's agent picker: wide enough for a real agent name (it was 80px, so
   every option read "First ag…"), and it never outgrows the row. */
.skill-slot-select { min-width: 180px; max-width: 260px; }

/* A task's clock, on its Overview. */
.skill-sched-line { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.skill-sched-text { font-size: 13px; color: var(--text-2); }
.skill-sched-actions { display: flex; align-items: center; gap: 8px; }

/* Art inside a library tile — the Glyphh bundle's brand mark comes through
   the app resolver, so it arrives as an <img> with a monogram fallback. */
.skill-tile-icon img { width: 68%; height: 68%; object-fit: contain; display: block; }
.skill-tile-icon .skill-icon-initial { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 600; border-radius: 7px; }

/* ── TOASTS — the app's notifications (his order, 2026-09-17) ──────────
   One stack, top right, ABOVE the settings overlay and every modal (the
   highest z-index in this file is 100000, so the stack sits past it). The
   look is the house toast the downloader and updater already wear. */

#toast-stack {
  position: fixed;
  top: 44px;                 /* clear of the title bar's drag strip */
  right: 14px;
  z-index: 1000000;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-end;
  pointer-events: none;      /* the page keeps working behind the stack */
  max-width: min(420px, calc(100vw - 28px));
}

.toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 9px;
  min-width: 240px;
  max-width: 100%;
  padding: 10px 10px 10px 12px;
  background: var(--toast-bg);
  border: 1px solid var(--border-2);
  border-left: 3px solid var(--accent);
  border-radius: 10px;
  box-shadow: 0 6px 24px var(--shadow);
  animation: toast-slide-in 0.18s ease-out;
}
@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; }
}

.toast.going { animation: toast-slide-out 0.16s ease-in forwards; }

@keyframes toast-slide-in {
  from { transform: translateX(14px); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}
@keyframes toast-slide-out {
  from { transform: translateX(0); opacity: 1; }
  to   { transform: translateX(14px); opacity: 0; }
}

.toast-ok    { border-left-color: var(--success); }
.toast-error { border-left-color: var(--danger); }
.toast-info  { border-left-color: var(--accent); }

.toast-mark { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 1px; }
.toast-mark svg { width: 16px; height: 16px; display: block; }
.toast-ok .toast-mark    { color: var(--success); }
.toast-error .toast-mark { color: var(--danger); }
.toast-info .toast-mark  { color: var(--accent); }

.toast-body { min-width: 0; flex: 1; }
.toast-msg { font-size: 13px; line-height: 1.4; color: var(--text); overflow-wrap: anywhere; }
.toast-detail { margin-top: 2px; font-size: 12px; line-height: 1.45; color: var(--text-3); overflow-wrap: anywhere; }

.toast-right { flex: 0 0 auto; display: flex; align-items: center; gap: 2px; }

.toast-action {
  background: none;
  border: none;
  padding: 2px 6px;
  font: inherit;
  font-size: 12px;
  color: var(--accent-text);
  cursor: pointer;
  border-radius: 6px;
}
.toast-action:hover { background: var(--hover); }

.toast-x {
  background: none;
  border: none;
  padding: 1px 4px;
  font-size: 11px;
  line-height: 1;
  color: var(--text-faint);
  cursor: pointer;
  border-radius: 6px;
}
.toast-x:hover { color: var(--text); background: var(--hover); }

/* ── Download toast ────────────────────────────────────── */

.download-toast {
  position: fixed;
  bottom: 16px;
  right: 16px;
  z-index: 300;
  background: var(--toast-bg);
  border: 1px solid var(--accent);
  border-radius: 10px;
  padding: 10px 14px;
  min-width: 280px;
  max-width: 380px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  box-shadow: 0 4px 20px var(--shadow);
  animation: toast-in 0.25s ease-out;
}

@keyframes toast-in {
  from { transform: translateY(20px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

.download-info {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

#download-filename {
  font-size: 12px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
}

#download-status {
  font-size: 11px;
  color: var(--text-3);
  white-space: nowrap;
}

.download-progress-bar {
  height: 3px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
}

.download-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  border-radius: 2px;
  transition: width 0.2s ease;
}

.download-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
}

.download-dismiss {
  background: none;
  border: none;
  color: var(--text-3);
  font-size: 16px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
}

.download-dismiss:hover { color: var(--white); }

/* ── Update bar ───────────────────────────────────────── */

.update-bar {
  position: fixed;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 300;
  background: var(--toast-bg);
  border: 1px solid var(--accent);
  border-radius: 10px;
  padding: 8px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  box-shadow: 0 4px 20px var(--shadow);
  animation: toast-in 0.25s ease-out;
}

.update-message {
  font-size: 13px;
  color: var(--text);
}

.update-progress {
  width: 80px;
  height: 3px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
}

.update-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  border-radius: 2px;
  transition: width 0.3s ease;
}

.update-action {
  font-size: 12px;
  padding: 4px 12px;
}

.update-dismiss {
  background: none;
  border: none;
  color: var(--text-3);
  font-size: 16px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
}

.update-dismiss:hover { color: var(--white); }

/* ── Drip overlay ──────────────────────────────────────── */

.drip-overlay {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9999;
}

/* ── Settings (help tab) ──────────────────────────────────── */

.settings-layout {
  display: flex;
  gap: 0;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.settings-nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 184px;
  flex-shrink: 0;
  padding: 8px 12px 12px 0;
  border-right: 1px solid var(--border);
  overflow-y: auto;
}

/* Group heading — the rail is a dozen items long, and "which of these is about
   ME vs the org vs this machine" is the question it kept failing to answer. */
.settings-nav-group {
  padding: 0 12px;
  margin: 14px 0 4px;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  user-select: none;
}
.settings-nav-group:first-child { margin-top: 2px; }

.settings-nav-item {
  display: flex;
  align-items: center;
  gap: 9px;
  background: none;
  border: none;
  color: var(--text-3);
  font-size: 13px;
  font-weight: 500;
  padding: 7px 12px;
  border-radius: 7px;
  cursor: pointer;
  text-align: left;
  transition: color 0.15s, background 0.15s;
}

/* The icon carries the row's colour, so it lifts with the label rather than
   sitting at a fixed grey while the text brightens. */
.settings-nav-icon {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  opacity: 0.75;
  transition: opacity 0.15s;
}

.settings-nav-item:hover {
  color: var(--text);
  background: var(--active-bg);
}
.settings-nav-item:hover .settings-nav-icon { opacity: 1; }

.settings-nav-item.active {
  color: var(--white);
  background: var(--active-bg);
}
.settings-nav-item.active .settings-nav-icon { opacity: 1; color: var(--accent); }

.settings-panels {
  flex: 1;
  min-width: 0;
  padding: 8px 28px 8px 28px;
  overflow-y: auto;
}

.settings-panel {
  display: none;
}


.settings-panel.active {
  display: block;
}

.settings-panel h2 {
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
  margin: 0 0 4px;
}

.settings-panel .section-desc {
  margin: 0 0 16px;
}

.settings-form {
  max-width: 420px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 16px;
}

/* Provider cards fill the panel width — they're wide compound cards
   (label + status badge + hint + key input + Save + verify response),
   not narrow form fields, so the 420px settings-form clamp doesn't
   fit them. */
#provider-keys-list {
  max-width: none;
}

.settings-label {
  /* <label> is inline by default and inline boxes IGNORE vertical margins —
     the 20px form rhythm silently vanished in any block container (labels
     only worked inside flex columns, which blockify their items). Block
     display makes the margins real everywhere. */
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-2);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-top: 4px;
}

.settings-input {
  width: 100%;
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px solid var(--border-3);
  background: var(--surface-2);
  color: var(--text);
  font-size: 14px;
  outline: none;
  transition: border-color 0.15s;
}

.settings-input:focus {
  border-color: var(--accent);
}

select.settings-input {
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%23888' viewBox='0 0 24 24'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
}

.settings-model-wrap {
  display: contents;
}

.settings-inline {
  display: flex;
  align-items: center;
  gap: 10px;
}
/* The input in an inline row takes the slack; the button beside it keeps its
   label on one line instead of being squeezed into a two-line block. */
.settings-inline > .action-btn {
  flex-shrink: 0;
  white-space: nowrap;
}

.settings-input-sm {
  width: 80px;
  flex-shrink: 0;
}

.settings-input-md {
  width: 200px;
  flex-shrink: 0;
}

.settings-hint {
  color: var(--text-2);
  font-size: 12px;
}

.settings-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 8px;
}

.settings-success,
.settings-error,
.settings-warn {
  font-size: 13px;
  font-weight: 500;
  padding: 10px 14px;
  border-radius: 10px;
  border: 1px solid;
  margin: 0 0 14px;
}
.settings-success:empty, .settings-error:empty, .settings-warn:empty { display: none; }
.settings-success {
  color: var(--success);
  border-color: color-mix(in srgb, var(--success) 40%, transparent);
  background: color-mix(in srgb, var(--success) 12%, transparent);
}
.settings-error {
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 40%, transparent);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
}
.settings-warn {
  color: var(--warning);
  border-color: color-mix(in srgb, var(--warning) 40%, transparent);
  background: color-mix(in srgb, var(--warning) 12%, transparent);
}

/* A settings row a panel's "Open settings" link pointed at — a short outline
   flash so the eye lands on the switch (help/settings.ts). */
.set-pref-row.set-pref-focus {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
  border-radius: 10px;
  transition: outline-color .3s;
}

.settings-subheading {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-bright);
  margin: 28px 0 4px;
}
.settings-subheading + .section-desc {
  margin-top: 0;
}

.settings-toggles {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 420px;
  margin-top: 12px;
}

.settings-toggle {
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  padding: 10px 14px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  transition: border-color 0.15s;
}
.settings-toggle:hover { border-color: var(--border-3); }
/* Disabled switch — the same dimmed affordance the scheduler toggle uses
   (sched-toggle): the roles model list reads inert until the limit is on. */
.settings-toggle input:disabled + .toggle-switch { opacity: 0.4; cursor: not-allowed; }

.settings-toggle input[type="checkbox"] {
  display: none;
}

.toggle-switch {
  position: relative;
  width: 40px;
  min-width: 40px;
  height: 22px;
  border-radius: 11px;
  background: var(--border-3);
  transition: background 0.2s;
}
.toggle-switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--text-3);
  transition: transform 0.2s, background 0.2s;
}
.settings-toggle input:checked + .toggle-switch {
  background: var(--accent);
}
.settings-toggle input:checked + .toggle-switch::after {
  transform: translateX(18px);
  background: var(--white);
}

.toggle-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.toggle-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-bright);
}
.toggle-desc {
  font-size: 11px;
  color: var(--text-3);
}
.toggle-desc code {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-2);
  background: var(--surface-2);
  padding: 1px 4px;
  border-radius: 3px;
}

/* ── Theme picker ─────────────────────────────────────────── */

.theme-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 8px;
}

.theme-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 8px;
  background: none;
  border: 2px solid var(--border-2);
  border-radius: 12px;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-2);
}
.theme-option:hover { border-color: var(--border-3); color: var(--text); background: var(--hover); }
.theme-option.active { border-color: var(--accent); color: var(--text); }
.theme-option.active:hover { border-color: var(--accent); color: var(--text); background: var(--hover); }

.theme-preview {
  width: 100px;
  height: 64px;
  border-radius: 6px;
  overflow: hidden;
  display: flex;
}

.tp-sidebar { width: 24px; }
.tp-main { flex: 1; display: flex; flex-direction: column; }
.tp-bar { height: 10px; }
.tp-content { flex: 1; }

.theme-preview-dark { background: #000; }
.theme-preview-dark .tp-sidebar { background: #000; border-right: 1px solid #5a5a5a; }
.theme-preview-dark .tp-bar { background: #0d0d0d; border-bottom: 1px solid #5a5a5a; }
.theme-preview-dark .tp-content { background: #000; }

.theme-preview-light { background: #fff; }
.theme-preview-light .tp-sidebar { background: #fff; border-right: 1px solid #8a8a8a; }
.theme-preview-light .tp-bar { background: #f7f7f7; border-bottom: 1px solid #8a8a8a; }
.theme-preview-light .tp-content { background: #fff; }

.theme-preview-system { background: linear-gradient(135deg, #000 50%, #fff 50%); }
.theme-preview-system .tp-sidebar { background: linear-gradient(180deg, #000 50%, #fff 50%); border-right: 1px solid #7a7a7a; }
.theme-preview-system .tp-bar { background: linear-gradient(135deg, #0d0d0d 50%, #f7f7f7 50%); border-bottom: 1px solid #7a7a7a; }
.theme-preview-system .tp-content { background: linear-gradient(135deg, #000 50%, #fff 50%); }

.theme-preview-modern-dark { background: #1a1a1c; }
.theme-preview-modern-dark .tp-sidebar { background: #111; border-right: 1px solid #1e1e1e; }
.theme-preview-modern-dark .tp-bar { background: #111; border-bottom: 1px solid #1e1e1e; }
.theme-preview-modern-dark .tp-content { background: #1a1a1c; }

.theme-preview-modern-light { background: #f5f5f5; }
.theme-preview-modern-light .tp-sidebar { background: #fff; border-right: 1px solid #e5e5e5; }
.theme-preview-modern-light .tp-bar { background: #fff; border-bottom: 1px solid #e5e5e5; }
.theme-preview-modern-light .tp-content { background: #f5f5f5; }

.theme-preview-purple { background: #140a1f; }
.theme-preview-purple .tp-sidebar { background: #1b1029; border-right: 1px solid #2c1e42; }
.theme-preview-purple .tp-bar { background: #1b1029; border-bottom: 1px solid #2c1e42; }
.theme-preview-purple .tp-content { background: #221634; }

.theme-preview-aurora { background: radial-gradient(120% 120% at 0% 100%, rgba(147,51,234,.55), transparent 55%), radial-gradient(100% 100% at 100% 0%, rgba(236,72,153,.4), transparent 52%), #0a0610; }
.theme-preview-aurora .tp-sidebar { background: rgba(27,16,41,.7); border-right: 1px solid rgba(124,58,237,.4); }
.theme-preview-aurora .tp-bar { background: rgba(27,16,41,.7); border-bottom: 1px solid rgba(124,58,237,.4); }
.theme-preview-aurora .tp-content { background: transparent; }

.theme-preview-prism { background: radial-gradient(120% 120% at 0% 100%, rgba(109,94,252,.30), transparent 55%), radial-gradient(110% 110% at 100% 0%, rgba(34,211,238,.28), transparent 52%), radial-gradient(120% 120% at 100% 100%, rgba(244,114,182,.24), transparent 55%), #f4f4fb; }
.theme-preview-prism .tp-sidebar { background: rgba(255,255,255,.65); border-right: 1px solid rgba(214,213,234,.8); }
.theme-preview-prism .tp-bar { background: rgba(255,255,255,.65); border-bottom: 1px solid rgba(214,213,234,.8); }
.theme-preview-prism .tp-content { background: transparent; }

.theme-preview-github { background: #0d1117; }
.theme-preview-github .tp-sidebar { background: #161b22; border-right: 1px solid #30363d; }
.theme-preview-github .tp-bar { background: #161b22; border-bottom: 1px solid #30363d; }
.theme-preview-github .tp-content { background: #0d1117; }

.theme-preview-claude { background: #f0eee6; }
.theme-preview-claude .tp-sidebar { background: #faf9f5; border-right: 1px solid #e3e1d6; }
.theme-preview-claude .tp-bar { background: #faf9f5; border-bottom: 1px solid #e3e1d6; }
.theme-preview-claude .tp-content { background: #f0eee6; }

.theme-preview-chatgpt { background: #212121; }
.theme-preview-chatgpt .tp-sidebar { background: #171717; border-right: 1px solid #424242; }
.theme-preview-chatgpt .tp-bar { background: #2f2f2f; border-bottom: 1px solid #424242; }
.theme-preview-chatgpt .tp-content { background: #212121; }

.theme-preview-gemini { background: radial-gradient(120% 120% at 0% 100%, rgba(66,133,244,.4), transparent 55%), radial-gradient(110% 110% at 100% 0%, rgba(161,66,244,.32), transparent 52%), #131314; }
.theme-preview-gemini .tp-sidebar { background: rgba(30,31,32,.75); border-right: 1px solid rgba(68,70,73,.8); }
.theme-preview-gemini .tp-bar { background: rgba(30,31,32,.75); border-bottom: 1px solid rgba(68,70,73,.8); }
.theme-preview-gemini .tp-content { background: transparent; }

.theme-preview-dracula { background: #282a36; }
.theme-preview-dracula .tp-sidebar { background: #21222c; border-right: 1px solid #44475a; }
.theme-preview-dracula .tp-bar { background: #343746; border-bottom: 1px solid #44475a; }
.theme-preview-dracula .tp-content { background: #282a36; }

.theme-preview-nord { background: #2e3440; }
.theme-preview-nord .tp-sidebar { background: #3b4252; border-right: 1px solid #4c566a; }
.theme-preview-nord .tp-bar { background: #3b4252; border-bottom: 1px solid #4c566a; }
.theme-preview-nord .tp-content { background: #2e3440; }

.theme-preview-synthwave { background: radial-gradient(120% 120% at 0% 100%, rgba(255,46,151,.45), transparent 55%), radial-gradient(110% 110% at 100% 0%, rgba(0,229,255,.32), transparent 52%), #1a1030; }
.theme-preview-synthwave .tp-sidebar { background: rgba(34,22,65,.8); border-right: 1px solid rgba(69,48,122,.9); }
.theme-preview-synthwave .tp-bar { background: rgba(34,22,65,.8); border-bottom: 1px solid rgba(69,48,122,.9); }
.theme-preview-synthwave .tp-content { background: transparent; }

.theme-preview-matrix { background: #020a02; }
.theme-preview-matrix .tp-sidebar { background: #071507; border-right: 1px solid #14371a; }
.theme-preview-matrix .tp-bar { background: #071507; border-bottom: 1px solid #14371a; }
.theme-preview-matrix .tp-content { background: #020a02; }

.settings-relaunch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 16px;
  padding: 10px 14px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  max-width: 420px;
}
.settings-relaunch span {
  font-size: 13px;
  color: var(--warning);
}
.settings-relaunch.hidden { display: none; }

/* Onboarding provider select */
#onboarding-provider {
  width: 100%;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid var(--border-3);
  background: var(--surface);
  color: var(--text);
  font-size: 14px;
  outline: none;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%23888' viewBox='0 0 24 24'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 36px;
}

#onboarding-provider:focus {
  border-color: var(--accent);
}

/* ── About section ────────────────────────────────────────── */

.about-header {
  text-align: left;
  padding: 24px 0 32px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 32px;
}

.about-update-btn {
  display: inline-block;
  margin-top: 12px;
  padding: 6px 16px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: none;
  cursor: pointer;
  transition: all 0.15s;
}
.about-update-btn:hover {
  background: var(--active-bg);
}
.about-update-btn:disabled {
  opacity: 1;
  color: var(--text-bright);
  border-color: var(--border);
  cursor: default;
}

/* Secondary "Check for Updates" button spacing (uses the shared .btn styles). */
.about-check-update { margin-top: 12px; }

/* Bottom-right "Relaunch to Update" prompt on the About page. */
.about-update-prompt {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 12px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.28);
}
.about-update-prompt.hidden { display: none; }
.about-update-prompt-text {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.about-logo {
  margin-bottom: 8px;
}

.about-logo .glyphh-logo { height: 56px; }

.about-version {
  font-size: 13px;
  color: var(--text-3);
  font-family: var(--font-mono);
  margin-bottom: 4px;
}

.about-progress {
  margin-top: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.about-progress-bar {
  width: 200px;
  height: 6px;
  background: var(--surface-2);
  border-radius: 3px;
  overflow: hidden;
}
.about-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  border-radius: 3px;
  transition: width 0.3s ease;
}
.about-progress-text {
  font-size: 11px;
  color: var(--text-3);
  font-family: var(--font-mono);
}

.about-restart {
  margin-top: 12px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.about-restart-text {
  font-size: 12px;
  color: var(--text);
  font-weight: 600;
}
.about-restart-btn {
  padding: 6px 16px;
  font-size: 12px;
  font-weight: 600;
  color: #000;
  background: var(--accent);
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: opacity 0.15s;
}
.about-restart-btn:hover {
  opacity: 0.85;
}

.about-copyright {
  font-size: 12px;
  color: var(--text-muted);
}

.about-policies {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.about-policy h3 {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-bright);
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}

.policy-content {
  font-size: 13px;
  line-height: 1.7;
  color: var(--text-2);
}

.policy-content p {
  margin-bottom: 10px;
}

.policy-content strong {
  color: var(--text);
}

.policy-content ul {
  padding-left: 20px;
  margin-bottom: 10px;
}

.policy-content li {
  margin-bottom: 4px;
}

/* ── Account: the identity header ─────────────────────────── */
/* One statement of who you are — avatar, name, sign-in email, then role / org
   / plan as chips. Replaced a label:value row list that repeated the email and
   name the profile form below already showed. */

.acct-identity {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 14px;
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
}

.acct-id-face {
  display: flex;
  align-items: center;
  gap: 16px;
  min-width: 0;
}

/* Avatar + its Add-image button stack as one centered column. */
.acct-avatar-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.acct-avatar-add {
  font-size: 11px;
  padding: 2px 8px;
  min-height: 0;
  height: auto;
  line-height: 1.6;
}

/* The avatar and its initials fallback occupy the SAME box, so swapping one
   for the other can't shift the row. */
.acct-avatar-slot {
  position: relative;
  width: 60px;
  height: 60px;
  flex-shrink: 0;
}

.acct-initials,
.acct-avatar {
  position: absolute;
  inset: 0;
  width: 60px;
  height: 60px;
  border-radius: 50%;
}

.acct-initials {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-bg, var(--surface-2));
  color: var(--accent);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: 0.02em;
  user-select: none;
}

.acct-avatar {
  object-fit: cover;
  background: var(--surface-2);
}

.acct-id-text { min-width: 0; }

.acct-name {
  font-size: 18px;
  font-weight: 600;
  color: var(--text-bright);
  letter-spacing: -0.01em;
  line-height: 1.25;
}

.acct-email {
  /* One quiet size, the page's own face — the mono/13px combo read as yet
     another font under the 18px name. */
  font-size: 12px;
  color: var(--text-3);
  margin-top: 2px;
  overflow-wrap: anywhere;
}

.acct-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
}

.acct-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border: 1px solid var(--border-2);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 11.5px;
  font-weight: 500;
  text-transform: capitalize;
  white-space: nowrap;
}

/* The plan chip IS the settings primary component (`action-btn primary` on the
   element itself — no bespoke fill) and navigates to Billing. Only layout is
   tuned here: chip-row height + room for the refresh icon. */
.acct-chip-plan { padding-right: 6px; height: 24px; border-radius: 999px; }

.acct-chip-refresh {
  display: inline-flex;
  align-items: center;
  padding: 2px;
  border: none;
  border-radius: 50%;
  background: none;
  color: inherit;
  opacity: 0.6;
  cursor: pointer;
  transition: opacity var(--transition), background var(--transition);
}
.acct-chip-refresh:hover { opacity: 1; background: var(--hover); }
.acct-chip-refresh.spinning svg { animation: acct-spin 0.6s linear infinite; }
@keyframes acct-spin { to { transform: rotate(360deg); } }

.acct-id-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

/* ── Account: compact field rows ──────────────────────────── */
/* The stacked label/input column made a short form read as a long one — every
   field a full-width block. These rows put related fields side by side and
   wrap on their own, so the panel is scanned rather than scrolled. */

.acct-section {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 12px;
}

.acct-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 16px;
}

.acct-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  flex: 1 1 170px;
  min-width: 0;
}
/* Names and postcodes want a box; addresses and URLs want the rest of the row. */
.acct-field-wide { flex: 2 1 280px; }
/* Alone on its row, a field would stretch the full panel — the zone picker and
   its button read as one control only if the row stops where they do. */
.acct-field-solo { flex: 0 1 420px; }

.acct-field .settings-label { margin: 0; }
.acct-field .settings-input { width: 100%; }

/* A quiet divider-heading inside a section (Address, Billing address…) — the
   subheading weight would compete with the section titles above it. */
/* GENERAL page rhythm — groups breathe instead of jamming into one another:
   real space between the compaction form, Sessions, Guardrails, and toggles;
   headings get a genuine bottom margin (the global -2px reads as jammed). */
.settings-panel[data-sub="general"] .settings-form { gap: 12px; }
.settings-panel[data-sub="general"] #general-runtime-group,
.settings-panel[data-sub="general"] #general-guardrails-group { margin-top: 30px; }
.settings-panel[data-sub="general"] .acct-row-head { margin: 0 0 8px; }
.settings-panel[data-sub="general"] .section-desc { margin: 0 0 14px; }
.settings-panel[data-sub="general"] #runtime-region-select { margin-top: 2px; }
.settings-panel[data-sub="general"] .settings-toggles { margin-top: 30px !important; }

.acct-row-head {
  margin: 6px 0 -2px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-3);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ── Account: the organization bar ────────────────────────── */
/* Full width, name left, id right — the id is what support and the API ask
   for, so it is one click to copy rather than something to go hunting for. */

/* The bar: one full-width row that heads a section — something on the left,
   something on the right. `.set-fold-bar` is the same box plus disclosure
   behaviour, so the two never drift apart. */
.set-bar,
.set-fold-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  margin-top: 8px;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  color: var(--text);
  text-align: left;
  font: inherit;
}

.set-bar-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.set-bar-sub { font-size: 12px; color: var(--text-3); }

.set-fold-bar {
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.set-fold-bar:hover { background: var(--hover); border-color: var(--border-2); }

.set-fold-head {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.set-fold-chevron {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  color: var(--text-3);
  transition: transform 160ms ease;
}
.set-fold-bar[aria-expanded="true"] .set-fold-chevron { transform: rotate(90deg); }

.set-fold-body { padding-top: 4px; }

/* ── Account: the auto-save state line ────────────────────── */
/* No Save button anywhere in this panel — this is the whole report, sat beside
   the section heading it belongs to. Weight is deliberately low: a save that
   worked should be confirmable, not announced. */
.set-save-state {
  margin-left: 8px;
  font-size: 11.5px;
  font-weight: 500;
  color: var(--text-3);
  text-transform: none;
  letter-spacing: 0;
}
.set-save-state.success { color: var(--success); }
.set-save-state.error { color: var(--danger); }

.set-fold-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-bright);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.set-fold-aside {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  color: var(--text-3);
}

.set-fold-aside code {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.01em;
}

.set-copy-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  color: var(--text-3);
  cursor: pointer;
  transition: color var(--transition), background var(--transition), border-color var(--transition);
}
.set-copy-btn svg { width: 14px; height: 14px; }
.set-copy-btn:hover { color: var(--text); background: var(--hover); border-color: var(--border-2); }
/* Copied: the icon swaps to a tick via CSS so the button never reflows. */
.set-copy-btn.copied { color: var(--success); }
.set-copy-btn.copied svg { display: none; }
.set-copy-btn.copied::after {
  content: '✓';
  font-size: 13px;
  line-height: 1;
}

/* ── Workspaces ───────────────────────────────────────────── */
/* A workspace narrows what the org already allows, so the editor is three
   tabs of allow-lists. The LIST is the standard lib-table grammar (rendered
   by settings-workspaces.ts); the model and connection grids reuse the
   Models page's card grid. */

/* Back out of the editor / the tool drill-down. */

.ws-tab { display: none; }
.ws-tab.active { display: block; }

/* A model card in the editor is the Models page's card plus a checkbox; the
   dimming says "excluded" without removing it from the list. */
.ws-model-card { cursor: pointer; }
.ws-model-card.off { opacity: 0.45; }
.ws-model-card input[type="checkbox"] { margin-bottom: 6px; }

.ws-conn-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  text-align: left;
  cursor: pointer;
}

.ws-conn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 11px;
  font-weight: 600;
  overflow: hidden;
}
.ws-conn-icon img { width: 100%; height: 100%; object-fit: contain; }

/* The per-connection tool list. Long, so it scrolls on its own rather than
   pushing the tab's chrome off screen. */





@media (max-width: 720px) {
    }

/* ── Members ──────────────────────────────────────────────── */
/* A row, not a table cell: name is an input that saves itself, role is a live
   select, and Remove sits at the end. A <table> would have meant a second
   editing mode on top of the one every other Settings field now uses. */

.mbr-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
}

.mbr-row {
  display: grid;
  grid-template-columns: minmax(140px, 1.2fr) minmax(180px, 1.6fr) 130px auto;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
}

.mbr-email {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
}

.mbr-name,
.mbr-role { width: 100%; }
.mbr-remove { justify-self: end; }

@media (max-width: 720px) {
  .mbr-row { grid-template-columns: 1fr 1fr; }
  .mbr-email { grid-column: 1 / -1; }
}

/* ── A4 panels — API Keys / Support / Runtime list rows ─────────────────────
   A simple name-over-subtext row with a trailing action, styled to match the
   native settings surface (same surface/border tokens as .mbr-row, .crud-card). */
.a4-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  margin-bottom: 6px;
  text-align: left;
  width: 100%;
}
button.a4-row-btn { cursor: pointer; font: inherit; color: inherit; transition: background 0.15s, border-color 0.15s; }
button.a4-row-btn:hover { background: var(--surface-2); border-color: var(--border-2); }
button.a4-row-btn:disabled { opacity: 0.55; cursor: default; }
.a4-row-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.a4-row-name { font-size: 13px; font-weight: 500; color: var(--text-bright); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.a4-row-sub { font-size: 11px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.a4-row-tick { display: flex; align-items: center; color: var(--accent); }
.a4-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); vertical-align: middle; }
.a4-spin {
  display: inline-block; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid var(--border-2); border-top-color: var(--accent);
  animation: a4-spin 0.7s linear infinite;
}
@keyframes a4-spin { to { transform: rotate(360deg); } }

/* Support thread — chat bubbles, user right / admin left. */
.support-msgs { display: flex; flex-direction: column; gap: 8px; max-height: 46vh; overflow-y: auto; padding: 4px 2px; }
.support-msg {
  max-width: 82%; padding: 8px 12px; border-radius: 12px; font-size: 13px; line-height: 1.45;
  white-space: pre-wrap; word-break: break-word;
}
.support-msg-user { align-self: flex-end; background: var(--accent); color: var(--accent-fg); border-bottom-right-radius: 4px; }
.support-msg-admin { align-self: flex-start; background: var(--surface-2); color: var(--text); border: 1px solid var(--border); border-bottom-left-radius: 4px; }

/* ── Account / Organization forms ───────────────────────── */


/* Read-only field values (email, role, seat ceiling) — the display twin of
   .settings-input so a locked field lines up with the editable ones instead of
   collapsing to a bare line of text. */
.settings-readonly {
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-2);
  font-size: 14px;
}

/* ── Billing ────────────────────────────────────────────── */
/* Everything here reuses the app's existing surfaces (dash-card for the budget
   split, lib-table for invoices, action-btn for every control); only the three
   layouts below — top-up presets, the seat meter, and the plan grid — have no
   existing equivalent. */

/* The page reads as SECTIONS on the General page's rhythm: ~30px between
   groups, 8px under each heading — one gutter, no orphaned margins. Only the
   panel's top-level heads (and the org group's) get the group gap; the h4s
   inside forms keep the component default. */
.settings-panel[data-sub="billing"] > .acct-row-head,
.settings-panel[data-sub="billing"] #billing-org-group > .acct-row-head { margin: 30px 0 8px; }
.settings-panel[data-sub="billing"] > .acct-row-head:first-of-type { margin-top: 18px; }
/* Whatever sits DIRECTLY under a section heading starts flush at the 8px the
   heading already provides — bars between siblings keep their component gap. */
.settings-panel[data-sub="billing"] .acct-row-head + .set-bar,
.settings-panel[data-sub="billing"] .acct-row-head + .set-fold-bar,
.settings-panel[data-sub="billing"] .acct-row-head + .billing-topup-grid,
.settings-panel[data-sub="billing"] .acct-row-head + .dash-grid { margin-top: 0; }

.billing-topup-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px;
  margin-top: 12px;
}
/* The compact 402 "Budget used up" dialog — reuses the Add-funds card grid + toggle. */
.add-funds-box { max-width: 480px; width: min(480px, 92vw); }
/* Embedded Stripe checkout mounted inside the modal: give the iframe room and
   its own scroll — the modal must never grow past the viewport. */
.bc-checkout-stage { min-height: 480px; max-height: min(72vh, 700px); overflow-y: auto; border-radius: 10px; }
.bc-confirming { display: flex; align-items: center; gap: 10px; justify-content: center; min-height: 120px; color: var(--text-2); font-size: 14px; text-align: center; padding: 20px; }
.bc-confirming.bc-done { color: var(--text); font-weight: 600; }
.bc-back { margin-top: 10px; align-self: flex-start; }
.add-funds-box .bc-balance { margin: 0 0 4px; color: var(--text-2); font-size: 13px; }
/* Super-admin org detail (Orgs → Manage): stat cards + key/value grid. */
.pa-org-stats { display: flex; gap: 12px; margin: 12px 0 10px; }
.pa-stat { flex: 1; border: 1px solid var(--border-1, #2a2a2a); border-radius: 10px; padding: 12px 14px; display: flex; flex-direction: column; gap: 2px; }
.pa-stat-num { font-size: 22px; font-weight: 700; color: var(--text); line-height: 1.1; }
.pa-stat-lbl { font-size: 11px; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.04em; }
.pa-kv { display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; margin: 6px 0 4px; }
.pa-kv > div { display: flex; justify-content: space-between; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--border-1, #2a2a2a); font-size: 13px; }
.pa-kv > div > span { color: var(--text-3); }
.pa-kv > div > b { color: var(--text); font-weight: 600; text-align: right; }
.billing-topup-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 14px 16px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s, background 0.15s;
}
.billing-topup-card:hover:not(:disabled) { border-color: var(--accent); background: var(--hover); }
.billing-topup-card:disabled { opacity: 0.5; cursor: default; }
.billing-topup-amount { font-size: 20px; font-weight: 600; color: var(--text-bright); }
.billing-topup-unit { font-size: 11px; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.04em; }

/* The plan picker — the old platform pricing page's grid, folded under the
   Plan bar. Cards share the top-up cards' surface grammar; the current plan
   is marked by the accent border + flag, and every action is a real
   .action-btn so the theme owns all color. */
.billing-plan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px;
  margin-top: 10px;
}
.billing-plan-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 16px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
}
.billing-plan-card.current { border-color: var(--accent); }
.billing-plan-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.billing-plan-name { font-size: 14px; font-weight: 600; color: var(--text-bright); }
/* The current/bespoke marker is the EXISTING .acct-chip component — no
   bespoke pill here. The card's selected state mirrors .theme-option.active
   (accent border), the house selected-card grammar. */
.billing-plan-price { margin: 2px 0 4px; }
.billing-plan-amount { font-size: 20px; font-weight: 600; color: var(--text-bright); }
.billing-plan-period { font-size: 11px; color: var(--text-3); }
.billing-plan-line { font-size: 12px; color: var(--text-2); }
.billing-plan-sso {
  margin-left: 4px;
  padding: 0 4px;
  border: 1px solid var(--border-2);
  border-radius: 4px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--text-3);
}
/* The action pins to the card's bottom edge (margin-top:auto in the column
   flex) so a short card's button lines up with its neighbors'; the min-margin
   keeps it off the text when the card is already full. */
.billing-plan-card .billing-plan-btn {
  margin-top: auto;
  width: 100%;
  justify-content: center;
}
.billing-plan-line:last-of-type { margin-bottom: 8px; }

.billing-seats { max-width: 420px; margin-top: 10px; }
/* The meter reads first; the count is the caption under it. */
.billing-seats-count { margin: 6px 0 0; }
.billing-seats-bar {
  height: 6px;
  border-radius: 3px;
  background: var(--surface-2);
  overflow: hidden;
}
.billing-seats-fill {
  height: 100%;
  width: 0;
  border-radius: 3px;
  background: var(--accent);
  transition: width 0.2s;
}
.billing-seats-fill.full { background: var(--danger); }


/* The invoice table is five even-ish columns, not the library's name/desc
   shape — override .lib-table's fixed widths rather than fork the component. */
.lib-table.billing-invoices th,
.lib-table.billing-invoices td { width: auto; }
.lib-table.billing-invoices tbody tr { cursor: default; }
.lib-table.billing-invoices tbody tr:hover td { background: transparent; }
.lib-table.billing-invoices .billing-invoice-link { text-align: right; }
/* DNS records (Domains editor) — same override play as billing-invoices: the
   generic 26%/18% fixed columns + nowrap ellipsis CLIPPED the long values
   (verify token, IPv6) and pushed their copy buttons out of view (his report,
   2026-08-31). AUTO layout (his report, 2026-09-01: fixed still scrunched the
   columns evenly): content sizes each column, long values wrap cleanly. */
.lib-table.dom-dns { table-layout: auto; }
/* Shrink-to-content columns; the LAST column takes every remaining pixel.
   (Plain auto layout handed the slack to Name and crushed Value against the
   right edge — his report, 2026-09-01.) */
.lib-table.dom-dns th:not(:last-child), .lib-table.dom-dns td:not(:last-child) { width: 1%; white-space: nowrap; }
.lib-table.dom-dns th:last-child, .lib-table.dom-dns td:last-child { width: auto; white-space: normal; }
.lib-table.dom-dns td { vertical-align: top; }
.lib-table.dom-dns td:not(:last-child) { padding-right: 28px; }
.lib-table.dom-dns td code { word-break: break-all; }
.lib-table.dom-dns tbody tr { cursor: default; }
.lib-table.dom-dns tbody tr:hover td { background: transparent; }

/* The validated form modal (formModal): one vertical rhythm — fields stack
   with real air, labels sit 6px off their inputs (his report, 2026-09-01:
   the Invite modal was crammed). */
.fm-form { display: flex; flex-direction: column; gap: 16px; }
/* flex: none — the acct-field base class grows to fill spare height, which
   stretched the invite modal's two fields across a huge box (his report,
   2026-09-02). Modal fields size to content. */
.fm-form .fm-field { display: flex; flex-direction: column; flex: 0 0 auto; }
.fm-form .fm-field .settings-label { margin-bottom: 6px; }
.fm-form .fm-err { margin-top: 6px; }

/* Editor footer (the standard Security edit form): Delete bottom-left,
   Cancel + Save (primary) bottom-right — identical on every page. */
.crud-edit-foot { display: flex; align-items: center; gap: 10px; margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--border); }
/* The scaffold's editor runs FULL WIDTH — matching the Roles editor
   (#ws-edit-view max-width:none; his call, 2026-09-01: "full width to match
   roles"). */
.crud-inline-form.lp-edit { max-width: none; }
/* Editor sections — one consistent vertical rhythm (his report, 2026-09-01:
   "everything is crammed and the sections are not clear"): each section owns
   real air below it and a hairline above the next; the heading gets 8px onto
   its description, the description 14px onto the content. */
.lp-edit .lp-sec { margin: 0 0 34px; }
.lp-edit .lp-sec + .lp-sec { padding-top: 26px; border-top: 1px solid var(--border); }
.lp-edit .lp-sec .acct-row-head { margin: 0 0 8px; }
.lp-edit .lp-sec .section-desc { margin: 0 0 16px; }
.lp-edit .lp-sec:last-of-type { margin-bottom: 8px; }

/* ── Support ────────────────────────────────────────────── */

.support-discord-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 20px;
  background: #5865F2;
  color: #ffffff;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s;
  margin-top: 16px;
}

.support-discord-btn:hover {
  background: #4752C4;
}

.support-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 480px;
  margin: 24px 0 20px;
  color: var(--text-muted);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.support-divider::before,
.support-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--hover);
}

.support-form {
  max-width: 480px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.support-textarea {
  min-height: 120px;
  resize: vertical;
  font-family: inherit;
  line-height: 1.5;
}

.support-form-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.support-context {
  font-size: 11px;
  color: var(--text-muted);
}

.support-status {
  font-size: 13px;
  min-height: 20px;
}

.support-status.success {
  color: var(--text);
}

.support-status.error {
  color: var(--danger);
}

/* ── Yo agent slide-out panel ──────────────────────────────── */

.yo-panel {
  position: fixed;
  top: var(--titlebar-h);
  right: 0;
  bottom: 0;
  width: 380px;
  background: var(--surface-2);
  border-left: 1px solid var(--border-3);
  display: flex;
  flex-direction: column;
  z-index: 60;
  transform: translateX(100%);
  transition: transform 0.2s ease;
}

.yo-panel-resize {
  position: absolute;
  left: -4px;
  top: 0;
  bottom: 0;
  width: 8px;
  cursor: col-resize;
  z-index: 1;
}
.yo-panel-resize::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 3px;
  height: 32px;
  background: transparent;
  border-radius: 2px;
  transition: background 0.15s;
}
.yo-panel-resize:hover::after {
  background: var(--border-3);
}
.yo-panel-resize.dragging::after {
  background: var(--accent);
  height: 100%;
  width: 2px;
  border-radius: 0;
  box-shadow: 0 0 10px rgba(175, 95, 255, 0.4);
}
.yo-panel.open {
  transform: translateX(0);
}
.yo-panel.hidden { display: none !important; }
/* Hide the resize/peek strip whenever the panel is closed — otherwise the
   4px that sits left of the panel's edge (left: -4px on an 8px element)
   sticks out at the viewport's right edge and reads as an unintended
   "popout tab". Users open .Yo via the titlebar button instead. */
.yo-panel:not(.open) .yo-panel-resize { display: none; }

/* ── Files left rail ──────────────────────────────────────── */

.files-rail-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 22px;
  margin: 0 4px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 5px;
  color: var(--text-2);
  cursor: pointer;
  -webkit-app-region: no-drag;
}
.files-rail-toggle:hover { background: var(--surface-2); color: var(--text); }
.files-rail-toggle.active { color: var(--text); }

.files-rail {
  position: fixed;
  top: var(--titlebar-h);
  left: 0;
  bottom: 0;
  width: 240px;
  background: var(--surface-2);
  border-right: 1px solid var(--border-3);
  display: flex;
  flex-direction: column;
  z-index: 60;
  transform: translateX(-100%);
  transition: transform 0.2s ease;
}
.files-rail.open { transform: translateX(0); }
.files-rail.hidden { display: none !important; }
/* Dashboard shell (5a) — files-rail + tab-bar are not shown in the new
   post-auth flow. The rail toggle button stays in the DOM (unused for now,
   not deleted per the 5a scope) but the rail itself never opens. */
.files-rail.dashboard-hidden { display: none !important; }
#tab-bar.dashboard-hidden { display: none !important; }

/* ── Left-rail user section (bottom) — chip + upward dropup ─────── */
.files-rail-user {
  position: relative;
  flex-shrink: 0;
  border-top: 1px solid var(--border-2);
  padding: 6px;
}
.files-rail-user-btn {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: transparent; border: 1px solid transparent; border-radius: 8px;
  padding: 6px 8px; cursor: pointer; color: var(--text); text-align: left;
  transition: background 0.1s;
}
.files-rail-user-btn:hover { background: var(--surface-3); }
.files-rail-user-avatar {
  width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0;
  background: var(--accent-bg, rgba(155,60,246,0.18)); color: var(--text);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; text-transform: uppercase;
}
.files-rail-user-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.files-rail-user-name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.files-rail-user-sub { font-size: 11px; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.files-rail-user-chevron { width: 14px; height: 14px; flex-shrink: 0; color: var(--text-3); transition: transform 0.15s; }
.files-rail-user.open .files-rail-user-chevron { transform: rotate(180deg); }
.files-rail-user-menu {
  position: absolute; left: 6px; right: 6px; bottom: calc(100% - 2px);
  background: var(--surface-2); border: 1px solid var(--border-3); border-radius: 8px;
  padding: 4px; box-shadow: 0 -4px 20px var(--shadow); z-index: 100;
}
.files-rail-user-menu.hidden { display: none; }
.files-rail-user-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: transparent; border: none; border-radius: 6px;
  padding: 7px 8px; cursor: pointer; color: var(--text); font-size: 13px; text-align: left;
}
.files-rail-user-item:hover { background: var(--surface-3); }
.files-rail-user-item.danger { color: var(--danger, #e0483d); }
.files-rail-user-item svg { width: 15px; height: 15px; flex-shrink: 0; }
.files-rail-user-divider { height: 1px; background: var(--border-2); margin: 4px 2px; }

.files-rail-resize {
  position: absolute;
  right: -4px;
  top: 0;
  bottom: 0;
  width: 8px;
  cursor: col-resize;
  z-index: 1;
}
.files-rail-resize::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 3px;
  height: 32px;
  background: transparent;
  border-radius: 2px;
  transition: background 0.15s;
}
.files-rail-resize:hover::after { background: var(--border-3); }
.files-rail-resize.dragging::after {
  background: var(--accent);
  height: 100%;
  width: 2px;
  border-radius: 0;
}

.files-rail-header {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 8px 0 12px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.files-rail-title {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 0;
  height: 24px;
  padding: 0 6px;
  background: transparent;
  border: none;
  border-radius: 5px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-2);
  cursor: pointer;
}
.files-rail-title:hover { background: var(--surface); color: var(--text); }
.files-rail-title svg { flex-shrink: 0; }
.files-rail-title span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Top: launcher buttons. Height is driven by the draggable split below;
   the recents pane takes the remaining space. */
.files-rail-nav {
  flex: 0 0 var(--rail-nav-h, 280px);
  min-height: 80px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 6px;
  gap: 1px;
}
/* Legacy spacer — no longer pushes anything to the rail bottom now that
   Platform + Sign Out are gone, but kept as a small floor inside the nav. */
.files-rail-spacer { flex: 0 0 8px; }

/* Draggable divider between the launcher nav and Recents. */
.rail-split-handle {
  flex: 0 0 6px;
  position: relative;
  cursor: row-resize;
  background: transparent;
}
.rail-split-handle::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  top: 50%; transform: translateY(-50%);
  height: 1px;
  background: var(--border);
  transition: background 0.15s, height 0.15s;
}
.rail-split-handle:hover::after { background: var(--border-3); height: 2px; }
.rail-split-handle.dragging::after { background: var(--accent); height: 2px; }

/* Middle: Recents — app-centric grid. Fixed height (resizable via the
   split handle below it); Workspaces takes the remaining space. */
.rail-recents {
  flex: 0 0 var(--rail-recents-h, 200px);
  min-height: 80px;
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--border);
  padding: 8px;
  gap: 6px;
  position: relative;
}
.rail-recents-header {
  display: flex;
  align-items: center;
  gap: 6px;
}
.rail-recents-title {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-3);
  white-space: nowrap;
}
.rail-recents-spacer { flex: 1; }
/* Per-section clear button on Recents + Workspaces headers (far right).
   Ghost icon button; reveals on header hover. */
.rail-section-clear {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-3);
  border-radius: 4px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 120ms ease, background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.rail-recents-header:hover .rail-section-clear { opacity: 0.7; }
.rail-section-clear:hover {
  opacity: 1;
  background: var(--surface);
  border-color: var(--border);
  color: var(--text);
}
.rail-recents-add {
  width: 20px; height: 20px;
  display: flex; align-items: center; justify-content: center;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text-2);
  cursor: pointer;
  font-size: 13px; font-weight: 600; line-height: 1;
  transition: border-color 120ms ease, color 120ms ease;
}
.rail-recents-add:hover { border-color: var(--accent); color: var(--text); }
.rail-recents-add-menu {
  position: absolute;
  top: 32px; right: 8px;
  min-width: 120px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 5px;
  box-shadow: 0 4px 16px var(--overlay-bg);
  padding: 3px;
  z-index: 20;
  display: flex; flex-direction: column;
}
.rail-recents-add-menu.hidden { display: none; }
.rail-recents-add-menu button {
  background: transparent; border: none;
  padding: 5px 8px;
  text-align: left;
  color: var(--text);
  font-family: inherit; font-size: 11px;
  cursor: pointer;
  border-radius: 3px;
}
.rail-recents-add-menu button:hover { background: var(--surface); color: var(--text); }
.rail-recents-search {
  width: 100%; box-sizing: border-box;
  padding: 4px 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-family: inherit;
  font-size: 11px;
  outline: none;
  transition: border-color 120ms ease;
}
.rail-recents-search:focus { border-color: var(--accent); }
.rail-recents-list {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  /* Grid of app cells — fits at least 2 across, expands as the rail widens. */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: 6px;
  padding: 2px;
  align-content: start;
}
.rail-recents-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 6px 4px;
  border-radius: 6px;
  cursor: pointer;
  background: transparent;
  border: 1px solid transparent;
  color: var(--text);
  font-family: inherit;
  min-width: 0;
  transition: background 120ms ease, border-color 120ms ease, transform 120ms ease;
}
/* Slight magnify on hover (Recents + Apps). */
.rail-recents-cell:hover { background: var(--surface); border-color: var(--border); transform: scale(1.07); }
/* Apps section: fills the rail below the nav (Workspaces removed); list scrolls. */
.rail-apps { flex: 1 1 0; min-height: 0; }
.rail-recents-icon {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: var(--surface-2);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  flex-shrink: 0;
}
.rail-recents-icon-img {
  width: 20px;
  height: 20px;
  object-fit: contain;
}
.rail-recents-icon-initial {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
  font-family: inherit;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}
.rail-recents-name {
  font-size: 10.5px;
  color: var(--text-2);
  text-align: center;
  line-height: 1.2;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail-recents-cell:hover .rail-recents-name { color: var(--text); }
/* Empty-state row spans the whole grid so it isn't squished into one cell. */
.rail-recents-empty { grid-column: 1 / -1; }
.rail-recents-empty {
  padding: 12px 8px;
  font-size: 11px;
  color: var(--text-3);
  text-align: center;
  border: 1px dashed var(--border);
  border-radius: 5px;
  line-height: 1.4;
}
.rail-recents-more {
  align-self: stretch;
  padding: 4px 8px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text-2);
  font-family: inherit; font-size: 11px;
  cursor: pointer;
  transition: border-color 120ms ease, color 120ms ease;
}
.rail-recents-more:hover { border-color: var(--accent); color: var(--text); }
.files-rail-navitem {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 28px;
  padding: 0 8px;
  background: transparent;
  border: none;
  border-radius: 5px;
  font-size: 12.5px;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.files-rail-navitem svg { flex-shrink: 0; color: var(--text-3); }
.files-rail-navitem:hover { background: var(--surface); }
.files-rail-navhead { margin-top: 4px; }
.files-rail-navchevron {
  margin-left: auto;
  font-size: 9px;
  color: var(--text-3);
  transition: transform 0.12s;
}
.files-rail-navhead.open .files-rail-navchevron { transform: rotate(180deg); }
.files-rail-navdanger { color: var(--danger); }
.files-rail-navdanger svg { color: var(--danger); }
.files-rail-navdanger:hover { background: rgba(213, 99, 91, 0.12); }
.files-rail-settings-menu {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.files-rail-settings-menu.hidden { display: none; }
.files-rail-settings-menu .files-rail-navitem { height: 26px; font-size: 12px; }
.files-rail-menu-divider {
  height: 1px;
  margin: 5px 8px;
  background: var(--border);
}

/* Right-click context menu */
.files-rail-ctx {
  position: fixed;
  z-index: 200;
  min-width: 130px;
  padding: 4px;
  background: var(--surface-2);
  border: 1px solid var(--border-3);
  border-radius: 6px;
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.35);
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.files-rail-ctx.hidden { display: none; }
.files-rail-ctx button {
  height: 26px;
  padding: 0 10px;
  background: transparent;
  border: none;
  border-radius: 4px;
  font-size: 12.5px;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.files-rail-ctx button:hover { background: var(--surface); }
.files-rail-ctx-sep {
  height: 1px;
  margin: 4px 6px;
  background: var(--border);
}
.files-rail-ctx-danger { color: var(--danger); }
.files-rail-ctx-danger:hover { background: rgba(213, 99, 91, 0.12) !important; }
.confirm-danger-btn {
  background: #d5635b;
  border-color: var(--danger);
  color: #fff;
}
.confirm-danger-btn:hover { background: #c4514a; border-color: #c4514a; }

/* Inline new file / folder input row */
.files-rail-input {
  flex: 1;
  min-width: 0;
  height: 18px;
  padding: 0 4px;
  background: var(--surface-2);
  border: 1px solid var(--accent);
  border-radius: 3px;
  font-size: 12.5px;
  font-family: inherit;
  color: var(--text);
  outline: none;
}
.files-rail-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 4px;
  color: var(--text-3);
  cursor: pointer;
}
.files-rail-btn:hover { background: var(--surface); color: var(--text); }

.files-rail-tree {
  flex: 1;
  overflow-y: auto;
  padding: 4px 0 12px;
  font-size: 12.5px;
  user-select: none;
}
.files-rail-row {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 22px;
  padding-right: 8px;
  cursor: pointer;
  white-space: nowrap;
  color: var(--text);
}
.files-rail-row:hover { background: var(--surface); }
.files-rail-row.active { background: var(--accent-soft, rgba(175, 95, 255,0.14)); }
.files-rail-caret {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  flex-shrink: 0;
  color: var(--text-3);
  transition: transform 0.12s;
}
.files-rail-caret.open { transform: rotate(90deg); }
.files-rail-caret.leaf { visibility: hidden; }
.files-rail-name {
  overflow: hidden;
  text-overflow: ellipsis;
}
.files-rail-icon { flex-shrink: 0; color: var(--text-3); }
.files-rail-empty {
  padding: 16px 12px;
  font-size: 12px;
  color: var(--text-3);
  line-height: 1.5;
}

.yo-panel-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border-2);
  flex-shrink: 0;
}

.yo-history-toggle,
.yo-chat-new {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 16px;
  cursor: pointer;
  padding: 0 2px;
  line-height: 1;
  transition: color 0.15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.yo-history-toggle:hover,
.yo-chat-new:hover { color: var(--white); }

.yo-panel-title { font-weight: 600; }
.yo-panel-header-spacer { flex: 1; }

/* History is a dropdown anchored under the clock button in the header.
   Replaces the old inline panel + the panel close X (rail toggle is the
   close affordance now). */
.yo-history {
  position: absolute;
  top: calc(100% + 4px);
  right: 38px;
  width: 260px;
  max-height: 320px;
  display: flex;
  flex-direction: column;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-radius: 8px;
  box-shadow: 0 8px 24px var(--overlay-bg);
  z-index: 30;
  overflow: hidden;
}
.yo-panel-header { position: relative; }
.yo-history.hidden { display: none; }

.yo-history-search {
  margin: 8px;
  padding: 6px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  font-family: inherit;
  font-size: 12px;
  outline: none;
  transition: border-color 120ms ease;
}
.yo-history-search:focus { border-color: var(--accent); }

.yo-history-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 0 8px;
}

.yo-history-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  cursor: pointer;
  transition: background 0.1s;
}
.yo-history-item:hover { background: var(--border); }

.yo-history-title {
  flex: 1;
  font-size: 12px;
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.yo-history-date {
  font-size: 11px;
  color: var(--text-muted);
  flex-shrink: 0;
}

.yo-history-delete {
  background: none;
  border: none;
  color: var(--text-faint);
  font-size: 14px;
  cursor: pointer;
  padding: 0 2px;
  line-height: 1;
  opacity: 0;
  transition: opacity 0.1s, color 0.1s;
}
.yo-history-item:hover .yo-history-delete { opacity: 1; }
.yo-history-delete:hover { color: var(--danger); }

.yo-history-empty {
  padding: 12px 14px;
  font-size: 12px;
  color: var(--text-muted);
}

.yo-history-section-header {
  padding: 8px 14px 4px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.yo-history-section-header:not(:first-child) {
  border-top: 1px solid var(--border-2);
  margin-top: 4px;
}

.yo-panel-title {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  color: var(--white);
  letter-spacing: -0.02em;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.yo-panel-title .yo-dot {
  color: var(--text);
}
/* Brand logo + ".Sup <name>" sit inside the panel title. Favicons are
   pre-designed square marks — no border-radius, no padding, no background. */
.yo-brand-logo {
  width: 20px;
  height: 20px;
  object-fit: contain;
  flex-shrink: 0;
  display: inline-block;
}
.yo-brand-logo[src=""],
.yo-brand-logo:not([src]) { display: none; }
.yo-brand-text {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}

.yo-panel-close {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 20px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
  transition: color 0.15s;
}
.yo-panel-close:hover { color: var(--white); }

.yo-panel-messages {
  flex: 1;
  overflow-y: auto;
  padding: 12px 22px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
}

/* ── Yo scroll-to-bottom button ──────────────── */

.yo-scroll-btn {
  position: absolute;
  left: 50%;
  bottom: 110px;
  transform: translateX(-50%);
  z-index: 10;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1px solid var(--border-3);
  background: var(--surface-2);
  color: var(--text-2);
  cursor: pointer;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 0;
  opacity: 0;
  transition: opacity 0.2s;
  box-shadow: 0 1px 4px rgba(0,0,0,0.2);
}
.yo-scroll-btn:hover {
  background: var(--accent);
  color: var(--white, #fff);
  border-color: var(--accent);
}
.yo-scroll-btn.visible {
  display: flex;
  opacity: 0.9;
}
.yo-scroll-btn svg {
  display: block;
}

/* ── Yo panel welcome ────────────────────────── */

.yo-panel-welcome {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: left;
  gap: 6px;
  padding: 24px 20px;
  animation: yo-welcome-in 0.4s ease-out;
}
.yo-welcome-logo {
  margin-bottom: 6px;
  /* The logo PNG carries transparent padding on its left, so the visible mark
     sits indented from the greeting text below. Nudge it left to align. */
  margin-left: -6px;
}
.yo-welcome-logo .glyphh-logo { height: 72px; }
.yo-welcome-tagline {
  font-size: 13px;
  color: var(--text-3);
  margin-bottom: 18px;
}
.yo-welcome-hints {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  max-width: 280px;
}
.yo-welcome-hint {
  font-size: 12.5px;
  color: var(--text-3);
  padding: 10px 14px;
  background: var(--hover);
  border: 1px solid var(--border-2);
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.yo-welcome-hint:hover {
  background: var(--border-2);
  border-color: rgba(175, 95, 255, 0.25);
  color: var(--text);
}
@keyframes yo-welcome-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ── Tutorial modal ──────────────────────────── */

.tutorial-overlay {
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: var(--overlay-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: tut-fade-in 0.3s ease;
}
.tutorial-overlay.hidden { display: none !important; }

@keyframes tut-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.tutorial-card {
  background: var(--hover);
  border: 1px solid var(--border-2);
  border-radius: 16px;
  width: 440px;
  max-width: 90vw;
  padding: 36px 32px 28px;
  position: relative;
  animation: tut-card-in 0.4s ease-out;
}
@keyframes tut-card-in {
  from { opacity: 0; transform: translateY(20px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

.tutorial-close {
  position: absolute;
  top: 12px;
  right: 16px;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 22px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
}
.tutorial-close:hover { color: var(--white); }

.tutorial-logo {
  display: flex;
  justify-content: center;
  margin-bottom: 4px;
}
.tutorial-logo .glyphh-logo { height: 64px; }
/* .tutorial-dot-sm still styles the dot in the .yo/.sup/.dip command demos. */
.tutorial-dot-sm { color: var(--text); }

.tutorial-sub {
  text-align: center;
  font-size: 13px;
  color: var(--text-3);
  margin-bottom: 28px;
}

.tutorial-steps {
  position: relative;
  min-height: 180px;
}

.tutorial-step {
  display: none;
  flex-direction: column;
  gap: 14px;
  animation: tut-step-in 0.35s ease-out;
}
.tutorial-step.active { display: flex; }

@keyframes tut-step-in {
  from { opacity: 0; transform: translateX(30px); }
  to { opacity: 1; transform: translateX(0); }
}

.tutorial-demo {
  background: var(--bg-raised);
  border: 1px solid var(--border-2);
  border-radius: 10px;
  padding: 16px 18px;
  min-height: 48px;
  display: flex;
  align-items: center;
}

.tutorial-input-mock {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--text);
  display: flex;
  align-items: center;
}

.tutorial-cursor {
  color: var(--text);
  animation: tut-blink 0.8s step-end infinite;
  margin-right: 0;
  font-weight: 300;
}
@keyframes tut-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}

.tutorial-kbd-mock {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.tutorial-key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 36px;
  padding: 0 10px;
  background: var(--surface-2);
  border: 1px solid var(--border-3);
  border-radius: 8px;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 500;
  box-shadow: 0 2px 0 var(--border);
}

.tutorial-cmd {
  font-size: 28px;
  font-weight: 700;
  color: var(--white);
  letter-spacing: -0.5px;
}

.tutorial-desc {
  font-size: 14px;
  color: var(--text-2);
  line-height: 1.6;
}

.tutorial-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 24px;
}

.tutorial-dots {
  display: flex;
  gap: 8px;
}

.tutorial-nav-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--border-3);
  transition: background 0.2s;
}
.tutorial-nav-dot.active { background: var(--accent); }

/* The Next / Get Started button reuses the auth screens' primary button
   (.btn.btn-primary.btn-lg — see sections/tutorial.html). */

/* ── Messages ─────────────────────────────────── */

.yo-msg {
  max-width: 100%;
  font-size: 12.5px;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: var(--font-sans);
}

.yo-msg-user {
  align-self: flex-end;
  max-width: 85%;
  background: var(--border-2);
  color: var(--text);
  padding: 10px 14px;
  border-radius: 14px 14px 4px 14px;
  font-weight: 450;
}

.yo-msg-assistant {
  align-self: flex-start;
  color: var(--text);
  padding: 4px 0;
  white-space: normal;
  position: relative;
}

/* ── Agent phase indicators ("Thinking…" / "Actioning…") ─────────────── */
.yo-phase {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 2px;
  font-size: 13px;
  color: var(--text-faint);
}
.yo-phase-icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.yo-phase-thinking .yo-phase-icon::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-faint);
  opacity: 0.65;
}
.yo-phase-actioning .yo-phase-icon::before {
  content: "✱";
  color: #FF2D55;
  font-size: 14px;
  line-height: 1;
}

/* ── Task-run marker (top of a persisted scheduled/manual run) ───────────── */
.yo-run-marker {
  align-self: stretch;
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  text-align: left;
  padding: 10px 12px;
  margin-bottom: 8px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2, rgba(127,127,127,0.06));
  font: inherit;
  font-size: 12.5px;
  color: var(--text-2, var(--text));
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}
.yo-run-marker:hover {
  border-color: var(--accent, #af5fff);
  background: var(--surface-3, rgba(127,127,127,0.10));
}
.yo-run-marker > svg { width: 16px; height: 16px; stroke: var(--accent, #af5fff); flex-shrink: 0; }
.yo-run-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.yo-run-label { font-weight: 600; color: var(--text); }
.yo-run-skill {
  font-size: 11.5px;
  color: var(--text-2, var(--text));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.yo-run-chevron {
  width: 16px; height: 16px;
  stroke: var(--text-faint, #9ca3af) !important;
  flex-shrink: 0;
}

/* ── Swarm activity (inline in the yo panel) ─────────────────────────────── */
.yo-msg-swarm-start {
  align-self: stretch;
  white-space: normal;
  border: 1px solid var(--border);
  border-left: 3px solid #A855F7;
  border-radius: 8px;
  padding: 8px 12px;
  background: rgba(175, 95, 255, 0.06);
}
.swarm-start-title { font-weight: 700; font-size: 12.5px; color: var(--text); }
.swarm-start-goal { font-size: 11.5px; color: var(--text-2); margin: 2px 0 6px; }
.swarm-start-roster { display: flex; flex-wrap: wrap; gap: 6px; }
.swarm-roster-chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 10.5px; color: var(--text-2);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 5px; padding: 2px 6px 2px 3px;
}

.yo-msg-swarm {
  align-self: stretch;
  white-space: normal;
  display: flex; gap: 8px; align-items: flex-start;
  padding: 4px 0;
}
.swarm-badge {
  width: 20px; height: 20px; border-radius: 5px; flex-shrink: 0;
  overflow: hidden; display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface); border: 1px solid var(--border);
}
.swarm-badge img { width: 14px; height: 14px; object-fit: contain; }
.member-badge-initial { font-size: 11px; font-weight: 700; color: var(--text-2); }
.swarm-body { flex: 1; min-width: 0; }
.swarm-meta { display: flex; gap: 6px; align-items: baseline; }
.swarm-from { font-weight: 700; font-size: 11px; color: var(--text); }
.swarm-to { font-size: 11px; color: var(--text-3); }
.swarm-kind {
  font-size: 8.5px; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; padding: 1px 5px; border-radius: 3px;
}
.swarm-text {
  font-size: 11.5px; color: var(--text-2); margin-top: 2px;
  word-break: break-word; line-height: 1.5;
}
/* Markdown rendered inside a swarm row — keep it compact for the feed. */
.swarm-text > :first-child { margin-top: 0; }
.swarm-text > :last-child { margin-bottom: 0; }
.swarm-text p { margin: 4px 0; }
.swarm-text ul, .swarm-text ol { margin: 4px 0; padding-left: 18px; }
.swarm-text li { margin: 1px 0; }
.swarm-text h1, .swarm-text h2, .swarm-text h3,
.swarm-text h4, .swarm-text h5, .swarm-text h6 {
  margin: 8px 0 3px; font-size: 12px; font-weight: 700; color: var(--text);
}
.swarm-text pre {
  margin: 4px 0; padding: 7px 9px; background: var(--surface-3);
  border: 1px solid var(--border); border-radius: 5px;
  overflow-x: auto; font-size: 10.5px;
}
.swarm-text code { font-size: 10.5px; }
.swarm-text strong { color: var(--text); }

/* Long bodies collapse behind a Show more / less toggle. */
.swarm-collapsible .swarm-text {
  max-height: 8.4em;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent);
  mask-image: linear-gradient(to bottom, #000 70%, transparent);
}
.swarm-collapsible.swarm-expanded .swarm-text {
  max-height: none;
  -webkit-mask-image: none;
  mask-image: none;
}
.swarm-toggle {
  margin-top: 4px;
  background: none; border: none; padding: 0;
  color: var(--text); font-size: 10.5px; font-weight: 600;
  font-family: inherit; cursor: pointer;
}
.swarm-toggle:hover { text-decoration: underline; }

.yo-msg-actions {
  display: flex;
  justify-content: flex-end;
  padding: 4px 0 0;
  opacity: 0;
  transition: opacity 0.15s;
}
.yo-msg-assistant:hover .yo-msg-actions {
  opacity: 1;
}

.yo-msg-copy-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: none;
  border: 1px solid var(--border-3);
  border-radius: 6px;
  color: var(--text-3);
  font-size: 11px;
  padding: 3px 8px;
  cursor: pointer;
  font-family: inherit;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.yo-msg-copy-btn:hover {
  color: var(--text);
  border-color: var(--text-muted);
  background: var(--border);
}
.yo-msg-copy-btn.yo-copied {
  color: var(--text);
  border-color: rgba(175, 95, 255, 0.33);
}
.yo-msg-copy-btn svg {
  flex-shrink: 0;
}

.yo-msg-status {
  font-size: 13px;
  color: var(--text-3);
  padding: 6px 0;
  display: flex;
  align-items: center;
  gap: 10px;
}

.yo-msg-error {
  color: var(--danger);
  font-size: 12px;
  padding: 6px 12px;
  background: rgba(255, 95, 87, 0.08);
  border-radius: 8px;
  border: 1px solid rgba(255, 95, 87, 0.15);
}

.yo-msg-stopped {
  color: var(--text-2);
  font-size: 12px;
  padding: 6px 12px;
}

.yo-msg-chat {
  align-self: flex-start;
  white-space: normal;
  background: rgba(175, 95, 255, 0.06);
  border-radius: 2px 12px 12px 12px;
  padding: 6px 10px;
  max-width: 80%;
}
.yo-chat-header {
  display: flex; align-items: baseline; gap: 6px;
  margin-bottom: 2px;
}
.yo-chat-sender { font-size: 11px; font-weight: 600; color: #A855F7; }
.yo-chat-time { font-size: 9px; opacity: 0.4; margin-left: auto; }
.yo-chat-body { font-size: 12.5px; color: var(--text); line-height: 1.45; }
.yo-msg-chat-local {
  align-self: flex-end;
  background: rgba(175, 95, 255, 0.1);
  border-radius: 12px 2px 12px 12px;
}
.yo-msg-chat-local .yo-chat-sender { color: var(--text); }

/* ── Activity timeline (result items with connecting line) ── */

.yo-ag-timeline {
  position: relative;
  padding-left: 20px;
  margin: 4px 0;
}
.yo-ag-timeline::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 0;
  bottom: 0;
  width: 1.5px;
  background: rgba(175, 95, 255, 0.35);
}
.yo-ag-timeline.done::before {
  background: rgba(175, 95, 255, 0.15);
}

/* ── Tool row (per-call: dot + bold name + subtitle) ── */
.yo-result-block {
  position: relative;
  margin: 10px 0;
  animation: yo-block-in 0.2s ease-out;
}
@keyframes yo-block-in {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}

.yo-result-header {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 2px 0;
  font-size: 12px;
}

/* Dot on the timeline — filled when active/done; pulses while running */
.yo-ag-dot {
  position: absolute;
  left: -18px;
  top: 6px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  border: 1.5px solid var(--accent);
  z-index: 1;
}
.yo-result-block.yo-active .yo-ag-dot {
  animation: yo-dot-pulse 1.2s ease-in-out infinite;
  box-shadow: 0 0 0 0 rgba(175, 95, 255, 0.6);
}
@keyframes yo-dot-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(175, 95, 255, 0.55); }
  70%  { box-shadow: 0 0 0 6px rgba(175, 95, 255, 0); }
  100% { box-shadow: 0 0 0 0 rgba(175, 95, 255, 0); }
}

.yo-result-headings {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1;
}
/* Title line — "<Tool>  <file/arg>" on a single row */
.yo-result-titleline {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}
.yo-result-name {
  color: var(--text);
  font-weight: 700;
  font-size: 12px;
  line-height: 1.35;
  flex-shrink: 0;
}
.yo-result-file {
  color: var(--text-3);
  font-weight: 400;
  font-size: 11.5px;
  line-height: 1.4;
  font-family: var(--font-mono);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.yo-result-progress {
  color: var(--text-3);
  font-size: 11px;
  font-style: italic;
  flex-shrink: 0;
}

/* File label that opens the file in the OS default app on click */
.yo-result-file.yo-file-link {
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: transparent;
  transition: color 0.12s, text-decoration-color 0.12s;
}
.yo-result-file.yo-file-link:hover {
  color: var(--text);
  text-decoration-color: var(--accent);
}

/* Tool stat line — Claude-Code style one-liner under the header.
   Always visible when a tool finishes; clicking it expands the output. */
.yo-tool-stat {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
  font-size: 11px;
  color: var(--text-3);
  font-family: var(--font-mono);
  user-select: none;
}
.yo-tool-stat::before {
  content: "⎿";
  color: var(--text-3);
  opacity: 0.6;
}
.yo-result-block.yo-has-detail .yo-tool-stat { cursor: pointer; }
.yo-result-block.yo-has-detail .yo-tool-stat:hover { color: var(--text); }
.yo-tool-stat-chevron {
  font-size: 9px;
  transition: transform 0.15s ease;
}
.yo-result-block.yo-expanded .yo-tool-stat-chevron { transform: rotate(90deg); }

/* Delegate instruction box — bordered, collapsible */
.yo-delegate-instruction {
  margin-top: 4px;
  padding: 6px 10px;
  border: 1px solid var(--border-2);
  border-radius: 6px;
  font-size: 11.5px;
  color: var(--text-2);
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  cursor: pointer;
}
.yo-delegate-instruction:hover { border-color: var(--border-3); }
.yo-delegate-preview { display: block; }
.yo-delegate-full { display: block; }
.yo-delegate-expanded { border-color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, var(--border-2)); }

/* Full tool output — hidden until the stat line is clicked. */
.yo-result-content {
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  margin-top: 4px;
  margin-left: 12px;
  font-size: 11px;
  font-family: var(--font-mono);
  color: var(--text-2);
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 360px;
  overflow-y: auto;
  display: none;
}
.yo-result-block.yo-expanded .yo-result-content {
  display: block;
}
/* When tool output is plain text wrapped in <pre>, normalize the inner block
   so it inherits scrolling + width from the parent .yo-result-content host. */
.yo-result-content .yo-tool-output {
  margin: 0;
  padding: 0;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: inherit;
  color: inherit;
  background: transparent;
  border: 0;
}
/* Code fences inside tool output: actual rendered code blocks. */
.yo-result-content pre code,
.yo-result-content code {
  font-family: var(--font-mono);
  color: var(--text);
}
.yo-result-content pre {
  background: var(--surface-2);
  border-radius: 4px;
  padding: 6px 8px;
  margin: 4px 0;
  overflow-x: auto;
}

/* ── Todo checklist ────────────────────────────── */
.yo-todo-checklist {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 0;
}
.yo-todo-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  line-height: 1.4;
}
.yo-todo-icon {
  width: 14px;
  text-align: center;
  font-size: 11px;
  color: var(--text-3);
  flex-shrink: 0;
}
.yo-todo-icon.yo-todo-done {
  color: var(--text);
  font-weight: 700;
}
.yo-todo-icon.yo-todo-active {
  color: var(--text);
  animation: yo-todo-pulse 1.2s ease-in-out infinite;
}
@keyframes yo-todo-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}
.yo-todo-label {
  color: var(--text);
}
.yo-todo-label-done {
  color: var(--text-2);
  text-decoration: line-through;
  text-decoration-color: var(--text-3);
}

/* Active spinner row (always at bottom of group) */
.yo-ag-active {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
}

.yo-ag-spinner {
  font-size: 18px;
  color: var(--text);
  width: 20px;
  text-align: center;
  flex-shrink: 0;
  font-family: var(--font-mono);
}

.yo-ag-phrase {
  font-size: 13px;
  color: var(--text-2);
}

/* ── Task items ───────────────────────────────── */

.yo-task-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 5px 0;
}
.yo-task-check {
  color: var(--text);
  font-size: 11px;
  flex-shrink: 0;
  margin-top: 2px;
  width: 16px;
  height: 16px;
  border: 1.5px solid var(--accent);
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
}
.yo-task-text {
  flex: 1;
  color: var(--text);
}

/* ── Markdown rendering ──────────────────────── */

.yo-md-p {
  margin: 0 0 8px;
  line-height: 1.55;
}
.yo-md-p:last-child { margin-bottom: 0; }

.yo-md-h1, .yo-md-h2, .yo-md-h3, .yo-md-h4 {
  color: var(--text);
  font-weight: 600;
  margin: 14px 0 6px;
  line-height: 1.3;
}
.yo-md-h1 { font-size: 15px; }
.yo-md-h2 { font-size: 14px; }
.yo-md-h3 { font-size: 13px; }
.yo-md-h4 { font-size: 13px; color: var(--text); }
.yo-msg-assistant > .yo-md-h1:first-child,
.yo-msg-assistant > .yo-md-h2:first-child,
.yo-msg-assistant > .yo-md-h3:first-child,
.yo-msg-assistant > .yo-md-h4:first-child { margin-top: 0; }

/* Inline code READS in every theme (his report, 2026-09-27, again): the chip
   used the border colour as its ground and the accent-ish --code-inline as
   its ink — purple on dark purple, grey on grey. It is a raised surface with
   the theme's own body text now, so whatever a theme defines for text on its
   surfaces is what the chip shows. High-vis by construction. */
.yo-md-inline {
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border-2);
  padding: 1px 5px;
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
}
.yo-md-cmd {
  cursor: pointer;
  border: 1px solid var(--border-2);
  padding: 2px 7px;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.yo-md-cmd:hover {
  background: var(--accent-bg);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--text);
}
.yo-md-cmd.yo-cmd-copied {
  background: color-mix(in srgb, var(--success) 14%, transparent);
  border-color: color-mix(in srgb, var(--success) 50%, transparent);
  color: var(--text);
}

.yo-md-link {
  color: var(--text);
  text-decoration: none;
}
.yo-md-link:hover { text-decoration: underline; }

.yo-md-ul, .yo-md-ol {
  margin: 4px 0 8px;
  padding-left: 20px;
}
.yo-md-ul li, .yo-md-ol li {
  margin: 2px 0;
  line-height: 1.55;
}
.yo-md-ul { list-style: disc; }
.yo-md-ol { list-style: decimal; }

.yo-md-quote {
  border-left: 3px solid var(--accent);
  padding: 4px 12px;
  margin: 6px 0;
  color: var(--text-2);
  font-style: italic;
  white-space: pre-wrap;
}

.yo-md-hr {
  border: none;
  border-top: 1px solid var(--border-2);
  margin: 10px 0;
}

/* ── Code blocks (collapsible, with copy) ───── */

.yo-md-codeblock {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin: 8px 0;
  overflow: hidden;
}

.yo-md-codeblock-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 5px 10px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.yo-md-codeblock-lang {
  font-size: 11px;
  color: var(--text-3);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}

.yo-md-codeblock-actions { display: flex; align-items: center; gap: 4px; }
.yo-md-copy-btn, .yo-md-run-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 22px;
  background: none;
  border: 1px solid var(--border-3);
  border-radius: 4px;
  color: var(--text-3);
  padding: 0;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.yo-md-copy-btn:hover, .yo-md-run-btn:hover {
  color: var(--text);
  border-color: var(--text-muted);
  background: var(--border);
}
/* Copied reads as DONE in every theme: the theme's own success colour. */
.yo-md-copy-btn.yo-copied, .yo-md-run-btn.yo-copied {
  color: var(--success);
  border-color: color-mix(in srgb, var(--success) 50%, transparent);
}
.yo-md-copy-btn:focus-visible, .yo-md-run-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.yo-md-pre {
  margin: 0;
  padding: 10px 12px;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  color: var(--text);
  white-space: pre;
  max-height: 300px;
  overflow-y: auto;
}
.yo-md-pre code {
  font-family: inherit;
  font-size: inherit;
}

/* ── SYNTAX TOKENS (highlight.ts) — his order, 2026-09-29: "theme aligned per
   selected theme". No palette lives here: every token maps onto a SEMANTIC
   variable each theme already defines (its accent, success, warning, blue,
   purple, danger, faint text), so High Vis, its light mirror, Nord, Dracula,
   Synthwave and the rest each colour code in their own voice. ── */
.tk-keyword  { color: var(--accent-text, var(--accent)); }
.tk-string   { color: var(--success); }
.tk-number,
.tk-builtin,
.tk-regex    { color: var(--warning); }
.tk-function { color: var(--blue); }
.tk-type     { color: var(--purple, var(--accent)); }
.tk-variable { color: var(--purple, var(--accent)); }
.tk-property,
.tk-attr     { color: color-mix(in srgb, var(--blue) 65%, var(--text)); }
.tk-tag      { color: var(--danger-soft, var(--danger)); }
.tk-comment  { color: var(--text-faint, var(--text-3)); font-style: italic; }
.tk-operator,
.tk-punct    { color: var(--text-3); }
.tk-inserted { color: var(--success); background: color-mix(in srgb, var(--success) 12%, transparent); display: inline-block; min-width: 100%; }
.tk-deleted  { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, transparent); display: inline-block; min-width: 100%; }


/* ── Working-directory bar (sits directly above the composer) ── */

.yo-workdir-bar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 16px 0;
  flex-shrink: 0;
}
.yo-workdir-btn,
.yo-workdir-add {
  background: transparent;
  border: 1px solid transparent;
  padding: 4px 8px;
  border-radius: 6px;
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 6px;
  transition: background 0.10s, border-color 0.10s, color 0.10s;
}
.yo-workdir-btn:hover,
.yo-workdir-add:hover {
  background: var(--hover);
  color: var(--text);
  border-color: var(--border-2);
}
/* Drips button — far right of the workdir bar (replaces the old animated dot). */
.yo-workdir-drip {
  background: transparent;
  border: 1px solid transparent;
  padding: 3px 6px;
  margin-right: 4px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  display: flex;
  align-items: center;
  transition: background 0.10s, border-color 0.10s;
}
.yo-workdir-drip:hover { background: var(--hover); border-color: var(--border-2); }
.yo-workdir-branch {
  font-size: 12px;
  color: var(--text-faint);
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 4px 6px;
  cursor: pointer;
  border-radius: 6px;
  transition: background 0.10s, color 0.10s;
}
.yo-workdir-branch:hover { background: var(--hover); color: var(--text); }
.yo-workdir-bar svg {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  stroke: currentColor;
}
.yo-workdir-bar-spacer { flex: 1; }

/* Animated `.` dot on the far right of the workdir bar — ported from
   the (removed) Agent app so the right-rail Yo keeps the same affordance.
   Single oversized accent dot on a multi-pattern 4.2s loop. */
.agent-yo-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  user-select: none;
  padding-right: 8px;
  width: 24px;
  height: 24px;
}
.agent-yo-mark .agent-yo-dot {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent);
  animation: agent-dot-dance 4.2s ease-in-out infinite;
  will-change: transform, opacity;
  transform-origin: center;
}
@keyframes agent-dot-dance {
  0%   { transform: translate(0, 0) scale(1);        opacity: 1; }
  10%  { transform: translate(0, -8px) scale(1);     opacity: 1; }
  20%  { transform: translate(0, 0) scale(1);        opacity: 1; }
  30%  { transform: translate(-8px, 0) scale(0.85);  opacity: 0.7; }
  45%  { transform: translate(0, -6px) scale(1.25);  opacity: 1; }
  60%  { transform: translate(8px, 0) scale(0.85);   opacity: 0.7; }
  75%  { transform: translate(0, -10px) scale(1);    opacity: 1; }
  85%  { transform: translate(0, 0) scale(1.1);      opacity: 1; }
  100% { transform: translate(0, 0) scale(1);        opacity: 1; }
}

/* Workdir picker popup — fixed-positioned in JS above the bar. */
.yo-workdir-menu {
  position: fixed;
  display: none;
  min-width: 220px;
  max-width: 380px;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-radius: 8px;
  box-shadow: 0 6px 24px rgba(0,0,0,0.18);
  padding: 4px;
  z-index: 9500;
}
.yo-workdir-menu.open { display: block; }
.yo-workdir-menu-item {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 6px 10px;
  background: transparent;
  border: none;
  font: inherit;
  font-size: 12.5px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  border-radius: 4px;
}
.yo-workdir-menu-item:hover { background: var(--hover); }
.yo-workdir-menu-item .check {
  width: 14px; height: 14px;
  flex-shrink: 0;
  color: var(--text);
}
.yo-workdir-menu-item .check svg { width: 14px; height: 14px; }
.yo-workdir-menu-item .ic {
  width: 14px; height: 14px;
  flex-shrink: 0;
  color: var(--text-faint);
  display: inline-flex;
}
.yo-workdir-menu-item .ic svg { width: 14px; height: 14px; }
.yo-workdir-menu-item .nm {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.yo-workdir-menu-sep {
  height: 1px;
  background: var(--border-2);
  margin: 4px 2px;
}

/* Branch picker — reuses the workdir-menu surface; list grows upward
   and the search input sits at the bottom (closest to the click target). */
.yo-branch-menu {
  min-width: 240px;
  max-width: 360px;
  padding: 6px;
  display: none;
  flex-direction: column;
  gap: 6px;
}
.yo-branch-menu.open { display: flex; }
.yo-branch-list {
  max-height: 280px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.yo-branch-item {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 6px 10px;
  background: transparent;
  border: none;
  font: inherit;
  font-size: 12.5px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  border-radius: 4px;
}
.yo-branch-item:hover { background: var(--hover); }
.yo-branch-item .nm {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-mono);
}
.yo-branch-item .check {
  width: 14px; height: 14px;
  flex-shrink: 0;
  color: var(--text);
}
.yo-branch-item .check svg { width: 14px; height: 14px; }
.yo-branch-current .nm { color: var(--text); }
.yo-branch-empty {
  padding: 10px;
  color: var(--text-3);
  font-size: 12px;
  text-align: center;
}
.yo-branch-search-wrap {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 6px;
}
.yo-branch-search-icon { font-size: 11px; color: var(--text-3); }
.yo-branch-search {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  outline: none;
  color: var(--text);
  font: inherit;
  font-size: 12.5px;
}

/* ── Composer-area interaction (ask / approve takes over above the input) ──── */
/* The prompt is part of the panel, not a popup: no card, no tinted surface, no
   drop shadow. It shares the panel's background so it reads as the composer
   simply expanding upward. The only mode accent is the top divider (which lines
   up with the input's own top border) and the borders of the selected option. */
.yo-composer-interaction {
  flex-shrink: 0;
  /* Bottom padding = the gap between the question block and the input below. */
  padding: 11px 22px 12px;
  /* Top divider picks up the permission-mode color — the "top of the panel"
     border the user sees when the composer expands for a question. */
  border-top: 1px solid color-mix(in srgb, var(--yo-mode-color, var(--accent)) 55%, var(--border-2));
}
.yo-composer-interaction[hidden] { display: none; }

/* Persistent background-agent indicator — sits just above the input. */
.yo-bg-indicator {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 22px;
  font-size: 11px;
  color: var(--text-2);
}
.yo-bg-indicator[hidden] { display: none; }
.yo-bg-indicator-label { letter-spacing: 0.01em; }
.yo-bg-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--yo-mode-color, var(--accent));
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--yo-mode-color, var(--accent)) 60%, transparent);
  animation: yo-bg-pulse 1.4s ease-in-out infinite;
}
@keyframes yo-bg-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--yo-mode-color, var(--accent)) 55%, transparent); opacity: 1; }
  70%  { box-shadow: 0 0 0 5px color-mix(in srgb, var(--yo-mode-color, var(--accent)) 0%, transparent); opacity: 0.6; }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--yo-mode-color, var(--accent)) 0%, transparent); opacity: 1; }
}

/* The scroll-to-bottom arrow is absolutely positioned and would float over the
   question — suppress it while an interaction owns the composer. */
.yo-panel.interaction-active .yo-scroll-btn { display: none !important; }

/* When the composer is expanded for a question the interaction wrap already
   carries the (mode-colored) top divider, so drop the input's own top border —
   otherwise there'd be a second line between the question and the input,
   breaking the "one expanded panel" look. No border on the bottom. */
.yo-panel.interaction-active .yo-panel-input-wrap { border-top: none; }

.yo-ci-panel {
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0;
  outline: none;
  animation: yo-ci-rise 0.14s ease;
}
@keyframes yo-ci-rise {
  from { opacity: 0; transform: translateY(3px); }
  to   { opacity: 1; transform: translateY(0); }
}
.yo-ci-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 9px;
}
.yo-ci-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  color: var(--yo-mode-color, var(--accent));
}
.yo-ci-title {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--yo-mode-color, var(--accent)) 50%, var(--text-3));
}
/* Wizard step dots — pinned to the right of the header. */
.yo-ci-steps {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 5px;
}
.yo-ci-step-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--border-3);
  transition: background 0.15s ease, transform 0.15s ease;
}
.yo-ci-step-dot.done {
  background: color-mix(in srgb, var(--yo-mode-color, var(--accent)) 55%, transparent);
}
.yo-ci-step-dot.current {
  background: var(--yo-mode-color, var(--accent));
  transform: scale(1.3);
}
/* Body holds the current step's question + options; swapped per step. */
.yo-ci-body { animation: yo-ci-step-fade 0.14s ease; }
@keyframes yo-ci-step-fade {
  from { opacity: 0; transform: translateX(4px); }
  to   { opacity: 1; transform: translateX(0); }
}
.yo-ci-detail {
  margin: 0 0 4px;
  padding: 8px 10px;
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.45;
  color: var(--text-2);
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 140px;
  overflow-y: auto;
}
.yo-ci-question {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  margin: 2px 0 9px;
}
.yo-ci-options {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.yo-ci-option {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 11px;
  background: color-mix(in srgb, var(--surface-2) 70%, var(--surface));
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, box-shadow 0.12s;
}
.yo-ci-option:hover { background: var(--hover); }
/* Selection is shown by the mode-colored border + filled radio — no tinted
   (green) fill, so the option keeps the panel's neutral surface. */
.yo-ci-option.selected {
  border-color: var(--yo-mode-color, var(--accent));
}
.yo-ci-option.cursor {
  border-color: var(--yo-mode-color, var(--accent));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--yo-mode-color, var(--accent)) 25%, transparent);
}
.yo-ci-radio {
  flex-shrink: 0;
  width: 15px;
  height: 15px;
  margin-top: 1px;
  border: 1.5px solid var(--border-3);
  border-radius: 50%;
  transition: border-color 0.12s;
}
.yo-ci-option.selected .yo-ci-radio {
  border-color: var(--yo-mode-color, var(--accent));
  background:
    radial-gradient(circle, var(--yo-mode-color, var(--accent)) 0 4px, transparent 5px);
}
.yo-ci-option-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.yo-ci-option-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.yo-ci-option-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.yo-ci-option-desc {
  font-size: 12px;
  color: var(--text-3);
  line-height: 1.4;
}
.yo-ci-recommended {
  font-size: 10.5px;
  font-weight: 600;
  padding: 1px 7px;
  border-radius: 999px;
  color: var(--yo-mode-color, var(--accent-dark));
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--yo-mode-color, var(--accent)) 45%, var(--border));
}
.yo-ci-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}
.yo-ci-hint {
  margin-right: auto;
  font-size: 10.5px;
  color: var(--text-faint);
}
.yo-ci-btn {
  padding: 6px 13px;
  border-radius: 8px;
  border: 1px solid var(--border-2);
  background: var(--surface-2);
  color: var(--text-2);
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s, opacity 0.12s;
}
.yo-ci-btn:hover { background: var(--hover); color: var(--text); }
/* Primary action follows the active permission mode rather than a fixed green,
   so the whole interaction reads as one piece with the mode-tinted dividers. */
.yo-ci-btn.primary {
  background: var(--yo-mode-color, var(--accent));
  border-color: var(--yo-mode-color, var(--accent));
  color: #04230f;
  font-weight: 600;
}
.yo-ci-btn.primary:hover {
  background: color-mix(in srgb, var(--yo-mode-color, var(--accent)) 85%, #000);
  color: #04230f;
}
.yo-ci-btn.danger {
  border-color: color-mix(in srgb, var(--danger) 45%, var(--border-2));
  color: var(--danger);
}
.yo-ci-btn.danger:hover {
  background: var(--danger-bg);
  color: var(--danger);
}
.yo-ci-btn:disabled { opacity: 0.5; cursor: default; }

.yo-panel-input-wrap {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  padding: 8px 22px 8px;
  /* The composer's top divider highlights to the active permission mode so the
     whole input region reads as "in" that mode. Softened against the default
     border so it's a tasteful accent line, not a hard rule. */
  border-top: 1px solid color-mix(in srgb, var(--yo-mode-color, var(--accent)) 55%, var(--border-2));
  flex-shrink: 0;
}

#yo-panel-input {
  flex: 1;
  background: var(--surface-3);
  border: 1px solid var(--border-3);
  border-radius: 12px;
  padding: 10px 12px;
  color: var(--text);
  font-size: 13px;
  font-family: var(--font-sans);
  resize: none;
  outline: none;
  max-height: 160px;
  min-height: 40px;
  height: 40px;
  line-height: 1.5;
  overflow-y: auto;
}
#yo-panel-input:focus { border-color: var(--yo-mode-color, var(--accent)); }
#yo-panel-input::placeholder { color: var(--text-muted); }
#yo-panel-input.yo-input-disabled {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}

.yo-mic-btn {
  background: none;
  border: none;
  color: var(--text-3);
  font-size: 14px;
  cursor: pointer;
  flex-shrink: 0;
  padding: 4px;
  border-radius: 4px;
  margin-bottom: 8px;
  transition: color 0.15s, background 0.15s;
}
.yo-mic-btn:hover { color: var(--text-2); }
.yo-mic-btn.listening {
  color: var(--danger);
  animation: mic-pulse 1s ease-in-out infinite;
}
.yo-mic-btn.disabled {
  opacity: 0.3;
  cursor: not-allowed;
}
@keyframes mic-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

#yo-panel-send {
  background: var(--accent);
  color: #000;
  border: 2px solid transparent;
  box-sizing: border-box;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  flex-shrink: 0;
  transition: opacity 0.15s, background 0.15s, color 0.15s, border-color 0.15s;
  display: flex;
  align-items: center;
  justify-content: center;
}
#yo-panel-send:hover { opacity: 0.8; }
#yo-panel-send.yo-stop {
  background: transparent !important;
  border-color: var(--yo-mode-color, var(--accent));
  color: transparent;
  position: relative;
  font-size: 0;
}
#yo-panel-send.yo-stop::before {
  content: "";
  display: block;
  width: 10px;
  height: 10px;
  background: var(--yo-mode-color, var(--accent));
  border-radius: 2px;
}

/* ── Yo panel controls (mode + perm + drip + send) ─────────── */

.yo-panel-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px 10px;
  border-top: 1px solid var(--border-2);
  flex-shrink: 0;
  flex-wrap: wrap; /* never overflow the narrow panel — wrap controls instead */
}
/* Keep the send button pinned to the right edge of its row. */
#yo-panel-send { margin-left: auto; }

.yo-controls-spacer { flex: 1; }

.yo-control-select {
  flex: 1;
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  border-radius: 6px;
  padding: 4px 8px;
  color: var(--text-2);
  font-size: 11px;
  font-family: var(--font-mono);
  cursor: pointer;
  outline: none;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg width='8' height='5' viewBox='0 0 8 5' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l3 3 3-3' stroke='%23666' stroke-width='1.2' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  padding-right: 22px;
}
.yo-control-select:hover { border-color: var(--text-faint); color: var(--text); }
.yo-control-select:focus { border-color: var(--yo-mode-color, var(--accent)); }

/* ── Custom mode dropdown ──────────────────────────────── */

.yo-mode-dropdown {
  position: relative;
}
#yo-perm-dropdown {
  flex: 1;
}

.yo-mode-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 5px;
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  border-radius: 6px;
  padding: 4px 8px;
  color: var(--white);
  font-size: 11px;
  font-family: var(--font-mono);
  cursor: pointer;
  outline: none;
  transition: border-color 0.15s;
}
.yo-mode-trigger:hover { border-color: var(--text-faint); }
.yo-mode-trigger .yo-mode-icon { font-size: 12px; line-height: 1; }
.yo-mode-trigger .yo-mode-label { flex: 1; text-align: left; text-transform: lowercase; }
.yo-mode-trigger .yo-mode-chevron { color: var(--text-3); font-size: 10px; margin-left: auto; }

.yo-mode-menu {
  position: absolute;
  bottom: calc(100% + 4px);
  left: 0;
  min-width: 180px;
  background: var(--surface-2);
  border: 1px solid var(--border-3);
  border-radius: 8px;
  padding: 4px;
  z-index: 100;
  box-shadow: 0 -4px 20px var(--shadow);
}
.yo-mode-menu.hidden { display: none; }

.yo-mode-option,
.yo-perm-option,
.yo-type-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 5px;
  cursor: pointer;
  transition: background 0.1s;
}
.yo-mode-option:hover,
.yo-perm-option:hover,
.yo-type-option:hover { background: var(--hover); }
.yo-mode-option.active,
.yo-perm-option.active,
.yo-type-option.active { background: var(--border); }

/* Plan checkbox — binary modifier, sits next to the perm dropdown */
.yo-plan-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  border-radius: 6px;
  color: var(--text-2);
  font-size: 11px;
  font-family: var(--font-mono);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
  user-select: none;
}
.yo-plan-toggle input { position: absolute; opacity: 0; pointer-events: none; }
.yo-plan-toggle:hover { border-color: var(--text-faint); }
.yo-plan-toggle:has(input:checked) {
  background: rgba(139, 92, 246, 0.15);
  border-color: #8B5CF6;
  color: #8B5CF6;
}
.yo-plan-icon { font-size: 12px; line-height: 1; }

/* Model dropdown — section headers separate Claude / GPT, disabled rows
   are dimmed and unclickable. */
.yo-model-section-header {
  padding: 6px 8px 2px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.yo-model-section-header:not(:first-child) {
  border-top: 1px solid var(--border-2);
  margin-top: 4px;
  padding-top: 8px;
}
.yo-model-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 5px;
  cursor: pointer;
  transition: background 0.1s;
}
.yo-model-option:hover { background: var(--hover); }
.yo-model-option.active { background: var(--border); }
.yo-model-option.disabled {
  cursor: not-allowed;
  opacity: 0.45;
}
.yo-model-option.disabled:hover { background: transparent; }

/* Composer model menu — ⓘ info button + themed tooltip. The sub line stays
   a one-line summary; the full story (role, RAM, download size, state)
   opens in a small themed tip that never triggers a model switch. */
#code-model-menu .code-drop-item { position: relative; }

.model-info-btn {
  margin-left: auto;
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-faint);
  font-size: 10px;
  line-height: 1;
  font-style: italic;
  font-family: Georgia, "Times New Roman", serif;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

.model-info-btn:hover {
  color: var(--text);
  border-color: var(--text-faint);
}

.model-info-tip {
  position: absolute;
  right: 10px;
  bottom: calc(100% - 4px);
  z-index: 40;
  width: 230px;
  padding: 9px 11px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 9px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-2);
  white-space: pre-line;
  text-align: left;
  cursor: default;
}

/* The model dropdown lives on the RIGHT side of the controls row. Anchor
   its menu to the trigger's right edge so it doesn't overflow the panel.
   Also bump the min-width so the descriptions don't wrap awkwardly. */
/* Keep wide menus INSIDE the ~380px panel — native workspace BrowserViews
   composite above any DOM that spills past the panel edge, clipping it.
   Model menu is left-anchored (its trigger sits left-of-center) and caps its
   width so it can't overflow the panel. */
#yo-model-dropdown .yo-mode-menu {
  left: 0;
  right: auto;
  min-width: 240px;
  max-width: calc(var(--right-inset, 380px) - 28px);
}

/* Checkmark sits on the far right of each option row; only visible when
   that row is `.active`. Same pattern works for model + perm + type. */
.yo-mode-opt-check {
  margin-left: auto;
  width: 14px;
  height: 14px;
  color: var(--text);
  flex-shrink: 0;
  opacity: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.yo-mode-opt-check svg { width: 14px; height: 14px; stroke: currentColor; }
.yo-model-option.active .yo-mode-opt-check,
.yo-perm-option.active .yo-mode-opt-check,
.yo-type-option.active .yo-mode-opt-check { opacity: 1; }

/* Replace emoji-based opt icons with consistently-sized inline SVGs. */
.yo-mode-opt-icon svg {
  width: 14px;
  height: 14px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  display: block;
}
.yo-perm-icon svg,
.yo-type-icon svg {
  width: 12px;
  height: 12px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  display: block;
}

/* Bypass mode: alert-red so the user can't pick it accidentally */
.yo-mode-option[data-value="bypass"] .yo-mode-opt-label,
.yo-perm-option[data-value="bypass"] .yo-mode-opt-label { color: #FF2D55; font-weight: 700; }
.yo-mode-option[data-value="bypass"] .yo-mode-opt-desc,
.yo-perm-option[data-value="bypass"] .yo-mode-opt-desc  { color: #FF2D55; opacity: 0.85; }
.yo-mode-option[data-value="bypass"]:hover,
.yo-perm-option[data-value="bypass"]:hover { background: rgba(255, 45, 85, 0.12); }
.yo-mode-option[data-value="bypass"].active,
.yo-perm-option[data-value="bypass"].active { background: rgba(255, 45, 85, 0.22); }

.yo-mode-opt-icon {
  font-size: 14px;
  width: 20px;
  text-align: center;
  flex-shrink: 0;
  line-height: 1;
}

.yo-mode-opt-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.yo-mode-opt-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-bright);
  font-family: var(--font-mono);
  text-transform: lowercase;
}

.yo-mode-opt-desc {
  font-size: 9px;
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Model names are proper-cased (prettyModelLabel) — don't force lowercase like
   the permission options, and let their longer "when to use" line wrap. */
.yo-model-option .yo-mode-opt-label { text-transform: none; }
.yo-model-option .yo-mode-opt-desc { white-space: normal; font-size: 10px; line-height: 1.3; margin-top: 2px; }

/* ── Plan action buttons ───────────────────────────────── */

.yo-plan-actions {
  display: flex;
  gap: 8px;
  padding: 8px 0;
}

.yo-plan-btn {
  flex: 1;
  padding: 8px 12px;
  border-radius: 8px;
  border: 1px solid var(--border-3);
  background: var(--surface-2);
  color: var(--text);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}

.yo-plan-btn:hover {
  border-color: var(--text-muted);
  color: var(--white);
}

.yo-plan-proceed {
  border-color: var(--accent);
  color: var(--text);
}
.yo-plan-proceed:hover {
  background: var(--accent);
  color: #000;
}

.yo-plan-auto {
  border-color: var(--warning);
  color: var(--warning);
}
.yo-plan-auto:hover {
  background: var(--warning);
  color: #000;
}

.yo-plan-edit:hover {
  background: var(--border-3);
}

/* ── Yo panel approval cards ─────────────────────────────── */

.yo-approval-card {
  background: var(--border);
  border: 1px solid var(--border-3);
  border-left: 3px solid var(--warning);
  border-radius: 8px;
  padding: 10px 12px;
  animation: yo-approval-in 0.2s ease-out;
}
@keyframes yo-approval-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

.yo-approval-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}
.yo-approval-icon {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--warning);
  color: #000;
  font-size: 11px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.yo-approval-title {
  flex: 1 1 auto;
  min-width: 0;            /* allow the flex item to shrink instead of overflowing */
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  overflow-wrap: anywhere; /* wrap long tool names rather than push the card wide */
  word-break: break-word;
}
.yo-approval-detail {
  font-size: 11px;
  color: var(--text-2);
  margin-bottom: 8px;
  padding-left: 26px;
  word-break: break-word;
}
.yo-approval-actions {
  display: flex;
  gap: 6px;
  padding-left: 26px;
}
.yo-approval-btn {
  padding: 4px 14px;
  border-radius: 6px;
  border: none;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s;
}
.yo-approval-btn:hover { opacity: 0.8; }
.yo-approval-allow {
  background: var(--accent);
  color: #000;
}
.yo-approval-deny {
  background: var(--border-3);
  color: var(--text);
}

.yo-approval-resolved {
  opacity: 0.6;
}
.yo-approval-resolved .yo-approval-detail { display: none; }
.yo-approval-allowed { border-left-color: var(--accent); }
.yo-approval-denied { border-left-color: var(--text-muted); }

.yo-approval-status {
  font-size: 11px;
  font-weight: 500;
  margin-left: auto;
}
.yo-approval-status.allowed { color: var(--text); }
.yo-approval-status.denied { color: var(--text-3); }

/* ── Tool permissions table (settings page) ──────────────── */

/* ── MCP Servers ────────────────────────────────────────── */

.mcp-preset-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 10px;
  margin-top: 8px;
}

.mcp-preset-card {
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  border-radius: 8px;
  padding: 12px 14px;
  cursor: pointer;
  transition: border-color 0.15s;
}
.mcp-preset-card:hover { border-color: var(--accent); }
.mcp-preset-card.mcp-installed {
  opacity: 0.5;
  cursor: default;
  border-color: var(--border-2);
}

.mcp-preset-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-bright);
  margin-bottom: 4px;
}

.mcp-preset-desc {
  font-size: 11px;
  color: var(--text-3);
  line-height: 1.4;
}

.mcp-preset-hint {
  font-size: 10px;
  color: var(--text-muted);
  margin-top: 6px;
  font-style: italic;
}

.mcp-status-badge {
  font-size: 10px;
  padding: 2px 8px;
  border-radius: 4px;
  font-weight: 500;
  white-space: nowrap;
}
.mcp-status-badge.status-connected {
  background: rgba(175, 95, 255, 0.15);
  color: var(--text);
}
.mcp-status-badge.status-connecting {
  background: rgba(74, 158, 255, 0.15);
  color: var(--blue);
}
.mcp-status-badge.status-disconnected {
  background: rgba(100, 100, 100, 0.15);
  color: var(--text-3);
}
.mcp-status-badge.status-error {
  background: rgba(255, 68, 68, 0.15);
  color: var(--danger);
}
.mcp-tool-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  font-family: 'SF Mono', 'Fira Code', monospace;
  background: rgba(175, 95, 255, 0.12);
  color: var(--text);
}

.mcp-server-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 6px;
  cursor: pointer;
  transition: border-color 0.15s;
}
.mcp-server-row:hover { border-color: var(--border-3); }

.mcp-server-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  flex: 1;
}

.mcp-server-tools {
  font-size: 11px;
  color: var(--text-muted);
}

/* ── App Browse Grid (Pipedream catalog) ───────────────── */

.connector-app-card {
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color 0.15s;
  text-align: center;
}
.connector-app-card:hover { border-color: var(--accent); }

.connector-app-card-icon {
  width: 32px;
  height: 32px;
  margin: 0 auto 8px;
  border-radius: 6px;
  background: var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  color: var(--text-2);
}
.connector-app-card-icon img {
  width: 100%;
  height: 100%;
  border-radius: 6px;
  object-fit: contain;
}

.connector-app-card-name {
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
  margin-bottom: 2px;
}

.connector-app-card-desc {
  font-size: 10px;
  color: var(--text-3);
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

/* ── Command palette (Cmd+K) ───────────────────────────── */

.cmd-palette {
  position: fixed;
  inset: 0;
  z-index: 99999;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 18vh;
}
.cmd-palette.hidden { display: none; }

.cmd-palette-backdrop {
  position: absolute;
  inset: 0;
  background: var(--shadow);
}

.cmd-palette-modal {
  position: relative;
  z-index: 1;
  width: min(520px, 80vw);
  background: var(--surface-3);
  border: 1px solid var(--yo-mode-color, var(--accent));
  border-radius: 14px;
  padding: 4px;
  box-shadow: 0 16px 48px var(--overlay-bg), 0 0 0 1px var(--active-bg);
}

.cmd-palette-input {
  width: 100%;
  background: transparent;
  border: none;
  border-radius: 10px;
  padding: 14px 16px;
  color: var(--text);
  font-size: 15px;
  font-family: var(--font-sans);
  outline: none;
  caret-color: var(--yo-mode-color, var(--accent));
}
.cmd-palette-input::placeholder { color: var(--text-muted); }

/* ── Drip picker tray ──────────────────────────────────── */

.drip-picker {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 0;
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  border-radius: 12px;
  padding: 10px;
  max-height: 220px;
  overflow-y: auto;
  box-shadow: 0 -4px 16px var(--shadow);
  z-index: 20;
  opacity: 0;
  transform: translateY(8px); /* slides up into place (opens above the input) */
  transition: opacity 0.15s ease, transform 0.15s ease;
  pointer-events: none;
}
.drip-picker.visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.drip-picker-section {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
  gap: 4px;
}

.drip-picker-divider {
  height: 1px;
  background: var(--border-2);
  margin: 8px 0;
}

.drip-picker-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 6px 2px;
  border-radius: 8px;
  cursor: pointer;
  background: transparent;
  border: none;
  color: var(--text-2);
  transition: background 0.12s;
}
.drip-picker-tile:hover {
  background: var(--active-bg);
}
.drip-picker-tile .drip-tile-icon {
  font-size: 20px;
  line-height: 1;
}
.drip-picker-tile .drip-tile-label {
  font-size: 9px;
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 54px;
  text-align: center;
}

.yo-drip-btn {
  background: none;
  border: none;
  color: var(--text-3);
  font-size: 16px;
  cursor: pointer;
  flex-shrink: 0;
  padding: 4px;
  border-radius: 4px;
  transition: color 0.15s;
}
.yo-drip-btn:hover { color: var(--text-2); }

/* ── Compaction "fuel gauge" (context usage ring) ───────────── */
.yo-compaction-btn {
  background: none;
  border: none;
  cursor: pointer;
  flex-shrink: 0;
  padding: 4px;
  border-radius: 4px;
  line-height: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s;
}
.yo-compaction-btn:hover { background: var(--surface-3); }

.yo-compaction-ring {
  transform: rotate(-90deg);
  transform-origin: center;
}
.yo-compaction-track {
  fill: none;
  stroke: var(--border-2);
  stroke-width: 3;
}
.yo-compaction-fill {
  fill: none;
  stroke: var(--accent);
  stroke-width: 4;
  stroke-linecap: round;
  /* r=15 → circumference = 2·π·15 ≈ 94.25 */
  stroke-dasharray: 94.25;
  stroke-dashoffset: 94.25;
  transition: stroke-dashoffset 0.3s ease, stroke 0.3s ease;
}
.yo-compaction-btn.amber .yo-compaction-fill { stroke: var(--warn, #e0a800); }
.yo-compaction-btn.danger .yo-compaction-fill { stroke: var(--danger, #e0483d); }

/* Compaction modal — reuses .yo-modal overlay/panel/actions/buttons. */
.yo-compaction-textarea {
  width: 100%;
  box-sizing: border-box;
  margin-top: 4px;
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  border-radius: 6px;
  padding: 8px 10px;
  color: var(--text);
  font-size: 12px;
  font-family: var(--font-mono);
  resize: vertical;
  outline: none;
}
.yo-compaction-textarea:focus { border-color: var(--accent); }
.yo-compaction-save-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--text-2);
  cursor: pointer;
}
.yo-compaction-save-row input { cursor: pointer; }

/* ── Wassup admin modal ─────────────────────────────────── */



/* ════════════════════════════════════════════════════════════════════
   Skills explorer (ported from v4, themed to .yo tokens)
   ════════════════════════════════════════════════════════════════════ */

/* Map the v4 workspace (--ws-*) tokens onto .yo tokens so the ported CSS
   themes correctly and flips light/dark with the rest of the app. Both
   "card" + "rail" bgs resolve to --surface so every panel inside the
   Workbench (Files, Terminal, Diff, Preview, Monaco viewer) reads the
   same color as the Plan body + Agent body + Token Metrics card. */
:root {
  --ws-line: var(--border);
  --ws-line-soft: var(--border);
  --ws-bg-card: var(--surface);
  --ws-bg-rail: var(--surface);
  --ws-text: var(--text);
  --ws-text-muted: var(--text-2);
  --ws-text-faint: var(--text-faint);
  --ws-accent: var(--accent);
  --ws-accent-soft: var(--accent-bg);
  --ws-radius: 8px;
  --ws-radius-sm: 6px;
  --ws-shadow-sm: 0 1px 2px var(--shadow);
  --ws-shadow-md: 0 6px 24px var(--shadow);
  --ws-diff-add: #4fae63;
  --ws-diff-del: #d44a4a;
}

/* Generic popover base (the create + kebab menus reuse these). */
.ws-popover {
  position: fixed; z-index: 1000; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 6px 24px var(--shadow);
}
.ws-popover-item {
  display: flex; align-items: center; width: 100%; box-sizing: border-box;
  background: none; border: none; cursor: pointer; color: var(--text);
  text-align: left; font: inherit; font-size: 13px; padding: 8px 12px; border-radius: 6px;
}
.ws-popover-item:hover { background: var(--hover); }
.ws-popover-item.danger { color: var(--ws-diff-del); }

/* ── Capture-enable warning modal ────────────────────────────────────────
   Red-accented confirmation shown when the user is about to enable capture
   for an app (turning "Do Not Capture" off). Tells them the risk: captured
   content lands in plain text on the local capture store. */
.capture-warning-overlay {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: capture-fade-in 120ms ease;
}
@keyframes capture-fade-in { from { opacity: 0; } to { opacity: 1; } }
.capture-warning-card {
  width: min(480px, 90vw);
  background: var(--surface-2);
  border: 1px solid #e53935;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
  font-size: 13px;
  color: var(--text);
}
.capture-warning-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  background: #e53935;
  color: #fff;
  font-weight: 600;
  font-size: 13px;
}
.capture-warning-header svg { width: 16px; height: 16px; flex-shrink: 0; }
.capture-warning-body {
  padding: 14px 16px 4px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  line-height: 1.5;
  color: var(--text-2);
}
.capture-warning-body p { margin: 0; }
.capture-warning-body strong { color: var(--danger); }
.capture-warning-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 14px 14px;
}
.capture-warning-cancel,
.capture-warning-confirm {
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  padding: 7px 14px;
  border-radius: 6px;
  cursor: pointer;
  border: 1px solid var(--border-2);
  background: transparent;
  color: var(--text-2);
  transition: background 100ms ease, color 100ms ease, border-color 100ms ease;
}
.capture-warning-cancel:hover { background: var(--hover); color: var(--text); }
.capture-warning-confirm {
  background: #e53935;
  border-color: var(--danger);
  color: #fff;
}
.capture-warning-confirm:hover { background: #c62828; border-color: #c62828; }

/* Docs + About render long-form prose where the right page padding adds
   visible whitespace next to the scrollbar; drop it for those two only.
   The Settings page also drops the right page padding — its inner
   .settings-panels has its own 28px right gutter, so the page reads as
   filled-but-padded. */
#page-body:has(.help-section[data-section="docs"].active),
#page-body:has(.help-section[data-section="settings"].active) {
  padding-right: 0;
}

/* Editing a connection is a full-bleed two-column detail — drop the page's
   right gutter so the tools pane and its scrollbar reach the window's right
   edge (only in edit mode; the connections LIST keeps the normal gutter). */
#page-body:has(.help-section[data-section="connections"] #conn-detail:not(.hidden)) {
  padding-right: 0;
}

/* Settings sits tighter into the corner — trim the page's 32/40px gutters. */
#page-body:has(.help-section[data-section="settings"].active) {
  padding-top: 12px;
  padding-left: 16px;
}

/* Wide settings panels — the 420px .settings-form clamp is right for narrow
   input rows but too tight for compound panels (provider cards, MCP
   tokens + connectors). Let these fill the available width so the user
   doesn't have to scroll a tall column of inputs. */
.settings-panel[data-sub="mcp"] .settings-form,
.settings-panel[data-sub="providers"] .settings-form,
#mcp-section-wrap,
#provider-keys-list {
  max-width: none;
}
.skills-explorer-host { flex: 1; min-height: 0; display: flex; }
.skills.skills-explorer { flex: 1; min-height: 0; }

/* ── Explorer shell: tree | divider | content, full height ── */
.skills.skills-explorer {
  --skill-gut: 20px;
  display: flex; flex-direction: row; min-height: 0; width: 100%; height: 100%;
}

/* ── Tree panel (left) ── */
.skill-tree-panel {
  flex: 0 0 280px; min-width: 0; display: flex; flex-direction: column;
  border-right: 1px solid var(--ws-line);
}
.skill-tree-toolbar {
  display: flex; align-items: center;
  gap: 8px; padding: 8px 10px 8px var(--skill-gut); min-height: 44px;
  border-bottom: 1px solid var(--ws-line-soft);
}
.skill-tree-title { font-size: 14px; font-weight: 600; color: var(--ws-text); margin-right: auto; }
.skill-tree-searchrow { padding: 8px 10px 8px var(--skill-gut); }
.skill-search {
  flex: 1; display: flex; align-items: center; gap: 6px; min-width: 0;
  background: var(--ws-bg-card); border: 1px solid var(--ws-line); border-radius: var(--ws-radius-sm); padding: 0 8px;
}
.skill-search svg { width: 14px; height: 14px; color: var(--ws-text-faint); flex-shrink: 0; }
.skill-search-input { flex: 1; min-width: 0; border: none; background: none; outline: none; color: var(--ws-text); font: inherit; font-size: 13px; padding: 6px 0; }
.skill-new-btn {
  flex-shrink: 0; width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 4px; cursor: pointer; color: var(--text-faint); background: transparent; padding: 0;
  transition: background 0.10s, color 0.10s;
}
.skill-new-btn:hover { background: var(--hover); color: var(--text); }
.skill-new-btn svg { width: 14px; height: 14px; }
.skill-tree-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 6px 8px 6px var(--skill-gut); }

/* ── Tree: skill folders → files ── */
.skill-tree-empty { padding: 16px 10px; color: var(--ws-text-faint); font-size: 12.5px; }
.skill-tree-folder.hidden, .skill-tree-files.hidden, .skill-monaco.hidden, .skill-md-render.hidden,
.skill-run-pane.hidden, .skill-run-preview.hidden, .skill-form-error.hidden { display: none; }

.skill-tree-folder-row, .skill-tree-file {
  display: flex; align-items: center; gap: 6px; padding: 5px 8px; border-radius: var(--ws-radius-sm);
  cursor: pointer; user-select: none; color: var(--ws-text); white-space: nowrap;
}
.skill-tree-folder-row:hover, .skill-tree-file:hover { background: var(--hover); }
.skill-tree-folder-row.active, .skill-tree-file.active { background: var(--ws-accent-soft); color: var(--ws-text, var(--text)); }
.skill-tree-caret { display: inline-flex; align-items: center; justify-content: center; width: 16px; flex-shrink: 0; color: var(--ws-text-muted); transition: transform 0.12s, color 0.12s; }
.skill-tree-caret svg { width: 13px; height: 13px; }
.skill-tree-caret.open { transform: rotate(90deg); }
.skill-tree-folder-row:hover .skill-tree-caret, .skill-tree-folder-row.active .skill-tree-caret { color: var(--ws-text); }
.skill-tree-ficon { display: inline-flex; flex-shrink: 0; color: var(--ws-text); }
.skill-tree-ficon svg { width: 16px; height: 16px; }
.skill-tree-folder-row .skill-tree-ficon { color: var(--ws-text, var(--text)); }
.skill-tree-ficon.md   { color: var(--ws-text, var(--text)); }
.skill-tree-ficon.code { color: #4aa3df; }
.skill-tree-ficon.data { color: #d6912b; }
.skill-tree-name { font-size: 13px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; }
.skill-tree-pills { margin-left: auto; display: flex; gap: 4px; flex-shrink: 0; }
.skill-pill { font-size: 10px; padding: 1px 6px; border-radius: 4px; background: var(--surface-3); color: var(--text-3); }
.skill-pill-scheduled { background: var(--accent-bg); color: var(--text); }
.skill-tree-files { margin: 1px 0 2px 17px; padding-left: 9px; border-left: 1px solid var(--ws-line); }
.skill-tree-fname { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; font-family: 'SF Mono', 'Fira Code', 'JetBrains Mono', Menlo, monospace; }

/* ── Draggable divider ── */
.skill-explorer-divider { flex: 0 0 7px; align-self: stretch; cursor: col-resize; position: relative; }
.skill-explorer-divider::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 3px; width: 1px; background: var(--ws-line); transition: background 0.12s, width 0.12s;
}
.skill-explorer-divider:hover::after, .skill-explorer-divider.dragging::after { background: var(--ws-accent); width: 2px; }

/* ── Content pane (right) ── */
.skill-content { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; }
.skill-content-bar {
  display: flex; align-items: center; gap: 10px; padding: 8px var(--skill-gut); min-height: 44px;
  border-bottom: 1px solid var(--ws-line-soft);
}
.skill-content-title { font-size: 14px; font-weight: 600; color: var(--ws-text); }
.skill-content-filename { font-size: 12.5px; color: var(--ws-text-muted); font-family: 'SF Mono', 'Fira Code', 'JetBrains Mono', Menlo, monospace; }
.skill-content-actions { margin-left: auto; display: flex; align-items: center; gap: 6px; }
.skill-content-body { flex: 1; min-height: 0; display: flex; }
.skill-content-body > * { flex: 1; min-width: 0; min-height: 0; }
.skill-content-empty { padding: 24px var(--skill-gut); color: var(--ws-text-faint); font-size: 13px; }

.skill-icon-btn {
  width: 30px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--ws-line); border-radius: var(--ws-radius-sm); cursor: pointer;
  background: var(--ws-bg-card); color: var(--ws-text-muted);
}
.skill-icon-btn:hover { color: var(--ws-text); border-color: var(--ws-accent); }
.skill-icon-btn.active { color: var(--ws-text, var(--text)); border-color: var(--ws-accent); }
.skill-icon-btn svg { width: 15px; height: 15px; }

.skill-monaco { min-height: 0; }
.skill-md-render { overflow: auto; padding: 20px var(--skill-gut); color: var(--ws-text); font-size: 14px; line-height: 1.65; }

/* create form */
.skill-create-form { max-width: 480px; display: flex; flex-direction: column; gap: 6px; padding: 20px var(--skill-gut); }
.skill-create-label { font-size: 12px; color: var(--ws-text-muted); margin-top: 8px; }
.skill-create-actions { margin-top: 14px; }
.skill-create-hint { font-size: 12px; color: var(--ws-text-faint); margin-top: 12px; line-height: 1.5; }
.skill-create-instr { resize: vertical; min-height: 120px; font-family: inherit; line-height: 1.5; }
.skill-form-error { color: var(--ws-diff-del); font-size: 12px; }

/* ── Rendered markdown (.yo-md) ── */
.skill-md-render.yo-md > :first-child { margin-top: 0; }
.skill-md-render.yo-md h1 { font-size: 24px; font-weight: 700; margin: 24px 0 12px; color: var(--ws-text); line-height: 1.25; }
.skill-md-render.yo-md h2 { font-size: 19px; font-weight: 700; margin: 22px 0 10px; color: var(--ws-text); padding-bottom: 5px; border-bottom: 1px solid var(--ws-line); }
.skill-md-render.yo-md h3 { font-size: 16px; font-weight: 600; margin: 18px 0 8px; color: var(--ws-text); }
.skill-md-render.yo-md p { margin: 0 0 12px; }
.skill-md-render.yo-md a { color: var(--ws-text, var(--text)); text-decoration: none; }
.skill-md-render.yo-md ul, .skill-md-render.yo-md ol { margin: 0 0 12px; padding-left: 24px; }
.skill-md-render.yo-md li { margin: 4px 0; }
.skill-md-render.yo-md code { font-family: 'SF Mono', 'Fira Code', Menlo, monospace; font-size: 0.88em; background: var(--surface-3); padding: 1px 5px; border-radius: 4px; }
.skill-md-render.yo-md pre { background: var(--ws-bg-rail); border: 1px solid var(--ws-line); border-radius: var(--ws-radius); padding: 12px 14px; overflow-x: auto; margin: 0 0 14px; }
.skill-md-render.yo-md pre code { background: none; padding: 0; }
.skill-md-render.yo-md blockquote { margin: 0 0 12px; padding: 4px 14px; border-left: 3px solid var(--ws-accent); color: var(--ws-text-muted); }
.skill-md-render.yo-md hr { border: none; border-top: 1px solid var(--ws-line); margin: 20px 0; }

/* ── Run console + web preview ── */
.skill-run-pane { display: flex; flex-direction: column; min-height: 0; gap: 10px; padding: 12px; }
.skill-run-preview { flex: 0 0 45%; min-height: 0; border: 1px solid var(--ws-line); border-radius: var(--ws-radius); overflow: hidden; background: #fff; }
.skill-run-iframe { width: 100%; height: 100%; border: none; }
.skill-run-console {
  flex: 1; min-height: 120px; overflow: auto; background: var(--ws-bg-rail);
  border: 1px solid var(--ws-line); border-radius: var(--ws-radius); padding: 10px 12px;
  font-family: 'SF Mono', 'Fira Code', Menlo, monospace; font-size: 12px; line-height: 1.5;
}
.skill-run-line { white-space: pre-wrap; word-break: break-word; }
.skill-run-line.sys { color: var(--ws-text-faint); }
.skill-run-line.run { color: var(--ws-text, var(--text)); }
.skill-run-line.out { color: var(--ws-text); }
.skill-run-line.ok { color: var(--ws-text, var(--text)); }
.skill-run-line.err { color: var(--ws-diff-del); }

/* ── "+" create dropdown ── */
.skill-create-menu { min-width: 230px; padding: 8px; }
.skill-create-menu .skill-menu-item { display: flex !important; flex-direction: row; align-items: center; gap: 14px; padding: 9px 12px; border-radius: 7px; }
.skill-create-menu .skill-menu-item + .skill-menu-item { margin-top: 3px; }
.skill-create-menu .skill-menu-icon { width: 16px; height: 16px; margin: 0; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; color: var(--ws-text-muted); }
.skill-create-menu .skill-menu-icon svg { width: 16px; height: 16px; }
.skill-create-menu .skill-menu-label { font-size: 13px; font-weight: 500; color: var(--ws-text); }

/* ── Upload-skill modal ── */
.skill-upload-overlay { position: fixed; inset: 0; z-index: 1000; background: var(--overlay-bg); display: flex; align-items: center; justify-content: center; }
.skill-upload-box { width: 440px; max-width: 92vw; background: var(--ws-bg-card); border: 1px solid var(--ws-line); border-radius: var(--ws-radius); box-shadow: var(--ws-shadow-md); padding: 18px; display: flex; flex-direction: column; gap: 12px; }
.skill-upload-head { font-size: 15px; font-weight: 600; color: var(--ws-text); }
.skill-upload-drop { border: 1.5px dashed var(--ws-line); border-radius: var(--ws-radius); padding: 28px 16px; text-align: center; cursor: pointer; transition: border-color 0.12s, background 0.12s; }
.skill-upload-drop:hover, .skill-upload-drop.over { border-color: var(--ws-accent); background: var(--ws-accent-soft); }
.skill-upload-drop-title { font-size: 14px; font-weight: 500; color: var(--ws-text); }
.skill-upload-drop-sub { font-size: 12px; color: var(--ws-text-muted); margin-top: 3px; }
.skill-upload-reqs { margin: 0; padding-left: 18px; color: var(--ws-text-muted); font-size: 12.5px; line-height: 1.6; }
.skill-upload-status { font-size: 12.5px; color: var(--ws-text-muted); min-height: 1em; }
.skill-upload-actions { display: flex; justify-content: flex-end; }

/* ── Skill overview ── */
.skill-meta-grid { display: flex; gap: 40px; margin-bottom: 16px; }
.skill-meta-h { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ws-text-muted); margin-bottom: 3px; }
.skill-meta-v { font-size: 13.5px; color: var(--ws-text); }
.skill-desc-block { margin-bottom: 6px; }
.skill-desc-label { position: relative; display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ws-text-muted); margin-bottom: 5px; }
.skill-desc-help { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; padding: 0; border: none; background: none; color: var(--ws-text-muted); cursor: pointer; }
.skill-desc-help:hover { color: var(--ws-text, var(--text)); }
.skill-desc-help svg { width: 14px; height: 14px; }
.skill-desc-tip { position: absolute; top: 100%; left: 0; margin-top: 6px; z-index: 20; background: var(--ws-bg-card); border: 1px solid var(--ws-line); border-radius: var(--ws-radius-sm); box-shadow: var(--ws-shadow-md); padding: 7px 11px; max-width: 280px; font-size: 12px; font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--ws-text); }
.skill-desc-tip.hidden { display: none; }
.skill-desc-text { font-size: 14px; color: var(--ws-text); margin: 0; line-height: 1.55; }
.skill-divider { border: none; border-top: 1px solid var(--ws-line); margin: 18px 0; }

/* enabled toggle switch */
.skill-toggle { position: relative; display: inline-flex; align-items: center; cursor: pointer; }
.skill-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.skill-toggle-track { width: 34px; height: 19px; border-radius: 999px; background: var(--ws-line); transition: background 0.15s; display: inline-flex; align-items: center; padding: 2px; }
.skill-toggle-thumb { width: 15px; height: 15px; border-radius: 50%; background: #fff; transition: transform 0.15s; box-shadow: var(--ws-shadow-sm); }
.skill-toggle input:checked + .skill-toggle-track { background: var(--ws-accent); }
.skill-toggle input:checked + .skill-toggle-track .skill-toggle-thumb { transform: translateX(15px); }

/* media preview */
.skill-media-wrap { display: flex; align-items: center; justify-content: center; min-height: 0; padding: 16px; flex: 1; }
.skill-media-img, .skill-media-video { max-width: 100%; max-height: 100%; border-radius: var(--ws-radius-sm); }
.skill-media-video { background: #000; }
.skill-media-audio { width: 80%; max-width: 540px; }

/* kebab menu */
.skill-kebab-menu { min-width: 184px; padding: 5px; }
.skill-kebab-menu .ws-popover-item { display: flex; align-items: center; }
.skill-menu-icon { display: inline-flex; width: 16px; margin-right: 9px; color: var(--ws-text-muted); }
.skill-menu-icon svg { width: 15px; height: 15px; }
.ws-popover-item.danger .skill-menu-icon { color: var(--ws-diff-del); }

/* ── Schedule run toast (ported from v4) ───────────────────────────── */
.sched-toast {
  position: fixed; bottom: 20px; left: 50%;
  transform: translate(-50%, 20px); opacity: 0;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; box-shadow: 0 6px 24px var(--shadow);
  padding: 10px 12px 10px 14px; display: flex; align-items: center; gap: 12px;
  z-index: 2000; transition: opacity 0.2s, transform 0.2s;
  font-size: 13px; color: var(--text); max-width: 90vw;
}
.sched-toast.show { opacity: 1; transform: translate(-50%, 0); }
.sched-toast-msg { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sched-toast-action {
  background: var(--accent); color: #000; border: none; border-radius: 5px;
  padding: 4px 10px; font-size: 12px; font-weight: 600; cursor: pointer; flex-shrink: 0;
}
.sched-toast-action:hover { opacity: 0.85; }
.sched-toast-close {
  background: none; border: none; color: var(--text-3); cursor: pointer;
  font-size: 16px; line-height: 1; padding: 0 2px; flex-shrink: 0;
}
.sched-toast-close:hover { color: var(--text); }

/* ════════════════════════════════════════════════════════════════════
   Workbench app (yo://workbench)
   Right-rail tiling system ported from v4 — each rail holds up to 2
   stacked slots; opening a section appends to the first rail with
   slack, otherwise spawns a new rail to the right.
   ════════════════════════════════════════════════════════════════════ */
:root {
  --ws-diff-add-bg: rgba(79, 174, 99, 0.12);
  --ws-diff-del-bg: rgba(212, 74, 74, 0.10);
  --ws-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

.ws-right-rails {
  display: flex;
  height: 100%;
  min-width: 0;
}
/* A layout with a full-width spanning cell: bands stack above/below the
   column row, so the rails container flips vertical. */
.ws-right-rails.has-banner { flex-direction: column; }
.ws-rails-row { display: flex; flex: 1 1 0; min-width: 0; min-height: 0; }
.ws-right-rail.ws-rail-banner { width: auto !important; min-height: 120px; }
/* Drag handle between the column row and a band — resizes the band height. */
.ws-band-hsep {
  /* 1px visible seam; padding+negative margin keep a 7px grab zone. */
  height: 1px;
  padding: 3px 0;
  margin: -3px 0;
  z-index: 3;
  flex-shrink: 0;
  background: transparent;
  border-top: 1px solid var(--ws-line);
  cursor: row-resize;
  transition: background 0.10s;
}
.ws-band-hsep:hover, .ws-band-hsep.dragging { background: var(--accent, #af5fff); }
.ws-right-rails.has-fullscreen .ws-band-hsep { display: none; }
/* Modals vs <webview>: the webview compositing layer beats every z-index, so
   while a modal is open the workspace panels' webviews go invisible. The
   WHOLE app layer hides — the holders live at z-120 (above the overlay's
   z-100 stacking context the modal renders in), so a holder's surface
   background alone was enough to blank out a dialog. */
body.wb-modal-open webview,
body.wb-modal-open #code-wb-applayer,
body.wb-modal-open #code-rail-layer,
body.wb-modal-open #code-agent-layer { visibility: hidden !important; }
.ws-right-rail {
  background: var(--ws-bg-rail);
  /* Right border on every rail so the column's right edge is visible
     against the workbench body (same surface color). Inter-rail seams
     are covered by the next rail's border-left so we don't double up. */
  border-right: 1px solid var(--ws-line);
  border-left: 1px solid var(--ws-line);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
  flex-shrink: 0;
  width: 320px;
  position: relative;
}
.ws-right-rail:first-child { border-left: none; }

.ws-rail-slot {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
.ws-rail-slot-header {
  height: 38px;
  padding: 0 8px 0 14px;
  border-bottom: 1px solid var(--ws-line);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  background: var(--ws-bg-rail);
}
.ws-rail-slot-header .icon {
  width: 14px; height: 14px;
  color: var(--ws-text-faint);
  flex-shrink: 0;
  stroke: currentColor;
}
.ws-rail-slot-header .title {
  flex: 1;
  min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-size: 13px;
  font-weight: 500;
  color: var(--ws-text);
}
.ws-rail-slot-header .ws-icon-btn.slot-close {
  background: transparent; border: none; padding: 0;
  width: 24px; height: 24px; border-radius: 4px;
  color: var(--ws-text-faint); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.10s, color 0.10s;
}
.ws-rail-slot-header .ws-icon-btn.slot-close:hover { background: var(--hover); color: var(--ws-text); }
.ws-rail-slot-header .ws-icon-btn.slot-close svg { width: 12px; height: 12px; }

.ws-rail-slot-body {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.ws-rail-vsep {
  height: 5px;
  flex-shrink: 0;
  background: transparent;
  border-top: 1px solid var(--ws-line);
  cursor: row-resize;
}
.ws-rail-vsep:hover,
.ws-rail-vsep.dragging { background: var(--ws-accent); opacity: 0.4; }

.ws-resize-v {
  position: absolute;
  top: 0; bottom: 0;
  width: 6px;
  cursor: col-resize;
  z-index: 10;
  background: transparent;
  transition: background 0.10s;
}
.ws-resize-v:hover,
.ws-resize-v.dragging { background: var(--ws-accent); opacity: 0.5; }
.ws-rail-vsep { transition: background 0.10s; }
.ws-rail-vsep:hover { opacity: 0.6; }

/* ── Files view ── */
.ws-file-search {
  padding: 8px 10px;
  border-bottom: 1px solid var(--ws-line);
  flex-shrink: 0;
  display: flex; align-items: center; gap: 6px;
}
/* + file / + folder — same 24px/13px rules as the Browser bar's buttons
   (.ws-icon-btn now has a bare-icon base near the top reset; this just sizes). */
.ws-file-add {
  background: transparent; border: none; padding: 0;
  width: 24px; height: 24px; border-radius: 4px;
  color: var(--ws-text-faint); cursor: pointer;
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.ws-file-add:hover { background: var(--hover); color: var(--ws-text); }
.ws-file-add:disabled { opacity: 0.4; cursor: default; }
.ws-file-add svg { width: 13px; height: 13px; }
/* Inline name entry for create/rename — matches the row typography. */
.ws-files-newinput {
  flex: 1; min-width: 0;
  background: var(--surface-2); color: var(--ws-text, var(--text));
  border: 1px solid var(--border-2); border-radius: 5px;
  font: inherit; font-size: 12px; padding: 1px 6px; outline: none;
}
.ws-files-row.ws-files-newrow { padding-top: 2px; padding-bottom: 2px; padding-right: 8px; }
.ws-file-search input {
  flex: 1; min-width: 0;
  padding: 5px 9px;
  border: 1px solid var(--ws-line);
  border-radius: 6px;
  background: var(--ws-bg-card);
  font: inherit;
  font-size: 12.5px;
  color: var(--ws-text);
  outline: none;
  transition: border-color 0.10s;
  box-sizing: border-box;
}
.ws-file-search input:focus { border-color: var(--ws-accent); }
.ws-files-tree {
  flex: 1;
  overflow-y: auto;
  padding: 4px 0 12px;
  font-size: 12.5px;
  user-select: none;
  min-height: 0;
}
.ws-files-row {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 22px;
  padding-right: 8px;
  cursor: pointer;
  white-space: nowrap;
  color: var(--ws-text);
}
.ws-files-row:hover { background: var(--hover); }
.ws-files-row.hidden { display: none; }
.ws-files-caret {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  flex-shrink: 0;
  color: var(--ws-text-faint);
  transition: transform 0.12s;
  font-size: 10px;
}
.ws-files-caret.open { transform: rotate(90deg); }
.ws-files-caret.leaf { visibility: hidden; }
.ws-files-icon {
  flex-shrink: 0;
  color: var(--ws-text-faint);
  width: 13px;
  height: 13px;
}
.ws-files-name {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Monaco/file viewer ── */
.ws-monaco-header {
  height: 32px;
  padding: 0 6px 0 12px;
  border-bottom: 1px solid var(--ws-line);
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  font-size: 12px;
  color: var(--ws-text-muted);
  background: var(--ws-bg-card);
}
.ws-monaco-filename {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ws-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  direction: rtl;
  text-align: left;
}
.ws-monaco-actions { display: flex; align-items: center; gap: 1px; flex-shrink: 0; }
.ws-monaco-icon-btn {
  background: transparent;
  border: 1px solid transparent;
  width: 26px; height: 26px;
  border-radius: 5px;
  cursor: pointer;
  color: var(--ws-text-faint);
  padding: 0;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.10s, color 0.10s;
}
.ws-monaco-icon-btn:hover  { background: var(--hover); color: var(--ws-text); }
.ws-monaco-icon-btn.active { background: var(--ws-accent-soft); color: var(--ws-text, var(--text)); }
.ws-monaco-icon-btn.copied { color: var(--ws-text, var(--text)); }
.ws-monaco-icon-btn svg { width: 14px; height: 14px; stroke: currentColor; }

.ws-monaco-search {
  display: none;
  align-items: center;
  gap: 8px;
  padding: 6px 6px 6px 10px;
  border-bottom: 1px solid var(--ws-line);
  background: var(--ws-bg-card);
  flex-shrink: 0;
}
.ws-monaco-search.open { display: flex; }
.ws-monaco-search-wrap { flex: 1; position: relative; display: flex; align-items: center; }
.ws-monaco-search-wrap > svg {
  position: absolute; left: 9px; width: 13px; height: 13px;
  color: var(--ws-text-faint); pointer-events: none;
}
.ws-monaco-search input {
  width: 100%;
  padding: 5px 10px 5px 28px;
  border: 1px solid var(--ws-line);
  border-radius: 5px;
  background: var(--bg);
  font: inherit;
  font-size: 11.5px;
  color: var(--ws-text);
  font-family: var(--font-mono);
  outline: none;
  transition: border-color 0.10s;
  box-sizing: border-box;
}
.ws-monaco-search input:focus { border-color: var(--ws-accent); }
.ws-monaco-search .match-count {
  font-size: 10.5px;
  color: var(--ws-text-faint);
  font-family: var(--font-mono);
  flex-shrink: 0;
}

.ws-monaco-body {
  flex: 1;
  overflow: auto;
  padding: 14px 18px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.55;
  background: var(--ws-bg-card);
  color: var(--ws-text);
  white-space: pre;
}
.ws-monaco-body mark {
  background: rgba(255, 209, 102, 0.55);
  color: inherit;
  padding: 0 1px;
  border-radius: 2px;
}

/* ── Diff view ── */
.ws-diff-toolbar {
  height: 32px;
  padding: 0 8px 0 12px;
  border-bottom: 1px solid var(--ws-line);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  background: var(--ws-bg-rail);
  font-size: 12px;
  color: var(--ws-text-muted);
}
.ws-diff-summary { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-diff-summary .add { color: var(--ws-diff-add); margin-left: 6px; }
.ws-diff-summary .del { color: var(--ws-diff-del); margin-left: 4px; }
.ws-diff-refresh {
  background: transparent; border: none; padding: 0;
  width: 24px; height: 24px; border-radius: 4px;
  color: var(--ws-text-faint); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.ws-diff-refresh:hover { background: var(--hover); color: var(--ws-text); }
.ws-diff-refresh svg { width: 13px; height: 13px; }

.ws-diff-files { flex: 1; overflow: auto; background: var(--ws-bg-card); }
.ws-diff-empty {
  padding: 20px; text-align: center;
  color: var(--ws-text-faint); font-size: 12px;
}
.ws-diff-file { border-bottom: 1px solid var(--ws-line); }
.ws-diff-file-header {
  height: 30px;
  padding: 0 10px 0 8px;
  display: flex; align-items: center; gap: 6px;
  cursor: pointer; user-select: none;
  background: var(--ws-bg-rail);
  transition: background 0.10s;
}
.ws-diff-file-header:hover { background: var(--hover); }
.ws-diff-caret {
  width: 14px; flex-shrink: 0;
  color: var(--ws-text-faint); font-size: 10px;
  transition: transform 120ms var(--ws-ease);
  transform: rotate(90deg);
}
.ws-diff-file.collapsed .ws-diff-caret { transform: rotate(0); }
.ws-diff-file-name {
  flex: 1;
  font-size: 12px;
  color: var(--ws-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-mono);
}
.ws-diff-stat {
  display: flex; gap: 6px;
  font-variant-numeric: tabular-nums;
  font-size: 11.5px; flex-shrink: 0;
}
.ws-diff-stat .add { color: var(--ws-diff-add); }
.ws-diff-stat .del { color: var(--ws-diff-del); }
.ws-diff-file-body {
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.55;
  padding: 4px 0;
  background: var(--ws-bg-card);
}
.ws-diff-file.collapsed .ws-diff-file-body { display: none; }
.ws-diff-line { padding: 0 12px; white-space: pre; color: var(--ws-text); }
.ws-diff-line.hunk    { color: var(--ws-text-faint); background: rgba(0,0,0,0.025); }
.ws-diff-line.add     { background: var(--ws-diff-add-bg); color: var(--ws-diff-add); }
.ws-diff-line.del     { background: var(--ws-diff-del-bg); color: var(--ws-diff-del); }

/* ── Preview view (stub) ── */
/* Browser TABS — one webview per tab (visibility-swapped; reparenting
   reloads a guest), monaco-style strip with + and a right-click menu. */
.ws-preview-tabs {
  display: flex; align-items: center; gap: 2px;
  padding: 4px 6px 0; background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.ws-preview-tabs .wpt-list { display: flex; gap: 2px; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.ws-preview-tabs .wpt-list::-webkit-scrollbar { height: 0; }
.ws-preview-tab {
  display: flex; align-items: center; gap: 6px; max-width: 180px; min-width: 0;
  padding: 4px 6px 4px 10px; border-radius: 7px 7px 0 0;
  font-size: 11px; color: var(--text-3); cursor: pointer; white-space: nowrap;
  border: 1px solid transparent; border-bottom: none;
}
.ws-preview-tab:hover { background: var(--hover); color: var(--text-2); }
.ws-preview-tab.active { background: var(--surface-2); color: var(--text); border-color: var(--border); }
.ws-preview-tab .nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ws-preview-tab .close {
  display: flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; padding: 0; border: none; border-radius: 4px;
  background: none; color: var(--text-faint); font-size: 13px; line-height: 1; cursor: pointer;
}
.ws-preview-tab .close:hover { background: var(--border-2); color: var(--text); }
.ws-preview-tabs .wpt-new {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin-bottom: 2px; padding: 0;
  border: none; border-radius: 6px; background: none; color: var(--text-3); cursor: pointer;
}
.ws-preview-tabs .wpt-new:hover { background: var(--hover); color: var(--text); }
.ws-preview-tabs .wpt-new svg { width: 13px; height: 13px; }
.ws-preview-frames { position: absolute; inset: 0; }
.ws-preview-frames webview.ws-preview-frame { position: absolute; inset: 0; width: 100%; height: 100%; }

.ws-preview-url {
  height: 36px;
  padding: 0 8px 0 12px;
  border-bottom: 1px solid var(--ws-line);
  display: flex; align-items: center; gap: 8px;
  flex-shrink: 0;
  background: var(--ws-bg-rail);
}
.ws-preview-input {
  flex: 1;
  padding: 4px 8px;
  border: 1px solid var(--ws-line);
  border-radius: 5px;
  background: var(--ws-bg-card);
  font: inherit;
  font-size: 11.5px;
  color: var(--ws-text);
  font-family: var(--font-mono);
  outline: none;
  box-sizing: border-box;
}
.ws-preview-input:focus { border-color: var(--ws-accent); }
.ws-preview-reload,
.ws-preview-openfile {
  background: transparent; border: none; padding: 0;
  width: 24px; height: 24px; border-radius: 4px;
  color: var(--ws-text-faint); cursor: pointer;
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.ws-preview-reload:hover,
.ws-preview-openfile:hover { background: var(--hover); color: var(--ws-text); }
.ws-preview-reload svg,
.ws-preview-openfile svg { width: 13px; height: 13px; }
.ws-preview-body { flex: 1; overflow: hidden; background: var(--ws-bg-card); display: flex; align-items: center; justify-content: center; position: relative; }
.ws-preview-frame {
  flex: 1 1 auto;
  align-self: stretch;
  width: 100%;
  height: 100%;
  border: none;
  /* Theme-follow, never hard white: on web this holder sits BEHIND the
     streamed panel (whose backing is var(--bg-2)) and it's what shows in
     every empty/loading/error state — #fff here was the white rectangle in
     dark themes. Native webviews paint their own page over it either way. */
  background: var(--ws-bg-card);
}
.ws-preview-frame[hidden] { display: none; }

/* ── App slots — in-workbench apps (the OS-window replacement) ──────────
   The slot body holds only a placeholder rect; the live <webview> sits in
   the fixed #code-wb-applayer and follows the placeholder each frame
   (webviews reload when reparented, so they never ride the rails DOM). */
.ws-app-placeholder { flex: 1 1 auto; align-self: stretch; width: 100%; height: 100%; background: var(--surface); }
/* Above the home overlay (z-index 100) — the layer lives on <body>, outside
   the overlay, so at z-index 40 the whole UI painted over the webviews and you
   saw the placeholder's surface background instead. Each holder is clipped to
   its slot rect, so this only covers the workbench slots, not the rest. */
#code-wb-applayer { position: fixed; inset: 0; pointer-events: none; z-index: 120; }
.ws-app-holder {
  position: fixed;
  pointer-events: auto;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.ws-app-holder webview { flex: 1 1 auto; min-height: 0; width: 100%; border: none; }

/* ── The agent overlay — the ONE .code-agent, mounted once ──────────────
   Same pattern as the app layer: the rail coding seat and the echo agent
   card each render only a .ws-agent-placeholder; the live .code-agent lives
   in the fixed #code-agent-layer and follows whichever placeholder is
   showing, each frame. It is never re-parented between hosts — mid-run
   typing, staged notes and scroll survive by construction. (Dock/collapsed
   modes keep the agent as a .code-root child, in-flow — the reconciler moves
   it between exactly those two homes and nowhere else.) */
.ws-agent-placeholder { flex: 1 1 auto; align-self: stretch; width: 100%; height: 100%; min-width: 0; min-height: 0; background: var(--bg); }
/* Below the app layer (z-120) so an app-webview wins an overlap, above panel
   chrome. Clipped to the placeholder rect, so it only ever covers its host. */
#code-agent-layer { position: fixed; inset: 0; pointer-events: none; z-index: 118; }
.ws-agent-holder {
  position: fixed;
  pointer-events: auto;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}
.ws-agent-holder > .code-agent { flex: 1 1 auto; min-height: 0; min-width: 0; max-width: none; width: auto; height: auto; }

/* ── The Rail panel — the ONE #app-rail, hosted by a workbench slot ─────
   Same pattern as the agent overlay: a Rail slot renders only a
   .ws-rail-placeholder; the live #app-rail (menu, Recents, Apps, Workspaces,
   account footer — all still wired by help/code.ts + navigation.ts) sits in
   the fixed #code-rail-layer and follows whichever placeholder is showing.
   The shell's own left rail stays retired (display:none above); only a holder
   un-hides it, so the two can never both claim the node. */
.ws-rail-placeholder { flex: 1 1 auto; align-self: stretch; width: 100%; height: 100%; min-width: 0; min-height: 0; background: var(--surface-2); }
/* Below the agent layer (z-118) — a Rail panel never covers the agent. */
#code-rail-layer { position: fixed; inset: 0; pointer-events: none; z-index: 117; }
.ws-rail-holder {
  position: fixed;
  pointer-events: auto;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--surface-2);
}
/* Hosted: the rail fills the holder and drops the shell chrome it only had as
   a left column (fixed width, right border, the web top inset). */
.ws-rail-holder > #app-rail {
  display: flex !important;
  width: auto !important;
  min-width: 0 !important;
  flex: 1 1 auto;
  border-right: none;
  padding-top: 0 !important;
  transition: none;
  /* Menu + Recents + both trays + the footer can outgrow a short panel — the
     rail scrolls rather than crushing the tray minimums. */
  overflow-y: auto;
}
/* A COLLAPSED Rail panel (.rail-strip) is the icon strip: its header keeps
   only the rail-hide toggle (which now expands) — title, drag affordance and
   the other controls don't fit 64px and go. Rails surface + Echo card. */
.ws-rail-slot.rail-strip .ws-rail-slot-header > :not(.slot-rail-hide),
.echo-card.rail-strip .echo-card-head > :not(.echo-rail-hide) { display: none !important; }
.ws-rail-slot.rail-strip .ws-rail-slot-header,
.echo-card.rail-strip .echo-card-head { justify-content: center; padding: 4px 0; }
.slot-rail-hide.active, .echo-rail-hide.active { color: var(--accent); }

/* Per-cell configs (Workspaces → the panel's setup pane): each toggle hides
   one section of the hosted rail. Apps has no toggle — it is the tray the
   panel exists for. */
#app-rail.rail-hide-menu [data-rail-section="menu"],
#app-rail.rail-hide-recents [data-rail-section="recents"],
#app-rail.rail-hide-layouts [data-rail-section="layouts"] { display: none !important; }

/* ── ICONS MODE — the collapsed Rail (the panel's rail-hide affordance) ──
   The hosting column narrows to the icon strip (RAIL_STRIP_W); the rail keeps
   only what reads at that width: the + button, the nav icons, the tray tile
   icons, and the account icon. Text, searches, Recents and the section
   headers go — a 64px recents list is noise, not navigation. */
#app-rail.rail-icons .code-new-session-rail span,
#app-rail.rail-icons .app-rail-nav-item span,
#app-rail.rail-icons .app-rail-user-btn span,
#app-rail.rail-icons .app-rail-tile .tile-name { display: none; }
/* WORKSPACES keep a very small name under their mini-icon stack — a layout's
   icon collage isn't identifiable alone the way an app icon is. Apps stay
   icon-only (his spec, 2026-08-30). */
#app-rail.rail-icons #recent-layouts-list .app-rail-tile .tile-name {
  display: block;
  font-size: 8.5px;
  line-height: 1.15;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
#app-rail.rail-icons .code-new-session-rail { padding: 7px 0; margin: 8px 6px 4px; }
#app-rail.rail-icons .app-rail-nav-item { justify-content: center; padding: 7px 0; }
#app-rail.rail-icons .app-rail-user-btn { justify-content: center; }
#app-rail.rail-icons #recents-toggle,
#app-rail.rail-icons .app-rail-search,
#app-rail.rail-icons #code-history,
#app-rail.rail-icons .app-rail-section-head,
#app-rail.rail-icons .rail-grid-pager { display: none !important; }
/* The trays stay: one icon per row. Collapsed tray state still applies —
   a .hidden body stays hidden. */
#app-rail.rail-icons .app-rail-grid { grid-template-columns: 1fr; padding: 2px 6px 8px; gap: 4px; }
#app-rail.rail-icons .app-rail-section-body { min-height: 0; }
#app-rail.rail-icons .app-rail-relaunch span { display: none; }
/* Per-panel browser chrome — back/fwd/reload + address bar + hide toggle. */
.ws-app-chrome {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  height: 34px;
  padding: 0 6px;
  background: var(--ws-bg-rail, var(--surface-2));
  border-bottom: 1px solid var(--ws-line, var(--border));
}
.ws-app-nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--text-2);
  cursor: pointer;
  padding: 0;
}
.ws-app-nav svg { width: 15px; height: 15px; }
.ws-app-nav:hover { background: var(--hover); color: var(--text); }
.ws-app-nav[disabled] { opacity: 0.35; cursor: default; }
.ws-app-nav[disabled]:hover { background: none; color: var(--text-2); }
.ws-app-urlbar {
  flex: 1 1 auto;
  min-width: 0;
  height: 24px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--surface);
  color: var(--text);
  font-size: 12px;
  outline: none;
}
.ws-app-urlbar:focus { border-color: var(--accent); }
.ws-app-download { margin-left: auto; }
/* Header toggle collapses the whole chrome bar (the toggle itself lives in the
   panel header, so it stays reachable). */
.ws-app-holder.urlbar-hidden .ws-app-chrome { display: none; }
/* Slide in left→right; out right→left. */
.ws-app-holder.entering { transform: translateX(-26px); opacity: 0; }
.ws-app-holder.leaving { transform: translateX(-40px); opacity: 0; }
.ws-rail-slot.flash { outline: 2px solid var(--accent); outline-offset: -2px; transition: outline-color 0.6s ease; }

/* (command-center CSS removed — Echo is the launcher. The Layouts page
   still speaks the cc- card language for its cards + mini previews.) */
.cc-card-name { font-size: 12px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cc-layouts { display: flex; flex-wrap: wrap; gap: 16px; }
.cc-layout-card {
  position: relative;
  display: flex; flex-direction: column; gap: 8px; cursor: pointer;
  border: none; background: transparent; align-items: center;
  transition: transform .16s cubic-bezier(.2,.8,.2,1);
}
.cc-layout-card:hover { transform: scale(1.06); }
/* Space badge — same glyph chip the echo tiles wear, upper-right of the mini. */

/* "Maintain on close" — the terminal cell's keep-alive toggle in App Setup. */
/* Space filter beside the layouts search — funnel button + check dropdown. */
.cc-mini {
  position: relative; width: 150px; height: 94px; border-radius: 10px;
  background: var(--surface-2); border: 1px solid var(--border); overflow: hidden;
}
.cc-mini-cell {
  position: absolute; background: var(--hover); border: 1px solid var(--border-2); border-radius: 3px;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}

/* A SECTION hosted as a workbench panel (2.5.0 shell): the section's own
   DOM fills the slot and scrolls itself; padding matches the old #page-body. */
.ws-section-body { display: flex; flex-direction: column; overflow: hidden; }
.ws-section-body > .help-section {
  /* The slot header already titles the panel — content starts tight. */
  flex: 1; min-height: 0; overflow-y: auto; padding: 10px 32px 24px;
}
/* The rails CONTAINER always fills the workbench — it was flex 0 1 auto
   (content-sized), so any state where rail widths went content-driven
   (solo mode) collapsed the whole surface to its content width. */
#code-wb-rails { flex: 1 1 auto; min-width: 0; }

/* SOLO panel — the one open panel fills the page as if expanded: no drop
   strips, no width handle, flush to every edge. */
.ws-right-rails.solo-slot .ws-rail-dropstrip { display: none; }
.ws-right-rails.solo-slot .ws-resize-v { display: none; }
.ws-right-rails.solo-slot .ws-right-rail { width: auto !important; flex: 1 1 auto !important; }

/* Hosted Apps page: the "Apps" h2 renders in-panel exactly like Connections'
   h2 does — hiding it left .section-desc first, whose -16px top margin
   (designed to tuck under an h2) pulled the subtitle up under the panel
   title bar. */
.ws-section-body > .help-section[data-section="docs"],
.ws-section-body > .help-section[data-section="settings"],
.ws-section-body > .help-section[data-section="dashboard"],
.ws-section-body > .help-section[data-section="apps"],
.ws-section-body > .help-section[data-section="connections"],
.ws-section-body > .help-section[data-section="layouts"],
.ws-section-body > .help-section[data-section="build"],
.ws-section-body > .help-section[data-section="customize"] {
  display: flex; flex-direction: column;
}
/* Build / Customize: the hosted .settings-panels own the gutter and the
   scroll (same rules as the modal); the tab strip sits on the same 28px edge. */
.ws-section-body > .help-section.settings-group { padding: 10px 0 0; }
.settings-group-tabs { padding: 0 28px; }
/* Settings/Docs scroll an INNER pane (.settings-panels) — the hosted
   section's own right/bottom gutter left that pane's scrollbar floating
   inboard of the card edge. Mirror the full-page rule (#page-body:has):
   drop the outer gutter, the pane's 28px padding keeps the content inset. */
.ws-section-body > .help-section[data-section="docs"],
.ws-section-body > .help-section[data-section="settings"] {
  padding-right: 0;
  padding-bottom: 0;
}

/* Floating relaunch-to-update badge (was in the rail; the rail is gone). */

/* The app header (2.5.0 shell): a full-width 38px bar — the same height
   #help-overlay offsets by, so every panel opens exactly under it. The whole
   bar is a window-drag surface; #panel-wc (fixed, z 300) rides on top with
   no-drag buttons. */
/* The app header — a SMALL, slightly transparent bar in the theme's surface
   color (the content shows through faintly; blur keeps text legible). */
#shell-drag-strip {
  position: fixed; top: 0; left: 0; right: 0; height: var(--titlebar-h); z-index: 380;
  background: color-mix(in srgb, var(--surface-2) 72%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
}
/* (The header carries no buttons — settings/account live in the wall's
   dock, inside the settings modal.) */
/* The DRAG surface is a child that starts past the chrome cluster — a drag
   region overlapping the buttons eats their clicks (the original rail bug).
   syncDragStripOffset() measures the cluster and overrides the fallback. */
#shell-drag-strip .shell-drag-area {
  height: 100%;
  margin-left: 218px;
  -webkit-app-region: drag;
}
/* Layouts PAGE reuses the command-center card + mini-preview, laid out as a
   left-aligned wrapping grid (the CC storefront centers; the page starts left). */
.layouts-page-grid { justify-content: flex-start; padding: 6px 0; }

/* ── Terminal view (stub session) ── */
.ws-terminal {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--ws-bg-card);
}
.ws-terminal-tabs {
  height: 28px;
  display: flex;
  align-items: stretch;
  gap: 2px;
  padding: 0 4px;
  border-bottom: 1px solid var(--ws-line);
  background: var(--ws-bg-rail);
  flex-shrink: 0;
}
.ws-terminal-tab {
  display: flex; align-items: center; gap: 4px;
  padding: 0 8px;
  font-size: 11.5px;
  color: var(--ws-text-faint);
  cursor: pointer;
  border-bottom: 2px solid transparent;
}
.ws-terminal-tab.active { color: var(--ws-text); border-bottom-color: var(--ws-accent); }
.ws-terminal-tab .close {
  background: transparent; border: none; padding: 0;
  width: 14px; height: 14px;
  font-size: 14px; color: var(--ws-text-faint);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.ws-terminal-tab .close:hover { color: var(--ws-text); }
.ws-terminal-new {
  background: transparent; border: none;
  padding: 0 6px;
  font-size: 14px; color: var(--ws-text-faint);
  cursor: pointer;
}
.ws-terminal-new:hover { color: var(--ws-text); }
.ws-terminal-body {
  flex: 1;
  overflow: auto;
  padding: 8px 12px;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.45;
  color: var(--ws-text);
  white-space: pre-wrap;
  word-break: break-word;
}
.ws-terminal-body .prompt-row {
  display: inline-flex; align-items: center; gap: 4px;
  width: 100%;
}
.ws-terminal-body .ps1 { color: var(--ws-text, var(--text)); }
.ws-terminal-body input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  font: inherit;
  color: var(--ws-text);
  padding: 0;
}

/* ── Workbench Monaco viewer (tabbed) ── */
.ws-monaco-tabs {
  display: flex;
  align-items: stretch;
  gap: 0;
  background: var(--ws-bg-rail);
  border-bottom: 1px solid var(--ws-line);
  overflow-x: auto;
  flex-shrink: 0;
  height: 30px;
  padding: 0 4px;
}
.ws-monaco-tabs::-webkit-scrollbar { height: 0; }
.ws-monaco-tabs-empty { align-self: center; padding: 4px 12px; font-size: 11px; color: var(--text-faint); white-space: nowrap; }
.ws-monaco-tab {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0 8px;
  font-size: 11.5px;
  color: var(--ws-text-faint);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  font-family: var(--font-mono);
}
.ws-monaco-tab.active {
  color: var(--ws-text);
  border-bottom-color: var(--ws-accent);
  background: var(--ws-bg-card);
}
.ws-monaco-tab .close {
  background: transparent; border: none; padding: 0;
  width: 14px; height: 14px;
  font-size: 14px; line-height: 1;
  color: var(--ws-text-faint);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.ws-monaco-tab .close:hover { color: var(--ws-text); }
.ws-monaco-path {
  height: 22px;
  padding: 0 12px;
  border-bottom: 1px solid var(--ws-line);
  background: var(--ws-bg-card);
  display: flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--ws-text-faint);
  flex-shrink: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  direction: rtl;
  text-align: left;
}
.ws-monaco-host {
  flex: 1;
  min-height: 0;
  position: relative;
  background: var(--ws-bg-card);
}

/* ── Workbench drag + drop ── */
.ws-rail-slot-header[draggable="true"] { cursor: grab; }
.ws-rail-slot-header[draggable="true"]:active { cursor: grabbing; }
.ws-rail-slot.dragging { opacity: 0.5; }

/* Insertion indicator: a 3px accent line at the top/bottom edge of the
   hovered slot. */
.ws-rail-slot { position: relative; }
.ws-rail-slot.drop-above::before,
.ws-rail-slot.drop-below::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: 3px;
  background: var(--ws-accent);
  z-index: 30;
  pointer-events: none;
}
.ws-rail-slot.drop-above::before { top: 0; }
.ws-rail-slot.drop-below::after  { bottom: 0; }

/* Between-rail drop strip: a 6px-wide vertical column between rails.
   Highlights on drag-over so the user knows a NEW rail will be inserted. */
.ws-rail-dropstrip {
  /* Invisible seam normally — panels sit flush. While a slot drag is live
     (body.wb-mouse-drag) the strips open up as visible drop targets. */
  width: 0;
  flex-shrink: 0;
  align-self: stretch;
  position: relative;
}
body.wb-mouse-drag .ws-rail-dropstrip { width: 8px; }
.ws-rail-dropstrip.drag-over::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: 2px;
  width: 3px;
  background: var(--ws-accent);
  pointer-events: none;
}

/* Diff expand/collapse-all buttons mirror the refresh button styling. */
.ws-diff-expand,
.ws-diff-collapse {
  background: transparent; border: none; padding: 0;
  width: 24px; height: 24px; border-radius: 4px;
  color: var(--ws-text-faint); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.ws-diff-expand:hover,
.ws-diff-collapse:hover { background: var(--hover); color: var(--ws-text); }
.ws-diff-expand svg,
.ws-diff-collapse svg { width: 13px; height: 13px; }

/* ── Workbench Monaco markdown toggle ── */
/* The path row is now a flex row: path on the left, spacer, then two
   mode buttons (preview / code) on the right. Only shown for .md files. */
.ws-monaco-path { display: flex; align-items: center; }
.ws-monaco-path-text {
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  direction: rtl;
  text-align: left;
}
.ws-monaco-path-spacer { flex: 1; }
.ws-monaco-mode-btn {
  background: transparent;
  border: none;
  padding: 0;
  width: 20px; height: 20px;
  border-radius: 4px;
  color: var(--ws-text-faint);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.10s, color 0.10s;
}
.ws-monaco-mode-btn:hover { background: var(--hover); color: var(--ws-text); }
.ws-monaco-mode-btn.active { color: var(--ws-text, var(--text)); }
.ws-monaco-mode-btn svg { width: 13px; height: 13px; }

/* Markdown rendered host — same scrollable region as the code editor. */
.ws-monaco-md-host {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 14px 22px;
  background: var(--ws-bg-card);
  color: var(--ws-text);
  font-size: 13.5px;
  line-height: 1.55;
}
.ws-monaco-md-host h1,
.ws-monaco-md-host h2,
.ws-monaco-md-host h3,
.ws-monaco-md-host h4 { color: var(--ws-text); margin-top: 1.2em; }
.ws-monaco-md-host pre,
.ws-monaco-md-host code {
  font-family: var(--font-mono);
  font-size: 12px;
  background: var(--ws-bg-rail);
  border-radius: 4px;
  padding: 0.1em 0.3em;
}
.ws-monaco-md-host pre { padding: 10px 12px; overflow-x: auto; }
.ws-monaco-md-host pre code { background: transparent; padding: 0; }
.ws-monaco-md-host a { color: var(--ws-text, var(--text)); }

/* Workbench terminal — xterm host fills the rest of the slot. */
.ws-terminal-host {
  flex: 1;
  min-height: 0;
  padding: 6px 8px;
  background: var(--ws-bg-card);
  position: relative;
}
.ws-terminal-host .xterm,
.ws-terminal-host .xterm .xterm-viewport,
.ws-terminal-host .xterm .xterm-screen { width: 100% !important; height: 100% !important; }

/* ── Workbench slot maximize / restore ── */
/* The coding tile's session controls — sized like every header button. */

.ws-rail-slot-header .slot-maximize {
  background: transparent; border: none; padding: 0;
  width: 24px; height: 24px; border-radius: 4px;
  color: var(--ws-text-faint); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.10s, color 0.10s;
}
.ws-rail-slot-header .slot-maximize:hover { background: var(--hover); color: var(--ws-text); }
.ws-rail-slot-header .slot-maximize svg { width: 12px; height: 12px; }
/* App-panel address-bar toggle — lives beside Expand; accent when the bar shows. */
.ws-rail-slot-header .slot-urltoggle {
  background: transparent; border: none; padding: 0;
  width: 24px; height: 24px; border-radius: 4px;
  color: var(--ws-text-faint); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.10s, color 0.10s;
}
.ws-rail-slot-header .slot-urltoggle:hover { background: var(--hover); color: var(--ws-text); }
.ws-rail-slot-header .slot-urltoggle.active { color: var(--accent); }
.ws-rail-slot-header .slot-urltoggle svg { width: 13px; height: 13px; }

/* Fullscreen state: collapse everything except the maximized slot. The
   maximized slot's rail expands to fill the container, and inside that
   rail only the maximized slot is visible (its vsep + sibling slot hide). */
.ws-right-rails.has-fullscreen .ws-right-rail:not(.rail-has-fullscreen),
.ws-right-rails.has-fullscreen .ws-rail-dropstrip { display: none; }
.ws-right-rails.has-fullscreen .ws-right-rail.rail-has-fullscreen {
  width: auto !important;
  /* !important: a BAND rail carries an inline flex (its rowHeights share),
     which otherwise beats this rule and pins the maximized band to ~40%. */
  flex: 1 1 auto !important;
}
/* A maximized band floods the whole column: the rails row holding the
   non-maximized panels leaves the layout entirely. (When the maximized slot
   is INSIDE the row, the row stays and its siblings hide as usual.) */
.ws-right-rails.has-fullscreen .ws-rails-row:not(:has(.rail-has-fullscreen)) { display: none; }
.ws-right-rails.has-fullscreen .ws-rail-slot:not(.fullscreen),
.ws-right-rails.has-fullscreen .ws-rail-vsep { display: none; }
.ws-right-rails.has-fullscreen .ws-rail-slot.fullscreen {
  flex: 1 !important;
}

/* Layout tab — single grid glyph in front of the layout's name. Replaces
   the previous stacked-favicons cluster. */
.tab-layout-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-2);
  flex-shrink: 0;
  margin-right: 2px;
}
.tab-layout-icon svg { width: 13px; height: 13px; stroke: currentColor; }
.tab-active .tab-layout-icon { color: var(--text); }

/* ── Multi-choice ask card ─────────────────────────────────
   The "Input required" component used between spec-workflow phases (and
   any other multi-choice question the agent emits). Plan-mode purple
   accents to stay consistent with the perm-dropdown plan chip and the
   Plan app chrome. */
.yo-ask-card {
  margin: 8px 6px;
  border: 1px solid #8B5CF6;
  border-radius: 10px;
  background: var(--surface-2);
  overflow: hidden;
  font-size: 13px;
  transition: opacity 0.15s;
}
.yo-ask-card.yo-ask-resolved { opacity: 0.55; pointer-events: none; }

.yo-ask-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: #8B5CF6;
  color: #fff;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.yo-ask-header-icon { width: 14px; height: 14px; }

.yo-ask-question {
  padding: 12px 14px 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-bright);
  line-height: 1.35;
}

.yo-ask-body {
  display: flex;
  flex-direction: column;
}
.yo-ask-card.yo-ask-with-preview .yo-ask-body {
  flex-direction: row;
  align-items: stretch;
}
.yo-ask-options {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px 12px;
}
.yo-ask-card.yo-ask-with-preview .yo-ask-options {
  flex: 0 0 42%;
  border-right: 1px solid var(--border-2);
}
.yo-ask-preview {
  flex: 1;
  padding: 10px 12px 12px;
  background: var(--surface);
  font-size: 12px;
  color: var(--text-2);
  line-height: 1.45;
  overflow-x: auto;
  max-height: 280px;
}
.yo-ask-preview pre {
  background: var(--surface-2);
  border-radius: 4px;
  padding: 6px 8px;
  margin: 0;
  overflow-x: auto;
  font-family: var(--font-mono);
}
.yo-ask-preview code { font-family: var(--font-mono); color: var(--text); }
.yo-ask-preview-empty { color: var(--text-faint); font-style: italic; padding: 6px 0; }
.yo-ask-card:focus { outline: none; }
.yo-ask-option {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border-2);
  border-radius: 6px;
  cursor: pointer;
  background: var(--surface);
  transition: border-color 0.10s, background 0.10s, box-shadow 0.10s;
}
.yo-ask-option:hover { border-color: var(--border-3); background: var(--hover); }
.yo-ask-option.selected {
  border-color: #8B5CF6;
  background: rgba(139, 92, 246, 0.08);
}
/* Keyboard cursor — a focus ring that's independent of the selected fill. */
.yo-ask-option.cursor {
  border-color: #8B5CF6;
  box-shadow: 0 0 0 2px rgba(139, 92, 246, 0.30);
}
/* Radio indicator */
.yo-ask-radio {
  flex-shrink: 0;
  width: 15px;
  height: 15px;
  margin-top: 1px;
  border-radius: 50%;
  border: 1.5px solid var(--border-3);
  background: transparent;
  transition: border-color 0.10s, box-shadow 0.10s;
}
.yo-ask-option.selected .yo-ask-radio {
  border-color: #8B5CF6;
  box-shadow: inset 0 0 0 3.5px #8B5CF6;
}
.yo-ask-option-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.yo-ask-option-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.yo-ask-option-label {
  font-weight: 600;
  color: var(--text-bright);
  font-size: 13px;
}
.yo-ask-option-desc {
  display: block;
  font-size: 11.5px;
  color: var(--text-2);
  margin-top: 3px;
  line-height: 1.4;
}
.yo-ask-recommended {
  margin-left: auto;
  background: rgba(139, 92, 246, 0.18);
  color: #8B5CF6;
  border: 1px solid rgba(139, 92, 246, 0.35);
  border-radius: 4px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.yo-ask-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 12px;
}
.yo-ask-hint {
  margin-right: auto;
  font-size: 10.5px;
  color: var(--text-faint);
  letter-spacing: 0.02em;
}
.yo-ask-btn {
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  padding: 6px 12px;
  border-radius: 6px;
  cursor: pointer;
  border: 1px solid var(--border-2);
  background: transparent;
  color: var(--text-2);
  transition: background 0.10s, color 0.10s, border-color 0.10s;
}
.yo-ask-btn:hover { background: var(--hover); color: var(--text); }
.yo-ask-submit {
  background: #8B5CF6;
  border-color: #8B5CF6;
  color: #fff;
}
.yo-ask-submit:hover {
  background: #7c4cf0;
  border-color: #7c4cf0;
  color: #fff;
}
.yo-ask-btn:disabled { opacity: 0.6; cursor: default; }

/* ── Workbench Sub-Agents view ── */
.ws-subagents-tabs {
  display: flex;
  align-items: stretch;
  background: var(--ws-bg-rail);
  border-bottom: 1px solid var(--ws-line);
  overflow-x: auto;
  flex-shrink: 0;
  height: 30px;
  padding: 0 4px;
  gap: 2px;
}
.ws-subagents-tabs::-webkit-scrollbar { height: 0; }
.ws-subagents-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  font-size: 11.5px;
  color: var(--ws-text-faint);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.ws-subagents-tab.active {
  color: var(--ws-text);
  border-bottom-color: var(--ws-accent);
  background: var(--ws-bg-card);
}
.ws-subagents-tab .dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--text-faint);
  flex-shrink: 0;
}
.ws-subagents-tab.status-running .dot { background: var(--ws-accent); animation: pulse-dot 1.4s ease-in-out infinite; }
.ws-subagents-tab.status-done .dot    { background: var(--ws-text-faint); }
.ws-subagents-tab.status-error .dot   { background: var(--danger); }
@keyframes pulse-dot {
  0%,100% { opacity: 1; }
  50%     { opacity: 0.35; }
}

.ws-subagents-body {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--ws-bg-card);
}
.ws-subagents-empty {
  padding: 20px;
  color: var(--ws-text-faint);
  font-size: 12px;
  text-align: center;
  line-height: 1.5;
}
.ws-subagents-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-bottom: 1px solid var(--ws-line);
  font-size: 10.5px;
  color: var(--ws-text-faint);
  font-family: var(--font-mono);
  flex-shrink: 0;
}
.ws-subagents-source { text-transform: uppercase; letter-spacing: 0.06em; }
.ws-subagents-status {
  margin-left: auto;
  padding: 1px 6px;
  border-radius: 3px;
  text-transform: uppercase;
  font-weight: 600;
  font-size: 9.5px;
}
.ws-subagents-status.status-running { background: rgba(175, 95, 255, 0.15); color: var(--ws-text, var(--text)); }
.ws-subagents-status.status-done    { background: var(--ws-line); color: var(--ws-text-faint); }
.ws-subagents-status.status-error   { background: rgba(220, 38, 38, 0.15); color: var(--danger); }

/* Host wrapper that the active agent's persistent ChatRenderer node is moved
   into. The node itself (.ws-subagents-chat, also .yo-chat) is the scroller. */
.ws-subagents-chat-host {
  flex: 1;
  min-height: 0;
  display: flex;
  overflow: hidden;
  background: var(--ws-bg-card);
}
.ws-subagents-chat {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 12px 14px;
  /* Wrap long, unbroken tokens (file paths, URLs) so the panel never
     overruns the page horizontally. */
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* ── Workbench Plan view ── */
.ws-plan-tabs {
  display: flex;
  align-items: stretch;
  background: var(--ws-bg-rail);
  border-bottom: 1px solid var(--ws-line);
  height: 30px;
  padding: 0 4px;
  gap: 2px;
  flex-shrink: 0;
}
.ws-plan-tab {
  display: inline-flex;
  align-items: center;
  padding: 0 12px;
  font-size: 11.5px;
  color: var(--ws-text-faint);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  text-transform: lowercase;
  font-family: var(--font-mono);
  font-weight: 600;
}
.ws-plan-tab.active {
  color: var(--ws-text);
  border-bottom-color: var(--ws-accent);
  background: var(--ws-bg-card);
}
.ws-plan-status {
  height: 22px;
  padding: 0 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  border-bottom: 1px solid var(--ws-line);
  background: var(--ws-bg-rail);
  flex-shrink: 0;
  font-size: 10.5px;
  font-family: var(--font-mono);
  color: var(--ws-text-faint);
}
.ws-plan-path {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  direction: rtl;
  text-align: left;
}
.ws-plan-savestate.plan-saved  { color: var(--ws-text, var(--text)); }
.ws-plan-savestate.plan-dirty  { color: var(--warning); }
.ws-plan-host {
  flex: 1;
  min-height: 0;
  position: relative;
  background: var(--ws-bg-card);
}
.ws-plan-host .monaco-editor,
.ws-plan-host .monaco-editor-background,
.ws-plan-host .monaco-editor .margin,
.ws-plan-host .monaco-editor .overflow-guard,
.ws-plan-host .monaco-scrollable-element { background: var(--ws-bg-card) !important; }

/* ── Workbench Plan markdown host + mode toggle ── */
.ws-plan-md-host {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 14px 22px;
  background: var(--ws-bg-card);
  color: var(--ws-text);
  font-size: 13.5px;
  line-height: 1.55;
}
.ws-plan-md-host h1,
.ws-plan-md-host h2,
.ws-plan-md-host h3,
.ws-plan-md-host h4 { color: var(--ws-text); margin-top: 1.2em; }
.ws-plan-md-host pre,
.ws-plan-md-host code {
  font-family: var(--font-mono);
  font-size: 12px;
  background: var(--ws-bg-rail);
  border-radius: 4px;
  padding: 0.1em 0.3em;
}
.ws-plan-md-host pre { padding: 10px 12px; overflow-x: auto; }
.ws-plan-md-host pre code { background: transparent; padding: 0; }
.ws-plan-md-host a { color: var(--ws-text, var(--text)); }

/* Reuse the Monaco file viewer's mode-btn styles for Plan too. */
.ws-plan-status .ws-monaco-mode-btn {
  background: transparent;
  border: 1px solid transparent;
  width: 22px; height: 22px;
  border-radius: 4px;
  color: var(--ws-text-faint);
  cursor: pointer;
  padding: 0;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.10s, color 0.10s;
  margin-left: 4px;
}
.ws-plan-status .ws-monaco-mode-btn:hover { background: var(--hover); color: var(--ws-text); }
.ws-plan-status .ws-monaco-mode-btn.active { color: var(--ws-text, var(--text)); }
.ws-plan-status .ws-monaco-mode-btn svg { width: 13px; height: 13px; }

/* (Old in-window Command Center CSS removed — the command overlay's styles
   live in the "Command overlay" section further up, alongside .cc-input,
   .cc-pager, .cc-mini-ico, and the .cc-card--os running-apps variants.) */

/* ── Composer file-attachment preview (drag & drop) ───────────────────────── */
/* Sits above the input row and grows the composer upward to fit. */
.yo-attach-bar { display: flex; flex-wrap: wrap; gap: 8px; padding: 8px 10px 2px; }
.yo-attach-item { position: relative; display: inline-flex; align-items: center; }
.yo-attach-image .yo-attach-thumb {
  width: 56px; height: 56px; object-fit: cover; display: block;
  border-radius: 8px; border: 1px solid var(--border);
}
.yo-attach-file {
  gap: 6px; max-width: 220px; padding: 6px 10px; border-radius: 8px;
  background: var(--accent-bg); border: 1px solid var(--border); font-size: 12px;
}
.yo-attach-icon { flex: 0 0 auto; }
.yo-attach-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.yo-attach-x {
  position: absolute; top: -6px; right: -6px; width: 18px; height: 18px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 50%;
  background: var(--surface, #1b1b1f); color: var(--text);
  cursor: pointer; font-size: 13px; line-height: 1; padding: 0;
}
.yo-attach-x:hover { background: var(--accent); color: #000; border-color: var(--accent); }
#yo-panel.yo-drag-over { outline: 2px dashed var(--accent); outline-offset: -4px; }

/* ── Dashboard HOME composer (replica of the agent panel composer) ──────────
   The panel composer is pinned to the bottom of the right rail; on the HOME
   landing the same markup/classes sit in normal page flow as a card. Reuses
   every .yo-* style unchanged — only the wrapper layout + the home- ids differ
   (the panel's #yo-panel-input / #yo-panel-send styles are id-scoped, so the
   home- ids need their own copies here). */
.home-composer {
  position: relative;             /* anchor the absolutely-positioned drip tray */
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  margin-bottom: 20px;
  padding-bottom: 4px;
  overflow: visible;
}
/* The panel's input-wrap/controls carry top dividers tuned for the stacked
   panel layout; in the card the workdir bar is already the top element, so the
   input-wrap divider is the only accent line we keep. */
.home-composer .yo-panel-controls { border-top: none; }

#home-panel-input {
  flex: 1;
  width: 100%;
  box-sizing: border-box;
  background: var(--surface-3);
  border: 1px solid var(--border-3);
  border-radius: 12px;
  padding: 10px 12px;
  color: var(--text);
  font-size: 13px;
  font-family: var(--font-sans);
  resize: vertical;
  outline: none;
  min-height: 120px;              /* taller multi-row input */
  line-height: 1.5;
  overflow-y: auto;
}
#home-panel-input:focus { border-color: var(--yo-mode-color, var(--accent)); }
#home-panel-input::placeholder { color: var(--text-muted); }

#home-panel-send {
  background: var(--accent);
  color: #000;
  border: 2px solid transparent;
  box-sizing: border-box;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  flex-shrink: 0;
  margin-left: auto;              /* pin send to the right edge of the row */
  transition: opacity 0.15s, background 0.15s;
  display: flex;
  align-items: center;
  justify-content: center;
}
#home-panel-send:hover { opacity: 0.8; }

/* Two-row list cards (Chat history / Scheduled Tasks). The base .crud-card is
   a centered single row; here we stack a title row over a meta row. */
.home-list-card { align-items: stretch; }
.home-card-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.home-card-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }
.home-card-row .crud-card-name { flex: 1; min-width: 0; }
.home-card-row-meta .crud-card-meta { flex: none; }
.home-card-open { flex-shrink: 0; opacity: 0.7; }
.home-list-card:hover .home-card-open { opacity: 1; }

/* ── Form-field focus highlight ──────────────────────────────
   Neutral highlight (white in dark mode, black in light mode) instead of the
   purple accent — applies app-wide, overriding the per-component :focus rules.
   Error/invalid states keep their own higher-specificity colour. */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):focus,
textarea:focus,
select:focus {
  border-color: var(--text-bright) !important;
  box-shadow: none !important;
}

/* ── Field hints + inline messages (ported from platform globals.css for
   Agents-form parity) ─────────────────────────────────────── */
.field-hint { font-size: 0.75rem; color: var(--text-3); margin-top: 0.25rem; }
.msg { font-size: 0.8125rem; margin-top: 0.5rem; padding: 0.5rem 0.75rem; border-radius: var(--radius-sm, 6px); }
.msg-warning {
  background: rgba(245, 158, 11, 0.1);
  border: 1px solid rgba(245, 158, 11, 0.3);
  color: var(--text);
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
}
.msg-warning svg { flex-shrink: 0; color: #f59e0b; margin-top: 0.0625rem; }
.msg-warning a { color: var(--text); text-decoration: underline; font-weight: 600; cursor: pointer; }

/* ══ Apps page ═══ */
/* While an app editor / add form is open, hide the page-level chrome (the
   "Apps" heading + description) so the form stands alone with just its
   breadcrumb — same as the connection editor. (The one apps grid — work
   panels + org apps in #apps-list — is JS-hidden on those paths.) */
.help-section[data-section="apps"]:has(#app-detail:not(.hidden)) .apps-page-heading,
.help-section[data-section="apps"]:has(#app-detail:not(.hidden)) > #apps-library-page > .section-desc,
.help-section[data-section="apps"]:has(#app-add-form:not(.hidden)) .apps-page-heading,
.help-section[data-section="apps"]:has(#app-add-form:not(.hidden)) > #apps-library-page > .section-desc {
  display: none !important;
}
/* Same for the connection editor: hide the "Connections" heading + description
   while a connection detail is open, so the form stands alone. */
.help-section[data-section="connections"]:has(#conn-detail:not(.hidden)) > h2,
.help-section[data-section="connections"]:has(#conn-detail:not(.hidden)) > .section-desc {
  display: none !important;
}
/* .apps-page-heading carries NO offsets of its own — it renders on the base
   .help-section h2 grammar so the Apps header lands exactly where the
   Connections header does. (The old margin-top:20px was the dead
   My apps | Marketplace tab-strip y-offset.) */

/* Work panels — the fixed built-in cards that sit FIRST in the one apps grid
   (#apps-grid). Same .app-card grammar as the org cards after them; only the
   inline SVG icon (verbatim from the old view-dropdown buttons) needs a size. */
.workpanel-card .app-card-icon svg { width: 28px; height: 28px; }

/* ── Marketplace storefront (its own section — sections/marketplace.html) ── */
.mkt-banner {
  position: relative; overflow: hidden;
  margin-top: 20px; margin-bottom: 24px;
  padding: 30px 34px; border-radius: 18px;
  /* The brand ramp from the web hero (glyphh.ai → Desktop, .hs-canvas): violet at
     the bottom-left, peach at the top-right. One surface language across the site
     and the app, so the marketplace reads as the same product as the landing page. */
  /* A tad darker (his call, 2026-08-20) so the white type carries. */
  background:
    radial-gradient(90% 80% at 100% 0%, rgba(255,255,255,.28) 0%, rgba(255,255,255,0) 55%),
    radial-gradient(100% 90% at 0% 100%, rgba(109,40,217,.62) 0%, rgba(109,40,217,0) 62%),
    linear-gradient(35deg, #8b5cf6 0%, #a678f0 44%, #e79cd0 100%);
  box-shadow: 0 18px 60px rgba(16,4,40,.45), inset 0 0 0 1px rgba(255,255,255,.35);
  /* Ink on a LIGHT ramp — the old banner was white-on-violet. */
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 28px; align-items: center;
}
/* Braille-dot texture — the Glyphh mark, whispered. Same as the web canvas. */
.mkt-banner::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(rgba(70,28,140,.16) 1px, transparent 1.4px);
  background-size: 16px 16px;
  -webkit-mask-image: linear-gradient(35deg, transparent 25%, #000 85%);
          mask-image: linear-gradient(35deg, transparent 25%, #000 85%);
}

/* ── The deliverable: an app someone built, floating on the ramp ── */
.mkt-hero-art {
  position: relative; width: 316px; flex: none;
  margin: 4px 6px 0 0;
  transform: rotate(-1.4deg);
}
.mha-app {
  background: #fbf9fe; border-radius: 13px; overflow: hidden;
  box-shadow: 0 26px 70px rgba(16,4,40,.45), 0 0 0 1px rgba(255,255,255,.6);
}
.mha-bar {
  display: flex; align-items: center; gap: 5px;
  padding: 8px 11px; background: #f2edfa; border-bottom: 1px solid #e6dff2;
}
.mha-dot { width: 7px; height: 7px; border-radius: 50%; background: #d9cff0; }
.mha-name { margin-left: 7px; font-size: 11px; font-weight: 680; color: #3b3350; letter-spacing: -.01em; }
.mha-chip {
  margin-left: auto; font-size: 8.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: #2f7d5b; background: rgba(52,211,153,.2); padding: 2px 6px; border-radius: 4px;
}
.mha-body { padding: 13px 14px 15px; }
.mha-kpi { display: flex; align-items: baseline; gap: 8px; }
.mha-kpi-label { font-size: 9.5px; text-transform: uppercase; letter-spacing: .06em; color: #a49bb8; }
.mha-kpi-value { margin-left: auto; font-size: 21px; font-weight: 760; color: #2c2735; letter-spacing: -.02em; }
.mha-kpi-cents { font-size: 13px; color: #8e85a5; font-weight: 700; }

.mha-chart { display: flex; align-items: flex-end; gap: 5px; height: 46px; margin: 11px 0 13px; }
.mha-chart i { flex: 1; border-radius: 3px 3px 1px 1px; background: #e2d8f5; }
/* One bar carries the brand accent — the month in progress. */
.mha-chart i.on { background: linear-gradient(180deg, #a78bfa, #af5fff); }

.mha-rows { display: flex; flex-direction: column; gap: 7px; }
.mha-row { display: flex; align-items: center; gap: 7px; }
.mha-av {
  width: 19px; height: 19px; flex: none; border-radius: 6px;
  background: #ede6fa; color: #6d28d9; font-size: 8px; font-weight: 750;
  display: flex; align-items: center; justify-content: center; letter-spacing: .02em;
}
.mha-vendor { font-size: 10.5px; color: #3b3350; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mha-tag {
  font-size: 8.5px; color: #7c6f96; background: #f1ecf8; border-radius: 4px; padding: 2px 5px; flex: none;
}
.mha-amt { margin-left: auto; font-size: 10.5px; font-weight: 700; color: #2c2735; font-variant-numeric: tabular-nums; }

.mha-foot {
  display: flex; align-items: center; gap: 6px;
  margin-top: 12px; padding-top: 10px; border-top: 1px solid #ece5f7;
  font-size: 9.5px; color: #8e85a5; letter-spacing: .02em;
}
.mha-foot-dot { width: 5px; height: 5px; border-radius: 50%; background: #af5fff; flex: none; }
.mha-foot-sep { color: #cec4e4; }

/* The art is decoration: below this width the copy + search take the whole banner
   rather than being squeezed beside it.
   A CONTAINER query, not a media query — the Apps page is a panel inside the
   workbench, so the window can be 1400px wide while this pane is 500px. Keying
   off the viewport squeezed the search box on exactly the layouts people use. */
#mkt-store { container-type: inline-size; }
@container (max-width: 760px) {
  .mkt-banner { grid-template-columns: minmax(0, 1fr); }
  .mkt-hero-art { display: none; }
}
/* Beside the search, not in the banner's corner — the corner is where the app
   mockup lives, and two things fighting for it read as a collision. */
.mkt-refresh {
  position: relative; flex: none;
  width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 12px; cursor: pointer;
  background: rgba(255,255,255,.72); border: 1px solid rgba(255,255,255,.9); color: #4c1d95;
  box-shadow: 0 8px 24px rgba(16,4,40,.16);
  transition: background .12s;
}
.mkt-refresh:hover { background: rgba(255,255,255,.85); }
.mkt-refresh.spinning svg { animation: mkt-spin .7s linear infinite; }
@keyframes mkt-spin { to { transform: rotate(360deg); } }
.mkt-banner-inner { position: relative; max-width: 620px; }
.mkt-banner-title {
  /* WHITE, non-negotiable (2026-08-20): !important + text-fill so no theme,
     gradient-text, or heading rule anywhere can override it. */
  font-size: 27px; font-weight: 780; margin: 0 0 8px;
  color: #ffffff !important;
  -webkit-text-fill-color: #ffffff !important;
  letter-spacing: -0.03em;
  text-shadow: 0 1px 10px rgba(76, 29, 149, 0.35);
}
.mkt-banner-sub { font-size: 14px; line-height: 1.5; margin: 0 0 20px; max-width: 54ch; color: rgba(255,255,255,.92) !important; -webkit-text-fill-color: rgba(255,255,255,.92) !important; text-shadow: 0 1px 8px rgba(76, 29, 149, 0.3); }

.mkt-search-wrap { position: relative; max-width: 508px; display: flex; align-items: center; gap: 8px; }
.mkt-search-icon { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: #7b7b86; z-index: 1; }
.mkt-search {
  width: 100%; height: 44px; padding: 0 14px 0 38px; box-sizing: border-box;
  background: rgba(255,255,255,.96); border: 1px solid transparent; border-radius: 12px;
  color: #16161a; font-size: 14px;
  box-shadow: 0 8px 24px rgba(16,4,40,.22);
}
.mkt-search::placeholder { color: #8a8a95; }
.mkt-search:focus { outline: none; border-color: #af5fff; box-shadow: 0 8px 28px rgba(16,4,40,.3); }

.mkt-scopebar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.mkt-scope-tabs { display: flex; gap: 4px; background: var(--surface-2); border: 1px solid var(--border-2); border-radius: 10px; padding: 3px; }
.mkt-scope {
  padding: 5px 14px; border-radius: 7px; border: none; background: transparent;
  color: var(--text-3); font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.mkt-scope:hover { color: var(--text); }
.mkt-scope.active { background: var(--surface); color: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,.15); }
.mkt-sort { width: auto; height: 34px; font-size: 12.5px; padding: 0 10px; }

/* Type filters — same button-pill style as the page tabs, but the selected
   one gets a white border (not a white fill). */
.mkt-categories { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 22px; }
.mkt-cat {
  padding: 7px 14px; border-radius: 9px; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--border-2);
  color: var(--text-2); font-size: 12.5px; font-weight: 600; white-space: nowrap;
  transition: background .12s, color .12s, border-color .12s;
}
.mkt-cat:hover { color: var(--text); border-color: var(--border-3, var(--border-2)); }
.mkt-cat.active { background: var(--surface-2); border-color: #fff; color: #fff; }

.mkt-strip { margin-bottom: 30px; }
.mkt-strip-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; }
.mkt-strip-head h4 { font-size: 15px; font-weight: 700; color: var(--text); margin: 0; }
.mkt-count { font-size: 12.5px; color: var(--text-3); }

/* Grids */
/* auto-fit (not auto-fill) so a partial last row stretches to the full width —
   auto-fill keeps phantom empty tracks on the right, which read as a gap. */
.mkt-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; }
/* Popular strip wraps onto multiple rows — no horizontal scroll. */
.mkt-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; }

/* Card — modeled after the Shopify app-store listing tile.
   The whole card is a link into the app's detail page (no per-card Install). */
.mkt-card {
  position: relative; cursor: pointer;
  display: flex; flex-direction: column; gap: 9px; padding: 16px;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: 14px;
  transition: border-color .15s, transform .15s, box-shadow .15s;
}
.mkt-card:hover { border-color: var(--border-3, var(--accent)); transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,0,0,.14); }
.mkt-card-top { display: flex; align-items: flex-start; gap: 11px; }
/* Icon matches the My-apps page card icon (32px). */
/* 52px, up from 32 (his call, 2026-08-27 — the storefront cards read tiny). */
.mkt-card-icon { width: 52px; height: 52px; border-radius: 12px; overflow: hidden; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.mkt-card-icon img { width: 100%; height: 100%; object-fit: contain; padding: 5px; box-sizing: border-box; }
.mkt-card-initial { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: var(--accent); color: var(--accent-fg); font-size: 15px; font-weight: 700; }
.mkt-card-head { min-width: 0; flex: 1; }
.mkt-card-name { font-size: 14.5px; font-weight: 650; color: var(--text); line-height: 1.25; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.mkt-card-metaline { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 5px; font-size: 11.5px; color: var(--text-3); }
.mkt-rating { color: var(--text-2); display: inline-flex; align-items: center; gap: 4px; }
.mkt-rating b { color: var(--text); font-weight: 650; }
.mkt-rating-count { color: var(--text-3); }
.mkt-stars { color: #f5a623; letter-spacing: -1px; }
.mkt-dot { color: var(--text-3); }
.mkt-price { color: var(--text-2); }
.mkt-card-tagline { font-size: 12.5px; line-height: 1.45; color: var(--text-2); flex: 1; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Required-connection icons — icons only, same as the Layouts card row
   (.layout-app-icon), just smaller. No name labels. */
.mkt-conns { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 1px; }
.mkt-conn {
  width: 18px; height: 18px; border-radius: 5px; overflow: hidden; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.mkt-conn img { width: 18px; height: 18px; display: block; border-radius: 5px; object-fit: contain; }
.mkt-conn-initial {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--accent-fg); font-size: 9px; font-weight: 700;
}

.mkt-note {
  background: var(--accent-bg, rgba(175,95,255,.12)); border: 1px solid var(--accent);
  color: var(--text); font-size: 12.5px; padding: 8px 12px; border-radius: 8px; margin-bottom: 14px;
}

/* Inline notice banner (mktNoticeHtml) — icon + message on a quiet surface,
   used wherever a marketplace fetch fails (console profiles, Settings →
   Developer). Deliberately NOT a loud red row: surface background, normal
   text, only the icon carries the danger color. */
.mkt-notice {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 11px 14px; margin: 0 0 16px;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: 10px;
  font-size: 13px; line-height: 1.5; color: var(--text-2);
}
.mkt-notice-icon { flex-shrink: 0; display: flex; margin-top: 2px; color: var(--text-3); }
.mkt-notice.error .mkt-notice-icon { color: var(--danger, #e5484d); }
.mkt-notice.warn .mkt-notice-icon { color: #f5a623; }
.mkt-notice.warn { border-color: rgba(245, 166, 35, 0.35); }
.mkt-notice-text { min-width: 0; }

/* Dashed placeholder card — the marketplace's quiet empty state (console
   "Your listings", etc.), matching the office panels' dashed-box pattern. */
.mkt-empty-card {
  padding: 28px 20px; text-align: center;
  background: var(--surface); border: 1px dashed var(--border-2); border-radius: 12px;
  color: var(--text-3); font-size: 13px; line-height: 1.55;
}

/* ── Marketplace app detail page (Shopify-style listing) ─────────── */
.mkt-detail { margin-top: 18px; padding-bottom: 40px; }

.mkt-back {
  display: inline-flex; align-items: center; gap: 6px; margin-bottom: 12px;
  background: none; border: none; padding: 4px 0; cursor: pointer;
  color: var(--text-2); font-size: 13px; font-weight: 600;
}
.mkt-back:hover { color: var(--text); }
.mkt-crumbs { font-size: 12px; color: var(--text-3); margin-bottom: 18px; }
.mkt-crumbs .sep { margin: 0 7px; opacity: .6; }
.mkt-crumbs .cur { color: var(--text-2); }

/* Hero */
.mkt-dt-hero {
  display: grid; grid-template-columns: 84px 1fr auto; align-items: start; gap: 20px;
  padding-bottom: 26px; margin-bottom: 26px; border-bottom: 1px solid var(--border-2);
}
.mkt-dt-icon { width: 84px; height: 84px; border-radius: 20px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,.16); }
.mkt-dt-icon img { width: 100%; height: 100%; object-fit: contain; padding: 10px; box-sizing: border-box; }
.mkt-dt-headmain { min-width: 0; }
.mkt-dt-name { font-size: 26px; font-weight: 750; color: var(--text); margin: 0 0 6px; letter-spacing: -0.02em; line-height: 1.1; }
.mkt-dt-tagline { font-size: 15px; color: var(--text-2); margin: 0 0 12px; line-height: 1.4; }
.mkt-dt-metarow { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-bottom: 8px; }
.mkt-dt-dev { font-size: 13px; color: var(--text-2); }
.mkt-dt-dev b { color: var(--text); font-weight: 650; }
.mkt-dt-statrow { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font-size: 13px; color: var(--text-2); }
.mkt-dt-statrow .mkt-stars { font-size: 14px; }
.mkt-dt-statrow b { color: var(--text); }
.mkt-dt-cta { display: flex; flex-direction: column; align-items: stretch; gap: 8px; min-width: 168px; }
.mkt-dt-install { justify-content: center; height: 42px; font-size: 14px; font-weight: 650; }
.mkt-dt-price-note { font-size: 12px; color: var(--text-3); text-align: center; }

/* Two-column body */
.mkt-dt-body { display: grid; grid-template-columns: minmax(0,1fr) 300px; gap: 34px; align-items: start; }
.mkt-dt-main { min-width: 0; }
.mkt-dt-section { margin-bottom: 34px; }
.mkt-dt-section > h3 { font-size: 17px; font-weight: 700; color: var(--text); margin: 0 0 14px; }

/* Gallery */
.mkt-gallery-main {
  border-radius: 14px; overflow: hidden; border: 1px solid var(--border-2);
  background: var(--surface-2); aspect-ratio: 16 / 10; display: flex;
  min-width: 0; min-height: 0;
}
.mkt-gallery-main img { width: 100%; height: 100%; object-fit: cover; display: block; cursor: zoom-in; }
.mkt-gallery-video { width: 100%; height: 100%; object-fit: contain; display: block; background: #000; }
.mkt-gallery-caption { font-size: 12.5px; color: var(--text-3); margin: 10px 2px 12px; }
.mkt-gallery-thumbs { display: flex; gap: 10px; flex-wrap: wrap; }
.mkt-thumb {
  width: 96px; height: 62px; border-radius: 9px; overflow: hidden; cursor: pointer;
  border: 2px solid transparent; background: var(--surface-2); flex-shrink: 0; padding: 0;
}
.mkt-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mkt-thumb.active { border-color: var(--accent); }

/* Highlights */
.mkt-highlights { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.mkt-highlights li { display: flex; align-items: flex-start; gap: 10px; font-size: 13.5px; color: var(--text-2); line-height: 1.45; }
.mkt-highlights svg { flex-shrink: 0; margin-top: 1px; color: var(--accent); }

/* Description */
.mkt-dt-desc p { font-size: 14px; line-height: 1.65; color: var(--text-2); margin: 0 0 14px; }
.mkt-dt-desc p:last-child { margin-bottom: 0; }

/* Plans */
.mkt-plans { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px; }
.mkt-plan {
  border: 1px solid var(--border-2); border-radius: 14px; padding: 18px; background: var(--surface);
  display: flex; flex-direction: column; gap: 4px;
}
.mkt-plan-name { font-size: 14px; font-weight: 700; color: var(--text); }
.mkt-plan-price { font-size: 22px; font-weight: 750; color: var(--text); letter-spacing: -0.02em; margin-top: 2px; }
.mkt-plan-price small { font-size: 12px; font-weight: 500; color: var(--text-3); }
.mkt-plan-blurb { font-size: 12px; color: var(--text-3); margin-bottom: 8px; }
.mkt-plan-features { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 8px; }
.mkt-plan-features li { display: flex; align-items: flex-start; gap: 8px; font-size: 12.5px; color: var(--text-2); line-height: 1.4; }
.mkt-plan-features svg { flex-shrink: 0; margin-top: 2px; color: var(--accent); }
.mkt-plans-note { font-size: 12px; color: var(--text-3); margin-top: 12px; }

/* Reviews */
.mkt-reviews-summary { display: grid; grid-template-columns: auto 1fr; gap: 28px; align-items: center; padding: 18px 20px; border: 1px solid var(--border-2); border-radius: 14px; margin-bottom: 20px; }
.mkt-reviews-score { text-align: center; }
.mkt-reviews-score .big { font-size: 40px; font-weight: 780; color: var(--text); line-height: 1; letter-spacing: -0.03em; }
.mkt-reviews-score .mkt-stars { font-size: 15px; }
.mkt-reviews-score .cnt { font-size: 12px; color: var(--text-3); margin-top: 3px; }
.mkt-reviews-bars { display: grid; gap: 6px; }
.mkt-bar-row { display: grid; grid-template-columns: 46px 1fr 42px; align-items: center; gap: 10px; font-size: 12px; color: var(--text-3); }
.mkt-bar-track { height: 8px; border-radius: 6px; background: var(--surface-3, var(--surface-2)); overflow: hidden; }
.mkt-bar-fill { height: 100%; border-radius: 6px; background: #f5a623; }
.mkt-bar-row .pct { text-align: right; }
.mkt-review-list { display: grid; gap: 16px; }
.mkt-review { border-bottom: 1px solid var(--border-2); padding-bottom: 16px; }
.mkt-review:last-child { border-bottom: none; padding-bottom: 0; }
.mkt-review-head { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; }
.mkt-review-head .mkt-stars { font-size: 13px; }
.mkt-review-date { font-size: 12px; color: var(--text-3); }
.mkt-review-body { font-size: 13.5px; line-height: 1.55; color: var(--text-2); margin: 0 0 8px; }
.mkt-review-who { font-size: 12px; color: var(--text-3); }
.mkt-review-who b { color: var(--text-2); font-weight: 650; }

/* Sidebar */
.mkt-dt-side { display: grid; gap: 16px; position: sticky; top: 12px; }
.mkt-side-card { border: 1px solid var(--border-2); border-radius: 14px; padding: 16px 18px; background: var(--surface); }
.mkt-side-card h4 { font-size: 13px; font-weight: 700; color: var(--text); margin: 0 0 12px; text-transform: uppercase; letter-spacing: .04em; }
.mkt-works { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.mkt-works li { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--text-2); }
.mkt-works .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
.mkt-side-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-size: 12.5px; padding: 5px 0; }
.mkt-side-row + .mkt-side-row { border-top: 1px solid var(--border-2); }
.mkt-side-row span { color: var(--text-3); flex-shrink: 0; }
.mkt-side-row b { color: var(--text); font-weight: 600; text-align: right; }
.mkt-side-row a { color: var(--accent); text-decoration: none; text-align: right; word-break: break-all; }
.mkt-side-row a:hover { text-decoration: underline; }
.mkt-dataaccess { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.mkt-dataaccess li { display: flex; align-items: flex-start; gap: 9px; font-size: 12.5px; color: var(--text-2); line-height: 1.4; }
.mkt-dataaccess svg { flex-shrink: 0; margin-top: 1px; color: var(--text-3); }

@media (max-width: 900px) {
  .mkt-dt-body { grid-template-columns: 1fr; }
  .mkt-dt-side { position: static; }
  .mkt-dt-hero { grid-template-columns: 64px 1fr; }
  .mkt-dt-icon { width: 64px; height: 64px; }
  .mkt-dt-cta { grid-column: 1 / -1; min-width: 0; }
}

/* ── Marketplace M2: badges, reviews, developer pages, console, desk ── */
/* Every color is a theme variable — themes own colors (repo law). */

/* Kind + state chips on cards and the detail hero. */
.mkt-kind-badge {
  align-self: flex-start;
  font-size: 10.5px; font-weight: 650; letter-spacing: .02em;
  color: var(--text-2); background: var(--surface-2);
  border: 1px solid var(--border-2); border-radius: 5px; padding: 2px 7px;
}
.mkt-installed { color: var(--success, var(--accent)); font-weight: 650; }
.mkt-rating-none, .mkt-rating-pending { color: var(--text-3); font-size: 11.5px; }
.mkt-discount-chip {
  font-size: 10.5px; font-weight: 650; color: var(--accent);
  border: 1px solid var(--accent); border-radius: 5px; padding: 1px 6px;
}
.mkt-discount-note { font-size: 12px; color: var(--accent); margin-top: 6px; }
.mkt-price s { color: var(--text-3); margin-right: 2px; }

/* Suspension + admin strip on the detail page. */
.mkt-suspended-banner {
  margin: 10px 0; padding: 10px 12px; border-radius: 8px;
  border: 1px solid var(--danger, #e5484d); color: var(--danger, #e5484d);
  font-size: 12.5px;
}
.mkt-admin-strip {
  display: flex; align-items: center; gap: 10px; margin: 10px 0;
  padding: 8px 12px; border-radius: 8px;
  background: var(--surface-2); border: 1px dashed var(--border-2);
}
.mkt-admin-tag {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-3);
}
.mkt-reported-chip {
  font-size: 11px; font-weight: 650; color: var(--danger, #e5484d);
  border: 1px solid var(--danger, #e5484d); border-radius: 5px; padding: 1px 7px;
}

/* Review rows: actions, moderation chips, the developer's public reply. */
.mkt-review-head { display: flex; align-items: center; gap: 8px; }
.mkt-rev-act {
  background: none; border: none; cursor: pointer; padding: 2px 4px;
  font-size: 11.5px; color: var(--text-3);
}
.mkt-rev-act:hover { color: var(--text); text-decoration: underline; }
.mkt-flag-chip {
  font-size: 10px; font-weight: 650; color: var(--text-3);
  border: 1px solid var(--border-2); border-radius: 4px; padding: 0 5px;
}
.mkt-review-response {
  margin-top: 8px; padding: 8px 10px; border-left: 2px solid var(--accent);
  background: var(--surface-2); border-radius: 0 8px 8px 0;
  font-size: 12.5px; color: var(--text-2); line-height: 1.5;
}
.mkt-review-response-tag { display: block; font-size: 10.5px; font-weight: 700; color: var(--text-3); margin-bottom: 3px; }

/* The write-a-review form (apps + developers share it). */
.mkt-review-form { margin-top: 18px; padding: 14px; border: 1px solid var(--border-2); border-radius: 12px; background: var(--surface); }
.mkt-review-form h4 { margin: 0 0 10px; font-size: 13.5px; color: var(--text); }
.mkt-star-input { display: flex; gap: 2px; margin-bottom: 10px; }
.mkt-star-btn {
  background: none; border: none; cursor: pointer; padding: 0 2px;
  font-size: 22px; line-height: 1; color: var(--text-3);
}
.mkt-star-btn.on, .mkt-star-btn:hover { color: #f5a623; }

/* Developer card (detail sidebar) + the public profile page. */
.mkt-dev-row { display: flex; align-items: center; gap: 10px; }
.mkt-dev-avatar {
  width: 40px; height: 40px; border-radius: 50%; overflow: hidden; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; background: var(--surface-2);
}
.mkt-dev-avatar img { width: 100%; height: 100%; object-fit: cover; }
.mkt-dev-id { display: flex; flex-direction: column; min-width: 0; }
.mkt-dev-id b { font-size: 13px; color: var(--text); }
.mkt-dev-handle { font-size: 11.5px; color: var(--text-3); }
.mkt-dev-stats { margin: 10px 0; font-size: 12px; color: var(--text-2); display: grid; gap: 4px; }
.mkt-dev-rollup { color: var(--text-3); }
.mkt-dev-profile-btn { width: 100%; }
.mkt-support-link { display: block; margin-top: 8px; font-size: 12.5px; color: var(--accent); }
.mkt-support-link:hover { text-decoration: underline; }
.mkt-devp-hero { grid-template-columns: 84px 1fr; }
.mkt-devp-avatar { border-radius: 50%; }
.mkt-devp-avatar img { object-fit: cover; }
.mkt-devp-bio { font-size: 13.5px; line-height: 1.6; color: var(--text-2); margin: 0; max-width: 640px; }
.mkt-dev-apps { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 10px; }
.mkt-dev-app {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: 10px;
  color: var(--text); text-align: left;
}
.mkt-dev-app:hover { border-color: var(--border-3, var(--accent)); }
.mkt-dev-app-name { flex: 1; font-size: 13px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Developer console. */
/* Header: crumbs → H1 → its own muted subtitle line. The global .section-desc
   carries a -16px top margin (built to tuck under section h2s with a 24px
   bottom margin) — under this 4px-margin H1 it climbed INTO the heading, so
   the console subtitle is its own class with plain margins. */
.mkt-console-title {
  font-size: 24px; font-weight: 750; letter-spacing: -0.02em; line-height: 1.15;
  color: var(--text); margin: 0 0 6px;
}
.mkt-console-sub { font-size: 13.5px; color: var(--text-2); line-height: 1.5; margin: 0 0 28px; max-width: 640px; }
/* Developer profile tabs (renderDeveloperProfiles): the app's REAL tab strip
   (.app-detail-tabs — Workspaces/Models/app editors, underline active), with
   the autosave chip riding the strip's right edge in place of the heading it
   sits beside elsewhere. The pane content reuses the settings form grammar
   (acct-identity / acct-row / acct-field) — nothing invented. */
.mc-tabs { align-items: center; }
.mc-tabs .mc-save-state { margin-left: auto; }
/* "View public page" is navigation inside the identity card, not a button. */
.mc-view-link { font-size: 12px; margin-top: 2px; }
.mkt-console-apps { display: grid; gap: 10px; }

/* ── Developer console: Home tab (usage-style) ────────────────────────── */
/* Air between the tab strip and the stat cards, and around the charts. */
#mcc-home .dash-grid { margin-top: 22px; }
.mcc-charts { display: grid; grid-template-columns: 2fr 1fr; gap: 14px; margin: 18px 0 6px; }
.mcc-chart-host { position: relative; height: 220px; margin-top: 10px; }
@media (max-width: 900px) { .mcc-charts { grid-template-columns: 1fr; } }
.mc-chip-row { display: flex; justify-content: flex-end; min-height: 20px; }
.mkt-console-app { border: 1px solid var(--border-2); border-radius: 12px; background: var(--surface); overflow: hidden; }
.mkt-console-app-head {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 12px 14px;
  background: none; border: none; cursor: pointer; color: var(--text); text-align: left;
}
.mkt-console-app-head:hover { background: var(--hover); }
.mkt-console-app-head .mkt-card-icon { width: 28px; height: 28px; }
.mkt-console-app-name { font-size: 13.5px; font-weight: 650; }
.mkt-console-app-sub { font-size: 11.5px; color: var(--text-3); font-family: var(--font-mono); }
.mkt-console-chev { color: var(--text-3); }
.mkt-listed-chip {
  font-size: 10.5px; font-weight: 650; color: var(--text-3);
  border: 1px solid var(--border-2); border-radius: 5px; padding: 1px 7px;
}
.mkt-listed-chip.on { color: var(--success, var(--accent)); border-color: var(--success, var(--accent)); }
.mkt-console-app-body { padding: 4px 14px 14px; border-top: 1px solid var(--border-1, var(--border-2)); }
.mkt-console-cols { display: grid; grid-template-columns: minmax(260px, 380px) 1fr; gap: 22px; }
.mkt-console-col h5 {
  margin: 12px 0 8px; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-3);
}
.mkt-disc-window { display: flex; align-items: center; gap: 8px; }
.mkt-disc-window span { color: var(--text-3); }
@media (max-width: 900px) { .mkt-console-cols { grid-template-columns: 1fr; } }

/* Release rows (console) + review-status chips (console + desk). */
.mkt-release-row { padding: 8px 0; border-top: 1px solid var(--border-1, var(--border-2)); }
.mkt-release-row:first-child { border-top: none; }
.mkt-release-head { display: flex; align-items: center; gap: 8px; }
.mkt-review-chip {
  display: inline-flex; align-items: center;
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  border-radius: 4px; padding: 1px 6px; border: 1px solid var(--border-2); color: var(--text-3);
  white-space: nowrap;
}
.mkt-review-chip.submitted, .mkt-review-chip.in_review { color: var(--accent); border-color: var(--accent); }
.mkt-review-chip.approved { color: var(--success, var(--accent)); border-color: var(--success, var(--accent)); }
.mkt-review-chip.rejected { color: var(--danger, #e5484d); border-color: var(--danger, #e5484d); }
.mkt-review-notes { margin-top: 6px; font-size: 12px; color: var(--text-2); line-height: 1.5; }

/* ── Settings → Developer (the M7 program panel) ──────────────────── */
/* Flat subheading + acct-section blocks — the same grammar as Account; the
   only bespoke bit is the status chip sitting on line with its explanation. */
.dev-status-row { display: flex; align-items: flex-start; gap: 10px; }
.dev-status-row .mkt-review-chip { padding: 3px 9px; border-radius: 6px; margin-top: 1px; }
.dev-status-row .settings-hint { line-height: 1.55; }

/* Review desk (platform admin). */
.mkt-admin-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin: 6px 0 16px; }
.mkt-admin-row { padding: 12px 14px; border: 1px solid var(--border-2); border-radius: 12px; background: var(--surface); margin-bottom: 10px; }
.mkt-admin-row-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.mkt-admin-app-link { background: none; border: none; cursor: pointer; padding: 0; color: var(--text); text-align: left; }
.mkt-admin-app-link:hover b { text-decoration: underline; }

/* ── Connections section ─────────────────────────────────────────── */
.conn-tools-pane { flex: 1; min-height: 0; overflow-y: auto; padding: 16px; }
/* Inline button spinner — Add & Connect / Connect while an MCP server dials. */
.btn-spinner {
  display: inline-block; width: 11px; height: 11px; margin-right: 7px;
  border: 2px solid currentColor; border-top-color: transparent; border-radius: 50%;
  vertical-align: -1px; animation: btn-spin .7s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
/* Shared edit-form header: icon (or icon-list) + NAME + slug. Used by the
   Apps, Connections, Layouts and Drips editors for a consistent look. */
.edit-head { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; }
.edit-head .app-card-icon { width: 40px; height: 40px; }
.edit-head-icons { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.edit-head-name { font-size: 17px; font-weight: 700; color: var(--text); display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.edit-head-slug { font-size: 12px; font-weight: 500; color: var(--text-3); font-family: var(--font-mono); }
/* Name+slug row on top, the published address (or "Not Published") on its own
   line UNDER the title — never inline with it. */
.edit-head-col { display: flex; flex-direction: column; min-width: 0; }
.edit-head-url { font-size: 12px; margin-top: 3px; font-weight: 400; }
.edit-head-url a { color: var(--accent); text-decoration: none; font-family: var(--font-mono); }
.edit-head-url a:hover { text-decoration: underline; }
.edit-head-url-none { color: var(--text-3); }

.conn-tools { display: grid; gap: 2px; margin-top: 10px; }
.conn-tool-row { display: flex; align-items: flex-start; gap: 10px; padding: 8px 10px; border-radius: 8px; }
.conn-tool-row:hover { background: var(--surface-2); }
.conn-tool-check { margin-top: 3px; flex-shrink: 0; accent-color: var(--accent); width: 15px; height: 15px; cursor: pointer; }
.conn-tool-details { flex: 1; min-width: 0; }
.conn-tool-details > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 6px;
}
.conn-tool-details > summary::-webkit-details-marker { display: none; }
.conn-tool-details > summary::before {
  content: "▸"; color: var(--text-3); font-size: 10px; flex-shrink: 0; transition: transform .12s;
}
.conn-tool-details[open] > summary::before { transform: rotate(90deg); }
.conn-tool-name { font-size: 12.5px; font-weight: 600; color: var(--text); font-family: var(--font-mono); }
/* Tools with no description: no caret — pad to line up with the ones that have one. */
.conn-tool-name-flat { flex: 1; padding-left: 16px; }
.conn-tool-desc { font-size: 12px; color: var(--text-3); line-height: 1.45; margin-top: 5px; padding-left: 16px; }

/* "+ New" catalog modal */
.conn-modal { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; }
.conn-modal.hidden { display: none; }
.conn-modal-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,.5); }
.conn-modal-panel {
  position: relative; width: min(680px, 92vw); height: min(600px, 82vh); display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: 16px;
  box-shadow: 0 24px 60px rgba(0,0,0,.4); padding: 18px 18px 16px;
}
.conn-modal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.conn-modal-title { font-size: 16px; font-weight: 700; color: var(--text); margin: 0; }
.conn-modal-close { background: none; border: none; color: var(--text-3); font-size: 16px; cursor: pointer; line-height: 1; padding: 4px; }
.conn-modal-close:hover { color: var(--text); }
.conn-modal-panel .settings-input { margin-bottom: 12px; flex-shrink: 0; }
/* Grid fills the constant-height panel + scrolls, so search results never
   resize the modal. */
.conn-modal-panel .connector-grid { flex: 1; min-height: 0; overflow-y: auto; align-content: start; }
/* A search in flight dims the current results instead of wiping them. */
.connector-grid.is-searching { opacity: .6; transition: opacity .15s; }

/* ── Required connections (app editor, installed Glyphh apps) ── */
.app-req-conn-row {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; margin-bottom: 6px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface);
}
.app-req-conn-name { font-size: 13px; color: var(--text); }
.app-req-conn-status {
  margin-left: auto; font-size: 11px; font-weight: 600;
  padding: 2px 9px; border-radius: 999px;
}
.app-req-conn-status.ok { color: #4ade80; background: rgba(74, 222, 128, .12); }
.app-req-conn-status.missing { color: #f87171; background: rgba(248, 113, 113, .12); }
.app-req-conns-warn { margin-top: 8px; font-size: 12px; line-height: 1.5; color: #f87171; }
.app-req-conns-warn a { color: var(--text); text-decoration: underline; cursor: pointer; }

/* ── Field hints in the app editor ── */
.proxy-field-hint { margin-top: 6px; font-size: 11.5px; color: var(--text-3); line-height: 1.5; }
.proxy-field-hint code {
  background: var(--surface-2); padding: 1px 6px; border-radius: 4px;
  font-size: 11px; font-family: var(--font-mono); color: var(--text); user-select: all;
}

/* ── MCP-exposing apps: approved-tools list + endpoint (app editor) ── */
.app-mcp-endpoint {
  display: block; margin: 6px 0; padding: 8px 10px; border-radius: 6px;
  background: var(--surface-2); font-family: var(--font-mono); font-size: 11.5px;
  color: var(--text); word-break: break-all; user-select: all;
}
.mcp-tool-row {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 9px 11px; margin-bottom: 6px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface);
  cursor: pointer;
}
.mcp-tool-row:hover { border-color: var(--border-3, var(--border)); }
.mcp-tool-check { margin-top: 2px; flex-shrink: 0; accent-color: var(--accent); }
.mcp-tool-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mcp-tool-name { font-family: var(--font-mono); font-size: 12.5px; font-weight: 600; color: var(--text); }
.mcp-tool-desc { font-size: 11.5px; color: var(--text-2); line-height: 1.45; }

/* Host-only (credential) config-var badge — key never reaches the sandbox. */
.config-var-hostonly {
  display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 999px;
  font-size: 10px; font-weight: 600; letter-spacing: .02em; text-transform: uppercase;
  color: #4ade80; background: rgba(74, 222, 128, .12); vertical-align: middle;
}

/* ── Code — the William agent surface (chats | agent | workbench) ───────── */
/* Full-bleed inside #help-content when active (other sections keep padding). */
#page-body:has(.help-section[data-section="code"].active) {
  padding: 0;
  overflow: hidden;
}
.help-section[data-section="code"].active {
  display: flex;
  height: 100%;
  overflow: hidden;
}
.code-root { display: flex; flex: 1; min-width: 0; min-height: 0; width: 100%; }
/* 2.5.0: no center agent column — the agent DOM parks hidden as a direct
   child of .code-root and only shows when the coding slot adopts it. */
.code-root > .code-agent { display: none; }


/* Center — agent */
.code-agent { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--bg); container-type: inline-size; container-name: agent; }
.code-agent-head {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;          /* ONE row, always — the shrink clamps below
                                 keep it fitting; no overflow clip, because
                                 the ⋮ dropdown renders INSIDE this row and
                                 a clip makes it unclickable */
  gap: 8px;
  min-height: 38px;
  padding: 4px 12px;
  border-bottom: 1px solid var(--border);
  -webkit-app-region: drag;
}
/* Icons and button clusters never shrink — the labels do. */
.code-agent-head .code-icon-btn,
.code-agent-head .code-view-toggles { flex-shrink: 0; }
.code-agent-head .code-wd-btn { flex-shrink: 1; min-width: 44px; overflow: hidden; }
.code-agent-head .code-wd-btn span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.code-agent-head .code-wd-branch { flex-shrink: 1; min-width: 0; overflow: hidden; }
.code-agent-head .code-wd-branch span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#code-session-title { flex-shrink: 1; }
.code-agent-head button,
.code-agent-head .code-wd-btn { -webkit-app-region: no-drag; }
.code-spacer { flex: 1; }

/* ── Session head (SessionHeader port): ‹ + locus + name, sticky + fades ── */
.session-head-back {
  display: inline-flex; align-items: center; gap: 7px;
  border: none; background: none; color: var(--text); cursor: pointer;
  padding: 3px 6px 3px 2px; border-radius: 7px; min-width: 0; flex-shrink: 1;
  -webkit-app-region: no-drag;
}
.session-head-back:hover { background: var(--hover); }
.session-head-back .session-head-chev { color: var(--text-3); flex-shrink: 0; }
.session-head-locus { color: var(--text-3); display: inline-flex; flex-shrink: 0; }
.session-head-back #code-session-title {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
/* A landing (no open session): the head is a plain non-interactive title —
   hide the ‹ and locus, kill the hover. */
.session-head-back.headless { pointer-events: none; padding-left: 8px; }
.session-head-back.headless .session-head-chev,
.session-head-back.headless .session-head-locus { display: none; }
/* Sticky/fade — the head sits transparent over the thread top and fades in as
   content scrolls under it. */
.code-agent-head { position: sticky; top: 0; z-index: 5; background: var(--bg); transition: box-shadow 0.2s ease, background 0.2s ease; }
.code-agent-head.scrolled { box-shadow: 0 1px 0 var(--border), 0 6px 14px -10px rgba(0,0,0,0.35); }
.session-head-rename {
  font-size: 13.5px; color: var(--text); background: var(--surface-2, var(--hover));
  border: 1px solid var(--border-2); border-radius: 6px; padding: 3px 8px; min-width: 160px;
  -webkit-app-region: no-drag;
}
.session-head-menu { min-width: 150px; }
/* Kebab items lead with an icon (SessionHeader: IcRename / IcPin / IcTrash). */
.session-head-menu .code-menu-item { display: flex; align-items: center; gap: 8px; }
.session-head-menu .code-menu-item svg { width: 15px; height: 15px; flex-shrink: 0; color: var(--text-3); }
.session-head-menu .code-menu-item.danger svg { color: var(--danger); }
.session-head-kebab { -webkit-app-region: no-drag; }
/* New-chat / landing screen: the header STAYS — the code menu (history / +
   new / session kebab / view toggles) lives in the top-right and must be
   reachable from the landing. Only the LEFT side (back / locus / title) is
   suppressed: there's no open session to name, so ‹ + locus + title would be
   meaningless. The right-side control cluster renders as normal. */
.code-agent-head.head-landing #code-session-back { display: none; }
.code-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--text-3);
  cursor: pointer;
}
.code-icon-btn { transition: background 0.12s ease, color 0.12s ease, transform 0.15s cubic-bezier(0.25, 0.9, 0.3, 1); }
.code-icon-btn:hover { background: var(--hover); color: var(--text); transform: scale(var(--icon-zoom, 1.08)); }
.code-thread {
  flex: 1;
  overflow-y: auto;
  /* Right gets +4 over left: the scrollbar rides in the right gutter and
     visually tightens it. */
  padding: 20px 52px 24px 48px;
  /* The thread is REBUILT on every live-run frame; the browser's scroll
     anchoring then latched onto an artifact card's button row and tugged the
     view back to it as text streamed (his report: "anchored to the div with
     the buttons and flickers"). Following is ours: threadPinned sets scrollTop. */
  overflow-anchor: none;
}
.code-thread-inner {
  width: 100%;
  max-width: 780px;
  min-height: 100%;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.code-msg {
  max-width: 720px;
  padding: 10px 14px;
  border-radius: 12px;
  font-size: 13.5px;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
}
.code-msg.user { align-self: flex-end; background: var(--active-bg); border: 1px solid var(--border); color: var(--text); }
/* Agent replies read as plain transcript text — no bubble, full width. */
.code-agent-text {
  align-self: stretch;
  max-width: 720px;
  padding: 2px 2px 6px;
  font-size: 13.5px;
  line-height: 1.62;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text);
}
/* Gateway-decline card (budget used up / role / rate) — replaces raw error text. */
.code-decline-wrap { align-self: stretch; max-width: 720px; }
.decline-card {
  display: flex;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--border-2);
  border-left: 3px solid var(--accent);
  border-radius: 12px;
  background: var(--surface-2);
}
.decline-card--credits { border-left-color: #ffbd2e; }
.decline-card--role { border-left-color: #ff5f56; }
.decline-card-icon {
  flex-shrink: 0;
  width: 22px; height: 22px;
  color: var(--text-3);
}
.decline-card-icon svg { width: 22px; height: 22px; }
.decline-card--credits .decline-card-icon { color: #ffbd2e; }
.decline-card-main { flex: 1; min-width: 0; }
.decline-card-title { font-size: 13.5px; font-weight: 600; color: var(--text); margin-bottom: 3px; }
.decline-card-body { font-size: 12.5px; line-height: 1.5; color: var(--text-2); }
.decline-card-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.decline-card-cta {
  padding: 6px 14px; border: none; border-radius: 8px; cursor: pointer;
  background: var(--accent); color: var(--accent-fg); font-size: 12.5px; font-weight: 500;
}
.decline-card-cta:hover { filter: brightness(1.08); }
.decline-card-alt {
  padding: 6px 14px; border: 1px solid var(--border-2); border-radius: 8px; cursor: pointer;
  background: none; color: var(--text-2); font-size: 12.5px;
}
.decline-card-alt:hover { border-color: var(--border-3); color: var(--text); }

/* "+N -M" diff badge on edit breadcrumbs. */
.code-diff-badge { font-family: var(--font-mono, ui-monospace, monospace); font-size: 11px; }
.code-diff-badge .diff-add { color: #3fb950; }
.code-diff-badge .diff-del { color: var(--danger); }

/* Markdown rhythm inside agent transcript text. */
.code-agent-text { white-space: normal; }
.code-agent-text .yo-md-p { margin: 0 0 10px; }
.code-agent-text .yo-md-p:last-child { margin-bottom: 0; }
.code-agent-text .yo-md-h1, .code-agent-text .yo-md-h2,
.code-agent-text .yo-md-h3, .code-agent-text .yo-md-h4 {
  margin: 16px 0 8px;
  color: var(--text-bright);
  line-height: 1.3;
}
.code-agent-text .yo-md-h1 { font-size: 17px; }
.code-agent-text .yo-md-h2 { font-size: 15.5px; }
.code-agent-text .yo-md-h3 { font-size: 14px; }
.code-agent-text .yo-md-h4 { font-size: 13.5px; }
.code-agent-text .yo-md-ul, .code-agent-text .yo-md-ol { margin: 4px 0 10px; padding-left: 22px; }
.code-agent-text .yo-md-ul li, .code-agent-text .yo-md-ol li { margin: 3px 0; }
.code-agent-text .yo-md-codeblock { margin: 10px 0; }
.code-agent-text .yo-md-pre { overflow-x: auto; }

/* File card — a written file the workbench can open (Monaco tab). */
.code-file-card, .code-run-card {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 640px;
  margin: 2px 0;
  padding: 6px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 12px;
  color: var(--text-2);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.12s ease, color 0.12s ease;
}
.code-file-card:hover, .code-run-card:hover { border-color: var(--text-3); color: var(--text); }
.code-file-card svg, .code-run-card svg { flex: 0 0 auto; opacity: 0.75; }
.code-file-card .cfc-name { font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; color: var(--text); }
.code-file-card .cfc-dir {
  font-size: 10.5px;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 260px;
}
.code-run-card .crc-cmd {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 11.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.code-run-card.failed { border-color: rgba(248, 81, 73, 0.4); }
.code-run-card.failed .crc-cmd { color: var(--danger); }

/* Composer attachments — chips queue above the input and ride the send. */
.code-attach-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 10px 0;
}
/* Same [hidden] override as the pending-notes dock — keep the empty chip row
   from reserving padding above the input. */
.code-attach-chips[hidden] { display: none; }
.code-attach-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 240px;
  padding: 4px 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 7px;
  font-size: 11.5px;
  color: var(--text-2);
}
.code-attach-chip img {
  width: 26px;
  height: 26px;
  object-fit: cover;
  border-radius: 4px;
  display: block;
}
.code-attach-chip .cac-ic { display: inline-flex; opacity: 0.75; }
.code-attach-chip .cac-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 11px;
}
.code-attach-chip .cac-x {
  border: none;
  background: none;
  color: var(--text-3);
  font-size: 13px;
  line-height: 1;
  padding: 0 0 0 2px;
  cursor: pointer;
}
.code-attach-chip .cac-x:hover { color: var(--text); }

/* Image attachments in the thread render as previews (2026-09-20). */
.code-attach-preview {
  margin: 0; display: inline-flex; flex-direction: column; gap: 4px; max-width: 100%;
}
.code-attach-preview img {
  display: block; max-width: min(360px, 100%); max-height: 240px; width: auto; height: auto;
  border-radius: 10px; border: 1px solid var(--border); background: var(--surface); cursor: zoom-in;
}
.code-attach-preview figcaption {
  font-family: var(--font-mono, ui-monospace, monospace); font-size: 11px; color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 360px;
}
.code-attach-chip img { cursor: zoom-in; }

/* The lightbox: a clicked image on a dark backdrop, × top-right, zoom bar below. */
.code-lightbox { position: fixed; inset: 0; z-index: 100000; background: rgba(0, 0, 0, 0.86); display: flex; flex-direction: column; }
.code-lightbox.hidden { display: none; }
.code-lightbox-stage { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; overflow: hidden; cursor: zoom-out; }
.code-lightbox-stage.zoomed { cursor: grab; }
.code-lightbox-img { max-width: 92vw; max-height: 84vh; object-fit: contain; border-radius: 8px; box-shadow: 0 20px 60px rgba(0,0,0,.6); transform-origin: center center; transition: transform .08s ease-out; will-change: transform; cursor: default; }
.code-lightbox-stage.zoomed .code-lightbox-img { cursor: grab; }
.code-lightbox-x {
  position: absolute; top: 14px; right: 18px; width: 36px; height: 36px; border: 1px solid rgba(255,255,255,.18); border-radius: 50%;
  background: rgba(20,20,22,.7); color: #fff; font-size: 24px; line-height: 1; cursor: pointer;
}
.code-lightbox-x:hover { background: rgba(255,255,255,.14); }
.code-lightbox-bar {
  display: flex; align-items: center; justify-content: center; gap: 8px; padding: 10px 16px 16px; color: rgba(255,255,255,.75); font-size: 12px;
}
.code-lightbox-btn { min-width: 30px; height: 28px; padding: 0 10px; border: 1px solid rgba(255,255,255,.18); border-radius: 8px; background: rgba(20,20,22,.7); color: #fff; font-size: 14px; cursor: pointer; }
.code-lightbox-btn:hover { background: rgba(255,255,255,.14); }
.code-lightbox-pct { min-width: 44px; text-align: center; font-variant-numeric: tabular-nums; }
.code-lightbox-name { margin-left: 12px; font-family: var(--font-mono, ui-monospace, monospace); font-size: 11px; color: rgba(255,255,255,.55); max-width: 40vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The + chip (right of the mode chip) — the "add to this session" menu. */
/* Higher specificity (.code-chip.code-plus-chip) so these WIN over the base
   .code-chip rule defined later in the file — otherwise its pill border /
   radius / padding override everything and the + reads as a bordered chip. */
/* Voice mic chip — matches the + chip, with recording / transcribing states. */
.code-chip.code-mic-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 6px;
}
.code-chip.code-mic-chip.recording {
  color: #fff;
  background: var(--danger, #ef4444);
  animation: code-mic-pulse 1.2s ease-in-out infinite;
}
.code-chip.code-mic-chip.transcribing { opacity: 0.55; }
/* The caret that opens the mic device/mode drop-up — a slim sibling of the chip. */
.code-chip.code-mic-caret {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
  margin-left: -2px;
  color: var(--text-3);
}
.code-chip.code-mic-caret:hover { color: var(--text); }
@keyframes code-mic-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.5); } 50% { box-shadow: 0 0 0 5px rgba(239, 68, 68, 0); } }
/* The caret that opens the mic device/mode drop-up — a slim sibling of the chip. */
/* Mic drop-up extras: a divider + the "Hold to record" toggle row. */
.code-drop-sep { height: 1px; background: var(--border-2); margin: 6px 0; }
.code-drop-item.code-drop-toggle { justify-content: space-between; gap: 10px; }
.code-drop-switch {
  position: relative;
  width: 34px;
  min-width: 34px;
  height: 19px;
  border-radius: 10px;
  background: var(--border-3);
  transition: background 0.2s;
  flex-shrink: 0;
}
.code-drop-switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--text-3);
  transition: transform 0.2s, background 0.2s;
}
.code-drop-switch.on { background: var(--accent); }
.code-drop-switch.on::after { transform: translateX(15px); background: var(--white); }
/* "Stop" chip shown while the agent speaks a reply — gentle pulse, click/Esc to halt. */
.code-chip.code-speak-stop {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 0 9px;
  color: #fff;
  background: var(--danger, #ef4444);
  animation: code-mic-pulse 1.4s ease-in-out infinite;
}
.code-chip.code-speak-stop:hover { filter: brightness(1.08); }
/* Live mic waveform — a transparent canvas laid over the composer input while
   recording voice. Pointer-transparent so the field stays usable; the bars are
   drawn in the accent colour from the real mic level (voice-mic.ts). */
.code-rec-wave {
  position: absolute;
  left: 14px;
  right: 44px;
  top: 50%;
  transform: translateY(-50%);
  height: 24px;
  pointer-events: none;
  z-index: 3;
  opacity: 0.9;
}
.code-rec-wave.hidden { display: none; }
/* While recording, clear the placeholder so the waveform has a clean field. */
.code-input-wrap.code-recording .code-input::placeholder { color: transparent; }
/* Mic capture error (permission denied / unsupported) — a brief red flash on the
   chip so a blocked mic never reads as "the button does nothing". */
.code-chip.code-mic-chip.mic-error {
  color: #fff;
  background: var(--danger, #ef4444);
  animation: mic-error-flash 0.9s ease-in-out 0s 3;
}
@keyframes mic-error-flash { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }

.code-chip.code-plus-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 4px;
  border: none;
  border-radius: 0;
  background: none;
  color: var(--text-2);
  font-size: 16px;
  font-weight: 400;
  line-height: 1;
}
.code-chip.code-plus-chip:hover { color: var(--text); border: none; }

/* Drag-over target state for the whole composer. */
.code-composer.dropping { outline: 1px dashed var(--text-3); outline-offset: -6px; border-radius: 12px; }

/* Sent attachments under the user pill — same right alignment, no remove. */
.code-msg-atts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
  margin: 4px 0 2px;
}
.code-msg-atts .code-attach-chip { cursor: default; }

.code-composer {
  width: 100%;
  /* Mirror the thread EXACTLY: 780px content + 44px gutters = 868px. The
     gutters never collapse (so the input keeps its padding when the pane is
     narrow), and the 780px content lines up with the thread above. */
  max-width: 880px;   /* 780px content + 48/52px gutters — matches the thread */
  margin: 0 auto;
  padding: 4px 52px 26px 48px;
  box-sizing: border-box;
}
.code-input-wrap { position: relative; display: flex; }
.code-input {
  flex: 1;
  resize: none;
  min-height: 40px;
  max-height: 220px;
  /* Text insets: normal on the left (the attach icon that once lived there
     is gone), 44px on the right to clear the in-input send button. */
  padding: 10px 44px 10px 14px;
  border: 1px solid var(--border-2);
  border-radius: 12px;
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 13.5px;
  line-height: 1.5;
  outline: none;
}
.code-input:focus { border-color: var(--accent); }

/* Right — the workbench rails (ported old-workbench engine). The aside sizes
   to its rails; each rail carries its own width (drag its right edge). */
.code-workbench {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  overflow: hidden;
}
.code-workbench .ws-right-rails { height: 100%; }

/* Shared empty state */
.code-empty {
  margin: auto;
  padding: 24px;
  max-width: 420px;
  text-align: center;
  color: var(--text-3);
  font-size: 13px;
  line-height: 1.6;
}

/* In-input send — return icon normally, stop icon while thinking. */
.code-send {
  position: absolute;
  right: 7px;
  bottom: 7px;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 7px;
  background: none;
  color: var(--text-3);
  cursor: pointer;
  padding: 0;
}
.code-send:hover { color: var(--accent); background: var(--hover); }
.code-send .icon-stop { display: none; }
.code-send.thinking .icon-return { display: none; }
.code-send.thinking .icon-stop { display: block; }


/* Workdir controls (old workbench header, adapted) */
.code-wd-btn,
.code-wd-branch {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  color: var(--text-2);
  font-size: 12.5px;
  white-space: nowrap;
  cursor: pointer;
}
.code-wd-btn:hover { background: var(--hover); color: var(--text); }
.code-wd-btn svg,
.code-wd-branch svg { width: 13px; height: 13px; flex-shrink: 0; }
.code-wd-btn span,
.code-wd-branch span { max-width: 180px; overflow: hidden; text-overflow: ellipsis; }
.code-wd-branch { color: var(--text-3); font-family: var(--font-mono); font-size: 12px; cursor: default; }

/* Workbench view toggles (old wb-section-toggles, adapted) */
.code-view-toggles { display: flex; align-items: center; gap: 2px; }
.code-view-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  padding: 0;
}
.code-view-btn:hover { background: var(--hover); color: var(--text); }
.code-view-btn.active { color: var(--white); }
.code-view-btn svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }


/* Maximize floods the section: the docked/home agent column collapses, rails
   take the width. Scope to the `.code-root` position ONLY — the OVERLAY agent
   (following a maximized coding seat) must stay visible; it hides on its own
   when a non-coding panel maximizes (its placeholder goes offscreen). */
body.wb-max .code-root > .code-agent,
body.wb-max .code-wb-edge { display: none; }
body.wb-max .code-workbench { flex: 1; }
body.wb-max .ws-right-rails { width: 100%; }

/* Whole-workbench edge drag handle — absolutely positioned over the aside's
   left border so it adds no layout width (the border IS the divider). */
.code-workbench { position: relative; }
.code-wb-edge {
  position: absolute;
  left: -2px;
  top: 0;
  bottom: 0;
  width: 5px;
  z-index: 5;
  cursor: col-resize;
  background: transparent;
}
.code-wb-edge:hover,
.code-wb-edge.dragging { background: var(--border-2); }


/* Full-bleed chrome — the home panel covers the titlebar strip. */
#panel-wc {
  position: fixed;
  top: 0;
  left: 0;
  height: 30px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding-left: 14px;
  /* ABOVE the drag strip (z 380 since the workspace-bar fix, 2026-08-20) —
     at 300 the blurred strip painted over the traffic lights and ate them. */
  z-index: 390;
}
#panel-wc,
#panel-wc * { -webkit-app-region: no-drag; }
/* (No brand mark in the cluster anymore — traffic lights + the wall button.) */
#panel-wc .code-icon-btn { width: 26px; height: 26px; }
.app-rail-top {
  flex: 0 0 38px;
  height: 38px;
  /* Drag surface for the gap right of the chrome cluster — starts past the
     cluster so the fixed overlay never sits on a drag region (that overlap
     is what used to eat clicks). syncDragStripOffset() measures the cluster and
     overrides this at boot; the value here is only the pre-JS fallback, sized
     for the current button count. */
  margin-left: 218px;
  -webkit-app-region: drag;
}
/* Layout tiles — mini 2x2 stack of the layout's app icons. */
.tile-layout .mini {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 3px;
  overflow: hidden;
  background: var(--surface-2);
  min-width: 0;
  min-height: 0;
}
.tile-layout .mini img {
  width: 100%; height: 100%; object-fit: contain;
  padding: 2px; box-sizing: border-box;
}
.tile-layout .tile-mini-initial { font-size: 8px; font-weight: 600; color: var(--text-3); }



/* While the full-bleed home panel is active, the base titlebar's OS drag
   claim (which bleeds through BrowserViews across the WHOLE top band) shrinks
   to a 6px sliver at the very top edge — window drag survives, and every
   control in the panel's top strip (chrome cluster, workdir, view toggles)
   gets its clicks back. */
body.fullbleed-active #titlebar > * { display: none; }
body.fullbleed-active #titlebar { height: 6px; min-height: 6px; }

/* Ghost empty state — Glyphh mark + rotating Lovelace-spirited quotes. */
.code-ghost {
  margin: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 24px;
  transform: translateY(26px);   /* sit a touch below dead-center */
}
.code-ghost-mark {
  width: 88px;
  height: 88px;
  opacity: 0.82;
  user-select: none;
  -webkit-user-drag: none;
  margin-bottom: 8px;
  color: var(--accent);
}
/* The mascot is now inline SVG — size the svg child to fill the square box. */
.code-ghost-mark img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  -webkit-user-drag: none;
}
.code-ghost-mark svg {
  width: 100%;
  height: 100%;
  display: block;
}
/* TITLE — mirrors the home hero's greeting (.dash-greeting): title font. */
.code-ghost-title {
  font-family: var(--font-sans);
  font-size: 34px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
  text-align: center;
  margin: 0;
}
/* SAYING — the rotating slogan, in the secondary font (.dash-subtitle). */
.code-ghost-quote {
  max-width: 440px;
  text-align: center;
  font-size: 15px;
  color: var(--text-2);
  line-height: 1.65;
  transition: opacity 0.5s ease;
}



/* Slim the leading drop strip inside the rails (between-rail strips keep
   their drop-target width). */
#code-wb-rails > .ws-rail-dropstrip:first-child { width: 2px; flex-basis: 2px; }



/* ── Glyphh spinner — tumbling wireframe cube + typed working phrase ────── */
/* App-level loading overlay — the standard spinner over the entire app,
   blocking interaction (e.g. verifying a Pipedream connection after the
   OAuth window closes). Shown/hidden by app-overlay.ts. */
.app-overlay {
  position: fixed;
  inset: 0;
  z-index: 100000;
  display: none;
  flex-direction: column; /* mascot stacked above the spinner */
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--bg) 78%, transparent);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
.app-overlay.visible { display: flex; }

.glyphh-spinner {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  /* The cube + particles draw with this color — white on dark themes,
     near-black on light. Override to retheme the cube. */
  color: var(--text-bright);
}
.gs-cube { display: block; flex-shrink: 0; }
.gs-phrase {
  font-size: 12.5px;
  color: var(--text-2);
  min-width: 180px;
  min-height: 1em;
}
.gs-meta {
  font-size: 12.5px;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.gs-phrase.typing::after {
  content: "\258d";
  margin-left: 1px;
  color: var(--accent);
  animation: gs-caret 0.7s step-end infinite;
}
@keyframes gs-caret { 50% { opacity: 0; } }

/* Spinner row in the Code thread — no bubble chrome, just the spinner. */
.code-working {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 4px 0;
}

/* ── Composer bar — permission mode + effort chips ──────────────────────── */
.code-composer-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  /* ONE row, always: chips are popup buttons — their labels ellipsize down
     to slivers before the row may wrap or spill. No overflow clip: the mode/
     model/effort menus render inside their chipwraps and must escape. */
  flex-wrap: nowrap;
  margin-top: 7px;
  padding: 0 4px;
}
.code-chipwrap { position: relative; min-width: 0; }
/* A CHIP NEVER GROWS PAST ITS OWN SLOT (his report + screenshot, 2026-08-28:
   a two-seat model label — "First seat: … / Second seat: …" — ran straight
   over the Loop chip and the send spinner, and shoved the mic out of place).
   The chip is not the flex item; its wrap is. The wrap could shrink, but the
   chip inside kept its content width and simply OVERFLOWED, so the ellipsis
   the max-width rules promised never kicked in. Bounding the chip to its wrap
   makes it collapse in place instead of pushing its neighbours. */
.code-chipwrap > .code-chip { max-width: 100%; }
/* Text chips give way; ICONS never do — the mic, the +, the meter and the
   speak-stop keep their size and their seat no matter how long a label gets. */
#code-model-wrap, #code-level-wrap, #code-mode-wrap { flex: 0 1 auto; }
#code-mic-wrap, #code-speak-wrap, #code-plus-wrap, #code-ctx-wrap { flex: 0 0 auto; }
.code-bar-left { display: flex; align-items: center; flex-wrap: nowrap; gap: 8px; min-width: 0; }
.code-bar-right { display: flex; align-items: center; flex-wrap: nowrap; gap: 10px; min-width: 0; }

/* Compaction meter — fills toward the fold tick (compaction point). */
.code-ctx-meter {
  position: relative;
  width: 16px; height: 16px;
  border-radius: 50%;
  cursor: pointer;
  --ctx-color: var(--accent);
  background:
    radial-gradient(closest-side, var(--surface-2) 60%, transparent 61% 100%),
    conic-gradient(var(--ctx-color) var(--ctx-pct, 0%), var(--border) 0);
}
.code-ctx-meter.hot { --ctx-color: var(--danger, #ef4444); }
.code-ctx-meter .ctx-tick, .code-ctx-meter .ctx-fill { display: none; }
.code-ctx-meter .ctx-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0%;
  border-radius: 3px;
  background: var(--text-3);
  transition: width 0.4s ease;
}
.code-ctx-meter .ctx-fill.hot { background: var(--accent); box-shadow: 0 0 6px rgba(175, 95, 255, 0.5); }
.code-ctx-meter .ctx-tick {
  position: absolute;
  top: -2px;
  bottom: -2px;
  left: 60%;
  width: 1.5px;
  background: var(--text-faint);
}

/* Compaction panel — one row per model lane, distance to fold. The meter is
   the rightmost trigger; anchor right but pull the panel WELL left of it.
   Compound selector on purpose: the .code-drop-up base rule (left:0,
   min-width:190px) sits later in this file and silently won the cascade at
   equal specificity — this must outrank it, not out-position it. */
.code-drop-up.code-ctx-pop {
  left: auto;
  right: 20px;
  min-width: min(320px, 92cqi);
  max-width: min(360px, 92cqi);
  padding: 16px 18px 17px;
}
.ctx-lane { margin-top: 10px; }
.ctx-lane-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.ctx-lane-name { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; color: var(--text-2); }
.ctx-lane-kind {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-3);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 5px;
}
.ctx-lane-bar { position: relative; height: 4px; border-radius: 2px; background: var(--border); margin-top: 5px; overflow: visible; }
.ctx-lane-fill { position: absolute; inset: 0 auto 0 0; width: 0%; border-radius: 2px; background: var(--text-3); }
.ctx-lane-fill.hot { background: var(--accent); box-shadow: 0 0 6px rgba(175, 95, 255, 0.5); }
.ctx-lane-tick { position: absolute; top: -2px; bottom: -2px; width: 1.5px; background: var(--text-faint); }
.ctx-lane-stats { margin-top: 4px; font-size: 10.5px; color: var(--text-3); }
.ctx-pop-empty { font-size: 11px; color: var(--text-3); }
.ctx-compact-row { display: flex; gap: 6px; margin-top: 12px; }
.ctx-compact-row input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 5px 8px;
  font-size: 11px;
  color: var(--text);
  outline: none;
}
.ctx-compact-row input:focus { border-color: var(--accent); }
.ctx-compact-btn {
  flex: 0 0 auto;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-2);
  border-radius: 7px;
  padding: 5px 10px;
  font-size: 11px;
  cursor: pointer;
  white-space: nowrap;
}
.ctx-compact-btn:hover:not(:disabled) { border-color: var(--text-3); color: var(--text); }
.ctx-compact-btn:disabled { opacity: 0.5; cursor: default; }

/* Drop-UP panels anchored to the chips */
.code-drop-up {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0;
  min-width: 190px;
  /* Never wider than the PANEL: 92cqi is 92% of the agent container's inline
     size, so in a narrow layout panel the menu shrinks with it instead of
     overrunning the edge. JS (openChipDropUp) clamps the anchored position;
     this caps the box itself. min-width above still wins on roomy panels. */
  max-width: min(360px, 92cqi);
  max-height: 60vh;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  padding: 5px;
  z-index: 60;
}
.code-drop-up.hidden { display: none; }
/* (the drop-ups are centred over the chat input at open time — see
   centerDropOverInput; no side-anchored defaults to fight it) */

/* A chip's ⓘ opens its detail IN THIS POPUP: the list hides, the detail
   takes its place behind a back arrow. */
.drop-pane.hidden { display: none; }
.drop-detail { padding: 2px 4px 6px; max-width: 420px; }
.drop-detail-head {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 2px 8px; border-bottom: 1px solid var(--border);
  margin-bottom: 8px;
}
.drop-detail-back {
  display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex: none; padding: 0;
  border: none; border-radius: 6px; background: none;
  color: var(--text-2); cursor: pointer;
}
.drop-detail-back:hover { background: var(--hover); color: var(--text); }
.drop-detail-back svg { width: 14px; height: 14px; }
.drop-detail-title { font-size: 13px; font-weight: 600; color: var(--text); }
.drop-detail-body {
  font-size: 12.5px; line-height: 1.5; color: var(--text-2);
  white-space: pre-wrap; padding: 0 2px;
}
.code-drop-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  border: none;
  background: none;
  color: var(--text-2);
  font-size: 12.5px;
  padding: 7px 10px;
  border-radius: 7px;
  cursor: pointer;
  text-align: left;
}
.code-drop-item:hover { background: var(--hover); color: var(--text); }
.code-drop-item.selected { color: var(--text); }
.code-drop-item .drop-check { color: var(--white); flex-shrink: 0; }

/* Mode menu — two-line items (label + one-line description) with a header
   row whose ⓘ opens the full permission-modes explainer. */
#code-mode-menu { width: min(264px, 92cqi); }
.code-drop-item .drop-lines { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.code-drop-item .drop-hint { font-size: 11px; color: var(--text-3); line-height: 1.35; white-space: normal; }
.code-drop-item:hover .drop-hint { color: var(--text-2); }
.code-drop-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 5px 10px 7px; margin-bottom: 3px;
  border-bottom: 1px solid var(--border);
  font-size: 11px; font-weight: 600; color: var(--text-3);
  text-transform: uppercase; letter-spacing: 0.04em;
}
.drop-info-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border: 1px solid var(--border-3); border-radius: 50%;
  background: none; color: var(--text-3); font-size: 10px; font-style: italic;
  font-family: Georgia, serif; line-height: 1; cursor: pointer;
}
.drop-info-btn:hover { color: var(--text); border-color: var(--text-3); }

/* ── Workspace-source chip (RuntimeLocationChip port) ─────────────────────
   Sits above the composer in every space; a drop-up picks cloud/local source.
   In Chat it is inert (.cl-chip-static) and just states "Cloud". */
.code-source-slot { padding: 0 4px; margin-bottom: 6px; }
.cl-runtime-chip-wrap { position: relative; display: inline-flex; }
/* Compact: this chip sits in a row with the folder and repo chips, so it earns
   only the space its label needs. */
.cl-runtime-chip {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--border); background: var(--surface-2, var(--hover));
  color: var(--text-2); font-size: 11.5px; padding: 3px 8px; border-radius: 999px;
  cursor: pointer; max-width: 100%; min-width: 0; line-height: 1.5;
}
.cl-runtime-chip .ws-chev { width: 11px; height: 11px; opacity: 0.7; }

/* The whole chip row is one compact scale — folder, repo and + match the
   source chip rather than each carrying their own padding. */
.dash-wd-chips .code-wd-btn, .code-source-slot .code-wd-btn {
  font-size: 11.5px; padding: 3px 8px; gap: 5px; border-radius: 999px; line-height: 1.5;
}
.dash-wd-chips .code-icon-btn, .code-source-slot .code-icon-btn {
  width: 25px; height: 25px; border-radius: 999px;
}
.dash-wd-chips .code-wd-btn svg, .code-source-slot .code-wd-btn svg { width: 13px; height: 13px; }
/* Search pinned to the bottom of a flex drop, list scrolling above it. */
.ws-drop-flex .repo-drop-search, .ws-drop-flex .ws-fs-search { margin: 0 0 6px; flex: 0 0 auto; }
.cl-runtime-chip:hover { border-color: var(--border-2); color: var(--text); }
.cl-runtime-lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.cl-runtime-dot {
  width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0;
  background: var(--text-faint);
}
.cl-runtime-dot[data-live] { background: var(--accent); box-shadow: 0 0 5px rgba(175, 95, 255, 0.5); }
.cl-runtime-chip .ws-chev { flex-shrink: 0; opacity: 0.7; }

/* The drop-up opens UP from the chip (matches code-drop-up mechanics). */
.ws-source-drop {
  bottom: calc(100% + 8px); top: auto;
  /* Cap to the panel (92cqi) as well as the viewport, so the source/folder/git
     picker stays inside a narrow layout panel instead of overrunning it. */
  width: min(300px, 92cqi); max-width: min(84vw, 92cqi);
  max-height: 60vh; overflow-y: auto;
}
/* Section headers inside the chip drops ("Cloud runtime", "Connected
   machines"). They were the same grey as the row subtitles and read as just
   more list text — brighter and heavier so they land as headers. */
.ws-sec-label {
  font-size: 10.5px; font-weight: 700; color: var(--text);
  text-transform: uppercase; letter-spacing: 0.06em;
  padding: 10px 10px 4px;
}
.code-drop-up .code-drop-head { font-weight: 700; color: var(--text); }
.ws-drill .ws-chev { opacity: 0.6; }
.ws-source-drop .ws-main { color: inherit; }
.ws-install { opacity: 0.95; }
/* An unreachable source: still listed (so the user knows it exists) but not
   selectable, and its subtitle says why rather than describing what it does. */
.code-drop-item.ws-unreachable { opacity: 0.45; cursor: not-allowed; }
.code-drop-item.ws-unreachable:hover { background: transparent; }
/* The chip when its own source is down — the live dot stops claiming a
   connection that isn't there. */
.cl-runtime-chip.cl-runtime-down { opacity: 0.6; }
.cl-runtime-chip.cl-runtime-down .cl-runtime-dot { background: var(--text-3); box-shadow: none; animation: none; }
/* CONNECTING — the dot pulses while the source is being reached. */
.cl-runtime-chip.cl-runtime-connecting .cl-runtime-dot {
  background: var(--accent); box-shadow: none; animation: cl-runtime-pulse 1s ease-in-out infinite;
}
@keyframes cl-runtime-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
/* CONNECTED — a green dot beside the source's name. */
.cl-runtime-chip.cl-runtime-live .cl-runtime-dot { background: #22c55e; box-shadow: 0 0 0 2px color-mix(in srgb, #22c55e 22%, transparent); }
@media (prefers-reduced-motion: reduce) {
  .cl-runtime-chip.cl-runtime-connecting .cl-runtime-dot { animation: none; opacity: 0.7; }
}
/* FAILED — the chip reads as a problem, not as a live connection. */
.cl-runtime-chip.cl-runtime-down { color: var(--danger, #ef4444); opacity: 0.9; }
.cl-runtime-chip.cl-runtime-down .cl-runtime-dot { background: var(--danger, #ef4444); }
.code-repo-drop-list { max-height: 260px; overflow-y: auto; }
.ws-fs-list { max-height: 220px; }
.ws-path {
  font-size: 11px; color: var(--text-3); padding: 4px 10px 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ws-fs-row { gap: 9px; }
.ws-fs-up { color: var(--text-3); }
.ws-gitdot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex-shrink: 0;
}
.ws-use-folder { width: calc(100% - 20px); margin: 8px 10px 4px; }
.ws-note { padding: 10px; }
.ws-note-title { font-size: 12.5px; font-weight: 600; color: var(--text); margin-bottom: 3px; }
.ws-note-body { font-size: 11.5px; color: var(--text-3); line-height: 1.45; }
.ws-source-drop .drop-empty { font-size: 12px; color: var(--text-3); padding: 8px 10px; }

/* ── Code HOME (CodeLanding port) — greeting + two-column, composer stays at
   the bottom of .code-agent. Rendered into #code-thread's inner. ─────────── */
/* The landing goes full-bleed (bypasses the thread's 780px reading cap) so the
   rise backdrop fills the space; the body keeps its own centered max-width. */
/* The Code landing's HeroFlow backdrop (rise) — behind the body, click-through. */
.cl-body { position: relative; z-index: 1; max-width: 860px; margin: 0 auto; padding: 24px 20px 8px; width: 100%; }
.cl-head { display: flex; align-items: center; gap: 12px; margin-bottom: 26px; }
.cl-mark { width: 34px; height: 34px; opacity: 0.95; }
.cl-greeting { font-size: 22px; font-weight: 600; color: var(--text); margin: 0; }
.cl-two-col { align-items: start; }
.cl-sessions { margin-top: 10px; }
.dash-tasks-empty { font-size: 12.5px; color: var(--text-3); padding: 10px 2px; }

/* Session cards (Code home RIGHT column + the per-space session list) —
   2-row, left-justified, locus icon leading. */
.session-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
  width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface-2, var(--hover));
  border-radius: 10px; padding: 10px 12px;
}
.session-card:hover { border-color: var(--border-2); background: var(--hover); }
.session-card-row1 { display: flex; align-items: center; gap: 8px; width: 100%; min-width: 0; }
.session-card-locus { color: var(--text-3); flex-shrink: 0; display: inline-flex; }
.session-card-title {
  font-size: 13.5px; font-weight: 550; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1;
}
.session-card-pin { font-size: 11px; flex-shrink: 0; }
.session-card-row2 { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--text-3); min-width: 0; width: 100%; }
.session-card-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--text-faint); flex-shrink: 0; }
.session-card-dot.busy { background: var(--accent); }
.session-card-dot.input { background: #f59e0b; }
.session-card-dot.ready { background: #10b981; }
.session-card-dot.err { background: #ef4444; }
.session-card-status.busy { color: var(--accent); }
.session-card-status.input { color: #f59e0b; }
.session-card-sep { opacity: 0.5; }
.session-card-snippet { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.session-card-age { margin-left: auto; flex-shrink: 0; opacity: 0.8; }

/* ── Per-space session LIST VIEW (SessionList port) ───────────────────────── */
.session-list-host { width: 100%; }
.session-list { max-width: 720px; margin: 0 auto; padding: 18px 20px 8px; width: 100%; }
.session-list-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.session-list-search {
  display: flex; align-items: center; gap: 7px; flex: 1; min-width: 0;
  border: 1px solid var(--border); background: var(--surface-2, var(--hover));
  border-radius: 8px; padding: 6px 10px; color: var(--text-3);
}
.session-list-search-input {
  flex: 1; min-width: 0; border: none; background: none; color: var(--text);
  font-size: 13px; outline: none;
}
.session-list-filterwrap { position: relative; }
.session-list-filter.on { color: var(--accent); }
.session-list-filter-menu { position: absolute; top: calc(100% + 4px); right: 0; z-index: 20; min-width: 160px; }
.session-list-new { display: inline-flex; align-items: center; gap: 5px; flex-shrink: 0; }
.session-list-scroll { display: flex; flex-direction: column; gap: 8px; }
.session-list-empty { font-size: 12.5px; color: var(--text-3); padding: 16px 2px; text-align: center; }

/* Permission-modes explainer — the one dialog that runs wider than the
   standard 420px confirm box: five modes with real paragraphs need room. */
.mode-info-box { width: min(560px, 90vw) !important; text-align: left !important; }
.mode-info-box .confirm-body { max-height: 60vh; overflow-y: auto; }
.mode-info-entry { padding: 10px 0; }
.mode-info-entry + .mode-info-entry { border-top: 1px solid var(--border); }
.mode-info-entry h4 { margin: 0 0 4px; font-size: 13px; font-weight: 600; color: var(--text-bright); }
.mode-info-entry p { margin: 0; font-size: 12.5px; color: var(--text-2); line-height: 1.55; }

.code-chip {
  border: 1px solid var(--border);
  background: none;
  color: var(--text-3);
  font-size: 11px;
  font-weight: 500;
  padding: 2.5px 11px;
  border-radius: 999px;
  cursor: pointer;
}
.code-chip:hover { color: var(--text); border-color: var(--border-3); }

/* Chips shrink as the agent narrows; the popup they open carries the full
   text, so an ellipsized (even single-character) chip stays functional. */
.code-chip { max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.code-bar-left, .code-bar-right { display: flex; align-items: center; gap: 6px; min-width: 0; }
.code-bar-left { flex-shrink: 1; }
.code-bar-right { flex-shrink: 1; }
#code-plus-wrap, #code-ctx-wrap { flex-shrink: 0; }   /* the + and the meter are icons — fixed */

/* ── Graduated tiers (container queries against the AGENT panel width) ── */
@container agent (max-width: 560px) {
  .code-chip, #code-model-chip { max-width: 92px; }
  .code-wd-btn span { max-width: 110px; }
}
@container agent (max-width: 460px) {
  /* Branch collapses to its icon; session title gives way (the history
     dropdown carries it); folder name tightens. */
  .code-wd-branch span { display: none; }
  #code-session-title { max-width: 90px; }
  .code-wd-btn span { max-width: 72px; }
  .code-chip, #code-model-chip { max-width: 64px; padding: 2.5px 8px; }
}
@container agent (max-width: 380px) {
  /* Chip-icon mode: folder is an icon chip (tooltip/popup has the path),
     the title hides entirely, chips are slivers. Icons never disappear. */
  #code-session-title { display: none; }
  .code-wd-btn span { display: none; }
  .code-chip, #code-model-chip { max-width: 40px; padding: 2.5px 6px; }
  .code-agent-head { gap: 4px; }
  .code-composer-bar { gap: 4px; }
  .code-bar-left, .code-bar-right { gap: 3px; }
}
.code-chip.mode-plan { color: #4fc3f7; border-color: rgba(79, 195, 247, 0.4); }
.code-chip.mode-acceptEdits { color: #34d399; border-color: rgba(52, 211, 153, 0.4); }
.code-chip.mode-auto { color: #ff7a70; border-color: rgba(255, 122, 112, 0.45); }

/* Ask dock — approvals + agent questions, docked just above the composer.
   One card at a time; slides up like it belongs to the input. */
.code-ask-dock {
  margin: 0 0 8px;
  padding: 12px 14px;
  border: 1px solid var(--border-2);
  border-radius: 12px;
  /* OPAQUE on purpose: the approval must never inherit the Echo Agent
     transparency or show the panel through itself. */
  background: color-mix(in srgb, var(--surface-2) 100%, transparent);
  position: relative;
  z-index: 4;   /* above the connected thread panel (2) AND the pill (3) */
  box-shadow: 0 14px 44px rgba(0, 0, 0, 0.35);
  animation: askDockIn 0.16s ease;
}
@keyframes askDockIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
.cad-head { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.cad-kind {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent);
}
.cad-kind.ask { color: var(--text-bright); }
.cad-step, .cad-count { font-size: 10.5px; color: var(--text-3); }
.cad-count { margin-left: auto; }
.cad-title { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.cad-detail {
  margin: 0 0 10px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 7px 9px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 130px;
  overflow-y: auto;
}
/* The command being approved: the tool's input, unescaped, readable in full. */
.cad-cmd { color: var(--text); max-height: 200px; }
.cad-rows { display: flex; flex-direction: column; gap: 4px; margin: 0 0 10px; }
.cad-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; font-size: 12px; }
.cad-key { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em; color: var(--text-3); flex: none; }
.cad-val { color: var(--text-2); overflow-wrap: anywhere; }
.cad-val-block { flex: 1 1 100%; margin: 2px 0 0; max-height: 120px; }
.cad-actions { display: flex; gap: 8px; justify-content: flex-end; }
.cad-options { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 9px; }
.cad-option {
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  font-size: 12.5px;
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}
.cad-option:hover { border-color: var(--text-3); background: var(--surface-3, var(--surface)); }
.cad-custom { display: flex; gap: 8px; align-items: center; }
.cad-custom input {
  flex: 1;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  font-size: 12.5px;
  outline: none;
}
.cad-custom input:focus { border-color: var(--white, #fff); }
.cad-skip {
  border: none;
  background: none;
  color: var(--text-3);
  font-size: 11.5px;
  cursor: pointer;
  padding: 4px 2px;
}
.cad-skip:hover { color: var(--text); text-decoration: underline; }
/* The gate decides on its own when the countdown runs out (approval → denied,
   ask → carried on) — say so quietly under the actions, without competing. */
.cad-timeout {
  margin-top: 8px;
  font-size: 11px;
  color: var(--text-3);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.cad-timeout[hidden] { display: none; }

/* Prompt modal textarea (skill-ask-user — restored for compact/steer) */
#skill-ask-user-answer {
  width: 100%;
  box-sizing: border-box;
  margin: 10px 0 14px;
  padding: 8px 10px;
  border: 1px solid var(--border-2);
  border-radius: 8px;
  background: var(--surface-2);
  color: var(--text);
  font-size: 12.5px;
  font-family: inherit;
  resize: vertical;
  outline: none;
}
#skill-ask-user-answer:focus { border-color: var(--accent); }

/* Meter is clickable (compact now) + pulses while folding */
.code-ctx-meter { cursor: pointer; }
.code-ctx-meter.compacting .ctx-fill {
  background: var(--accent);
  animation: ctx-compacting 1s ease-in-out infinite;
}
@keyframes ctx-compacting { 50% { opacity: 0.35; } }

/* Agent-loop breadcrumbs — compact chrome-free tool rows in the thread */
.code-tool-line {
  align-self: flex-start;
  max-width: 720px;
  font-size: 11.5px;
  font-family: "SF Mono", "Fira Code", monospace;
  color: var(--text-3);
  padding: 1px 4px;
  white-space: pre-wrap;
  word-break: break-word;
}


/* Collapsed tool-run groups — quiet summary, click to inspect */
.code-tool-group {
  align-self: flex-start;
  max-width: 720px;
  width: 100%;
}
.code-tool-summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: none;
  color: var(--text-3);
  font-size: 11.5px;
  padding: 2px 4px;
  border-radius: 6px;
  cursor: pointer;
}
.code-tool-summary:hover { color: var(--text-2); background: var(--hover); }
.code-tool-summary .tg-chev { transition: transform 0.15s ease; }
.code-tool-summary.open .tg-chev { transform: rotate(90deg); }
.code-tool-group .code-tool-line { padding-left: 14px; margin-top: 2px; }

/* The model's thinking — the same quiet summary, folded above the answer. */
.code-thinking { align-self: stretch; max-width: 720px; }
.code-thinking-body {
  margin: 2px 0 6px;
  padding: 2px 4px 2px 14px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-3);
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 240px;
  overflow: auto;
}

/* Plan rail — William run timeline strip */
.ws-plan-timeline {
  border-bottom: 1px solid var(--ws-line, var(--border));
  padding: 8px 12px;
  max-height: 180px;
  display: flex;
  flex-direction: column;
}
.ws-plan-timeline.hidden { display: none; }
.ws-plan-timeline-title {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-3);
  margin-bottom: 5px;
}
.ws-plan-timeline.running .ws-plan-timeline-title { color: var(--accent); }
.ws-plan-timeline-rows { overflow-y: auto; min-height: 0; }
.ws-plan-timeline-row {
  font-family: "SF Mono", "Fira Code", monospace;
  font-size: 11px;
  line-height: 1.6;
  color: var(--text-2);
  white-space: pre-wrap;
  word-break: break-word;
}
.ws-plan-timeline-row.failed { color: var(--text-3); }

/* Two-line model menu items: name row + usage line */
.code-drop-item.drop-item-2line {
  flex-direction: column;
  align-items: stretch;
  gap: 3px;
}
.code-drop-item .drop-main {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}
.code-drop-item .drop-sub {
  font-size: 10.5px;
  line-height: 1.45;
  color: var(--text-3);
  white-space: normal;
}
#code-model-menu {
  min-width: min(300px, 92cqi); max-width: min(340px, 92cqi);
  /* The model chip sits near the RIGHT edge — the menu grows LEFT from the
     chip's right edge instead of pushing the page wider. In a narrow panel
     the container-relative caps keep it inside the panel. */
  left: auto; right: 0;
}
/* (positioning is JS-owned at open time — up and to the left, viewport
   clamped; see openChipDropUp) */
/* A multi-slot loop names every binding on the chip ("Planner: Fable 5 / …");
   cap it so a many-slot loop cannot blow up the composer row — the title
   attribute carries the full cast. */
#code-model-chip { max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Model picker — a loop can offer many models across several slots, so the list
   scrolls while the search stays pinned. */
#code-model-menu .drop-search { padding: 2px 2px 6px; display: flex; align-items: center; gap: 6px; }
/* The X — same icon-button voice as .settings-modal-close, picker-sized. It is
   the multi-slot menu's ONLY close affordance (picks keep the form open). */
.drop-close-x {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--text-3);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.drop-close-x:hover { background: var(--active-bg); color: var(--text); }
/* Collapsible slot sections: header is the toggle, chevron rides its right edge. */
.code-drop-head.drop-head-toggle { cursor: pointer; user-select: none; }
.code-drop-head .drop-chev { margin-left: auto; flex: 0 0 auto; font-size: 10px; color: var(--text-3); }
.code-drop-head.drop-head-2line .drop-chev { position: absolute; right: 10px; top: 8px; margin-left: 0; }
.code-drop-head.drop-head-2line.drop-head-toggle { position: relative; }
.drop-search-input {
  width: 100%;
  box-sizing: border-box;
  height: 30px;
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  border-radius: 8px;
  padding: 0 10px;
  color: var(--text);
  font-size: 12.5px;
  outline: none;
}
.drop-search-input:focus { border-color: var(--accent); }
.drop-search-input::placeholder { color: var(--text-muted); }
.drop-scroll { max-height: 320px; overflow-y: auto; overscroll-behavior: contain; }
.drop-empty { padding: 10px; font-size: 12px; color: var(--text-3); text-align: center; }

/* A slot's header stacks: its name, then what the slot is FOR. The description
   is prose, so it opts out of the header's uppercase label treatment. */
.code-drop-head.drop-head-2line { flex-direction: column; align-items: flex-start; gap: 2px; }
.code-drop-head .drop-sub {
  font-size: 10.5px;
  line-height: 1.45;
  color: var(--text-3);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  white-space: normal;
}

/* Composer gate — sleeping until a working folder is chosen */
.code-input-wrap.gated { cursor: pointer; }
.code-input-wrap.gated .code-input {
  cursor: pointer;
  opacity: 0.65;
}
.code-input-wrap.gated .code-send { opacity: 0.35; pointer-events: none; }

/* While any workbench drag is live, iframes must not swallow the pointer —
   otherwise a rail-resize freezes the instant it crosses the Preview frame
   and the mouseup is never seen. */
body.wb-mouse-drag iframe { pointer-events: none !important; }
body.wb-mouse-drag webview { pointer-events: none !important; }
/* App panels are <webview>s in the overlay layer, not iframes — they'd swallow
   the drag's mousemove the instant the cursor crossed a panel (e.g. resizing a
   rail rightward, over its own webview), freezing the resize. Disable the whole
   holder during a workbench drag so events reach the document. */
body.wb-mouse-drag .ws-app-holder { pointer-events: none !important; }

/* Monaco save button — appears when the file is dirty */
.ws-monaco-save {
  border: 1px solid var(--white);
  background: none;
  color: var(--white);
  font-size: 11px;
  font-weight: 600;
  padding: 2px 11px;
  border-radius: 6px;
  cursor: pointer;
  margin-left: 6px;
}
.ws-monaco-save:hover { background: var(--hover); }
.ws-monaco-save.hidden { display: none; }

/* ── Library pages (Loops / Skills / Agents) ─────────────────────────────── */
.lib-badge {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.03em;
  background: var(--surface-3); color: var(--text-3); border: 1px solid var(--border-2);
}
.lib-badge-live { color: var(--accent); border-color: var(--accent); }
.code-textarea { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 12px; line-height: 1.5; }
.field-hint-inline { font-weight: 400; font-size: 11px; color: var(--text-3); text-transform: none; letter-spacing: 0; }
.lib-guard-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 8px; }
.lib-role-row { margin-bottom: 8px; }
.lib-skill-row { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 13px; color: var(--text-2); cursor: pointer; }
/* A real toggle switch (the Live control) — not a bare checkbox. */
.lib-switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
.lib-switch-label { font-size: 12px; color: var(--text-2); }
.lib-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.lib-switch-track {
  width: 34px; height: 19px; border-radius: 999px; background: var(--surface-3);
  border: 1px solid var(--border-2); position: relative; transition: background 0.15s, border-color 0.15s;
}
.lib-switch-thumb {
  position: absolute; top: 2px; left: 2px; width: 13px; height: 13px; border-radius: 50%;
  background: var(--text-3); transition: transform 0.15s, background 0.15s;
}
.lib-switch input:checked + .lib-switch-track { background: var(--accent); border-color: var(--accent); }
.lib-switch input:checked + .lib-switch-track .lib-switch-thumb { transform: translateX(15px); background: #fff; }
.lib-task-row {
  display: flex; align-items: center; gap: 10px; padding: 6px 10px;
  border: 1px solid var(--border); border-radius: 8px; margin-bottom: 6px; font-size: 12.5px;
}
.lib-task-name { font-weight: 600; color: var(--text); }
.lib-task-binding { color: var(--text-3); font-family: ui-monospace, Menlo, monospace; font-size: 11.5px; }
.lib-task-status { flex: 1; text-align: right; color: var(--text-3); font-size: 11px; }
.lib-task-delete { padding: 2px 8px; font-size: 11px; }
.lib-task-form { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; align-items: center; }
.lib-task-form .settings-input { flex: 1 1 120px; min-width: 100px; }

/* ── Library editors — the app-standard form on the left, the live React-Flow
   view on the right. Form fields are the same settings-label/settings-input
   system the Apps page uses; only the split shell is new. ── */
/* SPLIT editors — a form beside a live pane needs the full width; the 620px
   column comes from .app-builder-controls, not from this cap. */
#skill-editor.crud-inline-form, #task-editor.crud-inline-form, #agent-editor.crud-inline-form,
#agent-form.crud-inline-form, #ws-edit-view.crud-inline-form { max-width: none; }
/* The same horizontal rule the Apps detail draws under its header (its tab
   bar's border-bottom) — ties the two-column editors to one look. */
#skill-editor .crud-inline-header, #task-editor .crud-inline-header, #agent-editor .crud-inline-header {
  border-bottom: 1px solid var(--border);
  padding-bottom: 10px;
}

.lib-split { display: flex; gap: 0; flex: 1; min-height: 0; align-items: flex-start; }
.lib-split-form {
  width: 50%; flex-shrink: 0; min-width: 0;
  display: flex; flex-direction: column;
  overflow-y: auto; padding-right: 16px;
}
/* Same vertical rhythm as the apps builder: 20px above each label, 6px to its
   field. The first label sits snug to the top. */
.lib-split-form .settings-label { margin-top: 20px; margin-bottom: 6px; }
.lib-split-form .settings-label:first-child { margin-top: 8px; }
.lib-split-form .lib-json-row { margin: 16px 0 6px; }
.lib-split-form .settings-actions { margin-top: 24px; }
.lib-split-flow {
  /* Full WIDTH of its half, not full height: the graph doesn't grow taller
     just because the prompt on the left is long — it keeps a fixed window
     and stays pinned while the left column scrolls. */
  flex: 1; min-width: 0; height: 560px;
  position: sticky; top: 0;
  /* Borderless viewer — the graph floats on the page (no frame, no dot grid;
     the dots died with skill-flow's <Background>). */
  background: var(--surface); overflow: hidden; margin-left: 16px;
  border-radius: 10px;
}
/* The divider line still spans the row's full height. */
.lib-split > .lib-split-divider { align-self: stretch; }





/* "Create with AI" — a quiet link beside the breadcrumb, NEW pages only:
   an existing object is edited by hand, a blank one is worth delegating. */
.lib-ai-link {
  display: inline-flex; align-items: center; gap: 5px;
  margin-left: 14px; font-size: 12.5px; color: var(--text);
  cursor: pointer; text-decoration: none;
}
.lib-ai-link:hover { color: var(--text-bright); }
/* The wand carries the accent; the words stay bright and readable. */
.lib-ai-link svg { flex-shrink: 0; color: var(--accent); }

/* ── Composer "/" skill menu — anchored at the caret ── */
.slash-menu {
  position: fixed; z-index: 200; width: 340px; max-height: 320px;
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35); padding: 6px; overflow: hidden;
}
.slash-search {
  flex-shrink: 0; height: 30px; margin-bottom: 6px; padding: 0 10px;
  background: var(--surface-3); border: 1px solid var(--border-2); border-radius: 8px;
  color: var(--text); font-size: 12.5px; outline: none;
}
.slash-search:focus { border-color: var(--accent); }
.slash-list { overflow-y: auto; min-height: 0; }
.slash-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  border: none; background: none; text-align: left; cursor: pointer;
  padding: 7px 10px; border-radius: 7px; color: var(--text-2);
}
.slash-item.active { background: var(--hover); color: var(--text); }
.slash-item-slug { font-family: ui-monospace, Menlo, monospace; font-size: 12.5px; font-weight: 600; flex-shrink: 0; }
.slash-item-desc { font-size: 11.5px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.slash-empty { padding: 10px; font-size: 12px; color: var(--text-3); text-align: center; }

/* Approval card explainer — why this one interrupted auto mode. */
.cad-why { font-size: 11.5px; color: var(--text-3); margin-top: 2px; line-height: 1.45; }

/* The approval chip must be READABLE — it is the thing being decided. */
.cad-kind.warn { color: #fff; }

/* Agent cards: the model cast — one initial per bound model, stable color. */
.agent-model-cast { display: inline-flex; gap: 4px; align-items: center; margin-top: 6px; }
.agent-model-dot {
  width: 20px; height: 20px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--dot); color: #fff; font-size: 10.5px; font-weight: 700;
}
.agent-model-more { font-size: 10.5px; color: var(--text-3); }

/* ── Library READ views — what the agent built, shown as prose ── */
.lib-read { padding-top: 16px; }
.lib-read-title { font-size: 20px; font-weight: 700; color: var(--text); margin: 0 0 6px; }
.lib-read-desc { font-size: 14px; color: var(--text-2); margin: 0 0 24px; line-height: 1.55; }
.lib-read-meta { display: flex; flex-direction: column; gap: 9px; margin-bottom: 24px; }
.lib-read-row { display: flex; gap: 14px; align-items: baseline; font-size: 13px; }
.lib-read-label { display: block; font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-3); }
/* Inside a meta ROW the label is the fixed-width left column. Standalone (a
   section heading like PROGRAM) it must NOT keep the 140px flex-basis — in
   the surrounding flex COLUMN that basis becomes 140px of HEIGHT, which was
   exactly the mystery gap under every section label. */
.lib-read-row > .lib-read-label { flex: 0 0 140px; }
.lib-read > .lib-read-label, .lib-read div > .lib-read-label:only-child { margin-bottom: 8px; }
.lib-read-value { color: var(--text); min-width: 0; line-height: 1.5; }
.lib-read-when { margin: 0 0 8px; }
.lib-read-when p { margin: 6px 0 0; font-size: 13px; color: var(--text-2); line-height: 1.55; }
.lib-read .lib-divider { margin: 24px 0; }
.lib-read-code {
  background: var(--surface-2); border: 1px solid var(--border-2); border-radius: 8px;
  padding: 12px 14px; overflow-x: auto; font-family: ui-monospace, Menlo, monospace;
  font-size: 12px; line-height: 1.55; color: var(--text-2); margin-top: 6px;
}
#agent-detail.lib-read { max-width: 720px; }

/* Rendered markdown in the read views (a skill's prompt as prose). */
.lib-md-render { color: var(--text); font-size: 13px; line-height: 1.6; }
.lib-md-render > :first-child { margin-top: 0; }
.lib-md-render h1 { font-size: 18px; font-weight: 700; margin: 18px 0 8px; }
.lib-md-render h2 { font-size: 15.5px; font-weight: 700; margin: 16px 0 7px; padding-bottom: 4px; border-bottom: 1px solid var(--border); }
.lib-md-render h3 { font-size: 14px; font-weight: 600; margin: 14px 0 5px; }
.lib-md-render p { margin: 0 0 12px; }
.lib-md-render ul, .lib-md-render ol { margin: 0 0 12px; padding-left: 24px; }
.lib-md-render li { margin: 4px 0; }
.lib-md-render code { font-family: ui-monospace, Menlo, monospace; font-size: 0.88em; background: var(--surface-3); padding: 1px 5px; border-radius: 4px; }
.lib-md-render pre { background: var(--surface-2); border: 1px solid var(--border-2); border-radius: 8px; padding: 12px 14px; overflow-x: auto; margin: 0 0 14px; }
.lib-md-render pre code { background: none; padding: 0; }
.lib-md-render blockquote { margin: 0 0 12px; padding: 4px 14px; border-left: 3px solid var(--accent); color: var(--text-2); }

/* ── Library tables (Loops / Skills / Drips lists) ── */
/* Skills / Loops / Agents tables NEVER scroll sideways: fixed layout so the
   columns divide whatever width the panel has (an Echo card can be narrow),
   every cell ellipsizes, and the secondary columns drop out as it tightens.
   All three share the same 5-column shape: Name · Description · <facet> ·
   <state> · ⋯ */
#skills-list, #tasks-list, #agents-list { container-type: inline-size; }
.lib-table { width: 100%; table-layout: fixed; border-collapse: collapse; font-size: 13px; }
.lib-table th, .lib-table td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lib-table th:nth-child(1), .lib-table td:nth-child(1) { width: 26%; }
.lib-table th:nth-child(3), .lib-table td:nth-child(3) { width: 18%; }
.lib-table th:nth-child(4), .lib-table td:nth-child(4) { width: 15%; }
@container (max-width: 620px) {
  .lib-table th:nth-child(3), .lib-table td:nth-child(3) { display: none; }
  .lib-table th:nth-child(1), .lib-table td:nth-child(1) { width: 34%; }
}
@container (max-width: 430px) {
  .lib-table th:nth-child(4), .lib-table td:nth-child(4) { display: none; }
  .lib-table th:nth-child(1), .lib-table td:nth-child(1) { width: 44%; }
}
.lib-table th {
  text-align: left; padding: 8px 12px; font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-3);
  border-bottom: 1px solid var(--border);
}
.lib-table td { padding: 10px 12px; border-bottom: 1px solid var(--border); color: var(--text-2); vertical-align: middle; }
.lib-table tbody tr { cursor: pointer; }
.lib-table tbody tr:hover td { background: var(--hover); }
.lib-table .lib-table-name { font-weight: 600; color: var(--text); }
/* the description takes whatever is left (no fixed 480px column — that is
   what forced the horizontal scrollbar) */
.lib-table .lib-table-desc { max-width: none; }
.lib-table .lib-table-dim { color: var(--text-3); font-size: 12px; white-space: nowrap; }

/* Table row ⋯ menu (Edit / Delete). */
/* text-overflow:clip — the generic td ellipsis rendered a stray "." beside
   the squeezed kebab (his report, 2026-08-25). */
.lib-table .lib-row-kebab-cell { width: 40px; text-align: right; text-overflow: clip; }
/* The models-tab filter funnel: a stock action-btn beside the search; an
   active provider shows only as its name inside the button. */
.ws-filter-btn { display: inline-flex; align-items: center; gap: 6px; }
.ws-filter-btn svg { width: 14px; height: 14px; }
.ws-filter-btn #ws-models-filter-label { font-size: 12px; }
/* Members tabs breathe above their content. */
#members-tabs, #webhooks-tabs { margin-bottom: 16px; }
#members-tab-invited .crud-toolbar { margin-bottom: 14px; }
/* Tools page title row: app name left, the master toggle at the far right. */
.ws-tools-head { display: flex; align-items: center; gap: 12px; }
.ws-tools-head .settings-subheading { flex: 1; margin: 0; }
/* Tool rows: two-line description clamp; clicking the text expands. */
.ws-tool-line .set-pref-desc {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  cursor: pointer;
}
.ws-tool-line.expanded .set-pref-desc { -webkit-line-clamp: unset; }
/* The roles allow-modal is the Connections add-modal, floated over the
   platform page (the shared z 1000 only works inside the section DOM). */
.conn-modal.ws-allow-overlay { z-index: 9600; }
/* Role connections tab: vertical rhythm — the sub-tabs, blurb, toggle
   pills, toolbar and table each get room to breathe. */
.ws-tab[data-wstab="connections"] #ws-conn-tabs { margin-bottom: 14px; }
.ws-tab[data-wstab="connections"] #ws-conn-blurb { margin: 0 0 18px; }
.ws-tab[data-wstab="connections"] #ws-mcp-row { margin-bottom: 12px; }
.ws-tab[data-wstab="connections"] #ws-conn-grid { margin-top: 4px; }
/* Role connections table: 7 columns — the GENERIC .lib-table nth-child
   widths (built for 4 columns) squeezed the kebab out of view and hid the
   Description/Tools columns at narrow widths. Higher-specificity overrides
   pin every column. */
.lib-table.ws-conn-table th:nth-child(1), .lib-table.ws-conn-table td:nth-child(1) { width: 40px; }
.lib-table.ws-conn-table th:nth-child(2), .lib-table.ws-conn-table td:nth-child(2) { width: 24%; }
.lib-table.ws-conn-table th:nth-child(3), .lib-table.ws-conn-table td:nth-child(3) { width: auto; display: table-cell; }
.lib-table.ws-conn-table th:nth-child(4), .lib-table.ws-conn-table td:nth-child(4) { width: 72px; display: table-cell; }
.lib-table.ws-conn-table th:nth-child(5), .lib-table.ws-conn-table td:nth-child(5) { width: 84px; }
.lib-table .ws-conn-icon-cell { width: 40px; text-overflow: clip; }
.lib-table .ws-conn-icon-cell .ws-conn-icon { width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center; }
.lib-table .ws-conn-icon-cell .ws-conn-icon img { width: 20px; height: 20px; border-radius: 5px; }
/* Role editor models table: the toggle column hugs the right edge. */
.lib-table .ws-model-toggle-cell { width: 90px; text-align: left; text-overflow: clip; }
.ws-model-allow, .ws-model-exempt { padding: 0; border: none; background: none; display: inline-flex; }

.ak-token-modal { width: min(480px, 92vw); }
.ak-token-modal .settings-inline { margin-top: 12px; }
.ak-token-modal .settings-input { font-family: var(--mono, monospace); font-size: 12px; }
/* API keys table: label over the masked token, console-style. */
.ak-name { display: block; }
.ak-prefix { display: block; font-family: var(--mono, monospace); font-size: 11.5px; color: var(--text-3); margin-top: 2px; }
.lib-row-kebab {
  width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center;
  border: none; background: none; border-radius: 6px; color: var(--text-3); cursor: pointer;
}
.lib-row-kebab:hover { background: var(--hover); color: var(--text); }
.lib-row-menu {
  /* Above .yo-modal (9000): these tables also render inside the Settings
     modal, where 300 put the popover BEHIND the panel. */
  position: fixed; z-index: 9500; min-width: 140px; padding: 5px;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: 9px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
}
.lib-row-menu button {
  display: flex; width: 100%; align-items: center; gap: 8px;
  border: none; background: none; text-align: left; cursor: pointer;
  padding: 7px 10px; border-radius: 6px; font-size: 12.5px; color: var(--text-2);
}
.lib-row-menu button:hover { background: var(--hover); color: var(--text); }
.lib-row-menu button.danger { color: var(--danger); }
.lib-row-menu-icon { display: inline-flex; align-items: center; flex-shrink: 0; color: currentColor; }

/* Detail-page actions: bottom-LEFT of the form column, with the content. */
.lib-detail-actions { margin-top: 28px; justify-content: flex-start !important; }
.lib-identity-edit {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; margin-left: 8px; vertical-align: middle;
  border: none; border-radius: 6px; background: transparent;
  color: var(--text-3); cursor: pointer; padding: 0;
}
.lib-identity-edit:hover { background: var(--surface-3); color: var(--text); }
.lib-identity-form { display: flex; flex-direction: column; gap: 8px; margin: 0 0 24px; max-width: 560px; }
.lib-identity-form textarea { resize: vertical; min-height: 64px; }

/* The coding panel's header row is REMOVED — the agent head is its header. */
.ws-rail-slot[data-view="coding"] .ws-rail-slot-header.hidden-header { display: none; }
/* History dropdown rows: title | pin | delete. */
.wb-session-menu {
  /* WIDER but constrained (his ask, 2026-08-20) — sections + search need room. */
  min-width: 340px; max-width: min(480px, 92vw); max-height: 60vh;
  display: flex; flex-direction: column; overflow: hidden;
  z-index: 400; padding: 4px;
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}
.wb-session-row { display: flex; align-items: center; gap: 2px; border-radius: 6px; }
.wb-session-search { padding: 2px 2px 6px; }
.wb-session-search .repo-drop-search { width: 100%; box-sizing: border-box; }
.wb-session-list { overflow-y: auto; min-height: 0; }
.wb-session-menu .code-history-sec { padding: 8px 8px 4px; }
.wb-session-row:hover { background: var(--hover); }
.wb-session-row.selected .wb-session-title {
  color: color-mix(in srgb, var(--accent) 55%, var(--text));
  font-weight: 600;
}
.wb-session-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; background: none; }
/* Same chrome as the header icons (.code-icon-btn) — just sized to the row. */
.wb-session-row .code-icon-btn { flex: 0 0 auto; width: 24px; height: 24px; }
.wb-session-row .code-icon-btn svg { width: 14px; height: 14px; }
.wb-session-row .wb-session-pin.on { color: var(--accent); }
/* Delete is ALWAYS the red icon. */
.wb-session-row .wb-session-del { color: var(--danger, #e5484d); }
.wb-session-row .wb-session-del:hover { color: #f2555a; background: rgba(229, 72, 77, 0.12); }
.wb-session-empty { padding: 10px 12px; font-size: 12px; color: var(--text-3); }

#code-session-title {
  font-size: 12.5px; font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 220px; min-width: 32px; margin-right: 4px;
}

/* Built-in nav-app glyphs — inline SVG on currentColor so they render white
   on dark themes and black on light ones, wherever the tile lives. */
.nav-glyph {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%; color: var(--text);
}
.nav-glyph svg { width: 62%; height: 62%; }

/* Schedule editor + run feed on agent task rows. */
.lib-task-wrap { margin-bottom: 6px; }
.lib-task-sched {
  border: none; background: var(--surface-3); color: var(--text-2); cursor: pointer;
  font-size: 11.5px; padding: 3px 9px; border-radius: 999px; white-space: nowrap;
}
.lib-task-sched:hover { color: var(--text); background: var(--hover); }
.lib-task-run {
  border: 1px solid var(--border-2); background: none; color: var(--text-2); cursor: pointer;
  font-size: 11px; padding: 2px 9px; border-radius: 999px; white-space: nowrap;
}
.lib-task-run:hover:not(:disabled) { color: var(--text); border-color: var(--accent); }
.lib-task-run:disabled { opacity: 0.6; cursor: default; }
.lib-task-history {
  border: none; background: none; color: var(--text-3); cursor: pointer;
  font-size: 11px; text-decoration: none; padding: 2px 6px; border-radius: 6px;
}
.lib-task-history:hover { color: var(--text); background: var(--hover); }
/* ── Agents manual form — one bordered card per task binding, the schedule
   grammar inside it; guardrail-grid labels sit snug to their inputs. ── */
.agent-f-task {
  border: 1px solid var(--border); border-radius: 8px;
  padding: 10px 12px; display: flex; flex-direction: column; gap: 8px;
}
.agent-f-task .lib-task-form { margin-top: 0; }
.agent-f-task .tf-args { resize: vertical; font-family: ui-monospace, Menlo, monospace; font-size: 12px; }
.agent-f-task .tf-enabled-wrap { flex: 0 0 auto; padding: 2px 0; white-space: nowrap; }
.agent-f-task .tf-remove { flex: 0 0 auto; padding: 4px 10px; font-size: 11.5px; }
#agent-f-tasks { display: flex; flex-direction: column; gap: 8px; }
.lib-guard-grid .agent-f-gr-label { margin: 0 0 4px; font-size: 10.5px; }

.lib-sched-editor { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; width: 100%; }
.lib-sched-editor .settings-input { width: auto; min-width: 0; }
.lib-sched-editor .se-preview { font-size: 11.5px; color: var(--text-3); margin-left: 4px; flex: 1; }
.lib-run-feed { margin: 4px 0 10px 34px; display: flex; flex-direction: column; gap: 6px; }
/* One run = one collapsible row: caret + date/time left, Success/Failed on
   the far right; the header click reveals the run's output. */
.lib-run-row { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.lib-run-rowhead {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 7px 10px; background: none; border: none; cursor: pointer;
  color: var(--text-2); font-size: 12px; text-align: left; font-family: inherit;
}
.lib-run-row.running .lib-run-rowhead { cursor: default; }
.lib-run-row:not(.running) .lib-run-rowhead:hover { background: var(--hover); }
.lib-run-caret { flex-shrink: 0; color: var(--text-3); transition: transform 0.14s; }
.lib-run-row.open .lib-run-caret { transform: rotate(90deg); }
.lib-run-when { font-size: 12px; color: var(--text-2); }
.lib-run-badge { margin-left: auto; flex-shrink: 0; font-size: 11px; font-weight: 600; }
.lib-run-badge.ok { color: var(--success); }
.lib-run-badge.err { color: var(--danger); }
.lib-run-badge.running { color: var(--text-2); }
.lib-run-spin {
  flex-shrink: 0; width: 10px; height: 10px; border-radius: 50%;
  border: 2px solid var(--border-2); border-top-color: var(--accent);
  animation: lib-run-spin 0.7s linear infinite;
}
@keyframes lib-run-spin { to { transform: rotate(360deg); } }
.lib-run-detail { padding: 2px 12px 10px 29px; }
.lib-run-detail.hidden { display: none; }
.lib-run-body { font-size: 12.5px; color: var(--text-2); line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
.lib-run-row.error .lib-run-body { color: var(--danger); }

/* The agent detail's right pane: schedule + run feeds, its own scroll. */
.lib-split-side { flex: 1; min-width: 0; margin-left: 16px; padding-top: 16px; overflow-y: auto; min-height: 0; }
.lib-run-body.md p { margin: 0 0 8px; }
.lib-run-body.md ul, .lib-run-body.md ol { margin: 0 0 8px; padding-left: 20px; }
.lib-run-body.md code { font-family: ui-monospace, Menlo, monospace; font-size: 0.9em; background: var(--surface-3); padding: 1px 4px; border-radius: 4px; }
.lib-run-body.md pre { background: var(--surface-2); border: 1px solid var(--border-2); border-radius: 8px; padding: 10px 12px; overflow-x: auto; margin: 0 0 8px; }
.se-status { font-size: 11px; color: var(--text-3); }

/* ── Dashboard landing body: a balanced two-column split beneath the
   full-width starters strip — recommendations LEFT, the cross-agent tasks
   list RIGHT. ── */
.dash-two-col {
  display: grid; grid-template-columns: 1fr 1fr; gap: 28px; margin-top: 4px;
  align-items: start;
}
/* In a narrow panel the columns stack: recommendations on top, tasks beneath. */
@container dash (max-width: 780px) { .dash-two-col { grid-template-columns: 1fr; gap: 20px; } }

/* Recommended for you — prompt starters, icon on the right. */
.dash-recs { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.dash-rec {
  display: flex; align-items: center; gap: 12px; width: 100%;
  text-align: left; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 10px; padding: 12px 14px;
  color: var(--text); font-size: 13px; line-height: 1.45; font-family: inherit;
  transition: border-color 0.15s, background 0.15s;
}
.dash-rec:hover { border-color: var(--border-2); background: var(--hover); }
.dash-rec-text { flex: 1; min-width: 0; }
.dash-rec-ico { color: var(--text); flex-shrink: 0; display: inline-flex; }

/* Recent runs — every task firing across every agent; a click opens the run
   as a chat session. */
.dash-tasks-search { margin: 10px 0 10px; width: 100%; }
.dash-tasks-list { display: flex; flex-direction: column; gap: 6px; }
.dash-run-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  text-align: left; cursor: pointer; font-family: inherit;
  background: none; border: 1px solid var(--border); border-radius: 8px;
  padding: 9px 12px; font-size: 12.5px; color: var(--text-2);
  transition: border-color 0.15s, background 0.15s;
}
.dash-run-row:hover { border-color: var(--border-2); background: var(--hover); }
.dash-run-task { font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-task-agent {
  color: var(--text-3); font-size: 11px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 999px; padding: 1px 8px; white-space: nowrap; flex-shrink: 0;
}
.dash-run-when { margin-left: auto; color: var(--text-3); font-size: 11px; white-space: nowrap; }
#dash-tasks-pager .pagination-bar { margin-top: 10px; }

/* ── Coding Agent tile: the live agent DOM, reparented into a workbench slot ── */
.ws-rail-slot[data-view="coding"] .ws-rail-slot-body {
  display: flex; flex-direction: column; overflow: hidden; padding: 0;
}
/* Sized like every other slot view: flex in the column, never height:100%
   (percentage heights against flex-derived parents collapse on some paths —
   the layout-open one included). */
.ws-agent-holder > .code-agent {
  flex: 1 1 auto; min-height: 0; height: auto;
  min-width: 0; max-width: none; width: auto;
  border-right: none;
}
/* In the overlay, the home column's 44px gutters waste the width — a few px. */
.ws-agent-holder .code-thread { padding: 14px 14px; }
/* The header's session dropdown — the composer menus' surface, fixed-positioned. */
.wb-session-menu {
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  padding: 5px;
  z-index: 1000; max-height: 320px; overflow-y: auto; min-width: 240px; max-width: 360px;
}
.wb-session-menu .code-drop-item {
  display: block; width: 100%; text-align: left;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── Editor tab-strip context menu: Save all / Close all ── */
.ws-tab-ctx-menu {
  position: fixed;
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  padding: 5px;
  z-index: 1000; min-width: 150px;
}
.ws-tab-ctx-item {
  appearance: none; background: none; border: 0;
  text-align: left; cursor: pointer;
  padding: 7px 10px; border-radius: 6px;
  font-size: 12px; color: var(--text);
}
.ws-tab-ctx-item:hover { background: var(--hover); }
.ws-tab-ctx-item.checkable { position: relative; padding-left: 26px; }
.ws-tab-ctx-item.checkable.checked::before {
  content: "\2713"; position: absolute; left: 9px; color: var(--accent);
}
.ws-tab-ctx-item.danger { color: var(--danger, #e5484d); }
.ws-tab-ctx-item.danger:hover { background: color-mix(in srgb, var(--danger, #e5484d) 14%, transparent); }

/* ── Loop drop-up: search on top, two-line entries, ⓘ for the full story ── */
.loop-drop-search {
  display: block; width: calc(100% - 16px); margin: 4px 8px 6px;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); border-radius: 7px;
  font-size: 12px; padding: 5px 9px; outline: none;
}
.loop-drop-search:focus { border-color: var(--border-2); }
.loop-drop-list { max-height: 300px; overflow-y: auto; }
/* The entry is exactly two lines: the name row + ONE clamped description line. */
/* Name on line one, ONE sentence on line two — the row is never taller. */
.loop-drop-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; max-width: 100%; }
.loop-drop-item { position: relative; }

/* ── Monaco landing: the website hero's gradient, the ghost mark overlaid ── */
.ws-monaco-landing {
  /* The host is position:relative — pin to it, full pane, no flex/percentage
     height negotiation to lose. */
  position: absolute; inset: 0; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(90% 80% at 100% 0%, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 55%),
    radial-gradient(100% 90% at 0% 100%, rgba(124, 58, 237, 0.5) 0%, rgba(124, 58, 237, 0) 62%),
    linear-gradient(35deg, #a78bfa 0%, #c4a9f8 44%, #f5c1e0 100%);
}
.wsml-inner {
  display: flex; flex-direction: column; align-items: center; gap: 20px;
  padding: 28px; text-align: center;
}
.wsml-mark {
  width: 128px; height: 128px;
  opacity: 0.22; filter: grayscale(1);
  user-select: none; -webkit-user-drag: none;
}
.wsml-hint {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 11px; color: rgba(44, 39, 53, 0.65);
}

/* View-toggles overflow: a few visible, the rest behind ⋮ */
.code-view-more-wrap { position: relative; display: inline-flex; }
.code-view-more-menu {
  /* ALWAYS opens UPWARD (his rule, 2026-08-19): the source row lives at the
     top right of the composer, which itself sits at the bottom of the screen
     — a downward menu falls over the input or off the bottom edge. */
  position: absolute; bottom: calc(100% + 6px); right: 0; z-index: 200;
  min-width: 150px; padding: 4px;
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}
.code-view-more-menu .code-view-menu-item {
  /* The base .code-view-btn is a centered 28px square — undo that here or
     every row centers icon+label as a group and the icons zig-zag. */
  display: flex; align-items: center; justify-content: flex-start; gap: 9px;
  width: 100%; height: auto;
  background: none; border: none; cursor: pointer; text-align: left;
  padding: 7px 10px; border-radius: 7px;
  font-size: 12.5px; color: var(--text-2); font-family: inherit;
}
.code-view-more-menu .code-view-menu-item svg { flex: 0 0 auto; }
.code-view-more-menu .code-view-menu-item:hover { background: var(--hover); color: var(--text); }
.code-view-more-menu .code-view-menu-item.active { color: var(--accent-light); }
.code-view-more-menu .code-view-menu-item svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* ── App-detail Deploy (dev-host) tab ─────────────────────────────── */
.deploy-status { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--text); }
.deploy-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--text-3); flex-shrink: 0; }
.deploy-dot.on { background: #34d399; box-shadow: 0 0 8px rgba(52, 211, 153, 0.7); }
.deploy-dot.pending { background: #fbbf24; box-shadow: 0 0 8px rgba(251, 191, 36, 0.6); }

/* ── Composer: notes queued while a run is in flight ─────────────── */
.code-pending-notes {
  display: flex; flex-direction: column; gap: 5px;
  margin-bottom: 8px; padding: 8px 10px;
  border: 1px dashed var(--border-2); border-radius: 10px;
  background: var(--surface);
}
/* `display: flex` above outranks the UA [hidden] rule (equal specificity, later
   wins), so the empty dock stayed visible as a stray dashed box. Restore it. */
.code-pending-notes[hidden] { display: none; }
.cpn-head {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-3);
}
/* The note card: text and its × on the first line, the Interrupt control
   tucked under them on the RIGHT (his spec, 2026-08-28). */
.cpn-row { display: flex; align-items: flex-start; gap: 8px; flex-wrap: wrap; }
.cpn-actions { flex-basis: 100%; display: flex; justify-content: flex-end; }
.cpn-act {
  border: 1px solid var(--border); background: none; color: var(--text-3);
  font-size: 10.5px; font-weight: 500; padding: 2px 9px;
  border-radius: 999px; cursor: pointer;
}
.cpn-act:hover { color: var(--text); border-color: var(--border-3); }
.cpn-text {
  flex: 1; min-width: 0; font-size: 12.5px; line-height: 1.45; color: var(--text-2);
  /* Two lines, then ellipsis — the queue is a reminder, not a second thread. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.cpn-del {
  flex: none; width: 18px; height: 18px; line-height: 16px; padding: 0;
  border: none; border-radius: 5px; cursor: pointer;
  background: transparent; color: var(--text-3); font-size: 15px;
}
.cpn-del:hover { background: var(--surface-2); color: var(--danger, #f87171); }

/* ── Connection tools: the select-all header ─────────────────────── */
.conn-tools-select-all {
  display: flex; align-items: center; gap: 7px; cursor: pointer;
  margin: 8px 0 6px; font-size: 12px; color: var(--text-2); user-select: none;
}
.conn-tools-select-all input[type="checkbox"] { width: auto; margin: 0; accent-color: var(--accent); }
.conn-tools-select-all:hover { color: var(--text); }

/* ── Marketplace detail: video embed, required connections, markdown ── */
.mkt-video { position: relative; width: 100%; aspect-ratio: 16 / 9; border-radius: 12px; overflow: hidden; background: #000; }
.mkt-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.mkt-req-conns { display: flex; flex-direction: column; gap: 8px; }
.mkt-req-conn { display: flex; align-items: center; gap: 9px; padding: 8px 10px; border: 1px solid var(--border-2); border-radius: 10px; background: var(--surface); }
.mkt-req-conn-name { font-size: 13px; font-weight: 600; }
.mkt-req-conn .app-conn-status { margin-left: auto; }
/* Markdown body — headings/lists/code render, tuned to the detail column. */
.mkt-md { font-size: 13.5px; line-height: 1.65; color: var(--text-2); }
.mkt-md h1, .mkt-md h2, .mkt-md h3 { color: var(--text); margin: 16px 0 8px; line-height: 1.3; }
.mkt-md h1 { font-size: 20px; } .mkt-md h2 { font-size: 17px; } .mkt-md h3 { font-size: 15px; }
.mkt-md p { margin: 0 0 10px; }
.mkt-md ul, .mkt-md ol { margin: 0 0 10px; padding-left: 20px; }
.mkt-md li { margin: 3px 0; }
.mkt-md code { background: var(--surface-2); padding: 1px 5px; border-radius: 4px; font-family: var(--font-mono); font-size: 12px; }
.mkt-md pre { background: var(--surface-2); padding: 10px 12px; border-radius: 8px; overflow-x: auto; margin: 0 0 10px; }
.mkt-md pre code { background: none; padding: 0; }
.mkt-md a { color: var(--accent); }
/* Description-body images (markdown screenshots publishers paste into About) had
   NO clamp — they rendered at intrinsic size and filled the page (his bug). Clamp
   to the column width, keep aspect (no distortion), cap height, and make them
   expandable (tap → lightbox). */
.mkt-md img {
  max-width: 100%; height: auto; max-height: 70vh; object-fit: contain;
  display: block; margin: 12px 0; border-radius: 10px; border: 1px solid var(--border-2);
  cursor: zoom-in;
}
/* Fullscreen image viewer — tap any clamped image to see it large; tap to close. */
.mkt-lightbox {
  position: fixed; inset: 0; z-index: 9600; padding: 24px;
  background: rgba(0,0,0,.86); display: flex; align-items: center; justify-content: center;
  cursor: zoom-out;
}
.mkt-lightbox.hidden { display: none; }
.mkt-lightbox img { max-width: 94vw; max-height: 94vh; border-radius: 10px; box-shadow: 0 8px 40px rgba(0,0,0,.5); }

/* ── App-detail Connections tab: required connections + their tools ── */
.app-conns-list { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.app-conn-row { border: 1px solid var(--border-2); border-radius: 10px; overflow: hidden; background: var(--surface); }
.app-conn-head {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  padding: 10px 12px; background: none; border: none; cursor: pointer; color: var(--text); font: inherit;
}
.app-conn-head:hover { background: var(--surface-2); }
.app-conn-chev { width: 12px; color: var(--text-3); font-size: 10px; flex: none; }
.app-conn-name { font-size: 13px; font-weight: 600; }
.app-conn-status { margin-left: auto; font-size: 11px; padding: 2px 8px; border-radius: 5px; flex: none; }
.app-conn-status.ok { color: #34d399; background: rgba(52,211,153,.14); }
.app-conn-status.missing { color: var(--danger, #f87171); background: rgba(248,113,113,.12); }
.app-conn-tools { padding: 2px 12px 10px 33px; display: flex; flex-direction: column; gap: 5px; }
.app-conn-tool { display: flex; align-items: center; gap: 8px; }
.app-conn-tool-name { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-2); }
.app-conn-tool-state { margin-left: auto; font-size: 10px; padding: 1px 6px; border-radius: 4px; }
.app-conn-tool-state.allowed { color: #34d399; background: rgba(52,211,153,.12); }
.app-conn-tool-state.blocked { color: var(--danger, #f87171); background: rgba(248,113,113,.12); }
.app-conn-tool-empty { font-size: 11.5px; color: var(--text-3); }

/* Installed-app release view: the "update available" banner. */
.release-update-banner {
  display: flex; align-items: center; gap: 10px; margin-top: 12px;
  padding: 10px 12px; border-radius: 10px;
  background: rgba(175,95,255,.10); border: 1px solid var(--accent);
}
#release-update-text { flex: 1; font-size: 12.5px; color: var(--text); }

/* ── App-detail Marketplace tab: listing images ───────────────────── */
.listing-icon-row { display: flex; align-items: center; gap: 12px; margin-top: 6px; }
.listing-icon-preview {
  width: 88px; height: 88px; flex: none; display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--border-2); border-radius: 14px;
  background: var(--surface); color: var(--text-3); font-size: 11px; overflow: hidden;
}
.listing-icon-preview img { width: 100%; height: 100%; object-fit: cover; }

.listing-shots { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; margin-top: 6px; }
.listing-shot { position: relative; border: 1px solid var(--border-2); border-radius: 8px; overflow: hidden; background: var(--surface); }
.listing-shot img { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; }
.listing-shot-remove {
  position: absolute; top: 4px; right: 4px; width: 20px; height: 20px; line-height: 18px;
  border-radius: 50%; border: none; cursor: pointer; font-size: 14px;
  background: rgba(0, 0, 0, .62); color: #fff;
}
.listing-shot-remove:hover { background: var(--danger, #f87171); }

/* ── App-detail Releases tab ──────────────────────────────────────── */
.release-selected { font-size: 13px; color: var(--text); }
.release-count { font-size: 11.5px; color: var(--text-3); }
.release-list { display: flex; flex-direction: column; gap: 6px; max-height: 60vh; overflow-y: auto; }

.release-row {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 9px 11px; border: 1px solid var(--border-2); border-radius: 8px;
  background: var(--surface); color: var(--text); font: inherit;
}
.release-row:hover { border-color: var(--border-3); }
.release-row.selected { border-color: var(--accent); background: var(--surface-2); }

.release-row-head { display: flex; align-items: center; gap: 8px; }
.release-version { font-family: var(--font-mono); font-size: 12.5px; font-weight: 600; }
.release-date { margin-left: auto; font-size: 11px; color: var(--text-3); }

.release-check { flex: 0 0 14px; vertical-align: -2px; margin-right: 2px; }
.release-badge {
  font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
  padding: 1px 6px; border-radius: 4px; background: var(--surface-2); color: var(--text-3);
}
.release-badge.live { background: rgba(52, 211, 153, .16); color: #34d399; }
/* A build that never finished is the row an author is looking for. */
.release-state { font-size: 10.5px; color: var(--text-3); }
.release-state.failed { color: var(--danger, #f87171); }

.release-notes-preview { margin-top: 5px; font-size: 11.5px; color: var(--text-2); line-height: 1.45; }
.release-build-error {
  margin-top: 6px; padding: 5px 7px; border-radius: 5px;
  background: rgba(248, 113, 113, .10); color: var(--danger, #f87171);
  font-family: var(--font-mono); font-size: 10.5px; white-space: pre-wrap; word-break: break-word;
}



/* ── Models (org admin) — desktop mirror of platform Configure → Models ── */
#models-tabs { padding: 0; margin: 8px 0 20px; }
.mdl-count { color: var(--text-3); font-size: 11px; margin-left: 4px; }
.mdl-tab { display: none; }
.mdl-tab.active { display: block; }
/* .section-desc's global -16px top margin exists to tuck it under an h2 —
   inside a tab panel it drags the intro into the tab strip. Reset it. */
.mdl-tab > .section-desc { margin: 0 0 18px; }
.mdl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 8px; }
.mdl-card {
  display: flex; flex-direction: column; gap: 8px; padding: 10px 12px;
  background: var(--surface-3); border: 1px solid var(--border); border-radius: 8px;
}
.mdl-card.mdl-provider-off { opacity: 0.6; }
.mdl-card-name { font-size: 12px; font-weight: 600; color: var(--text); }
.mdl-card-sub { font-size: 11px; color: var(--text-3); margin-top: 2px; }
.mdl-chip-warn {
  align-self: flex-start; padding: 1px 7px; border-radius: 100px; cursor: pointer;
  font-size: 10px; color: #f59e0b; background: rgba(245, 158, 11, 0.10);
  border: 1px solid rgba(245, 158, 11, 0.35);
}
.mdl-toggle { margin-top: auto; }
.mdl-toggle-text { font-size: 11px; color: var(--text-2); }
/* ── Models admin (2026-08-24: ONE page — expandable provider rows with the
   models inside; modals for add/edit; open weight cut) ── */
.mdl-prov-row { border: 1px solid var(--border); border-radius: 10px; margin-top: 8px; overflow: hidden; }
.mdl-prov-head {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 14px; cursor: pointer; background: var(--surface);
  transition: background 0.15s;
}
.mdl-prov-head:hover { background: var(--surface-2); }
.mdl-prov-chevron { display: inline-flex; color: var(--text-3); transition: transform 0.15s; flex-shrink: 0; }
.mdl-prov-chevron svg { width: 13px; height: 13px; }
.mdl-prov-head.open .mdl-prov-chevron { transform: rotate(90deg); }
.mdl-prov-info { flex: 1; min-width: 0; }
.mdl-type-chip {
  margin-left: 8px; padding: 1px 8px; border-radius: 999px;
  font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;
  background: var(--surface-3); color: var(--text-3); vertical-align: 1px;
}
.mdl-type-chip.glyphh { background: var(--active-bg); color: var(--accent, #af5fff); }
.mdl-ico-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border: none; border-radius: 7px;
  background: none; color: var(--text-3); cursor: pointer; flex-shrink: 0;
  transition: background 0.15s, color 0.15s;
}
.mdl-ico-btn svg { width: 14px; height: 14px; }
.mdl-ico-btn:hover { background: var(--hover); color: var(--text); }
.mdl-ico-btn.danger:hover { color: var(--danger, #e5484d); }
.mdl-prov-models { border-top: 1px solid var(--border); background: var(--bg-raised, var(--bg)); padding: 4px 14px 8px 52px; }
.mdl-prov-models .mdl-td-name { font-size: 12.5px; font-weight: 400; }
.mdl-prov-models .mdl-td-sub { font-size: 11px; }
.mdl-model-line { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-bottom: 1px solid var(--border); }
.mdl-model-line:last-child { border-bottom: none; }
.mdl-model-info { flex: 1; min-width: 0; }
.mdl-prov-models .crud-empty { padding: 12px 0; }
.mdl-form-modal { width: min(460px, 92vw); text-align: left; }
.mdl-form-modal .yo-modal-title { font-size: 15px; font-weight: 600; margin-bottom: 4px; }
.mdl-form-modal .settings-label { margin-top: 10px; }
.mdl-form-modal .mdl-modal-check { display: flex; align-items: center; gap: 8px; text-transform: none; letter-spacing: 0; }
.mdl-form-modal .mdl-modal-check input { width: auto; margin: 0; flex: none; }
.mdl-input-clearwrap { position: relative; display: block; }
.mdl-input-clearwrap .settings-input { width: 100%; padding-right: 34px; }
.mdl-input-clear {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border: none; border-radius: 50%;
  background: none; color: var(--text-3); cursor: pointer;
}
.mdl-input-clear svg { width: 15px; height: 15px; }
.mdl-input-clear:hover { color: var(--danger, #e5484d); }

/* ── (tables kept for other admin lists) ── */
.mdl-table-wrap { overflow-x: auto; margin-top: 6px; }
.mdl-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.mdl-table th {
  text-align: left; padding: 7px 10px; font-size: 10.5px; font-weight: 600;
  color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.06em;
  border-bottom: 1px solid var(--border);
}
.mdl-table td { padding: 8px 10px; border-bottom: 1px solid var(--border); color: var(--text-2); vertical-align: middle; }
.mdl-table tr:last-child td { border-bottom: none; }
.mdl-th-right { text-align: right; }
.mdl-table td.mdl-th-right { white-space: nowrap; }
.mdl-td-name { color: var(--text); font-weight: 500; }
.mdl-td-sub { color: var(--text-3); font-size: 12px; }
.mdl-table tr.mdl-provider-off td { opacity: 0.65; }
.mdl-table .mdl-key { max-width: 260px; }
.mdl-table td.crud-empty { padding: 14px 10px; }
.mdl-table tr.mdl-row-click { cursor: pointer; }
.mdl-table tr.mdl-row-click:hover td { background: var(--hover); }

.mdl-row {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px; margin-bottom: 4px;
  background: var(--surface-3); border: 1px solid var(--border); border-radius: 8px;
}
.mdl-row-id { flex: 0 0 150px; min-width: 0; }
.mdl-row-id .mdl-card-name { font-size: 12px; }
.mdl-row-wide { flex: 1; }
.mdl-key { flex: 1; height: 30px; padding: 0 10px; font-size: 12px; }
.mdl-key-state { flex: 0 0 60px; text-align: center; font-size: 10.5px; color: var(--text-3); white-space: nowrap; }
.mdl-key-state.mdl-key-ok { color: #34d399; }
.mdl-custom-form {
  display: grid; grid-template-columns: 1fr 1fr; gap: 4px 10px; padding: 14px;
  margin-bottom: 16px; background: var(--surface-3); border: 1px solid var(--border); border-radius: 8px;
}
.mdl-custom-form .settings-label { margin: 0; }
.mdl-custom-form .settings-input { margin-top: 4px; padding: 7px 10px; font-size: 12.5px; }
.mdl-span { grid-column: 1 / -1; }
.mdl-hint { color: var(--text-3); font-weight: 400; font-size: 10.5px; text-transform: none; letter-spacing: 0; }
.mdl-form-actions { grid-column: 1 / -1; display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
.mdl-card-sub.mono { font-family: var(--font-mono, ui-monospace, monospace); font-size: 10.5px; }

/* The ghost above the cube on the app-level overlay ("Connecting…"). */
.app-overlay-mascot {
  width: 72px;
  height: 72px;
  object-fit: contain;
  margin-bottom: 14px;
  opacity: 0.92;
  animation: overlay-mascot-bob 2.6s ease-in-out infinite;
}
@keyframes overlay-mascot-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

/* LAST WORD on the model chip: its 320px ID rule above ties the container
   tiers on specificity and wins on source order — so the clamps repeat here,
   after it, where source order works for us. */
@container agent (max-width: 560px) { #code-model-chip { max-width: 92px; } }
@container agent (max-width: 460px) { #code-model-chip { max-width: 64px; } }
@container agent (max-width: 380px) { #code-model-chip { max-width: 40px; } }


/* ═══ App rail — RESTORED (was removed in the 2.5.0 shell cut; brought back
   beside the full-width workbench: nav drives the section PANELS now). ═══ */



/* ── Pending-update badge (bottom-right, all home pages) ─────────────── */
/* The update prompt moved from a floating bottom-right badge to a rail button
   (.app-rail-relaunch) — the old .update-badge* rules are gone with it. */

/* The library page wrapper (added for the My apps | Marketplace tabs) must
   pass the section's flex layout through — otherwise #app-detail's flex:1
   sits in a plain block and the editor's split pane never fills the page
   (right pane stops at its content instead of stretching). */
.help-section[data-section="apps"].active > #apps-library-page:not(.hidden) {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}


/* App rail — the persistent left rail (Home|Code, sessions, nav, user) */
#app-rail {
  width: 264px;
  min-width: 264px;
  display: flex;
  flex-direction: column;
  /* The console gives its sidebar its own ground; the themes that declare no
     --sidebar keep the surface they always had. */
  border-right: 1px solid var(--sidebar-border, var(--border));
  background: var(--sidebar, var(--surface-2));
  overflow: hidden;
  transition: width 0.16s ease, min-width 0.16s ease;
}

/* The left rail is RETIRED from the shell (2026-08-18): navigation moved onto
   the wall (the Echo dock + top bar carry Apps/Marketplace/Connections/
   Workspaces/Tasks/Agents, settings, and the account dropdown). The rail's
   DOM stays — recents/search/user wiring still renders into it — but nothing
   shows it and there is no collapse toggle anymore. */
#code-rail-splitter { display: none !important; }

#app-rail.collapsed { width: 0 !important; min-width: 0 !important; border-right: none; }

/* + New session IS the theme's primary button (.btn .btn-primary). Keep it a
   content-width pill — align-self:flex-start stops the rail's stretch from
   blowing it edge-to-edge. */
/* A substantial primary button: stretches to the rail width minus a comfortable
   inset (not edge-to-edge, not a tiny content-width pill). */
/* Both surfaces: the full btn-lg button, transform-scaled down on both axes. */
/* TWO TYPES, ONE TAB PAIR (his order, 2026-09-29). A segmented control at the
   top of the rail: the active tab is the type + New creates and the type the
   Recents list shows. Reads at the icon-strip width too — the labels go, the
   glyphs stay. */
.rail-type-tabs {
  display: flex;
  gap: 4px;
  margin: 10px 12px 0;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2, rgba(255, 255, 255, 0.03));
}
.rail-type-tab {
  flex: 1 1 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 7px 10px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--text-dim, #9aa0aa);
  font: inherit;
  /* The rail's own reading size (his order, 2026-09-29: "make the text for work
     and code bigger") — the nav rows below use 13px, and a tab that names the
     whole list should not read smaller than a destination. */
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.rail-type-tab svg { width: 15px; height: 15px; flex: none; }
.rail-type-tab:hover { color: var(--text); }
.rail-type-tab.active { background: var(--surface-3, rgba(255, 255, 255, 0.08)); color: var(--text); }
#app-rail.rail-icons .rail-type-tabs { margin: 8px 6px 0; }
#app-rail.rail-icons .rail-type-tab span { display: none; }

/* The recents dropdown's copy of the pair sits UNDER its search and reads a
   size down from the rail's (his order, 2026-09-29: "move the tabs under the
   search and make the buttons smaller, still centered") — the tabs size to
   their words instead of stretching, and the pair is centred in the menu. */
.wb-session-tabs {
  margin: 0 2px 6px;
  justify-content: center;
  align-self: center;
}
.wb-session-tabs .rail-type-tab {
  flex: 0 0 auto;
  gap: 5px;
  padding: 4px 10px;
  font-size: 12px;
}
.wb-session-tabs .rail-type-tab svg { width: 13px; height: 13px; }

/* + New is a rail ROW now (his order + screenshot, 2026-09-29), so it takes
   the nav item's own geometry — no filled-button scale, no stretch. */
.code-new-session-rail { margin-top: 6px; }
/* DESKTOP only: the 30px header crammed the wordmark — give the logo row its
   room back (the drag strip + every offset follows --titlebar-h). Web stays 0. */
html:not(.glyphh-web) body { --titlebar-h: 40px; }
html:not(.glyphh-web) #panel-wc { height: 40px; padding-left: 16px; }

.code-rail-label {
  padding: 12px 14px 6px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-3);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* Recents shares the rail with the Apps grid below it, so it is capped rather
   than flex:1 — the grid takes the remaining space. */
.app-rail-nav { display: flex; flex-direction: column; gap: 1px; padding: 6px 8px 0; }

.app-rail-nav-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 10px;
  border: none;
  border-radius: 8px;
  background: none;
  color: var(--text-2);
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}

.app-rail-nav-item svg { width: 15px; height: 15px; flex-shrink: 0; }

.app-rail-nav-item:hover { background: var(--hover); color: var(--text); }

/* Recents shares the rail with the OPT-IN Apps/Layouts trays below it. It is
   capped rather than flex:1; when no tray is open (the default — they're
   Appearance opt-ins) syncRailLayout() flexes it to fill the rail. */
.code-history { flex: 0 1 170px; min-height: 60px; overflow-y: auto; padding: 0 8px 6px; }

/* ── Rail Apps/Layouts trays (opt-in via Settings → Appearance) ─────────── */
/* Recents vertical resize */
.recents-vsplit {
  flex: 0 0 4px;
  margin: 1px 8px;
  border-radius: 2px;
  cursor: row-resize;
  background: var(--text-faint);
  opacity: 0.7;
}
.recents-vsplit:hover { background: var(--accent); opacity: 1; }

/* Apps grid (rail) — Apps-page icons in tiles */
.app-rail-grid {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 2px 10px 10px;
  display: grid;
  /* TABS PER ROW (Appearance → Tabs per row). Unset = auto-fill at a 58px
     floor, the behaviour this grid has always had; a set count pins the
     columns instead and lets them shrink to share the rail's width. */
  grid-template-columns: repeat(var(--rail-tabs-cols, auto-fill), minmax(var(--rail-tabs-min, 58px), 1fr));
  gap: 6px;
  align-content: start;
}

.rail-grid-pager { grid-column: 1 / -1; padding: 2px 0 4px; }
.rail-grid-pager .pagination-nav { justify-content: center; }

/* Collapsible rail section header — disclosure toggle (chevron + label) on the
   left, the open-page icon on the right. */
.app-rail-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}
.app-rail-section-head .app-rail-section-toggle { flex: 1; min-width: 0; }
.app-rail-section-head .rail-label-btn { flex: none; }

/* An OPEN section must always show its list — a floor keeps the lists usable
   when the rail runs short; the rail scrolls instead (see #app-rail). */
.app-rail-section-body {
  display: flex; flex-direction: column;
  flex: 1 1 auto; min-height: 132px; overflow: hidden;
}
/* RECENTS hugs its content (his report, 2026-09-14: a flexing body around a
   capped list left a dead gap and the rail "didn't extend down") — content
   flows Recents → vsplit → Apps → Workspaces, the user row's margin-top:auto
   soaks the leftover. The LIST scrolls itself past a generous cap; a dragged
   height (the vsplit) overrides inline. */
#rail-recents-body { flex: 0 0 auto; min-height: 0; }
#recent-sessions-list { flex: 0 1 auto; max-height: 44vh; }

/* Rail section titles are CONTENT, not links — standard text colors in every
   theme rather than the ancestor accent (which read purple). */
.app-rail-section-head .code-rail-disclosure,
.app-rail-section-head .code-rail-label { color: var(--text); }

.code-history-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 3px 3px 10px;
  border-radius: 7px;
  cursor: pointer;
  color: var(--text-3);
  font-size: 12.5px;
  line-height: 1.5;
  min-height: 24px;
}

.code-history-item:hover { background: var(--hover); color: var(--text-2); }

/* The Recent-session highlight only shows while the agent (code) is the
   active section — so the rail never shows two highlights at once. */
body[data-rail-section="code"] .code-history-item.active { background: var(--rail-active-bg); color: var(--white); }

.code-history-title { flex: 1; margin-left: 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Inline rename field — swaps in for the title when the active row's title
   is clicked; matches the row's type so nothing jumps. */
.code-history-rename {
  flex: 1; min-width: 0; margin-left: 6px;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border-2); border-radius: 5px;
  font: inherit; padding: 1px 6px; outline: none;
}

.code-history-item:hover .code-chat-menu-btn,
body[data-rail-section="code"] .code-history-item.active .code-chat-menu-btn { opacity: 1; }

/* Rail collapsed → the fixed chrome cluster floats over the page; shove the
   header content right so they don't overlap. */


/* Drag splitters between the rails and the agent column. */
.code-splitter {
  flex: 0 0 4px;
  width: 4px;
  margin: 0 -2px;
  position: relative;
  z-index: 2;
  cursor: col-resize;
  background: transparent;
}

.code-splitter:hover,
body.code-dragging .code-splitter {
  background: color-mix(in srgb, var(--accent) 45%, transparent);
}

#app-rail.collapsed + .code-splitter { display: none; }

body.code-dragging { cursor: col-resize; user-select: none; }

body.code-dragging #app-rail { transition: none; }













/* App rail — user area (bottom) */
/* Org switcher (multi-org members): a compact select at the rail's top-left
   and the Settings nav head. Hidden until initOrgSwitcher() finds 2+ orgs.
   FULLY self-styled — settings-input's global margins overlapped the first
   nav item on the platform (his report, 2026-09-02). */
.org-switch { flex-shrink: 0; padding: 0 12px 10px 0; }
/* Desktop settings nav: UNDER the search, sharing its horizontal metrics
   (search wrap pads 12px left, 0 right — his order, 2026-09-02). */
.settings-nav > .org-switch, .settings-nav-list > .org-switch { padding: 0 0 10px 12px; }
body.platform-shell .settings-nav > .org-switch { padding: 0 14px 14px 2px; }
#app-rail > .org-switch { padding: 10px 10px 4px; }
.org-switch .org-switch-select {
  display: block; width: 100%; height: 34px; margin: 0;
  background: var(--surface-2, transparent); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px;
  font-family: var(--font-sans); font-size: 13px; font-weight: 500;
  padding: 0 10px;
}
.org-switch .org-switch-select:hover { border-color: var(--text-3); }

/* The rail's scroll body: sections stack inside it and it scrolls as one,
   so the account row below never leaves the viewport however long Recents,
   Apps and Workspaces get. */
.app-rail-scroll {
  display: flex; flex-direction: column;
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overflow-x: hidden;
}
.app-rail-user {
  flex: 0 0 auto;
  /* A column: the new-release card stacks ABOVE the account button (his
     report, 2026-09-20: a row squashed the card beside the name). */
  display: flex; flex-direction: column; align-items: stretch; gap: 6px;
  padding: 8px;
  /* The rail's own divider, on the rail's own ground. */
  border-top: 1px solid var(--sidebar-border, var(--border));
}
.app-rail-user .app-rail-user-btn { width: 100%; min-width: 0; }
#app-rail.rail-icons .app-rail-user { flex-direction: column; }

/* New-release card — sits just above the account button once the feed offers
   a newer version (home.ts paints available / downloading / ready). */
.app-rail-update {
  position: relative;
  display: flex; align-items: flex-start; gap: 8px;
  width: 100%; margin: 0; padding: 8px 26px 8px 10px;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--border-2));
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface-2));
  color: var(--text); font-size: 12px; line-height: 1.35;
}
.app-rail-update > svg { width: 15px; height: 15px; flex: none; margin-top: 1px; color: var(--accent); }
.app-rail-update-body { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 4px; }
.app-rail-update-text { overflow: hidden; text-overflow: ellipsis; }
.app-rail-update-link {
  align-self: flex-start; padding: 0; border: none; background: none;
  color: var(--accent); font: inherit; font-weight: 600; cursor: pointer; text-decoration: underline;
}
.app-rail-update-link:hover { color: var(--accent-hover, var(--accent)); }
.app-rail-update-link:disabled { opacity: .6; cursor: default; }
.app-rail-update-bar { height: 4px; border-radius: 2px; background: var(--border-2); overflow: hidden; }
.app-rail-update-bar > div { height: 100%; width: 0; background: var(--accent); transition: width .2s; }
.app-rail-update-bar.hidden, .app-rail-update-link.hidden, .app-rail-update.hidden { display: none; }
.app-rail-update-close {
  position: absolute; top: 4px; right: 4px; width: 20px; height: 20px;
  display: flex; align-items: center; justify-content: center;
  border: none; border-radius: 5px; background: none; color: var(--text-muted); cursor: pointer;
}
.app-rail-update-close:hover { color: var(--text); background: color-mix(in srgb, var(--accent) 18%, transparent); }
.app-rail-update-close > svg { width: 12px; height: 12px; }
#app-rail.rail-icons .app-rail-update-close { display: none; }
/* Icon-strip rail: only the glyph survives; the card stays clickable via its
   title, and the download/restart link is the whole card. */
#app-rail.rail-icons .app-rail-update { justify-content: center; padding: 7px 0; cursor: pointer; }
#app-rail.rail-icons .app-rail-update-body { display: none; }

.app-rail-user-btn {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 10px;
  border: none;
  border-radius: 8px;
  background: none;
  color: var(--text-2);
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}

.app-rail-user-btn svg { width: 16px; height: 16px; flex-shrink: 0; }
/* The profile avatar in the rail chip — same footprint as the person glyph it
   replaces (his report, 2026-09-01: the set avatar never showed here). */
.app-rail-user-btn .rail-user-avatar { width: 16px; height: 16px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }

.app-rail-user-btn:hover { background: var(--hover); color: var(--text); }

.app-rail-user-btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }


/* User dropdown (opens upward; reuses .code-menu) */
/* Wider (his order, 2026-09-18): it sat narrower than the rail row it opens
   from, so it read as a stray popover rather than that row's menu. */
/* TWO classes on purpose: a later `.code-menu { min-width: 120px }` in this
   same file has equal specificity and was winning, which is why widening it
   did nothing (his report, 2026-09-18). */
.code-menu.app-rail-user-menu { min-width: 216px; }

.app-rail-user-menu .code-menu-item {
  display: flex;
  align-items: center;
  gap: 9px;
}

.app-rail-user-menu .code-menu-item svg { width: 14px; height: 14px; flex-shrink: 0; }






body.code-vdragging { cursor: row-resize; user-select: none; }

.app-rail-search { padding: 0 10px 6px; }


.app-rail-search input {
  width: 100%;
  box-sizing: border-box;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  font-size: 12.5px;
  outline: none;
}

.app-rail-search input:focus { border-color: var(--accent); }



/* Empty rail grid: one action, spanning the whole grid so it can't be
   squeezed into a 58px column and wrap mid-word. */
.app-rail-empty, .app-rail-empty-btn { grid-column: 1 / -1; }
.app-rail-empty { margin: 8px auto; }
.app-rail-empty-btn {
  margin: 6px 0 2px;
  padding: 7px 10px;
  border: 1px dashed var(--border-2); border-radius: 8px;
  background: transparent; color: var(--text-2);
  font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.app-rail-empty-btn:hover { border-color: var(--accent); color: var(--text); }

.app-rail-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 8px 2px 6px;
  border: none;
  border-radius: 9px;
  background: none;
  color: var(--text-2);
  cursor: pointer;
}

.app-rail-tile:hover { background: var(--hover); color: var(--text); }

.app-rail-tile .tile-icon {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-3);
}

/* Favicons sit INSET in the plate — full-bleed read a tad oversized next
   to the 28px panel marks (his eye, 2026-09-10). */
.app-rail-tile .tile-icon img { width: 22px; height: 22px; object-fit: contain; border-radius: 5px; }
/* Panel tiles (Slides/Docs/Design/Band/…) carry their OWN filled marks — no
   frame, just the mark, bigger. The gray box stays only for app favicons,
   which are arbitrary images that need one. */
.app-rail-tile .tile-icon:has(> svg) {
  background: none;
  border-radius: 0;
  overflow: visible;
}
.app-rail-tile .tile-icon:has(> svg) > svg {
  width: 28px !important;
  height: 28px !important;
}
.code-mini-tray .app-rail-tile .tile-icon:has(> svg) > svg {
  width: 24px !important;
  height: 24px !important;
}

.app-rail-tile .tile-initial {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
}

.app-rail-tile .tile-name {
  max-width: 100%;
  font-size: 10.5px;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}


/* Layout tiles — mini 2x2 stack of the layout's app icons. */
.app-rail-tile .tile-icon.tile-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 1fr;
  gap: 1px;
  padding: 2px;
  box-sizing: border-box;
}

/* Section labels + pagers inside the rail grid (palette parity) */
.rail-grid-label {
  grid-column: 1 / -1;
  padding: 10px 2px 2px;
}






/* Apps label row — open icon on the far right */
.app-rail-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}








/* Below ~620px of rail there isn't room for two lists AND recents — let the
   rail itself scroll rather than crushing the lists to nothing. */
/* The rail itself must NOT scroll: .app-rail-scroll is the scrolling body and
   the account row is pinned under it. With a scroller on the rail as well, the
   whole column scrolled and the account row left the viewport (his report,
   2026-09-18). */
#app-rail { overflow: hidden; overscroll-behavior: contain; }

.rail-label-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 5px;
  background: none;
  color: var(--text-3);
  cursor: pointer;
  padding: 0;
}

.rail-label-btn svg { width: 12px; height: 12px; }

.rail-label-btn:hover { background: var(--hover); color: var(--text); }

.app-rail-tile--os { opacity: 0.78; }

.app-rail-tile--os:hover { opacity: 1; }


/* Recents disclosure */
.code-rail-disclosure {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  border: none;
  background: none;
  cursor: pointer;
  text-align: left;
}

/* Breathing room between the nav and the Recents header. */
#recents-toggle { margin-top: 14px; }

.code-rail-disclosure .disc-chevron {
  width: 11px;
  height: 11px;
  transition: transform 0.15s ease;
}

.code-rail-disclosure.closed .disc-chevron { transform: rotate(-90deg); }

body.code-dragging iframe { pointer-events: none !important; }
/* webviews swallow mousemove exactly like iframes — without this the rail
   splitter drag dies the moment the cursor crosses an echo card */
body.code-dragging webview { pointer-events: none !important; }






/* .code-menu family — the shared dropdown chrome the rail menus ride
   (session-row ⋯, More fly-out, user menu). Missed by the rail restore. */



/* Session row menu (⋯ → Delete) */
.code-menu {
  position: fixed;
  z-index: 1000;
  min-width: 120px;
  padding: 4px;
  background: var(--bg-raised);
  border: 1px solid var(--border-2);
  border-radius: 9px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}

.code-menu-item:hover { background: var(--hover); }

.code-menu-item.danger { color: var(--danger); }

.code-menu-item.danger:hover { background: rgba(229, 72, 77, 0.1); }


/* ═══ v2.4.5 selectors missed by the rail restore — complete sweep:
   session-row ⋯ button + run dot, the authentic session-row menu,
   slot maximize, rail apps-list sizing, layout minis. ═══ */




.ws-rail-slot-header .slot-maximize {
  background: transparent; border: none; padding: 0;
  width: 24px; height: 24px; border-radius: 4px;
  color: var(--ws-text-faint); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.10s, color 0.10s;
}


#recent-apps-list { flex: 1; min-height: 96px; }


/* Agent-loop status — faint dot per session, strobing green while working. */
.code-chat-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-left: 2px;
  background: var(--text-faint);
  opacity: 0.35;
}


/* THE STROBE ITSELF (his report, 2026-09-29: "the left rail should show the
   flashing green dot"). Every dot named this animation and NOTHING defined it —
   the keyframes were lost, so a running thread's dot sat there solid green. */
@keyframes gs-dot-strobe {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.35; transform: scale(0.82); }
}
/* THE FOUR STATES (his order, 2026-09-29): green working (and flashing, so a
   running thread is visible from across the room), yellow waiting on the
   person, red the last turn failed, grey idle — the base style above. */
.code-chat-dot.working {
  background: #34d399;
  opacity: 1;
  animation: gs-dot-strobe 1.5s ease-in-out infinite;
}
.code-chat-dot.waiting {
  background: #fbbf24;
  opacity: 1;
  animation: gs-dot-strobe 2.4s ease-in-out infinite;
}
.code-chat-dot.failed {
  background: #f87171;
  opacity: 1;
}


.code-chat-menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--text-2);
  cursor: pointer;
  padding: 0;
  margin-left: auto;
  opacity: 0;
}


.code-chat-menu-btn:hover { color: var(--text); background: var(--hover); }



/* Session row menu (⋯ → Delete) */
.code-menu {
  position: fixed;
  z-index: 1000;
  min-width: 120px;
  padding: 4px;
  background: var(--bg-raised);
  border: 1px solid var(--border-2);
  border-radius: 9px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}


.code-menu-item {
  display: block;
  width: 100%;
  padding: 7px 10px;
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--text);
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
}


.tile-layout .mini {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 3px;
  overflow: hidden;
  background: var(--surface-2);
  min-width: 0;
  min-height: 0;
}

/* Internal app panels (hosted sections: Home, Apps, Settings, Layouts, …)
   have NO header row at all — like the agent panel, the page IS the surface
   and carries its own headings; nav/dock/rail is how you leave. Workspace
   tools and app webview panels keep their headers and controls. */
.ws-rail-slot[data-view="section"] > .ws-rail-slot-header { display: none; }
/* Echo is THE surface — no panel chrome of its own. */
.ws-rail-slot[data-view="echo"] > .ws-rail-slot-header { display: none; }

/* ── Echo, phase 1 — everything (command center + panel types) on one
   three.js WebGL wall; drag pans, wheel/± zooms. ─────────────────────── */
.ws-echo-body {
  position: relative; overflow: hidden;
  /* The command center wears the theme's own background — NO bloom. (The splash
     purple lives on the new-session HeroFlow backdrop, not here.) Slightly
     DARKENED so the wall reads as its own room, theme-aware via color-mix. */
  background: color-mix(in srgb, var(--bg) 88%, black);
}
.echo-stage { position: absolute; inset: 0; z-index: 1; overflow: hidden; cursor: grab; }
.echo-stage:active { cursor: grabbing; }
.echo-stage canvas { display: block; }

/* Zoom controls, bottom-right over the scene. */
/* Keep only the command icon (.echo-shadow-btn = "show the wall"); hide the
   zoom in/out/reset trio. The elements STAY in the DOM so their click handlers
   (bound later via querySelector(...)!.addEventListener) don't null-throw. */
.echo-z-in, .echo-z-out { display: none; }
/* the header's command-center eye mirrors the echo eye's pinned state */
#code-cc-btn.active { color: var(--accent); }

/* (The rail's Apps and Layouts sections were hidden 2026-07-31 and are back
   as of 2026-08-01 — collapsed by default, see RAIL_SECTIONS in help/code.ts.) */

/* GATED composer — no working folder yet. A disabled textarea swallows
   clicks, so let them pass through to the wrap (whose click opens the
   folder picker), and give the gate its own visible voice. */
.code-input-wrap.gated .code-input { pointer-events: none; opacity: 0.55; }
.code-gate-note {
  display: block; width: 100%; text-align: left;
  padding: 7px 12px; margin-bottom: 6px;
  border: 1px solid var(--accent); border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent); font-size: 12.5px; font-weight: 600;
  cursor: pointer;
}
.code-gate-note:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }

/* The VEIL — with cards open the wall fades back behind a slightly darker
   wash (the old layout-manager feel); ⌘⇧ / the eye lifts it. */
.echo-veil {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  opacity: 0; transition: opacity 0.25s ease;
}
.ws-echo-body:has(.echo-card) .echo-veil { opacity: 1; }
.ws-echo-body:has(.echo-cards.echo-shadow) .echo-veil { opacity: 0; }

/* Open panels: LIVE webview cards that zoom up out of their tile and back.
   The layer never blocks the wall — only the cards themselves take input. */
.echo-cards { position: absolute; inset: 0; z-index: 3; pointer-events: none; overflow: hidden; }
.echo-card {
  position: absolute; display: flex; flex-direction: column; pointer-events: auto;
  border-radius: 10px; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border-2);
  box-shadow: 0 18px 50px var(--shadow);
  opacity: 0;
  transition: left .35s cubic-bezier(.2, .8, .25, 1), top .35s cubic-bezier(.2, .8, .25, 1),
    width .35s cubic-bezier(.2, .8, .25, 1), height .35s cubic-bezier(.2, .8, .25, 1), opacity .3s ease;
}
.echo-card.flash { box-shadow: 0 0 0 2px var(--accent), 0 18px 50px var(--shadow); }
/* A maximized card owns the stage: sibling cards disappear ENTIRELY —
   webview guests composite above any z-index, so visibility (which does
   suspend their compositing) is the only real occlusion — and they take
   their headers, seams and drag affordances with them. */
.echo-cards.has-expanded .echo-card:not(.expanded) {
  visibility: hidden;
  pointer-events: none;
}
/* Flow panels reorder by dragging their header (up/down/across columns). */
.echo-card-head { cursor: grab; position: relative; }
.echo-card-head:active { cursor: grabbing; }
/* The grab HANDLE — a short line at the head's top center. Appears as the
   hover affordance, turns accent while the panel is being dragged. */
.echo-card-head::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 3px;
  transform: translateX(-50%);
  width: 44px;
  height: 3px;
  border-radius: 2px;
  background: var(--border-2);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.echo-card-head:hover::after { opacity: 0.8; }
.echo-card.echo-card-dragging .echo-card-head::after { opacity: 1; background: var(--accent); }
.echo-card.echo-card-dragging { opacity: 0.88; z-index: 3; }
/* While a drag is live, embedded pages must not swallow the pointer, and
   text selection would fight the gesture. */
body.echo-drag { user-select: none; }
body.echo-drag .echo-card iframe,
body.echo-drag .echo-card webview { pointer-events: none; }
.echo-card-head {
  display: flex; align-items: center; gap: 6px;
  padding: 5px 6px 5px 10px; font-size: 12px; font-weight: 600; color: var(--text-2);
  border-bottom: 1px solid var(--border);
}
.echo-card-head { cursor: grab; }
/* The PIN — apps land in this card (the workbench sticky rule, in Echo). */
.echo-card.echo-pinned .echo-card-head span::before {
  content: ""; display: inline-block; width: 6px; height: 6px;
  margin-right: 7px; border-radius: 50%; background: var(--accent);
  vertical-align: 1px;
}
.echo-card.dragging { transition: none; z-index: 5; opacity: 0.92; }
/* Dividers — the seams between layout slots (the old rail handles): drag
   to reshape the whole layout. */
/* ── The FLAT LAUNCHER — iPhone-style pages of icons (no WebGL) ── */
.echo-pages {
  position: absolute; inset: 0;
  display: flex;
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.echo-pages::-webkit-scrollbar { display: none; }
.echo-page {
  flex: 0 0 100%; height: 100%;
  scroll-snap-align: start;
  display: flex; align-items: flex-start; justify-content: center;
  /* Big icons × many-per-page can outgrow the band — scroll, never clip. */
  overflow-y: auto;
  scrollbar-width: none;
}
.echo-page::-webkit-scrollbar { display: none; }
.echo-page-grid {
  display: grid;
  /* The NATURAL cap: columns at the 1.45×icon ceiling they have always had,
     plus the gaps between them, plus this grid's own side padding (the
     global box-sizing is border-box). Spelled once, read by max-width. */
  --echo-wall-natural: calc(
    var(--echo-cols, 8) * var(--echo-icon-size, 76px) * 1.45
    + (var(--echo-cols, 8) - 1) * (20px + (var(--icon-zoom, 1.08) - 1) * var(--echo-icon-size, 76px) * 0.62)
    + 68px
  );
  /* TILES PER ROW (Appearance → Tiles per row): the column COUNT is the
     setting. Columns keep their icon-sized floor and take 1fr above it, so
     the width slider below has something to spend its room on. */
  grid-template-columns: repeat(var(--echo-cols, 8), minmax(calc(var(--echo-icon-size, 76px) * 0.95), 1fr));
  /* ZOOM-AWARE SPACING (his rule, 2026-08-20): the hover zoom grows a tile by
     (zoom-1)·size/2 per side — the gaps grow with the SAME term (plus slack)
     so no icon-zoom / icon-size pairing can make neighbours overlap. */
  gap: calc(17px + (var(--icon-zoom, 1.08) - 1) * (var(--echo-icon-size, 76px) + 24px) * 0.62)
       calc(20px + (var(--icon-zoom, 1.08) - 1) * var(--echo-icon-size, 76px) * 0.62);
  justify-content: center; align-content: start;
  /* WALL WIDTH (Appearance → Wall width, --echo-wall-w = 0..100). 0 is the
     grid's NATURAL cap — columns at their old 1.45×icon ceiling, which is
     exactly the width the wall has always drawn. 100 opens it to the full
     page, the 34px padding below being the "just a bit" of side air. The
     two ends are interpolated, so the slider is continuous between them. */
  width: 100%;
  max-width: calc(
    var(--echo-wall-natural) + (100% - var(--echo-wall-natural)) * var(--echo-wall-w, 0) / 100
  );
  margin-inline: auto;
  /* More air under the dock (labels live there now), and under the search
     pill between the dock and the tiles (--echo-search-top is measured by
     positionPageChrome; the pill is 44px tall). */
  padding: calc(var(--echo-search-top, 98px) + 44px + 26px) 34px 148px;
}

/* THE SEARCH PILL (his ask, 2026-10-03): round, centred, in the theme's own
   surface and border, between the dock and the tiles. Restored from the
   2026-08 top bar; a miss dims, a hit stays. */
.echo-search-wrap {
  position: absolute; left: 50%; top: var(--echo-search-top, 98px); transform: translateX(-50%);
  z-index: 3;
  display: flex; align-items: center; gap: 10px;
  width: min(520px, 64vw); height: 44px;
  padding: 0 18px; box-sizing: border-box;
  border: 1px solid var(--border); border-radius: 999px;
  background: color-mix(in srgb, var(--surface-2) 86%, transparent);
  backdrop-filter: blur(18px);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.18);
  cursor: text;
  transition: border-color 120ms ease;
}
.echo-search-wrap:focus-within { border-color: var(--accent); }
.echo-search-ic { width: 17px; height: 17px; flex: none; color: var(--text-faint); }
.echo-search {
  flex: 1; min-width: 0; border: none; background: none; outline: none;
  color: var(--text); font: inherit; font-size: 15px;
}
.echo-search::placeholder { color: var(--text-faint); }
.echo-app-btn.echo-search-miss { opacity: 0.14; }

/* the drip PICKER popup — ABOVE its droplet (the anchor wraps the button,
   which sits on the agent's top row, right of the caret) */
.echo-drip-anchor { position: relative; display: inline-flex; }
.echo-drip-pop {
  position: absolute; bottom: calc(100% + 8px); top: auto; right: 0;
  display: grid; grid-template-columns: repeat(3, 96px); gap: 6px;
  padding: 10px;
  border: 1px solid var(--border); border-radius: 13px;
  background: var(--surface-2);
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25);
  z-index: 5;
}
.echo-drip-pop.hidden { display: none; }
.echo-drip-tile {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 10px 6px; border: none; border-radius: 10px;
  background: none; color: var(--text); cursor: pointer; font-size: 12px;
}
.echo-drip-tile:hover { background: var(--hover); }
.echo-drip-tile .edt-ic { font-size: 20px; }
.echo-drip-tile .edt-nm { max-width: 88px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.echo-drip-empty { padding: 12px 16px; color: var(--text-faint); font-size: 12.5px; grid-column: 1 / -1; }

/* ── EDIT MODE (press-and-hold): iPhone wiggle + delete badges ── */
.echo-pages.echo-edit .echo-app-btn { animation: echo-jiggle 0.30s ease-in-out infinite alternate; }
.echo-pages.echo-edit .echo-app-btn:nth-child(2n) { animation-duration: 0.26s; animation-delay: -0.1s; }
.echo-pages.echo-edit .echo-app-btn:nth-child(3n) { animation-duration: 0.34s; animation-delay: -0.18s; }
@keyframes echo-jiggle {
  from { transform: rotate(-1.7deg); }
  to   { transform: rotate(1.7deg); }
}
.echo-app-btn { position: relative; }
.echo-app-del {
  position: absolute; top: -7px; left: -7px; z-index: 2;
  width: 21px; height: 21px; border-radius: 50%;
  border: none; padding: 0;
  background: #e5484d; color: #ffffff;
  font-size: 12px; line-height: 1;
  display: none; align-items: center; justify-content: center;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}
.echo-pages.echo-edit .echo-app-btn.removable .echo-app-del { display: flex; }

/* ── DOCK AUTO-HIDE: hidden until the top edge is hovered ── */
/* MAGNIFICATION — a super smooth follow on every slot (JS sets the scale). */
/* The command-center (wall) button + the RESET above it — equal peers. */

.echo-dock-btn { transform-origin: top center; transition: transform 0.2s cubic-bezier(0.25, 0.9, 0.3, 1), box-shadow 0.12s ease; will-change: transform; }
.echo-app-btn {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  border: none; background: none; padding: 0; cursor: pointer;
}
/* SAME square as the dock slots — one icon language everywhere. */
.echo-app-ic {
  display: flex; align-items: center; justify-content: center;
  width: var(--echo-icon-size, 76px); height: var(--echo-icon-size, 76px);
  border-radius: 18px;
  background: var(--surface-3);
  color: var(--text-2);
  overflow: hidden;
  transition: box-shadow 0.12s ease;
}
/* LIGHT ICON ZOOM (Appearance → Icon zoom, --icon-zoom): every icon in the
   app breathes up a touch on hover. On the launcher the whole tile (icon +
   label) scales — sturdier target than the inner span, and reads more
   iPhone. Edit-mode wiggle (an animation) takes precedence while active. */
.echo-pages .echo-app-btn { transition: transform 0.15s cubic-bezier(0.25, 0.9, 0.3, 1); will-change: transform; }
.echo-pages .echo-app-btn:hover { transform: scale(var(--icon-zoom, 1.08)); }
.echo-app-btn:hover .echo-app-ic { box-shadow: 0 0 0 1.5px var(--echo-tile-highlight, var(--text)); }
.echo-app-btn.open .echo-app-ic { box-shadow: 0 0 0 1.5px var(--accent); }
.echo-app-ic svg { width: 62%; height: 62%; }
/* The dev workbench tool tiles (Files/Terminal/Editor/Diff/Plan/Releases):
   plain outline glyphs read oversized at 62% — seat them smaller. */
.echo-app-ic svg.dev-glyph { width: 46%; height: 46%; }
.echo-dock-btn svg.dev-glyph { width: 46%; height: 46%; }
.echo-app-ic img { width: 54%; height: 54%; object-fit: contain; }
.echo-app-ic img[data-mark-src="brand/glyphh-mark.png"] { width: 74%; height: 74%; }   /* the mascot is tall, not a square favicon */   /* raster icons fill their box edge-to-edge — smaller than the svgs to match visual weight */
/* The SKILLS fallback mark (an app with no icon of its own): same weight as
   an app icon, not the larger tool-glyph size. */
.echo-app-ic svg.skill-mark { width: 54%; height: 54%; }
.echo-app-fallback { font: 600 20px var(--font-sans); color: var(--text-2); }
.echo-app-name {
  max-width: 96px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 11.5px; color: var(--text-2);
}
/* Layout icons — the 2×2 mini stack, DOM edition. */
.echo-app-mini { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; width: 72%; height: 72%; }
.echo-app-mini .mini { display: flex; align-items: center; justify-content: center; background: var(--surface-2); border-radius: 4px; overflow: hidden; }
.echo-app-mini .mini svg { width: 70%; height: 70%; }
.echo-app-mini .mini img { width: 80%; height: 80%; object-fit: contain; }
.echo-app-mini .mini i { font-style: normal; font-size: 9px; font-weight: 600; color: var(--text-3); }
.echo-app-btn.dock-dragging { opacity: 0.4; }
/* Multi-select: picked icons ring in accent; the square + line lassos. */
.echo-app-btn.selected .echo-app-ic { box-shadow: 0 0 0 2px var(--accent); }
.echo-marquee {
  position: absolute; z-index: 4; pointer-events: none;
  border: 1.5px solid var(--accent); border-radius: 4px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.echo-lasso-line {
  position: absolute; z-index: 4; pointer-events: none;
  height: 3px; border-radius: 2px;
  background: var(--accent);
  transform-origin: 0 50%;
  box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 55%, transparent);
}
/* Page dots — just UNDER the icon grid (code-workbench positions top). */
.echo-page-dots {
  position: absolute; left: 50%; transform: translateX(-50%);
  display: flex; gap: 8px; z-index: 3;
}
/* EDGE-DROP hints — glow strips while a card drag holds a band edge. */
.echo-stage::before, .echo-stage::after {
  content: "";
  position: absolute; top: 0; bottom: 0; width: 52px;
  pointer-events: none; opacity: 0; z-index: 6;
  transition: opacity 0.15s ease;
}
.echo-stage::before { left: 0; background: linear-gradient(to right, color-mix(in srgb, var(--accent) 30%, transparent), transparent); }
.echo-stage::after { right: 0; background: linear-gradient(to left, color-mix(in srgb, var(--accent) 30%, transparent), transparent); }
.echo-stage.echo-edge-left::before { opacity: 1; }
.echo-stage.echo-edge-right::after { opacity: 1; }

/* Page arrows — either side of the icon lists. */
.echo-page-arrow {
  position: absolute; z-index: 3;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%;
  background: color-mix(in srgb, var(--surface-2) 82%, transparent);
  backdrop-filter: blur(12px);
  color: var(--text-2); cursor: pointer;
  transition: color 0.12s ease, background 0.12s ease;
}
.echo-page-arrow:hover { color: var(--text); background: var(--surface-3); transform: scale(var(--icon-zoom, 1.08)); }
.echo-page-arrow svg { width: 18px; height: 18px; }
.echo-page-arrow.prev { left: 22px; }
.echo-page-arrow.next { right: 22px; }
.echo-page-dots.hidden { display: none; }
.echo-page-dot {
  width: 8px; height: 8px; border-radius: 50%; border: none; padding: 0;
  background: color-mix(in srgb, var(--text) 25%, transparent);
  cursor: pointer;
}
.echo-page-dot.active { background: var(--text-2); }
/* Traded-in app icons render as images inside dock slots. */
/* SAME inner proportions as the page tiles (.echo-app-ic) — one icon
   language: the glyph scales with ITS square, not the viewport. */
.echo-dock-btn img { width: 54%; height: 54%; object-fit: contain; }
/* TITLES under the dock icons (his ask, 2026-08-20) — pure CSS from the
   button's title attribute, so both builders (nav template + traded icons)
   get labels with zero markup churn. Absolute: the squares keep their size. */
/* Bottom margin RESERVES the magnification's reach: a zoomed slot grows down
   (scale + the arc's dip) — scaling the gap with the dock-zoom pref keeps it
   off the tiles below at every strength. */
.echo-dock { margin-bottom: calc(24px + (var(--dock-zoom, 1.2) - 1) * 64px); }
.echo-dock-btn { position: relative; overflow: visible; }
.echo-dock-btn::after {
  content: attr(title);
  position: absolute;
  top: calc(100% + 5px);
  left: 50%;
  transform: translateX(-50%);
  max-width: 110%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10.5px;
  line-height: 1;
  color: var(--text-3);
  pointer-events: none;
}
.echo-dock-btn .echo-app-mini { width: 72%; height: 72%; }   /* = the page tiles' mini */
.echo-dock-btn .echo-app-fallback { font-size: 20px; }

/* Echo top bar — JUST the dock now, sitting high on the page. Sits over
   the pages, under the cards. (Search is gone; drips live on the composer
   card.) */
.echo-topbar {
  position: absolute; top: 16px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px; z-index: 3;
}
/* The dock — FIXED nav slots above the search box: Apps / Marketplace /
   Connections / Workspaces / Scheduled Tasks / Agents / Browser / Settings.
   Office-icon language (full-bleed object silhouettes, the VIEW_META
   family). NO wrapping chrome — a bare row; each slot is the SAME rounded
   square the wall tiles draw (surface-3 box, hover ring in the tile
   highlight ink). */
.echo-dock {
  display: flex; align-items: center;
  gap: 14px;   /* the same in every space (2026-09-16) */
  /* The CONTENT side is the room it has, never the whole window — the fixed
     sidebar owns the left, so measuring the viewport let the row run off both
     edges of a centered dock (his report, 2026-09-17). */
  max-width: calc(100vw - var(--rail-w, 0px) - 32px);
  margin-top: 10px;               /* and a tad more drop below the dock line */
}
/* Slots SHRINK to fit the page: fluid between 46px and 76px squares (the
   glyphs ride along), so the dock always fits the window on one row. */
.echo-dock-btn {
  display: inline-flex; align-items: center; justify-content: center;
  /* The size preference is the MAXIMUM; the row shrinks from there to fit, and
     stays square while it does (height follows the width, not the setting). */
  width: var(--echo-icon-size, 76px); height: auto; aspect-ratio: 1 / 1;
  padding: 0; flex-shrink: 1; min-width: 40px;
  border: none; border-radius: 18px;
  background: var(--surface-3);
  cursor: pointer;
  transition: box-shadow 0.12s ease;
}
.echo-dock-btn:hover { box-shadow: 0 0 0 1.5px var(--echo-tile-highlight, var(--text)); }
/* Dock slots pick the hover zoom up too when the arch magnification is off
   (its inline transforms take precedence while active). */
.echo-dock-btn:hover:not([style*="transform"]) { transform: scale(var(--icon-zoom, 1.08)); }
.echo-dock-btn.dock-dragging { opacity: 0.4; }
.echo-dock-btn svg { width: 62%; height: 62%; display: block; }


.echo-dividers { position: absolute; inset: 0; pointer-events: none; z-index: 4; }
.echo-div { position: absolute; pointer-events: auto; border-radius: 4px; transition: background 0.12s ease; }
.echo-div-v { width: 8px; cursor: col-resize; }
.echo-div-h { height: 8px; cursor: row-resize; }
.echo-div:hover { background: color-mix(in srgb, var(--accent) 45%, transparent); }
.echo-cards.echo-no-anim .echo-card { transition: none; }
.echo-card.dragging .echo-card-head { cursor: grabbing; }
/* Inside a workbench/layout panel the composer's default 48/52px gutters +
   880px centering cap scrunch the input into a narrow column. Drop the gutters
   right down and release the cap so the input uses the panel's full width. */
.ws-agent-holder .code-composer { padding: 4px 12px 14px; max-width: 880px; margin: 0 auto; width: 100%; }
/* The HOLDER-hosted agent (a layout's Glyphh cell) wears the SAME design as
   the center agent — head hidden, thread above, the floating INPUT CARD
   below. The card/chip chrome is class-based and applies on its own; these
   mirror the center-scoped overrides that don't reach outside .code-root. */
.ws-agent-holder .code-agent > .code-thread { display: block; flex: 1; min-height: 0; overflow-y: auto; }
.ws-agent-holder .code-input {
  border: none;
  background: none;
  padding: 12px 44px 6px 6px;
  min-height: 48px;
  font-size: 14px;
}
.ws-agent-holder .code-input:focus { outline: none; box-shadow: none; }
.ws-agent-holder .code-composer-bar { padding: 2px 2px 0; }

/* The caret/status row is the BOTTOM composer's thread peek — in a cell the
   thread is right there above the input, so the row hides; drips/recents/+
   stay useful and keep their spots. */
.ws-agent-holder .code-status-line { display: none; }
/* CELL ARRANGEMENT (his spec): one row under the card header — session TITLE
   top left, the right-hand menu (droplet/recents/+/⋮ + kebab) top right —
   then the thread, then the input card (source row above the input; the
   permission/+ group bottom-left, model/loop/meter bottom-right ride the
   card's own bar). Grid places the two shared DOM rows side by side. */
.ws-agent-holder > .code-agent {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto minmax(0, 1fr) auto;
}
.ws-agent-holder .code-agent-head {
  display: flex;
  grid-area: 1 / 1 / 2 / 2;
  position: static;
  background: none;
  border-bottom: none;
  padding: 4px 4px 2px 10px;
  min-height: 0;
  -webkit-app-region: no-drag;
}
.ws-agent-holder .code-agent-toprow {
  grid-area: 1 / 2 / 2 / 3;
  padding: 4px 10px 2px 4px;
}
.ws-agent-holder .code-agent > .code-thread { grid-area: 2 / 1 / 3 / 3; }
.ws-agent-holder .code-agent > .code-composer { grid-area: 3 / 1 / 4 / 3; }
.ws-agent-holder .code-composer.typing-glow .code-input-card { animation: composer-glow 2.4s ease-in-out infinite; border-color: color-mix(in srgb, var(--accent) 28%, var(--border)); }
.echo-card-head span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* bare glyph buttons — no UA button chrome (the gray box) */
.echo-card-head .ws-icon-btn {
  display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0;
  border: none; border-radius: 6px; background: none;
  color: var(--text-3); cursor: pointer;
}
.echo-card-head .ws-icon-btn:hover { background: var(--hover); color: var(--text); }
.echo-card-head svg { width: 13px; height: 13px; }

/* B2: a panel that belongs to a LAYOUT hides its own close (X) — the layout is
   closed as a whole via the layout bar (B1). Standalone app cards keep their X. */
.echo-card.echo-card-in-layout .echo-card-close { display: none; }

/* B1: the layout bar — one "Close layout" control, shown only while a layout's
   panels are on stage. Sits top-center above the cards, out of the way. */
.echo-layout-bar {
  /* Re-parented into #shell-drag-strip (the 38px app header) in code-workbench.ts, so
     it's absolute-centered WITHIN that fixed header — dead center of the app header,
     not the content pane. no-drag so the button stays clickable in the drag region. */
  position: absolute;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  z-index: 201;
  -webkit-app-region: no-drag;
  display: flex; align-items: center; gap: 10px;
  padding: 4px 6px 4px 14px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 999px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
  max-width: 70%;
}
.echo-layout-bar.hidden { display: none; }
/* AUTO-HIDE while a layout shows (his rule, 2026-08-19): the bar tucks fully
   OUT OF SIGHT like the docked composer — only a grabber LINE stays visible;
   hovering it slides the bar down. */
.echo-layout-bar:not(.hidden) {
  /* DESKTOP CLICKABILITY (his bug, 2026-08-20: revealed bar dead after a
     tuck/reveal cycle): Electron's -webkit-app-region hit-test rects do NOT
     track CSS transforms, so a transform-tucked bar left its no-drag region
     behind and the revealed pill sat inside the window-DRAG region — every
     click started a window drag. The tuck now animates `top` (layout, which
     the region map does track); translate stays a constant centering. */
  transition: top 0.22s ease, opacity 0.22s ease, box-shadow 0.22s ease;
  /* Tucked: rendered top ≈ -41px (−24 − h/2), bottom edge ≈ -7px — nothing
     shows but the grabber line, same geometry as the old transform tuck. */
  top: -24px;
  box-shadow: none;   /* the 20px blur bled below the window edge otherwise */
}
.echo-layout-bar:not(.hidden)::after {
  content: "";
  position: absolute;
  top: calc(100% + 15px);   /* bar bottom sits at -7px → line lands at 8px */
  left: 50%;
  transform: translateX(-50%);
  width: 44px;
  height: 4px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--text-3) 60%, transparent);
}
/* A GENEROUS invisible hover pad under the tucked bar — the 4px line alone
   was a needle-threading target. Full pill width + margins, 34px tall. */
.echo-layout-bar:not(.hidden)::before {
  content: "";
  position: absolute;
  top: 100%;
  left: -48px;
  right: -48px;
  height: 34px;
}
.echo-layout-bar:not(.hidden):hover,
.echo-layout-bar:not(.hidden):focus-within,
.echo-layout-bar.peek:not(.hidden) {
  /* 19px = the 38px strip's center in px — px↔% doesn't interpolate, so the
     slide needs both ends in px. */
  top: 19px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
}
.echo-layout-bar:not(.hidden):hover::after,
.echo-layout-bar:not(.hidden):focus-within::after,
.echo-layout-bar.peek:not(.hidden)::after { opacity: 0; }
.echo-layout-bar.intro,
.echo-layout-bar.intro:not(.hidden) { top: 19px; transform: translate(-50%, -50%); opacity: 1; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28); }
.glyphh-web .echo-layout-bar:not(.hidden) { transform: translate(-50%, calc(-100% - 14px)) !important; }   /* fixed top:6px → bottom edge -8px */
.glyphh-web .echo-layout-bar.intro:not(.hidden) { transform: translateX(-50%) !important; opacity: 1; }
.glyphh-web .echo-layout-bar:not(.hidden):hover,
.glyphh-web .echo-layout-bar:not(.hidden):focus-within,
.glyphh-web .echo-layout-bar.peek:not(.hidden) { transform: translateX(-50%) !important; }
.echo-layout-bar-name {
  font-size: 12px; font-weight: 600; color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.echo-layout-cc, .echo-layout-reset {
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  border: none; border-radius: 50%; background: none;
  color: var(--text-2); cursor: pointer;
}
.echo-layout-cc:hover, .echo-layout-reset:hover { background: var(--hover); color: var(--text); }
.echo-layout-cc svg, .echo-layout-reset svg { width: 15px; height: 15px; }
.echo-layout-close {
  display: flex; align-items: center; gap: 6px;
  padding: 4px 12px 4px 10px; width: auto; height: auto;
  border: none; border-radius: 999px; cursor: pointer;
  background: var(--surface-3); color: var(--text-2);
  font-size: 12px; font-weight: 500;
  transition: background 0.15s, color 0.15s;
}
.echo-layout-close:hover { background: var(--danger, #e5484d); color: #fff; }
.echo-layout-close svg { width: 13px; height: 13px; }

/* Shadow mode (⌘⇧E): open cards fade to ghosts and stop taking input so
   the wall behind is visible and clickable; opening another app, closing
   the last one, toggling again, or Esc exits. */
.echo-card.placed { opacity: 1; }
.echo-cards.echo-shadow .echo-card.placed { opacity: 0.07; pointer-events: none; }
/* shadow mode aims every click at the WALL — the layout's divider handles
   behind the veil must not swallow drags */
.echo-cards.echo-shadow .echo-div { pointer-events: none; }
.echo-card-body { flex: 1; min-height: 0; display: flex; }
.echo-card-body webview { flex: 1; min-width: 0; min-height: 0; }


/* ═══════════════════════════════════════════════════════════════════════════
   WEB — PHONE MODE (splash + auth)
   Scoped to `.glyphh-web.glyphh-phone` so it can NEVER affect desktop or iPad
   (both stay on the FULL layout — iPad is not a separate tier). The marker class
   is set by web/src/bridge.js from the pure isPhoneViewport() min-dimension test.
   This slice covers ONLY the splash + login; the rest of the app's mobile layout
   is a later slice. Brand-forward amber (Ember) is a locally-scoped accent so it
   never leaks into the full layout's theme tokens.
   ═════════════════════════════════════════════════════════════════════════ */

.glyphh-web.glyphh-phone,
.glyphh-web.glyphh-phone body {
  /* Ember amber, scoped to phone only. */
  --phone-ember: #f59e0b;
  --phone-ember-strong: #f0a020;
  --phone-grad-ember: linear-gradient(120deg, #f59e0b, #fbbf24 55%, #f97316);
  /* Safe-area insets (require viewport-fit=cover, injected by serve.mjs). */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

/* ── Splash — native app launch screen ─────────────────────────────────────── */

/* The desktop close "traffic light" on the splash is meaningless in a browser
   tab / on a phone — hide it on the whole web target. */
.glyphh-web .splash-close { display: none !important; }

.glyphh-web.glyphh-phone #splash {
  /* Pad the launch content inside the notch + home indicator. */
  padding: calc(var(--safe-top) + 24px) calc(var(--safe-right) + 24px)
           calc(var(--safe-bottom) + 24px) calc(var(--safe-left) + 24px);
  box-sizing: border-box;
}

.glyphh-web.glyphh-phone .splash-content {
  width: 100%;
  max-width: 420px;
}

/* Brand sizes down for the small screen and sits optically centered. */
.glyphh-web.glyphh-phone .splash-logo { margin-bottom: 20px; }
.glyphh-web.glyphh-phone .splash-logo .glyphh-logo {
  height: clamp(72px, 22vw, 104px);
  width: auto;
}

.glyphh-web.glyphh-phone .splash-status {
  font-size: 13px;
}

/* A slim amber progress bar if an (unlikely on web) update paints. */
.glyphh-web.glyphh-phone .splash-update-bar { width: min(240px, 72vw); }
.glyphh-web.glyphh-phone .splash-update-fill { background: var(--phone-ember); }

/* ── Login — full-bleed native mobile sign-in ──────────────────────────────── */

/* The onboarding overlay + auth-shell become full-screen (no centered desktop
   card): a top-anchored brand, then a stacked, generously-spaced form that flows
   to the bottom, all inside the safe area. */
.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell {
  grid-template-rows: auto 1fr auto;
}

.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell-header {
  padding: calc(var(--safe-top) + 20px) calc(var(--safe-right) + 24px) 0
           calc(var(--safe-left) + 24px);
  justify-content: center;
}
.glyphh-web.glyphh-phone #onboarding-overlay .onboarding-wordmark .glyphh-logo {
  height: 40px;
}

.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell-body {
  /* Left-align the content column and let it breathe full-width. */
  align-items: stretch;
  justify-content: flex-start;
  padding: 8vh calc(var(--safe-right) + 24px) 4vh calc(var(--safe-left) + 24px);
}
.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell-content {
  max-width: none;
  width: 100%;
}

/* Big, brand-forward title. */
.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell-title {
  font-size: clamp(2rem, 9vw, 2.75rem);
  margin-bottom: 0.5rem;
}
.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell-lede {
  font-size: 1rem;
  margin-bottom: 2rem;
}

/* Inputs: 16px min font stops iOS auto-zoom on focus; taller tap target. */
.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell-input {
  font-size: 16px;
  padding: 1rem 1.05rem;
  border-radius: 14px;
}

/* Buttons: ≥44px touch targets, full-width, roomy stacking. */
.glyphh-web.glyphh-phone #onboarding-overlay .btn-lg {
  min-height: 52px;
  font-size: 1rem;
  border-radius: 14px;
}
.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell-actions { gap: 1rem; }

/* Login is the ONE surface themes don't override — it holds a fixed brand look.
   So the phone login CTA inherits the desktop primary (white) rather than the
   one-off amber it used to carry; no --phone-ember here. */

/* Google button + its GIS face fill the width and match the 52px height. */
.glyphh-web.glyphh-phone #onboarding-overlay .google-btn { height: 52px; }
.glyphh-web.glyphh-phone #onboarding-overlay .btn-social { min-height: 52px; border-radius: 14px; }

.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell-divider { margin: 1.75rem 0 1.5rem; }
.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell-social { gap: 0.875rem; }

/* Footer sits above the home indicator. */
.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell-footer {
  padding: 1rem calc(var(--safe-right) + 24px)
           calc(var(--safe-bottom) + 1rem) calc(var(--safe-left) + 24px);
}

/* "Check your email" state — same full-bleed treatment (inherits the above). */
.glyphh-web.glyphh-phone #onboarding-overlay .auth-shell-meta { margin-top: 1.5rem; font-size: 0.9375rem; }


/* The auto-updater is an OS-installer concept — a browser tab has none. Hide
   the About "Check for Updates" control + its progress on the web target. */
.glyphh-web #about-check-update,
.glyphh-web #about-progress,
.glyphh-web .about-check-update { display: none !important; }

/* Settings → Desktop: attach-status row — same bones as a connection row
   (connection-status-dot for state, action-btn for the download CTA). */
.desktop-attach-row { display: flex; align-items: center; gap: 10px; padding: 12px 14px;
  border: 1px solid var(--border-2); border-radius: 8px; background: var(--bg-2); }
.desktop-attach-text { flex: 1; min-width: 0; }
.desktop-attach-title { font-size: 12.5px; font-weight: 600; color: var(--text); }
.desktop-attach-sub { font-size: 11px; color: var(--text-3); margin-top: 2px; }

/* Starter cards — a compact full-width strip, 3 across (two rows of three for
   the six starters), title leads the top row with its pill. */
.dash-starters { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.dash-starter-top { display: flex; align-items: center; gap: 8px; }
.dash-starter-title { flex: 1; min-width: 0; font-weight: 600; }
@media (max-width: 900px) { .dash-starters { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* The Chat/Work/Code space pill inside the input was removed — every session
   is the Code agent now. */
.code-input-wrap { position: relative; }

/* Two-col landing: bare columns — header + cards only, no wrapper chrome. */
.dash-col { min-width: 0; }
.dash-session-row .dash-session-when { flex: none; font-size: 11px; color: var(--text-3); }


/* Landing chips row: source chip first, then folder/git/+ — one row, left. */
.dash-source-slot { display: contents; }
/* While the composer sits on Home its own source slot is empty — the chip
   moved up into the dash row; keep the empty slot from reserving space. */
.composer-on-home .code-source-slot { display: none; }

/* Cloud source: no machine folder to pick, nothing to attach from — the
   folder + add controls sleep (visible, explained by title, not clickable). */
.chip-disabled { opacity: 0.45; pointer-events: none; }

/* Repo drop (git chip): search pinned on top with the ACCENT focus treatment
   (the base loop search only shifts a border, which read as unthemed), the
   list scrolling beneath it inside the drop's own height. */
.repo-drop-search:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-bg, rgba(176, 102, 255, 0.18));
}
.repo-drop-search::placeholder { color: var(--text-3); }
.repo-drop-search::selection { background: var(--accent); color: var(--accent-ink, #fff); }
.code-repo-drop-list { max-height: min(300px, 46vh); overflow-y: auto; overscroll-behavior: contain; }

/* WEB: the folder chip + '+' WORK over the attach relay (fs.list browser /
   fs.mkdir) in BOTH rows — the agent view carries the same chips as the
   landing. Only the composer '+' stays hidden, because it drives a native
   attachment dialog a browser cannot run. */
.glyphh-web #code-plus-wrap { display: none !important; }

/* Machine folder browser: the "+ new folder" row (input + Create + error). */
.ws-fs-newfolder { display: flex; align-items: center; gap: 6px; padding: 2px 8px 4px; }
.ws-fs-newfolder .loop-drop-search { flex: 1; margin: 0; }
.ws-fs-newfolder-err { font-size: 11px; color: var(--danger, #e5484d); }

/* Drop-up pickers: the MENU is a flex column capped to the space above its
   anchor — the LIST is the only scrolling part (path header + "Use this
   folder" stay pinned). */
.ws-drop-flex { display: flex; flex-direction: column; }
.ws-drop-flex .ws-drop-body { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.ws-drop-flex .ws-fs-list,
.ws-drop-flex .code-repo-drop-list { flex: 1; min-height: 0; max-height: none; }

/* Scrollbars sit ON the drop's edge — the drop's 5px padding was insetting
   them, which read as a gap right of every picker's scrollbar. */
.code-drop-up .code-repo-drop-list,
.code-drop-up .ws-fs-list,
.code-drop-up .loop-drop-list { margin-right: -5px; padding-right: 5px; scrollbar-gutter: stable; }

/* ── The effort dial (2026-09-20): Claude's grammar — "Effort <level>" with ⓘ,
   Faster … Smarter, a track with one dot per step and a sliding thumb. Ultra
   lights the track with a pixel shimmer that runs right to left. ── */
.code-level-pop { min-width: 250px; padding: 8px 12px 12px; }
.code-level-pop .level-head { text-transform: none; letter-spacing: 0; font-size: 13px; font-weight: 500; color: var(--text-2); border-bottom: 0; padding: 2px 0 8px; margin: 0; }
.code-level-pop .level-name { font-weight: 600; color: var(--text); margin-left: 6px; }
.code-level-pop .level-head.ultra .level-name { color: #a56cf7; }
.code-level-pop .level-help { padding: 0 0 10px; font-size: 12px; color: var(--text-3); }
.level-scale { display: flex; justify-content: space-between; font-size: 12px; color: var(--text-3); margin-bottom: 8px; }
.level-track {
  position: relative; height: 26px; border-radius: 8px;
  background: var(--surface-2, var(--hover)); border: 1px solid var(--border);
  cursor: pointer; outline: none; touch-action: none; user-select: none;
}
.level-track:focus-visible { border-color: var(--accent); }
.level-fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0; border-radius: 8px; background: color-mix(in srgb, var(--text-3) 22%, transparent); pointer-events: none; }
.level-dot { position: absolute; top: 50%; width: 4px; height: 4px; margin-left: -2px; margin-top: -2px; border-radius: 50%; background: var(--border-3, var(--border)); pointer-events: none; }
.level-dot.on { background: var(--text-3); }
.level-thumb {
  position: absolute; top: 3px; bottom: 3px; width: 22px; margin-left: -11px; border-radius: 6px;
  background: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,.35); pointer-events: none;
  transition: left .12s ease;
}
.level-track .level-dot:first-of-type { margin-left: 4px; }
.level-track .level-dot:last-of-type { margin-left: -8px; }
.level-track .level-thumb[style*="left: 0%"] { margin-left: 3px; }
.level-track .level-thumb[style*="left: 100%"] { margin-left: -25px; }
/* Ultra: a purple particle field (his order, 2026-09-20). The ground runs
   from near-black on the far left to Glyphh purple at the thumb; the particles
   ride a pseudo-element masked the same way, so they are bright and dense on
   the right and vanish into the dark on the left, and three dot layers of
   different pitch drift right → left at different speeds. */
.level-track.ultra {
  /* LITERAL purples on purpose: color-mix() is dropped by this Electron, and
     every dropped declaration left the track grey (his report, 2026-09-20). */
  overflow: hidden;
  border-color: rgba(140, 59, 242, 0.65);
  background:
    radial-gradient(70% 140% at 100% 50%, rgba(140, 59, 242, 0.8), rgba(140, 59, 242, 0) 70%),
    linear-gradient(90deg, #120b1c 0%, #241238 40%, #4a1f8e 78%, #7a33d6 100%);
  box-shadow: inset 0 0 16px rgba(140, 59, 242, 0.45), 0 0 12px rgba(140, 59, 242, 0.35);
}
.level-track.ultra::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  /* Three purple dot layers: small bright lilac, medium Glyphh purple, large deep purple. */
  background-image:
    radial-gradient(circle, rgba(214, 190, 255, 0.95) 0 0.7px, rgba(214, 190, 255, 0) 1.2px),
    radial-gradient(circle, #8c3bf2 0 1px, rgba(140, 59, 242, 0) 1.7px),
    radial-gradient(circle, #5a2bb0 0 1.4px, rgba(90, 43, 176, 0) 2.2px);
  background-size: 5px 5px, 9px 9px, 14px 14px;
  background-position: 0 0, 3px 2px, 7px 5px;
  -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgba(0,0,0,.12) 22%, rgba(0,0,0,.55) 55%, #000 100%);
  mask-image: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgba(0,0,0,.12) 22%, rgba(0,0,0,.55) 55%, #000 100%);
  animation: level-ultra-drift 1.6s linear infinite;
}
.level-track.ultra .level-fill { background: transparent; }
.level-track.ultra .level-dot { background: rgba(200, 170, 255, 0.7); opacity: .6; }
.level-track.ultra .level-thumb { background: #fff; box-shadow: 0 0 0 1px rgba(140, 59, 242, 0.6), 0 0 14px rgba(140, 59, 242, 0.9); }
/* Each layer moves a whole number of its own tiles per cycle, so the loop never jumps. */
@keyframes level-ultra-drift {
  from { background-position: 0 0, 3px 2px, 7px 5px; }
  to   { background-position: -10px 0, -15px 2px, -21px 5px; }
}
#code-level-chip.ultra { color: #a56cf7; border-color: rgba(140, 59, 242, 0.65); }
@media (prefers-reduced-motion: reduce) { .level-track.ultra::before { animation: none; } .level-thumb { transition: none; } }

/* Designed monogram tiles — rounded plate, centered mark; the color comes
   inline (brand for household names, deterministic hue otherwise). */
.icon-monogram { display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%; border-radius: inherit; font-weight: 650; }

/* BOOT VEIL: nothing between the splash and the NEW CHAT screen. The wall
   mounts before the landing card does, and that bare-wall paint was the
   "echo command page flash" on every load. The wall's canvas does NOT live
   inside .code-workbench — echo renders in the app layer stitched onto
   <body> — so the veil covers BOTH containers until home.ts lifts it. */
.wb-booting .code-workbench,
.wb-booting #code-wb-applayer,
.wb-booting #code-rail-layer,
.wb-booting #code-agent-layer { visibility: hidden !important; }

/* ── Composer sizing by SURFACE ──────────────────────────────────────────
   The + New Session screen gets the tall inviting box; an AGENT (full screen
   or hosted in a layout) starts at ONE LINE and grows as you type. */
.code-input { min-height: 0; }
body:not(.composer-on-home) .code-input,
.echo-card .code-input,
.ws-rail-slot .code-input { min-height: 38px; }

/* The in-input space pill is gone — the composer input keeps a tight bottom
   padding (the send/stop button sits bottom-right). */
.code-input-wrap .code-input { padding-bottom: 10px; }

/* Folder git state. A repo shows its branch in the normal chip voice; a folder
   with no git reads as an absence, not an error — it is a fine way to start. */
.code-wd-branch.no-git { opacity: 0.62; font-style: italic; }

/* ── The workspace chips (source · folder · git · +) sit ABOVE the input on
   EVERY surface, and compress the way the composer-bar chips do. ── */
/* The row must NEVER clip: every chip in it opens an absolutely-positioned
   drop-up, and a 28px-tall `overflow: hidden` row cut those menus down to an
   invisible strip — the chip read as live, clicked, and nothing appeared.
   Truncation belongs to the chip LABELS below, which own it already. */
.dash-wd-chips, .code-source-slot {
  display: flex; align-items: center; gap: 4px; flex-wrap: nowrap;
  min-width: 0; overflow: visible; margin: 0 0 6px;
}
.dash-wd-chips > *, .code-source-slot > * { min-width: 0; flex: 0 1 auto; }
/* COMPRESSION. These rows live inside layout panels, so a viewport media query
   never fires for them — a narrow panel is narrow while the window is wide.
   Shrinking therefore has to come from the flex box itself: every chip may
   shrink to nothing, its LABEL ellipses, and its icons never give up a pixel. */
.dash-wd-chips .code-wd-btn, .code-source-slot .code-wd-btn,
.dash-wd-chips .cl-runtime-chip, .code-source-slot .cl-runtime-chip,
.dash-wd-chips .cl-runtime-chip-wrap, .code-source-slot .cl-runtime-chip-wrap {
  min-width: 0; overflow: hidden;
}
.dash-wd-chips .cl-runtime-lbl, .code-source-slot .cl-runtime-lbl,
.dash-wd-chips .code-wd-btn span, .code-source-slot .code-wd-btn span {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dash-wd-chips svg, .code-source-slot svg { flex: 0 0 auto; }
/* The chip WRAP must not clip its own drop — only the chip button inside it. */
.dash-wd-chips .cl-runtime-chip-wrap, .code-source-slot .cl-runtime-chip-wrap { overflow: visible; }
.dash-wd-chips .code-wd-btn span, .code-source-slot .cl-runtime-lbl {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 900px) {
  .dash-wd-chips .code-wd-btn span { max-width: 90px; }
  .code-source-slot .cl-runtime-lbl { max-width: 110px; }
}

/* ── Tight-PANEL compression for the source-slot chip row (container-driven).
   The landing/composer chip row lives inside .code-agent (container-name:
   agent), so it must react to the PANEL width, not the viewport. Flex shrink
   already ellipsizes labels; these tiers tighten labels further and, at the
   narrowest widths, let the row SCROLL horizontally rather than crush the
   chips into each other or overrun the composer edge. Icons never disappear. */
@container agent (max-width: 560px) {
  .code-source-slot .code-wd-btn span,
  .code-source-slot .cl-runtime-lbl { max-width: 84px; }
}
@container agent (max-width: 460px) {
  .code-source-slot .code-wd-btn span,
  .code-source-slot .cl-runtime-lbl { max-width: 60px; }
  .code-source-slot { gap: 3px; }
}
@container agent (max-width: 380px) {
  /* Below this the row can no longer fit even sliver labels beside every
     icon, so let it scroll: no clip, no overlap, chips stay tappable. The
     drop-ups are position:absolute against each chipwrap and still escape
     upward (the row scrolls on X only). */
  .code-source-slot {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: visible;
    scrollbar-width: none;
    gap: 3px;
  }
  .code-source-slot::-webkit-scrollbar { height: 0; }
  .code-source-slot > * { flex: 0 0 auto; }
  .code-source-slot .code-wd-btn span,
  .code-source-slot .cl-runtime-lbl { max-width: 44px; }
}

/* The agent's chips row mirrors the landing row: [source] in chat,
   [source][folder][+] in work, [source][folder][git][+] in code. */
.code-source-slot .code-wd-btn,
.code-source-slot .code-icon-btn { flex: 0 0 auto; }

/* A layout-hosted agent's empty thread is the MASCOT + text only — no
   starters, no columns, nothing borrowed from the landing. */
.echo-card .code-thread .dash-landing,
.echo-card .code-thread .dash-starters,
.echo-card .code-thread .dash-two-col,
.ws-rail-slot .code-thread .dash-landing,
.ws-rail-slot .code-thread .dash-starters,
.ws-rail-slot .code-thread .dash-two-col { display: none !important; }

/* Agent header, LEFT group: [+ new] [recents] [⋯] — the same trio on every
   agent view (full screen and layout-hosted), left of the spacer. */
.session-head-actions { display: inline-flex; align-items: center; gap: 2px; margin-left: 6px; }
/* The relocatable session-controls group (recents / + new / ⋯ dev tools) —
   lives in the composer's source slot by default; in a layout it moves into
   .session-head-actions (help/code.ts). Flex either way. */
.code-session-controls { display: inline-flex; align-items: center; gap: 2px; }
.session-head-actions + #code-session-kebab-wrap { margin-left: 0; }
/* The history dropdown hangs off its button in the header's left group. */
.session-head-actions { position: relative; }

/* The Code agent has ONE ⋯: the workbench "More" menu, which now carries the
   session actions. Its own kebab would be a second identical control. */
/* ONE ⋯ per surface. The Code agent's session actions live in the workbench
   "More" menu, so its own kebab hides — but ONLY there: #code-view-more is in
   the DOM on every space (Chat/Work merely hide the toggles), so keying off
   its existence hid the kebab everywhere and Chat/Work lost their menu. */
body[data-session-space="code"] #code-session-kebab-wrap { display: none; }
.code-view-session-actions { border-top: 1px solid var(--border-2); margin-top: 4px; padding-top: 4px; }
.code-view-session-actions .danger { color: var(--danger, #e5484d); }

/* Landing session column: pager under the rows. */
.dash-sessions-pager { display: flex; align-items: center; gap: 6px; justify-content: flex-end; margin-top: 6px; }
.dash-sessions-page-at { font-size: 11px; color: var(--text-3); }

/* Agent header: [+ new] [recents] [⋯] ride the RIGHT edge (they sit after the
   spacer); the title/back stay left. */
.code-agent-head .session-head-actions { margin-left: 0; margin-right: 2px; }
.code-agent-head .code-spacer { flex: 1 1 auto; }

/* Header actions order: [recents] [+] [⋯] — recents first, + right of it, and
   the three dots FAR RIGHT. (The kebab had no order and defaulted to 0, so it
   jumped ahead of both.) */
.session-head-actions { display: inline-flex; flex-direction: row; align-items: center; }
.session-head-actions #code-session-history { order: 1; }
.session-head-actions #code-session-new { order: 2; }
.session-head-actions #code-session-kebab-wrap { order: 3; }

/* Layout editor: the agent tabs at the top — same pill as the new-session
   screen, so "which agent rides this layout" reads identically. */
.layout-space-tabs { display: inline-flex; align-items: center; gap: 2px; padding: 2px;
  margin: 0 0 4px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 9px; }
.layout-space-tabs .code-space-opt { padding: 5px 12px; font-size: 12px; border-radius: 7px;
  border: 0; background: transparent; color: var(--text-3); font-family: inherit; cursor: pointer; }
.layout-space-tabs .code-space-opt:hover { color: var(--text); background: var(--hover); }
.layout-space-tabs .code-space-opt.active { background: var(--accent); color: var(--accent-ink, #fff); }

/* CHAT has no workspace: no folder, no tools — the MODEL and its effort stay,
   and the source chip stays as the inert "Cloud" label. */
body[data-session-space="chat"] #code-plus-wrap { display: none !important; }


.app-rail-tile .tile-name { color: var(--text-2); }
.app-rail-tile:hover .tile-name { color: var(--text); }

/* The wall's Chat/Work/Code agent tabs were removed — one session type now. */
/* Keep the drip button to the RIGHT of the search on one row (never wrap it
   below); the search itself shrinks in tight panels via its flex-basis. */
.echo-topbar-stacked { max-width: 92%; }

/* The rail's mark is the HOME button. */
.app-rail-mark-btn { border: 0; background: none; padding: 0; cursor: pointer; line-height: 0; }
.app-rail-mark-btn:hover { opacity: 0.85; }

/* HOME leads the rail's app list and is never draggable/paged. */
.app-rail-tile-home { order: -1; }
.app-rail-tile-home img { width: 22px; height: 22px; object-fit: contain; }

/* ── Releases workbench view (ws-rel-*) — release management for built apps ── */
.ws-rel-body { display: flex; flex-direction: column; height: 100%; overflow: hidden; }

/* Tasks view — scheduled work at a glance. Rides the ws-rel toolbar voice;
   its own classes carry only card/feed layout (sizes; colors from theme vars). */
.ws-tasks-body { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
.ws-tasks-heading { font-weight: 700; font-size: 12.5px; color: var(--text); }
.ws-tasks-scroll { flex: 1; overflow-y: auto; padding: 10px 32px 24px; }
/* The centered page column — same voice as the section pages (heading +
   .section-desc + a bounded content width). */
.ws-tasks-page { width: 100%; max-width: 880px; margin: 0 auto; display: flex; flex-direction: column; gap: 12px; }
.ws-tasks-title { font-size: 18px; font-weight: 600; color: var(--text); letter-spacing: 0; margin: 14px 0 0; }
.ws-tasks-page > .section-desc { margin: 0 0 4px; }
.ws-tasks-scroll.hidden { display: none; }
.ws-tasks-chartwrap { position: relative; height: 200px; flex: 0 0 auto; border: 1px solid var(--border-2); border-radius: 12px; background: var(--surface-2); padding: 14px 16px 10px; }
.ws-tasks-canvas { width: 100% !important; height: 100% !important; }
.ws-tasks-chartwrap .ws-tasks-refresh { position: absolute; top: 8px; right: 8px; }
/* Under the chart: TWO EQUAL columns — the landing-style prompt starters
   (dash-starter cards, stacked single-file inside their column) beside the
   recent-runs feed. */
.ws-tasks-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: start; }

/* Markdown tables in the thread — themed, compact, wide ones scroll inside
   their own wrapper (the bubble never scrolls horizontally). */
.yo-md-tablewrap { overflow-x: auto; margin: 8px 0; border: 1px solid var(--border-2); border-radius: 10px; }
.yo-md-table { border-collapse: collapse; width: 100%; font-size: 12.5px; }
.yo-md-table th, .yo-md-table td { padding: 7px 12px; text-align: left; border-bottom: 1px solid var(--border-2); vertical-align: top; }
.yo-md-table th { font-weight: 650; color: var(--text); background: var(--surface-3); white-space: nowrap; }
.yo-md-table td { color: var(--text-2, var(--text)); }
.yo-md-table tbody tr:last-child td { border-bottom: none; }
.ws-tasks-col { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.ws-tasks-col .ws-tasks-prompts.dash-starters { grid-template-columns: 1fr; }

.ws-tasks-create input, .ws-tasks-create select {
  width: 100%; box-sizing: border-box; height: 30px;
  background: var(--surface-3); border: 1px solid var(--border-2); border-radius: 8px;
  padding: 0 10px; color: var(--text); font-size: 12px;
}
.ws-tasks-create input:focus, .ws-tasks-create select:focus { border-color: var(--accent); outline: none; }
.ws-tasks-prompts { display: flex; flex-direction: column; gap: 8px; }
/* The cards are .dash-starter — the + New Session landing's own style. Only
   the blurb clamp is local (these prompts run longer than the landing's). */
.ws-tasks-prompts .dash-starter-blurb { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ws-tc-row { display: flex; gap: 8px; }
.ws-tc-row > * { flex: 1 1 0; min-width: 0; }
.ws-tc-note { font-size: 11px; color: var(--text-3); min-height: 14px; }
.ws-tasks-coltitle { font-weight: 700; font-size: 12px; color: var(--text); }
.ws-tasks-alltitle { margin-top: 2px; }
.ws-tasks-recents { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.ws-tasks-recent-list { display: flex; flex-direction: column; gap: 6px; }
.ws-task-recent { display: flex; align-items: center; gap: 8px; border: 1px solid var(--border-2); border-radius: 8px; background: var(--surface-2); padding: 6px 10px; cursor: pointer; font-size: 11.5px; }
.ws-task-recent:hover { border-color: var(--accent); }
.ws-task-recent-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.ws-task-detailwrap { flex: 1; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 8px; }
.ws-task-detailwrap.hidden { display: none; }
.ws-tasks-list { display: flex; flex-direction: column; gap: 8px; }
.ws-task-card {
  border: 1px solid var(--border-2);
  border-radius: 10px;
  background: var(--surface-2);
  padding: 10px 12px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.ws-task-card:hover { border-color: var(--accent); }
.ws-task-card.off { opacity: 0.55; }
.ws-task-head { display: flex; align-items: center; gap: 8px; }
.ws-task-name { font-weight: 600; font-size: 12.5px; color: var(--text); flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-task-chip { flex: 0 0 auto; font-size: 10px; padding: 1px 7px; border-radius: 999px; border: 1px solid var(--border-2); color: var(--text-3); }
.ws-task-chip.ok { color: var(--ok, #3fb96f); border-color: currentColor; }
.ws-task-chip.err { color: var(--danger, #e5534b); border-color: currentColor; }
.ws-task-next { flex: 0 0 auto; font-size: 11px; color: var(--accent); font-variant-numeric: tabular-nums; }
.ws-task-sub { display: flex; align-items: center; gap: 10px; margin-top: 4px; font-size: 11px; color: var(--text-3); min-width: 0; }
.ws-task-sub > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-task-kind { flex: 0 0 auto; text-transform: capitalize; }
.ws-task-cron { margin-left: auto; flex: 0 0 auto; }
.ws-task-detail-head { display: flex; align-items: center; gap: 10px; padding: 2px 2px 8px; }
.ws-task-detail-head .ws-task-name { flex: 1 1 auto; }
.ws-task-runs { display: flex; flex-direction: column; gap: 8px; }
.ws-task-run { border: 1px solid var(--border-2); border-radius: 10px; background: var(--surface-2); padding: 8px 10px; }
.ws-task-run.failed { border-color: color-mix(in srgb, var(--danger, #e5534b) 45%, var(--border-2)); }
.ws-task-run-head { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--text-3); }
.ws-task-run-when { font-variant-numeric: tabular-nums; }
.ws-task-run-dur { margin-left: auto; font-variant-numeric: tabular-nums; }
.ws-task-run-out, .ws-task-run-err {
  margin: 6px 0 0;
  max-height: 260px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 11px;
  line-height: 1.45;
  color: var(--text-2, var(--text));
  background: var(--surface-3);
  border-radius: 8px;
  padding: 8px 10px;
}
.ws-task-run-err { color: var(--danger, #e5534b); }
.ws-task-run-out a { color: var(--accent); }
.ws-rel-toolbar {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; border-bottom: 1px solid var(--border-2);
  flex: 0 0 auto;
}
.ws-rel-app {
  max-width: 45%; min-width: 0; flex: 0 1 auto;
  padding: 4px 8px; font-size: 12.5px;
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--border-2); border-radius: 7px; outline: none;
}
.ws-rel-note { flex: 1; min-width: 0; font-size: 11.5px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-rel-note.err { color: var(--danger); }
/* Buttons are the app-standard .action-btn — the THEME owns their colors;
   only sizing is adjusted for the compact panel. */
.ws-rel-body .action-btn { flex: 0 0 auto; padding: 4px 10px; font-size: 11.5px; }
.ws-rel-body .action-btn:disabled { opacity: 0.55; cursor: default; }
.ws-rel-list { flex: 1; min-height: 0; overflow-y: auto; padding: 6px 10px 10px; }
.ws-rel-empty { padding: 14px 4px; font-size: 12.5px; color: var(--text-3); line-height: 1.55; }
.ws-rel-row { padding: 9px 2px 8px; border-bottom: 1px solid var(--border-2); }
.ws-rel-row:last-child { border-bottom: 0; }
.ws-rel-row-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ws-rel-version { font-size: 13px; font-weight: 600; color: var(--text); }
.ws-rel-badge {
  font-size: 10px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 1.5px 6px; border-radius: 99px;
  background: var(--bg-2); color: var(--text-3); border: 1px solid var(--border-2);
}
.ws-rel-badge.live { background: var(--accent-glow); color: var(--accent-light); border-color: transparent; }
.ws-rel-state { font-size: 10.5px; color: var(--text-3); }
.ws-rel-state.building, .ws-rel-state.pending, .ws-rel-state.uploading { color: var(--accent-light); }
.ws-rel-state.failed { color: var(--danger); }
.ws-rel-date { margin-left: auto; font-size: 11px; color: var(--text-4); flex: 0 0 auto; }
.ws-rel-actions { display: flex; gap: 6px; flex: 0 0 auto; }
.ws-rel-actions .action-btn { padding: 2.5px 8px; font-size: 11px; }
.ws-rel-notes-preview { margin-top: 4px; font-size: 11.5px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-rel-error { margin-top: 4px; font-size: 11px; color: var(--danger); white-space: pre-wrap; word-break: break-word; }
.ws-rel-notes-edit { display: flex; gap: 6px; margin-top: 6px; align-items: flex-start; }
.ws-rel-notes-edit textarea {
  flex: 1; min-width: 0; resize: vertical;
  padding: 6px 8px; font-size: 12px; font-family: var(--font-sans);
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--border-2); border-radius: 7px; outline: none;
}
/* The hosting strip — the Public-hosting tab's essentials in one row. */
.ws-rel-hosting {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 10px; border-bottom: 1px solid var(--border-2);
  flex: 0 0 auto;
}
.ws-rel-host-status { flex: 1; min-width: 0; font-size: 11.5px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-rel-host-status a { color: var(--text-2); }
.ws-rel-host-status a:hover { color: var(--text); }
.ws-rel-access {
  flex: 0 0 auto; padding: 3px 7px; font-size: 11.5px;
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--border-2); border-radius: 7px; outline: none;
}

/* The rail's More fly-out — anchored right of the toggle (navigation.ts). */
.app-rail-more-toggle { opacity: 0.85; }
[data-theme="dark"] .app-rail-more-toggle, [data-theme="modern-dark"] .app-rail-more-toggle { opacity: 0.55; }
.app-rail-more-toggle:hover, .app-rail-more-toggle.open { opacity: 1; }
.rail-more-menu { position: fixed; z-index: 300; display: flex; flex-direction: column; gap: 2px; min-width: 172px; padding: 6px; }
.rail-more-menu .app-rail-nav-item { width: 100%; }

/* ── The agent — the PERMANENT floating bottom composer ──────────────────
   The anchor SYSTEM is gone (2026-08-18): no rail/left/right/none modes, no
   picker, no dock splitter. data-anchor="center" is asserted at boot and is
   the ONLY presentation: the composer floats bottom-center OVER the
   workspace — no background, no full-width bar — and the caret PEEKS the
   live thread as a dialog above it. z-index is explicit because
   container-type:inline-size on .code-agent makes it a stacking context. */
.code-root[data-anchor="center"] { position: relative; }
.code-root[data-anchor="center"] > .code-workbench { flex: 1 1 auto; min-width: 0; }
.code-root[data-anchor="center"] #code-wb-edge { display: none; }
.code-root[data-anchor="center"] > .code-agent {
  /* THE PURGE (2026-09-10): the echo agent is dead — the floating bottom
     composer never renders. The agent shows ONLY when a surface hosts it
     (the Glyphh agent card, a rail seat, a layout's agent cell); the DOM
     stays parked here so every id + listener survives. */
  display: none;
  flex-direction: column;
  position: absolute;
  /* Draggable geometry (his rule, 2026-08-20): X offset + width ride vars —
     drag the top row left/right to move, drag the card's side edges to size. */
  left: calc(50% + var(--echo-agent-x, 0px));
  bottom: 12px;
  transform: translateX(-50%);
  width: min(var(--echo-agent-w, 920px), calc(100% - 24px));
  background: none;
  border: none;
  z-index: 30;
}
/* Hidden, never removed — the ids must survive (listeners live on them). */
.code-root[data-anchor="center"] .code-agent-head { display: none; }
.code-root[data-anchor="center"] > .code-agent > .code-thread { display: none; }
/* A live layout HOSTING the agent removes the center composer — the agent is
   in the layout's cell (the overlay follows its placeholder; a holder-hosted
   agent is not a .code-root child, so this only hides the PARKED composer). */
body.echo-agent-in-layout .code-root[data-anchor="center"] > .code-agent { display: none; }
/* The composer fills the floating box — its 880px cap and side gutters were
   for the full-page column. */
.code-root[data-anchor="center"] .code-composer { max-width: 100%; padding: 6px 4px 8px; }

/* THE INPUT CARD — the composer's one visual object, floating over the wall
   in the dock's own language (translucent surface, blur, soft shadow):
   the textarea and the chip row live INSIDE it; the input itself goes bare. */
.code-input-card {
  display: flex;
  flex-direction: column;
  /* Above the peek thread (z 2): the backdrop-filter makes this card a
     stacking context, so every chip drop-up inside is layered at the CARD's
     level — without this the open thread painted over the model/loop/
     permission menus (his screenshot, 2026-08-19). The card and thread never
     overlap; only the upward-growing menus do. */
  position: relative;
  z-index: 3;
  padding: 4px 10px 8px;
  border: 1px solid var(--border);
  border-radius: 17px;
  background: color-mix(in srgb, var(--surface-2) 82%, transparent);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.18);
  transition: box-shadow 0.3s ease, border-color 0.3s ease;
}
.code-root[data-anchor="center"] .code-input {
  border: none;
  background: none;
  padding: 12px 44px 6px 6px;
  min-height: 48px;
  font-size: 14px;
}
.code-root[data-anchor="center"] .code-input:focus { outline: none; box-shadow: none; }
.code-root[data-anchor="center"] .code-composer-bar { padding: 2px 2px 0; }

/* Source / git / folder — its own quiet row ABOVE the input, left-aligned
   (inside the card, both hosts). */
.code-input-card .code-source-slot {
  display: flex; align-items: center; gap: 4px;
  margin: 0; padding: 6px 4px 0;
  min-width: 0;
  color: var(--text-3);
}

/* The row ABOVE the input card: [drips][recents][+] on the left, then the
   status line — whose caret sits at the far right — filling the rest. */
.code-agent-toprow { display: flex; align-items: center; gap: 2px; padding: 0 6px 4px; }
.code-agent-toprow .code-status-line { flex: 1; width: auto; }

/* TYPING GLOW — the theme's accent breathing around the OUTER ring while
   keys land (the inner cap stays quiet). Pure var(--accent) mixes, so every
   theme owns its own halo. The holder-hosted agent (no pill row) keeps the
   glow on its card via the .ws-agent-holder rule. */
.code-root[data-anchor="center"] > .code-agent .code-composer.typing-glow .code-pill-row {
  animation: composer-glow 2.4s ease-in-out infinite;
}
/* SUBTLE (his order, 2026-09-18): a hairline that breathes, not a halo. The
   ring is thinner and the outer bloom is gone; what is left is close enough to
   the card that it reads as focus rather than a light show. */
@keyframes composer-glow {
  0%, 100% {
    box-shadow:
      0 0 0 1px color-mix(in srgb, var(--accent) 34%, transparent),
      0 0 8px color-mix(in srgb, var(--accent) 12%, transparent);
  }
  50% {
    box-shadow:
      0 0 0 1px color-mix(in srgb, var(--accent) 52%, transparent),
      0 0 12px color-mix(in srgb, var(--accent) 18%, transparent);
  }
}

.code-status-line {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 4px 8px;
  background: none;
  border: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
  color: var(--text-3);
}
.code-status-line[hidden] { display: none; }
.code-status-line:hover { color: var(--text); }
.code-status-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
.code-status-line.is-running { color: var(--text); }
.code-status-line.is-blocked { border-left: 2px solid var(--accent); padding-left: 14px; }

/* The raised wall (⌘⇧Space over a layout/cards) must never sit UNDER the
   layout-docked agent — the holder rides a body-level layer above the
   workbench, so it hides while the wall is lifted. */
body.echo-wall-lifted .ws-agent-holder,
body.echo-wall-lifted .ws-rail-holder { visibility: hidden; pointer-events: none; }
/* A FULLSCREEN card covers every panel — the docked agent included. */
body.echo-card-fullscreen .ws-agent-holder { visibility: hidden; pointer-events: none; }
body.echo-card-fullscreen .code-root[data-anchor="center"] > .code-agent { visibility: hidden; pointer-events: none; }

/* ── Agent OVERLAY + AUTO-HIDE over open apps (his rule, 2026-08-19) ─────────
   With loose app cards open (anything but the bare command center or a
   layout — exactly body.echo-cc-needed), the composer rides ON TOP of the
   web content and HIDES at the page bottom: a 16px sliver stays hoverable,
   and hovering (or keyboard focus, or the open thread panel) slides it up
   over the apps. The workbench's buildBand skips the composer in this state,
   so the cards take the full height beneath it. */
.code-root[data-anchor="center"] > .code-agent { transition: transform 0.24s ease; }
/* NEVER hidden while the echo panel shows (his rule, 2026-08-19): the
   composer tucks to the page bottom when cards fully cover the wall — and
   (2026-08-27) when a LAYOUT without an agent cell owns the surface: the
   composer floats tucked on top instead of reserving a bottom band. A layout
   HOSTING the agent is exempt (echo-agent-in-layout). BOTH states keep the
   translateX(-50%) centering — the base positioning is left:50% + translateX,
   so a Y-only transform here shoved it hard right. */
body.echo-wall-hidden:not(.echo-agent-in-layout) .code-root[data-anchor="center"] > .code-agent {
  transform: translate(-50%, calc(100% - 16px));
}
body.echo-wall-hidden:not(.echo-agent-in-layout) .code-root[data-anchor="center"] > .code-agent:hover,
body.echo-wall-hidden:not(.echo-agent-in-layout) .code-root[data-anchor="center"] > .code-agent:focus-within,
body.echo-wall-hidden:not(.echo-agent-in-layout).peek-open .code-root[data-anchor="center"] > .code-agent,
body.echo-wall-hidden:not(.echo-agent-in-layout).glyphh-ask-pending .code-root[data-anchor="center"] > .code-agent {
  transform: translateX(-50%);
}
/* Tucked: the agent-output row (status line) hides with it — only the
   grabber marks the sliver; summoning brings the row back. */
body.echo-wall-hidden:not(.echo-agent-in-layout) .code-root[data-anchor="center"] > .code-agent:not(:hover):not(:focus-within) .code-agent-toprow {
  opacity: 0;
  transition: opacity 0.18s ease;
}
body.echo-wall-hidden:not(.echo-agent-in-layout).peek-open .code-root[data-anchor="center"] > .code-agent .code-agent-toprow,
body.echo-wall-hidden:not(.echo-agent-in-layout).glyphh-ask-pending .code-root[data-anchor="center"] > .code-agent .code-agent-toprow { opacity: 1; }
/* The grabber — a small bar marking the hidden composer's hover sliver. */
body.echo-wall-hidden:not(.echo-agent-in-layout) .code-root[data-anchor="center"] > .code-agent:not(:hover):not(:focus-within)::after {
  content: "";
  position: absolute;
  top: 4px;
  left: 50%;
  transform: translateX(-50%);
  width: 44px;
  height: 4px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--text-3) 60%, transparent);
}

/* ── The PILL composer (his reference, 2026-08-19: the Gemini bar) ──────────
   Center-anchored only: the card collapses to ONE row — [+] input [mic] [⏎] —
   wearing a multicolor gradient ring, with a SIDE BAND to the right of the
   enter button holding the options caret (expands the full controls) and the
   command-center / reset buttons when panels cover the wall. The holder-hosted
   agent (layout cells) keeps the full arrangement. */
/* TWO EQUAL PILLS (his mock, 2026-08-19): the button pill is the SAME size
   as the input pill, sits UNDER it, shifted right. The gradient ring lives on
   the OUTSIDE of the composite silhouette only; the input's own cap — the
   INTERNAL ring — is a thin gray/white line. */
.code-root[data-anchor="center"] > .code-agent .code-pill-row {
  position: relative;
  /* The stacking order of the agent's own layers (his rule, 2026-08-19):
     chip DROP-UPS must ALWAYS win, so the pill row (their stacking context)
     sits above the ask dock (4), which sits above the thread panel (2). */
  z-index: 5;
  display: flex;
  align-items: stretch;
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface-2) 82%, transparent);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  /* The glow rides the THEME's shadow token — light themes carry a much
     softer value than the old hardcoded dark rgba. */
  box-shadow: 0 8px 26px var(--shadow);
}
.code-root[data-anchor="center"] > .code-agent .code-pill-row:has(.code-input-card.options-open) { border-radius: 24px; }
.code-root[data-anchor="center"] > .code-agent .code-pill-row::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;
  background: linear-gradient(100deg,
    color-mix(in srgb, var(--accent) 82%, #4c8dff),
    #4285f4 30%, #2bbf8f 62%, #f2a83c 94%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  /* Above both pill SURFACES (z-auto positioned) but BELOW every chip menu
     (z 200+): the ring must never cross a drop-up again. */
  z-index: 1;
}
.code-root[data-anchor="center"] > .code-agent .code-input-card {
  /* NO z-index on purpose: a z here makes the card a stacking context that
     CAPS its chip menus under the ring/ask-dock. Paint order comes from DOM
     order + the band being click-transparent instead. */
  position: relative;
  flex: 1;
  min-width: 0;
  /* The INTERNAL ring: thin, gray-white — the gradient belongs to the
     composite's outside edge only (the row's ring). */
  /* Theme-robust internal ring: white-mixed vanished on light themes once
     the shadow stopped faking the seam — mix toward the theme's INK instead. */
  border: 1px solid color-mix(in srgb, var(--text) 26%, var(--border));
  border-radius: 999px;
  padding: 5px 8px;
  /* ONE surface for both sections: the row paints it — the card adds no fill,
     no blur, and NO shadow of its own (it cast a stripe onto the band). */
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}
/* Expanded: the inner ring drops (borderless card inside the outer ring),
   and the side band STAYS PUT — pinned to the bottom at its collapsed height
   instead of stretching up with the card. */
.code-root[data-anchor="center"] > .code-agent .code-input-card.options-open {
  border-radius: 22px;
  border-color: transparent;
}
.code-root[data-anchor="center"] > .code-agent .code-pill-row:has(.code-input-card.options-open) .code-side-band {
  align-self: flex-end;
  min-height: 46px;
}
/* Collapsed (default): just the input row. The caret in the side band brings
   the source row + the chip bar back. */
.code-root[data-anchor="center"] > .code-agent .code-input-card:not(.options-open) .code-source-slot,
.code-root[data-anchor="center"] > .code-agent .code-input-card:not(.options-open) .code-composer-bar { display: none; }
/* The input goes BARE inside the pill — the card is the surface. */
.code-root[data-anchor="center"] > .code-agent .code-input-wrap {
  align-items: center;
  gap: 2px;
  padding-right: 38px;   /* clears the absolute send button */
}
/* Docked (layout-hosted) agent: the mic rides BESIDE the ⏎ on the bottom
   line, never stacked over/under it. */
.ws-agent-holder .code-input-wrap { align-items: flex-end; padding-right: 38px; }
.ws-agent-holder .code-input-wrap #code-mic-wrap { align-self: flex-end; margin-bottom: 3px; }
.ws-agent-holder .code-input-wrap .code-mic-chip { border: none; background: transparent; }

/* Pushes the drips/recents/+/⋮ cluster to the source row's RIGHT end. */
.code-source-slot .code-source-spacer { flex: 1; min-width: 8px; }
/* EXPANDED (his ask, 2026-08-20): the cluster right-aligns to the OUTER
   pill's edge — the card ends where the side band begins, so without this
   the icons stopped a band-width short of the right edge. The band's buttons
   sit pinned at the BOTTOM in this state; the top strip is free air. */
.code-root[data-anchor="center"] > .code-agent .code-input-card.options-open .code-source-slot { margin-right: -49px; }
/* …and the ⏎/stop rides out with the cluster so the column stays aligned. */
.code-root[data-anchor="center"] > .code-agent .code-input-card.options-open .code-input-wrap .code-send { right: -42px; }

/* The ⏎ sits a tad lower in the pill. */
.code-root[data-anchor="center"] > .code-agent .code-input-wrap .code-send { bottom: 4px; }
/* The mic (+ its caret) rides the BOTTOM line with the ⏎/stop button no
   matter how tall the input grows — never centered up the expanded card. */
.code-root[data-anchor="center"] > .code-agent .code-input-wrap #code-mic-wrap {
  align-self: flex-end;
  margin-bottom: 3px;   /* optically level with the absolute ⏎ (bottom 4px) */
}
.code-root[data-anchor="center"] > .code-agent .code-input {
  border: none;
  background: transparent;
  box-shadow: none;
  min-height: 34px;
  padding: 8px 6px;
}
.code-root[data-anchor="center"] > .code-agent .code-input:focus {
  border: none;
  box-shadow: none;
  outline: none;
}
/* + and mic ride IN the row as bare round glyphs. */
.code-root[data-anchor="center"] > .code-agent .code-input-wrap .code-plus-chip {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--text-2);
  font-size: 19px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.code-root[data-anchor="center"] > .code-agent .code-input-wrap .code-mic-chip {
  border: none;
  background: transparent;
  color: var(--text-2);
}
.code-root[data-anchor="center"] > .code-agent .code-input-wrap .code-mic-chip svg {
  width: 17px;
  height: 17px;
}
.code-root[data-anchor="center"] > .code-agent .code-input-wrap .code-plus-chip:hover,
.code-root[data-anchor="center"] > .code-agent .code-input-wrap .code-mic-chip:hover {
  background: var(--hover);
  color: var(--text);
}
/* The side band — ANOTHER input circle (his sketch, 2026-08-19:
   "} ^ ⌘ ↺ )") to the right of the main one: same translucent surface, same
   gradient ring as the input pill, holding caret / command-center / reset. */
.code-side-band { display: none; }
.code-root[data-anchor="center"] > .code-agent .code-side-band {
  position: relative;
  /* Painted after the card (DOM order) but CLICK-TRANSPARENT except its
     buttons — its tucked-under padding must never eat the send button. */
  pointer-events: none;
  display: flex;
  align-items: center;
  align-self: stretch;   /* EXACTLY the input pill's height */
  gap: 2px;
  /* Tucked under the input's cap; the left padding clears the overlap so the
     buttons live in the visible tail. */
  margin-left: -34px;
  padding: 5px 10px 5px 42px;
}
.code-side-band .ws-icon-btn {
  pointer-events: auto;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--text-2);
  cursor: pointer;
  padding: 0;
}
.code-side-band .ws-icon-btn:hover { background: var(--hover); color: var(--text); }
#code-opts-caret svg { transition: transform 0.18s ease; }
.code-agent:has(.code-input-card.options-open) #code-opts-caret svg { transform: rotate(180deg); }
/* CC + reset only while panels cover the wall (the workbench flips the class). */
#code-cc-open, #code-reset-open { display: none; }
body.echo-cc-needed .code-root[data-anchor="center"] > .code-agent #code-cc-open,
body.echo-cc-needed .code-root[data-anchor="center"] > .code-agent #code-reset-open { display: flex; }
body.echo-cc-pinned #code-cc-open { color: var(--accent); }

/* ── Peek ───────────────────────────────────────────────────────────────────
   Repositions the LIVE thread rather than copying it: renderThread() wipes
   #code-thread on every repaint and the streamer writes into that same
   element, so a clone would be stale within a frame. "Last few messages"
   falls out of the existing bottom-pinned scroll plus max-height. */
.code-root[data-anchor="center"].peeking > .code-agent > .code-thread {
  /* Echo Agent transparency (Appearance slider): panel AND text fade as one,
     so the work underneath shows through while the conversation stays legible. */
  opacity: var(--echo-agent-opacity, 1);
  display: block;
  position: absolute;
  /* GEOMETRY IS MEASURED at open time (code-anchor fitPeek): exactly the
     pill's width, bottom edge tucked BEHIND the input card. These are the
     fallbacks for the first frame only. */
  bottom: calc(100% + 2px);
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  /* Clicking the status text opens the FULL agent thread (scrollable), not
     just the last few messages — the bar is a one-line window onto the whole
     conversation. Opening it never closes a panel: it is an OVERLAY dialog. */
  max-height: min(var(--echo-agent-max-h, 76vh), 860px);
  padding: 12px 20px;
  overflow-y: auto;
  /* The pill's gradient ring, worn by the panel too: two-layer background —
     opaque fill in the padding box, the ribbon in the border band. Backgrounds
     paint the element's box, not its scrolled content, so the ring holds while
     the thread scrolls. */
  border: 1.5px solid transparent;
  background:
    linear-gradient(var(--bg), var(--bg)) padding-box,
    linear-gradient(100deg,
      color-mix(in srgb, var(--accent) 82%, #4c8dff),
      #4285f4 30%, #2bbf8f 62%, #f2a83c 94%) border-box;
  /* Rounded crown; the feet are hidden behind the pill it connects to. */
  border-radius: 20px 20px 12px 12px;
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.35);
  z-index: 2;   /* UNDER the input card (z 3) — the pill overlaps the panel's foot */
  animation: peek-connect 0.22s ease;
}
/* The panel emerges FROM the input: it rises the last few px into place.
   Only `from` is declared so opacity settles to the rule's own value (the
   Echo Agent transparency slider), not a hardcoded 1. */
@keyframes peek-connect {
  from { opacity: 0; margin-bottom: -12px; }
}
/* Webview compositing beats every z-index (see the note at .wb-app-layer), so
   an open app panel would paint straight over the peek. Same escape hatch the
   modal path already uses. Deliberate trade-off: app panels blank while
   peeking. */
body[data-glyphh-anchor="center"].peek-open #code-wb-applayer { visibility: hidden !important; }

/* ── Transcript panel (the "thread" workbench slot) ─────────────────────────
   Hosts the LIVE #code-thread (moved, never cloned). Sizing/spacing only —
   the thread keeps its own chrome; colors stay on the existing classes. */
.ws-thread-body { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.ws-thread-body > .code-thread { flex: 1; min-height: 0; overflow-y: auto; padding: 14px 16px; }
/* Peeking while the panel owns the thread flashes the panel instead (the
   thread stays put). One accent outline, briefly. */
.ws-rail-slot.ws-thread-flash { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ── gPoint — Glyphh power points ─────────────────────────────────────────
   Library (cards) → reader (slide rail + stage) → presenter (whole-app
   overlay). Deck iframes are srcdoc documents; the deck scales its own
   1920×1080 stage to whatever box the iframe gives it. */
.ws-gpoint-body { display: flex; flex-direction: column; overflow: hidden; }

.gpoint-lib {
  display: flex; flex-direction: column; gap: 12px;
  padding: 14px; height: 100%; box-sizing: border-box; overflow-y: auto;
}
.gpoint-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 12px; align-content: start;
}
.gpoint-card {
  display: flex; flex-direction: column; gap: 6px; padding: 8px;
  background: var(--surface-3); border: 1px solid var(--border);
  border-radius: 10px; cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.gpoint-card:hover { background: var(--surface-2); border-color: var(--border-3); }
.gpoint-thumb {
  position: relative; aspect-ratio: 16 / 9; border-radius: 6px;
  overflow: hidden; background: #0d0d0f; border: 1px solid var(--border);
}
.gpoint-thumb iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; pointer-events: none; }
.gpoint-thumb-ph { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: var(--text-muted); }
.gpoint-thumb-ph svg { width: 22px; height: 22px; }
.gpoint-card-row { display: flex; align-items: center; gap: 6px; }
.gpoint-card-meta { flex: 1; min-width: 0; text-align: left; }
.gpoint-card-title {
  font-size: 11px; font-weight: 500; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gpoint-card-sub { font-size: 9px; color: var(--text-muted); }
.gpoint-empty { padding: 28px 10px; text-align: center; color: var(--text-2); font-size: 12px; line-height: 1.6; }
.gpoint-menu { min-width: 150px; padding: 5px; }

.gpoint-reader { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
.gpoint-reader-bar {
  display: flex; align-items: center; gap: 8px; flex: none;
  padding: 5px 8px; border-bottom: 1px solid var(--border);
}
.gpoint-reader-title {
  flex: 1; min-width: 0; font-size: 12px; font-weight: 600; color: var(--text);
  background: none; border: 1px solid transparent; border-radius: 5px;
  padding: 2px 6px; font-family: inherit; outline: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gpoint-reader-title:hover { border-color: var(--border); }
.gpoint-reader-title:focus { border-color: var(--accent); }
.gpoint-back {
  display: inline-flex; align-items: center; gap: 3px; flex: none;
  background: none; border: none; cursor: pointer; color: var(--text-2);
  font: inherit; font-size: 12px; font-weight: 500;
  padding: 3px 8px 3px 3px; border-radius: 5px;
}
.gpoint-back:hover { background: var(--hover); color: var(--text); }
.gpoint-back svg { width: 13px; height: 13px; }
.gpoint-reader-count { font-size: 10px; color: var(--text-muted); font-family: var(--font-mono); }
.gpoint-reader-main { flex: 1; display: flex; min-height: 0; }
.gpoint-side {
  flex: 0 0 148px; width: 148px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 16px;
  padding: 12px 10px; border-right: 1px solid var(--border); box-sizing: border-box;
}
.gpoint-side-item {
  position: relative; flex: none; aspect-ratio: 16 / 9;
  border: 1px solid var(--border); border-radius: 6px;
  overflow: hidden; cursor: pointer; background: #0d0d0f;
}
.gpoint-side-item:hover { border-color: var(--border-3); }
.gpoint-side-item.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.gpoint-side-item iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; pointer-events: none; }
.gpoint-side-num {
  position: absolute; left: 4px; bottom: 3px; z-index: 1;
  font-size: 9px; font-family: var(--font-mono); color: rgba(255, 255, 255, 0.8);
  background: rgba(0, 0, 0, 0.55); padding: 1px 5px; border-radius: 999px;
}
.gpoint-stage { flex: 1; min-width: 0; position: relative; background: #000; }
.gpoint-stage iframe.gpoint-frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* Presenter: the deck IS the app until Esc. Sits above every DOM layer;
   BrowserView panels are frozen/hidden by the opener (yo-modal helpers). */
.gpoint-presenter { position: fixed; inset: 0; z-index: 12000; background: #000; }
.gpoint-presenter iframe.gpoint-presenter-frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.gpoint-presenter-hint {
  position: absolute; top: 14px; right: 18px; pointer-events: none;
  font-size: 11px; color: rgba(255, 255, 255, 0.6);
  background: rgba(0, 0, 0, 0.45); padding: 4px 10px; border-radius: 999px;
  transition: opacity 0.6s;
}
.gpoint-presenter-hint.faded { opacity: 0; }

/* ── Workbench dropdown: More ▸ flyout (Releases, gPoint) ──────────────── */
.code-view-menu-sub-wrap { position: relative; }
.code-view-menu-sub-wrap .code-view-menu-more { width: 100%; }
.code-view-menu-sub-caret { margin-left: auto; opacity: 0.55; }
.code-view-submenu {
  position: absolute; top: -5px; right: calc(100% + 2px); z-index: 201;
  min-width: 150px; padding: 4px; display: none;
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}
.code-view-menu-sub-wrap:hover .code-view-submenu,
.code-view-menu-sub-wrap:focus-within .code-view-submenu { display: block; }

.gpoint-err { display: inline-block; margin-top: 8px; font-family: var(--font-mono); font-size: 10px; color: var(--ws-diff-del); word-break: break-all; }

/* Slides reader: draggable rail — the grip sits between rail and stage (a
   sibling, not a child, so it never scrolls with the thumbs). Thumbs are
   width-driven aspect boxes, so the drag scales them live. */
.gpoint-side-resize {
  flex: 0 0 5px; cursor: col-resize; z-index: 2;
  background: transparent; transition: background 0.15s;
}
.gpoint-side-resize:hover, body.gpoint-col-drag .gpoint-side-resize { background: var(--accent); opacity: 0.5; }
body.gpoint-col-drag { cursor: col-resize; user-select: none; }
body.gpoint-col-drag .gpoint-stage iframe { pointer-events: none; }

/* Slides reader: the Present control is the app-standard primary button —
   themes own its colors; only its SIZE is scoped to the compact reader bar. */
.gpoint-reader-bar .action-btn.primary { height: 24px; padding: 3px 12px; font-size: 11.5px; flex: none; }
.gpoint-reader-bar .action-btn.primary svg { width: 11px; height: 11px; }

/* Slides reader: hidden slides stay in the rail (dimmed, dashed, badged) so
   they can be unhidden — the presenter simply never sees them. */
.gpoint-side-item.gpoint-hidden { border-style: dashed; }
.gpoint-side-item.gpoint-hidden iframe { opacity: 0.3; }
.gpoint-hidden-badge {
  position: absolute; right: 4px; top: 3px; z-index: 1;
  font-size: 9px; font-family: var(--font-mono); color: rgba(255, 255, 255, 0.75);
  background: rgba(0, 0, 0, 0.55); padding: 1px 6px; border-radius: 999px;
}

/* ── Glyphh Docs — the paper panel ───────────────────────────────────────── */
.ws-gdoc-body { display: flex; flex-direction: column; overflow: hidden; }
.gdoc-lib { display: flex; flex-direction: column; gap: 10px; padding: 14px; height: 100%; box-sizing: border-box; overflow-y: auto; }
.gdoc-rows { display: flex; flex-direction: column; gap: 2px; }
.gdoc-row {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border-radius: 8px; cursor: pointer; border: 1px solid transparent;
}
.gdoc-row:hover { background: var(--surface-2); border-color: var(--border); }
.gdoc-row-icon svg { width: 16px; height: 16px; display: block; color: var(--text-2); }
.gdoc-row-title { flex: 1; min-width: 0; font-size: 12.5px; font-weight: 500; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gdoc-row-file { font-size: 10px; color: var(--text-muted); font-family: var(--font-mono); }
.gdoc-row-date { font-size: 10.5px; color: var(--text-3); width: 52px; text-align: right; }
.gdoc-empty { padding: 28px 10px; text-align: center; color: var(--text-2); font-size: 12px; line-height: 1.6; }
.gdoc-menu { min-width: 190px; padding: 5px; }

.gdoc-doc { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
.gdoc-bar { display: flex; align-items: center; gap: 8px; flex: none; padding: 5px 8px; border-bottom: 1px solid var(--border); }
.gdoc-bar .action-btn { height: 24px; padding: 3px 10px; font-size: 11.5px; flex: none; }

/* Preview | Editor mode tabs — the standard tab chips, centered in the bar. */
.gdoc-mode-tabs { display: flex; gap: 2px; flex: none; margin: 0 auto; }
.gdoc-save-state { flex: none; font-size: 11px; }
/* Editor mode fills the pane; Monaco (or the textarea fallback) owns it. */
.gdoc-editor-host { flex: 1; min-height: 0; min-width: 0; display: flex; }
.gdoc-editor-host > * { flex: 1; min-height: 0; min-width: 0; }
.gdoc-raw-ta {
  resize: none; border: none; outline: none; background: var(--surface);
  color: var(--text); font: 13px/1.6 ui-monospace, monospace; padding: 14px 16px;
}

.gdoc-main { flex: 1; display: flex; min-height: 0; }
.gdoc-toc {
  flex: 0 0 180px; overflow-y: auto; padding: 14px 8px;
  display: flex; flex-direction: column; gap: 2px; border-right: 1px solid var(--border);
}
.gdoc-toc.hidden { display: none; }
.gdoc-toc-item {
  background: none; border: none; cursor: pointer; text-align: left;
  font: inherit; font-size: 11.5px; color: var(--text-2);
  padding: 4px 8px; border-radius: 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gdoc-toc-item:hover { background: var(--hover); color: var(--text); }
.gdoc-toc-item.lvl2 { padding-left: 20px; }
.gdoc-toc-item.lvl3 { padding-left: 32px; font-size: 11px; }
.gdoc-scroll { flex: 1; min-width: 0; overflow-y: auto; padding: 22px; background: var(--surface); }
/* The paper FOLLOWS THE THEME: a dark theme reads as dark paper, a light one
   as white — everything keys off the theme vars, nothing is hardcoded. */
.gdoc-paper {
  max-width: 760px; margin: 0 auto;
  background: var(--surface-2, var(--surface));
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 3px; box-shadow: 0 2px 14px rgba(0, 0, 0, 0.25);
  padding: 64px 72px; min-height: 100%; box-sizing: border-box;
  font-family: Georgia, 'Times New Roman', serif; font-size: 14.5px; line-height: 1.65;
}
.gdoc-paper h1, .gdoc-paper h2, .gdoc-paper h3, .gdoc-paper h4 { font-family: Inter, -apple-system, system-ui, sans-serif; color: var(--text); line-height: 1.25; }
.gdoc-paper a { color: var(--accent); }
.gdoc-paper table { border-collapse: collapse; width: 100%; }
.gdoc-paper th, .gdoc-paper td { border: 1px solid var(--border-2); padding: 6px 9px; text-align: left; }
.gdoc-paper pre { background: var(--bg); border-radius: 6px; padding: 10px 12px; overflow-x: auto; font-size: 12.5px; }
.gdoc-paper code { font-family: ui-monospace, monospace; font-size: 0.92em; }
.gdoc-paper blockquote { border-left: 3px solid var(--border-2); margin-left: 0; padding-left: 14px; color: var(--text-3); }
/* Design-system / theme overrides — inert until a :::glyphh directive sets the
   --doc-* vars; fallbacks reproduce the classic paper so unset docs are unchanged. */
.gdoc-paper { max-width: var(--doc-maxw, 760px); font-family: var(--doc-font-body, Georgia, 'Times New Roman', serif); color: var(--doc-fg, var(--text)); }
.gdoc-paper h1, .gdoc-paper h2, .gdoc-paper h3, .gdoc-paper h4 { font-family: var(--doc-font-head, Inter, -apple-system, system-ui, sans-serif); }
.gdoc-paper a, .gdoc-paper .yo-md-link { color: var(--doc-accent, var(--accent)); }
/* Structured blocks: callouts + columns. */
.yo-md-callout { display: flex; flex-direction: column; gap: 4px; margin: 14px 0; padding: 12px 16px; border-radius: 8px; border-left: 4px solid var(--doc-accent, var(--accent)); background: color-mix(in srgb, var(--doc-accent, var(--accent)) 8%, transparent); }
.yo-md-callout-t { font-weight: 700; font-size: 0.95em; }
.yo-md-callout-b > :first-child { margin-top: 0; } .yo-md-callout-b > :last-child { margin-bottom: 0; }
.yo-md-callout-tip { border-left-color: #22c55e; background: color-mix(in srgb, #22c55e 9%, transparent); }
.yo-md-callout-warning { border-left-color: #f59e0b; background: color-mix(in srgb, #f59e0b 10%, transparent); }
.yo-md-callout-info { border-left-color: #38bdf8; background: color-mix(in srgb, #38bdf8 9%, transparent); }
.yo-md-columns { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin: 14px 0; }
.yo-md-columns .yo-md-col > :first-child { margin-top: 0; }
@media (max-width: 620px) { .yo-md-columns { grid-template-columns: 1fr; } }
.gdoc-block { position: relative; border-radius: 6px; }
.gdoc-block:hover { outline: 1px dashed var(--border-2); outline-offset: 6px; }
.gdoc-block-edit, .gdoc-block-comment {
  position: absolute; top: -4px; opacity: 0;
  color: var(--text-3); transition: opacity 0.15s;
}
.gdoc-block-edit { right: -46px; }
.gdoc-block-comment { right: -78px; }
.gdoc-block:hover .gdoc-block-edit, .gdoc-block:hover .gdoc-block-comment { opacity: 1; }
.gdoc-comment-box { display: flex; gap: 8px; margin: 8px 0; align-items: center; }
.gdoc-comment-input {
  flex: 1; min-width: 0; font: inherit; font-size: 12.5px;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--accent); border-radius: 7px; padding: 6px 10px;
}
.gdoc-comment-box .action-btn { height: 26px; padding: 3px 12px; font-size: 12px; }
.gdoc-editor { display: flex; flex-direction: column; gap: 8px; margin: 8px 0; }
.gdoc-editor-ta {
  width: 100%; box-sizing: border-box; resize: vertical;
  font-family: ui-monospace, monospace; font-size: 12.5px; line-height: 1.55;
  background: var(--bg); color: var(--text); border: 1px solid var(--border-2); border-radius: 6px; padding: 10px 12px;
}
.gdoc-editor-bar { display: flex; gap: 8px; }
.gdoc-editor-bar .action-btn { height: 26px; padding: 3px 14px; font-size: 12px; }

.gdoc-review { flex: none; border-bottom: 1px solid var(--border); padding: 6px 10px; display: flex; flex-direction: column; gap: 8px; max-height: 45%; overflow-y: auto; }
.gdoc-review-toggle {
  background: none; border: none; cursor: pointer; text-align: left;
  font: inherit; font-size: 11.5px; font-weight: 600; color: var(--accent); padding: 2px 2px;
}
.gdoc-sug { border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; display: flex; flex-direction: column; gap: 6px; background: var(--surface-2); }
.gdoc-sug-head { display: flex; gap: 8px; align-items: baseline; }
.gdoc-sug-sec { font-size: 11px; font-weight: 600; color: var(--text); }
.gdoc-sug-note { font-size: 11px; color: var(--text-2); }
.gdoc-sug-before, .gdoc-sug-after {
  margin: 0; font-family: ui-monospace, monospace; font-size: 11px; line-height: 1.5;
  padding: 6px 8px; border-radius: 6px; white-space: pre-wrap; word-break: break-word;
}
.gdoc-sug-before { background: rgba(212, 74, 74, 0.12); color: var(--ws-diff-del); text-decoration: line-through; }
.gdoc-sug-after { background: rgba(79, 174, 99, 0.12); color: var(--ws-diff-add); }
.gdoc-sug-actions { display: flex; gap: 8px; }
.gdoc-sug-actions .action-btn { height: 24px; padding: 3px 12px; font-size: 11.5px; }

/* ── Glyphh Drive ────────────────────────────────────────────────────────── */
.ws-gdrive-body { display: flex; flex-direction: column; overflow: hidden; }
.gdrive { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
.gdrive-newfolder-input {
  margin: 2px 6px 6px; background: var(--surface-2); color: var(--text);
  border: 1px solid var(--accent); border-radius: 6px; padding: 4px 8px;
  font: inherit; font-size: 12px; outline: none;
}
/* Drive drag-and-drop: the dragged card dims; a hovered folder target rings. */
.ws-term-cloud-note {
  display: flex; align-items: center; justify-content: center; height: 100%;
  padding: 24px; text-align: center; color: var(--text-3); font-size: 13px;
}
.gdrive-dragging { opacity: 0.45; }
.gdrive-droptarget { box-shadow: 0 0 0 2px var(--accent) !important; border-radius: 10px; }

.gdrive-card {
  display: flex; flex-direction: column; gap: 6px; padding: 12px;
  background: var(--surface-3); border: 1px solid var(--border);
  border-radius: 10px; cursor: pointer; position: relative;
  transition: background 0.15s, border-color 0.15s;
}
.gdrive-card:hover { background: var(--surface-2); border-color: var(--border-3); }
.gdrive-card-ic svg { width: 20px; height: 20px; display: block; color: var(--text-2); }
.gdrive-card-title { font-size: 12px; font-weight: 500; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gdrive-card-meta { font-size: 10px; color: var(--text-muted); }
.gdrive-card-kebab { position: absolute; top: 8px; right: 6px; }
.gdrive-menu { min-width: 170px; padding: 5px; max-height: 50vh; overflow-y: auto; }

/* ── Glyphh Office — the shared Apps-root toolbar + card grid ────────────── */
.office-toolbar { display: flex; align-items: center; gap: 8px; flex: none; }
.gdrive .office-toolbar { padding: 8px 10px; border-bottom: 1px solid var(--border); }
.office-search {
  flex: 1; min-width: 0; background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); border-radius: 7px; padding: 5px 10px;
  font: inherit; font-size: 12px; outline: none;
}
.office-search:focus { border-color: var(--accent); }
.office-toolbar .action-btn.primary { height: 26px; padding: 3px 12px; font-size: 11.5px; flex: none; }
.office-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 10px; align-content: start;
}

/* Drive — Google-Drive shape: crumbs, Recents strip, folder cards, files. */
.gdrive-crumbs { display: flex; align-items: center; gap: 4px; flex: none; padding: 8px 12px 0; }
.gdrive-crumb {
  background: none; border: none; cursor: pointer; font: inherit;
  font-size: 12px; color: var(--text-2); padding: 2px 6px; border-radius: 6px;
}
.gdrive-crumb:hover { background: var(--hover); color: var(--text); }
.gdrive-crumb.current { color: var(--text); font-weight: 600; cursor: default; }
.gdrive-crumb.current:hover { background: none; }
.gdrive-crumb-sep { color: var(--text-muted); font-size: 12px; }
.gdrive-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 18px; }
.gdrive-section { display: flex; flex-direction: column; gap: 8px; }
.gdrive-section-title { font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-3); }
.gdrive-recents {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 10px; align-content: start;
}
.gdrive-folder-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 10px; align-content: start;
}
.gdrive-foldercard {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  background: var(--surface-3); border: 1px solid var(--border);
  border-radius: 10px; cursor: pointer; position: relative;
  transition: background 0.15s, border-color 0.15s;
}
.gdrive-foldercard:hover { background: var(--surface-2); border-color: var(--border-3); }
.gdrive-foldercard-ic svg { width: 18px; height: 18px; display: block; color: var(--text-2); }
.gdrive-foldercard-name { flex: 1; min-width: 0; font-size: 12px; font-weight: 500; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gdrive-foldercard .gdrive-card-kebab { position: static; }
.gdrive-files {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 10px; align-content: start;
}

/* New header/bar icons missed the per-class svg sizing the slot header uses
   (.slot-close/.slot-maximize) — unsized SVGs clip to slivers ("purple bars"). */
.slot-popout svg, .slot-present svg, .echo-card-popout svg, .gpoint-pdf svg,
.office-refresh svg, .gpoint-back svg, .gdoc-back svg, .gdrive-card-kebab svg,
.office-card-kebab svg, .gpoint-kebab svg, .gdoc-row-kebab svg, .gpoint-refresh svg {
  width: 13px; height: 13px; display: block;
}

/* Drive file cards carry the same previews the libraries do. */
.gdrive-card-row { display: flex; align-items: center; gap: 6px; }
.gdrive-card-row .gdrive-card-title { flex: 1; min-width: 0; }
.gdrive-card .gdrive-card-kebab { position: static; }
.gdrive-docthumb {
  position: absolute; inset: 0; background: #ffffff; overflow: hidden;
}
.gdrive-docthumb-inner {
  width: 300%; transform: scale(0.3333); transform-origin: top left;
  padding: 26px 30px; box-sizing: border-box;
  font-family: Georgia, 'Times New Roman', serif; font-size: 14px; line-height: 1.6; color: #1a1a1e;
  pointer-events: none;
}
.gdrive-docthumb-inner h1, .gdrive-docthumb-inner h2, .gdrive-docthumb-inner h3 {
  font-family: Inter, -apple-system, system-ui, sans-serif; color: #111;
}

/* Drive: collapsible folder rail + list view + shared pager. */
.gdrive-body { flex: 1; display: flex; min-height: 0; }
.gdrive-rail {
  flex: 0 0 190px; overflow-y: auto; padding: 10px 6px;
  display: flex; flex-direction: column; gap: 1px; border-right: 1px solid var(--border);
}
.gdrive-rail.hidden { display: none; }
.gdrive-railrow {
  display: flex; align-items: center; gap: 8px;
  background: none; border: none; cursor: pointer; text-align: left;
  font: inherit; font-size: 12px; color: var(--text-2);
  padding: 5px 10px; border-radius: 7px;
}
.gdrive-railrow:hover { background: var(--hover); color: var(--text); }
.gdrive-railrow.active { background: var(--surface-2); color: var(--text); }
.gdrive-railrow-ic svg { width: 14px; height: 14px; display: block; }
.gdrive-railrow-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gdrive-rail-toggle.active { color: var(--accent); }
.gdrive-rail-toggle svg { width: 14px; height: 14px; }
.gdrive-lib-head {
  margin-top: 12px; padding: 4px 10px 2px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-3);
}
.gdrive-libcard .gdrive-thumb-img { background-size: cover; background-position: center; }
.gdrive-libcard .gdrive-thumb-img .gpoint-thumb-ph { display: none; }
.gdrive-libcard .gpoint-thumb-ph svg { width: 26px; height: 26px; color: var(--text-3); }
.gdrive-section-head { display: flex; align-items: baseline; gap: 10px; }
.gdrive-section-head .gdrive-section-title { flex: 1; }
.gdrive-viewall {
  background: none; border: none; cursor: pointer; font: inherit;
  font-size: 11px; font-weight: 600; color: var(--accent); padding: 0 2px;
}
.gdrive-viewall:hover { text-decoration: underline; }
.gdrive-list { display: flex; flex-direction: column; gap: 2px; }
.gdrive-listrow {
  display: flex; align-items: center; gap: 10px; padding: 7px 10px;
  border-radius: 8px; cursor: pointer; border: 1px solid transparent;
}
.gdrive-listrow:hover { background: var(--surface-2); border-color: var(--border); }
.gdrive-listrow-ic svg { width: 15px; height: 15px; display: block; color: var(--text-2); }
.gdrive-listrow-title { flex: 1; min-width: 0; font-size: 12.5px; font-weight: 500; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gdrive-listrow-kind { font-size: 10.5px; color: var(--text-3); width: 44px; }
.gdrive-listrow-size { font-size: 10.5px; color: var(--text-muted); width: 52px; text-align: right; }
.gdrive-listrow-date { font-size: 10.5px; color: var(--text-3); width: 52px; text-align: right; }
.office-pager { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 8px 0 2px; }
.office-pager-btn { height: 24px; padding: 3px 12px; font-size: 12px; }
.office-pager-label { font-size: 11px; color: var(--text-3); font-family: var(--font-mono); }

/* ── Glyphh Sheets ───────────────────────────────────────────────────────── */
.ws-gsheet-body { display: flex; flex-direction: column; overflow: hidden; }
.gsheet { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
.gsheet-tabs { display: flex; gap: 2px; flex: none; padding: 4px 10px 0; border-bottom: 1px solid var(--border); }
.gsheet-tab {
  background: none; border: 1px solid transparent; border-bottom: none; cursor: pointer;
  font: inherit; font-size: 11.5px; color: var(--text-2);
  padding: 4px 12px; border-radius: 7px 7px 0 0;
}
.gsheet-tab.active { background: var(--surface-2); border-color: var(--border); color: var(--text); }
.gsheet-scroll { flex: 1; min-height: 0; overflow: auto; }
.gsheet-table { border-collapse: collapse; width: max-content; min-width: 100%; font-size: 12px; }
.gsheet-table thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface-2); color: var(--text);
  font-weight: 600; text-align: left; padding: 6px 10px;
  border: 1px solid var(--border); cursor: pointer; white-space: nowrap;
}
.gsheet-table thead th:hover { background: var(--hover); }
.gsheet-corner { width: 34px; cursor: default !important; }
.gsheet-ai { margin-left: 6px; color: var(--accent); }
.gsheet-rownum {
  background: var(--surface-2); color: var(--text-3); text-align: right;
  font-family: var(--font-mono); font-size: 10px; padding: 4px 6px;
  border: 1px solid var(--border); user-select: none;
}
.gsheet-table td { border: 1px solid var(--border); padding: 4px 10px; color: var(--text); min-width: 80px; max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: cell; }
.gsheet-table td.gsheet-num { text-align: right; font-variant-numeric: tabular-nums; }
.gsheet-table td.gsheet-formula { color: var(--accent); }
.gsheet-cell-input {
  width: 100%; box-sizing: border-box; background: var(--surface); color: var(--text);
  border: 1px solid var(--accent); border-radius: 3px; padding: 2px 6px;
  font: inherit; outline: none;
}
.gsheet-foot { flex: none; }
.gdoc-bar .action-btn { height: 24px; padding: 3px 10px; font-size: 11.5px; flex: none; }
.gsheet-menu { min-width: 150px; padding: 5px; }
.gsheet-thumbbox { position: absolute; inset: 0; background: #ffffff; overflow: hidden; padding: 8px; }
.gsheet-thumbbox table { border-collapse: collapse; font-size: 7px; width: 100%; }
.gsheet-thumbbox th { background: #eceef2; color: #333; font-weight: 600; text-align: left; }
.gsheet-thumbbox th, .gsheet-thumbbox td { border: 1px solid #d5d7dd; padding: 2px 4px; color: #222; overflow: hidden; white-space: nowrap; max-width: 40px; text-overflow: ellipsis; }

/* Sheets header: the sort affordance is VISIBLE — ↕ on every column, accent
   ▲/▼ on the sorted one. */
.gsheet-sort { margin-left: 7px; font-size: 9px; color: var(--text-3); opacity: 0.45; }
.gsheet-table thead th:hover .gsheet-sort { opacity: 0.9; }
.gsheet-sort.active { color: var(--accent); opacity: 1; }
.gsheet-table thead th .gsheet-cell-input { min-width: 80px; }

/* Sheets v2: Fx bar, coordinate letters, selection, grips, stats footer. */
.gsheet-fx { display: flex; align-items: center; gap: 8px; flex: none; padding: 4px 10px; border-bottom: 1px solid var(--border); }
.gsheet-fx-addr {
  min-width: 44px; text-align: center; font-family: var(--font-mono); font-size: 11px;
  color: var(--text-2); background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 6px; padding: 3px 6px;
}
.gsheet-fx-label { font-size: 11px; font-style: italic; color: var(--accent); font-weight: 700; }
.gsheet-fx-input {
  flex: 1; min-width: 0; background: none; color: var(--text);
  border: 1px solid transparent; border-radius: 6px; padding: 3px 8px;
  font-family: var(--font-mono); font-size: 12px; outline: none;
}
.gsheet-fx-input:hover { border-color: var(--border); }
.gsheet-fx-input:focus { border-color: var(--accent); }
.gsheet-letters th {
  position: sticky; top: 0; z-index: 3;
  background: var(--surface); color: var(--text-3);
  font-family: var(--font-mono); font-size: 10px; font-weight: 500; text-align: center;
  padding: 2px 4px; border: 1px solid var(--border); cursor: pointer; user-select: none;
  position: sticky;
}
.gsheet-letters th:hover { color: var(--accent); }
.gsheet-letter { position: relative; }
.gsheet-colgrip {
  position: absolute; top: 0; right: -3px; width: 6px; height: 100%;
  cursor: col-resize; z-index: 4;
}
.gsheet-colgrip:hover { background: var(--accent); opacity: 0.5; }
.gsheet-table thead .gsheet-letters th { top: 0; }
.gsheet-table thead tr + tr th { top: 21px; }
.gsheet-rownum { position: relative; cursor: pointer; }
.gsheet-rownum:hover { color: var(--accent); }
.gsheet-rowgrip {
  position: absolute; left: 0; bottom: -3px; width: 100%; height: 6px;
  cursor: row-resize; z-index: 2;
}
.gsheet-rowgrip:hover { background: var(--accent); opacity: 0.5; }
.gsheet-table td.sel { background: rgba(175, 95, 255, 0.14); }
.gsheet-table td.sel-anchor { outline: 2px solid var(--accent); outline-offset: -2px; background: rgba(175, 95, 255, 0.05); }
.gsheet-scroll:focus { outline: none; }
.gsheet-foot { display: flex; align-items: center; gap: 12px; padding: 0 12px; }
.gsheet-stats { flex: 1; font-size: 11px; color: var(--text-2); font-family: var(--font-mono); padding: 6px 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gsheet-foot-pager .office-pager { padding: 4px 0; }
/* Read-only charts strip below the grid (authored via add_chart). */
.gsheet-charts { flex: none; display: none; gap: 16px; flex-wrap: wrap; padding: 12px; overflow-x: auto; border-top: 1px solid var(--border-1); }
.gsheet-charts.has { display: flex; }
.gsheet-chart { flex: 0 0 auto; width: 360px; background: var(--surface-2, rgba(255,255,255,.02)); border: 1px solid var(--border-1); border-radius: 10px; padding: 12px; }
.gsheet-chart-t { font-size: 12px; font-weight: 600; color: var(--text-1); margin-bottom: 6px; }
.gsheet-chart-empty { font-size: 11px; color: var(--text-2); padding: 20px; text-align: center; }

/* ════ GLYPHH DESIGN panel — library + the shots.so-shaped studio.
   Chrome = workbench theme vars ONLY; the design paints inside the shot. ════ */

.ws-gdesign-body { display: flex; flex-direction: column; overflow: hidden; }

/* — library thumbnails — */
.gdz-thumb {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  border-radius: inherit;
}
.gdz-thumb-ag { font-size: 34px; line-height: 1; text-shadow: 0 2px 12px rgba(0,0,0,0.35); }
.gdz-thumb-row { display: flex; gap: 5px; }
.gdz-thumb-row span {
  width: 14px; height: 14px; border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.55);
}

/* — studio frame — */
.gdz-studio { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.gdz-topbar {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 8px 10px; border-bottom: 1px solid var(--border);
}
.gdz-name {
  flex: 1; min-width: 0;
  background: none; border: 1px solid transparent; border-radius: 8px;
  color: var(--text); font: inherit; font-weight: 650; padding: 4px 8px;
}
.gdz-name:hover { border-color: var(--border); }
.gdz-name:focus { border-color: var(--accent); outline: none; background: var(--surface); }
.gdz-savestate { flex: none; font-size: 11px; color: var(--text-3); min-width: 52px; text-align: right; }

.gdz-split { display: flex; flex: 1; min-height: 0; }

/* — the stage: soft dotted backdrop, the shot floats center — */
.gdz-stage {
  flex: 1; min-width: 0; overflow: auto;
  display: flex; align-items: center; justify-content: center;
  padding: 26px;
  background:
    radial-gradient(circle at 1px 1px, var(--border) 1px, transparent 1.5px) 0 0 / 22px 22px,
    var(--bg);
}
.gdz-shot {
  position: relative;
  width: min(560px, 100%);
  aspect-ratio: 4 / 3;
  border-radius: 22px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.45);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  transition: background 200ms ease;
}
.gdz-card {
  width: 68%;
  padding: 26px 28px;
  display: flex; flex-direction: column; gap: 10px;
}
.gdz-card-top { display: flex; gap: 6px; margin-bottom: 2px; }
.gdz-dot { width: 9px; height: 9px; border-radius: 50%; }
.gdz-kicker { font-size: 10px; letter-spacing: 0.18em; }
.gdz-h { margin: 0; font-size: 24px; line-height: 1.15; }
.gdz-p { margin: 0; font-size: 12.5px; line-height: 1.55; }
.gdz-btns { display: flex; gap: 8px; margin-top: 4px; }
.gdz-btn-primary, .gdz-btn-ghost {
  font-size: 12px; font-weight: 600; padding: 7px 14px;
  border: none; background: none; cursor: default;
}
.gdz-swatches { display: flex; gap: 6px; margin-top: 8px; }
.gdz-swatch { width: 18px; height: 18px; border-radius: 6px; border: 1px solid rgba(255,255,255,0.35); }
.gdz-specimen {
  position: absolute; right: 5%; bottom: 6%;
  padding: 10px 14px;
  display: flex; align-items: baseline; gap: 10px;
  backdrop-filter: blur(6px);
}
.gdz-spec-display { font-size: 30px; line-height: 1; }
.gdz-spec-meta { font-size: 10.5px; }

/* — control rail — */
.gdz-rail {
  flex: none; width: 288px; overflow-y: auto;
  border-left: 1px solid var(--border);
  background: var(--surface);
}
.gdz-sec { border-bottom: 1px solid var(--border); }
.gdz-sec > summary {
  list-style: none; cursor: pointer; user-select: none;
  padding: 10px 14px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-2);
}
.gdz-sec > summary::-webkit-details-marker { display: none; }
.gdz-sec > summary::before { content: "▸ "; color: var(--text-3); }
.gdz-sec[open] > summary::before { content: "▾ "; }
.gdz-sec-body { padding: 2px 14px 14px; display: flex; flex-direction: column; gap: 8px; }

.gdz-row { display: flex; align-items: center; gap: 8px; }
.gdz-row-label { flex: none; width: 84px; font-size: 12px; color: var(--text-2); }
.gdz-row.unset .gdz-color { opacity: 0.25; }
.gdz-color {
  flex: none; width: 26px; height: 26px; padding: 0;
  border: 1px solid var(--border-2); border-radius: 7px; background: none; cursor: pointer;
}
.gdz-color::-webkit-color-swatch-wrapper { padding: 2px; }
.gdz-color::-webkit-color-swatch { border: none; border-radius: 5px; }
.gdz-hex, .gdz-font, .gdz-tagline, .gdz-pal-name, .gdz-pal-role, .gdz-chip-input {
  flex: 1; min-width: 0;
  background: var(--bg); border: 1px solid var(--border-2); border-radius: 7px;
  color: var(--text); font-size: 12px; padding: 5px 8px;
}
.gdz-hex:focus, .gdz-font:focus, .gdz-tagline:focus, .gdz-pal-name:focus, .gdz-pal-role:focus, .gdz-chip-input:focus {
  border-color: var(--accent); outline: none;
}
.gdz-hex { max-width: 78px; font-family: var(--mono, monospace); }
.gdz-range { flex: 1; accent-color: var(--accent); }
.gdz-range-val { flex: none; width: 34px; text-align: right; font-size: 11px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.gdz-select {
  flex: 1; background: var(--bg); border: 1px solid var(--border-2); border-radius: 7px;
  color: var(--text); font-size: 12px; padding: 5px 6px;
}
.gdz-row-wide .gdz-row-label { width: 84px; }

.gdz-pal-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-3); margin-top: 6px;
}
.gdz-pal-row { display: flex; align-items: center; gap: 6px; }
.gdz-pal-name { max-width: 84px; }
.gdz-grad-box { display: flex; flex-direction: column; gap: 8px; padding-left: 8px; border-left: 2px solid var(--border); }
.gdz-grad-box.hidden { display: none; }

.gdz-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.gdz-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; color: var(--text);
  background: var(--bg); border: 1px solid var(--border-2); border-radius: 100px;
  padding: 3px 6px 3px 10px;
}
.gdz-chip button { background: none; border: none; color: var(--text-3); cursor: pointer; font-size: 10px; padding: 0 2px; }
.gdz-chip button:hover { color: var(--text); }
.gdz-chip-input { flex: 1 1 100%; }

.gdz-assets { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 8px; }
.gdz-asset {
  position: relative; border: 1px solid var(--border-2); border-radius: 9px; overflow: hidden;
  background: var(--bg);
}
.gdz-asset-img { aspect-ratio: 4/3; background: center / contain no-repeat; }
.gdz-asset-name {
  display: block; font-size: 10.5px; color: var(--text-2);
  padding: 4px 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gdz-asset-x { position: absolute; top: 4px; right: 4px; opacity: 0; }
.gdz-asset:hover .gdz-asset-x { opacity: 1; }
.gdz-asset-up { align-self: flex-start; }

.gdz-source { display: flex; gap: 8px; font-size: 11.5px; align-items: baseline; }
.gdz-source-type {
  flex: none; font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--accent); border: 1px solid var(--border-2); border-radius: 5px; padding: 1px 6px;
}
.gdz-source-ref { color: var(--text-3); overflow: hidden; text-overflow: ellipsis; }

/* Narrow slots: the rail slides under the stage. */
@container (max-width: 700px) {
  .gdz-split { flex-direction: column; overflow-y: auto; }
  .gdz-rail { width: auto; border-left: none; border-top: 1px solid var(--border); }
  .gdz-stage { flex: none; min-height: 320px; }
}

/* ════ GLYPHH MEMORY panel — list tabs + the 3D space ════ */

.ws-gmemory-body { display: flex; flex-direction: column; overflow: hidden; }
.gmem { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.gmem-bar {
  display: flex; align-items: center; gap: 8px; flex: none;
  padding: 8px 10px; border-bottom: 1px solid var(--border);
}
.gmem-tabs { display: flex; gap: 2px; }
.gmem-tab {
  background: none; border: none; cursor: pointer;
  color: var(--text-3); font: inherit; font-size: 12px; font-weight: 600;
  padding: 5px 10px; border-radius: 7px;
}
.gmem-tab:hover { color: var(--text); background: var(--surface-2, rgba(255,255,255,0.05)); }
.gmem-tab.on { color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.gmem-search {
  flex: 1; min-width: 60px;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: 8px;
  color: var(--text); font-size: 12px; padding: 5px 10px;
}
.gmem-search:focus { border-color: var(--accent); outline: none; }
.gmem-body { flex: 1; min-height: 0; overflow-y: auto; position: relative; }

.gmem-facts, .gmem-sem, .gmem-short { padding: 10px 12px; }
.gmem-facts-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 2px 2px 10px; font-size: 11.5px; color: var(--text-3);
}
.gmem-history { display: flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; }
.gmem-hint { font-size: 11px; color: var(--text-3); font-weight: 400; }
.gmem-count { font-weight: 700; color: var(--text-2); }
.gmem-list { display: flex; flex-direction: column; gap: 4px; }

.gmem-fact {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; border: 1px solid var(--border); border-radius: 9px;
  background: var(--surface); font-size: 12.5px;
}
.gmem-fact.superseded { opacity: 0.45; }
.gmem-fact .gmem-del, .gmem-chunk .gmem-del { opacity: 0; flex: none; }
.gmem-fact:hover .gmem-del, .gmem-chunk:hover .gmem-del { opacity: 1; }
.gmem-tier {
  flex: none; font-size: 9.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 1px 7px; border-radius: 100px; border: 1px solid var(--border-2);
}
.gmem-tier-long { color: var(--text); }
.gmem-tier-mid { color: #ec4899; border-color: rgba(236, 72, 153, 0.4); }
.gmem-tier-short { color: #2dd4bf; border-color: rgba(45, 212, 191, 0.4); }
.gmem-fact-entity { flex: none; font-weight: 650; color: var(--text); }
.gmem-fact-role { flex: none; font-family: var(--mono, monospace); font-size: 11px; color: var(--accent); }
.gmem-fact-filler { flex: 1; min-width: 0; color: var(--text-2); cursor: text; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gmem-fact-meta { flex: none; font-size: 10.5px; color: var(--text-3); }
.gmem-edit {
  width: 100%; background: var(--bg); border: 1px solid var(--accent); border-radius: 6px;
  color: var(--text); font: inherit; padding: 2px 6px;
}

.gmem-chunk {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 8px 10px; border: 1px solid var(--border); border-radius: 9px;
  background: var(--surface);
}
.gmem-chunk-main { flex: 1; min-width: 0; }
.gmem-chunk-text { font-size: 12.5px; color: var(--text); line-height: 1.5; word-break: break-word; cursor: pointer; }
/* Entries land clamped to two lines; clicking the text unfolds them. */
.gmem-chunk.collapsed .gmem-chunk-text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.gmem-chunk-meta { font-size: 10.5px; color: var(--text-3); margin-top: 3px; }
.gmem-score {
  flex: none; font-family: var(--mono, monospace); font-size: 11px; font-weight: 700;
  color: var(--accent); padding: 2px 7px; border-radius: 6px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 22%, transparent) var(--s, 0%), transparent var(--s, 0%));
  border: 1px solid var(--border-2);
}

.gmem-secs { display: flex; flex-direction: column; gap: 8px; }
.gmem-sec { border: 1px solid var(--border); border-radius: 11px; background: var(--surface); }
.gmem-sec > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: baseline; gap: 8px;
  padding: 9px 12px;
  font-size: 12px; font-weight: 700; color: var(--text-2);
}
.gmem-sec > summary::-webkit-details-marker { display: none; }
.gmem-sec > summary::before { content: "▸"; color: var(--text-3); font-size: 10px; }
.gmem-sec[open] > summary::before { content: "▾"; }
.gmem-sec-count { font-style: normal; font-family: var(--mono, monospace); font-size: 10.5px; color: var(--accent); }
.gmem-sec .gmem-list { padding: 0 10px 10px; }
.gmem-sec .office-pager { padding: 0 10px 10px; }

.gmem-sec-title { font-size: 12px; font-weight: 700; color: var(--text-2); margin: 6px 0 8px; display: flex; gap: 10px; align-items: baseline; }
.gmem-window { display: flex; flex-direction: column; gap: 4px; margin-bottom: 16px; }
.gmem-turn {
  display: flex; gap: 10px; padding: 6px 10px;
  border-left: 2px solid var(--border-2); font-size: 12.5px; color: var(--text-2);
}
.gmem-turn.user { border-left-color: var(--accent); }
.gmem-turn-speaker { flex: none; width: 64px; font-weight: 650; color: var(--text-3); font-size: 11px; padding-top: 1px; }
.gmem-turn-text { flex: 1; min-width: 0; word-break: break-word; }

/* — the 3D space — */
.gmem-3d { position: absolute; inset: 0; overflow: hidden; }
.gmem-3d-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.gmem-3d-legend {
  position: absolute; left: 12px; top: 10px;
  display: flex; flex-wrap: wrap; gap: 12px;
  font-size: 10.5px; color: var(--text-3); pointer-events: none;
}
.gmem-3d-legend i { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 5px; vertical-align: -1px; }
.gmem-3d-edges i { height: 2px; width: 14px; border-radius: 1px; vertical-align: 2px; }
.gmem-3d-edges i.sem { background: #af5fff; }
.gmem-3d-edges i.neu { background: #6b7280; opacity: 0.5; }
.gmem-3d-info {
  position: absolute; left: 12px; bottom: 12px; max-width: min(420px, 70%);
  padding: 12px 14px; border-radius: 12px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  border: 1px solid var(--border-2);
  backdrop-filter: blur(8px);
}
.gmem-3d-info.hidden { display: none; }
.gmem-3d-info-kind { font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 5px; }
.gmem-3d-info-text { font-size: 12.5px; color: var(--text); line-height: 1.5; max-height: 130px; overflow-y: auto; }
.gmem-3d-info-meta { font-size: 10.5px; color: var(--text-3); margin: 5px 0 8px; }
.gmem-3d-info-lines { white-space: pre-line; }

/* ── Design studio: the CANVAS (pan/zoom world + draggable artifact cards) ── */
.gdz-canvas { position: relative; overflow: hidden; display: block; padding: 0; }
.gdz-world {
  position: absolute; left: 0; top: 0;
  transform-origin: 0 0;
  width: 1200px; height: 900px;
}
.gdz-art {
  position: absolute;
  border-radius: 16px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.4);
}
.gdz-art-grip {
  position: absolute; top: -24px; left: 4px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-3); cursor: grab; user-select: none;
  padding: 2px 8px;
}
.gdz-art-grip:hover { color: var(--text); }
.gdz-art-grip:active { cursor: grabbing; }
.gdz-canvas-hint {
  position: absolute; left: 12px; bottom: 10px;
  font-size: 10.5px; color: var(--text-3); pointer-events: none;
}
.gdz-art .gdz-shot { width: 100%; }
.gdz-spec-sheet {
  border-radius: 14px; padding: 18px 20px;
  display: flex; flex-direction: column; gap: 10px;
  border: 1px solid rgba(255,255,255,0.08);
}
.gdz-spec-row { display: flex; align-items: baseline; gap: 10px; line-height: 1.2; white-space: nowrap; overflow: hidden; }
.gdz-spec-tag { flex: none; font-size: 10px; font-family: var(--mono, monospace); opacity: 0.7; width: 38px; }
.gdz-pal-sheet {
  border-radius: 14px; padding: 14px 16px;
  display: flex; flex-direction: column; gap: 6px;
  border: 1px solid rgba(255,255,255,0.08);
}
.gdz-pal-swatch { display: flex; align-items: center; gap: 10px; font-size: 12px; }
.gdz-pal-swatch i { width: 22px; height: 22px; border-radius: 7px; border: 1px solid rgba(255,255,255,0.25); flex: none; }
.gdz-pal-swatch b { flex: 1; font-weight: 600; }
.gdz-pal-swatch em { font-style: normal; font-family: var(--mono, monospace); font-size: 11px; }
.gdz-pal-swatch u { text-decoration: none; font-size: 10.5px; }
.gdz-ui-sheet {
  border-radius: 14px; padding: 18px 20px;
  display: flex; flex-direction: column; gap: 14px;
  border: 1px solid rgba(255,255,255,0.08);
}
.gdz-ui-row { display: flex; align-items: center; gap: 10px; }

/* — editable sources — */
.gdz-sources { display: flex; flex-direction: column; gap: 8px; }
.gdz-source-row { display: flex; align-items: center; gap: 6px; }
.gdz-source-row .gdz-source-kind { flex: none; width: 76px; }
.gdz-source-ref-in { flex: 1.4; }
.gdz-source-note-in { flex: 1; }
.gdz-source-ref-in, .gdz-source-note-in {
  min-width: 0; background: var(--bg); border: 1px solid var(--border-2); border-radius: 7px;
  color: var(--text); font-size: 12px; padding: 5px 8px;
}
.gdz-source-ref-in:focus, .gdz-source-note-in:focus { border-color: var(--accent); outline: none; }
.gdz-source-add { align-self: flex-start; }


/* Drive rail: the right-justified ＋ on every folder row (My Drive included). */
.gdrive-railrow { display: flex; align-items: center; gap: 7px; }
.gdrive-railrow-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; text-align: left; }
.gdrive-railrow-plus {
  flex: none; margin-left: auto; width: 20px; height: 20px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px; color: var(--text-3); font-size: 14px; line-height: 1;
  opacity: 0;
}
.gdrive-railrow:hover .gdrive-railrow-plus { opacity: 1; }
.gdrive-railrow-plus:hover { background: var(--hover, rgba(255,255,255,0.08)); color: var(--accent); }

/* ════ GLYPHH MEDIA panels (Image / Video / Sounds) ════ */
.ws-gmedia-body { display: flex; flex-direction: column; overflow: hidden; }
.gmedia-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 12px;
  padding: 10px 12px; overflow-y: auto;
}
.gmedia-card {
  border: 1px solid var(--border); border-radius: 12px; overflow: hidden;
  background: var(--surface); cursor: pointer;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.gmedia-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.gmedia-thumb {
  position: relative; aspect-ratio: 16/10;
  background: var(--bg) center / cover no-repeat;
  display: flex; align-items: center; justify-content: center;
}
.gmedia-thumb-ph svg, .gmedia-thumb-ph .icon { width: 34px; height: 34px; opacity: 0.7; }
.gmedia-thumb-audio { background: linear-gradient(135deg, #0c4a6e, #075985); }
.gmedia-thumb-dur {
  position: absolute; right: 7px; bottom: 6px;
  font-size: 10.5px; font-variant-numeric: tabular-nums; color: #fff;
  background: rgba(0, 0, 0, 0.6); border-radius: 5px; padding: 1px 6px;
}
.gmedia-card .gdrive-card-row { padding: 7px 9px 0; }
.gmedia-card .gdrive-card-meta { display: block; padding: 0 9px 8px; }

.gmedia-viewer { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.gmedia-viewer-title { flex: 1; min-width: 0; font-weight: 650; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gmedia-viewer-del { opacity: 1; }
.gmedia-stage {
  flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center;
  background: var(--bg); padding: 14px; overflow: hidden;
}
.gmedia-full { max-width: 100%; max-height: 100%; border-radius: 10px; }
.gmedia-audio-wrap { display: flex; flex-direction: column; align-items: center; gap: 18px; width: min(460px, 90%); }
.gmedia-audio-art {
  width: 120px; height: 120px; border-radius: 24px;
  display: flex; align-items: center; justify-content: center;
  font-size: 46px; color: #fff;
  background: linear-gradient(135deg, #0ea5e9, #6366f1);
}
.gmedia-audio-wrap audio { width: 100%; }
.gmedia-meta { flex: none; padding: 10px 14px; border-top: 1px solid var(--border); }
.gmedia-meta-prompt { font-size: 12.5px; color: var(--text-2); font-style: italic; margin-bottom: 5px; }
.gmedia-meta-row { font-size: 11px; color: var(--text-3); font-family: var(--mono, monospace); }

/* Design canvas: adopted imagery cards. */
.gdz-art-imagery .gdz-art-grip { display: flex; align-items: center; gap: 8px; left: 0; right: 0; }
.gdz-art { cursor: grab; }
.gdz-art:active { cursor: grabbing; }
.gdz-art-resize {
  position: absolute; right: 2px; bottom: 2px; width: 16px; height: 16px;
  cursor: nwse-resize; border-radius: 4px; opacity: 0;
  background:
    linear-gradient(135deg, transparent 0 50%, var(--text-3) 50% 58%, transparent 58% 70%, var(--text-3) 70% 78%, transparent 78%);
  transition: opacity 0.15s;
}
.gdz-art:hover .gdz-art-resize { opacity: 0.9; }
.gdz-img-role { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gdz-img-x { opacity: 0; }
.gdz-art-imagery:hover .gdz-img-x { opacity: 1; }
.gdz-img-frame {
  border-radius: 14px; overflow: hidden; background: var(--bg);
  border: 1px solid var(--border-2); min-height: 120px;
  display: flex; align-items: center; justify-content: center; color: var(--text-3); font-size: 12px;
}
.gdz-img-frame img, .gdz-img-frame video { display: block; width: 100%; height: auto; }
.gdz-img-picker { max-height: 320px; overflow-y: auto; }
.gdz-imagery-rows { display: flex; flex-direction: column; gap: 8px; }
.gdz-img-name { cursor: default; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ════ MUSIC STUDIO (the Sounds app's Songs / Artists / Music Video) ════ */
.gmus-shell { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.gmus-tabs { flex: none; padding: 8px 10px; border-bottom: 1px solid var(--border); display: flex; gap: 2px; }
.gmus-pane { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; }
.gmus-list { padding: 10px 12px; display: flex; flex-direction: column; gap: 10px; }
.gmus-count { font-size: 12px; color: var(--text-3); flex: 1; }
.gmus-songs { display: flex; flex-direction: column; gap: 6px; }
.gmus-song-card {
  display: flex; align-items: center; gap: 12px; text-align: left;
  padding: 10px 13px; border: 1px solid var(--border); border-radius: 11px;
  background: var(--surface); cursor: pointer; font: inherit; color: var(--text);
}
.gmus-song-card:hover { border-color: var(--accent); }
.gmus-song-title { flex: 1; min-width: 0; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gmus-song-meta { flex: none; font-size: 11.5px; color: var(--text-3); }
.gmus-song-badges { flex: none; font-size: 12px; color: var(--accent); font-variant-numeric: tabular-nums; }

/* — the song page: Apps→General split — */
.gmus-page { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.gmus-savestate { flex: 1; text-align: right; font-size: 11px; color: var(--text-3); padding-right: 6px; }
.gmus-split { display: flex; flex: 1; min-height: 0; }
.gmus-left {
  flex: 0 0 44%; min-width: 300px; max-width: 560px;
  display: flex; flex-direction: column; gap: 6px;
  padding: 14px 16px; overflow-y: auto; border-right: 1px solid var(--border);
}
.gmus-label { font-size: 11px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text-3); margin-top: 8px; display: flex; gap: 8px; align-items: baseline; }
.gmus-title {
  font: inherit; font-size: 17px; font-weight: 700; color: var(--text);
  background: none; border: none; border-bottom: 2px solid var(--accent);
  padding: 6px 2px; outline: none;
  box-shadow: 0 12px 22px -14px color-mix(in srgb, var(--accent) 80%, transparent);
}
.gmus-lyrics {
  flex: 1; min-height: 260px; resize: vertical;
  font: inherit; font-size: 14px; line-height: 1.7; color: var(--text);
  background: var(--surface); border: 1px solid var(--border-2); border-radius: 10px;
  border-bottom: 2px solid var(--accent);
  box-shadow: 0 18px 34px -18px color-mix(in srgb, var(--accent) 85%, transparent);
  padding: 12px 14px; outline: none;
}
.gmus-lyrics:focus, .gmus-prompt:focus { border-color: var(--accent); }
.gmus-prompt {
  min-height: 84px; resize: vertical;
  font-family: var(--mono, monospace); font-size: 12px; line-height: 1.6; color: var(--text-2);
  background: var(--bg); border: 1px solid var(--border-2); border-radius: 10px;
  padding: 10px 12px; outline: none;
}
.gmus-band-line { font-size: 11.5px; color: var(--text-3); margin-top: 10px; }

/* — the sound editor — */
.gmus-right { flex: 1; min-width: 0; display: flex; flex-direction: column; padding: 12px 14px; gap: 8px; }
.gmus-wave-bar { display: flex; align-items: center; gap: 8px; flex: none; flex-wrap: wrap; }
.gmus-tools { display: flex; gap: 5px; }
.gmus-wave-bar .action-btn { height: 25px; padding: 2px 11px; font-size: 11.5px; }
.gmus-time { font-family: var(--mono, monospace); font-size: 11.5px; color: var(--text-2); min-width: 84px; }
.gmus-interval { width: 84px; flex: none; }
.gmus-wave-wrap {
  flex: 1; min-height: 160px; overflow-x: auto; overflow-y: hidden;
  border: 1px solid var(--border); border-radius: 12px;
  background: color-mix(in srgb, var(--accent) 4%, var(--bg));
}
.gmus-wave { display: block; height: 100%; cursor: crosshair; }
.gmus-wave-hint { flex: none; font-size: 10.5px; color: var(--text-3); }

/* — artists — */
.gmus-artists { display: flex; flex-direction: column; gap: 8px; }
.gmus-artist-card, .gmus-artist-editor {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 13px; border: 1px solid var(--border); border-radius: 11px; background: var(--surface);
}
.gmus-artist-editor { flex-direction: column; align-items: stretch; gap: 8px; }
.gmus-artist-face {
  flex: none; width: 44px; height: 44px; border-radius: 12px;
  background: var(--bg) center / cover no-repeat;
  display: flex; align-items: center; justify-content: center;
  color: var(--accent); font-size: 18px;
}
.gmus-artist-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.gmus-artist-name { font-weight: 650; color: var(--text); }
.gmus-artist-style { font-size: 11.5px; color: var(--text-2); }
.gmus-artist-badges { font-size: 10.5px; color: var(--text-3); }
.gmus-a-name, .gmus-a-style, .gmus-a-voiceid {
  font: inherit; font-size: 13px; color: var(--text);
  background: var(--bg); border: 1px solid var(--border-2); border-radius: 8px; padding: 7px 10px; outline: none;
}
.gmus-a-name:focus, .gmus-a-style:focus, .gmus-a-voiceid:focus { border-color: var(--accent); }
.gmus-a-row { display: flex; align-items: center; gap: 8px; }
.gmus-a-voice-state, .gmus-a-avatar-state { font-size: 11.5px; color: var(--text-3); }
.gmus-a-voiceid { flex: 1; }

/* — music video assembler — */
.gmus-mv-head { font-size: 12px; color: var(--text-2); }
.gmus-mv-pool { display: flex; flex-wrap: wrap; gap: 6px; }
.gmus-mv-chip {
  font: inherit; font-size: 11.5px; color: var(--text-2);
  background: var(--surface); border: 1px solid var(--border-2); border-radius: 100px;
  padding: 4px 12px; cursor: pointer;
}
.gmus-mv-chip.on { color: var(--accent); border-color: var(--accent); }
.gmus-mv-save { align-self: flex-start; }

/* — band looks — */
.gmus-looks { display: flex; gap: 8px; margin-top: 6px; }
.gmus-look {
  display: flex; gap: 2px; padding: 2px;
  border: 1.5px solid var(--border-2); border-radius: 9px; background: var(--bg); cursor: pointer;
}
.gmus-look.on { border-color: var(--accent); }
.gmus-look-f, .gmus-look-b {
  width: 30px; height: 42px; border-radius: 5px;
  background: var(--surface) center / cover no-repeat;
}
.gmus-i-look {
  flex: none; width: 34px; height: 34px; border-radius: 8px;
  background: var(--bg) center / cover no-repeat;
  border: 1px solid var(--border-2);
}
.gmus-i-look.busy { animation: pulse-dot 1.2s ease infinite; }
.gmus-song-card .gmus-song-del { opacity: 0; flex: none; }
.gmus-song-card:hover .gmus-song-del { opacity: 1; }

/* Regenerate busy state — spinner in the button, both actions disabled. */
.gmus-regen.busy { opacity: 0.75; pointer-events: none; }
.gmus-regen:disabled, .gmus-savenew:disabled { opacity: 0.55; cursor: default; }
.gmus-spin {
  display: inline-block; width: 11px; height: 11px; margin-right: 7px;
  border: 2px solid rgba(255, 255, 255, 0.35); border-top-color: currentColor;
  border-radius: 50%; vertical-align: -2px;
  animation: gmus-spin 0.8s linear infinite;
}
@keyframes gmus-spin { to { transform: rotate(360deg); } }
.gmus-length { width: 104px; flex: none; }

/* — the artist page: looks gallery + full-panel lightbox — */
.gmus-artist-card { text-align: left; font: inherit; cursor: pointer; color: var(--text); width: 100%; }
.gmus-artist-card:hover { border-color: var(--accent); }
.gmus-artist-card .gmus-artist-del { opacity: 0; margin-left: auto; }
.gmus-artist-card:hover .gmus-artist-del { opacity: 1; }
.gmus-looks-head { display: flex; align-items: center; justify-content: space-between; }
.gmus-looks-gallery {
  flex: 1; min-height: 0; overflow-y: auto;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px;
  align-content: start;
}
.gmus-lookcard {
  border: 1.5px solid var(--border); border-radius: 13px; overflow: hidden;
  background: var(--surface);
}
.gmus-lookcard.on { border-color: var(--accent); }
.gmus-lookcard-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 6px 10px;
}
.gmus-look-use {
  background: none; border: none; cursor: pointer; font: inherit;
  font-size: 11.5px; font-weight: 650; color: var(--text-3); padding: 2px 0;
}
.gmus-lookcard.on .gmus-look-use { color: var(--accent); cursor: default; }
.gmus-look-use:hover { color: var(--text); }
/* Busy look card: a veil + centered ring + label; the whole card breathes. */
.gmus-lookcard { position: relative; }
.gmus-look-busy {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  background: color-mix(in srgb, var(--bg) 72%, transparent);
  backdrop-filter: blur(3px);
  border-radius: inherit;
  animation: gmus-busy-in 220ms ease;
}
.gmus-look-busy-label { font-size: 11px; font-weight: 650; color: var(--text-2); letter-spacing: 0.03em; }
.gmus-spin-lg {
  width: 26px; height: 26px; margin: 0;
  border-width: 3px;
  border-color: color-mix(in srgb, var(--accent) 25%, transparent);
  border-top-color: var(--accent);
  vertical-align: 0;
}
@keyframes gmus-busy-in { from { opacity: 0; } to { opacity: 1; } }
.gmus-lookcard-imgs { display: flex; gap: 2px; }
.gmus-lookimg {
  flex: 1; aspect-ratio: 2/3; cursor: zoom-in; position: relative;
  background: var(--bg) center / cover no-repeat;
}
.gmus-lookimg span {
  position: absolute; left: 6px; bottom: 5px;
  font-size: 9px; letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.85); background: rgba(0, 0, 0, 0.45);
  padding: 1px 6px; border-radius: 4px;
}
.gmus-look-hint { flex: none; font-size: 10.5px; color: var(--text-3); }
.gmus-lightbox {
  position: absolute; inset: 0; z-index: 30;
  background: rgba(0, 0, 0, 0.86);
  display: flex; align-items: center; justify-content: center;
  cursor: zoom-out;
}
.gmus-lightbox.hidden { display: none; }
.gmus-lightbox img { max-width: 94%; max-height: 94%; border-radius: 10px; }
.gmus-page { position: relative; }
.ws-gband-body { display: flex; flex-direction: column; overflow: hidden; }

/* — the music video dual-column picker + player — */
.gmv-dual { display: flex; gap: 8px; min-height: 180px; }
.gmv-col {
  flex: 1; min-width: 0; overflow-y: auto; max-height: 300px;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: 6px;
  align-content: start;
  border: 1px solid var(--border-2); border-radius: 10px; padding: 8px; background: var(--bg);
}
.gmv-ctl { flex: none; display: flex; flex-direction: column; gap: 6px; justify-content: center; }
.gmv-ctl .ws-icon-btn { font-size: 15px; }
.gmv-thumb {
  aspect-ratio: 1; border-radius: 7px; border: 1.5px solid transparent;
  background: var(--surface) center / cover no-repeat; cursor: pointer; position: relative;
  padding: 0;
}
.gmv-thumb.marked { border-color: var(--accent); }
.gmv-thumb-tag { position: absolute; right: 3px; bottom: 2px; font-size: 10px; color: #fff; text-shadow: 0 1px 3px #000; }
.gmv-player {
  flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center;
  background: var(--bg); border-radius: 12px; border: 1px solid var(--border); overflow: hidden;
}

/* — the Song team strip + picker chrome — */
.gmus-team {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  padding: 8px 14px; border-bottom: 1px solid var(--border); flex: none;
  min-height: 44px;
}
.gmv-team { border-bottom: none; padding: 6px 0; }
.gmus-team-member { display: flex; align-items: center; gap: 7px; }
.gmus-team-face {
  width: 30px; height: 30px; border-radius: 9px; flex: none;
  background: var(--surface) center / cover no-repeat;
  border: 1px solid var(--border-2);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent); font-size: 13px;
}
.gmus-team-inst .gmus-team-face { border-radius: 50%; font-size: 12px; }
.gmus-team-name { font-size: 11.5px; color: var(--text-2); font-weight: 600; }
.gmv-pickwrap { display: flex; flex-direction: column; gap: 6px; }
.gmv-search { width: 100%; }
.gmv-rows { display: flex; flex-direction: column; gap: 5px; grid-template-columns: none; }
.gmv-pick {
  display: flex; align-items: center; gap: 8px; text-align: left;
  font: inherit; font-size: 12px; color: var(--text);
  background: var(--surface); border: 1.5px solid var(--border-2); border-radius: 8px;
  padding: 4px 8px; cursor: pointer; width: 100%;
}
.gmv-pick.marked { border-color: var(--accent); }
.gmv-pick-face {
  width: 24px; height: 24px; border-radius: 6px; flex: none;
  background: var(--bg) center / cover no-repeat;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent); font-size: 11px;
}
.gmv-pick-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gmv-selrow { display: flex; align-items: center; gap: 6px; }
.gmv-selrow .gmv-pick { flex: 0 0 44%; }
.gmv-tweak { flex: 1; min-width: 0; font-size: 11.5px; }
.gmv-col.gmv-avail { grid-template-columns: none; display: flex; flex-direction: column; gap: 5px; }
.gmv-prompt-tall { min-height: 160px; }
.gmus-lookimg-solo { aspect-ratio: 4/3; }
.gmus-pager-top .office-pager { padding: 0; }

/* — design rail resize grip + thumbnail imagery picker — */
.gdz-rail-grip {
  flex: none; width: 5px; cursor: col-resize;
  background: transparent;
}
.gdz-rail-grip:hover { background: var(--accent); opacity: 0.5; }
.gdz-img-picker-grid { width: 340px; padding: 8px; }
.gdz-img-picker-search { width: 100%; margin-bottom: 8px; }
.gdz-img-picker-thumbs {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px;
  max-height: 300px; overflow-y: auto;
}
.gdz-img-picker-thumb {
  position: relative; aspect-ratio: 1; border-radius: 8px; overflow: hidden;
  border: 1.5px solid var(--border-2); background: var(--bg) center / cover no-repeat;
  cursor: pointer; padding: 0;
}
.gdz-img-picker-thumb:hover { border-color: var(--accent); }
.gdz-img-picker-tag { position: absolute; right: 4px; top: 3px; font-size: 10px; color: #fff; text-shadow: 0 1px 3px #000; }
.gdz-img-picker-name {
  position: absolute; left: 0; right: 0; bottom: 0;
  font-size: 9px; color: #fff; background: rgba(0,0,0,0.55);
  padding: 2px 5px; text-align: left;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Design modals — Uploads / Imagery / Sources browse centered, expandable, paginated */
.gdz-modal-veil {
  position: fixed; inset: 0; z-index: 1200;
  background: rgba(0, 0, 0, 0.45);
  display: flex; align-items: center; justify-content: center;
}
.gdz-modal {
  display: flex; flex-direction: column;
  width: min(880px, 92vw); max-height: 82vh;
  background: var(--surface-2); border: 1px solid var(--border-2);
  border-radius: 12px; box-shadow: 0 18px 60px rgba(0, 0, 0, 0.45);
  overflow: hidden;
}
.gdz-modal.expanded { width: 96vw; height: 94vh; max-height: 94vh; }
.gdz-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px; border-bottom: 1px solid var(--border-2);
}
.gdz-modal-title { font-size: 13px; font-weight: 600; }
.gdz-modal-tools { display: flex; gap: 6px; }
.gdz-modal-body { display: flex; flex-direction: column; gap: 10px; padding: 12px 14px; overflow-y: auto; flex: 1; }
.gdz-modal-search { width: 100%; }
.gdz-modal-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; }
.gdz-modal-grid.gdz-modal-rows { display: flex; flex-direction: column; gap: 8px; }
.gdz-modal-tile {
  border: 1px solid var(--border-2); border-radius: 10px; overflow: hidden;
  background: var(--bg); padding: 0; text-align: left;
}
.gdz-modal-pick { cursor: pointer; }
.gdz-modal-pick:hover { border-color: var(--accent); }
.gdz-modal-img { position: relative; aspect-ratio: 4 / 3; background: var(--bg) center / contain no-repeat; }
.gdz-modal-img .gdz-img-picker-tag { font-size: 13px; }
.gdz-modal-row { display: flex; align-items: center; gap: 6px; padding: 6px 8px; }
.gdz-modal-name { flex: 1; font-size: 11px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gdz-modal-role { width: 110px; }
.gdz-modal-foot .office-pager { padding: 4px 0 0; }
.gdz-modal-empty { grid-column: 1 / -1; padding: 30px 0; text-align: center; color: var(--text-3); font-size: 12px; }

/* ── Listing builder (developer console) ─────────────────────────────── */
.lb-head { display: flex; align-items: center; gap: 16px; margin: 18px 0 8px; }
.lb-icon { width: 72px; height: 72px; border-radius: 16px; overflow: hidden; background: var(--surface-3); display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.lb-icon img { width: 100%; height: 100%; object-fit: cover; }
.lb-head-main { min-width: 0; flex: 1; }
.lb-head-actions { display: flex; align-items: center; gap: 8px; }
.lb-shots { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.lb-shot { position: relative; border-radius: 10px; overflow: hidden; border: 1px solid var(--border); }
.lb-shot img { width: 100%; display: block; }
.lb-shot-del { position: absolute; top: 6px; right: 6px; width: 24px; height: 24px; border: none; border-radius: 50%; background: rgba(0,0,0,.55); color: #fff; cursor: pointer; font-size: 15px; line-height: 1; }
.lb-video { width: 100%; max-width: 640px; border-radius: 12px; background: #000; }
.mkt-console-approw {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 10px 14px; margin-bottom: 10px;
  text-align: left; cursor: pointer; color: var(--text);
}
.mkt-console-approw:hover { background: var(--hover); }
.mkt-console-approw .mkt-card-icon { width: 30px; height: 30px; flex: 0 0 auto; }
.mkt-console-approw .mkt-console-app-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mkt-console-approw .mkt-console-app-sub { white-space: nowrap; }
.mkt-console-apps .mkt-pagination { margin-top: 12px; }

/* Breathing room on the listing builder form (his call, 2026-08-20). */
#mkt-console .mkt-dt-section { margin-top: 36px; }
#mkt-console .mkt-dt-section h3 { margin-bottom: 16px; }
#mkt-console .acct-row { margin-bottom: 20px; gap: 18px; }
#mkt-console .acct-field { display: flex; flex-direction: column; gap: 6px; }
#mkt-console .acct-field .settings-input { margin-top: 2px; }
#mkt-console .lb-head { margin-bottom: 16px; }

/* ── Review recommendations + admin source viewer ─────────────────────── */
.mq-recs { margin: 10px 0 4px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-2); }
.mq-recs-head { font-size: 13px; margin-bottom: 8px; }
.mq-recs-list { margin: 0; padding-left: 4px; list-style: none; display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
.mq-recs-list .mkt-review-chip { margin-right: 4px; }
.mq-recs .action-btn { margin-top: 10px; }
.mq-src { display: grid; grid-template-columns: minmax(220px, 320px) 1fr; gap: 0; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; margin-top: 10px; max-height: 420px; }
.mq-src-tree { overflow-y: auto; border-right: 1px solid var(--border); background: var(--surface-2); }
.mq-src-row { display: flex; justify-content: space-between; gap: 8px; width: 100%; padding: 5px 10px; border: none; background: none; color: var(--text-2); font-size: 12px; font-family: ui-monospace, monospace; cursor: pointer; text-align: left; }
.mq-src-row:hover { background: var(--hover); color: var(--text); }
.mq-src-row.active { background: var(--hover); color: var(--accent-light); }
.mq-src-row i { font-style: normal; color: var(--text-3); flex: 0 0 auto; }
.mq-src-view { margin: 0; padding: 12px 14px; overflow: auto; font-size: 12px; line-height: 1.5; white-space: pre; }

/* ── Nav notification badges (red count, top-right of the icon) ────────── */
.echo-dock-btn[data-badge]::before,
.echo-app-btn[data-badge]::before {
  content: attr(data-badge);
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border-radius: 9px;
  background: #e5484d;
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  line-height: 17px;
  text-align: center;
  box-shadow: 0 1px 4px rgba(0,0,0,.35);
  z-index: 2;
  pointer-events: none;
}
/* Tiles are column-flex (icon over label): the badge pins to the ICON square's
   top-right — the button's own top-right IS the icon's. */
.echo-app-btn[data-badge] { overflow: visible; }

/* Video thumb in the gallery strip: real poster + play badge. */
.mkt-thumb-video { position: relative; background: #17141f; }
.mkt-thumb-video video, .mkt-thumb-video img { width: 100%; height: 100%; object-fit: cover; display: block; pointer-events: none; }
.mkt-thumb-play {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 15px; text-shadow: 0 1px 6px rgba(0,0,0,.6);
  background: linear-gradient(rgba(0,0,0,.08), rgba(0,0,0,.28));
  pointer-events: none;
}

.mkt-dev-row-link { cursor: pointer; border-radius: 8px; }
.mkt-dev-row-link:hover { background: var(--hover); }
.mkt-dev-row-link:hover b { color: var(--accent-light); text-decoration: underline; }

/* ── Echo FOLDERS (2026-08-20): wall groups for app + layout icons ───────── */
.echo-folder-glyph svg { width: 26px; height: 26px; opacity: 0.75; }
.echo-folder-mini { background: color-mix(in srgb, var(--surface-3) 70%, transparent); border-radius: 12px; }
.echo-folder-overlay {
  position: fixed; inset: 0; z-index: 9600;
  /* SAME dialog skeleton as every other modal (his rule, 2026-08-20: the
     panel matches the rest of the app; themes own these tokens). */
  background: var(--overlay-bg);
  display: flex; align-items: center; justify-content: center;
}
.echo-folder-card {
  width: min(560px, 92vw);
  max-height: 78vh;
  display: flex; flex-direction: column;
  /* A shade darker than the standard card (his call, 2026-08-20) — still the
     theme's surface, mixed down so the open folder reads as its own well. */
  background: color-mix(in srgb, var(--surface-2) 78%, black); border: 1px solid var(--border-3);
  border-radius: 12px; box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
  padding: 14px 18px 18px;
}
.echo-folder-head { display: flex; align-items: center; gap: 10px; margin-bottom: 26px; }
.echo-folder-name {
  flex: 1; min-width: 0;
  background: none; border: none; outline: none;
  color: var(--text); font-size: 15px; font-weight: 600;
  padding: 4px 6px; border-radius: 8px;
}
.echo-folder-name:hover, .echo-folder-name:focus { background: var(--surface-3); }
.echo-folder-close {
  width: 26px; height: 26px; border: none; border-radius: 50%;
  background: var(--surface-3); color: var(--text-2); cursor: pointer;
}
.echo-folder-close:hover { background: var(--hover); color: var(--text); }
.echo-folder-delete {
  border: none; border-radius: 999px; padding: 5px 12px; cursor: pointer;
  background: var(--surface-3); color: var(--text-2); font-size: 12px;
}
.echo-folder-delete:hover { background: var(--danger, #e5484d); color: #fff; }
.echo-folder-grid {
  flex: 1; min-height: 120px; overflow-y: auto;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px;
  align-content: start;
  padding-top: 8px;   /* the top row sits down a tad off the header */
}
.echo-folder-item.selected { outline: 2px solid var(--accent, #af5fff); outline-offset: 2px; border-radius: 14px; }
.echo-folder-item { width: auto; }
.echo-folder-empty {
  grid-column: 1 / -1; padding: 28px 12px; text-align: center;
  color: var(--text-3); font-size: 12.5px;
}
.echo-folder-pager {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  margin-top: 10px; color: var(--text-2); font-size: 12px;
}
.echo-folder-pager button {
  width: 26px; height: 26px; border: none; border-radius: 50%;
  background: var(--surface-3); color: var(--text-2); cursor: pointer;
}
.echo-folder-pager button:disabled { opacity: 0.4; cursor: default; }
.echo-folder-pager button:not(:disabled):hover { background: var(--hover); color: var(--text); }


/* ── Echo Agent: independent TEXT fade + lock + CC close (2026-08-20) ────── */
/* Text fades on its own slider, multiplying the panel fade — glassy panel
   with solid words, or both faded, each its own knob. */
.code-root[data-anchor="center"].peeking > .code-agent > .code-thread .code-msg {
  opacity: var(--echo-agent-text-opacity, 1);
}
#code-agent-lock.active { color: var(--accent, #af5fff); }
.echo-cc-close {
  position: absolute;
  top: 14px; right: 16px;
  z-index: 420;
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-2);
  cursor: pointer;
}
.echo-cc-close:hover { background: var(--hover); color: var(--text); }
.echo-cc-close.hidden { display: none; }


/* ── THE LOCK IS ABSOLUTE (his bug, 2026-08-20: "still auto-hiding with the
   lock on") — the agent has SEVERAL hide mechanisms (the covered tuck, the
   fullscreen-card hide); the lock beats them ALL at the paint level. The one
   exception stays: a layout hosting its own agent (echo-agent-in-layout uses
   display:none, which these rules deliberately don't touch). */
body.echo-agent-locked .code-root[data-anchor="center"] > .code-agent {
  transform: translate(-50%, 0) !important;
  visibility: visible !important;
  pointer-events: auto !important;
}
body.echo-agent-locked #code-agent-layer {
  visibility: visible !important;
  /* Over every card, fullscreen included (cards live well below 400). */
  z-index: 460;
}


/* ── Agent panel drag geometry (2026-08-20) ──────────────────────────────── */
.code-root[data-anchor="center"] .code-agent-toprow { cursor: grab; }
.code-root[data-anchor="center"] .code-agent-toprow:active { cursor: grabbing; }
.code-input-card { position: relative; }
.code-agent-edge {
  position: absolute; top: 0; bottom: 0; width: 8px;
  cursor: ew-resize; z-index: 5;
}
.code-agent-edge.left { left: -4px; }
.code-agent-edge.right { right: -4px; }
.code-thread-grip {
  position: absolute; left: 50%; transform: translateX(-50%);
  width: 72px; height: 8px; border-radius: 4px;
  background: color-mix(in srgb, var(--text-3) 45%, transparent);
  cursor: ns-resize; z-index: 6;
  opacity: 0; transition: opacity 0.15s;
}
.code-root[data-anchor="center"].peeking > .code-agent:hover .code-thread-grip { opacity: 1; }

/* The peek's MINIMIZE ✕ — INSIDE the panel at its top-right (his fix,
   2026-08-25), sticky so it holds while the transcript scrolls. Tucks the
   panel back down; the turn keeps streaming underneath. Hidden unless
   peeking. */
.code-peek-close { display: none; }
.code-root[data-anchor="center"].peeking > .code-agent > .code-thread .code-peek-close {
  display: flex; align-items: center; justify-content: center;
  position: sticky; top: 0; margin-left: auto; margin-bottom: -22px; z-index: 5;
  width: 22px; height: 22px; padding: 0;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--surface); color: var(--text-3); cursor: pointer;
}
.code-root[data-anchor="center"].peeking > .code-agent > .code-thread .code-peek-close:hover { color: var(--text); border-color: var(--border-2); }


/* THE LOCK FREEZES GEOMETRY (his rule, 2026-08-20): while locked, the panel
   holds its exact position and size — no move, no resize affordances. */
body.echo-agent-locked .code-root[data-anchor="center"] .code-agent-toprow { cursor: default; }
body.echo-agent-locked .code-agent-edge,
body.echo-agent-locked .code-thread-grip { display: none; }

/* Platform-only nav rows (Connections, Apps): hidden in the desktop settings
   modal, shown in the web platform shell. The Apps row's far-right launcher
   opens the Builder in a new tab. */
.settings-nav-item.platform-only,
.settings-nav-group.platform-only,
.settings-panel .platform-only { display: none; }
body.platform-shell .settings-panel .platform-only:not(.hidden) { display: block; }

/* ── Settings ROW grammar (his spec, 2026-08-24): title left, description
   under it, the value control aligned to the page's RIGHT edge. ── */
.set-pref-row {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}
.set-pref-text { flex: 1; min-width: 0; }
.set-pref-title { font-size: 13px; font-weight: 500; color: var(--text); }
.set-pref-desc { font-size: 11.5px; color: var(--text-3); margin-top: 3px; }
.set-pref-value { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.set-pref-value .settings-input { width: auto; }
.set-pref-value input[type="text"], .set-pref-value input[type="url"] { width: 280px; }
.set-pref-list .set-pref-row:last-child { border-bottom: none; }

/* ── APP Usage view (plan-limits look; the platform keeps its dashboard) ── */
/* The DESKTOP modal floats expand/close top-right — page titles drop clear
   of them (the platform shell has its own 48px padding). */
.yo-settings-modal:not(.platform-page) .settings-modal-body .settings-panels { padding-top: 52px; }
body.platform-shell .yo-settings-modal .settings-modal-body .settings-panels { padding-top: 48px; }

/* ── Settings rail SEARCH (app only) ── */
body.platform-shell #settings-nav-search-wrap { display: none; }
#settings-nav-search-wrap { position: relative; padding: 4px 0 10px 12px; }
#settings-nav-search-wrap .set-search-ico {
  position: absolute; left: 21px; top: 4px; height: calc(100% - 14px);
  display: flex; align-items: center;
  color: var(--text-3); pointer-events: none;
}
#settings-nav-search-wrap .set-search-ico svg { width: 13px; height: 13px; }
#settings-nav-search { width: 100%; font-size: 12.5px; padding-left: 28px; }
#settings-nav-search-pop {
  position: absolute;
  left: 12px; right: 0; top: calc(100% - 6px);
  z-index: 40;
  padding: 5px;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-radius: 10px;
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.35);
  max-height: 300px;
  overflow-y: auto;
}
#settings-nav-search-pop.hidden { display: none; }
#settings-nav-search-pop button {
  display: block; width: 100%;
  padding: 7px 10px;
  background: none; border: none; border-radius: 7px;
  color: var(--text-2); font: inherit; font-size: 12.5px; text-align: left; cursor: pointer;
}
#settings-nav-search-pop button:hover { background: var(--hover); color: var(--text); }
#settings-nav-search-pop .pop-sub { display: block; font-size: 10.5px; color: var(--text-3); margin-top: 1px; }
#settings-nav-search-pop .pop-empty { padding: 8px 10px; font-size: 12px; color: var(--text-3); }
.ua-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin: 8px 0 18px; }
.ua-head-aside { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.ua-title { font-size: 16px; font-weight: 700; color: var(--text); }
.ua-plan { font-size: 12.5px; font-weight: 400; color: var(--text-3); }
.ua-plan::before { content: "("; }
.ua-plan::after { content: ")"; }
.ua-row { display: flex; align-items: center; gap: 18px; padding: 12px 0; }
.ua-label { width: 180px; flex-shrink: 0; }
.ua-name { font-size: 13px; color: var(--text); }
.ua-sub { font-size: 11.5px; color: var(--text-3); margin-top: 3px; }
.ua-bar { flex: 1; height: 6px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.ua-fill { height: 100%; width: 0%; border-radius: 999px; background: var(--accent, #af5fff); transition: width 0.3s ease; }
.ua-spacer { flex: 1; }
.ua-pct { width: 90px; text-align: right; font-size: 12.5px; color: var(--text-2); flex-shrink: 0; }
.ua-updated { font-size: 11.5px; color: var(--text-3); }
.ua-section { font-size: 13.5px; font-weight: 700; color: var(--text); margin-top: 26px; padding-top: 16px; border-top: 1px solid var(--border); }
.billing-topup-card.selected { border-color: var(--accent, #af5fff); box-shadow: 0 0 0 1px var(--accent, #af5fff) inset; }
#ua-buy-grid { grid-template-columns: repeat(5, 1fr); }
#ua-buy-custom-row { display: block; }
#ua-buy-custom-row .settings-input { width: 100%; }
.ua-row.ua-budget-row { border-bottom: 1px solid var(--border); }
.ua-row.ua-budget-row:last-child { border-bottom: none; }
.bil-label-wide { width: auto; flex-shrink: 1; min-width: 0; }

/* ── Billing plan header (the Claude billing look) ── */
.bil-plan-head { display: flex; align-items: flex-start; gap: 16px; margin: 10px 0 6px; }
.bil-plan-mark { width: 44px; height: 44px; object-fit: contain; flex-shrink: 0; margin-top: 2px; }
.bil-plan-text { flex: 1; min-width: 0; }
.bil-plan-name { font-size: 15px; font-weight: 700; color: var(--text); }
.bil-plan-sub { font-size: 12.5px; color: var(--text-2); margin-top: 3px; }
.bil-plan-seats { font-size: 11.5px; color: var(--text-3); margin-top: 4px; }
.bil-plan-seats .billing-seats-bar.hidden { display: none; }
/* General (his spec, 2026-08-24): a divider under the compaction block —
   with air between the guidance paragraph and the line — and one under each
   row after it; only the last row (interface sounds) keeps no underline. */
.settings-panel[data-sub="general"] .settings-form.set-pref-full {
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border);
}
.settings-panel[data-sub="general"] .set-pref-row:has(#general-ui-sound) { border-bottom: none; }
/* Roles › General: the Hard-limit toggle is the tab's last row, and the form
   footer (.crud-edit-foot) draws its own border-top — without this the two
   hairlines stack into a double line. */
.ws-tab[data-wstab="general"] .set-pref-row:has(#ws-budget-hard) { border-bottom: none; }
/* Full-width form rows (the compaction guidance textarea) — match the row
   grammar's page width instead of the 420px form cap. */
.settings-form.set-pref-full { max-width: none; }
.settings-form.set-pref-full .settings-input { width: 100%; }
/* A toggle wearing the row grammar: same flex row, switch at the right edge,
   none of the pill padding/hover chrome of the stock .settings-toggle. */
.settings-toggle.set-pref-row {
  width: 100%; padding: 14px 0; border-radius: 0; background: none;
  border: none; border-bottom: 1px solid var(--border);
}
.settings-toggle.set-pref-row:hover { border-color: var(--border); }
/* Appearance: air under the last row, and no divider after it (the hidden
   tablet-only mobile-ui row doesn't count as "after"). */
.settings-panel[data-sub="appearance"] { padding-bottom: 28px; }
.settings-panel[data-sub="appearance"] .set-pref-row:has(#settings-app-urlbar) { border-bottom: none; }
#settings-mobile-ui-row { border-bottom: none !important; }
/* Organization › General: a divider between the address block and the two
   billing toggle rows below it. */
/* Section heads on Organization › General: air above each, description
   clear beneath (his report, 2026-08-25 — RUNTIME LIMITS sat on its blurb). */
.settings-panel[data-sub="org-general"] .acct-row-head { margin: 30px 0 8px; }
.settings-panel[data-sub="org-general"] .acct-row-head + .section-desc { margin: 0 0 14px; }
.settings-panel[data-sub="org-general"] { padding-bottom: 32px; }
/* Voice: same rule — the last row ends the page clean. */
.settings-panel[data-sub="voice"] .set-pref-row:has(#voice-brief) { border-bottom: none; }
.settings-toggle.set-pref-row .toggle-switch { margin-left: 0; flex-shrink: 0; }
body.platform-shell .settings-nav-item.platform-only { display: flex; }
/* Per-surface TEXT inside a shared nav item (Dashboard on platform, Usage on
   the app) — span-scoped so the item rules above stay untouched. */
.settings-nav span.platform-only { display: none; }
body.platform-shell .settings-nav span.platform-only { display: inline; }
body.platform-shell .settings-nav span.not-on-platform { display: none; }
/* DESKTOP settings rail user chip — pinned at the rail's bottom, the
   platform chip's grammar (avatar circle, name over plan). */
/* The desktop rail: the search box, the groups scrolling on their own, and
   the user chip as the footer below them (never over them). */
.settings-nav:has(> .settings-nav-list) { overflow: hidden; padding-bottom: 0; }
.settings-nav-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding-bottom: 12px;
}
.settings-nav-list > .settings-nav-group:first-child { margin-top: 2px; }
#app-settings-user {
  flex-shrink: 0;
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  background: var(--surface);
  border: none;
  border-top: 1px solid var(--border);
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
#app-settings-user:hover { background: var(--hover); }
#app-settings-user .asu-avatar {
  width: 26px; height: 26px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent, #af5fff); color: #fff;
  font-size: 12px; font-weight: 600; flex-shrink: 0;
}
#app-settings-user .asu-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
/* Members table: a disabled member reads dimmed; inline inputs stay compact.
   The fixed 28px height must DROP settings-input's 10px vertical padding or
   the text has negative room and clips (his report, 2026-09-01: role select
   showed nothing). */
.mbr-table .mbr-name { max-width: 220px; height: 28px; font-size: 12.5px; padding-top: 0; padding-bottom: 0; }
.mbr-table .mbr-role { height: 28px; font-size: 12.5px; width: auto; padding-top: 0; padding-bottom: 0; }
.mbr-table .mbr-toggle { border: none; padding: 0; margin: 0; }
tr.mbr-disabled td { opacity: 0.45; }
tr.mbr-disabled td:nth-last-child(-n+2) { opacity: 1; }
#app-settings-user .asu-meta { display: flex; flex-direction: column; min-width: 0; }
#app-settings-user .asu-name { font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#app-settings-user .asu-plan { font-size: 11px; color: var(--text-3); }
body.platform-shell #app-settings-user { display: none; }
/* Surface-split blocks: web-only shows on any glyphh-web page; desktop-only
   hides there. */
.glyphh-web-only { display: none; }
.glyphh-web .glyphh-web-only { display: block; }
.glyphh-web .glyphh-desktop-only { display: none; }
body.platform-shell .settings-nav-item.not-on-platform,
body.platform-shell .settings-nav-group.not-on-platform { display: none !important; }
/* Platform dashboard header: greeting left, actions at the right edge. */
.dash-head { display: flex; align-items: center; gap: 14px; margin: 2px 0 20px; }
/* Outranks the platform-only display:block reveal above. */
body.platform-shell .settings-panel .dash-head.platform-only:not(.hidden) { display: flex; }
.dash-head h2 { margin: 0; }
.dash-head-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.dash-head-actions .action-btn svg { width: 14px; height: 14px; margin-right: 6px; vertical-align: -2px; }
body.platform-shell .settings-nav-group.platform-only { display: block; }
.rail-row-launch {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  opacity: 0.5;
  transition: opacity 0.15s;
}
.rail-row-launch svg { width: 13px; height: 13px; }
.rail-row-launch:hover { opacity: 1; }
body.platform-rail-collapsed .rail-row-launch { display: none; }

/* ── Agent hosted in a LAYOUT: the head row reads (his spec, 2026-08-21)
   <session-name, inline editable> ......... <drips><recents><new><⋮ menu>
   — no chevron/locus clutter, no kebab (rename is the name itself), and no
   LOCK (pinning over panels makes no sense inside a layout cell). The name
   shows even on a fresh landing so there is always something to rename. ── */
body.echo-agent-in-layout .code-agent-head .session-head-chev,
body.echo-agent-in-layout .code-agent-head .session-head-locus,
body.echo-agent-in-layout #code-session-kebab-wrap,
body.echo-agent-in-layout #code-agent-lock { display: none !important; }
body.echo-agent-in-layout .code-agent-head.head-landing #code-session-back { display: inline-flex; }

/* Inside the relocatable controls group, DOM order IS the spec order —
   drips, recents, + new, ⋮ menu. The legacy .session-head-actions order
   rules above (history=1/new=2) otherwise shuffle the un-ordered items
   (drips, ⋮) to the front, which is exactly the backwards row he saw. */
.code-session-controls > .echo-drip-anchor { order: 1 !important; }
.code-session-controls > #code-session-history { order: 2 !important; }
.code-session-controls > #code-session-new { order: 3 !important; }
.code-session-controls > #code-tools-wrap { order: 4 !important; }


/* In the LAYOUT header the popovers hang DOWN (his rule, 2026-08-21): the
   row sits at the TOP of the panel, so the composer's open-upward default
   throws them off the top edge, clipped — "the menu doesn't work". */
body.echo-agent-in-layout .code-agent-head .code-view-more-menu { bottom: auto; top: calc(100% + 6px); }
body.echo-agent-in-layout .code-agent-head .echo-drip-pop { bottom: auto; top: calc(100% + 8px); }


/* The session name, now a sibling of the back button (rename needs a real
   span, not button innards). Reads like part of the head row. */
.session-head-title { font-weight: 600; font-size: 13px; color: var(--text);
  cursor: text; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0; flex-shrink: 1; -webkit-app-region: no-drag; }
.session-head-rename { font: inherit; font-weight: 600; color: var(--text);
  background: var(--surface); border: 1px solid var(--border-2);
  border-radius: 6px; padding: 2px 6px; min-width: 140px; }
/* ── Platform shell (web /platform) ──────────────────────────────────────────
   The settings surface PROMOTED to a full page: home.ts's platform branch sets
   body.platform-shell and opens the EXISTING settings modal — these rules
   restyle that same DOM into a full-bleed admin layout (rail left, content
   right) with no backdrop and no close/expand affordances (closeSettingsModal
   is also a guarded no-op there). Inert on desktop: the class is only ever set
   on the web-only /platform route. */
body.platform-shell #settings-modal .yo-modal-backdrop { display: none; }
body.platform-shell .yo-settings-modal .settings-modal-panel {
  position: fixed;
  inset: 0;
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  margin: 0;
  border: none;
  border-radius: 0;
  box-shadow: none;
  animation: none;
}
body.platform-shell .settings-modal-close,
body.platform-shell .settings-modal-max { display: none; }
/* The rail-collapse chevron (home.ts platform branch) reuses the modal
   icon-button voice but pins to the shell's TOP-LEFT, over the rail. The id
   out-specifies the .settings-modal-close display:none above. */
body.platform-shell #platform-rail-toggle {
  display: flex;
  position: static;
  margin-left: auto;
  pointer-events: auto;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
}
body.platform-shell #platform-rail-toggle svg { width: 16px; height: 16px; }
/* Full-page proportions (his rule, 2026-08-24: BIGGER): a wide rail with
   larger rows, room under the fixed chevron, and room above the bottom
   user chip. Build and Help are desktop-settings groups — the platform
   rail hides them (Docs/Support/About live in the user chip's menu). */
body.platform-shell .not-platform { display: none !important; }
body.platform-shell .settings-modal-body > .settings-layout > .settings-nav {
  width: 264px;
  padding-top: 64px;
  padding-left: 12px;
  padding-bottom: 76px;
  transition: width 0.15s ease, padding 0.15s ease;
}
body.platform-shell .settings-nav-item {
  font-size: 14px;
  padding: 9px 14px;
  gap: 11px;
}
body.platform-shell .settings-nav-item .settings-nav-icon { width: 17px; height: 17px; }
body.platform-shell .settings-nav-group { font-size: 11px; }
/* Collapsible rail sections (his order, 2026-09-02, platform only): the header
   toggles its items; a caret shows state. Preference rides ui-state. */
body.platform-shell .settings-nav-group.nav-group-collapsible {
  cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 6px;
}
body.platform-shell .settings-nav-group.nav-group-collapsible::after {
  content: ""; width: 7px; height: 7px; margin-left: auto;
  border-right: 1.5px solid var(--text-faint); border-bottom: 1.5px solid var(--text-faint);
  transform: rotate(45deg); transition: transform 0.15s ease;
}
body.platform-shell .settings-nav-group.nav-group-closed::after { transform: rotate(-45deg); }
body.platform-shell .settings-nav .nav-collapsed { display: none !important; }
body.platform-shell #platform-brand { height: 34px; }

/* ── Rail-bottom user chip: first name over the plan; menu opens UP with
   Docs / Support / About. Fixed bottom-left, sized to the rail. ── */
#platform-user-chip {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 264px;
  /* The platform page IS the settings modal (.yo-modal, z 9000) — the chip
     must float above it or the opaque panel paints over it. */
  z-index: 9100;
  padding: 10px 12px 12px;
  /* The rail's own surface (the settings panel paints var(--surface)) — the
     body bg read as a darker mismatched band. */
  background: var(--surface);
  /* The chip paints OVER the nav's full-height border — carry the same line
     so the rail edge runs to the page bottom (his report, 2026-08-25). */
  box-sizing: border-box;
  border-right: 1px solid var(--border);
}
#platform-user-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  background: none;
  border: 1px solid transparent;
  border-radius: 10px;
  cursor: pointer;
  text-align: left;
}
#platform-user-btn:hover { background: var(--active-bg); border-color: var(--border); }
#platform-user-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-fg);
  font-size: 13px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
#platform-user-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
#platform-user-meta { display: flex; flex-direction: column; min-width: 0; }
#platform-user-name {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#platform-user-plan { font-size: 11.5px; color: var(--text-3); }
#platform-user-menu {
  position: absolute;
  left: 12px;
  bottom: calc(100% - 2px);
  min-width: 180px;
  padding: 5px;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-radius: 10px;
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.35);
}
#platform-user-menu.hidden { display: none; }
#app-settings-user-menu {
  position: absolute;
  left: 10px; bottom: 56px;
  width: 200px;
  padding: 6px;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-radius: 12px;
  box-shadow: 0 14px 40px rgba(0,0,0,.4);
  z-index: 60;
}
#app-settings-user-menu.hidden { display: none; }
#app-settings-user-menu button {
  display: flex; align-items: center; gap: 9px;
  width: 100%;
  padding: 7px 10px;
  background: none; border: none; border-radius: 7px;
  color: var(--text-2); font-size: 13px; text-align: left; cursor: pointer;
}
#app-settings-user-menu button:hover { background: var(--active-bg); color: var(--text); }
#app-settings-user-menu button > svg { width: 14px; height: 14px; flex-shrink: 0; color: var(--text-3); }
#app-settings-user-menu .menu-sep { height: 1px; margin: 4px 6px; background: var(--border); }
#app-settings-user-menu .menu-danger { color: var(--danger, #e5484d); }
#platform-user-menu button {
  display: block;
  width: 100%;
  padding: 7px 10px;
  background: none;
  border: none;
  border-radius: 7px;
  color: var(--text-2);
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
#platform-user-menu button:hover { background: var(--active-bg); color: var(--text); }
/* Menu rows with icons — must sit AFTER the display:block base rule above
   (same specificity; source order decides). */
#platform-user-menu > button { display: flex; align-items: center; gap: 9px; }
#platform-user-menu > button > svg { width: 14px; height: 14px; flex-shrink: 0; color: var(--text-3); }
#platform-user-menu > button:hover > svg { color: inherit; }
#platform-user-menu .menu-sep { height: 1px; margin: 4px 6px; background: var(--border); }
#platform-user-menu .menu-danger { color: var(--danger, #e5484d); }
#platform-user-menu .menu-danger:hover { color: var(--danger, #e5484d); }
body.platform-rail-collapsed #platform-user-chip { width: 54px; padding: 8px 6px 10px; }
body.platform-rail-collapsed #platform-user-btn { justify-content: center; padding: 6px; }
body.platform-rail-collapsed #platform-user-meta { display: none; }
body.platform-shell .settings-modal-body > .settings-layout > .settings-panels {
  padding-top: 48px;
}
/* Only the Dashboard keeps the centered column (his order, 2026-08-25) —
   every other platform page runs full width. */
body.platform-shell .settings-panel[data-sub="dash"],
body.platform-shell .settings-panel[data-sub="org-general"],
body.platform-shell .settings-panel[data-sub="usage"],
body.platform-shell .settings-panel[data-sub="billing"] { max-width: 880px; margin: 0 auto; }
/* Collapsed rail — icons only (labels + group headings fold away); state in
   localStorage glyphhPlatformRail, toggled by #platform-rail-toggle. */
body.platform-shell.platform-rail-collapsed .settings-modal-body > .settings-layout > .settings-nav {
  width: 54px;
  padding-left: 6px;
  padding-right: 6px;
}
body.platform-shell.platform-rail-collapsed .settings-modal-body > .settings-layout > .settings-nav > .settings-nav-item {
  justify-content: center;
  gap: 0;
  padding: 8px 0;
}
body.platform-shell.platform-rail-collapsed .settings-modal-body > .settings-layout > .settings-nav > .settings-nav-item > span { display: none; }
body.platform-shell.platform-rail-collapsed .settings-modal-body > .settings-layout > .settings-nav > .settings-nav-item > .settings-nav-icon {
  width: 17px;
  height: 17px;
}
body.platform-shell.platform-rail-collapsed .settings-modal-body > .settings-layout > .settings-nav > .settings-nav-group {
  height: 0;
  margin: 8px 0 0;
  padding: 0;
  overflow: hidden;
}

/* Platform rail header: the wordmark alone (the surface switch is gone —
   the Builder opens from the Apps row's launcher). FIXED out of the
   .settings-layout flex row — as an in-flow sibling it became its own
   left column and shoved the whole nav sideways (the misaligned rail). */
#platform-rail-head {
  position: fixed;
  top: 0;
  left: 0;
  width: 264px;
  z-index: 3;
  /* Decoration only EXCEPT the rail toggle, which re-enables its own events. */
  pointer-events: none;
  padding: 12px 12px 8px;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
}
#platform-brand { display: block; height: 28px; width: auto; padding: 0 6px; object-fit: contain; }
#platform-mascot { display: none; height: 26px; width: auto; margin: 0 auto; }
body.platform-rail-collapsed #platform-rail-head { width: 54px; padding: 12px 6px 8px; }
body.platform-rail-collapsed #platform-brand { display: none; }
body.platform-rail-collapsed #platform-mascot { display: block; }

/* Collapsed rail: the expand toggle floats JUST OUTSIDE the rail's right
   edge (rail is 54px wide collapsed). */
body.platform-shell.platform-rail-collapsed #platform-rail-toggle {
  position: fixed !important;
  /* The base .settings-modal-close carries right:12px, and the expanded
     rule margin-left:auto — both must reset or the fixed box slides to the
     window's right edge. */
  left: 60px; right: auto; top: 12px; margin-left: 0; z-index: 9100;
  width: 26px; height: 26px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 50%;
  box-shadow: 0 2px 8px var(--shadow);
}


/* Inline notes under a version row (his order, 2026-08-25): the head toggles,
   the textarea saves on blur, Promote rides the expanded area. */
.release-row .release-row-head { all: unset; display: flex; align-items: center; gap: 8px; width: 100%; cursor: pointer; box-sizing: border-box; }
.release-notes-inline { padding: 8px 2px 2px; }

/* ── Wall tour — the first-run guided overlay (wall-tour.ts) ─────────────── */
.wtour { position: fixed; inset: 0; z-index: 9500; }
.wtour-svg { position: absolute; inset: 0; pointer-events: none; }
.wtour-dim { fill: rgba(0, 0, 0, 0.62); pointer-events: auto; }
/* Keep the marker readable over both the dimmed page and the live control in
   the hole. The paired light/dark halo prevents a theme accent from sinking
   into either a white light surface or a black dark surface. */
.wtour-arrow,
.wtour-ring {
  fill: none;
  stroke: var(--accent, #8c3bf2);
  stroke-width: 3;
  stroke-linecap: round;
  filter: drop-shadow(0 0 1px #fff) drop-shadow(0 0 1.5px #000);
}
.wtour-svg marker path {
  fill: var(--accent, #8c3bf2);
  filter: drop-shadow(0 0 1px #fff) drop-shadow(0 0 1.5px #000);
}
.wtour-labels { position: absolute; inset: 0; pointer-events: none; }
.wtour-arrow-label {
  position: absolute; transform: translateX(-50%);
  font: 700 12px var(--font-sans); color: var(--bg, #fff);
  background: var(--text-bright, #000); padding: 4px 10px; border-radius: 999px;
  white-space: nowrap; border: 2px solid var(--bg, #fff);
  box-shadow: 0 0 0 1px var(--text-bright, #000), 0 4px 14px rgba(0, 0, 0, 0.45);
}
.wtour-card {
  position: absolute; left: 50%; bottom: 96px; transform: translateX(-50%);
  width: min(460px, calc(100vw - 48px));
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 16px; padding: 20px 22px 16px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.5);
}
.wtour-step-num { font: 600 11px var(--font-sans); color: var(--text-3); letter-spacing: 0.04em; }
.wtour-title { margin: 6px 0 6px; font: 700 19px var(--font-sans); color: var(--text); }
.wtour-copy { margin: 0 0 14px; font: 400 13.5px/1.5 var(--font-sans); color: var(--text-2); }
.wtour-visual { margin-bottom: 14px; }
.wtour-foot { display: flex; align-items: center; gap: 10px; }
.wtour-dots { display: flex; gap: 6px; margin: 0 auto; }
.wtour-dot-nav { width: 7px; height: 7px; border-radius: 50%; background: var(--border-2); }
.wtour-dot-nav.active { background: var(--accent, #8c3bf2); }
.wtour-nav { display: flex; gap: 8px; }
/* The mock screenshots — CSS-drawn minis, themed, no bitmaps to go stale. */
.wtour-mock {
  border: 1px solid var(--border); border-radius: 10px; overflow: hidden;
  background: var(--surface-3);
}
.wtour-mock-bar { display: flex; gap: 5px; padding: 8px 10px; border-bottom: 1px solid var(--border); }
.wtour-mock-bar span { width: 8px; height: 8px; border-radius: 50%; background: var(--border-2); }
.wtour-mock-row {
  display: flex; align-items: center; gap: 9px; padding: 8px 12px;
  font: 500 12px var(--font-sans); color: var(--text-2);
  border-bottom: 1px solid var(--border);
}
.wtour-mock-row:last-child { border-bottom: none; }
.wtour-mock-row b { color: var(--text); font-weight: 600; }
.wtour-mock-row em { margin-left: auto; font-style: normal; font-size: 11px; color: var(--text-3); }
.wtour-mock-row em.on { color: #22c55e; }
.wtour-dot { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.wtour-mock-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; padding: 12px; }
.wtour-mock-app {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  font: 500 10.5px var(--font-sans); color: var(--text-2);
}
.wtour-mock-app i { width: 30px; height: 30px; border-radius: 8px; }
.wtour-mock-ghost { justify-content: center; color: var(--text-3); border: 1px dashed var(--border-2); border-radius: 8px; padding: 4px; }
.wtour-mock-splits { display: grid; grid-template-columns: 1.4fr 1fr; grid-template-rows: 1fr 1fr; gap: 7px; padding: 12px; height: 96px; }
.wtour-mock-splits div { background: var(--surface-2); border: 1px solid var(--border-2); border-radius: 7px; }
.wtour-mock-agent { display: flex; align-items: center; gap: 8px; padding: 10px 12px; }
.wtour-mock-prompt {
  flex: 1; font: 400 12px var(--font-sans); color: var(--text-2);
  background: var(--surface-2); border: 1px solid var(--accent, #8c3bf2);
  border-radius: 999px; padding: 8px 14px;
}
.wtour-mock-send { color: var(--text-3); font-size: 13px; }
.wtour-ring { opacity: 1; }
.wtour-mock-keys { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 22px 12px; }
.wtour-key {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; height: 44px; padding: 0 12px;
  font: 600 16px var(--font-sans); color: var(--text);
  background: var(--surface-2); border: 1px solid var(--border-2);
  border-bottom-width: 3px; border-radius: 9px;
}
.wtour-key-wide { min-width: 96px; }
/* The Dashboard | Desktop surface toggle was removed (his call, 2026-08-29):
   app-web is the Platform only, so both surfaces and the toggle are gone. The
   rail keeps the plain Dashboard row (.dash-plain) on every surface. */
/* ── Download page (platform rail) ──────────────────────────────────────── */
.dl-hero {
  border: 1px solid var(--border); border-radius: 14px;
  background: var(--surface-2); padding: 20px 22px; margin-bottom: 26px;
}
.dl-hero-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 16px; }
.dl-hero-ver { font: 700 22px var(--font-sans); color: var(--text); }
.dl-hero-date { font: 500 12.5px var(--font-sans); color: var(--text-3); }
.dl-hero-btns { display: flex; flex-wrap: wrap; gap: 10px; }
.dl-hero-btns .action-btn { text-decoration: none; }
.dl-prev-title { font: 650 15px var(--font-sans); color: var(--text); margin: 0 0 10px; }
.dl-asset-link { color: var(--text-2); text-decoration: none; }
.dl-asset-link:hover { color: var(--text); text-decoration: underline; }
/* The user menu's update dot — About carries it when a release is downloaded. */
.user-menu-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent, #8c3bf2); margin-left: auto; flex: none; }
/* ── Media viewer navigation — chevrons flank the stage, arrows step ────── */
.gmedia-stagewrap { display: flex; align-items: stretch; flex: 1 1 auto; min-height: 0; }
.gmedia-stagewrap .gmedia-stage { flex: 1 1 auto; min-width: 0; }
.gmedia-nav {
  flex: 0 0 44px; display: flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--text-3); cursor: pointer;
  opacity: 0.55; transition: opacity 0.12s ease, color 0.12s ease;
}
.gmedia-nav:hover { opacity: 1; color: var(--text); }
.gmedia-nav svg { width: 26px; height: 26px; }
/* The song's attached videos — a strip of playable thumbs under the band. */
.gmus-videos { display: flex; flex-wrap: wrap; gap: 10px; }
.gmus-videos:empty { display: none; }
.gmus-video-cell { width: 220px; border-radius: 10px; background: #000; border: 1px solid var(--border); }

/* The surface toggle was removed (his call, 2026-08-29): app-web shows the
   plain Dashboard row (.dash-plain), same as desktop — no per-surface override. */
/* The dock's Command-center slot shows ONLY with auto-hide OFF (his spec,
   2026-08-28): with auto-hide on, the dock vanishes with the wall and the
   composer's CC button is the summoner; pinned always-on, the dock needs its
   own way back to the wall. */
/* CC shows ONLY while auto-hide is ON and panels are open (his order,
   2026-08-28, third revision — supersedes always-visible): tucked/peeked
   over panels, CC is the way back to the wall; on the bare wall it is
   redundant. Sits RIGHT of Sign out.

   ALWAYS PRESENT (his order, 2026-08-28): CC and Close all are permanent
   dock slots — hiding them reshuffled the row and moved wherever the user
   had dragged them. With nothing open they simply go DIM and inert; the
   context menu offers no delete for fixed nav slots, so they can be
   reordered but never removed. */
.echo-dock-btn[data-dock="cc"],
.echo-dock-btn[data-dock="closeall"] { display: inline-flex; }
body:not(.echo-has-panels) .echo-dock-btn[data-dock="cc"],
body:not(.echo-has-panels) .echo-dock-btn[data-dock="closeall"] {
  opacity: 0.34; cursor: default;
}
/* The same two slots leading the WALL while the dock is off (his order,
   2026-10-04) go inert the same way — they run the dock's own action, which
   does nothing with no panels up. */
body.echo-dock-off:not(.echo-has-panels) .echo-app-btn[data-nav="cc"],
body.echo-dock-off:not(.echo-has-panels) .echo-app-btn[data-nav="closeall"] {
  opacity: 0.34; cursor: default;
}
body.echo-dock-off:not(.echo-has-panels) .echo-pages .echo-app-btn[data-nav="cc"]:hover,
body.echo-dock-off:not(.echo-has-panels) .echo-pages .echo-app-btn[data-nav="closeall"]:hover { transform: none; }
body.echo-dock-off:not(.echo-has-panels) .echo-app-btn[data-nav="cc"]:hover .echo-app-ic,
body.echo-dock-off:not(.echo-has-panels) .echo-app-btn[data-nav="closeall"]:hover .echo-app-ic { box-shadow: none; }
/* ATTACHED MODE: the CC slot is live from the first summon — over a foreign
   app it is the way to the wall, panels open or not. */
html[data-home-scope="agent-dock"] body:not(.echo-has-panels) .echo-dock-btn[data-dock="cc"] {
  opacity: 1; cursor: pointer;
}
/* Dim = inert: no hover ring, no hover zoom (the arc still carries them so
   the row never breaks its rhythm). */
body:not(.echo-has-panels) .echo-dock-btn[data-dock="cc"]:hover,
body:not(.echo-has-panels) .echo-dock-btn[data-dock="closeall"]:hover {
  box-shadow: none;
}
body:not(.echo-has-panels) .echo-dock-btn[data-dock="cc"]:hover:not([style*="transform"]),
body:not(.echo-has-panels) .echo-dock-btn[data-dock="closeall"]:hover:not([style*="transform"]) {
  transform: none;
}
/* ── Auto-hidden dock: tucked off-top, hint sliver, hover peek ──────────── */
/* The PARKED bar (dock-portal.ts moved it into the body-level layer while
   panels are up). Same icon sizing variables as at rest — the bar must look
   IDENTICAL to its wall seat (his rule: no spread, no zoom change) — plus a
   real backdrop so it reads as a bar over the panels. */
/* ABOVE EVERY PANEL (his report, 2026-09-18: the dock still drew under the
   agent panel). 2000 cleared the workbench's own layers but not the cards and
   overlays that climb past it; this sits under the settings modal (999000) and
   the toast stack (1000000) and above everything else. */
#echo-dock-layer { position: fixed; inset: 0; pointer-events: none; z-index: 99000; }
/* The peek SCRIM (his order, 2026-09-14): a theme gradient behind the
   dropped dock — the page's own surface color, darkest at the very top,
   gone within the dock's band — so the bar reads as descending from the
   chrome instead of floating over the panels. */
body.echo-dock-tucked #echo-dock-layer::before {
  /* BELOW the drag strip — the traffic lights stay visible no matter what
     (his order, 2026-09-14). */
  content: ""; position: fixed; top: var(--wb-top-inset, 0px); left: var(--rail-w, 0px); right: 0;
  height: 72px;
  background: linear-gradient(to bottom,
    var(--bg) 0%,
    color-mix(in srgb, var(--bg) 72%, transparent) 55%,
    transparent 100%);
  opacity: 0; transition: opacity 0.22s ease; pointer-events: none;
}
body.echo-dock-tucked.echo-dock-peek #echo-dock-layer::before { opacity: 1; }
/* The wall's "tad more drop" margin is wall-only — zero on the parked bar. */
#echo-dock-layer .echo-dock { margin-top: 0; }
#echo-dock-layer .echo-topbar {
  /* Hug the chrome (his report, 2026-09-14: "drops down way too far") —
     just under the drag strip, wall margins zeroed on the parked bar. */
  /* Centered over the CONTENT side, never the whole window: the fixed sidebar owns the left (2026-09-16). */
  /* ABSOLUTE INSIDE THE LAYER, not the viewport (his report, 2026-09-18: the
     dock's left end sat under the sidebar). The layer already starts after
     the rail, so centering within it cannot spill back over the rail however
     wide the bar gets. */
  position: absolute; top: calc(var(--wb-top-inset, 0px) + 2px); left: 50%;
  margin: 0;
  transform: translate(-50%, 0);
  transition: transform 0.22s ease;
  pointer-events: auto;
  /* TRANSPARENT over the panels (his order) — the icons carry themselves,
     exactly as they do on the wall, at their stylesheet size (padding here
     would shift them). */
  background: transparent; border: none; padding: 0;
  /* CENTERED MEANS CENTERED (his report, 2026-09-18). A bar wider than the
     content area overflows both sides and clips at the right, which reads as
     left-aligned. Capped to the space it actually has, so it centers while it
     fits and slides within itself when it does not. */
  /* NEVER a scroll container (his report, 2026-09-18: the dock looked like it
     was behind something). overflow makes the bar clip anything drawn outside
     it, and a tile's hover ring and tooltip are both outside it, so the first
     icon came back sliced. The bar pages its own icons, so it does not need to
     scroll. */
  max-width: calc(100% - 24px);
  overflow: visible;
}
body.echo-dock-tucked:not(.echo-dock-peek) #echo-dock-layer .echo-topbar {
  transform: translate(-50%, calc(-100% - 24px));
}
.echo-topbar-home { display: none; }
/* The hint sliver at the top center is OFF (his order, 2026-09-15: "when the
   dock is hidden remove this line"). The hover strip below still reveals the
   dock; hidden, not deleted. */
body.echo-dock-tucked:not(.echo-dock-peek)::after { display: none; }
/* The invisible top strip that catches the peek hover — webviews swallow
   host mouse events, so the strip sits ABOVE the panel layers. Present only
   while the dock is tucked, so it never steals clicks otherwise. */
.echo-dock-hotstrip { display: none; }
body.echo-dock-tucked .echo-dock-hotstrip {
  /* BACK TO A SLIVER (his report, 2026-09-18: at 34px it swallowed the agent
     panel's own header buttons). The strip exists only for WEBVIEWS, which eat
     host mouse events; everywhere else a document-level mousemove watches a
     much deeper band without capturing a single click. */
  display: block; position: fixed; top: var(--wb-top-inset, 0px); left: var(--rail-w, 0px); right: 0; height: 12px;
  z-index: 98999; background: transparent;
}
body.echo-dock-tucked.echo-dock-peek .echo-dock-hotstrip { display: none; }

/* (Close-all's always-present + dim-when-idle rules live with CC's above.) */
/* The layout bar RETIRES (his order, 2026-08-28): its pill + tooltip sat in
   the dock's hover zone and double-served the new Close-all slot. Hidden,
   not deleted. */
.echo-layout-bar { display: none !important; }

/* Desktop: the window drag strip owns the top of the page — the tucked-dock
   chrome (sliver, hot zone, peeked bar) starts below it. */
body.wb-has-dragstrip { --wb-top-inset: 38px; }

/* SHOW THE DOCK = off (his order, 2026-10-04; pref `dockEnabled`, Settings →
   Appearance → Dock, shared by desktop and web): the dock is NOT RENDERED —
   not tucked, not parked — its portal layer and its hover strip go with it,
   and every band measured from it (the search pill, the card band, help/
   dock-band.ts) reads zero. Everything the dock opened stays reachable from
   the rail and the keyboard (New session, Settings, ⌘⇧Space, Close all). */
body.echo-dock-off .echo-topbar,
body.echo-dock-off #echo-dock-layer,
body.echo-dock-off .echo-dock-hotstrip { display: none !important; }


/* (The standalone Loops PAGE is gone — loops are settings; its card,
   editor and key-row styles went with it. See .loop-acc above.) */

/* Agent terminal header (his spec, 2026-09-11): the tab row becomes the
   session-name row with the shared control cluster — identical to the chat
   head. Plain terminals keep their tabs; this styles only the agent face. */
.ws-agent-termhead { display: flex; align-items: center; gap: 4px; padding: 3px 8px; }
.ws-agent-term-title {
  font-size: 12px; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60%;
}
/* The agent terminal head's recents IS the chat head's dropdown —
   .wb-session-menu, opened through __glyphhSessionsMenu. No styles of its
   own on purpose: one surface, two places it can be opened from. */

/* Agent card dev-tools kebab — sits with the head's icon buttons. */
.echo-card-devtools svg { width: 15px; height: 15px; }

/* Org Models — the vendor row's key state (✓ set · ✗ removes + disables) */
.mdl-key-check { display: inline-flex; width: 18px; height: 18px; color: #2ecc71; flex: none; }
.mdl-key-check svg { width: 100%; height: 100%; }
.mdl-key-remove { color: #f43f5e; }

/* Provider filter drop (org Models + Roles): search on top, capped list.
   OWN panel chrome — appended to <body>, it inherits nothing (his report:
   it rendered as glass over the page). */
/* Roles list: the budget traffic light (his spec, 2026-09-11). */
.ws-budget-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin-right: 2px; vertical-align: middle;
}
.ws-budget-dot.green { background: #33d17a; }
.ws-budget-dot.yellow { background: #e5a50a; }
.ws-budget-dot.red { background: #e01b24; }

/* ── Models: the + New Provider install modal (his order, 2026-09-11) ─────── */
.mdl-install-modal { width: 540px; max-width: 92vw; }
.mdl-install-list, .mdl-install-models {
  max-height: 200px; overflow-y: auto; margin: 6px 0 12px;
  border: 1px solid var(--border); border-radius: 8px;
}
.mdl-install-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 7px 10px; cursor: pointer;
}
.mdl-install-row:hover { background: rgba(255, 255, 255, 0.04); }
.mdl-install-row.selected { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.mdl-install-model {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 6px 10px;
}

.mdl-provider-drop {
  position: fixed; width: 260px; padding: 6px;
  background: var(--surface-2, #1c1c1f);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
}
.mdl-provider-drop-list { max-height: 300px; overflow-y: auto; display: flex; flex-direction: column; }
.mdl-provider-drop .code-drop-item.active { color: var(--accent); }

/* Header ⓘ (Roles → Models "Auto exempt") + its explanation bubble */
.ws-info-btn {
  appearance: none; background: none; border: none; padding: 0 2px; cursor: pointer;
  color: var(--text-3); font-size: 13px; line-height: 1; vertical-align: middle;
}
.ws-info-btn:hover { color: var(--text); }
.ws-info-pop { width: 290px; padding: 12px 14px; font-size: 12.5px; line-height: 1.5; color: var(--text-2); }

/* ── Plan gating (help/plan-gate.ts) ──────────────────────────────────────
   A locked surface stays VISIBLE and inert (his call: visible + disabled +
   upsell, never hidden — an admin has to be able to see what they'd get).
   The dim is on the CONTROLS, not the copy, so the explanation stays
   readable while the things you can't use recede. */
.plan-locked .settings-input,
.plan-locked .action-btn,
.plan-locked input,
.plan-locked select,
.plan-locked textarea,
.plan-locked button { opacity: 0.45; cursor: not-allowed; }
.plan-locked-note {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 14px; padding: 10px 12px;
  border: 1px solid var(--border-2); border-left: 3px solid var(--accent);
  border-radius: 8px; background: var(--surface-2);
  color: var(--text-2); font-size: 13px; line-height: 1.45;
}
/* The note itself is never dimmed — it is the one thing that must read. */
.plan-locked > .plan-locked-note { opacity: 1; }
/* The one door out of a gate — the Billing link, on every gated page. */
.plan-locked-link { color: var(--accent); text-decoration: none; white-space: nowrap; flex-shrink: 0; }
.plan-locked-link:hover { text-decoration: underline; }

/* ── Loops as SETTINGS (help/settings-loops.ts) ───────────────────────────
   The fixed set, one expandable row each — the model catalog's grammar:
   name + optional sub-label left, the enable toggle pinned right, the
   configuration underneath. No New, no Delete: loops are settings. */
.loop-acc { border: 1px solid var(--border-2); border-radius: 10px; margin-bottom: 8px; background: var(--surface); }
.loop-acc-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px; cursor: pointer; user-select: none;
}
.loop-acc-head:hover { background: var(--hover); border-radius: 10px; }
.loop-acc.open > .loop-acc-head { border-bottom: 1px solid var(--border-2); border-radius: 10px 10px 0 0; }
.loop-acc-chev { width: 14px; height: 14px; color: var(--text-3); transition: transform 0.15s; flex: none; }
.loop-acc.open .loop-acc-chev { transform: rotate(90deg); }
.loop-acc-name { font-size: 14px; font-weight: 600; color: var(--text); }
.loop-acc-sub { font-size: 12px; color: var(--text-3); }
.loop-acc-spacer { flex: 1; }
/* The toggle is its own control — clicking it must not expand the row. */
.loop-acc-toggle { margin: 0; flex: none; }
/* The row kebab sits to the RIGHT of the toggle, in a slot that is ALWAYS
   reserved — a row without a menu (org connections) must not let its toggle
   drift right past the others. */
.loop-acc-kebab-slot { flex: none; width: 24px; margin-left: 8px; display: inline-flex; justify-content: flex-end; align-items: center; }
/* The glyph takes the muted text colour like every other row menu — inside an
   accordion head it was inheriting the head's text colour (his report,
   2026-09-12: "the three dots are white"). */
.loop-acc-kebab-slot .lib-row-kebab { color: var(--text-3); font-size: 16px; line-height: 1; }
.loop-acc-kebab-slot .lib-row-kebab:hover { color: var(--text); background: var(--hover); }
.loop-acc-body { padding: 6px 14px 16px; display: flex; flex-direction: column; }
.loop-acc-body > .settings-input { flex: 0 0 auto; }

/* Role → Members: the +Add picker is a searchable table, so it needs room
   the field-based form modal doesn't reserve. */
.ws-add-member-box { min-width: min(560px, 92vw); }
.ws-add-member-list { max-height: 46vh; overflow-y: auto; margin-top: 10px; }
.ws-add-member-list tr { cursor: pointer; }

/* ── Org › Library (help/org-library.ts) ─────────────────────────────────
   The single curated table: type pills, a truncating description cell, and
   the truncating description cell. */
.orglib-pill {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 500; border: 1px solid var(--border);
  color: var(--text-2); background: var(--surface-2);
}
.orglib-pill-task  { border-color: color-mix(in srgb, var(--accent) 40%, transparent); color: var(--accent); }
.orglib-pill-agent { border-color: color-mix(in srgb, #38bdf8 40%, transparent); color: #38bdf8; }
.orglib-pill-skill { border-color: color-mix(in srgb, #f59e0b 40%, transparent); color: #f59e0b; }
.orglib-desc { max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Settings → Connections: the tools SECTION collapses like the row above it. */
.conncfg-tools-head { display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; padding: 10px 0; }
.conncfg-tools-chev { width: 13px; height: 13px; color: var(--text-3); transition: transform 0.15s; flex: none; }
.conncfg-tools.open .conncfg-tools-chev { transform: rotate(90deg); }
.conncfg-tools .conncfg-tools-body { display: none; }
.conncfg-tools.open .conncfg-tools-body { display: block; }

/* Settings → Connections: the value column is a SHARE of the row, not a
   fixed pixel width — it tracks the panel instead of leaving a ragged gap at
   any other size (his correction, 2026-09-12: "fix the percentage"). */
.settings-panel[data-sub="connections-cfg"] .set-pref-row > .set-pref-text { flex: 1 1 auto; min-width: 0; }
.settings-panel[data-sub="connections-cfg"] .set-pref-value { flex: 0 0 55%; width: 55%; }
.settings-panel[data-sub="connections-cfg"] .set-pref-value > * { width: 100%; }
.settings-panel[data-sub="connections-cfg"] .set-pref-value > .settings-toggle { width: auto; margin-left: auto; }

/* Settings → Connections (help/settings-connections.ts): the far-left icon
   in the accordion head and the app rows of the New-connection modal. */
.conncfg-icon { width: 20px; height: 20px; border-radius: 5px; margin-right: 10px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; }
.conncfg-icon img { width: 100%; height: 100%; object-fit: contain; border-radius: 5px; }
.conncfg-icon-initial { font-size: 11px; font-weight: 600; color: var(--text-2); }
/* The adopted section is a PARTS BIN, not a page: only its catalog modal and
   its tools pane are wanted. The toolbar, the card list and the page-level
   detail editor (breadcrumb + head + Cancel/Save) all stay hidden — the tools
   pane has already relocated into the open accordion row by the time the
   detail un-hides itself (his report, 2026-09-12: the editor rendered under
   the list). */
.conncfg-legacy #connections-toolbar,
.conncfg-legacy #connections-list { display: none !important; }
/* The page EDITOR is hidden wherever it sits inside this page — bin, row, or
   anywhere a previous build left it. Scoping the hide to the bin let a node
   that had been relocated render its breadcrumb, Remove/Cancel/Save and its
   own field layout inside the accordion (his report, 2026-09-12). */
.settings-panel[data-sub="connections-cfg"] #conn-detail { display: none !important; }
/* …EXCEPT the Custom MCP form, which IS that same node. Hiding it outright
   made "+ Custom MCP" a no-op (his report, 2026-09-12): the button fired, the
   form opened, and it opened inside something invisible. The host flips this
   class for the duration of that flow. */

/* While the Custom MCP form is open it OWNS the page: the header, the search
   toolbar and the accordion step aside, exactly as the Connections page hides
   its list behind its editor. */
.settings-panel[data-sub="connections-cfg"].editing > h2,
.settings-panel[data-sub="connections-cfg"].editing > .section-desc,
.settings-panel[data-sub="connections-cfg"].editing > .crud-toolbar,
/* Inside an OPEN ROW the detail is the row's form — visible there, hidden in
   the parts-bin host it came from. */


/* ── Settings → Build → Skills (2026-09-16) — the list/detail pages ───────── */
.settings-panel.skills-panel.active { display: flex; flex-direction: column; min-height: 0; }
.skills-head { position: relative; display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 14px; min-height: 36px; }
.skills-head h2 { margin: 0; font-size: 20px; font-weight: 600; }
/* The search is centered on the page itself, whatever the title and button widths. */
.skills-head > .skills-search { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: min(420px, 46%); }
.skills-search { display: flex; align-items: center; gap: 8px; width: 100%; padding: 6px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-2); color: var(--text-3); }
.skills-search svg { width: 14px; height: 14px; flex-shrink: 0; }
.skills-search input { flex: 1; border: none; background: none; color: var(--text); font-size: 13px; outline: none; }
.skills-tabs { display: flex; align-items: center; gap: 4px; margin-bottom: 10px; }
.skills-pill { display: inline-flex; align-items: center; gap: 6px; margin-left: 8px; padding: 5px 10px; border: 1px solid var(--border); border-radius: 7px; background: var(--surface-2); color: var(--text-2); font: inherit; font-size: 12.5px; cursor: pointer; }
.skills-pill:hover { color: var(--text); background: var(--hover); }
.skills-pill.on { color: var(--text); border-color: var(--accent); }
.skills-pill svg { width: 13px; height: 13px; }
.skills-pill .skills-pill-caret { width: 12px; height: 12px; color: var(--text-3); }
.skills-menu .code-menu-label { padding: 6px 10px 4px; font-size: 11.5px; color: var(--text-3); }
.skills-menu .code-menu-item { display: flex; align-items: center; gap: 8px; }
.skills-menu .code-menu-item > span:first-child { flex: 1; }
.skills-menu .code-menu-item .menu-check { width: 14px; height: 14px; color: var(--accent); visibility: hidden; }
.skills-menu .code-menu-item.checked .menu-check { visibility: visible; }
.skills-menu .code-menu-item .menu-arrow { width: 12px; height: 12px; color: var(--text-3); }
.skills-tabs.detail { border-bottom: 1px solid var(--border); margin-bottom: 16px; gap: 0; }
.skills-tab { padding: 6px 10px; border: none; border-radius: 7px; background: none; color: var(--text-3); font-size: 13px; cursor: pointer; }
.skills-tab:hover { color: var(--text); }
.skills-tab.active { background: var(--hover); color: var(--text); }
.skills-tabs.detail .skills-tab { border-radius: 0; padding: 8px 12px; margin-bottom: -1px; border-bottom: 2px solid transparent; background: none; }
.skills-tabs.detail .skills-tab.active { border-bottom-color: var(--text); }
.skills-count { font-size: 12px; color: var(--text-3); }
.skill-group { margin-bottom: 18px; }
.skill-group-head { display: flex; align-items: baseline; gap: 6px; padding: 6px 4px; font-size: 13px; font-weight: 600; color: var(--text); }
.skill-group-count { font-weight: 400; color: var(--text-3); font-size: 12px; }
.skill-row { display: flex; align-items: center; gap: 14px; padding: 14px 8px; border-top: 1px solid var(--border); }
.skill-row.openable { cursor: pointer; }
.skill-row.openable:hover { background: var(--hover); border-radius: 8px; }
.skill-row.disabled .skill-row-main { opacity: .5; }
.skill-tile-icon { width: 40px; height: 40px; border-radius: 9px; background: var(--surface-2); border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; color: var(--text-2); flex-shrink: 0; }
.skill-tile-icon svg { width: 21px; height: 21px; }
.skill-tile-icon.lg { width: 52px; height: 52px; border-radius: 12px; }
.skill-tile-icon.lg svg { width: 26px; height: 26px; }
.skill-row-main { flex: 1; min-width: 0; }
.skill-row-name { font-size: 13.5px; font-weight: 500; color: var(--text); }
.skill-row-sub { display: flex; gap: 6px; font-size: 12px; color: var(--text-3); white-space: nowrap; overflow: hidden; }
.skill-row-desc { overflow: hidden; text-overflow: ellipsis; }
.skill-row-right { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.skill-row-date { font-size: 12px; color: var(--text-3); }
.skill-add-btn { min-width: 34px; }
.skills-kebab { width: 28px; height: 28px; border: none; border-radius: 6px; background: none; color: var(--text-3); font-size: 16px; cursor: pointer; }
.skills-kebab:hover { background: var(--hover); color: var(--text); }
.skills-menu { position: fixed; z-index: 10000; }
.layout-agent-cell { flex-direction: column; align-items: stretch; }
.layout-cell-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 8px 12px; }
.layout-cell-field { display: flex; flex-direction: column; gap: 4px; }
.layout-cell-field-label { font-size: 11.5px; color: var(--text-3); }
.layout-cell-field .layout-folder-row { display: flex; gap: 4px; align-items: center; }
.layout-cell-field .layout-folder-row input { flex: 1; min-width: 0; }
.skills-menu .code-menu-sep { height: 1px; margin: 4px 6px; background: var(--border); }
.skills-back { display: inline-flex; align-items: center; gap: 6px; margin-bottom: 14px; padding: 4px 6px; border: none; background: none; color: var(--text-3); font-size: 13px; cursor: pointer; border-radius: 6px; }
.skills-back svg { width: 14px; height: 14px; }
.skills-back:hover { color: var(--text); background: var(--hover); }
.skill-detail-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.skill-detail-name { font-size: 16px; font-weight: 600; color: var(--text); }
.skill-detail-sub { font-size: 12px; color: var(--text-3); }
.skills-switch { position: relative; display: inline-block; width: 34px; height: 20px; }
.skills-switch input { opacity: 0; width: 0; height: 0; }
.skills-switch span { position: absolute; inset: 0; border-radius: 20px; background: var(--border); transition: background .15s; cursor: pointer; }
.skills-switch span::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: transform .15s; }
.skills-switch input:checked + span { background: var(--accent); }
.skills-switch input:checked + span::after { transform: translateX(14px); }
/* FULL WIDTH UNLESS THERE IS A SIDEBAR (his order, 2026-09-17): every detail
   pane wore the Overview's two-column grid, so the Agents, Connections, Runs,
   Skills and Tools lists all stopped 240px short for a sidebar they do not
   have, and their descriptions truncated mid-word. The column exists only
   where the author card does. */
.skill-overview { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; max-width: 100%; }
.skill-overview:has(.skill-author-card) { grid-template-columns: minmax(0, 1fr) 240px; }
.skill-overview-main { min-width: 0; }
.skill-overview .lib-md-render pre { overflow-x: auto; max-width: 100%; }
.skill-overview-label { font-size: 12px; color: var(--text-3); margin-bottom: 6px; }
.skill-overview-desc { font-size: 13.5px; color: var(--text); margin-bottom: 18px; }
.skill-author-card { background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; height: fit-content; }
.skill-author { font-size: 13.5px; color: var(--text); }
.skill-author-meta { font-size: 12px; color: var(--text-3); margin-top: 4px; }
.skill-contents-bar { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.skill-version { padding: 5px 10px; border: 1px solid var(--border); border-radius: 7px; font-size: 12.5px; color: var(--text-2); background: var(--surface-2); cursor: pointer; }
.skill-version:disabled { cursor: default; opacity: .8; }
.skill-files { display: grid; grid-template-columns: 240px 1fr; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; min-height: 460px; height: calc(100vh - 340px); }
.skill-tree { border-right: 1px solid var(--border); padding: 10px 6px; overflow-y: auto; background: var(--surface-2); }
.skill-tree-dir { display: flex; align-items: center; gap: 6px; width: 100%; padding: 6px 8px; border: none; border-radius: 6px; background: none; font: inherit; font-size: 12.5px; color: var(--text-2); cursor: pointer; text-align: left; }
.skill-tree-dir:hover { background: var(--hover); color: var(--text); }
.skill-tree-dir svg { width: 14px; height: 14px; flex-shrink: 0; }
.skill-tree-dir span { flex: 1; }
.skill-tree-dir .skill-tree-chevron { color: var(--text-3); transform: rotate(-90deg); transition: transform .12s; }
.skill-tree-dir.open .skill-tree-chevron { transform: none; }
.skill-tree-file { display: block; width: 100%; text-align: left; padding: 5px 10px; border: none; border-radius: 6px; background: none; color: var(--text-3); font-size: 12.5px; cursor: pointer; }
.skill-tree-file:hover { background: var(--hover); color: var(--text); }
.skill-tree-file.active { background: var(--hover); color: var(--text); }
.skill-viewer { display: flex; flex-direction: column; min-width: 0; }
.skill-viewer-bar { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--border); font-size: 12px; color: var(--text-3); }
.skill-viewer-bar code { font-size: 12px; color: var(--text-3); }
.skill-view-toggle { display: inline-flex; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.skill-view-toggle button { padding: 3px 8px; border: none; background: none; color: var(--text-3); font-size: 12px; cursor: pointer; }
.skill-view-toggle button.active { background: var(--hover); color: var(--text); }
.skill-file-preview { flex: 1; min-height: 0; overflow-y: auto; padding: 16px 20px; }
.skill-file-editor { flex: 1; min-height: 0; }

/* ── Skills → Discover (his screens, 2026-09-16) ── */
.disc-featured { display: flex; align-items: center; gap: 24px; padding: 24px 28px; margin-bottom: 22px; border-radius: 14px; background: linear-gradient(135deg, rgba(140, 59, 242, .14), rgba(140, 59, 242, .04)); border: 1px solid var(--border); }
.disc-featured-main { flex: 1; min-width: 0; }
.disc-featured-from { font-size: 12px; color: var(--text-3); margin-bottom: 6px; }
.disc-featured-name { font-size: 22px; font-weight: 600; color: var(--text); margin-bottom: 6px; }
.disc-featured-desc { font-size: 13.5px; color: var(--text-2); margin-bottom: 14px; max-width: 560px; }
.disc-featured-art { color: var(--accent); opacity: .85; flex-shrink: 0; }
.skill-add-wide { min-width: 64px; }
.disc-shelf { margin-bottom: 22px; }
.disc-shelf-head { display: flex; align-items: center; justify-content: space-between; padding: 4px 2px 10px; font-size: 13px; font-weight: 600; color: var(--text); }
.disc-link { border: none; background: none; color: var(--text-3); font: inherit; font-size: 12.5px; font-weight: 400; cursor: pointer; }
.disc-link:hover { color: var(--text); }
.disc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; }
.disc-card.openable, .disc-row.openable, .disc-featured.openable { cursor: pointer; }
.disc-card.openable:hover, .disc-row.openable:hover { background: var(--hover); }
.disc-card { display: flex; gap: 12px; align-items: flex-start; padding: 14px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-2); }
.disc-card-main { flex: 1; min-width: 0; }
.disc-card-name { font-size: 13.5px; font-weight: 600; color: var(--text); margin-bottom: 3px; }
.disc-card-desc { font-size: 12.5px; color: var(--text-2); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; margin-bottom: 6px; }
.disc-card-meta { font-size: 12px; color: var(--text-3); }
.disc-cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.disc-cat { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-2); color: var(--text); font: inherit; font-size: 13.5px; cursor: pointer; text-align: left; }
.disc-cat:hover { background: var(--hover); }
.disc-cat-icon { width: 44px; height: 44px; border-radius: 10px; background: var(--bg); border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; color: var(--text-2); flex-shrink: 0; }
.disc-cat-label { flex: 1; }
.disc-cat-count { font-size: 12px; color: var(--text-3); }
.disc-back { display: inline-flex; align-items: center; gap: 6px; border: none; background: none; color: var(--text-2); font: inherit; font-size: 13px; cursor: pointer; padding: 4px 2px; margin-bottom: 8px; }
.disc-back:hover { color: var(--text); }
.disc-row { display: flex; align-items: center; gap: 12px; padding: 12px 6px; border-top: 1px solid var(--border); }
.disc-row-main { flex: 1; min-width: 0; }
.disc-row-title { display: flex; align-items: center; gap: 6px; font-size: 13.5px; font-weight: 500; color: var(--text); margin-bottom: 3px; }
.disc-row-sub { font-size: 12.5px; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.disc-row-installs { font-size: 12px; color: var(--text-3); white-space: nowrap; }
.disc-chip { font-size: 11px; padding: 1px 7px; border-radius: 999px; background: var(--hover); color: var(--text-2); }
.disc-chip.new { background: rgba(140, 59, 242, .18); color: var(--accent); }

/* ── Connections in the Skills grammar (his order, 2026-09-16) ── */
.conn2-chips { display: flex; gap: 4px; margin: 2px 0 12px; }
.conn2-chip { padding: 5px 10px; border: none; border-radius: 7px; background: none; color: var(--text-3); font: inherit; font-size: 13px; cursor: pointer; }
.conn2-chip:hover { color: var(--text); }
.conn2-chip.active { background: var(--hover); color: var(--text); }
.conn2-table { display: flex; flex-direction: column; }
.conn2-tr { display: grid; grid-template-columns: 28px minmax(0, 1fr) 160px 130px; align-items: center; gap: 12px; padding: 11px 8px; border-top: 1px solid var(--border); }
.conn2-tr.head { border-top: none; padding: 6px 8px; font-size: 12.5px; color: var(--text-3); }
.conn2-tr.openable { cursor: pointer; }
.conn2-tr.openable:hover { background: var(--hover); border-radius: 8px; }
.conn2-icon { width: 24px; height: 24px; border-radius: 6px; display: inline-flex; align-items: center; justify-content: center; overflow: hidden; background: var(--surface-2); border: 1px solid var(--border); flex-shrink: 0; }
.conn2-icon img { width: 100%; height: 100%; object-fit: contain; }
.conn2-icon.lg { width: 44px; height: 44px; border-radius: 10px; }
.conn2-icon.xl { width: 72px; height: 72px; border-radius: 16px; }
.conn2-icon-initial { font-size: 12px; font-weight: 600; color: var(--text-2); }
.conn2-icon.xl .conn2-icon-initial { font-size: 26px; }
.conn2-name { font-size: 13.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conn2-type { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-3); }
.conn2-badge { font-size: 11px; padding: 1px 7px; border-radius: 999px; background: var(--hover); color: var(--text-2); }
.conn2-status { display: flex; align-items: center; }
.conn2-check { color: var(--text-2); display: inline-flex; padding-left: 6px; }
.conn2-connect { min-width: 84px; }
.conn2-plus { width: 30px; height: 30px; padding: 0; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.conn2-plus.done { color: #4ade80; border-color: transparent; background: rgba(74, 222, 128, .12); }
.conn2-popular { margin-top: 22px; }
.conn2-popular-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.conn2-pop .conn2-name { flex: 1; }
.conn2-pop.openable, .conn2-dir-card.openable { cursor: pointer; }
.conn2-pop.openable:hover, .conn2-dir-card.openable:hover { background: var(--hover); }
.conn2-crumb { display: flex; gap: 8px; font-size: 13.5px; color: var(--text-3); margin: 2px 0 12px; }
.conn2-crumb .here { color: var(--text); }
.conn2-dir-bar { display: flex; gap: 8px; margin-bottom: 18px; }
.conn2-dir-search { flex: 1; max-width: none; }
.conn2-dir-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 12px; }
.conn2-dir-card { display: flex; align-items: center; gap: 12px; padding: 14px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-2); }
.conn2-dir-main { flex: 1; min-width: 0; }
.conn2-dir-name { display: flex; align-items: center; gap: 6px; font-size: 13.5px; font-weight: 600; color: var(--text); }
.conn2-verified { color: #4ade80; display: inline-flex; }
.conn2-dir-desc { font-size: 12.5px; color: var(--text-2); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.conn2-hero { display: flex; align-items: center; gap: 22px; padding: 36px 26px; margin: 0 -8px 18px; border-radius: 14px; background: var(--surface-2); border: 1px solid var(--border); }
.conn2-hero-main { flex: 1; min-width: 0; }
.conn2-hero-name { font-size: 24px; font-weight: 600; color: var(--text); margin-bottom: 4px; }
.conn2-hero-desc { font-size: 13.5px; color: var(--text-2); max-width: 560px; }
.conn2-hero-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.conn2-connected { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 8px; background: var(--hover); color: var(--text); font-size: 13px; }
.conn2-detail-body { padding: 0 4px 24px; }
.conn2-about { font-size: 14px; line-height: 1.55; color: var(--text-2); margin: 0 0 24px; }
.conn2-h3 { font-size: 18px; font-weight: 600; color: var(--text); margin: 24px 0 12px; }
.conn2-muted { font-size: 12.5px; color: var(--text-3); }
.conn2-tool-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.conn2-tool-chip { font-family: var(--font-mono); font-size: 12px; padding: 5px 10px; border-radius: 8px; background: var(--hover); color: var(--text); }
.conn2-tool-chip.off { opacity: .45; text-decoration: line-through; }
.conn2-chip-muted { font-size: 12.5px; color: var(--text-3); }
.conn2-perms { margin-top: 22px; }
.conn2-perms-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.conn2-perm-list { border-top: 1px solid var(--border); }
.conn2-perm { display: flex; align-items: center; gap: 12px; padding: 10px 4px; border-bottom: 1px solid var(--border); }
.conn2-perm-main { flex: 1; min-width: 0; cursor: pointer; }
.conn2-perm-name { font-size: 13.5px; color: var(--text); }
.conn2-perm-desc { font-size: 12.5px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conn2-perm.expanded .conn2-perm-desc { white-space: normal; }
.conn2-fields { margin: 0 0 12px; }
.conn2-meta { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 18px 24px; margin-top: 28px; padding-top: 22px; border-top: 1px solid var(--border); }
.conn2-meta-k { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-3); margin-bottom: 4px; }
.conn2-meta-v { font-size: 13.5px; color: var(--text); word-break: break-all; }
.conn2-tr { grid-template-columns: 28px minmax(0, 1fr) 150px 110px; }
.conn2-tr.head .conn2-head-connector { grid-column: 1 / 3; }
.conn2-head-status, .conn2-status { justify-self: end; }
.conn2-status .conn2-check { padding: 0 10px; }
.conn2-tool-chip { font-family: inherit; font-size: 12.5px; padding: 6px 12px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--border); color: var(--text); }
.conn2-phead { display: flex; align-items: center; gap: 10px; margin: 4px 0 12px; }
.conn2-phead .conn2-icon { width: 28px; height: 28px; border-radius: 7px; }
.conn2-phead-name { font-size: 16px; font-weight: 600; color: var(--text); }
.conn2-groups { display: flex; flex-direction: column; }
.conn2-group { border-bottom: 1px solid var(--border); }
.conn2-group-head { display: flex; align-items: center; gap: 8px; padding: 12px 4px; cursor: pointer; user-select: none; }
.conn2-group-chev { color: var(--text-3); transition: transform .12s; }
.conn2-group.open .conn2-group-chev { transform: rotate(90deg); }
.conn2-group-label { font-size: 14px; color: var(--text); }
.conn2-group-count { font-size: 11.5px; padding: 1px 7px; border-radius: 6px; background: var(--hover); color: var(--text-2); }
.conn2-mode-btn { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface-2); color: var(--text); font: inherit; font-size: 13px; cursor: pointer; }
.conn2-mode-btn:disabled { cursor: default; opacity: .7; }
.conn2-group-body { padding: 0 0 6px 22px; }
.conn2-prow { display: flex; align-items: center; gap: 12px; padding: 11px 4px; border-top: 1px solid var(--border); }
.conn2-seg { display: inline-flex; gap: 2px; padding: 2px; border-radius: 8px; background: var(--surface-2); border: 1px solid var(--border); flex-shrink: 0; }
.conn2-seg button { width: 26px; height: 24px; border: none; border-radius: 6px; background: none; color: var(--text-3); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.conn2-seg button:hover { color: var(--text); }
.conn2-seg button.active { background: var(--hover); color: var(--text); }
.conn2-seg button:disabled { cursor: default; }
.conn2-more { padding: 16px; text-align: center; font-size: 12.5px; color: var(--text-3); }
.conn2-crumb .crumb-link { cursor: pointer; }
.conn2-crumb .crumb-link:hover { color: var(--text); }
.conn2-filter { white-space: nowrap; }
.conn2-link { color: var(--accent); text-decoration: none; }
.conn2-link:hover { text-decoration: underline; }
.conn2-perm-main { position: relative; display: flex; align-items: center; gap: 6px; cursor: default; }
.conn2-pop { position: absolute; left: 0; top: calc(100% + 6px); z-index: 20; max-width: 520px; padding: 10px 12px; border-radius: 10px; background: var(--bg-raised); border: 1px solid var(--border-2); box-shadow: 0 8px 24px rgba(0, 0, 0, .18); font-size: 12.5px; line-height: 1.45; color: var(--text-2); white-space: normal; }
/* ── Apps: the Overview's gallery and dependencies ── */
.app-overview-extra { margin-top: 18px; }
.app-gallery { margin-bottom: 18px; }
.app-gallery-main img { width: 100%; max-height: 380px; object-fit: contain; border-radius: 10px; border: 1px solid var(--border); background: var(--surface-2); }
.app-gallery-caption { font-size: 12.5px; color: var(--text-3); margin: 6px 2px 0; }
.app-gallery-thumbs { display: flex; gap: 8px; margin-top: 8px; overflow-x: auto; }
.app-gallery-thumbs img { width: 96px; height: 60px; object-fit: cover; border-radius: 6px; border: 1px solid var(--border); cursor: pointer; opacity: .7; }
.app-gallery-thumbs img.active, .app-gallery-thumbs img:hover { opacity: 1; border-color: var(--accent); }
.app-deps-list { display: flex; flex-wrap: wrap; gap: 8px; }
.app-dep { font-size: 12.5px; padding: 5px 10px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--border); color: var(--text); }

.app-bundle-list { display: flex; flex-direction: column; margin-top: 10px; }
.app-bundle-list .skill-row:first-child { border-top: none; }
.app-conn-state { font-size: 12px; color: var(--text-3); }
.app-conn-state.on { color: var(--accent); }

.tabs-list { margin-top: 4px; }
.tabs-list .conn2-chips { margin: 2px 0 12px; }
.drip-recipe { font-family: var(--font-mono); font-size: 12px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.loop-mark { width: 14px; height: 14px; border-radius: 3px; margin-right: 7px; flex: none; object-fit: contain; }
.code-sess-mark { width: 14px; height: 14px; flex: none; display: inline-flex; align-items: center; justify-content: center; margin-right: 6px; }
.code-sess-mark img { width: 14px; height: 14px; border-radius: 3px; object-fit: contain; }
/* The Glyphh mascot is a tall figure, not a square favicon — at favicon size it
   read as a speck (his eye, 2026-09-21). It gets the whole row height and no plate rounding. */
.loop-mark.cli-mark-glyphh, .code-sess-mark img.cli-mark-glyphh { width: 20px; height: 20px; margin: -3px 5px -3px -3px; border-radius: 0; }
.code-sess-mark img.cli-mark-glyphh { margin: -3px; }
.app-rail-tile .tile-icon img.cli-mark-glyphh { width: 28px; height: 28px; border-radius: 0; }

.app-rail-search { display: flex; align-items: center; gap: 6px; }
.app-rail-search .search-clear-wrap, .app-rail-search input { flex: 1; min-width: 0; }
.rail-filter-btn { flex: none; width: 24px; height: 24px; border-radius: 6px; border: 1px solid transparent; background: none; color: var(--text-3); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.rail-filter-btn:hover { color: var(--text); background: var(--hover); }
.rail-filter-btn.active { color: var(--accent); border-color: var(--accent); }
.code-menu-item .loop-mark { vertical-align: middle; }
.code-menu-item .menu-check { margin-left: auto; }

/* ── THE FIXED SIDEBAR (his order, 2026-09-16): the rail is the one fixed
   panel, full height at the left, carrying the only header on the page. The
   content side starts at the very top; work panels bring their own heads. ── */
body { --titlebar-h: 0px; --rail-top-h: 38px; --rail-w-open: 264px; --rail-w: var(--rail-w-open); }
/* Collapsed: the sidebar leaves entirely (content takes the width); hovering
   the strip's icon PEEKS it back as an overlay in its old place. */
body.rail-collapsed { --rail-w: 0px; }
body.rail-collapsed #app-rail { width: var(--rail-w-open); transform: translateX(-100%); transition: transform 0.16s ease; box-shadow: none; }
body.rail-collapsed.rail-peek #app-rail { transform: translateX(0); box-shadow: 8px 0 24px rgba(0, 0, 0, 0.35); }
/* The strip: traffic lights (84px), then the expand and the Echo buttons.
   --rail-strip-w is what the top-left panel head clears (his report,
   2026-09-19: "New session" sat under the traffic lights). */
body { --rail-strip-w: 148px; }
#rail-collapsed-strip { position: fixed; top: 0; left: 0; height: var(--rail-top-h); width: var(--rail-strip-w); display: flex; align-items: center; justify-content: flex-start; gap: 2px; padding-left: 84px; z-index: 210; }
/* Whatever head lands under the strip is marked by the workbench (it reads
   the rects, since the agent rides a fixed overlay and the rails may nest). */
body.rail-collapsed .echo-card-head.clears-strip,
body.rail-collapsed .ws-rail-slot-header.clears-strip,
body.rail-collapsed .code-agent-head.clears-strip { padding-left: var(--rail-strip-w) !important; }
#rail-collapsed-strip.hidden { display: none; }
#rail-collapsed-strip .app-rail-drag { display: none; }
body.rail-collapsed.rail-peek #rail-collapsed-strip { display: none; }
#echo-dock-layer, .echo-dock-hotstrip { left: var(--rail-w) !important; }
body.rail-resizing, body.rail-resizing * { cursor: col-resize !important; user-select: none; }
body.rail-resizing #app-rail, body.rail-resizing #help-overlay { transition: none !important; }
#app-rail-resize { position: fixed; top: 0; left: calc(var(--rail-w) - 3px); bottom: 0; width: 7px; cursor: col-resize; z-index: 201; }
#app-rail-resize:hover { background: color-mix(in srgb, var(--accent) 45%, transparent); }
body.rail-collapsed #app-rail-resize { display: none; }
#app-rail-top { pointer-events: auto; }
#app-rail {
  position: fixed; top: 0; left: 0; bottom: 0; width: var(--rail-w); min-width: 0;
  display: flex !important; z-index: 200; padding-top: var(--rail-top-h);
  transition: width 0.16s ease;
}
/* The strip itself is NO drag region: a drag region under the traffic lights
   or the buttons eats their clicks at the compositor, whatever the z-index
   (the original rail bug). Only the empty middle drags. */
#app-rail-top {
  position: absolute; top: 0; left: 0; right: 0; height: var(--rail-top-h);
  display: flex; align-items: center; justify-content: flex-start; gap: 2px; padding: 0 6px 0 84px;
  border-bottom: 1px solid var(--border); -webkit-app-region: no-drag;
}
#app-rail-top .app-rail-drag { flex: 1 1 auto; align-self: stretch; -webkit-app-region: drag; }
.app-rail-top-btn { -webkit-app-region: no-drag; width: 26px; height: 26px; border-radius: 6px; border: none; background: none; color: var(--text-3); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.app-rail-top-btn:hover { color: var(--text); background: var(--hover); }
#shell-drag-strip { display: none !important; }
#shell-drag-strip .shell-drag-area { -webkit-app-region: no-drag; }
#help-overlay { top: 0; left: var(--rail-w); }
.ws-rail-placeholder-note { padding: 18px; font-size: 13px; color: var(--text-3); }

/* The sidebar scrolls as ONE column (his order, 2026-09-16): Recents has no
   scroll of its own and runs to the bottom; the account row stays pinned. */
/* ONE scroll, and it is .app-rail-scroll (his report, 2026-09-18: the rail
   stopped scrolling). Inside a scrolling flex column a `flex: 1 1 auto` child
   SHRINKS to fit instead of overflowing, so the sections have to take their
   natural height or the scroller has nothing to scroll and the list is simply
   clipped. Nothing between the scroller and the rows may hide overflow either. */
#app-rail .code-history { flex: 0 0 auto; min-height: 0; max-height: none !important; overflow: visible; }
#app-rail #rail-recents-body { flex: 0 0 auto; min-height: 0; display: flex; flex-direction: column; overflow: visible; }
#app-rail .app-rail-section-body { flex: 0 0 auto; min-height: 0; overflow: visible; }
#app-rail .app-rail-scroll { overflow-y: auto; overflow-x: hidden; min-height: 0; }
#echo-dock-layer { left: var(--rail-w); }
#drag-overlay, #grid-handles { left: var(--rail-w); }
.wb-session-search { display: flex; align-items: center; gap: 6px; }
.wb-session-search .repo-drop-search { flex: 1; min-width: 0; width: auto; }
.wb-session-search input { flex: 1; min-width: 0; }


/* In a CARD the session controls sit at the TOP, so their menus open DOWNWARD:
   upward would land above the card, where the holder clips it (the "dots and
   drips do nothing" of 2026-09-16). */
.ws-agent-holder .code-view-more-menu, .ws-agent-holder .echo-drip-pop { top: calc(100% + 6px); bottom: auto; }


/* Sidebar collapsed + a panel fullscreen: its head starts under the traffic
   lights and the strip's icons, so the title moves right past them; the
   offset goes when the sidebar is back (his report, 2026-09-16). */
body.rail-collapsed:not(.rail-peek) .echo-card.expanded > .echo-card-head,
body.rail-collapsed:not(.rail-peek) .ws-rail-slot.fullscreen > .ws-rail-slot-header { padding-left: 124px; }

/* Library pages' loading state. */
.lib-loading { display: flex; align-items: center; gap: 10px; padding: 28px 8px; color: var(--text-3); font-size: 13px; }
.lib-spinner { width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--border); border-top-color: var(--accent); animation: lib-spin 0.8s linear infinite; flex: none; }
@keyframes lib-spin { to { transform: rotate(360deg); } }

/* ── Tasks + Schedules (Settings → Build → Tasks, Customize → Schedules; 2026-09-17) ── */
.skill-tile-icon.own { background: transparent; border-color: transparent; }
.skill-tile-icon.own svg { width: 26px; height: 26px; }
.skill-tile-icon.lg.own svg { width: 34px; height: 34px; }
.ws-task-run.running { border-color: color-mix(in srgb, var(--accent) 45%, var(--border-2)); }
.ws-task-run + .ws-task-run { margin-top: 6px; }
.ws-task-run-head { cursor: pointer; user-select: none; }
.ws-task-run-trigger, .ws-task-run-count { opacity: .8; }
.ws-task-cancel, .ws-task-story-btn { margin-left: 6px; padding: 2px 8px; font-size: 11px; }
.task-story { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
.task-event { border-left: 2px solid var(--border-2); padding: 2px 0 2px 10px; }
.task-event-agent { border-left-color: var(--accent); }
.task-event-connection { border-left-color: #38bdf8; }
.task-event-data { border-left-color: #10b981; }
.task-event-checkpoint { border-left-color: #f59e0b; }
.task-event-result { border-left-color: #10b981; }
.task-event.failed, .task-event-failed { border-left-color: var(--danger, #e5534b); }
.task-event-head { display: flex; gap: 8px; align-items: baseline; font-size: 12px; color: var(--text-2); }
.task-event-kind { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-3); min-width: 74px; }
.task-event-body { margin: 4px 0 0; font-family: ui-monospace, monospace; font-size: 11.5px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; color: var(--text); max-height: 260px; overflow: auto; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 6px 8px; }
.help-section[data-section="schedules"] .ws-tasks-chartwrap { height: 180px; margin: 6px 0 14px; }
.help-section[data-section="schedules"] .ws-tasks-cols { display: grid; grid-template-columns: 1.4fr 1fr; gap: 16px; }
.help-section[data-section="schedules"] .ws-task-card { cursor: pointer; }
.help-section[data-section="schedules"] .ws-task-card + .ws-task-card { margin-top: 6px; }
@media (max-width: 900px) { .help-section[data-section="schedules"] .ws-tasks-cols { grid-template-columns: 1fr; } }
/* A skill's TYPE (2026-09-17): every bundle on the library pages is a skill;
   the chip says which kind it is, and shows only when that differs from the
   page you are already on. */
.skill-type-chip {
  flex: 0 0 auto; align-self: center;
  padding: 1px 6px; border-radius: 999px;
  border: 1px solid var(--border-2); background: var(--surface-2);
  color: var(--text-2); font-size: 10.5px; line-height: 1.5;
  letter-spacing: .03em; text-transform: lowercase;
}
.skill-row-sub .skill-type-chip { margin-right: 2px; }
.skill-detail-sub .skill-type-chip { margin-right: 6px; }
.disc-card-meta { display: flex; align-items: center; gap: 6px; min-width: 0; }
.disc-card-metatext { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The type sits BESIDE the name, never under it (his order, 2026-09-17). */
.skill-row-name, .disc-card-name, .skill-detail-name { display: flex; align-items: center; gap: 6px; min-width: 0; }
.skill-row-title, .disc-card-title, .skill-detail-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.skill-row-sub .skill-type-chip, .skill-detail-sub .skill-type-chip { margin-right: 0; }
.skill-update-btn { height: 24px; padding: 0 10px; font-size: 11px; border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); color: var(--accent); }
/* The fallback MARK where a monogram would go (Tabs table, app cards): no
   colored plate behind it. A panel's mark is full-bleed art and fills the box
   the way an icon does; the generic app glyph is line work and sits inside. */
.icon-mark { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; background: none; color: var(--text-2); }
.icon-mark.art svg { width: 100%; height: 100%; }
.icon-mark.glyph svg { width: 64%; height: 64%; }
/* The FLOW tab: one full-width surface, not the two-column overview grid, and
   as tall as the panel leaves it. The island needs a measured box to lay out. */
.skill-flow-pane { display: block; width: 100%; min-width: 0; }
.skill-flow-host { position: relative; width: 100%; height: calc(100vh - 250px); min-height: 380px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); overflow: hidden; }
/* The library pages' one message row, in its two moods. */
.crud-form-error.ok { color: var(--text-2); border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); background: color-mix(in srgb, var(--accent) 8%, transparent); }
/* Where a share stands: live on the org's hub, or waiting on its desk. */
.skill-share-chip { text-transform: none; }
.skill-share-chip.pending { border-color: color-mix(in srgb, var(--warning, #d9a441) 45%, var(--border-2)); color: var(--warning, #d9a441); }
/* The shelves a shared bundle sits on, on its detail (2026-09-17). */
.skill-cats-block { margin-top: 14px; }
.skill-cats { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.skill-cat-chip { padding: 1px 8px; border-radius: 999px; border: 1px solid var(--border-2); background: var(--surface-2); color: var(--text-2); font-size: 11px; }
.skill-cat-none { font-size: 12px; color: var(--text-3); }
.skill-cat-edit { background: none; border: none; padding: 1px 4px; color: var(--accent); font-size: 11.5px; cursor: pointer; }
.skill-cat-edit:hover { text-decoration: underline; }

/* Settings → Memory: the two privacy disclosures (his order, 2026-09-19). */
.memory-disclosure { border: 1px solid var(--border); border-radius: 8px; margin: 8px 0; background: var(--surface-2); }
.memory-disclosure summary { cursor: pointer; padding: 10px 14px; font-size: 13.5px; color: var(--text); list-style: none; display: flex; align-items: center; justify-content: space-between; }
.memory-disclosure summary::after { content: "›"; color: var(--text-3); transform: rotate(90deg); }
.memory-disclosure[open] summary::after { transform: rotate(-90deg); }
.memory-disclosure ul { margin: 0; padding: 0 14px 12px 32px; }
.memory-disclosure li { font-size: 13px; color: var(--text-2); line-height: 1.55; margin: 4px 0; }

/* THE CLI INSTALLER (2026-09-20): full screen over everything; no close. */
#cli-installer-overlay { position: fixed; inset: 0; z-index: 1000000; display: flex; flex-direction: column; background: var(--bg, #1a1a1c); padding: 38px 18px 18px; }
#cli-installer-overlay .cli-installer-host { flex: 1; min-height: 0; position: relative; }
#cli-installer-overlay.booting .cli-installer-host { visibility: hidden; }
#cli-installer-overlay .xterm { height: 100%; }
#cli-installer-overlay .ws-terminal-tabs { display: none; }
#cli-installer-overlay .cli-installer-quit { position: absolute; top: 8px; right: 12px; width: 30px; height: 30px; border: 0; border-radius: 8px; background: transparent; color: var(--muted, #c4c4c4); font-size: 22px; line-height: 1; cursor: pointer; opacity: .45; }
#cli-installer-overlay .cli-installer-quit:hover { opacity: 1; background: var(--panel, #252528); color: var(--ink, #f1f1f1); }
/* The recents loop filter: wide enough for a name, a mark and a check on one line. */
.code-menu.loop-filter-menu { min-width: 220px; }
.code-menu.loop-filter-menu .code-menu-item { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.code-menu.loop-filter-menu .code-menu-item .loop-label { flex: 1; overflow: hidden; text-overflow: ellipsis; }
.code-menu.loop-filter-menu .code-menu-item { justify-content: flex-start; text-align: left; }
.code-menu.loop-filter-menu .code-sess-mark { flex: none; width: 16px; height: 16px; margin: 0 4px 0 0; }
.code-menu.loop-filter-menu .code-sess-mark img { width: 16px; height: 16px; }
.code-sess-mark img.cli-mark-glyphh-cli { border-radius: 0; }
.code-menu.loop-filter-menu .menu-check { flex: none; display: inline-flex; }
.code-menu.loop-filter-menu .menu-check { flex: none; }

/* THE MEMORY BROWSER (2026-09-20): a knowledge base's rows. */
.mem-browser { margin-top: 12px; }
.mem-empty { color: var(--dim, #828282); font-size: 13px; }
.mem-section { padding: 14px 0 6px; font-size: 13px; font-weight: 600; color: var(--ink, #f1f1f1); border-bottom: 1px solid var(--line, #3f3f46); margin-bottom: 4px; }
.mem-row { display: grid; grid-template-columns: minmax(140px, 1fr) 2fr auto auto; gap: 16px; align-items: center; padding: 9px 4px 9px 8px; border-radius: 6px; cursor: pointer; font-size: 13px; }
.mem-actions { display: flex; gap: 4px; opacity: 0; transition: opacity .12s; }
.mem-row:hover .mem-actions { opacity: 1; }
.mem-icon { width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 6px; background: transparent; color: var(--muted, #c4c4c4); cursor: pointer; }
.mem-icon:hover { background: var(--bg-2, #2e2e32); color: var(--ink, #f1f1f1); }
.mem-page { padding: 4px 0 8px; display: flex; flex-direction: column; flex: 1; min-height: 0; }
/* Chat grammar: the body scrolls, the composer stays put at the bottom, and
   the model chip sits under it on the right (his order, 2026-09-20). */
.mem-page-body { flex: 1; min-height: 0; overflow-y: auto; padding-right: 4px; }
.mem-page-foot { flex: 0 0 auto; padding-top: 10px; }
.mem-foot-bar { display: flex; justify-content: flex-end; padding: 8px 4px 0; }
.settings-panel[data-sub="memory"].mem-page-open { display: flex; flex-direction: column; flex: 1; min-height: 0; height: 100%; }
.settings-panel[data-sub="memory"].mem-page-open > #memory-browser { flex: 1; min-height: 0; display: flex; flex-direction: column; margin-top: 0; }
.settings-modal-body .settings-panels:has(> .settings-panel.mem-page-open) { display: flex; flex-direction: column; overflow-y: hidden; }
.mem-back { display: inline-flex; align-items: center; gap: 6px; border: 0; background: transparent; color: var(--muted, #c4c4c4); font: inherit; font-size: 13px; cursor: pointer; padding: 0 0 14px; }
.mem-back:hover { color: var(--ink, #f1f1f1); }
.mem-page-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.mem-page-title { margin: 0; font-size: 15px; font-weight: 600; color: var(--ink, #f1f1f1); }
.mem-label { font-size: 12px; color: var(--dim, #828282); margin: 12px 0 4px; }
.mem-value { font-size: 13px; color: var(--ink, #f1f1f1); }
.mem-details { margin: 0; padding-left: 20px; font-size: 13px; color: var(--ink, #f1f1f1); line-height: 1.55; }
.mem-details li { margin: 4px 0; }
.mem-status { display: flex; align-items: center; gap: 8px; min-height: 22px; margin: 22px 0 8px; font-size: 12.5px; color: var(--muted, #c4c4c4); }
.mem-check { color: var(--muted, #c4c4c4); }
.mem-compose { display: flex; align-items: center; gap: 8px; padding: 6px 6px 6px 12px; border: 1px solid var(--line, #3f3f46); border-radius: 22px; background: var(--panel, #252528); }
.mem-compose .mem-input { flex: 1; border: 0; background: transparent; box-shadow: none; padding: 6px 0; }
.mem-send { width: 30px; height: 30px; border: 0; border-radius: 50%; background: var(--bg-2, #2e2e32); color: var(--ink, #f1f1f1); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.mem-send:hover { background: var(--accent, #8c3bf2); }
.mem-row:hover { background: var(--panel, #252528); }
.mem-name { color: var(--ink, #f1f1f1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mem-summary { color: var(--muted, #c4c4c4); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mem-when { color: var(--dim, #828282); font-size: 12px; white-space: nowrap; }
.settings-panel.mem-page-open > :not(#memory-browser) { display: none; }

/* ── A SOLO AGENT PANEL IS THE AGENT (his report, 2026-09-26: "a window in a
   window"). The instance webview hosts Echo as its only surface; here the
   dock, the layout bar and the page dots never show, and the agent's own card
   (chat or CLI) drops its head, border and shadow so the panel's edge is the
   agent's edge. Tool cards opened beside it keep their heads. ── */
[data-home-scope="solo-tool"] .echo-dock,
[data-home-scope="solo-tool"] .echo-topbar,
[data-home-scope="solo-tool"] .echo-pages,
[data-home-scope="solo-tool"] .echo-page-dots { display: none !important; }
[data-home-scope="solo-tool"] .echo-card.echo-agent-card,
[data-home-scope="solo-tool"] .echo-card.echo-cli-card { border: 0; border-radius: 0; box-shadow: none; }
[data-home-scope="solo-tool"] .echo-card.echo-agent-card > .echo-card-head,
[data-home-scope="solo-tool"] .echo-card.echo-cli-card > .echo-card-head { display: none; }
/* The solo agent card appears in place — no slide-in from an entrance rect
   inside a panel that is itself just arriving. */
[data-home-scope="solo-tool"] .echo-card.echo-agent-card,
[data-home-scope="solo-tool"] .echo-card.echo-cli-card { transition: none; }
/* A guest paints nothing until its page loads; the panel behind it is the
   surface colour, never black, while an agent panel boots. */
.echo-card webview { background: var(--surface); }
/* A solo agent panel shows NOTHING until its agent is seated (home.html's head
   script sets this before the first paint; the workbench lifts it). The body's
   own background still paints, so the panel is the surface colour meanwhile. */
[data-solo-booting] body > * { visibility: hidden !important; }

/* ── THE AGENTS WORK PANEL (his order, 2026-09-29: "a work panel for these
   like Files, Plans, etc. Each agent is an expandable div with its feed under
   the div as it works"). Every colour comes from the theme's own variables so
   High Vis and its light mirror both read as deliberate; the state dot is the
   same `.code-chat-dot` the rail and the recents use, so green/yellow/red mean
   the same thing everywhere. ── */
.agp-body { display: flex; flex-direction: column; min-height: 0; height: 100%; overflow: hidden; color: var(--text); }
.agp-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--border-2); flex: none; }
.agp-count { font-size: 12px; color: var(--text-3); }
.agp-list { flex: 1; min-height: 0; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 6px; }
.agp-empty { margin: 24px auto; max-width: 320px; text-align: center; display: flex; flex-direction: column; gap: 6px; color: var(--text-3); font-size: 13px; line-height: 1.5; }
.agp-empty strong { color: var(--text-2); font-weight: 600; }
.agp-make { align-self: center; margin-top: 6px; font: inherit; font-size: 12px; font-weight: 600; padding: 5px 11px; border-radius: 7px; border: 1px solid var(--border-2); background: transparent; color: var(--text-2); cursor: pointer; }
.agp-make:hover { background: var(--hover); color: var(--text); }
/* One group per parent session: its title, then its agents. */
.agp-group { display: flex; flex-direction: column; gap: 6px; }
.agp-group + .agp-group { margin-top: 10px; }
.agp-group-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding: 2px 4px; }
.agp-group-title { font-size: 12px; font-weight: 600; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agp-group-count { flex: none; font-size: 11.5px; color: var(--text-3); }

.agp-row { border: 1px solid var(--border-2); border-radius: 10px; background: var(--surface-2, transparent); overflow: hidden; }
.agp-row.working { border-color: color-mix(in srgb, #34d399 35%, var(--border-2)); }
.agp-row.waiting { border-color: color-mix(in srgb, #fbbf24 45%, var(--border-2)); }
.agp-row.failed { border-color: color-mix(in srgb, var(--danger, #e5484d) 45%, var(--border-2)); }

.agp-bar { width: 100%; display: flex; align-items: center; gap: 8px; padding: 9px 10px; border: 0; background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.agp-bar:hover { background: var(--hover); }
.agp-chev { display: inline-flex; flex: none; color: var(--text-3); transition: transform 0.15s ease; }
.agp-chev svg { width: 13px; height: 13px; }
.agp-row.open .agp-chev { transform: rotate(90deg); }
.agp-dot { flex: none; }
.agp-name { font-weight: 600; font-size: 13px; flex: none; }
.agp-model { flex: none; font-family: var(--mono, ui-monospace, monospace); font-size: 11px; padding: 1px 6px; border-radius: 5px; border: 1px solid var(--border-2); color: var(--text-2); }
.agp-bar-task { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; color: var(--text-2); }
.agp-meta { flex: none; font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }

.agp-feed { border-top: 1px solid var(--border-2); padding: 10px 12px 12px 32px; max-height: 420px; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.agp-task { font-size: 12.5px; color: var(--text-2); padding: 7px 9px; border-radius: 7px; background: var(--surface-3, var(--hover)); white-space: pre-wrap; }
.agp-text { font-size: 13px; line-height: 1.55; }
.agp-starting, .agp-approval { font-size: 12px; color: var(--text-3); font-style: italic; }
.agp-approval { color: var(--warning, #fbbf24); font-style: normal; }

.agp-spin { width: 10px; height: 10px; border-radius: 50%; border: 1.6px solid var(--border-2); border-top-color: var(--accent); animation: agp-spin 0.8s linear infinite; }
@keyframes agp-spin { to { transform: rotate(360deg); } }


/* The row under an agent reply (copy). Hidden until the reply is hovered or the
   row takes keyboard focus; the copied state is the theme's own success. */
.code-spend-banner { margin: 0 0 8px; }
.code-money-card { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 12px; margin: 2px 0 8px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); }
.code-money-card.plan { border-color: var(--accent); }
.code-money-card.warn { border-color: var(--warning); }
.code-money-card.out { border-color: var(--danger); }
.code-money-text { min-width: 0; }
.code-money-title { font-size: 13px; font-weight: 600; color: var(--text); }
.code-money-body { font-size: 12.5px; color: var(--text-muted); margin-top: 2px; }
.code-money-card .action-btn { flex: none; }
.code-money-close { flex: none; align-self: flex-start; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 6px; background: transparent; color: var(--text-muted); font-size: 16px; line-height: 22px; cursor: pointer; }
.code-money-close:hover { background: var(--hover, var(--surface-2)); color: var(--text); }
.code-money-details { margin-top: 6px; font-size: 11.5px; color: var(--text-muted); }
.code-money-details summary { cursor: pointer; }
.code-money-details pre { white-space: pre-wrap; word-break: break-word; margin: 4px 0 0; font-family: var(--font-mono, ui-monospace, monospace); font-size: 11px; max-height: 160px; overflow: auto; }
.code-msg-actions { display: flex; gap: 2px; margin: -2px 0 6px; opacity: 0; transition: opacity 0.12s ease; }
.code-agent-text:hover + .code-msg-actions,
.code-msg-actions:hover,
.code-msg-actions:focus-within { opacity: 1; }
.code-msg-action {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 24px; padding: 0; border: 0; border-radius: 6px;
  background: transparent; color: var(--text-3); cursor: pointer;
}
.code-msg-action:hover { background: var(--hover); color: var(--text); }
.code-msg-action.copied { color: var(--success); }
.code-msg-action:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ── INLINE IMAGES in a reply (format-markdown `![alt](src)`) ── */
.yo-md-figure { display: inline-flex; flex-direction: column; gap: 4px; max-width: 100%; margin: 6px 0; vertical-align: top; }
.yo-md-img { display: block; max-width: min(100%, 560px); max-height: 420px; border-radius: 10px; border: 1px solid var(--border-2); background: var(--surface-2); object-fit: contain; cursor: zoom-in; }
.yo-md-caption { font-size: 12px; color: var(--text-3); }
.yo-md-figure.broken .yo-md-img { display: none; }
.yo-md-figure.broken::before { content: "Image unavailable"; font-size: 12px; color: var(--text-3); padding: 8px 10px; border: 1px dashed var(--border-2); border-radius: 8px; }
.yo-md-file { cursor: pointer; text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 3px; }

/* ── ARTIFACT CARDS (help/artifacts.ts) — what the turn made. ── */
.code-artifact-wrap { margin: 6px 0 10px; }
.art-card { max-width: 620px; border: 1px solid var(--border-2); border-radius: 12px; background: var(--surface-2, var(--surface)); overflow: hidden; cursor: pointer; transition: border-color 0.12s ease; }
.art-card:hover { border-color: color-mix(in srgb, var(--accent) 55%, var(--border-2)); }
.art-head { display: flex; align-items: center; gap: 10px; padding: 10px 12px; }
.art-ic { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; flex: none; border-radius: 8px; background: var(--surface-3, var(--hover)); color: var(--text-2); }
.art-ic svg { width: 16px; height: 16px; }
.art-card.image .art-ic { color: var(--warning); }
.art-card.html .art-ic { color: var(--blue); }
.art-card.markdown .art-ic { color: var(--accent-text, var(--accent)); }
.art-card.text .art-ic { color: var(--success); }
.art-meta { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.art-name { font-size: 13px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.art-dir { font-size: 11.5px; color: var(--text-3); font-family: var(--font-mono, ui-monospace, monospace); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.art-verb { flex: none; font-size: 11px; font-weight: 600; padding: 2px 7px; border-radius: 999px; border: 1px solid var(--border-2); color: var(--text-2); }
.art-verb.created { color: var(--success); border-color: color-mix(in srgb, var(--success) 45%, transparent); }
.art-verb.edited { color: var(--blue); border-color: color-mix(in srgb, var(--blue) 45%, transparent); }
.art-preview { border-top: 1px solid var(--border-2); background: var(--surface, transparent); }
.art-preview img { display: block; max-width: 100%; max-height: 260px; margin: 0 auto; object-fit: contain; cursor: zoom-in; }
.art-code { margin: 0; padding: 9px 12px; font-family: var(--font-mono, ui-monospace, monospace); font-size: 11.5px; line-height: 1.5; color: var(--text); white-space: pre; overflow: hidden; }
.art-more { padding: 0 12px 8px; font-size: 11.5px; color: var(--text-3); }
.art-acts { display: flex; gap: 6px; padding: 8px 12px 10px; border-top: 1px solid var(--border-2); }
.art-btn { font: inherit; font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 7px; border: 1px solid var(--border-2); background: transparent; color: var(--text-2); cursor: pointer; }
.art-btn:hover { background: var(--hover); color: var(--text); }
.art-btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-fg, #fff); }
.art-btn.primary:hover { filter: brightness(1.08); }
.art-btn.copied { color: var(--success); border-color: color-mix(in srgb, var(--success) 50%, transparent); }
.art-btn:focus-visible, .art-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ── THE PREVIEW MODAL — the whole file over the conversation. ── */
.art-modal { position: fixed; inset: 0; z-index: 9000; display: flex; align-items: center; justify-content: center; padding: 28px; background: var(--overlay-bg, rgba(0, 0, 0, 0.6)); }
/* INSIDE THE AGENT PANEL (his order: the modal stays within the working
   window): mounted in `.code-agent`, it fills that panel, not the app. The
   agent becomes the containing block; a narrow card gets a tighter gutter and
   the grid-laid holder agent needs the overlay lifted out of the grid flow. */
.code-agent { position: relative; }
.art-modal.in-panel { position: absolute; padding: 16px; z-index: 50; border-radius: inherit; }
.ws-agent-holder > .code-agent > .art-modal.in-panel { grid-area: 1 / 1 / -1 / -1; }
@container agent (max-width: 520px) { .art-modal.in-panel { padding: 8px; } }
.art-modal-panel { width: min(960px, 100%); max-height: 100%; display: flex; flex-direction: column; border: 1px solid var(--border-2); border-radius: 14px; background: var(--bg-raised, var(--surface)); box-shadow: 0 20px 60px var(--shadow, rgba(0, 0, 0, 0.5)); overflow: hidden; }
.art-modal-head { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--border-2); }
.art-close { width: 30px; height: 30px; flex: none; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 8px; background: transparent; color: var(--text-3); cursor: pointer; }
.art-close svg { width: 16px; height: 16px; }
.art-close:hover { background: var(--hover); color: var(--text); }
.art-modal-body { flex: 1; min-height: 120px; overflow: auto; }
.art-modal-body .art-code.full { overflow: visible; padding: 14px 16px; font-size: 12.5px; }
.art-md { padding: 16px 20px; }
.art-note { padding: 14px 16px; font-size: 12.5px; color: var(--text-3); }
.art-modal-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--border-2); }

/* A streaming reply's two parts lay out as one block of text. */
.stream-frozen, .stream-tail { display: contents; }

/* Task lists: a plan that reads as one. The box is drawn, not an input — the
   transcript records what the agent did, it is not a form. */
.yo-md-tasks { list-style: none; padding-left: 4px; }
.yo-md-tasks li { display: flex; align-items: flex-start; gap: 8px; }
.yo-md-check { flex: none; width: 14px; height: 14px; margin-top: 3px; border: 1.5px solid var(--border-3, var(--border-2)); border-radius: 4px; }
.yo-md-check.on { background: var(--success); border-color: var(--success); background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12.5l4.5 4.5L19 7.5'/></svg>"); background-size: 11px; background-position: center; background-repeat: no-repeat; }
.yo-md-task-done { color: var(--text-3); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--text-3) 60%, transparent); }
.code-agent-text del { color: var(--text-3); }
/* A file reference in code opens the file. */
.yo-md-path { cursor: pointer; }
.yo-md-path:hover { border-color: color-mix(in srgb, var(--accent) 50%, var(--border-2)); color: var(--accent-text, var(--text)); }

/* Build → Agents (help/settings-agents.ts): the Connections table, with the
   agent's description under its name; the editor is the Drips form, and its
   brief is the one tall field. */
.agents2-table .conn2-tr { grid-template-columns: 28px minmax(0, 1fr) 200px 130px; }
.agents2-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.agents2-desc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agents2-inherit { font-style: italic; }
.agents2-brief { width: 100%; box-sizing: border-box; min-height: 180px; resize: vertical; line-height: 1.55; font: inherit; font-size: 13px; }
/* The brief's head: its label, and the wand that writes it. */
.agents2-brief-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 8px; margin-top: 8px; }
.agents2-brief-head .settings-label { margin-bottom: 0; }
.agents2-wand {
  display: inline-flex; align-items: center; gap: 6px; height: 28px; min-width: 28px; padding: 0 6px; margin-bottom: 4px;
  border: 1px solid transparent; border-radius: 7px; background: transparent; color: var(--accent-text, var(--accent));
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; justify-content: center;
}
.agents2-wand svg { width: 16px; height: 16px; }
.agents2-wand:hover:not(:disabled) { background: var(--accent-bg, var(--hover)); border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.agents2-wand:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.agents2-wand.generating { color: var(--text-2); cursor: progress; padding: 0 9px; }
.agents2-wand-spin { width: 12px; height: 12px; border-radius: 50%; border: 1.6px solid var(--border-2); border-top-color: var(--accent); animation: agp-spin 0.8s linear infinite; }
.agents2-brief[aria-busy="true"] { opacity: 0.6; }
.agents2-brief-error { font-size: 12px; color: var(--danger); margin: 0 0 6px; }

/* A PAGE PREVIEWS AS A PAGE (help/artifacts.ts): on the card, a full-width
   render scaled to a thumbnail that takes no clicks; in the modal, the page at
   size. Both are sandboxed frames — see the module header. */
.art-preview.art-page { position: relative; height: 210px; overflow: hidden; background: #fff; }
.art-page-frame { position: absolute; top: 0; left: 0; width: 250%; height: 250%; border: 0; transform: scale(0.4); transform-origin: 0 0; pointer-events: none; background: #fff; }
.art-modal-panel.wide { width: min(1280px, 100%); height: min(88vh, 100%); }
.art-modal-body.art-modal-page { padding: 0; overflow: hidden; background: #fff; }
.art-modal-frame { display: block; width: 100%; height: 100%; border: 0; background: #fff; }

/* ── WHAT THE AGENT DID (help/tool-view.ts) — his order, 2026-09-29: "file
   changes… + adds green, - removes red, foldable… way more robust viewing of
   the tool calls… world class". A turn's steps are one quiet line that opens
   into a bordered list; each step opens into the thing itself. Colours are
   the theme's own (success/danger/accent/text tiers), never a fixed palette. ── */
.tv-group { margin: 4px 0 8px; }
.tv-group-head {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 3px 0; border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 13px; color: var(--text-3); text-align: left;
}
.tv-group-head:hover { color: var(--text-2); }
/* Running text, not a flex row: a file name inside the sentence must sit in it
   with ordinary spacing, not a gap on each side. */
.tv-group-label { display: inline; min-width: 0; }
.tv-group-label > .tv-spin { margin-right: 7px; vertical-align: -1px; }
.tv-group-label .tv-badge, .tv-group-label .tv-count { margin-left: 6px; }
.tv-group-label .tv-file { color: var(--text); font-weight: 500; }
.tv-count { color: var(--text-faint, var(--text-3)); font-size: 12px; }
.tv-failed { color: var(--danger); }
.tv-chev { width: 11px; height: 11px; flex: none; transition: transform 0.14s ease; color: var(--text-3); }
.tv-group.open > .tv-group-head .tv-chev { transform: rotate(90deg); }

.tv-steps { margin-top: 6px; border: 1px solid var(--border-2); border-radius: 10px; overflow: hidden; background: var(--surface, transparent); }
.tv-step + .tv-step { border-top: 1px solid var(--border-2); }
.tv-step-btn {
  width: 100%; display: flex; align-items: center; gap: 8px; padding: 9px 12px;
  border: 0; background: transparent; cursor: pointer; font: inherit; color: inherit; text-align: left;
}
.tv-step-btn:hover { background: var(--hover); }
.tv-step-btn .tv-chev { margin-left: 2px; }
.tv-step.open > .tv-step-btn .tv-chev { transform: rotate(90deg); }
.tv-step-head { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; font-size: 13px; }
.tv-verb { flex: none; color: var(--text-3); }
.tv-file { font-weight: 500; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tv-cmd { font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.tv-subj { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.tv-meta { flex: none; display: inline-flex; align-items: center; gap: 8px; margin-left: auto; font-size: 12px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.tv-dur { color: var(--text-faint, var(--text-3)); }
.tv-state { flex: none; display: inline-flex; width: 14px; height: 14px; align-items: center; justify-content: center; }
.tv-state svg { width: 13px; height: 13px; }
.tv-state.done { color: var(--success); }
.tv-state.failed { color: var(--danger); }
.tv-badge { display: inline-flex; gap: 5px; font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; font-variant-numeric: tabular-nums; }
.tv-add { color: var(--success); }
.tv-del { color: var(--danger); }
.tv-exit { color: var(--danger); font-family: var(--font-mono, ui-monospace, monospace); }
.tv-ok { color: var(--success); font-family: var(--font-mono, ui-monospace, monospace); }
.tv-spin { display: inline-block; width: 11px; height: 11px; flex: none; border-radius: 50%; border: 1.6px solid var(--border-2); border-top-color: var(--accent); animation: agp-spin 0.8s linear infinite; }

.tv-step-body { padding: 0 12px 12px; }
.tv-note { font-size: 12px; color: var(--text-3); padding: 6px 2px 0; }
.tv-meta-line { padding-top: 0; }

/* A DIFF: path bar, then rows of old# · new# · marker · code. */
.tv-diff { border: 1px solid var(--border-2); border-radius: 8px; overflow: hidden; background: var(--bg, var(--surface)); }
.tv-path { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 10px; border-bottom: 1px solid var(--border-2); font-family: var(--font-mono, ui-monospace, monospace); font-size: 11.5px; color: var(--text-3); }
.tv-path > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tv-lines { max-height: 440px; overflow: auto; font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; line-height: 1.55; }
.tv-row { display: grid; grid-template-columns: 3.4em 3.4em 1.6em minmax(0, 1fr); min-width: max-content; }
.tv-no { padding: 0 6px; text-align: right; color: var(--text-faint, var(--text-3)); user-select: none; font-variant-numeric: tabular-nums; opacity: 0.8; }
.tv-mk { text-align: center; user-select: none; }
.tv-code { white-space: pre; padding-right: 14px; }
.tv-row.add { background: color-mix(in srgb, var(--success) 13%, transparent); }
.tv-row.add .tv-no, .tv-row.add .tv-mk { background: color-mix(in srgb, var(--success) 20%, transparent); color: var(--success); opacity: 1; }
.tv-row.del { background: color-mix(in srgb, var(--danger) 13%, transparent); }
.tv-row.del .tv-no, .tv-row.del .tv-mk { background: color-mix(in srgb, var(--danger) 20%, transparent); color: var(--danger); opacity: 1; }
.tv-gap { padding: 3px 10px; font-size: 11px; color: var(--text-3); background: var(--surface-2, var(--hover)); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.tv-gap:first-child { border-top: 0; }

/* A COMMAND: the prompt line, the output, the exit code. */
.tv-term { border: 1px solid var(--border-2); border-radius: 8px; overflow: hidden; background: var(--bg, var(--surface)); font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; }
.tv-term-cmd { display: flex; align-items: flex-start; gap: 8px; padding: 8px 10px; border-bottom: 1px solid var(--border-2); }
.tv-term-cmd code { flex: 1; min-width: 0; white-space: pre-wrap; word-break: break-word; color: var(--text); }
.tv-prompt { color: var(--accent-text, var(--accent)); user-select: none; }
.tv-term-out { margin: 0; padding: 8px 10px; max-height: 360px; overflow: auto; white-space: pre-wrap; word-break: break-word; color: var(--text-2); line-height: 1.5; }
.tv-stderr { color: var(--danger-soft, var(--danger)); }
.tv-term-empty { padding: 8px 10px; color: var(--text-3); font-style: italic; }
.tv-term-foot { display: flex; gap: 12px; padding: 5px 10px; border-top: 1px solid var(--border-2); font-size: 11px; color: var(--text-3); }

/* A LENT TOOL: arguments, then the result. */
.tv-io { display: flex; flex-direction: column; gap: 6px; }
.tv-io-head { display: flex; align-items: center; justify-content: space-between; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-3); }
.tv-io-pre { margin: 0; padding: 8px 10px; max-height: 320px; overflow: auto; border: 1px solid var(--border-2); border-radius: 8px; background: var(--bg, var(--surface)); font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; line-height: 1.5; white-space: pre-wrap; word-break: break-word; color: var(--text-2); }

.tv-copy { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 5px; background: transparent; color: var(--text-3); cursor: pointer; }
.tv-copy svg { width: 13px; height: 13px; }
.tv-copy:hover { background: var(--hover); color: var(--text); }
.tv-copy.done { color: var(--success); }

/* ── The display face (his pick, 2026-10-02): every heading in JetBrains Mono
   700, as on the site and the console. Body text stays Geist. A document the
   member is writing (.gdoc-paper) keeps its own faces. ──────────────────── */
:root { --font-display: var(--font-mono); }
:is(h1, h2, h3, h4):not(.gdoc-paper *),
.yo-modal-title, .dash-modal-title, .conn-modal-title, .gdz-modal-title,
.yo-panel-title, .dash-section-title, .gdrive-section-title, .gmem-sec-title,
.mem-page-title, .settings-subheading, .ws-tasks-heading, .mkt-banner-title,
.mkt-console-title, .dash-cowork-title, .lockout-title, .wtour-title {
  font-family: var(--font-display) !important;
  font-weight: 700 !important;
  letter-spacing: -0.02em;
}

/* The Workspaces editor's "+ New tab": the Tabs page's own form, standalone
   under the grid (his order, 2026-10-03). */
.layout-new-tab { margin-top: 12px; }
#layout-new-tab-host { margin-top: 10px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); }
#layout-new-tab-host.hidden { display: none; }

