/* Single CSS entry for login.html — same reasoning as entry-main.css's header comment.
   Matches login.html's original two <link> tags, same order. */
/* Business OS — base tokens + theme overrides (Prompt 24.8's CSS split of style.css).
   MUST load first — every other sheet inherits the --ds-* tokens from :root/[data-theme].
   No @media (prefers-color-scheme) here by design — theme.js resolves 'system' to a
   concrete data-theme value itself; this stays the one mechanism deciding colors. Also
   carries the page-wide reset (box-sizing, [hidden], body, .layout) since those depend on
   the tokens defined immediately above them. */

* { box-sizing: border-box; }
:root {
  --surface-hover: #242938;
  --border-strong: #3a3f52;
  --danger-bg: #3a1e22;
  --danger-text: #ff9a9a;

  /* ---- Design System tokens (Business OS — Design System + Environment Intelligence
     Redesign, V1). Forward-only: only new components (below) and Environment's rebuild
     consume these — the rest of the app's ~400 existing hardcoded hex occurrences are
     deliberately NOT retrofitted onto this scale (see docs/BUSINESS_OS.md's Design System
     section for the scoping rationale). See /styleguide for a live token+component
     showcase. ---- */

  /* Background layers */
  --ds-bg-page: #0f1115;
  --ds-bg-card: #171a21;
  --ds-bg-inset: #1d212b;
  --ds-border: #262b36;
  --ds-border-strong: #343b4a;

  /* Sidebar shell (.primary-nav and friends — Commit 5, dark/light/system theme).
     No existing --ds-* background/border token was a close semantic match for the
     sidebar's own slightly-lighter-than-page chrome, so these are new rather than a
     forced reuse of --ds-bg-card/--ds-border. */
  --ds-nav-bg: #14161c;
  --ds-nav-border: #23262f;
  --ds-nav-active-bg: #23283a;

  /* Text */
  --ds-text-primary: #e8e8ec;
  --ds-text-secondary: #aab0c0;
  --ds-text-muted: #6b7180;

  /* Driving-force accents (PESTTG) */
  --ds-force-political: #ef4444;
  --ds-force-economic: #22c55e;
  --ds-force-societal: #f0b429;
  --ds-force-technological: #3b82f6;
  --ds-force-mega_trends: #a855f7;
  --ds-force-globalisation: #14b8a6;

  /* Idea scope accents (Ideas Hub Redesign — Intrapreneurship V1) — org_wide/new_venture
     plus the 8 lib/businessOrgSlots.ts FUNCTION_SLOTS keys, same "one accent per enum
     value" shape as --ds-force-* above. */
  --ds-scope-org_wide: #6b7280;
  --ds-scope-new_venture: #ec4899;
  --ds-scope-supply_chain: #f0b429;
  --ds-scope-operations: #3b82f6;
  --ds-scope-marketing_sales: #22c55e;
  --ds-scope-service_warranty: #14b8a6;
  --ds-scope-infrastructure: #a855f7;
  --ds-scope-human_resources: #ef4444;
  --ds-scope-technology: #06b6d4;
  --ds-scope-procurement: #f97316;

  /* Semantic */
  --ds-success-bg: #14301f;
  --ds-success-text: #4ade80;
  --ds-warning-bg: #3a2e12;
  --ds-warning-text: #f0b429;
  --ds-danger-bg: #3a1e22;
  --ds-danger-text: #ff9a9a;
  --ds-info-bg: #14243a;
  --ds-info-text: #60a5fa;
  --ds-neutral-bg: #262b36;
  --ds-neutral-text: #aab0c0;

  /* Impact scale (low -> very_high) */
  --ds-impact-low: #6b7180;
  --ds-impact-medium: #60a5fa;
  --ds-impact-high: #f0b429;
  --ds-impact-very_high: #ef4444;

  /* Spacing scale */
  --ds-space-1: 4px;
  --ds-space-2: 8px;
  --ds-space-3: 12px;
  --ds-space-4: 16px;
  --ds-space-5: 24px;
  --ds-space-6: 32px;

  /* Radius scale */
  --ds-radius-sm: 6px;
  --ds-radius-md: 10px;
  --ds-radius-lg: 14px;

  /* Type scale */
  --ds-font-xs: 11px;
  --ds-font-sm: 12px;
  --ds-font-md: 13px;
  --ds-font-lg: 16px;
  --ds-font-xl: 22px;

  /* Z-index scale (P0-A — Z-Index Scale Consolidation). One ordered scale for the whole
     app shell's stacking, replacing scattered literals (including several max-int hacks
     that lived in the preview-iframe VE overlay scripts — see public/veZIndex.js, a
     separate parallel scale since that iframe document never loads this stylesheet).
     Each tier below lists every current consumer so the next addition has an obvious
     home; --ds-z-messages is a deliberate reserved gap for the upcoming shell messages
     overlay (must sit above all module chrome/popovers/drawers/modals, below toasts). */
  --ds-z-inline-suggest: 10;  /* .ds-mention-autocomplete, .ds-reference-search */
  --ds-z-float-control: 20;   /* .ds-info-tip::after, .ve-toolbar, .global-footer-bar, .docs-search-results */
  --ds-z-tooltip: 30;         /* [data-tip]:hover::after, #pesttgOverflowMenu */
  --ds-z-mobile-toggle: 50;   /* .ds-messages-rail-toggle (mobile) */
  --ds-z-modal-lite: 100;     /* .ds-messages-rail (mobile), .attachment-lightbox */
  --ds-z-menu: 200;           /* .ds-board-menu-popover, .ds-reaction-picker-popover */
  --ds-z-popover: 500;        /* .new-project-popover, .notifications-popover */
  --ds-z-drawer: 600;         /* .drawer-backdrop, .ds-search-modal-backdrop */
  --ds-z-drawer-top: 601;     /* .drawer-panel */
  --ds-z-modal: 700;          /* .ds-lightbox-backdrop */
  --ds-z-messages: 1000;      /* #messagesOverlayRoot — see public/messagesOverlay.js (P0-B) */
  --ds-z-toast: 2000;         /* .feedback-toast */
}

/* ---- Light theme (Business OS — Notifications Bell + Settings, V1, Commit 5). ----
   Overrides every color token declared in :root above for document.documentElement
   ([data-theme="light"] on <html>, set by public/theme.js / index.html's inline
   flash-of-wrong-theme guard — see theme.js's header comment). Purely attribute-driven:
   no `@media (prefers-color-scheme)` anywhere in this file — theme.js resolves 'system'
   to a concrete 'dark'/'light' data-theme value itself via matchMedia, so there is exactly
   one mechanism deciding colors.

   Scope of the retrofit that makes this override actually work app-wide, beyond the
   token layer itself: body{} (below) and the .primary-nav sidebar shell (further down —
   search ".primary-nav {") now read these tokens instead of hardcoded hex, since the
   sidebar wraps every page including /styleguide and /settings. Everything inside
   #bizosMain's per-module CSS (~400 pre-existing hardcoded hex values, out of scope for
   this commit) is NOT retrofitted and stays dark-only when data-theme="light" — logged
   page-by-page to docs/ROADMAP.md.

   Non-color tokens (spacing/radius/type scale) are identical in both modes and aren't
   repeated here. The 6 PESTTG force-accent colors and the 4 impact-scale colors are
   categorical, not background/foreground, so they're only lightly adjusted for
   contrast-on-white rather than fully re-paired like the bg/text tokens. */
[data-theme="light"] {
  --surface-hover: #e9ebef;
  --border-strong: #c7ccd6;
  --danger-bg: #fee2e2;
  --danger-text: #b91c1c;

  /* Background layers */
  --ds-bg-page: #f5f6f8;
  --ds-bg-card: #ffffff;
  --ds-bg-inset: #eef0f3;
  --ds-border: #dfe2e8;
  --ds-border-strong: #c7ccd6;

  /* Sidebar shell */
  --ds-nav-bg: #eef0f3;
  --ds-nav-border: #dde1e7;
  --ds-nav-active-bg: #e2e6ee;

  /* Text */
  --ds-text-primary: #14161c;
  --ds-text-secondary: #4b5563;
  --ds-text-muted: #6b7280;

  /* Driving-force accents (PESTTG) — darkened slightly from the dark-mode values for
     contrast against light backgrounds, otherwise the same recognizable hues. */
  --ds-force-political: #dc2626;
  --ds-force-economic: #16a34a;
  --ds-force-societal: #b45309;
  --ds-force-technological: #2563eb;
  --ds-force-mega_trends: #9333ea;
  --ds-force-globalisation: #0d9488;

  /* Idea scope accents — darkened for light-background contrast, same hues as the dark
     theme's --ds-scope-* above. */
  --ds-scope-org_wide: #4b5563;
  --ds-scope-new_venture: #db2777;
  --ds-scope-supply_chain: #b45309;
  --ds-scope-operations: #2563eb;
  --ds-scope-marketing_sales: #16a34a;
  --ds-scope-service_warranty: #0d9488;
  --ds-scope-infrastructure: #9333ea;
  --ds-scope-human_resources: #dc2626;
  --ds-scope-technology: #0891b2;
  --ds-scope-procurement: #c2410c;

  /* Semantic */
  --ds-success-bg: #dcfce7;
  --ds-success-text: #15803d;
  --ds-warning-bg: #fef3c7;
  --ds-warning-text: #92400e;
  --ds-danger-bg: #fee2e2;
  --ds-danger-text: #b91c1c;
  --ds-info-bg: #dbeafe;
  --ds-info-text: #1d4ed8;
  --ds-neutral-bg: #e5e7eb;
  --ds-neutral-text: #4b5563;

  /* Impact scale (low -> very_high) */
  --ds-impact-low: #6b7280;
  --ds-impact-medium: #2563eb;
  --ds-impact-high: #b45309;
  --ds-impact-very_high: #dc2626;
}

/* The `hidden` attribute must win even on flex/grid elements (otherwise a
   display:flex rule overrides it and the element stays visible). */
[hidden] { display: none !important; }
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  background: var(--ds-bg-page);
  color: var(--ds-text-primary);
  height: 100vh;
  overflow: hidden;
}
.layout {
  display: flex;
  height: 100vh;
}
/* Business OS — the AI App Builder's own shell (Prompt 24.8's CSS split of style.css).
   Predates Business OS entirely: sidebar/header/section cards/build progress/panels/
   checklist/login/visual-editing toolbar/attachments/voice input/brand kits/content (CMS)/
   publish. Not tied to any single os/<area>.js module — this is the chat-panel + preview-
   panel builder tool, not a Business OS analysis page. */

/* ---- Left sidebar (collapsible) ---- */
.chat-panel {
  width: 360px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  border-right: 1px solid #23262f;
  background: #14161c;
  padding: 14px;
  transition: width 0.18s ease, padding 0.18s ease;
}
.sidebar-inner {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
  gap: 10px;
}
.chat-panel.collapsed {
  width: 60px;
  padding: 12px 8px;
}

/* ---- Header ---- */
.sidebar-header {
  display: flex;
  align-items: center;
  gap: 8px;
}
.chat-panel h1 {
  font-size: 15px;
  margin: 0;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.header-right {
  display: flex;
  align-items: center;
  gap: 6px;
}
.chat-panel.collapsed .sidebar-header {
  flex-direction: column;
}
.chat-panel.collapsed h1,
.chat-panel.collapsed #provider {
  display: none;
}

select {
  /* Widened slightly beyond the plan's named sidebar selector list (Commit 5) — this bare
     `select` rule is what paints every plain <select> in the app (e.g. #provider,
     #projectSelect) consistently. Token values match the existing dark hex closely enough
     that dark mode is visually unchanged. */
  background: var(--ds-bg-inset, #1e212a);
  color: var(--ds-text-primary, #e8e8ec);
  border: 1px solid var(--ds-border-strong, #2c3040);
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 12px;
}

/* ---- Section cards (Project / Configuration) — grouped, visually distinct rows
   instead of a flat stack of same-weight controls. ---- */
.sidebar-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 9px;
  background: #181b23;
  border: 1px solid #23262f;
  border-radius: 8px;
}
.section-title {
  margin: 0;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #6b7180;
}
.section-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.section-row select {
  flex: 1;
  min-width: 0;
}
.section-row select:disabled {
  opacity: 0.7;
  cursor: default;
}
/* ---- Project actions: labelled two-row grid (icon above, sentence-case label below).
   4 columns so 7 buttons wrap to two rows (4 + 3) rather than one. No hover-tooltip
   mechanism here on purpose (see index.html's comment above this markup) — the label is
   a permanent child of the button, not a `[data-tip]:hover::after` reveal. ---- */
.project-actions-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
}
.icon-grid-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 6px 2px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--ds-text-secondary);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.icon-grid-btn:hover,
.icon-grid-btn.is-active {
  background: var(--surface-hover);
  border-color: var(--border-strong);
  color: var(--ds-text-primary);
}
.icon-grid-btn.danger:hover {
  background: var(--danger-bg, #3a1a1a);
  color: var(--danger-text, #f87171);
}
.icon-grid-btn .icon-grid-btn-icon .icon {
  width: 16px;
  height: 16px;
}
.icon-grid-btn-label {
  font-size: 10px;
  line-height: 1.15;
  text-align: center;
  white-space: nowrap;
}
.icon-grid-btn:disabled {
  opacity: 0.5;
  cursor: default;
}
.icon-grid-btn:disabled:hover {
  background: transparent;
  border-color: transparent;
  color: var(--ds-text-secondary);
}
.field-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  color: #6b7180;
}

/* This project's Brand Kit picker, rendered at the top of the Brand Kit panel (opened from
   the project row's icon — see brandKits.js's renderProjectBrandKitPicker). Not a permanent
   sidebar row: only present while the panel is open. */
.brandkit-project-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border-strong, #23262f);
}
.brandkit-project-row label {
  font-size: 12px;
  color: var(--ds-text-secondary);
  flex-shrink: 0;
}
.brandkit-project-row select {
  flex: 1;
  min-width: 0;
}

/* ---- Collapsed sidebar: section cards shrink to icon-only columns. Field icons (e.g. the
   Project row's folder glyph) still carry a data-tip hover reveal at this width — there's no
   room for a permanent label at 60px. The project-actions-grid buttons drop their permanent
   label here too for the same space reason, falling back to icon-only + aria-label; this is
   the one place they lose the always-visible label the rest of this file's sizing keeps. ---- */
.chat-panel.collapsed .section-title,
.chat-panel.collapsed .section-row select {
  display: none;
}
.chat-panel.collapsed .sidebar-section {
  align-items: center;
  padding: 6px 0;
  background: transparent;
  border-color: transparent;
}
.chat-panel.collapsed .section-row {
  flex-direction: column;
}
.chat-panel.collapsed .project-actions-grid {
  grid-template-columns: 1fr;
}
.chat-panel.collapsed .icon-grid-btn-label {
  display: none;
}
/* Nothing below the cost row (activity log, history/brand-kit panels, the composer)
   fits meaningfully in an icon-only column — hide it while collapsed, same as the
   old rail design did, just scoped per-element instead of one big wrapper. */
.chat-panel.collapsed .messages,
.chat-panel.collapsed .history-panel,
.chat-panel.collapsed .build-status,
.chat-panel.collapsed .prompt-form,
.chat-panel.collapsed .hint {
  display: none;
}

/* ---- Icon buttons: icon-only by default, label on hover via data-tip (no JS). ---- */
.icon-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  flex-shrink: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  /* Widened slightly beyond the plan's named sidebar selector list (Commit 5) — .icon-btn
     is what #primaryNavToggle/#bellBtn/#docsBtn/#settingsBtn/#logoutBtn (all in
     .primary-nav-header/#globalFooterBar, explicitly in scope) actually use for color. */
  color: var(--ds-text-secondary);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.icon-btn:hover,
.icon-btn.is-active {
  background: var(--surface-hover);
  border-color: var(--border-strong);
  color: var(--ds-text-primary);
}
.icon-btn.danger:hover {
  background: var(--danger-bg, #3a1a1a);
  color: var(--danger-text, #f87171);
}
/* "New project" as the primary action — toggled by projects.js only while there is no
   current project (see loadProjects/deleteCurrentProject's empty-state branches). Once a
   project exists, New Project reverts to an ordinary icon button; it's no longer the one
   obvious first thing to do. Same treatment components.css's .ds-btn-primary uses
   elsewhere, applied to this sidebar's own icon-button shape. */
.icon-btn.primary {
  background: var(--ds-info-text);
  border-color: var(--ds-info-text);
  color: #0b0d11;
}
.icon-btn.primary:hover {
  background: var(--ds-info-text);
  opacity: 0.85;
}
/* Notifications Bell's unread-count badge (see #bellBtn/#bellBadge in index.html) —
   .icon-btn's own position:relative anchors it. Hidden via the [hidden] attribute
   (public/notifications.js toggles it), not display:none in CSS, so JS stays the single
   source of truth for visibility. */
.icon-btn-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 15px;
  height: 15px;
  padding: 0 3px;
  border-radius: 999px;
  background: var(--ds-force-political, #ef4444);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
}
[data-tip] {
  position: relative;
}
[data-tip]:hover::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  background: #000;
  color: #fff;
  font-size: 11px;
  padding: 3px 7px;
  border-radius: 4px;
  white-space: nowrap;
  pointer-events: none;
  z-index: var(--ds-z-tooltip);
}
/* The top-bar toolbar sits right at the top of the viewport — a tooltip opening
   upward from there gets clipped by the browser chrome, so flip it downward. */
.toolbar-actions [data-tip]:hover::after {
  bottom: auto;
  top: calc(100% + 6px);
}

/* Sidebar collapse/expand toggle icon rotates to hint direction: pointing left = will
   collapse, pointing right = will expand. */
#sidebarToggle .icon {
  transition: transform 180ms ease;
  transform: rotate(90deg);
}
.chat-panel.collapsed #sidebarToggle .icon {
  transform: rotate(-90deg);
}

/* ---- Cost tracker: persistent metadata row, pulled out of the activity log. ---- */
.cost-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 9px;
  background: #12141a;
  border: 1px solid #23262f;
  border-radius: 6px;
}
.cost-row:has(.cost-text:empty) {
  display: none;
}
.cost-text {
  font-size: 11px;
  color: #8a92a6;
}
.chat-panel.collapsed .cost-text {
  display: none;
}
.chat-panel.collapsed .cost-row {
  justify-content: center;
  background: transparent;
  border-color: transparent;
  padding: 6px 0;
}
.messages {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 12px;
}
.history-panel {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}
.history-empty {
  font-size: 12px;
  color: #6b7080;
  margin: 0;
}
.history-item {
  background: #1a1d24;
  border: 1px solid #23262f;
  border-radius: 8px;
  padding: 10px;
}
.history-meta {
  font-size: 11px;
  color: #6b7080;
  margin-bottom: 4px;
}
.history-prompt {
  font-size: 13px;
  line-height: 1.35;
  color: #e8e8ec;
  white-space: pre-wrap;
  word-break: break-word;
  margin-bottom: 8px;
}
.history-actions {
  display: flex;
  gap: 6px;
}
.history-actions button {
  background: #23283a;
  font-size: 11px;
  padding: 4px 10px;
}
/* Elements panel (public/elementsPanel.js) — uses --ds-* tokens (both color modes), unlike
   this file's older .history-item etc. rules above, which predate the design system's token
   adoption and stay dark-only (see css/base.css's own header on that scope). */
.elements-target-status {
  margin-bottom: 10px;
}
.elements-target-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--ds-font-sm, 12px);
  color: var(--ds-text-primary);
  background: var(--ds-bg-inset);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-sm, 6px);
  padding: 8px 10px;
}
.elements-target-empty {
  color: var(--ds-text-secondary);
}
.elements-position-toggle {
  display: flex;
  gap: 6px;
  margin-top: 6px;
}
.elements-position-toggle button {
  flex: 1;
  font-size: var(--ds-font-xs, 11px);
  padding: 5px 8px;
  background: var(--ds-bg-card);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-sm, 6px);
  color: var(--ds-text-secondary);
  cursor: pointer;
}
.elements-position-toggle button.is-active {
  background: var(--ds-nav-active-bg, var(--ds-bg-inset));
  border-color: var(--ds-border-strong);
  color: var(--ds-text-primary);
}
.elements-shared-warning {
  margin-top: 6px;
  font-size: var(--ds-font-xs, 11px);
  background: var(--ds-warning-bg);
  color: var(--ds-warning-text);
  border-radius: var(--ds-radius-sm, 6px);
  padding: 6px 8px;
}
.elements-search {
  width: 100%;
  box-sizing: border-box;
  margin-bottom: 10px;
  padding: 6px 10px;
  font-size: var(--ds-font-sm, 12px);
  background: var(--ds-bg-card);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-sm, 6px);
  color: var(--ds-text-primary);
}
.elements-category-header {
  font-size: var(--ds-font-xs, 11px);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ds-text-muted);
  margin: 10px 0 6px;
}
.elements-category-header:first-child {
  margin-top: 0;
}
.elements-category-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
.elements-item-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 8px 4px;
  background: var(--ds-bg-card);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-sm, 6px);
  color: var(--ds-text-secondary);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.elements-item-btn:hover:not(:disabled) {
  background: var(--surface-hover);
  border-color: var(--border-strong);
  color: var(--ds-text-primary);
}
.elements-item-btn:disabled {
  opacity: 0.45;
  cursor: default;
}
.elements-item-icon .icon {
  width: 16px;
  height: 16px;
}
.elements-item-label {
  font-size: 10px;
  line-height: 1.15;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* ---- Round 4 drawer editor (public/veDrawer.js) — same panel shell as .history-panel,
   reuses .elements-target-row/.elements-target-empty/.elements-shared-warning verbatim for
   the "select an element" empty state and the shared-component warning. ---- */
.ve-section-title {
  font-size: var(--ds-font-xs, 11px);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ds-text-muted);
  margin: 14px 0 6px;
}
.ve-section-title:first-child {
  margin-top: 0;
}
.ve-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px;
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-sm, 6px);
  margin-bottom: 6px;
  font-size: var(--ds-font-sm, 12px);
}
.ve-field label {
  font-weight: 500;
  color: var(--ds-text-secondary);
}
.ve-field-row {
  flex-direction: row;
  align-items: center;
}
.ve-field-greyed {
  opacity: 0.65;
  background: var(--ds-bg-inset);
}
/* An UNSET-but-settable prop (Round 5 (a)) — deliberately NOT dimmed like .ve-field-greyed:
   its control is live, and dimming it is exactly what made "not set here" read as a refusal.
   The dashed border is the only thing marking it as not-yet-written. */
.ve-field-unset {
  border-style: dashed;
}
/* The repeatable array-of-media control (Carousel's images) — every row is local, unsaved
   state until "Save images", so nothing here implies a write has happened. */
.ve-media-rows {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ve-media-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.ve-media-thumb {
  width: 40px;
  height: 30px;
  object-fit: cover;
  border-radius: var(--ds-radius-sm, 6px);
  border: 1px solid var(--ds-border);
  flex-shrink: 0;
  background: var(--ds-bg-inset);
}
.ve-media-row .ve-media-alt {
  flex: 1 1 auto;
  min-width: 0;
}
.ve-media-row-actions {
  display: flex;
  gap: 2px;
  flex-shrink: 0;
}
.media-picker-multi-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--ds-border);
  font-size: var(--ds-font-sm, 12px);
  color: var(--ds-text-secondary);
}
.ve-prop-add-check {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1 1 auto;
  font-weight: 400;
  color: var(--ds-text-secondary);
}
.ve-greyed-reason {
  margin: 0;
  font-size: var(--ds-font-xs, 11px);
  color: var(--ds-text-muted);
}
.ve-color-row {
  display: flex;
  gap: 6px;
  align-items: center;
}
.ve-color-row select,
.ve-color-row input {
  flex: 1 1 auto;
  min-width: 0;
}
.ve-color-swatch {
  display: inline-block;
  width: 20px;
  height: 20px;
  border-radius: 4px;
  border: 1px solid var(--ds-border-strong);
  flex-shrink: 0;
}
.ve-color-subfield {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 400;
}
.ve-color-subfield span {
  font-size: var(--ds-font-xs, 11px);
  color: var(--ds-text-muted);
}
.ve-current-src {
  margin: 0;
  font-size: var(--ds-font-xs, 11px);
  color: var(--ds-text-secondary);
  word-break: break-all;
}
.ve-location-row {
  font-size: var(--ds-font-xs, 11px);
  color: var(--ds-text-muted);
  margin-bottom: 8px;
  overflow-wrap: anywhere;
}
.ve-delete-row {
  margin-bottom: 10px;
}
.ve-delete-row .ds-btn {
  width: 100%;
}
.ve-shared-warning {
  margin-bottom: 8px;
  font-size: var(--ds-font-xs, 11px);
  background: var(--ds-warning-bg);
  color: var(--ds-warning-text);
  border-radius: var(--ds-radius-sm, 6px);
  padding: 6px 8px;
}
.ve-status-row {
  font-size: var(--ds-font-xs, 11px);
  color: var(--ds-text-muted);
  margin-bottom: 8px;
}

.msg {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.4;
}
.msg-text {
  min-width: 0;
}
/* Activity-log status dot: gray for routine narration, green once a system message's
   phrasing reads as a completed/ready outcome (see messages.js's READY_RE). */
.msg-dot {
  flex-shrink: 0;
  width: 6px;
  height: 6px;
  margin-top: 5px;
  border-radius: 50%;
  background: #5a6072;
}
.msg-dot.ready {
  background: #4ade80;
}
.msg.user {
  background: #23283a;
  align-self: flex-end;
}
.msg.system {
  background: #1a1d24;
  color: #9aa0ac;
}
.msg.error {
  background: #3a1e22;
  color: #ff9a9a;
}
.msg.error .msg-dot {
  background: #ff9a9a;
}
.prompt-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
textarea {
  background: #1e212a;
  color: #e8e8ec;
  border: 1px solid #2c3040;
  border-radius: 8px;
  padding: 10px;
  resize: vertical;
  font-family: inherit;
  font-size: 13px;
}
button {
  background: #4a6cf7;
  color: white;
  border: none;
  border-radius: 6px;
  padding: 8px 14px;
  font-size: 13px;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
}
button:disabled {
  opacity: 0.6;
  cursor: default;
}
.hint {
  font-size: 11px;
  color: #6b7080;
  margin: 8px 0 0;
}

/* ---- Build progress indicator (see buildStatus.js) ------------------------ */
.build-status {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 7px 10px;
  background: #12141a;
  border: 1px solid #23262f;
  border-radius: 8px;
  font-size: 12px;
  color: #9aa0ac;
}
.build-status-header {
  display: flex;
  align-items: center;
  gap: 8px;
}
.build-status-trail {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}
/* Scrolling step-by-step log — plain lines, not styling-polished yet (first pass). */
.build-status-log {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 90px;
  overflow-y: auto;
}
.build-step {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.build-step__icon {
  flex-shrink: 0;
  width: 10px;
  text-align: center;
  color: #5a6072;
}
.build-step[data-status="active"] .build-step__icon {
  color: #4a6cf7;
}
.build-step[data-status="done"] {
  color: #6b7080;
}
.build-step[data-status="error"] .build-step__icon {
  color: #ff9a9a;
}
.build-status-footer {
  display: flex;
  justify-content: space-between;
  padding-top: 4px;
  border-top: 1px solid #23262f;
}
.build-status-cancel.icon-btn {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}
.build-stage-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #3a3f52;
  flex-shrink: 0;
}
.build-stage-dot.done {
  background: #5a6072;
}
.build-stage-dot.active {
  background: #4a6cf7;
  animation: build-stage-pulse 1s ease-in-out infinite;
}
@keyframes build-stage-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.45; transform: scale(1.35); }
}
.build-status-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.build-status-dismiss {
  background: transparent;
  border: none;
  color: inherit;
  font-size: 15px;
  line-height: 1;
  padding: 0 2px;
  cursor: pointer;
  flex-shrink: 0;
}
/* Clean success — green, auto-fades (see buildStatus.js AUTO_HIDE_MS). */
.build-status.success {
  background: #16301f;
  border-color: #1e4029;
  color: #8fe3a8;
}
.build-status.success .build-stage-dot.done,
.build-status.success .build-stage-dot.active {
  background: #4ade80;
  animation: none;
}
/* Success, but truncated or with warnings — amber, not green; stays until dismissed. */
.build-status.success-warn {
  background: #332b14;
  border-color: #4d3f1a;
  color: #f0c766;
}
.build-status.success-warn .build-stage-dot.done {
  background: #b8923f;
}
/* Informational terminal state (e.g. "full-stack detected but not buildable yet") —
   neutral, matching the muted .msg.system tone, not styled as an error. */
.build-status.info {
  background: #1a1d24;
  border-color: #2c3040;
  color: #9aa0ac;
}
/* Build failed — red, matching .msg.error's palette; stays until dismissed. */
.build-status.error {
  background: #3a1e22;
  border-color: #5a2a30;
  color: #ff9a9a;
}
.build-status.error .build-stage-dot.done {
  background: #7a3d42;
}
/* Stream dropped before a terminal event arrived — the build may well have completed
   server-side, so this is deliberately NOT styled as a hard failure. */
.build-status.lost {
  background: #332417;
  border-color: #4d3620;
  color: #ffb86b;
}

/* ---- Right side: resizable / collapsible panels ---- */
.preview-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
}
.panel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}
/* Top bar: view toggles on the left, device-size toggle truly centered (equal 1fr
   columns on either side keep it centered regardless of how wide those groups are),
   global actions on the right. */
.top-bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  border-bottom: 1px solid #23262f;
  background: #14161c;
  flex-shrink: 0;
}
.top-bar .view-toggle {
  justify-self: start;
}
.top-bar .device-toggle {
  justify-self: center;
}
.top-bar .toolbar-actions {
  justify-self: end;
}
.view-toggle {
  display: flex;
  gap: 4px;
  background: #12141a;
  border: 1px solid #23262f;
  border-radius: 8px;
  padding: 3px;
}
.view-btn {
  background: transparent;
  color: #9aa0ac;
  border: none;
  border-radius: 6px;
  padding: 6px 12px;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}
.view-btn:hover {
  background: #1a1d24;
  color: #e8e8ec;
}
.view-btn.active {
  background: #4a6cf7;
  color: #fff;
}
.icon {
  width: 16px;
  height: 16px;
  display: block;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Tabbed views: only the active one is shown. */
.view {
  display: none;
  flex: 1;
  min-width: 0;
  min-height: 0;
}
.view.active {
  display: flex;
  flex-direction: column;
}
#pane-notes {
  flex: 1;
}

/* Preview sub-toolbar: page picker (static multi-page projects only — hidden
   entirely for full-stack, see updatePreviewSurface). */
.preview-subbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px;
  border-bottom: 1px solid #23262f;
  background: #0f1115;
  flex-shrink: 0;
}
.device-toggle {
  display: flex;
  gap: 4px;
  background: #12141a;
  border: 1px solid #23262f;
  border-radius: 8px;
  padding: 3px;
}
.device-btn {
  background: transparent;
  color: #9aa0ac;
  border: none;
  border-radius: 6px;
  padding: 5px 9px;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}
.device-btn:hover {
  background: #1a1d24;
  color: #e8e8ec;
}
.device-btn.active {
  background: #4a6cf7;
  color: #fff;
}
.panel-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  border-bottom: 1px solid #23262f;
  font-size: 13px;
  background: #14161c;
  flex-shrink: 0;
}
.panel-title {
  font-weight: 500;
  white-space: nowrap;
}
.toolbar-left {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
#pageSelect {
  max-width: 200px;
}
.toolbar-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
}
/* Icon-only buttons (see .icon-btn) — same pattern as the sidebar's icon buttons. */
.min-btn {
  background: #23283a;
  font-size: 13px;
  line-height: 1;
  padding: 4px 9px;
  font-weight: 700;
}
.min-btn:hover {
  background: #2c3350;
}
.panel-body {
  flex: 1;
  min-height: 0;
  min-width: 0;
  display: flex;
  overflow: hidden;
}
.preview-body {
  flex: 1;
  min-height: 0;
  display: flex;
  justify-content: center;
  align-items: stretch;
  overflow: auto;
  background: #0b0d12;
  position: relative; /* anchor for the floating visual-editing toolbar */
}
/* Device-size wrapper: full-width desktop, or a centered framed viewport. */
.device-frame {
  display: flex;
  width: 100%;
  background: white;
}
.device-frame.dev-tablet,
.device-frame.dev-mobile {
  margin: 16px;
  max-width: 100%;
  border: 1px solid #2c3040;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 12px 44px rgba(0, 0, 0, 0.5);
}
.device-frame.dev-tablet {
  width: 768px;
}
.device-frame.dev-mobile {
  width: 375px;
}
#previewFrame {
  flex: 1;
  width: 100%;
  border: none;
  background: white;
}
.preview-idle {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  color: #9aa0ac;
  text-align: center;
  line-height: 1.6;
}
.preview-idle strong {
  color: #e8e8ec;
}
/* Notes tab: the checklist (when there's anything to show) stacks above the permanent
   reference content below, instead of the row layout .panel-body uses everywhere else. */
#pane-notes .panel-body {
  flex-direction: column;
  overflow-y: auto;
}
.preview-note {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  color: #9aa0ac;
  overflow: auto;
}
.preview-note .note-inner {
  max-width: 420px;
}
.preview-note ol {
  margin: 8px 0 0;
  padding-left: 18px;
  line-height: 1.7;
}
.preview-note h3 {
  margin: 0 0 8px;
  color: #e8e8ec;
  font-size: 15px;
}
.preview-note ul {
  margin: 8px 0 0;
  padding-left: 18px;
  line-height: 1.6;
}
.preview-note code {
  background: #1a1d24;
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 12px;
}

/* ---- Build checklist (Notes tab, see checklist.js) ------------------------ */
.checklist-container:empty {
  display: none;
}
.checklist {
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
  padding: 20px 24px 0;
  text-align: left;
  flex-shrink: 0;
}
.checklist-heading {
  margin: 0 0 12px;
  color: #e8e8ec;
  font-size: 15px;
}
.checklist-category {
  margin-bottom: 16px;
}
.checklist-category-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #6b7180;
}
.checklist-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px;
  background: #1a1d24;
  border: 1px solid #23262f;
  border-radius: 8px;
  margin-bottom: 6px;
}
.checklist-item.is-done {
  opacity: 0.6;
}
.checklist-item.is-done .checklist-item-title {
  text-decoration: line-through;
}
.checklist-checkbox {
  margin-top: 2px;
  flex-shrink: 0;
  cursor: pointer;
}
.checklist-item-body {
  flex: 1;
  min-width: 0;
}
.checklist-item-title {
  font-size: 13px;
  color: #e8e8ec;
  line-height: 1.4;
}
.checklist-item-desc {
  font-size: 12px;
  color: #9aa0ac;
  margin-top: 2px;
  line-height: 1.4;
}
.checklist-item-ref {
  font-size: 11px;
  color: #6b7180;
  margin-top: 4px;
  font-family: ui-monospace, SFMono-Regular, monospace;
}
.checklist-dismiss {
  background: transparent;
  border: none;
  color: #6b7180;
  font-size: 15px;
  line-height: 1;
  padding: 2px 4px;
  cursor: pointer;
  flex-shrink: 0;
}
.checklist-dismiss:hover {
  color: #ff9a9a;
}

.run-log {
  flex: 1;
  margin: 0;
  padding: 12px 16px;
  overflow: auto;
  background: #0b0d12;
  color: #b6c2cf;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Lower row: file tree | code, side by side */
.code-cols {
  flex: 1;
  display: flex;
  flex-direction: row;
  min-height: 0;
  min-width: 0;
}
#pane-filetree {
  flex: var(--tree-grow, 24) 1 0;
}
#pane-editor {
  flex: var(--editor-grow, 76) 1 0;
}
.file-tree {
  flex: 1;
  overflow: auto;
  padding: 8px 0;
  background: #0b0d12;
}
.tree-folder {
  font-size: 12px;
  color: #9aa0ac;
  padding: 4px 8px;
  white-space: nowrap;
}
.tree-file {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: 0;
  color: #c9d1d9;
  font-size: 12px;
  padding: 4px 8px;
  cursor: pointer;
  white-space: nowrap;
}
.tree-file:hover {
  background: #1a1d24;
}
.tree-file.active {
  background: #23283a;
  color: #fff;
}
.tree-empty {
  font-size: 12px;
  color: #6b7080;
  padding: 8px 12px;
  margin: 0;
}
.editor {
  flex: 1;
  min-width: 0;
  margin: 0;
  padding: 16px;
  overflow: auto;
  background: #0b0d12;
  color: #c9d1d9;
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Prism token colours for the read-only Code panel (public/codeHighlight.js). Hand-written
   against this panel's existing palette (bg #0b0d12 / fg #c9d1d9) rather than importing one of
   prismjs's own themes: a vendored theme would ship its own background, font stack and padding
   and then have to be fought back out again to match the panel it sits in. Only the token
   classes the six registered grammars actually emit are styled; anything unstyled simply
   inherits the panel's foreground, which is the pre-highlighting appearance and always legible. */
.editor .token.comment,
.editor .token.prolog,
.editor .token.doctype,
.editor .token.cdata {
  color: #6a737d;
  font-style: italic;
}
.editor .token.punctuation {
  color: #8b949e;
}
.editor .token.keyword,
.editor .token.rule,
.editor .token.important,
.editor .token.atrule {
  color: #ff7b72;
}
.editor .token.string,
.editor .token.char,
.editor .token.attr-value,
.editor .token.regex {
  color: #a5d6ff;
}
.editor .token.number,
.editor .token.boolean,
.editor .token.constant,
.editor .token.symbol {
  color: #79c0ff;
}
.editor .token.function,
.editor .token.class-name,
.editor .token.builtin {
  color: #d2a8ff;
}
.editor .token.tag,
.editor .token.selector {
  color: #7ee787;
}
.editor .token.attr-name,
.editor .token.property {
  color: #ffa657;
}
.editor .token.operator,
.editor .token.entity,
.editor .token.url {
  color: #a5d6ff;
}
.editor .token.deleted {
  color: #ffa198;
}
.editor .token.inserted {
  color: #7ee787;
}
.editor .token.namespace {
  opacity: 0.75;
}

/* Find-in-file matches (public/codeSearchMatch.js's markHtml). A match crossing Prism token
   spans is emitted as SEVERAL <mark> elements, so these rules must look continuous when two sit
   side by side — hence a flat background and no border/radius/padding, which would otherwise
   draw visible seams through the middle of one logical match. `color: inherit` keeps the
   token's own syntax colour underneath the highlight instead of flattening it. */
.editor mark.code-match {
  background: #3b3d1a;
  color: inherit;
  border-radius: 0;
  padding: 0;
}
.editor mark.code-match.is-active {
  background: #9e6a03;
  color: #fff5d6;
}

.code-search {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
}
.code-search-input {
  width: 130px;
  background: var(--ds-bg-inset, #0b0d12);
  border: 1px solid var(--ds-border-strong, #30363d);
  border-radius: 5px;
  color: var(--ds-text-primary, #c9d1d9);
  font-size: 11px;
  padding: 2px 6px;
}
.code-search-input:focus {
  outline: none;
  border-color: var(--ds-accent, #58a6ff);
}
.code-search-count {
  font-size: 10px;
  color: var(--ds-text-muted, #8b949e);
  min-width: 46px;
  text-align: right;
  white-space: nowrap;
}
.code-search-nav {
  background: transparent;
  border: 1px solid var(--ds-border-strong, #30363d);
  border-radius: 5px;
  color: var(--ds-text-secondary, #8b949e);
  cursor: pointer;
  font-size: 10px;
  line-height: 1;
  padding: 3px 5px;
}
.code-search-nav:hover:not(:disabled) {
  color: var(--ds-text-primary, #c9d1d9);
}
.code-search-nav:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Drag handles */
.resizer {
  flex-shrink: 0;
  background: #0b0d12;
  transition: background 0.12s ease;
}
.resizer-h {
  width: 6px;
  cursor: col-resize;
}
.resizer:hover,
.resizer.dragging {
  background: #4a6cf7;
}

/* Minimized panels collapse to a labeled strip; siblings grow to fill. */
.panel.minimized {
  flex: 0 0 auto;
}
.panel.minimized .panel-body {
  display: none;
}
.panel.minimized .panel-head {
  cursor: pointer;
}
/* File tree / code minimized: a narrow vertical strip with a rotated label. */
.subpanel.minimized {
  flex: 0 0 38px;
}
.subpanel.minimized .panel-head {
  flex-direction: column;
  align-items: center;
  gap: 10px;
  height: 100%;
  padding: 10px 4px;
  border-bottom: none;
  border-right: 1px solid #23262f;
}
.subpanel.minimized .panel-title {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

/* ---- Login / signup screen ---- */
.auth-screen {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.auth-card {
  width: 320px;
  max-width: 100%;
  background: #14161c;
  border: 1px solid #23262f;
  border-radius: 12px;
  padding: 28px 24px;
  display: flex;
  flex-direction: column;
}
.auth-card h1 {
  font-size: 18px;
  margin: 0 0 4px;
}
.auth-card h1.auth-brand {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}
.auth-brand-letter {
  color: #4a6cf7;
}
.auth-sub {
  font-size: 13px;
  color: #8a92a6;
  margin: 0 0 18px;
}
.auth-label {
  font-size: 11px;
  color: #8a92a6;
  margin-bottom: 4px;
}
.auth-card input {
  background: #1e212a;
  color: #e8e8ec;
  border: 1px solid #2c3040;
  border-radius: 8px;
  padding: 9px 10px;
  font-size: 13px;
  font-family: inherit;
  margin-bottom: 14px;
}
.auth-card input:focus {
  outline: none;
  border-color: #4a6cf7;
}
.auth-card #authSubmit {
  margin-top: 2px;
}
.auth-error {
  color: #ff9a9a;
  background: #3a1e22;
  border-radius: 6px;
  font-size: 12px;
  padding: 8px 10px;
  margin: 14px 0 0;
}
.auth-toggle {
  font-size: 12px;
  color: #8a92a6;
  margin: 16px 0 0;
  text-align: center;
}
.link-btn {
  background: none;
  border: none;
  color: #6b8afd;
  cursor: pointer;
  font-size: 12px;
  padding: 0 0 0 4px;
  text-decoration: underline;
}
/* ---- Visual-editing toolbar + composer chips ------------------------------ */
/* Floating mini toolbar, bottom-center over the live preview. */
.ve-toolbar {
  position: absolute;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px;
  background: #14161c;
  border: 1px solid #2c3040;
  border-radius: 10px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
  z-index: var(--ds-z-float-control);
}
.ve-toolbar button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: #23283a;
  color: #e8e8ec;
  border: none;
  border-radius: 6px;
  padding: 0;
  cursor: pointer;
}
.ve-toolbar button:hover {
  background: #2c3350;
}
.ve-toolbar .ve-tool.active {
  background: #4a6cf7;
  color: #fff;
}
.ve-toolbar .ve-send {
  background: #4a6cf7;
  color: #fff;
}
.ve-toolbar .ve-send:hover {
  background: #3a5ce0;
}
.ve-sep {
  width: 1px;
  align-self: stretch;
  background: #2c3040;
  margin: 2px 2px;
}

/* Attached-context chips shown above the prompt textarea. */
.vc-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 6px;
}
.vc-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: #1e212a;
  border: 1px solid #2c3040;
  color: #cdd2de;
  border-radius: 999px;
  padding: 3px 8px;
  font-size: 12px;
}
.vc-chip-x {
  background: transparent;
  border: none;
  color: #8a92a6;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0;
}
.vc-chip-x:hover {
  color: #ff9a9a;
}

/* ---- Prompt Attachments (chat-panel image attachments) --------------------------- */
.attachments-preview {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 6px;
}
.attachment-thumb {
  position: relative;
  width: 48px;
  height: 48px;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid #2c3040;
  background: #1e212a;
  cursor: zoom-in;
}
.attachment-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.attachment-thumb-x {
  position: absolute;
  top: 1px;
  right: 1px;
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  border: none;
  border-radius: 50%;
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}
.attachment-thumb-x:hover {
  background: #ff5a5a;
}
.attachment-drop-zone {
  position: relative;
  width: 100%;
}
/* A bare <textarea> sizes itself from its `cols` attribute, not its container, so without
   this it renders at roughly half the sidebar's width instead of filling it — the visible
   margin then comes entirely from .chat-panel's own 14px padding, not the textarea itself. */
#promptInput {
  width: 100%;
  box-sizing: border-box;
}
.attachment-drop-overlay {
  display: none;
  position: absolute;
  inset: 0;
  align-items: center;
  justify-content: center;
  background: rgba(74, 108, 247, 0.15);
  border: 2px dashed #4a6cf7;
  border-radius: 8px;
  color: #cdd2de;
  font-size: 12px;
  pointer-events: none;
}
.attachment-drop-zone.dragover .attachment-drop-overlay {
  display: flex;
}
.attachment-error {
  font-size: 11px;
  color: #ff9a9a;
  margin: -2px 0 2px;
}

/* Lightbox for a clicked attachment thumbnail — thumbnails/message images both use it. */
.attachment-lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--ds-z-modal-lite);
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.8);
  cursor: zoom-out;
}
.attachment-lightbox img {
  max-width: 90vw;
  max-height: 90vh;
  border-radius: 8px;
}

/* Sent-message thumbnails in the chat log (see messages.js). */
.msg-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}
.msg-attachments .attachment-thumb {
  cursor: zoom-in;
}

.prompt-form-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}
.prompt-form-actions #sendBtn {
  margin-left: auto;
}

/* ---- Voice input (recording / transcribing status) -------------------------------- */
.voice-status {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: #9aa0ac;
  background: #1a1d24;
  border: 1px solid #23262f;
  border-radius: 6px;
  padding: 6px 10px;
}
.voice-status.recording {
  color: #ff9a9a;
}
.voice-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #ff5a5a;
  animation: voice-pulse 1.2s ease-in-out infinite;
}
@keyframes voice-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}
.voice-level {
  flex: 1;
  height: 3px;
  border-radius: 2px;
  background: #2c3040;
  overflow: hidden;
  max-width: 80px;
}
.voice-level-bar {
  height: 100%;
  width: 0%;
  background: #ff5a5a;
  transition: width 80ms linear;
}

/* ---- Brand Kits (management panel + project-bar selector + new-project popover) --- */
.brandkit-manage-btn {
  background: #23283a;
  font-size: 11px;
  padding: 4px 10px;
  white-space: nowrap;
}

.brandkit-item {
  background: #1a1d24;
  border: 1px solid #23262f;
  border-radius: 8px;
  padding: 10px;
  margin-bottom: 8px;
}
.brandkit-item-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.brandkit-item-name {
  font-size: 13px;
  font-weight: 500;
}
.brandkit-swatches {
  display: flex;
  gap: 4px;
  margin: 6px 0;
}
.brandkit-swatch {
  width: 18px;
  height: 18px;
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, 0.15);
}
.brandkit-item-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.brandkit-item-actions button {
  background: #23283a;
  font-size: 11px;
  padding: 4px 8px;
}
.brandkit-item-actions button.danger {
  background: #3a1e22;
}

/* Kit detail/edit view */
.brandkit-detail-back {
  background: #23283a;
  font-size: 12px;
  padding: 4px 10px;
  margin-bottom: 10px;
}
.brandkit-field {
  margin-bottom: 14px;
}
.brandkit-field label {
  display: block;
  font-size: 11px;
  color: #8a92a6;
  margin-bottom: 4px;
}
.brandkit-field input[type="text"] {
  width: 100%;
  background: #1e212a;
  color: #e8e8ec;
  border: 1px solid #2c3040;
  border-radius: 6px;
  padding: 6px 8px;
  font-size: 13px;
}
.brandkit-color-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}
.contrast-badges {
  display: inline-flex;
  gap: 4px;
  flex-shrink: 0;
}
.contrast-badge {
  display: inline-block;
  min-width: 34px;
  text-align: center;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 5px;
  border-radius: 4px;
  background: #3a1e22;
  color: #ff9a9a;
}
.contrast-badge.AA,
.contrast-badge.AAA {
  background: #1a3a26;
  color: #7ee0a3;
}
.brandkit-color-row input[type="color"] {
  width: 32px;
  height: 32px;
  border: 1px solid #2c3040;
  border-radius: 6px;
  background: none;
  padding: 0;
  cursor: pointer;
}
.brandkit-color-row .role-label {
  width: 70px;
  font-size: 12px;
  color: #8a92a6;
  flex-shrink: 0;
}
.brandkit-color-row input[type="text"] {
  flex: 1;
  min-width: 0;
  background: #1e212a;
  color: #e8e8ec;
  border: 1px solid #2c3040;
  border-radius: 6px;
  padding: 5px 7px;
  font-size: 12px;
}
.brandkit-font-row {
  margin-bottom: 10px;
}
.brandkit-font-row .role-label {
  font-size: 12px;
  color: #8a92a6;
  margin-bottom: 4px;
  display: block;
}
.brandkit-assets-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 10px;
}
.brandkit-asset-tile {
  background: #1a1d24;
  border: 1px solid #23262f;
  border-radius: 8px;
  padding: 8px;
  text-align: center;
}
.brandkit-asset-tile img {
  max-width: 100%;
  max-height: 60px;
  margin-bottom: 6px;
}
.brandkit-asset-tile .label {
  font-size: 10px;
  color: #8a92a6;
  margin-bottom: 6px;
}
.brandkit-asset-tile .actions {
  display: flex;
  gap: 4px;
  justify-content: center;
}
.brandkit-asset-tile button {
  background: #23283a;
  font-size: 10px;
  padding: 3px 6px;
}
.brandkit-history-list {
  font-size: 12px;
  color: #9aa0ac;
}
.brandkit-history-entry {
  padding: 6px 0;
  border-bottom: 1px solid #23262f;
}
.brandkit-history-entry:last-child {
  border-bottom: none;
}

/* New Project popover (floating, anchored near the New button) */
.new-project-popover {
  position: fixed;
  z-index: var(--ds-z-popover);
  width: 300px;
  background: #14161c;
  border: 1px solid #2c3040;
  border-radius: 10px;
  padding: 14px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
  font-size: 13px;
}
.new-project-popover h3 {
  margin: 0 0 10px;
  font-size: 14px;
}
.new-project-popover input[type="text"] {
  width: 100%;
  box-sizing: border-box;
  background: #1e212a;
  color: #e8e8ec;
  border: 1px solid #2c3040;
  border-radius: 6px;
  padding: 6px 8px;
  font-size: 13px;
  margin-bottom: 10px;
}
.new-project-popover .brandkit-option {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
  font-size: 12px;
}
.new-project-popover .np-section-label {
  margin: 12px 0 6px;
  padding-top: 10px;
  border-top: 1px solid #23262f;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #6b7180;
}
.new-project-popover .brandkit-option.is-disabled {
  color: #6b7180;
  cursor: default;
}
.new-project-popover .np-coming-soon {
  margin-left: auto;
  padding: 1px 6px;
  border-radius: 999px;
  background: #23262f;
  color: #8a92a6;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.new-project-popover select {
  width: 100%;
  margin: 4px 0 10px;
}
.new-project-popover .actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  margin-top: 8px;
}
.new-project-popover .actions button.cancel {
  background: #23283a;
}

/* Notifications Bell popover (Business OS — Notifications Bell + Settings, V1) — same
   anchored-popover mechanics as .new-project-popover above (see public/notifications.js),
   styled with the --ds-* Design System tokens (see :root) since this is new UI. */
.notifications-popover {
  position: fixed;
  z-index: var(--ds-z-popover);
  width: 360px;
  max-height: 70vh;
  display: flex;
  flex-direction: column;
  background: var(--ds-bg-card);
  border: 1px solid var(--ds-border-strong);
  border-radius: var(--ds-radius-lg);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
  font-size: var(--ds-font-md);
  color: var(--ds-text-primary);
  overflow: hidden;
}
.notifications-popover-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-2);
  padding: var(--ds-space-3) var(--ds-space-4);
  border-bottom: 1px solid var(--ds-border);
  flex-shrink: 0;
}
.notifications-popover-header h3 {
  margin: 0;
  font-size: var(--ds-font-lg);
}
.notifications-popover-body {
  overflow-y: auto;
  padding: var(--ds-space-2) var(--ds-space-4);
}
.notifications-popover-footer {
  padding: var(--ds-space-3) var(--ds-space-4);
  border-top: 1px solid var(--ds-border);
  text-align: center;
  flex-shrink: 0;
}
.notifications-popover-footer a {
  color: var(--ds-info-text);
  text-decoration: none;
  font-size: var(--ds-font-sm);
}
.notifications-popover-footer a:hover {
  text-decoration: underline;
}
.notif-group {
  padding: var(--ds-space-2) 0;
}
.notif-group + .notif-group {
  border-top: 1px solid var(--ds-border);
}
.notif-group-title {
  font-size: var(--ds-font-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ds-text-muted);
  margin-bottom: var(--ds-space-1);
}
.notif-row {
  cursor: pointer;
}
.notif-row:hover {
  background: var(--ds-bg-inset);
}
.ds-source-area-icon {
  flex-shrink: 0;
  color: var(--ds-text-secondary);
}

/* ---- Content (CMS) panel: reuses .brandkit-item/.brandkit-field/.brandkit-detail-back
   for the type list + field-editor form (see content.js), plus its own badge styling below.
   This is the OLD, now-read-only builder-panel (public/content.js) — the editable field-row
   UI lives in public/os/content.js, styled in css/content.css, not here. ---- */
.content-type-fields-summary {
  font-size: 11px;
  color: #8a92a6;
  margin: 4px 0 8px;
}
.content-field-type-tag {
  display: inline-block;
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: #8a92a6;
  background: #1e212a;
  border-radius: 3px;
  padding: 1px 4px;
  margin-right: 6px;
}

/* CMS Round 3a — this panel became read-only; the link out to the canonical, writable OS
   surface (public/os/content.js). Persistent across every view in this panel (see
   content.js's manageLinkEl). */
.content-manage-link-wrap {
  margin-bottom: 10px;
}
.content-manage-link {
  background: none;
  border: none;
  color: #8ab4ff;
  font-size: 12px;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
}
.content-manage-link:hover {
  color: #a9c6ff;
}

.content-entries-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.content-entry-item .brandkit-item-head {
  justify-content: flex-start;
  gap: 8px;
}
.content-entry-updated {
  font-size: 10px;
  color: #6b7080;
}
.content-entry-preview {
  font-size: 12px;
  color: #c4c8d4;
  margin: 6px 0 8px;
  word-break: break-word;
}

/* Draft/Published badge — same visual language as .contrast-badge (fail vs AA/AAA). */
.content-badge {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 2px 6px;
  border-radius: 4px;
}
.content-badge.draft {
  background: #3a331e;
  color: #e0c07e;
}
.content-badge.published {
  background: #1a3a26;
  color: #7ee0a3;
}

/* Generic right-side drawer — a fixed panel over the whole app, since the sidebar itself
   is too narrow for a multi-field form (unlike the popover's small, anchored-near-a-
   button footprint). Shared by the Content entry editor (content.js) and Publish
   (publish.js) — kept generic on purpose rather than per-feature-prefixed. */
.drawer-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: var(--ds-z-drawer);
}
.drawer-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 360px;
  max-width: 90vw;
  background: var(--ds-bg-card);
  border-left: 1px solid var(--ds-border-strong);
  box-shadow: -8px 0 30px rgba(0, 0, 0, 0.5);
  z-index: var(--ds-z-drawer-top);
  display: flex;
  flex-direction: column;
}
/* Drawer Containment — designSystem.js's openDrawer(opts.container) modifier: a drawer
   opened from WITHIN another floating panel (the messages overlay's own drawers — New
   conversation/Create channel/AI summary/Forward/Pinned messages/Create task from message/
   Conversation settings) docks INSIDE that panel's own bounds instead of the true viewport
   edge. Requires the container to be `position: relative` + `overflow: hidden` (already
   true of .messages-overlay-panel) so `position: absolute` here is actually clipped to it —
   every other rule above (colors/borders/width/z-index) is unchanged, only the positioning
   scheme flips from viewport-relative to container-relative. */
.drawer-backdrop.contained,
.drawer-panel.contained {
  position: absolute;
}
/* Drawer Width — designSystem.js's openDrawer(opts.wide). The 360px default is exactly the
   width of .chat-panel (the sidebar), so a dense control surface that moved OUT of the sidebar
   into a drawer would otherwise gain no room at all. max-width keeps the same 90vw ceiling the
   base rule sets, so this can never crowd out the preview on a narrow viewport. */
.drawer-panel-wide {
  width: 460px;
}
/* Drawer Modality — designSystem.js's openDrawer(opts.modal === false). The backdrop element
   still exists (the drawer stack indexes on it), but is transparent and click-through, so the
   page behind stays fully interactive. Built for the visual editor's element-edit drawer,
   which stays open while the user keeps clicking elements on the preview canvas behind it —
   a normal modal backdrop would swallow exactly those clicks. Every other drawer is modal. */
.drawer-backdrop-nonmodal {
  background: transparent;
  pointer-events: none;
}
/* Drawer Stacking — designSystem.js's openDrawer(opts.stack): a picker drawer
   (openBusinessMediaPicker/openPartyPicker) opened from WITHIN an already-open drawer stacks
   on top of it instead of replacing it. The layer below gets this modifier: shifted further
   from the edge so a sliver stays visible, dimmed, and inert — so the caller sees the context
   they're picking for (e.g. the product they're adding an image to) without being able to
   interact with it until the drawer on top closes. */
.drawer-panel-stacked-back {
  right: 28px;
  opacity: 0.55;
  pointer-events: none;
}
.drawer-backdrop-stacked-back {
  pointer-events: none;
}
.drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--ds-border);
  font-size: 13px;
  font-weight: 500;
}
.drawer-close {
  background: transparent;
  border: none;
  color: var(--ds-text-secondary);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  padding: 0;
}
.drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 14px;
  color: var(--ds-text-primary);
}
.drawer-body textarea {
  width: 100%;
  box-sizing: border-box;
  background: var(--ds-bg-inset);
  color: var(--ds-text-primary);
  border: 1px solid var(--ds-border-strong);
  border-radius: 6px;
  padding: 6px 8px;
  font-size: 13px;
  font-family: inherit;
  resize: vertical;
}
.drawer-body input[type="text"],
.drawer-body input[type="url"],
.drawer-body input[type="password"] {
  width: 100%;
  box-sizing: border-box;
  background: var(--ds-bg-inset);
  color: var(--ds-text-primary);
  border: 1px solid var(--ds-border-strong);
  border-radius: 6px;
  padding: 6px 8px;
  font-size: 13px;
}
.drawer-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-top: 1px solid var(--ds-border);
}

/* Feedback Button (V1) — the one local toast in the main document (see public/feedback.js's
   own header for why every OTHER toast in this codebase is a small local one-off rather than
   a shared component). Bottom-right, success-tinted, uses the same design tokens the rest of
   the app already themes with, so it tracks light/dark automatically. */
.feedback-toast {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: var(--ds-z-toast);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-radius: 8px;
  background: var(--ds-success-bg);
  color: var(--ds-success-text);
  font-size: 13px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
}

.tasks-feedback-filter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0;
  font-size: 13px;
  color: var(--ds-text-secondary, #aab0c0);
}

.feedback-toast-link {
  background: none;
  border: none;
  color: inherit;
  text-decoration: underline;
  cursor: pointer;
  font: inherit;
  padding: 0;
}

.content-media-current {
  margin-bottom: 6px;
}
.content-media-thumb {
  width: 52px;
  height: 52px;
  object-fit: cover;
  border-radius: 4px;
  display: block;
}
.content-media-thumb-pick {
  cursor: pointer;
  border: 2px solid transparent;
}
.content-media-thumb-pick:hover {
  border-color: #4a6cf7;
}
.content-media-grid {
  display: grid;
  grid-template-columns: repeat(4, 52px);
  gap: 6px;
  max-height: 180px;
  overflow-y: auto;
  margin-top: 8px;
}

/* ---- Content Round 2: read-only block-document preview (contentBlocksPreview.js) — no
   editing controls, see that file's header. Reuses the surrounding drawer's own type styles
   for headings/paragraphs/etc.; these three classes are only for the non-content notes
   (component/unresolved-reference/unhandled) that have no natural HTML element of their own. */
.content-blocks-preview {
  max-height: 320px;
  overflow-y: auto;
  border: 1px solid #2c3040;
  border-radius: 6px;
  padding: 10px 12px;
  font-size: 13px;
  color: #c4c8d4;
}
.content-blocks-preview img.content-media-thumb {
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 160px;
}
.content-block-note {
  font-size: 11px;
  font-style: italic;
  color: #8a92a6;
  border-left: 2px solid #2c3040;
  padding-left: 8px;
  margin: 6px 0;
}
.content-block-unresolved {
  color: #d9a441;
  border-left-color: #d9a441;
}
.content-block-unhandled {
  color: #ff9a9a;
  border-left-color: #ff9a9a;
}

/* ---- Publish (publish.js): deploy status badge — distinct color mapping from the
   content-entry Draft/Published badge (pending/building/failed all have real meaning
   here, not just a binary state). ---- */
.deploy-status-badge {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 2px 6px;
  border-radius: 4px;
}
.deploy-status-badge.live {
  background: #1a3a26;
  color: #7ee0a3;
}
.deploy-status-badge.pending,
.deploy-status-badge.building {
  background: #3a331e;
  color: #e0c07e;
}
.deploy-status-badge.failed {
  background: #3a1e22;
  color: #ff9a9a;
}
