/* =========================================================
   BOS.Forge — Global stylesheet
   Design tokens sourced from docs/forge-ui.html mockup.
   All reusable styles live here. Do NOT add page-specific
   CSS files elsewhere — extend via utility classes below.
   ========================================================= */

/* ── Fonts ────────────────────────────────────────────── */
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600&family=DM+Sans:wght@300;400;500;600;700&display=swap');

/* ── Design tokens (Dark theme — default) ─────────────── */
:root {
  --bg-deep: #060a1a;
  --bg-primary: #0b1028;
  --bg-surface: #111938;
  --bg-elevated: #162044;
  --bg-hover: #1a2650;

  --border: #1e2d5a;
  --border-subtle: #152040;

  --text-primary: #e2e8f4;
  --text-secondary: #7b8bb5;
  --text-muted: #4a5a85;

  --accent-blue: #4d8ef7;
  --accent-blue-dim: #3a6fd4;
  --accent-light: #7db4ff;
  --accent-glow: rgba(77, 142, 247, 0.12);
  --accent-glow-strong: rgba(77, 142, 247, 0.25);

  --success: #34d399;
  --success-dim: rgba(52, 211, 153, 0.15);
  --warning: #fbbf24;
  --warning-dim: rgba(251, 191, 36, 0.15);
  --danger: #f87171;
  --danger-dim: rgba(248, 113, 113, 0.15);

  --font-mono: 'JetBrains Mono', monospace;
  --font-sans: 'DM Sans', system-ui, -apple-system, sans-serif;

  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
  --radius-xl: 12px;

  --transition: 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  --slide-transition: 0.35s cubic-bezier(0.4, 0, 0.2, 1);

  --header-height: 44px;
  --footer-height: 32px;
}

/* ── Global reset + base ──────────────────────────────── */
* { box-sizing: border-box; }

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

body {
  font-family: var(--font-sans);
  background: var(--bg-deep);
  color: var(--text-primary);
  font-size: 13px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ── Scrollbars (global) ──────────────────────────────────
   One thin, token-coloured scrollbar for the whole app so the default
   OS scrollbar never leaks through. The chat and artifact preview panes
   keep their own explicit rules further below — this global default
   matches them, so there's no visual change to those. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}
*::-webkit-scrollbar { width: 4px; height: 4px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 2px;
}
*::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
*::-webkit-scrollbar-corner { background: transparent; }

a { color: var(--accent-light); text-decoration: none; transition: color var(--transition); }
a:hover { color: var(--accent-blue); }

code, pre, .mono {
  font-family: var(--font-mono);
  font-size: 0.92em;
}

h1, h2, h3, h4, h5, h6 {
  font-weight: 600;
  color: var(--text-primary);
  margin: 0 0 0.5em;
}

p { margin: 0 0 1em; }

hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 24px 0;
}

.text-muted     { color: var(--text-muted) !important; }
.text-secondary { color: var(--text-secondary) !important; }

/* ── Layout shells ────────────────────────────────────── */
/* App-wide: header + footer pinned; only main scrolls */
.app-shell {
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.app-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

/* ── Header / top nav ─────────────────────────────────── */
.site-header {
  height: var(--header-height);
  background: var(--bg-primary);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  padding: 0 16px;
  flex-shrink: 0;
  z-index: 100;
}

.site-header .brand {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-right: 20px;
  border-right: 1px solid var(--border);
  margin-right: 4px;
  height: 100%;
  color: var(--text-primary);
}

.site-header .brand svg { width: 18px; height: 18px; color: var(--accent-blue); }

.site-header .brand-text {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-primary);
}

.site-nav {
  display: flex;
  align-items: center;
  height: 100%;
  gap: 0;
}

.site-nav-item {
  height: 100%;
  display: flex;
  align-items: center;
  padding: 0 14px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color var(--transition), background var(--transition);
  position: relative;
  user-select: none;
  text-decoration: none;
}

.site-nav-item:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.site-nav-item.active {
  color: var(--accent-blue);
  background: var(--accent-glow);
}

.site-nav-item.active::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--accent-blue);
}

.site-header-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 100%;
}

/* ── Footer ───────────────────────────────────────────── */
.site-footer {
  height: var(--footer-height);
  background: var(--bg-primary);
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  padding: 0 16px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.5px;
  color: var(--text-muted);
  flex-shrink: 0;
}

.site-footer a { color: var(--text-muted); }
.site-footer a:hover { color: var(--text-secondary); }
.site-footer .spacer { flex: 1; }

/* Beta-version chip — sits dead-center horizontally, independent of the surrounding flex
   children so the copyright on the left and links/widgets on the right don't shift it. */
.site-footer { position: relative; }
.site-footer-beta {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-muted);
  pointer-events: none;
}

/* ── Buttons ──────────────────────────────────────────── */
.btn-forge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 32px;
  padding: 0 14px;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  color: var(--text-primary);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all var(--transition);
  text-decoration: none;
  user-select: none;
  white-space: nowrap;
}

.btn-forge:hover {
  background: var(--bg-hover);
  border-color: var(--accent-blue-dim);
  color: var(--text-primary);
}

.btn-forge.primary {
  background: var(--accent-blue);
  border-color: var(--accent-blue);
  color: #fff;
}

.btn-forge.primary:hover {
  background: var(--accent-blue-dim);
  border-color: var(--accent-blue-dim);
  color: #fff;
}

.btn-forge.ghost {
  border-color: transparent;
  color: var(--text-secondary);
}

.btn-forge.ghost:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.btn-forge.lg {
  height: 40px;
  padding: 0 18px;
  font-size: 13px;
}

.btn-forge.block { width: 100%; }

.btn-forge svg { width: 14px; height: 14px; }

/* ── Icon button ──────────────────────────────────────── */
.icon-btn {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all var(--transition);
  text-decoration: none;
}

.icon-btn:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.icon-btn svg { width: 16px; height: 16px; }

/* ── Cards / surfaces ─────────────────────────────────── */
.surface {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.surface-elevated {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.card-forge {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
}

.card-title {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 12px;
}

/* ── Form controls ────────────────────────────────────── */
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 14px;
}

.field-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-muted);
}

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

.input-forge {
  height: 38px;
  width: 100%;
  padding: 0 12px;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--text-primary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color var(--transition), box-shadow var(--transition);
}

.input-forge::placeholder { color: var(--text-muted); }

.input-forge:focus {
  border-color: var(--accent-blue);
  box-shadow: 0 0 0 3px var(--accent-glow);
}

.input-forge:disabled {
  opacity: 0.6;
}

.input-forge.has-error { border-color: var(--danger); }

textarea.input-forge {
  height: auto;
  min-height: 96px;
  padding: 10px 12px;
  line-height: 1.5;
  resize: vertical;
}

.check-forge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--text-secondary);
  cursor: pointer;
  user-select: none;
}

.check-forge input[type="checkbox"] {
  width: 14px;
  height: 14px;
  accent-color: var(--accent-blue);
  cursor: pointer;
}

/* ── Auth — centered card over landing-style gradient ─── */
.auth-centered {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 64px 24px 48px;
  background:
    radial-gradient(ellipse at top, var(--accent-glow-strong), transparent 55%),
    var(--bg-deep);
}

.auth-centered-card {
  width: 100%;
  max-width: 440px;
  padding: 32px;
}

.auth-centered-alt {
  margin-top: 20px;
  font-size: 12px;
  color: var(--text-secondary);
  text-align: center;
}

.auth-centered-alt a {
  color: var(--accent-light);
  font-weight: 500;
  margin-left: 4px;
}

.auth-form-title {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin-bottom: 6px;
  background: linear-gradient(135deg, var(--text-primary), var(--accent-light));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.auth-form-subtitle {
  color: var(--text-secondary);
  font-size: 13px;
  margin-bottom: 24px;
}

.auth-divider {
  text-align: center;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.5px;
  margin: 24px 0;
  position: relative;
}

.auth-divider::before,
.auth-divider::after {
  content: '';
  position: absolute;
  top: 50%;
  width: calc(50% - 24px);
  height: 1px;
  background: var(--border);
}

.auth-divider::before { left: 0; }
.auth-divider::after  { right: 0; }

@media (max-width: 520px) {
  .auth-centered { padding: 32px 16px; }
  .auth-centered-card { padding: 24px; }
  .auth-form-title { font-size: 24px; }
}

/* ── Validation ───────────────────────────────────────── */
.validation-summary-valid { display: none; }

.validation-summary-errors {
  background: var(--danger-dim);
  border: 1px solid var(--danger);
  color: var(--danger);
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  font-size: 12px;
  margin-bottom: 16px;
}

.validation-summary-errors ul {
  margin: 0;
  padding-left: 18px;
}

.field-validation-error {
  color: var(--danger);
  font-size: 11px;
  display: block;
  margin-top: 4px;
}

.input-validation-error { border-color: var(--danger) !important; }

/* Status messages passed via ?status / TempData */
.status-message {
  background: var(--accent-glow);
  border: 1px solid var(--accent-blue-dim);
  color: var(--accent-light);
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  font-size: 12px;
  margin-bottom: 16px;
}

/* ── Status dot ──────────────────────────────────────── */
.status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--success);
  box-shadow: 0 0 6px rgba(52, 211, 153, 0.4);
  animation: pulse-dot 2s infinite;
  display: inline-block;
}

@keyframes pulse-dot {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.5; }
}

/* Conference beta QR — sits below the landing-hero CTAs. Two-column on wide viewports,
   stacks on narrow. The QR itself is a server-rendered inline SVG so there's no third-party
   image dependency to break at the booth. */
.landing-qr {
  display: flex;
  justify-content: center;
  margin: 40px auto 0;
  padding: 0 24px;
}
.landing-qr-card {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 20px 24px;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  max-width: 520px;
}
.landing-qr-img {
  flex-shrink: 0;
  width: 168px;
  height: 168px;
  background: #fff;
  border-radius: var(--radius-md);
  padding: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.landing-qr-img svg {
  display: block;
  width: 100%;
  height: 100%;
}
.landing-qr-meta {
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.landing-qr-eyebrow {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-muted);
}
.landing-qr-url {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--accent-blue);
  word-break: break-all;
}
.landing-qr-key-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 6px;
}
.landing-qr-key-label {
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.landing-qr-key {
  font-family: var(--font-mono);
  font-size: 18px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: 0.06em;
  padding: 3px 10px;
  border: 1px dashed var(--accent-blue-dim);
  border-radius: var(--radius-sm);
  background: var(--accent-glow);
}
.landing-qr-expires {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 4px;
}
@media (max-width: 540px) {
  .landing-qr-card {
    flex-direction: column;
    text-align: center;
    align-items: center;
  }
  .landing-qr-meta { text-align: center; align-items: center; }
}

/* ── Landing page ─────────────────────────────────────── */
.landing-hero {
  padding: 56px 24px 32px;
  text-align: center;
  background:
    radial-gradient(ellipse at top, var(--accent-glow-strong), transparent 50%),
    var(--bg-deep);
}

.landing-hero h1 {
  font-size: 48px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 16px;
  background: linear-gradient(135deg, var(--text-primary), var(--accent-light));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.landing-hero p {
  font-size: 16px;
  color: var(--text-secondary);
  max-width: 620px;
  margin: 0 auto 32px;
  line-height: 1.6;
}

.landing-section {
  max-width: 960px;
  margin: 0 auto;
  padding: 32px 24px;
}

.landing-section h2 {
  font-size: 22px;
  margin-bottom: 8px;
}

.landing-section .lede {
  color: var(--text-secondary);
  margin-bottom: 24px;
}

.landing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
  margin-top: 24px;
}

.landing-feature {
  padding: 20px;
}

.landing-feature h3 {
  font-size: 14px;
  margin-bottom: 8px;
}

.landing-feature p {
  font-size: 12px;
  color: var(--text-secondary);
  margin: 0;
}

/* ── Profile / Identity management shell ──────────────── */
.manage-shell {
  width: 100%;
  max-width: 560px;
  margin: 40px auto;
  padding: 0 24px;
}

.manage-nav {
  display: flex;
  gap: 2px;
  margin-bottom: 24px;
  border-bottom: 1px solid var(--border);
  padding-bottom: 8px;
}

.manage-nav a {
  display: block;
  padding: 8px 14px;
  font-size: 12px;
  color: var(--text-secondary);
  border-radius: var(--radius-sm);
  text-decoration: none;
  transition: all var(--transition);
}

.manage-nav a:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.manage-nav a.active {
  color: var(--accent-blue);
  background: var(--accent-glow);
}

.manage-content h1 {
  font-size: 22px;
  margin-bottom: 4px;
}

.manage-content .lede {
  color: var(--text-secondary);
  font-size: 13px;
  margin-bottom: 24px;
}

.manage-content .card-forge {
  width: 100%;
}

.manage-content .input-forge {
  width: 100%;
}

/* ── User menu (header dropdown) ──────────────────────── */
.user-menu {
  position: relative;
  height: 100%;
  display: flex;
  align-items: center;
}

.user-menu-trigger {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent-blue-dim);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  cursor: pointer;
  transition: background var(--transition);
}

.user-menu-trigger:hover {
  background: var(--accent-blue);
}

.user-menu-trigger svg {
  width: 16px;
  height: 16px;
}

.user-menu-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 180px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  z-index: 200;
  padding: 4px;
}

.user-menu-dropdown.open { display: block; }

.user-menu-dropdown .menu-label {
  padding: 8px 12px 4px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.5px;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-menu-dropdown .menu-divider {
  height: 1px;
  background: var(--border);
  margin: 4px 0;
}

.user-menu-dropdown a,
.user-menu-dropdown button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 12px;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--text-secondary);
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
  transition: all var(--transition);
}

.user-menu-dropdown a:hover,
.user-menu-dropdown button:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.user-menu-dropdown a svg,
.user-menu-dropdown button svg {
  width: 14px;
  height: 14px;
  color: var(--text-muted);
}

/* ── Workspace connection-status widget (footer-anchored) ─────────────────
   Sits at the right of the footer on /Workspace pages. Trigger is a low-key
   "Connected" pill with a green dot; click pops a small upward-anchored menu
   listing the three integrations with green/red status balls. */
.conn-status {
  position: relative;
  margin-left: 12px;
}
.conn-status-trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 2px 10px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-secondary);
  cursor: pointer;
  transition: border-color var(--transition), color var(--transition);
}
.conn-status-trigger:hover {
  border-color: var(--accent-blue-dim);
  color: var(--text-primary);
}
.conn-status-dropdown {
  display: none;
  position: absolute;
  /* Anchor upward — the widget lives in the footer, so the menu opens above it. */
  bottom: calc(100% + 6px);
  right: 0;
  min-width: 180px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.4);
  z-index: 200;
  padding: 4px;
}
.conn-status-dropdown.open { display: block; }
.conn-status-dropdown .menu-label {
  padding: 8px 12px 4px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.5px;
  color: var(--text-muted);
}
.conn-status-dropdown .menu-divider {
  height: 1px;
  background: var(--border);
  margin: 4px 0;
}
.conn-status-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 12px;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--text-secondary);
  /* Non-interactive — these are status indicators, not actions. No hover state. */
}
.conn-status-name { color: var(--text-secondary); }

/* Status ball — used in both the trigger and the dropdown rows. */
.conn-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
}
.conn-dot.ok {
  background: var(--success);
  box-shadow: 0 0 4px var(--success);
}
.conn-dot.bad {
  background: var(--danger);
  box-shadow: 0 0 4px var(--danger);
}

/* ── Utilities ────────────────────────────────────────── */
.u-mono     { font-family: var(--font-mono); }
.u-muted    { color: var(--text-muted); }
.u-mt-sm    { margin-top: 8px; }
.u-mt-md    { margin-top: 16px; }
.u-mt-lg    { margin-top: 24px; }
.u-mb-sm    { margin-bottom: 8px; }
.u-mb-md    { margin-bottom: 16px; }
.u-mb-lg    { margin-bottom: 24px; }
.u-flex     { display: flex; }
.u-flex-col { display: flex; flex-direction: column; }
.u-gap-sm   { gap: 8px; }
.u-gap-md   { gap: 12px; }
.u-gap-lg   { gap: 16px; }
.u-center   { justify-content: center; align-items: center; }
.u-between  { justify-content: space-between; align-items: center; }
.u-right    { margin-left: auto; }
.u-full     { width: 100%; }
.u-hidden   { display: none !important; }

.u-team-select { flex: 0; min-width: 160px; }

/* ── Onboarding — centered column with sticky action bar ── */

.onboard-shell {
  flex: 1;
  background: var(--bg-deep);
}

.onboard-column {
  width: 100%;
  max-width: 620px;
  margin: 0 auto;
  min-height: 100%;
  padding: 40px 24px 0;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}

.onboard-header {
  margin-bottom: 24px;
  flex-shrink: 0;
}

/* Actions always pinned to the bottom of the viewport */
.onboard-actions {
  margin-top: auto;
  position: sticky;
  bottom: 0;
  padding: 16px 0 24px;
  border-top: 1px solid var(--border);
  background: var(--bg-deep);
  display: flex;
  gap: 8px;
  align-items: center;
  z-index: 10;
}

.onboard-actions .spacer { flex: 1; }

/* Step indicator */
.step-indicator {
  display: flex;
  gap: 4px;
  margin-bottom: 28px;
}

.step-indicator-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.step-indicator-bar {
  width: 100%;
  height: 3px;
  border-radius: 2px;
  background: var(--border);
  transition: background var(--transition);
}

.step-indicator-item.active .step-indicator-bar,
.step-indicator-item.done .step-indicator-bar {
  background: var(--accent-blue);
}

.step-indicator-label {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-muted);
  transition: color var(--transition);
}

.step-indicator-item.active .step-indicator-label { color: var(--accent-blue); }
.step-indicator-item.done .step-indicator-label   { color: var(--text-secondary); }

/* Inline input + button row */
.invite-row {
  display: flex;
  gap: 8px;
  align-items: center;
}

.invite-row .input-forge { flex: 1; }
.invite-row select.input-forge { flex: 0; min-width: 130px; }

/* Chip lists (invites, files) */
.invite-list, .file-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 8px;
}

.invite-chip, .file-chip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  font-size: 12px;
  color: var(--text-secondary);
}

/* Owner chip — accent border + small "Owner" badge. The badge replaces the × button so the
   chip can't be removed by accident; transferring ownership is the only way out. */
.invite-chip-owner {
  border-color: var(--accent-blue-dim);
  background: var(--accent-glow);
}
.invite-chip .chip-badge {
  margin-left: 8px;
  padding: 2px 8px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--accent-blue);
  background: var(--bg-primary);
  border: 1px solid var(--accent-blue-dim);
  border-radius: 999px;
}

/* Generic margin utility — pushes the next sibling to the right inside a flex container.
   Used by the "Transfer ownership" button in the Org Admins card title row. */
.u-ml-auto { margin-left: auto; }

.file-chip {
  font-family: var(--font-mono);
  font-size: 11px;
}

.file-chip .file-size {
  color: var(--text-muted);
  font-size: 10px;
  margin-left: 8px;
}

.chip-remove {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  padding: 0 4px;
  transition: color var(--transition);
}

.chip-remove:hover { color: var(--danger); }

/* Item list (teams, projects) */
.item-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 16px;
}

.item-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 14px;
}

.item-card-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.item-card-name {
  font-weight: 600;
  font-size: 13px;
  color: var(--text-primary);
}

.item-card-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  letter-spacing: 0.5px;
}

.item-remove {
  margin-left: auto;
  color: var(--text-muted);
  background: none;
  border: none;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
  transition: color var(--transition);
}

.item-remove:hover { color: var(--danger); }

/* Sub-invite row (nested inside item cards) */
.sub-invite { margin-top: 10px; }

.input-forge.sm { height: 30px; font-size: 11px; padding: 0 8px; }
.btn-forge.sm   { height: 30px; font-size: 11px; padding: 0 10px; }

/* Toggle switch */
.toggle-switch {
  position: relative;
  width: 40px;
  height: 22px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 11px;
  cursor: pointer;
  transition: all var(--transition);
  flex-shrink: 0;
  user-select: none;
}

.toggle-switch::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  background: var(--text-secondary);
  border-radius: 50%;
  transition: all var(--transition);
}

.toggle-switch.on::after {
  left: 20px;
}

.toggle-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--text-primary);
  font-weight: 500;
  margin-bottom: 10px;
}

.codebase-hints {
  list-style: disc;
  padding-left: 20px;
  margin: 0;
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.8;
}

.codebase-hints strong {
  color: var(--text-primary);
  font-weight: 600;
}

/* Policy checklist */
.policy-checklist {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  max-height: 260px;
  overflow-y: auto;
}

/* Drag-and-drop zone */
.drop-zone {
  border: 2px dashed var(--border);
  border-radius: var(--radius-md);
  padding: 20px;
  text-align: center;
  color: var(--text-muted);
  font-size: 12px;
  cursor: pointer;
  transition: all var(--transition);
  margin-top: 10px;
}

.drop-zone:hover,
.drop-zone--active {
  border-color: var(--accent-blue-dim);
  background: var(--accent-glow);
  color: var(--text-secondary);
}

/* Onboarding section label */
.onboard-section-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-top: 20px;
  margin-bottom: 8px;
}

@media (max-width: 680px) {
  .onboard-card { max-width: 100%; padding: 20px; }
  .invite-row { flex-wrap: wrap; }
}

/* ── Org chooser ─────────────────────────────────────── */
.org-chooser-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}

.org-chooser-item-form { margin: 0; }

.org-chooser-item {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  transition: all var(--transition);
}

.org-chooser-item:hover {
  background: var(--bg-hover);
  border-color: var(--accent-blue-dim);
  color: var(--text-primary);
}

.org-chooser-item-arrow {
  color: var(--text-muted);
  font-size: 16px;
  transition: transform var(--transition), color var(--transition);
}

.org-chooser-item:hover .org-chooser-item-arrow {
  color: var(--accent-blue);
  transform: translateX(2px);
}

/* =========================================================
   Workspace — three-pane SDLC shell
   All rules namespaced with `ws-` prefix to keep the layout
   scoped and avoid clashes with onboarding / auth / landing.
   Ported from docs/forge-ui.html.
   ========================================================= */

/* When the workspace is present, lock main scroll so inner panes can scroll. */
.app-main:has(.ws-layout) { overflow: hidden; }
.app-main:has(.ws-empty)  { overflow: hidden; }

.ws-layout {
  flex: 1;
  display: flex;
  overflow: hidden;
  min-height: 0;
  position: relative;
}

/* Empty-state landing — shown when the user has no accessible projects
   in the active org (e.g. after skipping Teams/Projects onboarding). */
.ws-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 24px;
  min-height: 0;
}

.ws-empty-inner {
  max-width: 480px;
  text-align: center;
  /* Match the pane-empty-state styling used on the Projects tab. */
  font-size: 13px;
  color: var(--text-muted);
}

.ws-empty-inner svg {
  width: 48px;
  height: 48px;
  color: var(--text-muted);
  opacity: 0.5;
  margin: 0 auto 16px;
  display: block;
}

/* ── Rails (left SDLC + right Library) ─────────────────── */
.ws-rail {
  width: 260px;
  background: var(--bg-primary);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  transition: width var(--slide-transition);
  overflow: hidden;
}

.ws-rail-left  { border-right: 1px solid var(--border); }
.ws-rail-right { border-left:  1px solid var(--border); }

/* Visual Studio-style dock: collapsed rails keep a 28px column dedicated to
   the rotated reopen tab so the center pane never has a floating button
   overlapping its content. Border stays put — the column reads as the rail. */
.ws-rail.collapsed {
  width: 28px;
}

.ws-rail.collapsed > * {
  display: none;
}

.ws-rail-header {
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 12px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.ws-rail-header-title {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-muted);
}

.ws-rail-collapse-btn {
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  background: transparent;
  border: none;
  transition: all var(--transition);
}

.ws-rail-collapse-btn:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.ws-rail-collapse-btn svg { width: 14px; height: 14px; }

.ws-rail-content {
  flex: 1;
  overflow-y: auto;
  padding: 8px 0;
}

.ws-rail-content::-webkit-scrollbar { width: 4px; }
.ws-rail-content::-webkit-scrollbar-track { background: transparent; }
.ws-rail-content::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

/* VS-style tab dock for collapsed rails. The dock fills a 28px column
   top-to-bottom; tabs stack from the top with small gaps so we can add more
   later (e.g. additional tool panes). Each tab is borderless prose with an
   accent-blue strip on the outer edge that fades in on hover — matches the
   .ws-library-tab.active::after underline used elsewhere in the app. */
.ws-rail-tabs {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 28px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 8px 0;
  gap: 4px;
  z-index: 2;
  pointer-events: none; /* let clicks pass through empty dock space below tabs */
}

.ws-rail-tabs-left  { left: 0; }
.ws-rail-tabs-right { right: 0; }

.ws-rail-tab {
  pointer-events: auto;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px 0;
  background: transparent;
  color: var(--text-muted);
  border: none;
  cursor: pointer;
  transition: color var(--transition), background var(--transition);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  user-select: none;
  flex-shrink: 0;
}

.ws-rail-tab:hover {
  color: var(--accent-blue);
  background: var(--accent-glow);
}

/* Accent strip on the outer edge (the side facing the content area). Hidden
   by default, fades in on hover — same accent-blue used for active tabs in
   the library + workspace toolbar. */
.ws-rail-tab::after {
  content: '';
  position: absolute;
  top: 4px;
  bottom: 4px;
  width: 2px;
  background: var(--accent-blue);
  opacity: 0;
  transition: opacity var(--transition);
}

.ws-rail-tab:hover::after { opacity: 1; }

.ws-rail-tabs-left  .ws-rail-tab::after { right: 0; }
.ws-rail-tabs-right .ws-rail-tab::after { left: 0; }

.ws-rail-tab-label {
  writing-mode: vertical-rl;
  text-orientation: mixed;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  white-space: nowrap;
  user-select: none;
}

/* ── Team + Project selector block ─────────────────────── */
/* Uses the unchanged .input-forge theme so both selects render identically to
 * every other dropdown in the app (OrgSetup, ProjectSetup, ChooseOrg). Labels
 * and meta are padded by 12px to align with .input-forge's internal padding. */
.ws-project-selector {
  margin: 8px 10px 14px;
}

.ws-project-selector .field-label {
  display: block;
  padding-left: 12px;
  margin: 10px 0 6px;
}

.ws-project-selector .field-label:first-child {
  margin-top: 0;
}

.ws-project-meta {
  margin-top: 8px;
  padding-left: 12px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  letter-spacing: 0.3px;
}

/* ── Phases & steps ────────────────────────────────────── */
.ws-phase-group { margin-bottom: 4px; }

.ws-phase-group-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  cursor: pointer;
  transition: background var(--transition);
  user-select: none;
}

.ws-phase-group-header:hover { background: var(--bg-hover); }

.ws-phase-chevron {
  width: 12px;
  height: 12px;
  color: var(--text-muted);
  transition: transform var(--transition);
  flex-shrink: 0;
}

.ws-phase-group.open .ws-phase-chevron { transform: rotate(90deg); }

.ws-phase-status-ring {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.ws-phase-status-ring.complete {
  border-color: var(--success);
  background: var(--success-dim);
}

.ws-phase-status-ring.complete::after {
  content: '\2713';
  font-size: 9px;
  color: var(--success);
  font-weight: 700;
}

.ws-phase-status-ring.active {
  border-color: var(--accent-blue);
  background: var(--accent-glow);
}

.ws-phase-status-ring.active::after {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-blue);
}

.ws-phase-name {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-secondary);
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ws-phase-group.active .ws-phase-name   { color: var(--text-primary); }
.ws-phase-group.complete .ws-phase-name { color: var(--text-muted); }

.ws-phase-steps {
  display: none;
  padding-left: 22px;
}

.ws-phase-group.open .ws-phase-steps { display: block; }

.ws-step-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 14px 4px 18px;
  transition: background var(--transition);
  position: relative;
  user-select: none;
}

.ws-step-item::before {
  content: '';
  position: absolute;
  left: 21px;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--border);
}

.ws-step-item:last-child::before { height: 50%; }

.ws-step-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  flex-shrink: 0;
  z-index: 1;
  background: var(--bg-primary);
}

.ws-step-dot.complete {
  border-color: var(--success);
  background: var(--success);
}

.ws-step-dot.active {
  border-color: var(--accent-blue);
  background: var(--accent-blue);
  box-shadow: 0 0 6px rgba(77, 142, 247, 0.4);
}

.ws-step-label {
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ws-step-item.active .ws-step-label   { color: var(--accent-light); font-weight: 500; }
.ws-step-item.complete .ws-step-label { color: var(--text-muted); }

/* Click-to-view affordance — any step that can be opened for read-only inspection. */
.ws-step-item.clickable { cursor: pointer; }
.ws-step-item.clickable:hover { background: var(--bg-hover); }

/* Currently-viewed step — subtle highlight + left accent stripe so the user can see
 * which step's artifact + history is displayed in the centre panes. */
.ws-step-item.viewed {
  background: var(--accent-glow);
  box-shadow: inset 2px 0 0 var(--accent-blue);
}
.ws-step-item.viewed .ws-step-label { color: var(--text-primary); }

.ws-step-role {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-muted);
  margin-left: auto;
  flex-shrink: 0;
  opacity: 0.6;
}

/* ── Center column (chat + preview) ────────────────────── */
.ws-center {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  position: relative;
}

.ws-center-split {
  flex: 1;
  display: flex;
  overflow: hidden;
}

.ws-chat-pane {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  /* Separator between chat + preview is now the draggable .ws-pane-divider element */
}

/* ── Draggable divider between chat and preview ─────── */
.ws-pane-divider {
  width: 4px;
  flex-shrink: 0;
  background: var(--border);
  cursor: ew-resize;
  transition: background var(--transition);
  user-select: none;
}

.ws-pane-divider:hover,
.ws-pane-divider.dragging {
  background: var(--accent-blue);
}

/* Lock the cursor + prevent text selection across the whole page while a drag is in flight.
 * State class (no `u-` prefix) — matches the `.collapsed` / `.active` / `.open` pattern
 * used elsewhere for component state, rather than the `u-*` utility-class convention. */
body.ws-is-dragging,
body.ws-is-dragging * {
  cursor: ew-resize !important;
  user-select: none !important;
}

.ws-pane-toolbar {
  height: 36px;
  display: flex;
  align-items: center;
  padding: 0 10px;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  background: var(--bg-primary);
}

.ws-toolbar-btn {
  height: 26px;
  padding: 0 8px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all var(--transition);
  white-space: nowrap;
  user-select: none;
}

.ws-toolbar-btn:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.ws-toolbar-btn.active {
  color: var(--accent-blue);
  background: var(--accent-glow);
}

/* Static "Chat" / "Artifact" pane title — looks like an active toolbar button but is not
   interactive. Keep the default cursor and suppress hover so it doesn't pretend to be clickable. */
.ws-toolbar-pane-title,
.ws-toolbar-pane-title:hover {
  cursor: default;
  background: var(--accent-glow);
  color: var(--accent-blue);
}

/* ── Toolbar overflow (kebab + popup) ───────────────────
   When the chat pane is too narrow to fit every toolbar button, JS folds the lowest-priority
   foldable buttons into this kebab menu. The kebab is server-rendered hidden; JS reveals it
   when needed. The popup is anchored to the kebab and listed below the toolbar. */
.ws-toolbar-overflow {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}

.ws-toolbar-overflow-menu {
  /* position: fixed so the menu escapes ancestor overflow: hidden clipping
     (the chat-pane / layout containers crop the kebab popup otherwise).
     JS sets top/left in viewport coordinates on each open. */
  position: fixed;
  min-width: 160px;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
  z-index: 1100;
}

.ws-toolbar-overflow-menu .ws-toolbar-overflow-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 10px;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: 12px;
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
}
.ws-toolbar-overflow-menu .ws-toolbar-overflow-item:hover { background: var(--bg-hover); }
.ws-toolbar-overflow-menu .ws-toolbar-overflow-item svg { width: 13px; height: 13px; flex-shrink: 0; color: var(--text-secondary); }

.ws-toolbar-btn.primary {
  color: #fff;
  background: var(--accent-blue);
}

.ws-toolbar-btn.primary:hover { background: var(--accent-blue-dim); color: #fff; }

.ws-toolbar-btn[disabled],
.ws-toolbar-btn.disabled {
  opacity: 0.5;
  pointer-events: none;
}

.ws-toolbar-btn svg { width: 13px; height: 13px; flex-shrink: 0; }

.ws-toolbar-separator {
  width: 1px;
  height: 16px;
  background: var(--border);
  margin: 0 4px;
}

.ws-toolbar-spacer { flex: 1; }

.ws-toolbar-label {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  letter-spacing: 0.5px;
  /* Stay on one line and don't be flex-shrunk. Without these, the label wraps internally
     when the pane is narrow, which keeps the toolbar's scrollWidth equal to clientWidth and
     defeats the overflow detection — the label looks ugly and the JS never hides it. */
  white-space: nowrap;
  flex-shrink: 0;
}

/* ── Chat messages ─────────────────────────────────────── */
.ws-chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.ws-chat-messages::-webkit-scrollbar { width: 4px; }
.ws-chat-messages::-webkit-scrollbar-track { background: transparent; }
.ws-chat-messages::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

.ws-msg {
  display: flex;
  gap: 10px;
  max-width: 100%;
  animation: ws-msg-in 0.3s ease-out;
}

@keyframes ws-msg-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.ws-msg-avatar {
  width: 24px;
  height: 24px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 600;
  margin-top: 2px;
}
/* Avatars now use SVG icons (person for user, brain for Forge) instead of letter glyphs.
   Size + center inside the 24px avatar tile; stroke color comes from the parent's `color`
   so the user/forge variants keep their existing color treatment. */
.ws-msg-avatar svg {
  width: 14px;
  height: 14px;
}

.ws-msg-avatar.user {
  background: var(--accent-glow-strong);
  color: var(--accent-blue);
  border: 1px solid var(--accent-blue-dim);
}

.ws-msg-avatar.forge {
  background: var(--bg-surface);
  color: var(--text-secondary);
  border: 1px solid var(--border);
}

.ws-msg-body { flex: 1; min-width: 0; }

.ws-msg-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.ws-msg-sender {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-primary);
}

.ws-msg-time {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
}

.ws-msg-role-badge {
  font-family: var(--font-mono);
  font-size: 9px;
  padding: 1px 6px;
  border-radius: 3px;
  background: var(--accent-glow);
  color: var(--accent-blue);
  border: 1px solid rgba(77, 142, 247, 0.2);
}

.ws-msg-text {
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-secondary);
}

/* "Forge didn't respond" text inside a failed assistant bubble. Styled lightly italic so it
 * reads as a system-y status rather than something the AI said. The Retry button doesn't sit
 * inside the bubble — see .ws-msg-retry-row below. */
.ws-msg-failed-text {
  font-style: italic;
  color: var(--text-muted);
}

/* Centered Retry row that gets appended to the chat messages list under a failed assistant
 * message. The button uses the existing btn-forge ghost styling so it matches every other
 * action button in the app (Add knowledge, Save to Confluence, etc.) — only the layout is
 * specific to this surface. */
.ws-msg-retry-row {
  display: flex;
  justify-content: center;
  padding: 4px 0 12px;
}
.ws-msg-retry-row .btn-forge svg {
  width: 12px;
  height: 12px;
}

/* Pre-first-token indicator — single brand verb with an ellipsis that animates the word
 * itself. Single signal, no separate spinner element, brand-coherent. */
.ws-thinking-indicator {
  display: inline-block;
  color: var(--text-muted);
  font-style: italic;
  font-size: 13px;
  line-height: 1;
  padding: 2px 0;
}

.ws-thinking-indicator::after {
  content: '…';
  display: inline-block;
  width: 0;
  overflow: hidden;
  vertical-align: bottom;
  animation: ws-thinking-ellipsis 1.4s steps(4, end) infinite;
}

@keyframes ws-thinking-ellipsis {
  to { width: 1em; }
}

/* Mid-stream indicator — sibling of the streaming text container so it stays stable
 * across chunk re-renders (animation doesn't restart). Removed on content_final. */
.ws-stream-indicator {
  padding: 6px 0 0;
}

/* Loading state for primary toolbar buttons — pulses the icon + text so the user
 * sees activity even when the server is taking time to respond. */
.ws-toolbar-btn.is-loading {
  cursor: wait;
  animation: ws-btn-pulse 1.4s ease-in-out infinite;
  pointer-events: none;
}

@keyframes ws-btn-pulse {
  0%, 100% { opacity: 0.65; }
  50%      { opacity: 1; }
}

/* Rendered-Markdown elements inside assistant bubbles. Mirrors the artifact-body rules so
 * the formatting language is consistent across chat and preview — headings, bullets, code. */
.ws-msg-text h1,
.ws-msg-text h2,
.ws-msg-text h3,
.ws-msg-text h4 {
  color: var(--text-primary);
  font-weight: 600;
  margin: 10px 0 6px;
}
.ws-msg-text h1 { font-size: 15px; }
.ws-msg-text h2 { font-size: 14px; }
.ws-msg-text h3 { font-size: 13px; }
.ws-msg-text h4 { font-size: 12px; }
.ws-msg-text h1:first-child,
.ws-msg-text h2:first-child,
.ws-msg-text h3:first-child,
.ws-msg-text h4:first-child { margin-top: 0; }

.ws-msg-text p { margin: 0 0 8px; }
.ws-msg-text p:last-child { margin-bottom: 0; }

.ws-msg-text ul,
.ws-msg-text ol {
  padding-left: 18px;
  margin: 4px 0 8px;
}
.ws-msg-text li { margin: 2px 0; }

.ws-msg-text pre {
  font-family: var(--font-mono);
  font-size: 11.5px;
  padding: 8px 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  overflow-x: auto;
  margin: 6px 0;
}
.ws-msg-text pre code {
  padding: 0;
  background: none;
  border: none;
  color: inherit;
}

.ws-msg-text blockquote {
  margin: 6px 0;
  padding-left: 10px;
  border-left: 2px solid var(--accent-blue-dim);
  color: var(--text-muted);
}

.ws-msg-text a {
  color: var(--accent-light);
  text-decoration: underline;
}

.ws-msg-text code {
  font-family: var(--font-mono);
  font-size: 11.5px;
  padding: 1px 5px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  color: var(--accent-light);
}

.ws-msg-tool-call {
  margin-top: 8px;
  padding: 8px 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 6px;
}

.ws-msg-tool-call .ws-tool-icon { color: var(--accent-blue); }
.ws-msg-tool-call .ws-tool-name { color: var(--accent-light); font-weight: 500; }

/* ── Chat input (static) ─────────────────────────────── */
.ws-chat-input-area {
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  background: var(--bg-primary);
}

.ws-chat-input-box {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  transition: border-color var(--transition);
}

.ws-chat-input-box:focus-within { border-color: var(--accent-blue-dim); }

.ws-chat-input-box textarea {
  flex: 1;
  background: none;
  border: none;
  outline: none;
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 13px;
  resize: none;
  line-height: 1.5;
  /* 8 rows × 13px × 1.5 line-height ≈ 156px. JS sizes to content up to this cap. */
  max-height: 156px;
  min-height: 20px;
  overflow-y: auto;
}

.ws-chat-input-box textarea::placeholder { color: var(--text-muted); }

.ws-send-btn {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  background: var(--accent-blue);
  color: #fff;
  border: none;
  cursor: pointer;
  flex-shrink: 0;
  transition: all var(--transition);
}

.ws-send-btn:hover { background: var(--accent-light); }
.ws-send-btn svg   { width: 14px; height: 14px; }

/* ── Preview / artifact pane ─────────────────────────── */
.ws-preview-pane {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.ws-preview-content {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  background: var(--bg-deep);
}

.ws-preview-content::-webkit-scrollbar { width: 4px; }
.ws-preview-content::-webkit-scrollbar-track { background: transparent; }
.ws-preview-content::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

.ws-artifact-card {
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  animation: ws-card-in 0.4s ease-out;
}

@keyframes ws-card-in {
  from { opacity: 0; transform: scale(0.97); }
  to   { opacity: 1; transform: scale(1); }
}

.ws-artifact-card-header {
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--bg-surface);
}

.ws-artifact-type-badge {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 3px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  background: rgba(139, 92, 246, 0.15);
  color: #a78bfa;
  border: 1px solid rgba(139, 92, 246, 0.25);
}

.ws-artifact-card-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-primary);
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ws-artifact-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
}

/* Toolbar above the artifact body in the preview modal — Download / Save to Confluence.
   Sits between the header (title row) and the body so it's the first set of affordances
   the user sees on opening the preview. */
.ws-artifact-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-elevated);
}
.ws-artifact-toolbar .btn-forge {
  font-size: 11px;
  padding: 4px 10px;
}
.ws-artifact-toolbar .btn-forge svg { width: 12px; height: 12px; }

/* "Saved to Confluence at …" panel rendered above the body when the artifact has a link.
   Same low-key inline-info styling as the chat info-chips — a small banner of metadata,
   not a primary action. */
.ws-artifact-link-panel {
  padding: 8px 14px;
  font-size: 12px;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border);
  background: var(--bg-elevated);
}
.ws-artifact-link-row { line-height: 1.5; }
.ws-artifact-link-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-muted);
}
.ws-artifact-link-meta {
  font-size: 11px;
  color: var(--text-muted);
}

/* Vertical action grid inside the "Save to Confluence" modal when an artifact is linked —
   stacks Update / Save-as-new / Unlink as full-width buttons so each option reads cleanly. */
.ws-modal-action-grid {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.ws-modal-action-grid .btn-forge {
  width: 100%;
  justify-content: flex-start;
}

.ws-artifact-body {
  padding: 16px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--text-secondary);
}

.ws-artifact-body h1,
.ws-artifact-body h2,
.ws-artifact-body h3,
.ws-artifact-body h4 {
  color: var(--text-primary);
  font-weight: 600;
  margin: 16px 0 8px;
}

.ws-artifact-body h1 { font-size: 16px; }
.ws-artifact-body h2 { font-size: 14px; }
.ws-artifact-body h3 { font-size: 13px; }
.ws-artifact-body h4 { font-size: 12px; }
.ws-artifact-body h1:first-child,
.ws-artifact-body h2:first-child,
.ws-artifact-body h3:first-child,
.ws-artifact-body h4:first-child { margin-top: 0; }

.ws-artifact-body p { margin: 6px 0 10px; }

.ws-artifact-body ul,
.ws-artifact-body ol {
  padding-left: 18px;
  margin: 6px 0 10px;
}

.ws-artifact-body li { margin: 3px 0; }

.ws-artifact-body code {
  font-family: var(--font-mono);
  font-size: 11.5px;
  padding: 1px 5px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  color: var(--accent-light);
}

.ws-artifact-body pre {
  font-family: var(--font-mono);
  font-size: 11.5px;
  padding: 10px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  overflow-x: auto;
  margin: 8px 0;
}

.ws-artifact-body pre code {
  padding: 0;
  background: none;
  border: none;
  color: inherit;
}

.ws-artifact-body blockquote {
  margin: 10px 0;
  padding-left: 12px;
  border-left: 2px solid var(--accent-blue-dim);
  color: var(--text-muted);
}

.ws-artifact-empty {
  padding: 40px 20px;
  text-align: center;
  color: var(--text-muted);
  font-size: 12px;
  font-family: var(--font-mono);
}

.ws-artifact-empty-title {
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: 6px;
}

/* ── Library (right rail) ─────────────────────────────── */
.ws-library-tabs {
  display: flex;
  padding: 0 10px;
  gap: 0;
  border-bottom: 1px solid var(--border);
}

.ws-library-tab {
  padding: 6px 10px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-muted);
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all var(--transition);
  position: relative;
  user-select: none;
}

.ws-library-tab:hover { color: var(--text-secondary); }

.ws-library-tab.active { color: var(--accent-blue); }

.ws-library-tab.active::after {
  content: '';
  position: absolute;
  bottom: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--accent-blue);
}

/* "Add knowledge" dropdown sits between the tab strip and the item list. The trigger is a
   ghost btn-forge with a caret; the menu uses the same styling as the user-menu dropdown so
   the visual language stays consistent across the app. */
.ws-library-add {
  position: relative;
  padding: 6px 10px 0;
}
.ws-library-add-btn {
  width: 100%;
  justify-content: center;
  font-size: 11px;
  padding: 4px 10px;
}
.ws-library-add-btn svg { width: 12px; height: 12px; }
.ws-library-add-caret { margin-left: auto; }

.ws-library-add-menu {
  display: none;
  position: absolute;
  top: calc(100% + 2px);
  left: 10px;
  right: 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  z-index: 200;
  padding: 4px;
}
.ws-library-add-menu.open { display: block; }

.ws-library-add-menu .menu-label {
  padding: 8px 12px 4px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.5px;
  color: var(--text-muted);
}
.ws-library-add-menu .menu-divider {
  height: 1px;
  background: var(--border);
  margin: 4px 0;
}
.ws-library-add-menu button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 12px;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--text-secondary);
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-align: left;
  transition: all var(--transition);
}
.ws-library-add-menu button:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.ws-checkbox-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-primary);
  cursor: pointer;
}

.ws-library-items {
  flex: 1;
  overflow-y: auto;
  padding: 6px 0;
}

.ws-library-items::-webkit-scrollbar { width: 4px; }
.ws-library-items::-webkit-scrollbar-track { background: transparent; }
.ws-library-items::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

.ws-library-section {
  display: block;
}

.ws-library-section-label {
  padding: 8px 14px 4px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-muted);
}

.ws-library-subgroup-label {
  padding: 6px 14px 2px 22px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  letter-spacing: 0.2px;
}

.ws-library-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 14px;
  transition: background var(--transition);
  user-select: none;
}

.ws-library-item:hover { background: var(--bg-hover); }

.ws-library-item-icon {
  width: 18px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.ws-library-item-icon svg { width: 14px; height: 14px; }

.ws-library-item-icon.knowledge { color: var(--success); }
.ws-library-item-icon.policy    { color: var(--warning); }
.ws-library-item-icon.template  { color: #a78bfa; }
.ws-library-item-icon.doc       { color: var(--accent-blue); }

.ws-library-item-name {
  font-size: 12px;
  color: var(--text-secondary);
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ws-library-item-badge {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-muted);
  flex-shrink: 0;
}

.ws-library-empty {
  padding: 16px 14px;
  font-size: 11px;
  color: var(--text-muted);
  font-style: italic;
}

/* Inline "auto" badge next to a Jira required-field label — signals that Forge will fill the
   field in per story rather than asking the user to provide a value. Visual treatment matches
   the lightweight badges used elsewhere (library item kinds, conn-dot adjacents). */
.ws-jira-auto-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--accent-blue);
  background: rgba(77, 142, 247, 0.12);
  border-radius: 3px;
  vertical-align: middle;
}

.ws-banner { margin: 8px 12px; }

/* Small-screen adjustments — mirror mockup's behaviour. */
@media (max-width: 1200px) {
  .ws-rail { width: 220px; }
}

/* ── Config pages (Organization / Teams / Projects) ───── */
/* Class vocabulary and visual treatment mirror docs/forge-ui.html mock. */

.u-p-sm { padding: 8px 12px; }

/* Tab-view shell — full-page, stretched, no centering. */
.tab-view {
  flex: 1;
  display: flex;
  overflow: hidden;
  min-height: 0;
}

/* Left nav (Teams/Projects) */
.left-nav {
  width: 260px;
  background: var(--bg-primary);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  overflow: hidden;
}

.nav-header {
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 12px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.nav-header-title {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-muted);
}

.nav-add-btn {
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  background: transparent;
  border: none;
  transition: all var(--transition);
}
.nav-add-btn:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}
.nav-add-btn svg { width: 14px; height: 14px; }

.nav-content {
  flex: 1;
  overflow-y: auto;
  padding: 6px 0;
}
.nav-content::-webkit-scrollbar { width: 4px; }
.nav-content::-webkit-scrollbar-track { background: transparent; }
.nav-content::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

/* Team list items (Teams nav) */
.group-tree-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  margin: 0 6px 2px;
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background var(--transition);
  color: inherit;
}
.group-tree-item:hover { background: var(--bg-hover); }
.group-tree-item.active { background: var(--accent-glow); }
.group-tree-item svg { width: 16px; height: 16px; color: var(--text-muted); flex-shrink: 0; }
.group-tree-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Project list (grouped by team, collapsible) */
.project-list-group {
  margin: 0 6px 4px;
}
.project-list-group-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background var(--transition);
  user-select: none;
}
.project-list-group-header:hover { background: var(--bg-hover); }
.project-list-group-header svg { width: 12px; height: 12px; color: var(--text-muted); flex-shrink: 0; }
.project-list-group-header .plg-chevron { transition: transform var(--transition); }
.project-list-group.open .plg-chevron { transform: rotate(90deg); }
.project-list-group-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  flex: 1;
}
.project-list-group-children {
  display: none;
  padding-left: 8px;
}
.project-list-group.open > .project-list-group-children { display: block; }

.project-list-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 6px 24px;
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background var(--transition);
  color: inherit;
}
.project-list-item:hover { background: var(--bg-hover); }
.project-list-item.active { background: var(--accent-glow); }
.project-list-item-name {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-primary);
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Tree actions (hover-reveal delete icons) */
.tree-actions {
  display: flex;
  gap: 2px;
  flex-shrink: 0;
  opacity: 0;
  transition: opacity var(--transition);
}
.group-tree-item:hover .tree-actions,
.project-list-item:hover .tree-actions { opacity: 1; }

.tree-action-btn {
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  background: transparent;
  border: none;
  transition: all var(--transition);
}
.tree-action-btn:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

/* Main pane: full-page-split > full-page-left > (pane-toolbar + full-page-left-content) */
.full-page-split {
  flex: 1;
  display: flex;
  overflow: hidden;
}
.full-page-left {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.full-page-left-content {
  flex: 1;
  overflow-y: auto;
  padding: 24px 28px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Constrain content to a comfortable column width on the Org/Teams/Projects
   tabs. Cards remain full-width within this cap; the surrounding scroll area
   centers them so the page reads as a focused settings column rather than a
   wall of cards stretching to the rails. */
.full-page-left-content > * {
  width: 100%;
  max-width: 880px;
  margin-left: auto;
  margin-right: auto;
}
.full-page-left-content::-webkit-scrollbar { width: 4px; }
.full-page-left-content::-webkit-scrollbar-track { background: transparent; }
.full-page-left-content::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

/* Pane toolbar with Save / Delete / etc. */
.pane-toolbar {
  height: 36px;
  display: flex;
  align-items: center;
  padding: 0 10px;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  background: var(--bg-primary);
}

.toolbar-btn {
  height: 26px;
  padding: 0 8px;
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  border-radius: var(--radius-sm);
  cursor: pointer;
  background: transparent;
  border: none;
  transition: all var(--transition);
  white-space: nowrap;
  user-select: none;
}
.toolbar-btn:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}
.toolbar-btn.active {
  color: var(--accent-blue);
  background: var(--accent-glow);
}
.toolbar-btn.primary {
  color: var(--accent-blue);
}
.toolbar-btn:disabled {
  opacity: 0.5;
}
.toolbar-btn svg { width: 13px; height: 13px; flex-shrink: 0; }

.toolbar-separator {
  width: 1px;
  height: 16px;
  background: var(--border);
  margin: 0 4px;
}
.toolbar-spacer { flex: 1; }

.toolbar-label {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  letter-spacing: 0.5px;
  padding: 0 8px;
}
.toolbar-label.saved { color: var(--success); }

/* Bordered section cards */
.config-card {
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px;
}
.config-card.expand {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.config-card-title {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.config-card-title svg { width: 14px; height: 14px; }

.config-card-divider {
  height: 1px;
  background: var(--border);
  margin: 16px 0;
}

.config-field {
  margin-bottom: 10px;
}
.config-card .config-field:last-child { margin-bottom: 0; }

.config-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  margin-bottom: 4px;
  display: block;
}

.config-input {
  width: 100%;
  height: 32px;
  padding: 0 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: 12px;
  font-weight: 400;
  font-family: var(--font-sans);
  line-height: 1.5;
  outline: none;
  transition: border-color var(--transition);
}
.config-input:focus { border-color: var(--accent-blue-dim); }
.config-input[readonly] { opacity: 0.6; cursor: default; }
.config-input::placeholder { color: var(--text-muted); font-weight: 400; }

select.config-input { padding: 0 8px; }

/* Textareas can't honour rows= when a fixed height is set, so let them grow
   to whatever the rows attribute asks for and allow vertical resize. */
textarea.config-input {
  height: auto;
  min-height: 80px;
  padding: 8px 10px;
  line-height: 1.5;
  resize: vertical;
}

.config-meta-row {
  display: flex;
  gap: 20px;
  margin-top: 4px;
}
.config-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.config-meta-label {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-muted);
}
.config-meta-value {
  font-size: 12px;
  color: var(--text-primary);
}

/* Empty state for "no selection" */
.pane-empty-state {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
}
.pane-empty-state-inner {
  text-align: center;
  font-size: 13px;
}
.pane-empty-state-inner svg {
  width: 32px;
  height: 32px;
  margin: 0 auto 10px;
  display: block;
  opacity: 0.4;
}

/* Build step pane — replaces the chat thread for steps where Kind=Build. Lives inside the
   ws-chat-pane shell. The pane itself is a non-scrolling flex column; the active-build
   child handles its own top/bottom split with a draggable horizontal divider. */
.ws-build-pane {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  font-size: 13px;
}
.ws-build-no-build { padding: 16px 20px; }

/* Active build — flex column with two children + a divider. Top holds meta/plan/actions,
   bottom holds the live event log; both scroll internally so neither blows out the layout. */
.ws-build-active {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.ws-build-top {
  flex: 0 0 50%;       /* initial split: 50/50; JS sets pixel basis when user drags */
  min-height: 80px;
  overflow: hidden;    /* header is pinned, body scrolls — no scroll on the wrapper */
  display: flex;
  flex-direction: column;
}
/* Non-scrolling header — holds meta block + action buttons. Stays visible regardless of
   how far the user scrolls in the plan-step list below. Without this, a long plan list
   pushed Next / Abort / Open-PR off-screen and the user had to scroll to find them. */
.ws-build-top-header {
  flex: 0 0 auto;
  padding: 16px 20px 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  border-bottom: 1px solid var(--border);
}
/* Scrollable body — currently just the plan-step list, may grow later. */
.ws-build-top-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 20px 16px;
}
.ws-build-bottom {
  flex: 1;
  min-height: 80px;
  overflow-y: auto;
  padding: 12px 20px 16px;
  display: flex;
  flex-direction: column;
}
.ws-build-bottom .ws-build-events { flex: 1; max-height: none; }

/* Horizontal divider between top and bottom — same vocabulary as the chat/preview ws-pane-divider
   but rotates the cursor for vertical drag. JS sets ws-build-pane.style.userSelect during drag. */
.ws-build-divider-h {
  height: 4px;
  flex-shrink: 0;
  background: var(--border);
  cursor: ns-resize;
  transition: background var(--transition);
  user-select: none;
}
.ws-build-divider-h:hover { background: var(--accent, var(--text-muted)); }
.ws-build-loading { color: var(--text-muted); }
.ws-build-section-title { font-size: 14px; font-weight: 600; margin: 0 0 4px; }
.ws-build-meta {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 4px 12px;
  padding: 12px;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.ws-build-meta-row { display: contents; }
.ws-build-meta-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-muted);
}
.ws-build-meta-value { color: var(--text-primary); font-family: var(--font-mono); font-size: 12px; }
.ws-build-plan-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ws-build-plan-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-primary);
}
.ws-build-plan-item.current { border-color: var(--success); }
.ws-build-plan-num {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  min-width: 50px;
}
.ws-build-plan-title { flex: 1; }
.ws-build-plan-badge {
  font-size: 10px;
  font-family: var(--font-mono);
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  background: var(--bg-secondary);
  color: var(--text-muted);
}
.ws-build-plan-badge.completed { background: var(--success-dim); color: var(--success); }
.ws-build-plan-badge.running { background: var(--success-dim); color: var(--success); }
.ws-build-plan-badge.failed { background: var(--danger-dim); color: var(--danger); }
.ws-build-events {
  font-family: var(--font-mono);
  font-size: 12px;
  background: var(--bg-deep);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  max-height: 280px;
  overflow-y: auto;
}
.ws-build-event-line {
  color: var(--text-secondary);
  margin-bottom: 4px;
  white-space: pre-wrap;
}

/* "Forge is working…" indicator — sits above the event log while a sidecar run streams.
   Three pulsing dots + a label, so the user has visible feedback that the agent is doing
   something even while events are still being decoded. */
.ws-build-running {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  margin-bottom: 12px;  /* breathing room above the event log */
  background: var(--success-dim);
  border: 1px solid var(--success);
  color: var(--success);
  border-radius: var(--radius-md);
  font-size: 12px;
}
.ws-build-running-text { font-weight: 500; }
.ws-build-running-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--success);
  display: inline-block;
  animation: ws-build-running-pulse 1.2s infinite ease-in-out both;
}
.ws-build-running-dot:nth-child(1) { animation-delay: -0.32s; }
.ws-build-running-dot:nth-child(2) { animation-delay: -0.16s; }
@keyframes ws-build-running-pulse {
  0%, 80%, 100% { transform: scale(0.6); opacity: 0.5; }
  40% { transform: scale(1); opacity: 1; }
}

/* ── Build pane — bottom tabs (AI output / Refactor chat) ─────────────────
   Bottom-aligned tabs (Visual Studio style): the selected panel fills the column,
   tab strip sits below with a top border. Refactor tab is disabled until the plan
   step completes — JS toggles the `disabled` attribute. We keep the cursor at
   the default arrow on disabled tabs (no `not-allowed` icon) per UX feedback. */
.ws-build-bottom {
  padding: 0;
}
.ws-build-tab-panel {
  flex: 1;
  min-height: 0;
  /* Inner content owns its own scrolling. The panel itself stays fixed so anything
     pinned within (input box, Apply button) stays visible while the thread scrolls. */
  overflow: hidden;
  padding: 12px 20px 12px;
  display: flex;
  flex-direction: column;
}
.ws-build-tab-panel .ws-build-events {
  flex: 1;
  max-height: none;
  overflow-y: auto;
}
.ws-build-tabs {
  flex: 0 0 auto;
  display: flex;
  gap: 0;
  border-top: 1px solid var(--border);
  background: var(--bg-primary);
  padding: 0 12px;
}
.ws-build-tab {
  background: transparent;
  border: none;
  border-top: 2px solid transparent;
  color: var(--text-muted);
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  padding: 8px 14px;
  cursor: pointer;
  transition: color var(--transition), border-color var(--transition);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.ws-build-tab:hover:not(:disabled) { color: var(--text-secondary); }
.ws-build-tab.active {
  color: var(--text-primary);
  border-top-color: var(--accent-blue);
}
.ws-build-tab:disabled { opacity: 0.5; }
.ws-build-tab-count {
  display: inline-block;
  min-width: 18px;
  padding: 1px 5px;
  border-radius: 10px;
  background: var(--accent-glow);
  color: var(--accent-light);
  font-family: var(--font-mono);
  font-size: 10px;
  text-align: center;
}

/* ── Refactor chat — reuses .ws-msg / .ws-msg-avatar / .ws-msg-body / .ws-msg-text
   so messages match the main step-chat exactly. The pane itself just stacks a
   scrollable thread, the staged-attachments row, the input box, and a sticky
   Apply button at the bottom so it stays accessible regardless of scroll. */
.ws-build-refactor {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  gap: 10px;
}
.ws-build-refactor-thread {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 4px 0;
}
.ws-build-refactor-thread::-webkit-scrollbar { width: 4px; }
.ws-build-refactor-thread::-webkit-scrollbar-track { background: transparent; }
.ws-build-refactor-thread::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
.ws-build-refactor-staged {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  flex: 0 0 auto;
}
.ws-build-refactor-staged:empty { display: none; }
.ws-build-refactor-staged-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  font-size: 11px;
  font-family: var(--font-mono);
}
.ws-build-refactor-staged-chip button {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
  font-size: 14px;
  line-height: 1;
}
.ws-build-refactor-staged-chip button:hover { color: var(--danger); }

/* Apply button — lives inline with the send button so the whole "send + commit" row stays
   pinned, no scrolling required. Sized to match the 28px send button so the row doesn't
   look ragged; tighter padding than the default .btn-forge so it doesn't dominate. */
.ws-build-refactor-apply-btn {
  flex-shrink: 0;
  height: 28px;
  padding: 0 12px;
  font-size: 12px;
  line-height: 1;
  align-self: flex-end;
  display: inline-flex;
  align-items: center;
}

/* Visible feedback when a file is dragged over the refactor input box. Mirrors
   .ws-chat-input-box.is-drop-target styling vocabulary so both chats feel the same. */
.ws-build-refactor-input-box.is-drop-target {
  border-color: var(--accent-blue);
  background: var(--accent-glow);
}

/* Hide Apply while a chat send is streaming — same idea as the send button getting
   swapped for the spinner. The user shouldn't (and can't) commit mid-thought, so the
   button visually disappears until the agent comes back. */
.ws-chat-input-box.is-streaming .ws-build-refactor-apply-btn {
  display: none;
}

/* Per-message attachment chips (rendered inside .ws-msg-text). Pulled out of the bubble
   styling above — the main chat doesn't use bubbles, so neither do we. */
.ws-msg-attachment-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin: 6px 6px 0 0;
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
}

/* Back-link used at the top of sub-pages (e.g. settings detail screens) to return to the
   parent index. Visually quiet — same vocabulary as .field-hint with a small chevron. */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--text-muted);
  text-decoration: none;
  margin-bottom: 12px;
}
.back-link:hover { color: var(--text-primary); }
.back-link svg { width: 14px; height: 14px; }

/* Success-flavored sibling of .validation-summary-errors. Same shape and rhythm so the
   two read as a matched pair on settings/integration pages. */
.notice-success {
  background: var(--success-dim);
  border: 1px solid var(--success);
  color: var(--success);
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  font-size: 12px;
  margin-bottom: 16px;
}
.notice-success strong { color: var(--text-primary); }

/* Compact key/value row used for read-only metadata blocks (e.g. installed-app details on
   the GitHub Integration page). Label sits left, value right; stacks on narrow screens. */
.kv-row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 6px 0;
  border-top: 1px solid var(--border);
}
.kv-row:first-of-type { border-top: 0; padding-top: 0; }
.kv-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-muted);
  min-width: 120px;
}
.kv-value { color: var(--text-primary); font-size: 13px; }
@media (max-width: 540px) {
  .kv-row { flex-direction: column; gap: 2px; }
  .kv-label { min-width: 0; }
}

/* Repository chip + list — codegen targets registered against a project. Mirrors the
   .invite-chip / .file-chip vocabulary the rest of the project page already uses. */
.repo-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}
.repo-chip {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 6px 10px;
}
.repo-chip-name {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text-primary);
}
.repo-chip-branch {
  font-size: 11px;
  color: var(--text-muted);
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 1px 6px;
}
.repo-chip .chip-remove { margin-left: auto; }

/* Picker rows used inside the Add Repository modal. One row per available repo. */
.picker-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 320px;
  overflow-y: auto;
  padding-right: 4px;
}
.picker-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
}
.picker-row:hover { background: var(--bg-secondary); }
.picker-row input[type=radio] { margin: 0; }
.picker-row-name { font-family: var(--font-mono); font-size: 13px; }
.picker-row-meta { font-size: 11px; color: var(--text-muted); margin-left: auto; }

/* Integration row — used inside the Integrations config-card on the Organization page.
   Each row pairs a label/description block with a single right-aligned action button. */
.integration-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 0;
  border-top: 1px solid var(--border);
}
.integration-row:first-of-type { border-top: 0; padding-top: 4px; }
.integration-row-text { flex: 1; min-width: 0; }
.integration-row-title { font-weight: 600; color: var(--text-primary); }
.integration-row-sub {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 2px;
}

/* Subsection heading inside a config-card (e.g., "Baselines" within a Policies card). */
.config-subsection-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin-top: 12px;
  margin-bottom: 6px;
}
.config-card > .config-subsection-label:first-of-type { margin-top: 0; }

/* One level deeper than a subsection — groups toggles inside a subsection
   (e.g., "Backend" / "Frontend" within the Technology Stack subsection). */
.policy-subgroup-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-muted);
  margin-top: 8px;
  margin-bottom: 4px;
}
.policy-toggle-grid + .policy-subgroup-label { margin-top: 10px; }

/* ── Policy toggle grid (Organization / Project settings) ─ */
.policy-toggle-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 8px;
}

.policy-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color var(--transition), background var(--transition);
  user-select: none;
}
.policy-toggle:hover { border-color: var(--accent-blue-dim); }

.policy-toggle.readonly {
  cursor: default;
  background: var(--bg-elevated);
}
.policy-toggle.readonly:hover { border-color: var(--border); }

.policy-toggle-label {
  flex: 1;
  font-size: 12px;
  color: var(--text-primary);
}

.policy-toggle-badge {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--bg-primary);
}

/* Stronger visual when ON — the existing toggle-switch.on only moves the knob; we
   fill the track so scanning a grid of toggles is easy. */
.policy-toggle .toggle-switch.on {
  background: var(--accent-blue-dim);
  border-color: var(--accent-blue);
}
.policy-toggle .toggle-switch.on::after {
  background: #fff;
}

/* Locked baseline: show an on-state that can't be toggled, no cursor pointer. */
.policy-toggle .toggle-switch.locked {
  cursor: default;
  opacity: 0.75;
}
.policy-toggle .toggle-switch.locked.on {
  background: var(--text-muted);
  border-color: var(--text-muted);
}

/* ─────────────────────────────────────────────────────────────────────
   Sub-artifacts (mermaid, json, svg, html, markdown attached to a parent
   artifact). Rendered below the parent in the preview pane and listed
   indented in the library tree.
   ───────────────────────────────────────────────────────────────────── */
.ws-subartifacts {
  margin-top: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.ws-subartifacts-header {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 0 4px;
}
.ws-subartifact-card {
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-secondary);
  overflow: hidden;
}
.ws-subartifact-card-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-primary);
}
.ws-subartifact-name {
  font-weight: 600;
  font-size: 13px;
  color: var(--text-primary);
}
.ws-subartifact-format {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-radius: 3px;
}
.ws-subartifact-body {
  padding: 12px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-primary);
  overflow-x: auto;
}
.ws-subartifact-body pre {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px;
}
/* Mermaid frame — outer container with relative positioning so the zoom toolbar
   stays anchored in the top-right regardless of how far the user pans inside
   the inner scroll wrap. */
.forge-sub-mermaid-frame {
  position: relative;
  max-height: 600px;
}
/* Inner scroll wrap — clips and scrolls when the diagram is zoomed past the
   visible area. Grab cursor signals drag-to-pan; flips to grabbing while a
   pan is active. */
.forge-sub-mermaid-wrap {
  overflow: auto;
  max-height: 600px;
  cursor: grab;
}
.forge-sub-mermaid-wrap.is-panning {
  cursor: grabbing;
  user-select: none;
}
.forge-sub-mermaid {
  display: block;
  text-align: center;
}
/* Floating zoom controls — anchored to the FRAME (not the wrap) so they stay
   fixed in the top-right while the user pans the diagram. Right offset is large
   enough to clear the scrollbar that appears on the wrap when the diagram is
   zoomed past the visible area. Subtle backdrop so the buttons read on light
   or dark mermaid themes. */
.forge-sub-mermaid-zoom {
  position: absolute;
  top: 6px;
  right: 20px;
  display: flex;
  gap: 2px;
  z-index: 2;
  padding: 2px;
  background: rgba(0, 0, 0, 0.35);
  border-radius: 4px;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.forge-sub-mermaid-zoom button {
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-secondary);
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 3px;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0;
  font-family: var(--font-sans, inherit);
  transition: background var(--transition), color var(--transition);
}
.forge-sub-mermaid-zoom button:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}
.forge-sub-mermaid-zoom button:active {
  background: var(--accent-glow);
}
.forge-sub-svg {
  display: block;
}
.forge-sub-svg svg {
  max-width: 100%;
  height: auto;
}
.forge-sub-html {
  width: 100%;
  min-height: 240px;
  border: 0;
  background: #fff;
}

/* Library: indented sub-artifact rows under a parent artifact.
 * Deeper indent + dimmed icon make hierarchy obvious without implying interactivity. */
.ws-library-item-sub {
  padding-left: 32px;
}
.ws-library-item-sub .ws-library-item-name {
  color: var(--text-muted);
}
.ws-library-item-icon.subartifact {
  color: var(--text-muted);
  opacity: 0.6;
}

/* Clickable library items (artifacts + sub-artifacts open the preview modal). */
.ws-library-item-clickable { cursor: pointer; }

/* ── Library preview modal ─────────────────────────────────────
 * Center-stage modal showing a server-rendered artifact (or single sub-artifact)
 * without disturbing the active step's chat + preview. Mermaid runs after content
 * lands so diagram sub-artifacts render the same as the artifact pane. */
.ws-preview-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.ws-preview-modal-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(2px);
}

.ws-preview-modal-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(900px, calc(100vw - 48px));
  /* Fixed height so the dialog reads the same regardless of artifact size —
     short artifacts get extra empty body space, long ones scroll within. */
  height: calc(100vh - 64px);
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}

.ws-preview-modal-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.ws-preview-modal-titles {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.ws-preview-modal-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ws-preview-modal-subtitle {
  font-size: 11px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
}

.ws-preview-modal-close {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  transition: background var(--transition), color var(--transition);
}
.ws-preview-modal-close:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}
.ws-preview-modal-close svg { width: 16px; height: 16px; }

.ws-preview-modal-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px 20px;
}
.ws-preview-modal-body::-webkit-scrollbar       { width: 6px; }
.ws-preview-modal-body::-webkit-scrollbar-track { background: transparent; }
.ws-preview-modal-body::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }

.ws-preview-modal-loading,
.ws-preview-modal-error {
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
  padding: 32px 16px;
}
.ws-preview-modal-error { color: var(--danger, #ef4444); }

/* Streaming state on the chat input box.
   - Hides the send button entirely (no background, no tooltip surface)
   - Hides the textarea placeholder so it doesn't read like "Message Forge…" while
     the user is waiting for a response
   - Shows a 12-tick activity spinner where the send button used to live
   The spinner is a classic Apple-style indicator: 12 small rounded bars arranged
   in a circle, each bar fades from full to faint as it travels round, giving the
   illusion of a leading "head" with a fading tail. Single tone (uses --text-muted),
   no background — appears directly on the dark input box. */
.ws-chat-input-box.is-streaming .ws-send-btn {
  display: none;
}
.ws-chat-input-box.is-streaming textarea::placeholder {
  /* During streaming the JS swaps the placeholder text to a "please wait" message; keep it
     visible (just slightly muted) so the user has a clear cue that something's in flight. */
  color: var(--text-muted);
  font-style: italic;
}

.ws-stream-spinner {
  display: none;
  position: relative;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
}
.ws-chat-input-box.is-streaming .ws-stream-spinner {
  display: block;
}
.ws-stream-spinner > div {
  position: absolute;
  top: 0;
  left: 50%;
  width: 2px;
  height: 6px;
  margin-left: -1px;
  background: var(--text-muted);
  border-radius: 1px;
  transform-origin: 50% 11px;
  animation: ws-stream-tick-fade 1.8s linear infinite;
}
.ws-stream-spinner > div:nth-child(1)  { transform: rotate(0deg);   animation-delay: -1.650s; }
.ws-stream-spinner > div:nth-child(2)  { transform: rotate(30deg);  animation-delay: -1.500s; }
.ws-stream-spinner > div:nth-child(3)  { transform: rotate(60deg);  animation-delay: -1.350s; }
.ws-stream-spinner > div:nth-child(4)  { transform: rotate(90deg);  animation-delay: -1.200s; }
.ws-stream-spinner > div:nth-child(5)  { transform: rotate(120deg); animation-delay: -1.050s; }
.ws-stream-spinner > div:nth-child(6)  { transform: rotate(150deg); animation-delay: -0.900s; }
.ws-stream-spinner > div:nth-child(7)  { transform: rotate(180deg); animation-delay: -0.750s; }
.ws-stream-spinner > div:nth-child(8)  { transform: rotate(210deg); animation-delay: -0.600s; }
.ws-stream-spinner > div:nth-child(9)  { transform: rotate(240deg); animation-delay: -0.450s; }
.ws-stream-spinner > div:nth-child(10) { transform: rotate(270deg); animation-delay: -0.300s; }
.ws-stream-spinner > div:nth-child(11) { transform: rotate(300deg); animation-delay: -0.150s; }
.ws-stream-spinner > div:nth-child(12) { transform: rotate(330deg); animation-delay: 0s; }
@keyframes ws-stream-tick-fade {
  0%   { opacity: 1.00; }
  20%  { opacity: 0.65; }
  40%  { opacity: 0.35; }
  60%  { opacity: 0.20; }
  100% { opacity: 0.10; }
}
@media (prefers-reduced-motion: reduce) {
  .ws-stream-spinner > div { animation: none; opacity: 0.4; }
}

/* ─────────────────────────────────────────────────────────────────────
   Public marketing/auth pages — Contact link in header + Privacy link
   in footer. Quiet, unobtrusive, matches the IDE theme.
   ───────────────────────────────────────────────────────────────────── */
.site-public-link {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  text-decoration: none;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  transition: color var(--transition), background var(--transition);
}
.site-public-link:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

/* Long-form prose pages (Privacy, Contact). Centered, comfortable
   reading width. Section headings tighter than the default cards. */
.prose-page {
  max-width: 760px;
  margin: 0 auto;
  padding: 32px 24px 64px;
}
.prose-page h1 {
  font-size: 28px;
  margin: 0 0 8px;
}
.prose-page h2 {
  font-size: 18px;
  margin: 32px 0 12px;
  color: var(--text-primary);
}
.prose-page p,
.prose-page ul,
.prose-page ol {
  font-size: 14px;
  line-height: 1.65;
  color: var(--text-secondary);
}
.prose-page ul,
.prose-page ol {
  padding-left: 22px;
  margin: 0 0 14px;
}
.prose-page ul li,
.prose-page ol li {
  margin: 4px 0;
}
.prose-page a {
  color: var(--accent-blue);
}
.prose-page a:hover {
  text-decoration: underline;
}
.prose-page .prose-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin-bottom: 24px;
}

.contact-list {
  list-style: none;
  padding: 0;
  margin: 24px 0 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.contact-list li {
  font-size: 15px;
  margin: 0;
}

/* ── Contact page ──────────────────────────────────────────
   Hero uses the same radial-glow + bg-deep pairing as the auth + landing-hero so the page
   feels like part of the same surface family. Cards below are clickable anchors styled to
   match card-forge with hover + arrow-on-right affordance. */
.contact-hero {
  padding: 72px 24px 32px;
  text-align: center;
  background:
    radial-gradient(ellipse at top, var(--accent-glow-strong), transparent 55%),
    var(--bg-deep);
}
.contact-hero-title {
  font-size: 40px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 12px;
  background: linear-gradient(135deg, var(--text-primary), var(--accent-light));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.contact-hero-subtitle {
  font-size: 16px;
  color: var(--text-secondary);
  max-width: 560px;
  margin: 0 auto;
  line-height: 1.6;
}

.contact-cards {
  max-width: 720px;
  margin: 0 auto;
  padding: 32px 24px 16px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.contact-card {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 20px 22px;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  color: var(--text-primary);
  text-decoration: none;
  transition: border-color var(--transition), background var(--transition), transform var(--transition);
}
.contact-card:hover {
  border-color: var(--accent-blue-dim);
  background: var(--bg-elevated);
  text-decoration: none;
  transform: translateY(-1px);
}

.contact-card-icon {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  background: var(--accent-glow);
  color: var(--accent-blue);
}
.contact-card-icon svg { width: 22px; height: 22px; }

.contact-card-body { flex: 1; min-width: 0; }
.contact-card-eyebrow {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.contact-card-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 4px;
  word-break: break-word;
}
.contact-card-desc {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.55;
}

.contact-card-arrow {
  flex-shrink: 0;
  color: var(--text-muted);
  transition: color var(--transition), transform var(--transition);
}
.contact-card-arrow svg { width: 16px; height: 16px; }
.contact-card:hover .contact-card-arrow {
  color: var(--accent-blue);
  transform: translateX(2px);
}

.contact-footer {
  max-width: 720px;
  margin: 0 auto;
  padding: 8px 24px 64px;
  font-size: 13px;
  color: var(--text-muted);
  text-align: center;
  line-height: 1.6;
}

/* ── Phase header action icons (edit / delete) ──────────────────
 * Hover-revealed pencil + trash on each phase row in the workflow rail. Stay flush right
 * inside the existing header layout; appear only when the user hovers the header so the
 * default reading state stays clean. */
.ws-phase-action-btn {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  opacity: 0;
  transition: opacity var(--transition), background var(--transition), color var(--transition);
  margin-left: 4px;
}
.ws-phase-action-btn svg { width: 13px; height: 13px; }
.ws-phase-group-header:hover .ws-phase-action-btn { opacity: 0.85; }
.ws-phase-action-btn:hover {
  opacity: 1;
  background: var(--bg-hover);
  color: var(--text-primary);
}

/* ── Step lock indicator ────────────────────────────────────────
 * Tiny lock glyph beside a step's status dot when the step is currently locked. Keeps the
 * row layout intact — position is between the label and the role badge, sized small enough
 * to read as a status hint rather than a primary control. */
.ws-step-lock {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  margin-left: 6px;
  color: var(--text-muted);
  flex-shrink: 0;
}
.ws-step-lock svg { width: 11px; height: 11px; }
.ws-step-lock.by-self  { color: var(--accent-blue, #3b82f6); }
.ws-step-lock.by-other { color: #f59e0b; }

.ws-step-item.locked-by-other {
  /* Subtle visual cue: locked-by-other rows feel "in-flight" by another user */
  opacity: 0.85;
}

/* ── Rail bottom actions (Add Phase, Generate from Plan) ───────
 * Sit below the phase list in the workflow rail. Stack vertically with consistent spacing.
 * Use the existing .btn-forge.ghost styling so they read as secondary actions. */
.ws-rail-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 12px 16px 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.ws-rail-actions .btn-forge {
  font-size: 12px;
  padding: 8px 12px;
}

/* ── Generic workspace modal (Phase add/edit, confirm, changelog) ──
 * Smaller and lighter than .ws-preview-modal — used for forms and confirmations rather than
 * full artifact previews. Same overlay treatment for consistency, narrower panel, no fixed
 * height (panels size to content within a max).
 *
 * Three structural elements:
 *   .ws-modal-header  — title + close button
 *   .ws-modal-body    — fields, hints, errors
 *   .ws-modal-footer  — primary + secondary action buttons */
.ws-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ws-modal-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(2px);
}
.ws-modal-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(560px, calc(100vw - 48px));
  max-height: calc(100vh - 64px);
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}
.ws-modal-panel-narrow { width: min(420px, calc(100vw - 48px)); }

/* Wide variant — matches the .ws-preview-modal-panel sizing so document-style content
   (activity log, future reports lists) reads at the same width as the report viewer. */
.ws-modal-panel-wide {
  width: min(900px, calc(100vw - 48px));
  height: calc(100vh - 64px);
  max-height: calc(100vh - 64px);
}

.ws-modal-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.ws-modal-title {
  flex: 1;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}
.ws-modal-close {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  transition: background var(--transition), color var(--transition);
}
.ws-modal-close:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}
.ws-modal-close svg { width: 16px; height: 16px; }

.ws-modal-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.ws-modal-body::-webkit-scrollbar       { width: 6px; }
.ws-modal-body::-webkit-scrollbar-track { background: transparent; }
.ws-modal-body::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }

.ws-modal-hint {
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.45;
}

.ws-modal-error {
  font-size: 12px;
  color: var(--danger, #ef4444);
  background: rgba(239, 68, 68, 0.08);
  border: 1px solid rgba(239, 68, 68, 0.3);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
}

/* Activity Log dialog */
.activity-log-header {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px 20px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}
.activity-log-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.activity-log-meta-label {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-muted);
}
.activity-log-meta-value {
  font-size: 12px;
  color: var(--text-primary);
}

.activity-log-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12px;
}
.activity-log-row {
  display: grid;
  grid-template-columns: 130px 110px 1fr;
  gap: 12px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
  align-items: baseline;
}
.activity-log-row:last-child { border-bottom: none; }
.activity-log-row-time {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
}
.activity-log-row-type {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-primary);
}
.activity-log-row-desc {
  color: var(--text-primary);
  line-height: 1.4;
}
.activity-log-row-actor {
  display: block;
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 2px;
}
.activity-log-empty {
  font-size: 12px;
  color: var(--text-muted);
  font-style: italic;
  padding: 12px 0;
}

.ws-modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}

.ws-radio-row {
  display: flex;
  gap: 16px;
}
.ws-radio {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-primary);
  cursor: pointer;
}
.ws-radio input { margin: 0; }

.field-hint {
  font-weight: 400;
  color: var(--text-muted);
  font-size: 11px;
  margin-left: 4px;
}

/* ── Artifact pane "jump to document" dropdown ──────────────────
 * Borderless select that lets the user scroll the preview pane to a specific sub-artifact.
 * Reads as a label with a chevron rather than a form control — sits next to the "Artifact"
 * pill in the pane toolbar. */
.ws-artifact-jump {
  background: transparent;
  border: none;
  color: var(--text-secondary);
  font-size: 12px;
  padding: 4px 22px 4px 8px;
  margin-left: 8px;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2'><path d='M6 9l6 6 6-6'/></svg>");
  background-repeat: no-repeat;
  background-position: right 6px center;
  border-radius: var(--radius-sm);
  transition: background-color var(--transition), color var(--transition);
  max-width: 220px;
  /* Shrink + truncate on narrow panes so the dropdown never pushes other toolbar items
     off-screen. min-width: 0 lets a flex item ignore its intrinsic min-content width. */
  min-width: 0;
  flex-shrink: 1;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
.ws-artifact-jump:hover { background-color: var(--bg-hover); color: var(--text-primary); }
.ws-artifact-jump:focus { outline: none; background-color: var(--bg-hover); color: var(--text-primary); }

/* Popup options match the rail's input-forge select popup (dark elevated bg + primary text)
   so the open dropdown reads consistently across the app. The trigger stays borderless to
   blend with the toolbar — only the popup menu gets the rail-style treatment. */
.ws-artifact-jump option {
  background: var(--bg-elevated);
  color: var(--text-primary);
  padding: 6px 12px;
}

/* ── Chat toolbar breadcrumb (phase → step) ─────────────────────
 * Sits between the "Chat" pill and the spacer so users always know which step they're on
 * without scanning the rail. Phase reads slightly muted; step pops as the primary identifier. */
.ws-toolbar-breadcrumb {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: 12px;
  font-size: 12px;
  color: var(--text-muted);
  min-width: 0;
}
.ws-toolbar-breadcrumb-phase {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  max-width: 220px;
}
.ws-toolbar-breadcrumb-sep {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  opacity: 0.6;
}
.ws-toolbar-breadcrumb-step {
  color: var(--text-primary);
  font-weight: 600;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  max-width: 220px;
}

/* ── Project guidance edit button (left rail) ───────────────────
 * Compact icon-button that lives in the project meta area. Visible only to project admins. */
.ws-rail-edit-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  cursor: pointer;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  font-size: 11px;
  margin-left: 8px;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.ws-rail-edit-btn svg { width: 11px; height: 11px; }
.ws-rail-edit-btn:hover {
  background: var(--bg-hover);
  border-color: var(--text-muted);
  color: var(--text-primary);
}

/* ── Step history list ──────────────────────────────────────────
 * Inside the history modal — vertical list of changelog entries, each card showing
 * the summary plus author + relative time. */
.ws-history-empty {
  text-align: center;
  padding: 24px 12px;
  color: var(--text-muted);
  font-size: 13px;
}
.ws-history-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ws-history-entry {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  background: var(--bg-secondary, var(--bg-primary));
}
.ws-history-entry-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11px;
  color: var(--text-muted);
  margin-bottom: 4px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.ws-history-entry-summary {
  font-size: 13px;
  color: var(--text-primary);
  white-space: pre-wrap;
  line-height: 1.5;
}

/* ── Knowledge document raw embeds ──────────────────────────────
 * Images / PDFs / SVG / HTML render inside the preview modal via <img> or <iframe>.
 * For images we re-use the mermaid zoom frame so users get pan + zoom on big screenshots.
 * For PDFs / SVG / HTML the iframe takes the available height of the modal body. */
.forge-knowledge-raw-body {
  height: calc(100vh - 220px);
  display: flex;
  flex-direction: column;
}
.forge-knowledge-image {
  display: block;
  max-width: 100%;
  max-height: none;
  height: auto;
  margin: 0 auto;
}
.forge-knowledge-iframe {
  flex: 1;
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  min-height: 360px;
}
.forge-knowledge-download {
  display: inline-block;
  padding: 10px 16px;
  margin: 16px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  text-decoration: none;
}
.forge-knowledge-download:hover { background: var(--bg-hover); }

/* ── CSV table ──────────────────────────────────────────────────
 * Server-rendered table for previewing CSV knowledge docs. */
.forge-csv-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  font-family: var(--font-mono);
}
.forge-csv-table th,
.forge-csv-table td {
  border: 1px solid var(--border);
  padding: 6px 10px;
  text-align: left;
  vertical-align: top;
  white-space: nowrap;
}
.forge-csv-table th {
  background: var(--bg-elevated);
  color: var(--text-primary);
  font-weight: 600;
}
.forge-csv-table tbody tr:nth-child(even) td {
  background: var(--bg-secondary, var(--bg-primary));
}

/* ── Policy rule cards ──────────────────────────────────────────
 * Friendly view of a policy's rules — each rule a stacked card with name + instructions
 * and an optional fenced example. Used inside the preview modal for policy library items. */
.forge-policy-rules {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.forge-policy-rule {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  background: var(--bg-secondary, var(--bg-primary));
}
.forge-policy-rule-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 6px;
}
.forge-policy-rule-instructions {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.55;
  white-space: pre-wrap;
}
.forge-policy-rule-example {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--border);
}
.forge-policy-rule-example-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.forge-policy-rule-example pre {
  margin: 0;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  font-size: 12px;
  overflow-x: auto;
}

/* ── Upstream changes group ─────────────────────────────────────
 * Each artifact that has changes gets its own header (artifact name + phase) followed by the
 * stack of new changelog entries beneath it. Visually grouped to make multi-artifact diffs
 * scannable. */
.ws-upstream-group {
  margin-bottom: 16px;
}
.ws-upstream-group:last-child { margin-bottom: 0; }
.ws-upstream-group-header {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 0 0 6px 0;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  color: var(--text-primary);
}
.ws-upstream-group-header strong { font-weight: 600; }
.ws-upstream-phase {
  font-size: 11px;
  color: var(--text-muted);
  font-family: var(--font-mono);
}

/* ── Step knowledge attachments ──────────────────────────
   The "+" button mirrors ws-send-btn but on the left of the chat input. Stays subtle so
   the primary affordance (Send) remains visually dominant. */
.ws-attach-btn {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border);
  cursor: pointer;
  flex-shrink: 0;
  transition: all var(--transition);
}
.ws-attach-btn:hover:not(:disabled) {
  background: var(--bg-elevated);
  color: var(--text-primary);
  border-color: var(--accent-blue-dim);
}
.ws-attach-btn:disabled {
  opacity: 0.4;
}
.ws-attach-btn svg { width: 14px; height: 14px; }

.ws-chat-input-box.is-streaming .ws-attach-btn {
  visibility: hidden;
}

/* Drop highlight — appears when a file is being dragged over the chat input box. */
.ws-chat-input-box.is-drop-target {
  border-color: var(--accent-blue);
  background: var(--bg-elevated);
  outline: 2px dashed var(--accent-blue-dim);
  outline-offset: -4px;
}

/* Inline info-chip used for system events in the chat thread (file attached, file removed).
   Centered, narrow, no avatar — visually distinct from user/assistant turns. */
.ws-msg-info-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 8px auto;
  padding: 4px 12px;
  max-width: 80%;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 11px;
  color: var(--text-secondary);
}
.ws-msg-info-chip-text { line-height: 1.4; }
.ws-msg-info-chip-text strong { color: var(--text-primary); font-weight: 600; }
.ws-msg-info-chip-text p { margin: 0; display: inline; }
.ws-msg-info-chip-time {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
}

/* Right-pane × button on a step-knowledge chip. Hidden by default; reveals on hover of
   the row so the chip stays clean when not interacting. */
.ws-library-item-remove {
  width: 18px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  opacity: 0;
  transition: all var(--transition);
}
.ws-library-item:hover .ws-library-item-remove { opacity: 1; }
.ws-library-item-remove:hover {
  background: var(--bg-hover);
  color: var(--danger, #f87171);
}
.ws-library-item-remove svg { width: 12px; height: 12px; }

/* ── Blueprint empty state (artifact pane, pre-draft) ────
   Shown when the step's artifact body still equals the workflow template — the user hasn't
   iterated yet. Mirrors the landing-hero gradient (radial accent glow over bg-deep) plus a
   dotted grid overlay so the pane reads as "ready to draft" rather than blank. The card is
   centered and minimal — the empty state is signal, not noise. */
.ws-blueprint-empty {
  flex: 1;
  min-height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 24px;
  background:
    radial-gradient(ellipse at top, var(--accent-glow-strong), transparent 55%),
    /* Dotted grid — subtle bluish dots on a 22px lattice. Goes UNDER the radial glow so the
       grid fades into the brighter top while staying crisp toward the bottom. */
    radial-gradient(circle, rgba(120, 160, 220, 0.12) 1px, transparent 1.4px),
    var(--bg-deep);
  background-size: auto, 22px 22px, auto;
  background-position: center top, 0 0, 0 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  /* Clip the gradient to the rounded corners so the dotted grid doesn't square off the edges. */
  overflow: hidden;
}

.ws-blueprint-empty-inner {
  text-align: center;
  max-width: 380px;
  padding: 24px;
}

.ws-blueprint-empty-icon {
  width: 56px;
  height: 56px;
  margin-bottom: 16px;
  color: var(--accent-light);
  opacity: 0.85;
}

.ws-blueprint-empty-title {
  font-size: 18px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.01em;
  margin-bottom: 6px;
}

.ws-blueprint-empty-text {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.5;
  margin: 0;
}

/* ──────────────────────────────────────────────────────────────────────────
   CENTER TAB SCENES (Workflow / Facilitator / Instructor)
   Each scene owns a full chat-pane + artifact-pane pair; the bottom tab strip
   spans the full center width below all three. Visual-Studio-style: tab strip
   anchored to the bottom, panels above.
   ────────────────────────────────────────────────────────────────────────── */

/* ws-center is already flex column; the scenes fill the space above the tabs. */
.ws-tab-scene {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Hidden scene retains its layout state (chat scroll, divider position) so the
   user returns to it exactly where they left off. */
.ws-tab-scene.u-hidden {
  display: none;
}

.ws-chat-tabs {
  flex: 0 0 auto;
  display: flex;
  gap: 0;
  border-top: 1px solid var(--border);
  background: var(--bg-primary);
  padding: 0 12px;
}

.ws-chat-tab {
  background: transparent;
  border: none;
  border-top: 2px solid transparent;
  /* Use --text-secondary (medium gray-blue) for inactive tabs rather than --text-muted
     (dark gray-blue) — the latter reads as "disabled" and made users hesitate to click
     vibe / facilitator / instructor. Inactive tabs are always available; the active-state
     contrast still comes through via --text-primary + accent-blue underline. */
  color: var(--text-secondary);
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  padding: 8px 14px;
  cursor: pointer;
  transition: color var(--transition), border-color var(--transition);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.ws-chat-tab svg {
  width: 14px;
  height: 14px;
}

.ws-chat-tab:hover { color: var(--text-primary); }
.ws-chat-tab.active {
  color: var(--text-primary);
  border-top-color: var(--accent-blue);
}

/* ──────────────────────────────────────────────────────────────────────────
   FACILITATOR + INSTRUCTOR PANELS
   Three states swapped via .u-hidden: loading / catalog / chat.
   The chat state reuses .ws-chat-messages + .ws-chat-input-area so message
   bubbles + send box look identical to the workflow chat.
   ────────────────────────────────────────────────────────────────────────── */
.ws-session-loading {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 24px;
  color: var(--text-muted);
  font-size: 13px;
}

.ws-session-catalog {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 20px 24px 24px;
}

.ws-session-catalog-header {
  margin-bottom: 18px;
}

.ws-session-catalog-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 4px;
}

.ws-session-catalog-hint {
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.5;
  max-width: 60ch;
}

.ws-session-catalog-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.ws-session-category {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.ws-session-category-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 0 2px;
}

.ws-session-type-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 12px;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
  text-align: left;
}

.ws-session-type-card:hover {
  background: var(--bg-hover);
  border-color: var(--accent-blue);
}

.ws-session-type-card-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
}

.ws-session-type-card-desc {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.45;
}

/* Active session — chat thread + input fill the panel below the toolbar. */
.ws-session-chat {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.ws-session-chat .ws-chat-messages {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

/* Reference chip strip — sits between the facilitator chat pane toolbar and the
   content area, listing prior session reports the user attached as AI context.
   Each chip shows the type name + remove (×) button. Hidden when no refs attached. */
.ws-session-refs {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-secondary);
}

.ws-session-ref-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px 4px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 11px;
  color: var(--text-secondary);
}

.ws-session-ref-chip-name {
  font-weight: 500;
  color: var(--text-primary);
}

.ws-session-ref-chip-meta {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 10px;
}

.ws-session-ref-chip-remove {
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--text-muted);
  border-radius: 50%;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.ws-session-ref-chip-remove:hover {
  background: var(--bg-hover);
  color: var(--danger, #ef4444);
}
.ws-session-ref-chip-remove svg { width: 11px; height: 11px; }

/* Empty-list placeholder used when ListMine returns 0 sessions on the My
   Instructor Sessions page. Kept tonally similar to .ws-empty-inner so the
   page reads like the rest of the app. */
.ws-session-empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-muted);
  font-size: 13px;
}

/* ──────────────────────────────────────────────────────────────────────────
   FACILITATOR SESSIONS MODAL (Projects tab) + INSTRUCTOR SESSIONS PAGE
   Both reuse the existing .ws-modal shell or main page shell — these styles
   cover only the session-specific table/list shape.
   ────────────────────────────────────────────────────────────────────────── */
.ws-session-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.ws-session-list-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.ws-session-list-row-main {
  flex: 1;
  min-width: 0;
}

.ws-session-list-row-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
}

.ws-session-list-row-meta {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 2px;
}

.ws-session-list-row-actions {
  display: flex;
  gap: 6px;
}

.ws-session-report-card {
  margin-top: 16px;
  padding: 16px 18px;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  max-height: 60vh;
  overflow-y: auto;
}

.ws-session-report-card .forge-md {
  font-size: 13px;
  line-height: 1.6;
}

/* Picker bar inside the facilitator preview modal — sits between header and the
   scrolling report body. Holds only the session-select dropdown; action buttons
   live inside the artifact-card toolbar in the body so this matches the workspace
   library's report viewer 1:1. */
.fac-picker-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-primary);
  flex-shrink: 0;
}

.fac-picker-bar .input-forge {
  flex: 1;
  max-width: 480px;
}

/* ─── Repos page ──────────────────────────────────────────────────────────
   Org-scoped Repos tab. Three-column shell built on top of the workspace's
   ws-rail-* classes so the rails inherit the same dark/blue theme. Design
   tokens (--bg-primary, --bg-surface, --accent-blue, etc.) are sourced from
   :root in the design-system block at the top of this file. */

.repos-page {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  background: var(--bg-deep);
  color: var(--text-primary);
}

/* No-install empty state ─────────────────────────────── */
.repos-no-install {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.repos-no-install-inner {
  text-align: center;
  max-width: 480px;
  padding: 32px;
  color: var(--text-secondary);
}
.repos-no-install-inner svg {
  width: 48px;
  height: 48px;
  color: var(--accent-blue);
  opacity: 0.7;
  margin-bottom: 16px;
}
.repos-no-install-inner h2 {
  margin: 0 0 12px;
  font-size: 1.25rem;
  color: var(--text-primary);
}
.repos-no-install-inner p {
  margin: 0 0 24px;
  line-height: 1.5;
}

/* Three-column shell — uses flex (NOT grid) to mirror the workspace's .ws-layout. With grid,
   collapsing a rail to 28px would leave the original 260px column slot empty since grid columns
   don't redistribute on element width changes; flex with the center pane on `flex: 1` absorbs
   reclaimed space automatically. position: relative is required so the absolute-positioned
   .ws-rail-tabs reopen docks anchor to this shell rather than the page. */
.repos-shell {
  display: flex;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  position: relative;
}

/* Repos-specific overrides on top of .ws-rail. The workspace's .ws-rail is 260px by default
   and 28px when .collapsed — both rails on this page inherit those widths verbatim. We only
   tweak content padding here so list items get a bit more horizontal breathing room. */
.repos-rail .ws-rail-content { padding: 6px; }

/* Cluster the rail-header buttons (refresh + collapse) on the right edge. The base
   .ws-rail-header uses justify-content: space-between and assumes two children (title +
   collapse); wrapping our two buttons in this container preserves that layout. */
.repos-rail-header-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}

/* Right rail uses border-left from .ws-rail-right (already in workspace CSS); both rails are
   flex-shrink: 0 via .ws-rail. Nothing to add. */

/* Left rail: repo picker rows ─────────────────────────── */
.repos-rail-list { display: flex; flex-direction: column; gap: 2px; }
.repos-rail-loading,
.repos-rail-empty,
.repos-rail-error {
  padding: 16px 12px;
  color: var(--text-muted);
  font-size: 12px;
  text-align: center;
}
.repos-rail-error { color: var(--danger); }

.repos-rail-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  padding: 8px 10px;
  cursor: pointer;
  color: var(--text-primary);
  transition: all var(--transition);
  font-family: var(--font-sans);
}
.repos-rail-item:hover {
  background: var(--bg-hover);
}
.repos-rail-item.active {
  background: var(--accent-glow);
  border-color: var(--accent-blue-dim);
}
.repos-rail-item-name {
  font-size: 13px;
  font-weight: 600;
  word-break: break-word;
}
.repos-rail-item-owner {
  font-size: 11px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  margin-top: 2px;
}
.repos-rail-item-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 6px;
}
.repos-rail-chip {
  display: inline-block;
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  font-size: 10px;
  font-family: var(--font-mono);
  background: var(--bg-elevated);
  color: var(--text-secondary);
}
.repos-rail-chip.index {
  background: var(--success-dim);
  color: var(--success);
}
.repos-rail-chip.running {
  background: var(--warning-dim);
  color: var(--warning);
}

/* Center main pane — flex: 1 makes it absorb whatever width the rails leave behind,
   so collapsing either side automatically widens this pane. min-width: 0 lets it shrink
   below content width when both rails are open on a small viewport. */
.repos-main {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  min-height: 0;
  background: var(--bg-deep);
  overflow: hidden;
}
.repos-view {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 24px;
}
.repos-view-empty {
  align-items: center;
  justify-content: center;
}

/* Run view goes edge-to-edge — the padding that gives the picker / actions / recovery views
   their breathing room would create a thick frame around the chat + artifact panes that the
   workspace doesn't have, so we strip it here. */
.repos-view-run {
  padding: 0;
}
.repos-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  color: var(--text-muted);
  text-align: center;
  font-size: 14px;
}
.repos-empty-state svg {
  width: 48px;
  height: 48px;
  opacity: 0.5;
}

/* Actions view ─────────────────────────────────────────── */
.repos-actions-header { margin-bottom: 24px; }
.repos-actions-title {
  margin: 0 0 4px;
  font-size: 1.4rem;
  color: var(--text-primary);
  font-family: var(--font-sans);
}
.repos-actions-meta {
  color: var(--text-secondary);
  font-size: 13px;
  font-family: var(--font-mono);
}
.repos-actions-meta strong { color: var(--text-primary); font-weight: 500; }

.repos-actions-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
}
.repos-action-card {
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px;
  gap: 12px;
}
.repos-action-icon {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  background: var(--accent-glow);
  color: var(--accent-blue);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.repos-action-icon svg { width: 18px; height: 18px; }
.repos-action-body h3 {
  margin: 0 0 4px;
  font-size: 1.05rem;
  color: var(--text-primary);
}
.repos-action-body p {
  margin: 0;
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.5;
}
.repos-action-disabled-note {
  margin-top: 6px;
  font-size: 12px;
  color: var(--warning);
}
.repos-action-controls {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Running view — chat pane (left) + artifact pane (right) split. The two children are
   .ws-chat-pane / .ws-preview-pane so they pick up the workspace's pane styling for free
   (toolbar height, background, scrollbars, divider). The shell flexes so the divider sits
   between them like the workspace's pane-divider does. */
.repos-run-shell {
  flex: 1;
  display: flex;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}

/* The chat pane on the Repos surface stacks toolbar + working-pill + events. The events
   wrap fills the remaining height so the .ws-build-events list grows to fill the pane
   instead of being capped at the workspace's 280px max-height (which is sized for the
   build step where the plan-step list shares the column). No padding on the wrap itself
   — .ws-build-events already has interior padding, so doubling it just made the event
   text feel cramped against a thick frame. */
.repos-run-events-wrap {
  flex: 1;
  min-height: 0;
  display: flex;
  padding: 0;
  overflow: hidden;
}
.repos-run-events-wrap > .ws-build-events {
  flex: 1;
  min-height: 0;
  max-height: none;        /* override workspace's 280px cap — we want full pane height */
  border: none;            /* the chat pane border-bottom on the toolbar is the visual frame */
  border-radius: 0;
}

/* The "Forge is working…" pill sits between the toolbar and the events log. Equal margin on
   all four sides — the bottom gap is what separates the pill from the streaming chat below. */
.repos-run-chat-pane > .ws-build-running {
  margin: 12px;
}

/* No per-sender accent on event lines — the build chat uses uniform .ws-build-event-line
   styling and lets the leading glyph (· system, 💬 assistant, 🔧 tool, ↩ result, ⚠ error,
   ✗ failure) tell the user what kind of event it is. Adding colours would just add noise. */

/* Index runs render their JSON inventory in a code block inside the artifact body. */
.repos-run-index-pre {
  background: var(--bg-elevated);
  padding: 12px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-subtle);
  font-family: var(--font-mono);
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
  color: var(--text-primary);
}

/* The right rail reuses the workspace's .ws-library-tabs / .ws-library-tab / .ws-library-item
   /.ws-library-item-icon / .ws-library-item-name classes directly so the rail reads identically
   to the workspace library. The compact-row pattern (icon + name only, metadata in the modal)
   is the workspace's house style. The repos-library-row class is just a hook for the click
   handler — no extra styling needed beyond what .ws-library-item already provides.

   In-progress runs get a subtle dimming so the user can tell they haven't finished yet, and
   the .ws-library-item-badge fills in the "running" hint without resorting to a coloured pill. */
.repos-library-row.is-running { opacity: 0.65; }

/* Library viewer modal — body is built dynamically into a .ws-artifact-card shell so the
   styling cascades from the workspace's existing artifact-preview rules (.ws-artifact-card,
   .ws-artifact-card-header, .ws-artifact-toolbar, .ws-artifact-body). No Repos-specific
   modal CSS needed beyond the small error message used in the promote/confluence sub-modals. */
.repos-modal-error {
  color: var(--danger);
  margin-top: 8px;
  font-size: 13px;
}

/* Version-history list — used inside the history sub-dialog. Each row is a click target that
   opens that version in the preview modal. Same compact-row rhythm as the workspace's history
   dialog: when on the left, who/badges on the right. */
.repos-history-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 360px;
  overflow-y: auto;
}
.repos-history-list::-webkit-scrollbar { width: 4px; }
.repos-history-list::-webkit-scrollbar-track { background: transparent; }
.repos-history-list::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

.repos-history-row {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) max-content;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  text-align: left;
  color: var(--text-primary);
  font-family: var(--font-sans);
  transition: all var(--transition);
}
.repos-history-row:hover {
  background: var(--bg-hover);
  border-color: var(--accent-blue-dim);
}
.repos-history-row-when {
  font-size: 12px;
  font-family: var(--font-mono);
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.repos-history-row-who {
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.repos-history-row-who strong { color: var(--text-secondary); font-weight: 500; }
.repos-history-row-badges {
  display: flex;
  gap: 4px;
}

/* Locked action cards: applied to the Document and Review cards while the repo has no
   completed Index. Greys out the card visually and prevents pointer events on the controls
   so even if a stray click reaches a select or button, nothing changes. */
.repos-action-card.locked {
  opacity: 0.55;
  background: var(--bg-elevated);
}
.repos-action-card.locked .repos-action-controls {
  pointer-events: none;
}

/* Recovery card — replaces the action grid when the selected repo has an in-progress run.
   Warning-tinted accent so the user spots it instantly and reaches for View / Abort rather
   than wondering why the action buttons are disabled. */
.repos-recovery-card {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  background: var(--bg-surface);
  border: 1px solid var(--warning);
  border-radius: var(--radius-lg);
  padding: 20px;
  max-width: 720px;
}
.repos-recovery-icon {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  background: var(--warning-dim);
  color: var(--warning);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.repos-recovery-icon svg { width: 18px; height: 18px; }
.repos-recovery-body { flex: 1; min-width: 0; }
.repos-recovery-body h3 {
  margin: 0 0 6px;
  font-size: 1.05rem;
  color: var(--text-primary);
}
.repos-recovery-body p {
  margin: 0;
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.5;
}
.repos-recovery-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex-shrink: 0;
}

/* Disabled state for the global Forge controls — these were missing visual cues before,
   so disabled buttons looked identical to enabled ones. Scoped to :disabled (and the
   [disabled] attribute) so it applies anywhere across the app, not just the Repos page.
   Cursor stays as the default arrow (matches the disabled-tab pattern noted in the
   ws-build-tab block) — the `not-allowed` icon is intentionally avoided. */
.btn-forge:disabled,
.btn-forge[disabled] {
  opacity: 0.5;
  background: var(--bg-elevated);
  color: var(--text-muted);
}
.btn-forge:disabled:hover,
.btn-forge[disabled]:hover {
  background: var(--bg-elevated);
  border-color: var(--border);
  color: var(--text-muted);
}
.input-forge:disabled,
.input-forge[disabled] {
  opacity: 0.6;
}

/* ─── Static rails (Org/Teams/Projects/Repos) ─────────────────────────────
   Same width and chrome as the workspace's .ws-rail, but no collapse button
   and no rotated reopen-tab dock. Layered on top of .ws-rail so the
   background, border, header strip, and scrollbars all track the workspace
   rails automatically — only collapse-related styles get neutralized. */
.ws-rail-static.collapsed { width: 260px; }
.ws-rail-static.collapsed > * { display: flex; }

/* ─── Section-bookmark rail (right side of Org/Teams/Projects) ─────────────
   List of in-page anchor links the user clicks to jump to a config-card.
   Same monospace mood as ws-library-tab; active state mirrors the
   .ws-library-tab.active accent rule used elsewhere. */
.bookmarks-list {
  display: flex;
  flex-direction: column;
  padding: 4px 0;
}

.bookmark-link {
  position: relative;
  display: flex;
  align-items: center;
  padding: 8px 16px;
  font-size: 12px;
  color: var(--text-secondary);
  text-decoration: none;
  border-left: 2px solid transparent;
  transition: all var(--transition);
  cursor: pointer;
  user-select: none;
}

.bookmark-link:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.bookmark-link.active {
  color: var(--accent-blue);
  border-left-color: var(--accent-blue);
  background: var(--accent-glow);
}

/* Anchor targets inside .full-page-left-content sit under the 36px pane
   toolbar; offset their scroll target so the title isn't hidden by it when
   a bookmark click scrolls them into view. */
.full-page-left-content .config-card[id] {
  scroll-margin-top: 12px;
}

/* ─── Vibe pane (chat-only, ephemeral session) ────────────────────────────
   Layered on top of .ws-chat-pane so the toolbar / event-log / composer
   chrome inherits from the workspace's pane vocabulary. Only the view-swap
   layout and the start-card styling are local. */
.vibe-pane {
  /* Without min-height: 0 the chat-pane sizes itself to its content (events
     log + input), pushing the input below the visible area as the log grows.
     min-height: 0 lets the column-flex chain shrink children and gives the
     events log a real "fill remaining space + scroll" behaviour. */
  min-height: 0;
}

.vibe-pane .vibe-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.vibe-view {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.vibe-view-start {
  align-items: center;
  justify-content: center;
  padding: 32px 24px;
  overflow-y: auto;
}

.vibe-start-card {
  width: 100%;
  max-width: 540px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
  color: var(--text-secondary);
}

.vibe-start-card svg {
  width: 40px;
  height: 40px;
  color: var(--accent-blue);
  opacity: 0.85;
}

.vibe-start-card h3 {
  margin: 4px 0 0;
  font-size: 16px;
  color: var(--text-primary);
}

.vibe-start-card p {
  margin: 0;
  line-height: 1.5;
}

.vibe-start-form {
  width: 100%;
  text-align: left;
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.vibe-start-empty {
  width: 100%;
  text-align: left;
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.vibe-events-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  /* Bottom padding gives breathing room between the events log and the chat input
     box below — without it the bordered events frame and input frame sit hard
     against each other and read as one cluttered shape. */
  padding: 12px 16px;
}

.vibe-events-wrap > .ws-build-events {
  /* Override the workspace's max-height on .ws-build-events — Vibe is the only thing
     in the chat view, so it gets all the available vertical space. min-height: 0 plus
     flex: 1 1 0 means the events log shrinks/grows with the available column space and
     scrolls internally rather than pushing the input box below the visible area. */
  flex: 1 1 0;
  min-height: 0;
  max-height: none;
  overflow-y: auto;
}

/* User messages get a slight accent so they stand out against assistant + tool lines. */
.vibe-events .ws-build-event-line.vibe-event-user {
  color: var(--text-primary);
  font-weight: 500;
}

/* ─── Vibe attach button + 3-way popover menu ─────────────────────────────
   The + button sits left of the textarea (mirrors workflow's .ws-attach-btn).
   Clicking it pops a small menu with Upload / Project knowledge / Repo review.
   Anchored to the wrap (position: relative) so positioning stays correct
   regardless of where the input box sits in the page. */
.vibe-attach {
  position: relative;
  display: flex;
  align-items: flex-end;
  flex-shrink: 0;
}

.vibe-attach-menu {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  min-width: 180px;
  padding: 4px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.vibe-attach-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: 12px;
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
  font-family: var(--font-sans);
}

.vibe-attach-menu-item:hover { background: var(--bg-hover); }

.vibe-attach-menu-item svg {
  width: 13px;
  height: 13px;
  color: var(--text-secondary);
  flex-shrink: 0;
}

/* ─── Vibe review checklist panel ─────────────────────────────────────────
   Inline panel that appears above the input box when the user selects a repo
   review. The user picks findings to address; clicking Apply dispatches a
   synthesized user message and collapses the panel back to a chip. */
.vibe-review-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 10px;
  padding: 12px 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent-blue);
  border-radius: var(--radius-md);
  max-height: 360px;
  overflow: hidden;
}

.vibe-review-panel-header {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.vibe-review-panel-title {
  flex: 1;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-primary);
}

.vibe-review-panel-close {
  background: transparent;
  border: none;
  color: var(--text-muted);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}
.vibe-review-panel-close:hover { color: var(--text-primary); }

.vibe-review-panel-list {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 0;
}

.vibe-review-finding {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  cursor: pointer;
  transition: border-color var(--transition);
}

.vibe-review-finding:hover { border-color: var(--accent-blue-dim); }

.vibe-review-finding.is-non-actionable {
  opacity: 0.55;
  cursor: default;
}

.vibe-review-finding-checkbox {
  margin-top: 2px;
  cursor: pointer;
}

.vibe-review-finding.is-non-actionable .vibe-review-finding-checkbox {
  pointer-events: none;
}

.vibe-review-finding-body {
  flex: 1;
  min-width: 0;
}

.vibe-review-finding-titlerow {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.vibe-review-finding-title {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.vibe-review-severity-pill {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  padding: 1px 5px;
  border-radius: 3px;
  flex-shrink: 0;
}
.vibe-review-severity-pill.critical,
.vibe-review-severity-pill.high   { background: var(--danger-dim);  color: var(--danger); }
.vibe-review-severity-pill.medium { background: var(--warning-dim); color: var(--warning); }
.vibe-review-severity-pill.low    { background: var(--accent-glow); color: var(--accent-light); }
.vibe-review-severity-pill.info   { background: var(--bg-hover);    color: var(--text-secondary); }

.vibe-review-finding-meta {
  font-size: 11px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.vibe-review-finding-summary {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: 4px;
  line-height: 1.45;
}

.vibe-review-sent-tag {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--success);
  margin-left: 4px;
}

.vibe-review-panel-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  padding-top: 4px;
  border-top: 1px solid var(--border);
}

.vibe-review-panel-summary {
  flex: 1;
  font-size: 11px;
  color: var(--text-muted);
  font-family: var(--font-mono);
}

/* Loading + error states for the review panel — extraction is a 10–20s call so
   we need clear feedback during the wait, and a visible "try again" path on
   failure. */
.vibe-review-panel-loading {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 4px;
  color: var(--text-secondary);
  font-size: 12px;
}

.vibe-review-panel-loading .ws-stream-spinner {
  position: relative;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.vibe-review-panel-loading-text {
  flex: 1;
}

.vibe-review-panel-error-block {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  background: var(--danger-dim);
  border: 1px solid rgba(248, 113, 113, 0.3);
  border-radius: var(--radius-sm);
}

.vibe-review-panel-error-text {
  font-size: 12px;
  color: var(--danger);
  line-height: 1.45;
}

/* Review chips look the same as attachment chips but click-to-toggle the panel
   instead of doing nothing. The × button still removes the selection from the
   session. */
.vibe-attachment-chip.is-review { cursor: pointer; }
.vibe-attachment-chip.is-review:hover { border-color: var(--accent-blue-dim); }

/* ─── Vibe attachment chips ───────────────────────────────────────────────
   Strip above the input box. Empty by default; chips render here as the
   user attaches files. Chips show a small icon for the source (upload /
   knowledge doc / review report) so the user remembers what they pulled in. */
.vibe-attachment-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 0 8px;
}

.vibe-attachment-strip:empty { display: none; }

.vibe-attachment-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  font-size: 11px;
  font-family: var(--font-mono);
  color: var(--text-secondary);
  max-width: 280px;
}

.vibe-attachment-chip svg {
  width: 11px;
  height: 11px;
  color: var(--text-muted);
  flex-shrink: 0;
}

.vibe-attachment-chip-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.vibe-attachment-chip-remove {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0 2px;
  font-size: 14px;
  line-height: 1;
}

.vibe-attachment-chip-remove:hover { color: var(--danger); }

/* ─── Vibe picker modal rows (knowledge + review picker share this) ────────
   List of clickable rows; each row attaches the corresponding source on click.
   Mirrors the .group-tree-item / .repo-list visual feel without inheriting
   their nav-specific behaviour. */
.vibe-picker-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 360px;
  overflow-y: auto;
}

.vibe-picker-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
  text-align: left;
  width: 100%;
  color: inherit;
}

.vibe-picker-row:hover {
  background: var(--bg-hover);
  border-color: var(--accent-blue-dim);
}

.vibe-picker-row:disabled,
.vibe-picker-row.is-attached {
  opacity: 0.5;
  cursor: default;
  pointer-events: none;
}

.vibe-picker-row svg {
  width: 14px;
  height: 14px;
  color: var(--text-secondary);
  flex-shrink: 0;
}

.vibe-picker-row-text {
  flex: 1;
  min-width: 0;
}

.vibe-picker-row-title {
  font-size: 13px;
  color: var(--text-primary);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.vibe-picker-row-meta {
  font-size: 11px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  margin-top: 2px;
}

.vibe-picker-empty {
  padding: 24px 12px;
  text-align: center;
  color: var(--text-muted);
  font-size: 12px;
}

/* ─── Vibe assistant message blocks ───────────────────────────────────────
   Match the workflow chat's prose treatment so Vibe reads as the same kind of
   chat the user already knows. The body inherits .ws-msg-text styling (13px,
   1.6 line-height, --text-secondary), and the small "Forge" sender label
   mirrors .ws-msg-sender so the visual rhythm of label-then-prose feels the
   same as the rest of the workspace's chat surfaces. */
.vibe-events .vibe-msg-assistant {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 12px 0;
}

.vibe-events .vibe-msg-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-primary);
}

/* Input area is a fixed-size sibling — never shrink it, even when the events log is
   taller than it can render. Without flex-shrink: 0 the column flex would happily
   squash the textarea + send button down to nothing under heavy events output. */
.vibe-input-area {
  flex-shrink: 0;
}

/* Working banner — sit it inset from the panel edges so it reads as a callout rather
   than spanning the whole pane width. Mirrors the visual weight of similar callouts
   on the workspace build pane, with slightly less bottom padding to keep the chat
   start text close to its banner. */
.vibe-pane .ws-build-running {
  margin: 12px 12px 8px;
}

