/* chatdlc-next custom overrides on top of the Data Link "Tactical HUD" theme
   that lives in /static/css/training/. Loaded AFTER training/* and AFTER
   Tailwind so this file wins on conflicts. */

:root {
  color-scheme: dark;
}

[data-theme="light"] {
  color-scheme: light;
}

/* Theme-toggle icon swap. Default (no [data-theme] or data-theme="dark"):
   show the moon (click to go light). [data-theme="light"]: show the sun
   (click to go back to dark). The button itself inherits .btn-icon size
   from layout.css so it lines up with the logout button. */
.theme-toggle .theme-icon-sun { display: none; }
.theme-toggle .theme-icon-moon { display: inline-block; }
[data-theme="light"] .theme-toggle .theme-icon-sun { display: inline-block; }
[data-theme="light"] .theme-toggle .theme-icon-moon { display: none; }

/* Light-mode polish — only applied when [data-theme="light"] is active.
   Most of the chat surface picks up the new tokens automatically through
   the Tailwind palette remap, but a few spots use literal classes that
   stayed legible in dark mode but need an override on white. */
[data-theme="light"] body {
  background: var(--bg-base);
}
[data-theme="light"] .chat-body {
  color: var(--text-primary);
}
[data-theme="light"] .chat-user {
  color: var(--text-primary);
}
/* ----- Message surfaces (ui-v2) -----
   User turns: compact right-aligned card. Assistant turns: borderless
   full-width prose delimited by the avatar row + a subtle separator —
   the box-free modern chat pattern. Theme-aware via tokens, so no
   per-theme override rules needed. */
.msg-user {
  background: var(--accent-subtle);
  border: 1px solid transparent;
  border-radius: var(--radius-2xl);
  border-bottom-right-radius: var(--radius-md);
  padding: 0.875rem 1.25rem;
  box-shadow: var(--shadow-sm);
}
[data-theme="light"] .msg-user {
  background: var(--bg-elevated);
  border-color: var(--border-subtle);
}
.msg-assistant {
  background: none;
  border: 0;
  padding: 0 0.25rem;
}
.msg-assistant:not(:last-child) {
  border-bottom: 1px solid var(--border-subtle);
  padding-bottom: 1.4rem;
}

/* ----- ui-v2 shared components ----- */

/* Rendered mermaid diagrams in chat — centered, scrollable when wide. */
.mermaid-rendered {
  margin: 0.7rem 0;
  padding: 0.7rem;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow-x: auto;
  display: flex;
  justify-content: center;
}
.mermaid-rendered svg { max-width: 100%; height: auto; }

/* Deep-link target flash (search results / saved links). */
.msg-highlight {
  animation: msg-highlight-fade 2.5s var(--ease-default) both;
}
@keyframes msg-highlight-fade {
  0%, 30% { box-shadow: 0 0 0 2px var(--accent); border-radius: var(--radius-md); }
  100%    { box-shadow: 0 0 0 2px transparent; }
}

/* Live + persisted thinking panel (Claude-style). Readable muted prose,
   NOT 11px green mono. Max-height keeps long reasoning from pushing the
   real answer below the fold. */
.thinking-live { font-size: var(--text-sm); }
.thinking-live-summary {
  cursor: pointer;
  user-select: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
  font-size: 12px;
  transition: color var(--duration-fast) var(--ease-default);
}
.thinking-live-summary:hover { color: var(--text-secondary); }
.thinking-live[open] .thinking-live-summary { margin-bottom: 4px; }
.thinking-live-prose {
  color: var(--text-muted);
  font-style: italic;
  font-size: 13px;
  line-height: 1.55;
  white-space: pre-wrap;
  word-wrap: break-word;
  max-height: 260px;
  overflow-y: auto;
  padding: 6px 10px;
  border-left: 2px solid var(--border-subtle);
  margin-left: 4px;
}
/* Soft pulse on the live marker while the model is reasoning. */
.is-thinking .thinking-live-pulse {
  display: inline-block;
  animation: thinking-pulse 1.6s ease-in-out infinite;
  color: var(--accent);
}
@keyframes thinking-pulse {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .is-thinking .thinking-live-pulse { animation: none; }
}

/* Solid-accent primary button — the ONE green-filled element per pane
   (+new chat in the sidebar, send in the composer). Explicit border
   (reset.css zeroes button borders). */
.btn-accent {
  background: var(--accent);
  color: var(--text-inverse);
  border: 1px solid transparent;
}
.btn-accent:hover:not(:disabled) {
  background: var(--accent-bright);
}
/* Light mode: black primary button per Jeff's black-on-white minimal
   direction (matches the pre-ui-v2 black send pill he signed off). */
[data-theme="light"] .btn-accent {
  background: #1c1c1f;
  color: #ffffff;
}
[data-theme="light"] .btn-accent:hover:not(:disabled) {
  background: #000000;
}

/* Active chat in the sidebar history — accent bar + subtle fill instead
   of a bordered box. */
.chat-item-active {
  border-color: transparent;
  border-left: 2px solid var(--accent);
  background: var(--accent-subtle);
  color: var(--accent);
}

/* Composer shell — soft 20px radius, accent glow on focus. */
.composer-shell {
  background: rgb(var(--bg-surface-rgb) / 0.6);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--duration-normal) var(--ease-default),
              box-shadow var(--duration-normal) var(--ease-default);
}
.composer-shell:focus-within {
  border-color: var(--accent);
  box-shadow: var(--shadow-accent-sm);
}

/* Hero headline + suggestion cards (welcome state). */
.hero-headline {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-display);
  color: var(--text-primary);
}
.suggestion-card {
  background: rgb(var(--bg-elevated-rgb) / 0.55);
  border: 1px solid var(--border-subtle);
  transition: transform var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out);
}
.suggestion-card:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

/* Welcome-screen quick-prompts hint. Muted green wink in dark; black in
   light per Matt (green-on-white read as decoration, not text). */
.hero-hint { color: rgb(var(--text-muted-rgb) / 0.9); }
.hero-hint:hover { color: var(--accent); }
[data-theme="light"] .hero-hint { color: var(--text-primary); }
[data-theme="light"] .hero-hint:hover { color: var(--accent-dim); }

/* Light-mode chat sidebar — the dark-tinted Tailwind classes resolve to a
   murky mid-gray on white. Clean light panel + readable history states. */
[data-theme="light"] .main-chat aside {
  background: var(--bg-elevated) !important;
  border-color: var(--border-subtle) !important;
}
[data-theme="light"] .chat-item-active {
  background: rgba(0, 165, 84, 0.10);
  color: var(--text-primary);
}
[data-theme="light"] .main-chat aside a.border-transparent {
  color: var(--text-secondary);
}
[data-theme="light"] .main-chat aside a.border-transparent:hover {
  color: var(--text-primary);
  background: rgba(0, 0, 0, 0.05);
}

/* Sidebar "options" disclosure arrow rotates when open. */
details[open] > summary .sidebar-options-arrow {
  display: inline-block;
  transform: rotate(90deg);
}
.sidebar-options-arrow {
  transition: transform var(--duration-fast) var(--ease-default);
}

/* Category tag on suggestion cards — quiet pill instead of raw cyan mono. */
.suggestion-tag {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.03em;
  padding: 1px 8px;
  border-radius: var(--radius-full);
  color: var(--text-secondary);
  background: rgb(var(--text-muted-rgb) / 0.12);
  border: 1px solid var(--border-subtle);
}
/* Code block backgrounds — Tailwind's `bg-gray-950` resolves to white in
   light mode, which makes <pre> blocks merge into the page. Force a
   subtle gray instead. */
[data-theme="light"] pre {
  background-color: #f3f3f0 !important;
  color: var(--text-primary);
  border: 1px solid var(--border-subtle);
}
[data-theme="light"] code {
  background-color: rgba(0, 0, 0, 0.04);
  color: var(--text-primary);
  padding: 1px 4px;
  border-radius: 3px;
}
[data-theme="light"] pre code {
  background: transparent;
  padding: 0;
}
/* Inputs and selects — make sure focus rings + borders are visible on white. */
[data-theme="light"] input[type="text"],
[data-theme="light"] input[type="email"],
[data-theme="light"] input[type="password"],
[data-theme="light"] input[type="search"],
[data-theme="light"] textarea,
[data-theme="light"] select {
  background-color: #ffffff;
  color: var(--text-primary);
  border-color: var(--border-default);
}
[data-theme="light"] textarea::placeholder,
[data-theme="light"] input::placeholder {
  color: var(--text-muted);
  opacity: 1;
}
/* `text-green-200` is stock Tailwind (#bbf7d0) — fine on dark, washed out
   on white. Used by the composer textarea, send button, and a couple of
   message-body divs. Force the primary text color in light mode so they
   stay readable. */
[data-theme="light"] .text-green-200,
[data-theme="light"] textarea.text-green-200 {
  color: var(--text-primary) !important;
}
/* Composer footer icons (📎 / mic / slash / lightning) — force pure
   black in light mode regardless of the text-green-* class on the button.
   At 14px SVG-stroke size the prior #3a3a3f looked tinted on the
   composer's mid-gray fill; #1c1c1f reads cleanly. Active mic
   (.voice-mic-active) keeps its red. */
[data-theme="light"] form button.text-green-600 {
  color: #1c1c1f !important;
}
[data-theme="light"] form button.text-green-600:hover {
  background-color: rgba(0, 0, 0, 0.06) !important;
  color: #000000 !important;
}
[data-theme="light"] form button.voice-mic-active {
  color: #d4313a !important;
}

/* Sidebar in light mode rides on top of the glass-panel mesh which gives
   a faint green tint to the background. Keep section labels at primary
   weight so they don't read faded. */
[data-theme="light"] aside .uppercase.tracking-wider {
  color: var(--text-primary);
}

/* Welcome / hero screen — the headline + subtitle + suggestion chip titles
   were all green shades. Convert to black-on-white. The cyan tag labels on
   suggestion chips stay as a small accent (Jeff's "more black everywhere
   else" implies single-color text dominance, not zero color anywhere). */
/* Hero name highlight inside the headline keeps a single accent touch in
   dark; in light it goes primary per Jeff. */
[data-theme="light"] .hero-headline .text-green-400 {
  color: var(--text-primary) !important;
}
[data-theme="light"] p.text-green-700\/80 {
  color: var(--text-secondary) !important;
}
[data-theme="light"] button .text-green-300 {
  color: var(--text-primary) !important;
}

/* Toggle switches — in light mode the ON state was green tinted, which
   re-introduces the green Jeff just asked us to strip. Flip ON-state to
   black: dark-gray fill + black thumb. OFF-state already neutral. */
[data-theme="light"] .dl-switch.is-on {
  background: rgba(0, 0, 0, 0.15);
  border-color: #1c1c1f;
}
[data-theme="light"] .dl-switch.is-on .dl-switch-thumb {
  background: #1c1c1f;
}

/* Header chrome — keep light mode neutral where layout.css uses --accent.
   (.header-title override removed 2026-06-10 — replaced by the brand
   lockup, whose wordmark is text-primary already; DLC keeps the accent
   as the single brand touch, which Jeff's "minimal" still allows.) */
[data-theme="light"] .avatar-initials {
  color: var(--text-primary);
}

/* "19 tools" popover button (top-right of chat pane) — uses Tailwind
   text-green-500 + border-green-900/50. Force black/neutral in light mode. */
[data-theme="light"] button.text-green-500[class*="border-green-900"] {
  color: var(--text-primary) !important;
  border-color: rgba(0, 0, 0, 0.2) !important;
}
[data-theme="light"] button.text-green-500[class*="border-green-900"]:hover {
  background-color: rgba(0, 0, 0, 0.04) !important;
  border-color: rgba(0, 0, 0, 0.4) !important;
}
[data-theme="light"] button.text-green-500[class*="border-green-900"][class*="bg-green-900/30"],
[data-theme="light"] button.text-green-500[class*="border-green-900"].bg-green-900\/30 {
  background-color: rgba(0, 0, 0, 0.06) !important;
  border-color: rgba(0, 0, 0, 0.4) !important;
}

/* ===== Admin + saved pages — light-mode polish =====
   These pages render heavy use of stock Tailwind cyan/yellow/red shades that
   aren't theme-aware (they bypass the rgb-channel remap). On white those
   read as glowing/saturated. Neutralize per Jeff's "black-on-white minimal"
   rule: cyan badges go neutral, warning/danger get WCAG-friendly hues, and
   the bg-black/40 pre blocks soften to a light panel. Dark mode unchanged. */

/* Cyan badges + tool-call chips. Keep them visually distinct from body
   text (they mean "tool call" or "action label") but legible on white —
   use --color-info (#0773aa) instead of stock cyan. Covers chat-page
   tool chips, admin audit action column, group-name pills, CHATDLC
   header label. */
[data-theme="light"] .text-cyan-300,
[data-theme="light"] .text-cyan-400,
[data-theme="light"] .text-cyan-500,
[data-theme="light"] [class*="text-cyan-300/"],
[data-theme="light"] [class*="text-cyan-400/"] {
  color: var(--color-info) !important;
}
[data-theme="light"] [class*="border-cyan-900"],
[data-theme="light"] [class*="border-cyan-700"] {
  border-color: rgba(7, 115, 170, 0.4) !important;
}
[data-theme="light"] [class*="bg-cyan-900"],
[data-theme="light"] [class*="bg-cyan-950"] {
  background-color: var(--color-info-dim) !important;
}

/* Yellow — regression banners, password-awaiting badge, "thinking" pre
   blocks on admin chat detail. Use --color-warning (a darker amber) so
   "warning" semantics survive on white without the neon glow. */
[data-theme="light"] .text-yellow-300,
[data-theme="light"] .text-yellow-400,
[data-theme="light"] .text-yellow-500,
[data-theme="light"] [class*="text-yellow-500/"],
[data-theme="light"] [class*="text-yellow-600/"],
[data-theme="light"] [class*="text-yellow-300/"] {
  color: var(--color-warning) !important;
}
[data-theme="light"] [class*="border-yellow-900"],
[data-theme="light"] [class*="border-yellow-700"] {
  border-color: rgba(182, 114, 0, 0.4) !important;
}
[data-theme="light"] [class*="bg-yellow-900"],
[data-theme="light"] [class*="bg-yellow-950"] {
  background-color: var(--color-warning-dim) !important;
}

/* Red — deleted-state pills, error banners on admin/new-user. Use
   --color-danger so destructive semantics stay visible. */
[data-theme="light"] .text-red-300,
[data-theme="light"] .text-red-400 {
  color: var(--color-danger) !important;
}
[data-theme="light"] [class*="border-red-900"],
[data-theme="light"] [class*="border-red-800"] {
  border-color: rgba(196, 36, 36, 0.4) !important;
}
[data-theme="light"] [class*="bg-red-900"],
[data-theme="light"] [class*="bg-red-950"] {
  background-color: var(--color-danger-dim) !important;
}

/* `bg-black/40` thinking + tool-call <pre> blocks on admin chat detail —
   40% black on white renders as gray and competes with surrounding panels.
   Soften to the standard elevated panel surface. */
[data-theme="light"] .bg-black\/40 {
  background-color: var(--bg-elevated) !important;
}

/* `bg-black` literal — the new-user form inputs use it as a backdrop.
   The generic input-bg override above doesn't catch the utility class
   directly, so flip it to white so the input doesn't render as a black
   slab on a white form panel. */
[data-theme="light"] input.bg-black {
  background-color: #ffffff !important;
}

/* Hover-row tinting on admin tables — `hover:bg-green-900/10` resolves to
   a near-invisible warm-white in light mode. Replace with a faint neutral
   so admins can still track which row their cursor is on. */
[data-theme="light"] tbody tr[class*="hover:bg-green-900"]:hover {
  background-color: rgba(0, 0, 0, 0.04) !important;
}

/* ----- Admin + saved panels: solid white instead of glass ----- */
/* `bg-gray-900/30`, `bg-gray-900/60`, `bg-gray-950/50` resolve via the
   rgb-channel remap to translucent white, which renders gray over the
   glass-panel chrome that admin/saved keep (chat is full-bleed). Force
   solid white for these specific div + form + thead container shapes.
   Excludes .msg-enter (chat bubbles, handled above), aside (chat sidebar),
   and form.bg-gray-900\/40 (composer, handled above). */
[data-theme="light"] div.bg-gray-900\/30:not(.msg-enter),
[data-theme="light"] div.bg-gray-900\/60:not(.msg-enter),
[data-theme="light"] div.bg-gray-950\/50:not(.msg-enter),
[data-theme="light"] form.bg-gray-900\/30,
[data-theme="light"] thead.bg-gray-900\/60 {
  background-color: #ffffff !important;
}

/* ----- Admin + saved page text: green → primary black ----- */
/* Tables and h1 page titles inherited green from dark mode but admin
   surfaces don't carry brand-green semantics (per Jeff's "more black
   everywhere else"). Scoped to <table> descendants and <h1> so chat-page
   sidebar/composer green accents are unaffected. */
[data-theme="light"] table[class*="text-green-"],
[data-theme="light"] thead[class*="text-green-"],
[data-theme="light"] tbody[class*="text-green-"],
[data-theme="light"] table [class*="text-green-"] {
  color: var(--text-primary) !important;
}
[data-theme="light"] h1[class*="text-green-"] {
  color: var(--text-primary) !important;
}

/* Admin/saved page header nav strip: `<div class="text-green-700/80">`
   wrapping hover-text-green-400 anchors. The wrapping div sets the
   default color via .text-green-700/80 — that's already routed through
   --text-muted-rgb so it's gray (fine). The hover state goes accent
   green; flip to primary so hover reads as a black underline-ish. */
[data-theme="light"] div.text-green-700\/80 a[class*="hover:text-green"]:hover {
  color: var(--text-primary) !important;
}

/* `<code>` inside admin pages — admin_chats has a path span styled
   `bg-gray-900 px-1`. With the gray remap that's white-on-white. Bump
   to a faint neutral. */
[data-theme="light"] code.bg-gray-900 {
  background-color: rgba(0, 0, 0, 0.05) !important;
  color: var(--text-primary) !important;
}

/* ===== Structural scope: non-chat pages get full black-on-white =====
   .main-inner.chat-fullbleed marks the chat page (set in chat.html via
   the main_extra_class block). Every other page (admin/*, saved, login)
   gets plain .main-inner, so :not(.chat-fullbleed) cleanly fences them
   off. Inside those pages we go aggressive: every green-* text utility
   → primary text, every translucent gray panel → solid white. The chat
   page handles its own brand-green placement so it's unaffected. */

[data-theme="light"] .main-inner:not(.chat-fullbleed) [class*="text-green-"] {
  color: var(--text-primary) !important;
}

[data-theme="light"] .main-inner:not(.chat-fullbleed) [class*="bg-gray-900\/30"],
[data-theme="light"] .main-inner:not(.chat-fullbleed) [class*="bg-gray-900\/40"],
[data-theme="light"] .main-inner:not(.chat-fullbleed) [class*="bg-gray-900\/50"],
[data-theme="light"] .main-inner:not(.chat-fullbleed) [class*="bg-gray-900\/60"],
[data-theme="light"] .main-inner:not(.chat-fullbleed) [class*="bg-gray-950\/50"],
[data-theme="light"] .main-inner:not(.chat-fullbleed) [class*="bg-gray-950\/60"] {
  background-color: #ffffff !important;
}

/* The bare `bg-gray-900` (no opacity modifier) — input backgrounds and
   the tools popover. On non-chat pages those are inputs that already get
   white from the input override, but the ::before/after layers sometimes
   peek through. Keep them white explicitly. */
[data-theme="light"] .main-inner:not(.chat-fullbleed) input.bg-gray-900,
[data-theme="light"] .main-inner:not(.chat-fullbleed) select.bg-gray-900 {
  background-color: #ffffff !important;
}

/* Submit buttons (filter / create / save / apply on admin pages) match
   the pagination "next →" / "← prev" anchors: thin gray outline, black
   text, transparent bg, faint neutral hover. Scoped to non-chat pages so
   the chat composer's solid-black send button is unaffected. */
/* training/reset.css zeroes `button { border: none }` so Tailwind's
   .border utility only restores width, not style. Re-assert solid 1px
   on every button that has the .border utility on non-chat pages so all
   admin/saved buttons (filter, create, save, apply, reset-password,
   cancel) paint their outlines. Color stays whatever the per-button
   Tailwind utility resolves to. */
[data-theme="light"] .main-inner:not(.chat-fullbleed) button.border {
  border-style: solid !important;
  border-width: 1px !important;
}

/* Submit buttons (filter / create / save / apply on admin pages) — green
   action style routed to outlined-neutral so they match the pagination
   anchor look. Color/bg only; width/style is handled by the rule above. */
[data-theme="light"] .main-inner:not(.chat-fullbleed) button[type="submit"][class*="bg-green-900"],
[data-theme="light"] .main-inner:not(.chat-fullbleed) button[type="submit"][class*="bg-green-900"][class*="text-green-"] {
  background-color: transparent !important;
  color: var(--text-primary) !important;
  border-color: var(--border-default) !important;
}
[data-theme="light"] .main-inner:not(.chat-fullbleed) button[type="submit"][class*="bg-green-900"]:hover {
  background-color: rgba(0, 0, 0, 0.04) !important;
  border-color: var(--border-strong) !important;
}

/* Chat goes full-bleed: kill the .main-inner glass-panel chrome that
   Jeremiah's portal uses for centered views. The chat page sets
   `chat-fullbleed` on .main-inner via the `main_extra_class` block.
   Login + admin pages keep the framed glass panel default. */
.main-inner.chat-fullbleed {
  max-width: none;
  margin: 0;
  padding: var(--space-3) var(--space-3);
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  height: 100%;
}

/* training/layout.css gives `.main` overflow-y:auto so admin/saved/login
   pages can scroll when content overflows. On the chat page that creates
   a SECOND scroll container outside #messages — when Gemma streams, the
   outer .main scrolls instead of #messages, and our scrollToBottom()
   targets #messages so the viewport never follows. Make #messages the
   sole scroller on chat by suppressing .main's overflow when the
   fullbleed layout is active.
   Originally used :has(> .main-inner.chat-fullbleed) but Safari (esp.
   older macOS) has known :has() quirks that left Jeff with two stacked
   scrollers. Switched 2026-05-01 to a direct .main-chat class set on
   <main> via base.html's {% block main_class %} — bulletproof across
   browsers, no :has() involved. */
.main.main-chat {
  overflow: hidden;
}
/* Belt-and-braces: keep the :has() form too so a future page that sets
   .chat-fullbleed without main-chat (e.g. an embedded iframe variant)
   still gets the right behavior on browsers that DO support :has(). */
.main:has(> .main-inner.chat-fullbleed) {
  overflow: hidden;
}

/* ----- Mobile / narrow-viewport sweep -----
   chatdlc-next is laptop-first (sidebar + chat pane side-by-side),
   but field techs on phones need it to be at least usable. Threshold
   set at 768px — anything narrower compresses the chrome.
   The sidebar becomes a drawer toggled by a hamburger button (added
   to the header). User-pill collapses to just the avatar. Composer
   shrinks the kb hints and keeps the essentials. */
@media (max-width: 768px) {
  .header { padding: 0 12px; gap: 4px; }
  .header-nav { gap: 0; }
  .header-nav .nav-item { padding: 6px 8px; font-size: 12px; }
  .header-user-info { display: none; }
  .header-avatar { width: 28px; height: 28px; }
  .header-actions .btn-icon { width: 32px; height: 32px; }

  /* Chat-fullbleed sidebar slides off-screen by default; a checkbox
     controlled hamburger toggles it in. We flip the layout flex-dir
     to column-reverse so the composer is at the bottom and messages
     scroll above it (same arrangement, just stacked). */
  .main-inner.chat-fullbleed { padding: 4px; }

  .mobile-sidebar-trigger { display: inline-flex; }

  /* The chat shell (.h-full.flex.gap-3) becomes a stacked layout. */
  .chat-fullbleed > div.h-full {
    gap: 0;
    position: relative;
  }
  /* Sidebar slides in from the left over the chat pane. Toggle via
     `data-sidebar-open=true` set on the parent by JS. */
  .chat-fullbleed > div.h-full > aside {
    position: absolute;
    inset: 0 auto 0 0;
    z-index: 50;
    width: 80%;
    max-width: 320px;
    transform: translateX(-105%);
    transition: transform 200ms var(--ease-default);
    box-shadow: var(--shadow-lg);
  }
  .chat-fullbleed > div.h-full[data-sidebar-open="true"] > aside {
    transform: translateX(0);
  }
  /* Backdrop when sidebar is open */
  .chat-fullbleed > div.h-full[data-sidebar-open="true"]::before {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.6);
    z-index: 40;
  }

}
/* Hamburger trigger lives in the chat header — always rendered, hidden
   on desktop via display: none here, shown on mobile via media query above. */
.mobile-sidebar-trigger { display: none; }

/* Artifacts: copy button on code blocks + download/sort on tables */
.artifact-copy-btn {
  position: absolute;
  top: 6px;
  right: 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 2px 8px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--duration-fast) var(--ease-default),
              color var(--duration-fast) var(--ease-default);
}
.chat-body pre:hover .artifact-copy-btn,
.artifact-copy-btn:focus { opacity: 1; }
.artifact-copy-btn:hover { color: var(--accent); }

/* Detected-language badge (set by enhanceArtifacts when hljs identifies
   the block). Pre gets breathing room up top when a badge is present. */
.artifact-code-lang {
  position: absolute;
  top: 6px;
  left: 10px;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: lowercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  user-select: none;
}
.chat-body pre[data-lang] {
  padding-top: 1.7rem;
  background: var(--bg-base);
}
[data-theme="light"] .chat-body pre[data-lang] {
  background: #f6f8fa;
}

/* highlight.js theme — token-driven so it flips with [data-theme].
   Covers the classes hljs's common-language bundle actually emits. */
.hljs { color: var(--text-primary); background: transparent; }
.hljs-keyword, .hljs-selector-tag, .hljs-literal, .hljs-built_in,
.hljs-type, .hljs-meta { color: var(--code-keyword); }
.hljs-string, .hljs-regexp, .hljs-template-string, .hljs-addition,
.hljs-quote { color: var(--code-string); }
.hljs-number, .hljs-symbol, .hljs-bullet, .hljs-link { color: var(--code-number); }
.hljs-comment, .hljs-deletion { color: var(--code-comment); font-style: italic; }
.hljs-title, .hljs-section, .hljs-name,
.hljs-function .hljs-title, .hljs-title.function_, .hljs-title.class_ { color: var(--code-title); }
.hljs-attr, .hljs-attribute, .hljs-variable, .hljs-template-variable,
.hljs-selector-attr, .hljs-selector-class, .hljs-selector-id,
.hljs-params { color: var(--code-attr); }
.hljs-emphasis { font-style: italic; }
.hljs-strong { font-weight: 600; }

.artifact-table-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 4px;
  margin-bottom: -4px;
}
.artifact-table-actions button {
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 2px 8px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-default);
}
.artifact-table-actions button:hover { color: var(--accent); }
.chat-body table th:hover { color: var(--accent-bright); }

/* Compact pill toggle for sidebar controls. Native checkboxes inherit
   too much OS chrome (and Jeremiah's .toggle sets a 44px touch-min). */
.dl-switch {
  position: relative;
  display: inline-block;
  width: 28px;
  height: 14px;
  border-radius: 999px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  transition: background var(--duration-fast) var(--ease-default),
              border-color var(--duration-fast) var(--ease-default);
  flex-shrink: 0;
}
.dl-switch-thumb {
  position: absolute;
  top: 1px;
  left: 1px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--text-secondary);
  transition: transform var(--duration-fast) var(--ease-default),
              background var(--duration-fast) var(--ease-default);
}
.dl-switch.is-on {
  background: var(--accent-subtle);
  border-color: var(--accent);
}
.dl-switch.is-on .dl-switch-thumb {
  transform: translateX(14px);
  background: var(--accent);
}

/* Avatar inside the user pill — initials in a green-tinted circle. */
.header-avatar {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  background: var(--glass-avatar-bg, var(--accent-subtle));
  border: 1px solid var(--glass-avatar-border, var(--accent-dim));
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.avatar-initials {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--accent);
  letter-spacing: 0.5px;
}

/* ----- Rendered chat-message body (markdown -> HTML) -----
   Tactical-HUD palette: high-contrast white-ish prose, accent green for
   emphasis, muted dividers. Mono only for code. */
.chat-body {
  font-family: var(--font-body);
  font-size: 0.97rem;   /* ≈15.5px — helpdesk readability bump (ui-v2 ph6) */
  line-height: var(--leading-relaxed);
  color: var(--text-primary);
}
.chat-body > *:first-child { margin-top: 0; }
.chat-body > *:last-child  { margin-bottom: 0; }

.chat-body p { margin: 0.6rem 0; }

/* Bold is emphasis, not decoration — accent stays reserved for links and
   inline code. (Green bold everywhere was the top readability complaint.) */
.chat-body strong, .chat-body b {
  color: var(--text-primary);
  font-weight: 650;
}
.chat-body em, .chat-body i { font-style: italic; opacity: 0.95; }

.chat-body a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: rgba(0, 210, 106, 0.4);
  text-underline-offset: 2px;
}
.chat-body a:hover {
  color: var(--accent-bright);
  text-decoration-color: var(--accent);
}

.chat-body h1, .chat-body h2, .chat-body h3,
.chat-body h4, .chat-body h5, .chat-body h6 {
  font-family: var(--font-display);
  color: var(--text-primary);
  font-weight: 700;
  line-height: 1.2;
  margin: 1.1rem 0 0.5rem 0;
}
.chat-body h1 { font-size: 1.35rem; }
.chat-body h2 { font-size: 1.18rem; }
.chat-body h3 { font-size: 1.05rem; }
.chat-body h4, .chat-body h5, .chat-body h6 { font-size: 0.98rem; }

.chat-body ul, .chat-body ol {
  margin: 0.6rem 0;
  padding-left: 1.4rem;
}
.chat-body ul { list-style: disc; }
.chat-body ol { list-style: decimal; }
.chat-body li { margin: 0.2rem 0; }
.chat-body li::marker { color: var(--accent); }
.chat-body li > ul, .chat-body li > ol { margin: 0.2rem 0; }

.chat-body code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  background: var(--bg-elevated);
  color: var(--accent-bright);
  border: 1px solid var(--border-subtle);
  padding: 0.05em 0.35em;
  border-radius: var(--radius-sm);
}

.chat-body pre {
  margin: 0.7rem 0;
  padding: 0.7rem 0.9rem;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 0.84rem;
  line-height: 1.4;
  color: var(--text-primary);
}
.chat-body pre code {
  background: none;
  border: none;
  padding: 0;
  color: inherit;
  font-size: inherit;
}

.chat-body blockquote {
  margin: 0.7rem 0;
  padding: 0.2rem 0.9rem;
  border-left: 3px solid var(--accent-dim);
  color: var(--text-secondary);
  font-style: italic;
}

.chat-body hr {
  border: 0;
  height: 1px;
  background: var(--border-subtle);
  margin: 1rem 0;
}

.chat-body table {
  border-collapse: collapse;
  margin: 0.6rem 0;
  font-size: 0.85rem;
}
.chat-body th, .chat-body td {
  border: 1px solid var(--border-subtle);
  padding: 0.3rem 0.6rem;
  text-align: left;
}
.chat-body th {
  background: var(--bg-elevated);
  color: var(--accent);
  font-weight: 600;
}

/* User-typed messages stay plain (no markdown render). Body font —
   the right-aligned card already distinguishes them from assistant
   prose; mono hurt readability for longer questions. */
.chat-user {
  font-family: var(--font-body);
  font-size: 0.92rem;
  color: var(--text-primary);
  white-space: pre-wrap;
  word-wrap: break-word;
}

/* ----- Data Link "chatdlc" avatar -----
   Circular DL brand mark next to the assistant speaker label.
   The PNG itself is a square crop of the circular emblem on black —
   border-radius: 50% gives us the clean circle. Static when at rest;
   heartbeat pulse while the model is thinking (driven by .is-thinking
   on the parent). */
.dlc-avatar {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  /* SVG bubble mark on transparent bg — no circle crop needed (the old
     PNG was a square photo crop that wanted border-radius: 50%). */
  object-fit: contain;
}

@keyframes dlc-heartbeat {
  0%   { transform: scale(1);    filter: drop-shadow(0 0 0   rgba(140, 255, 180, 0)); }
  14%  { transform: scale(1.18); filter: drop-shadow(0 0 6px rgba(140, 255, 180, 0.55)); }
  28%  { transform: scale(1);    filter: drop-shadow(0 0 0   rgba(140, 255, 180, 0)); }
  42%  { transform: scale(1.18); filter: drop-shadow(0 0 6px rgba(140, 255, 180, 0.55)); }
  70%  { transform: scale(1);    filter: drop-shadow(0 0 0   rgba(140, 255, 180, 0)); }
  100% { transform: scale(1); }
}

.is-thinking .dlc-avatar {
  animation: dlc-heartbeat 1.5s ease-in-out infinite;
  transform-origin: center;
}

/* Respect reduced-motion preferences — fall back to a gentle opacity pulse */
@media (prefers-reduced-motion: reduce) {
  .is-thinking .dlc-avatar {
    animation: dlc-fade 2s ease-in-out infinite;
  }
}
@keyframes dlc-fade {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}

/* ----- Hero emblem (welcome screen) -----
   Big static DL emblem with a gentle ambient pulse so the empty state
   feels alive, not dead. */
.dlc-hero {
  animation: dlc-hero-glow 4s ease-in-out infinite;
  filter: drop-shadow(0 0 12px rgba(80, 220, 130, 0.25));
}

/* Hero brand mark (ui-v2) — soft radial pool of accent light behind the
   large SVG so the empty welcome canvas has a focal point. */
.hero-mark-wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
}
.hero-mark-wrap::before {
  content: "";
  position: absolute;
  inset: -55px;
  border-radius: 50%;
  background: radial-gradient(circle,
              rgb(var(--accent-rgb) / 0.13) 0%,
              rgb(var(--accent-rgb) / 0.05) 45%,
              transparent 70%);
  pointer-events: none;
}
[data-theme="light"] .hero-mark-wrap::before {
  background: radial-gradient(circle,
              rgb(var(--accent-rgb) / 0.07) 0%,
              transparent 65%);
}
@keyframes dlc-hero-glow {
  0%, 100% { filter: drop-shadow(0 0 12px rgba(80, 220, 130, 0.20)); }
  50%      { filter: drop-shadow(0 0 22px rgba(80, 220, 130, 0.45)); }
}

/* ----- Message entrance animation -----
   New bubbles slide up + fade in. Subtle, ~250ms. */
.msg-enter {
  animation: msg-enter 280ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes msg-enter {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ----- Tool-call pending: scanning glow -----
   The yellow chip in the streaming bubble while a tool is in flight
   gets a subtle scanline shimmer so it visibly pulses with activity. */
.tool-pending {
  position: relative;
  overflow: hidden;
}
.tool-pending::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(220, 200, 80, 0.25) 50%,
    transparent 100%
  );
  animation: tool-scan 1.4s ease-in-out infinite;
  pointer-events: none;
}
@keyframes tool-scan {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* Active mic — soft red pulse while dictation is recording. Pairs with
   .voice-mic-active applied via :class= when voiceListening is true. */
.voice-mic-active {
  box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.55);
  animation: voice-mic-pulse 1.4s ease-out infinite;
}
@keyframes voice-mic-pulse {
  0%   { box-shadow: 0 0 0 0   rgba(239, 68, 68, 0.55); }
  70%  { box-shadow: 0 0 0 8px rgba(239, 68, 68, 0);    }
  100% { box-shadow: 0 0 0 0   rgba(239, 68, 68, 0);    }
}

@media (prefers-reduced-motion: reduce) {
  .msg-enter, .dlc-hero, .tool-pending::after, .voice-mic-active {
    animation: none !important;
  }
  .suggestion-card, .suggestion-card:hover {
    transform: none !important;
    transition: none !important;
  }
}

/* ===== What's New dropdown (2026-05-19) ============================== */
/* Triggered by the version badge in the chat header. Scrollable panel
   anchored to the bottom-right of the trigger; fits the dark cyberpunk
   theme by default and adapts to [data-theme="light"]. */

.whats-new-trigger {
  background: transparent;
}

.whats-new-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: min(440px, calc(100vw - 32px));
  max-height: min(70vh, 600px);
  background: rgba(10, 20, 14, 0.97);
  border: 1px solid rgba(40, 110, 70, 0.55);
  border-radius: 8px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6),
              0 0 0 1px rgba(60, 200, 130, 0.12) inset;
  display: flex;
  flex-direction: column;
  z-index: 1000;
  overflow: hidden;
  font-size: 0.85rem;
}

[data-theme="light"] .whats-new-panel {
  background: #ffffff;
  border-color: rgba(30, 100, 60, 0.35);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15),
              0 0 0 1px rgba(30, 100, 60, 0.08) inset;
}

.whats-new-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border-bottom: 1px solid rgba(40, 110, 70, 0.35);
  background: linear-gradient(180deg,
              rgba(40, 110, 70, 0.18),
              rgba(40, 110, 70, 0.06));
  flex-shrink: 0;
}

[data-theme="light"] .whats-new-header {
  background: rgba(30, 100, 60, 0.06);
  border-bottom-color: rgba(30, 100, 60, 0.2);
}

.whats-new-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  color: rgb(120, 220, 160);
  font-weight: 600;
}

[data-theme="light"] .whats-new-title {
  color: rgb(20, 90, 50);
}

.whats-new-version {
  font-size: 0.72rem;
  color: rgba(120, 220, 160, 0.7);
  font-weight: 400;
  font-family: ui-monospace, "JetBrains Mono", monospace;
}

[data-theme="light"] .whats-new-version {
  color: rgba(20, 90, 50, 0.7);
}

.whats-new-close {
  background: transparent;
  border: none;
  color: rgba(180, 220, 200, 0.7);
  font-size: 1.2rem;
  line-height: 1;
  padding: 2px 8px;
  cursor: pointer;
  border-radius: 4px;
}

.whats-new-close:hover {
  background: rgba(40, 110, 70, 0.25);
  color: rgb(180, 220, 200);
}

[data-theme="light"] .whats-new-close {
  color: rgba(20, 60, 40, 0.6);
}

[data-theme="light"] .whats-new-close:hover {
  background: rgba(30, 100, 60, 0.12);
  color: rgb(20, 60, 40);
}

.whats-new-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 8px 14px;
}

.whats-new-section {
  margin-bottom: 14px;
}

/* Data-freshness panel — live system state at the top of the dropdown.
   Compact list, one row per data source, dot indicator for status. */
.whats-new-freshness-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.whats-new-freshness-row {
  display: grid;
  grid-template-columns: 14px 1fr auto auto;
  gap: 8px;
  align-items: baseline;
  padding: 4px 8px;
  font-size: 0.78rem;
  border-radius: 4px;
  background: rgba(20, 35, 25, 0.35);
}

[data-theme="light"] .whats-new-freshness-row {
  background: rgba(20, 90, 50, 0.05);
}

.whats-new-freshness-row[data-status="red"] {
  background: rgba(150, 30, 30, 0.18);
}
.whats-new-freshness-row[data-status="yellow"] {
  background: rgba(180, 140, 30, 0.12);
}

.whats-new-freshness-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: rgba(120, 120, 120, 0.55);
  align-self: center;
}
.whats-new-freshness-dot[data-status="green"]   { background: rgb(80, 200, 110); }
.whats-new-freshness-dot[data-status="yellow"]  { background: rgb(230, 190, 60); }
.whats-new-freshness-dot[data-status="red"]     { background: rgb(225, 90, 90); }
.whats-new-freshness-dot[data-status="unknown"] { background: rgba(150, 150, 150, 0.45); }

.whats-new-freshness-label {
  color: rgba(200, 230, 210, 0.9);
  font-weight: 500;
}
[data-theme="light"] .whats-new-freshness-label {
  color: rgba(25, 70, 45, 0.92);
}

.whats-new-freshness-age {
  color: rgba(160, 200, 175, 0.65);
  font-variant-numeric: tabular-nums;
  font-size: 0.74rem;
}
[data-theme="light"] .whats-new-freshness-age {
  color: rgba(60, 100, 75, 0.65);
}

.whats-new-freshness-detail {
  color: rgba(160, 200, 175, 0.55);
  font-size: 0.72rem;
  font-style: italic;
}
[data-theme="light"] .whats-new-freshness-detail {
  color: rgba(80, 110, 90, 0.55);
}

.whats-new-section:last-child {
  margin-bottom: 4px;
}

.whats-new-h4 {
  margin: 8px 0 6px;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: rgba(160, 220, 180, 0.85);
  font-weight: 700;
}

[data-theme="light"] .whats-new-h4 {
  color: rgba(20, 90, 50, 0.85);
}

.whats-new-empty {
  color: rgba(180, 200, 190, 0.55);
  font-style: italic;
  padding: 6px 0;
  font-size: 0.8rem;
}

.whats-new-error {
  color: rgb(240, 130, 130);
}

.whats-new-entry {
  border: 1px solid rgba(40, 110, 70, 0.25);
  border-radius: 6px;
  padding: 6px 10px;
  margin-bottom: 6px;
  background: rgba(20, 35, 25, 0.45);
}

[data-theme="light"] .whats-new-entry {
  background: rgba(30, 100, 60, 0.04);
  border-color: rgba(30, 100, 60, 0.18);
}

.whats-new-entry summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
  color: rgb(200, 230, 210);
}

.whats-new-entry summary::-webkit-details-marker {
  display: none;
}

.whats-new-entry summary::before {
  content: "▸";
  display: inline-block;
  color: rgba(120, 200, 150, 0.7);
  font-size: 0.7rem;
  transition: transform 120ms ease;
  width: 10px;
  flex-shrink: 0;
}

.whats-new-entry[open] summary::before {
  transform: rotate(90deg);
}

[data-theme="light"] .whats-new-entry summary {
  color: rgb(20, 60, 40);
}

.whats-new-pill {
  font-family: ui-monospace, "JetBrains Mono", monospace;
  background: rgba(40, 110, 70, 0.45);
  color: rgb(160, 240, 190);
  padding: 1px 7px;
  border-radius: 10px;
  font-size: 0.7rem;
  font-weight: 600;
  white-space: nowrap;
}

[data-theme="light"] .whats-new-pill {
  background: rgba(30, 100, 60, 0.15);
  color: rgb(20, 90, 50);
}

.whats-new-pill-status[data-status="IN PROGRESS"] {
  background: rgba(200, 140, 30, 0.4);
  color: rgb(255, 210, 130);
}

.whats-new-pill-status[data-status="NEW PRIMARY"] {
  background: rgba(60, 140, 200, 0.4);
  color: rgb(160, 220, 255);
}

.whats-new-pill-status[data-status="READY"] {
  background: rgba(40, 110, 70, 0.45);
  color: rgb(160, 240, 190);
}

.whats-new-pill-status[data-status="DEFERRED"],
.whats-new-pill-status[data-status="GATED"],
.whats-new-pill-status[data-status="BLOCKED"] {
  background: rgba(120, 120, 130, 0.35);
  color: rgb(200, 200, 210);
}

[data-theme="light"] .whats-new-pill-status[data-status="IN PROGRESS"] {
  background: rgba(200, 140, 30, 0.18);
  color: rgb(160, 90, 10);
}

[data-theme="light"] .whats-new-pill-status[data-status="NEW PRIMARY"] {
  background: rgba(60, 140, 200, 0.15);
  color: rgb(20, 80, 140);
}

.whats-new-date {
  font-family: ui-monospace, "JetBrains Mono", monospace;
  color: rgba(180, 200, 190, 0.7);
  font-size: 0.72rem;
}

[data-theme="light"] .whats-new-date {
  color: rgba(20, 60, 40, 0.65);
}

.whats-new-entry-title {
  flex: 1 1 auto;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.whats-new-entry-body {
  margin-top: 8px;
  padding: 8px;
  border-left: 2px solid rgba(60, 200, 130, 0.35);
  background: rgba(10, 20, 14, 0.55);
  color: rgba(220, 235, 225, 0.88);
  font-size: 0.78rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 240px;
  overflow-y: auto;
  border-radius: 0 4px 4px 0;
}

[data-theme="light"] .whats-new-entry-body {
  background: rgba(30, 100, 60, 0.04);
  color: rgba(20, 60, 40, 0.85);
  border-left-color: rgba(30, 100, 60, 0.35);
}

.whats-new-footer {
  flex-shrink: 0;
  padding: 6px 14px;
  font-size: 0.7rem;
  color: rgba(140, 170, 150, 0.6);
  border-top: 1px solid rgba(40, 110, 70, 0.25);
  display: flex;
  gap: 6px;
  align-items: center;
  background: rgba(10, 20, 14, 0.6);
}

[data-theme="light"] .whats-new-footer {
  color: rgba(20, 60, 40, 0.55);
  border-top-color: rgba(30, 100, 60, 0.15);
  background: rgba(30, 100, 60, 0.03);
}

.whats-new-footer code {
  font-size: 0.7rem;
  background: rgba(40, 110, 70, 0.18);
  padding: 1px 5px;
  border-radius: 3px;
}

/* Required by x-cloak to hide the panel before Alpine hydrates */
[x-cloak] { display: none !important; }

/* ===================================================================
   DFD / Architecture page  (admin_architecture.html)
   =================================================================== */

/* --- Page layout: diagram left, side panel right --- */
.dfd-page-container {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  min-height: 520px;
}

.dfd-diagram-pane {
  position: relative;            /* anchor for the zoom toolbar */
  flex: 1 1 auto;
  min-width: 0;
  /* Fixed viewport for pan/zoom. overflow:hidden so the transformed SVG
     can extend beyond the pane on both axes without scrollbars fighting
     the transform. */
  overflow: hidden;
  height: calc(100vh - 240px);
  min-height: 520px;
  border: 1px solid rgba(var(--border-subtle-rgb), 0.4);
  border-radius: var(--radius-md, 6px);
  background: var(--bg-surface, #050d08);
  padding: 0;
  cursor: grab;
  user-select: none;
}

.dfd-diagram-pane.is-dragging,
.dfd-diagram-pane.is-dragging * {
  cursor: grabbing !important;
}

.dfd-mermaid-host {
  width: 100%;
  height: 100%;
  position: relative;
}

/* ---- Zoom toolbar (top-right of the diagram pane) ---- */
.dfd-zoom-toolbar {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(var(--border-default-rgb, 60 140 90), 0.45);
  border-radius: 4px;
  backdrop-filter: blur(6px);
}
.dfd-zoom-toolbar button {
  width: 26px;
  height: 26px;
  background: transparent;
  border: 1px solid rgba(var(--border-default-rgb, 60 140 90), 0.45);
  border-radius: 3px;
  color: var(--text-primary, #d3f7df);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: ui-monospace, monospace;
  padding: 0;
}
.dfd-zoom-toolbar button:hover {
  background: rgba(var(--accent-rgb, 0 165 84), 0.15);
  color: var(--accent-bright, #00d26a);
}
.dfd-zoom-toolbar .dfd-zoom-readout {
  font-family: ui-monospace, monospace;
  font-size: 11px;
  color: var(--text-secondary, #8fc3a3);
  display: inline-flex;
  align-items: center;
  padding: 0 6px;
  min-width: 46px;
  justify-content: center;
}
[data-theme="light"] .dfd-zoom-toolbar {
  background: rgba(255, 255, 255, 0.92);
  border-color: rgba(0, 0, 0, 0.15);
}
[data-theme="light"] .dfd-zoom-toolbar button {
  color: #1a3e26;
  border-color: rgba(0, 0, 0, 0.15);
}
[data-theme="light"] .dfd-zoom-toolbar .dfd-zoom-readout {
  color: #4a6b56;
}

/* --- Side panel --- */
.dfd-side-panel {
  flex: 0 0 340px;
  width: 340px;
  position: sticky;
  top: 16px;
  max-height: calc(100vh - 120px);
  overflow-y: auto;
  border: 1px solid rgba(var(--border-subtle-rgb), 0.4);
  border-radius: var(--radius-md, 6px);
  background: var(--bg-elevated, #0a1a10);
  padding: 12px;
  scroll-behavior: smooth;
}

.dfd-panel-body--collapsed {
  display: none;
}

/* On narrow screens the side panel becomes a bottom drawer */
@media (max-width: 900px) {
  .dfd-page-container {
    flex-direction: column;
  }
  .dfd-side-panel {
    flex: none;
    width: 100%;
    position: static;
    max-height: none;
  }
  .dfd-panel-body--collapsed {
    display: none;
  }
  .dfd-panel-toggle {
    display: inline-flex !important;
  }
}

@media (min-width: 901px) {
  .dfd-panel-toggle { display: none !important; }
  .dfd-panel-body--collapsed { display: block !important; }
}

/* --- Empty state --- */
.dfd-empty-state {
  padding: 24px 8px;
  text-align: center;
}

/* --- Node detail --- */
.dfd-node-detail { font-size: 12px; }

/* --- Kind badges --- */
.dfd-kind-badge {
  display: inline-block;
  font-size: 10px;
  font-family: var(--font-mono, ui-monospace);
  letter-spacing: 0.3px;
  padding: 2px 6px;
  border-radius: 3px;
  border: 1px solid transparent;
  text-transform: lowercase;
  white-space: nowrap;
}
.dfd-kind-external {
  background: rgba(0, 120, 160, 0.15);
  border-color: rgba(0, 120, 160, 0.4);
  color: #5bb8d4;
}
.dfd-kind-process {
  background: rgba(var(--accent-rgb, 0 165 84), 0.12);
  border-color: rgba(var(--accent-rgb, 0 165 84), 0.35);
  color: var(--accent, #00a554);
}
.dfd-kind-store {
  background: rgba(150, 100, 0, 0.15);
  border-color: rgba(180, 130, 0, 0.35);
  color: #c8a440;
}
.dfd-kind-boundary {
  background: rgba(160, 40, 40, 0.15);
  border-color: rgba(200, 60, 60, 0.35);
  color: #d47070;
}
.dfd-kind-default {
  background: rgba(var(--border-default-rgb, 80 80 80), 0.15);
  border-color: rgba(var(--border-default-rgb, 80 80 80), 0.35);
  color: var(--text-secondary);
}

/* Light-mode badge overrides */
[data-theme="light"] .dfd-kind-external  { color: #0773aa; background: rgba(7,115,170,0.07); border-color: rgba(7,115,170,0.3); }
[data-theme="light"] .dfd-kind-process   { color: #1a6e3c; background: rgba(0,165,84,0.07); border-color: rgba(0,165,84,0.3); }
[data-theme="light"] .dfd-kind-store     { color: #7a5800; background: rgba(180,130,0,0.07); border-color: rgba(180,130,0,0.3); }
[data-theme="light"] .dfd-kind-boundary  { color: #a01010; background: rgba(160,40,40,0.07); border-color: rgba(160,40,40,0.3); }

/* --- Freshness dot --- */
.dfd-freshness-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.dfd-dot-green  { background: var(--color-success, #00a554); }
.dfd-dot-yellow { background: var(--color-warning, #b67200); }
.dfd-dot-red    { background: var(--color-danger,  #c42424); }

/* --- Edge items --- */
.dfd-edge-item {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  padding: 3px 6px;
  border-radius: 3px;
  font-size: 11px;
  line-height: 1.4;
  background: rgba(var(--bg-base-rgb, 5 13 8), 0.5);
  border: 1px solid rgba(var(--border-subtle-rgb, 30 60 40), 0.3);
  margin-bottom: 2px;
}
.dfd-edge-item--in  { border-left: 2px solid rgba(0, 140, 200, 0.45); }
.dfd-edge-item--out { border-left: 2px solid rgba(var(--accent-rgb, 0 165 84), 0.45); }
.dfd-edge-arrow {
  flex-shrink: 0;
  color: var(--text-muted);
  font-size: 10px;
}
.dfd-edge-label {
  color: var(--text-muted);
  font-style: italic;
  font-size: 10px;
  margin-left: 4px;
}

[data-theme="light"] .dfd-edge-item {
  background: #f5f5f3;
  border-color: rgba(0,0,0,0.1);
}
[data-theme="light"] .dfd-edge-item--in  { border-left-color: #0773aa; }
[data-theme="light"] .dfd-edge-item--out { border-left-color: #1a6e3c; }

/* --- Level selector (segmented control) --- */
.dfd-level-selector {
  display: inline-flex;
  border: 1px solid rgba(var(--border-default-rgb, 60 140 90), 0.5);
  border-radius: var(--radius-sm, 4px);
  overflow: hidden;
  align-self: flex-start;
}
.dfd-level-btn {
  font-family: var(--font-mono, ui-monospace);
  font-size: 11px;
  padding: 4px 14px;
  background: transparent;
  border: none;
  border-style: solid !important;  /* defeat training/reset.css button{border:none} */
  border-width: 0 !important;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background var(--duration-fast, 120ms) ease,
              color    var(--duration-fast, 120ms) ease;
}
.dfd-level-btn + .dfd-level-btn {
  border-left: 1px solid rgba(var(--border-default-rgb, 60 140 90), 0.4) !important;
}
.dfd-level-btn:hover {
  background: rgba(var(--accent-rgb, 0 165 84), 0.08);
  color: var(--accent-bright);
}
.dfd-level-btn--active {
  background: rgba(var(--accent-rgb, 0 165 84), 0.18) !important;
  color: var(--accent-bright, #64c987) !important;
}

[data-theme="light"] .dfd-level-btn       { color: var(--text-primary); }
[data-theme="light"] .dfd-level-btn:hover { background: rgba(0,0,0,0.05); color: var(--text-primary); }
[data-theme="light"] .dfd-level-btn--active { background: rgba(0,0,0,0.08) !important; color: var(--text-primary) !important; }

/* --- SVG node freshness overlays (applied via JS after Mermaid renders) --- */
/* !important overrides Mermaid's inline fill= on <rect>/<polygon>        */
.dfd-status-green  { fill: rgba(0, 165, 84,  0.18) !important; stroke: rgba(0, 165, 84,  0.6) !important; }
.dfd-status-yellow { fill: rgba(182, 114, 0, 0.18) !important; stroke: rgba(182, 114, 0, 0.6) !important; }
.dfd-status-red    { fill: rgba(196, 36,  36, 0.18) !important; stroke: rgba(196, 36,  36, 0.6) !important; }

[data-theme="light"] .dfd-status-green  { fill: rgba(0, 165, 84,  0.10) !important; stroke: rgba(0, 165, 84,  0.5) !important; }
[data-theme="light"] .dfd-status-yellow { fill: rgba(182, 114, 0, 0.10) !important; stroke: rgba(182, 114, 0, 0.5) !important; }
[data-theme="light"] .dfd-status-red    { fill: rgba(196, 36,  36, 0.10) !important; stroke: rgba(196, 36,  36, 0.5) !important; }

/* --- Light-mode: diagram pane + side panel backgrounds --- */
[data-theme="light"] .dfd-diagram-pane { background: #ffffff; border-color: rgba(0,0,0,0.12); }
[data-theme="light"] .dfd-side-panel   { background: #fafaf8; border-color: rgba(0,0,0,0.12); }

/* --- Mermaid SVG sizing inside the host div ---
   max-width: none so the SVG can render at its natural width (Mermaid
   with useMaxWidth:false emits real width/height attributes); pan/zoom
   then transforms the SVG via translate+scale around transform-origin
   0,0. transform-origin is set inline by the renderer so it composes
   with mermaid's own classes correctly. */
.dfd-mermaid-host svg {
  max-width: none;
  height: auto;
  display: block;
}

/* ================================================================
   DFD L2A / L2B additions — appended, do not rewrite above
   ================================================================ */

/* --- "Up to L1" button (L2A / L2B) --- */
.dfd-up-button {
  font-family: var(--font-mono, ui-monospace);
  font-size: 11px;
  padding: 4px 12px;
  background: transparent;
  border: 1px solid rgba(var(--border-default-rgb, 60 140 90), 0.5) !important;
  border-style: solid !important;
  border-radius: var(--radius-sm, 4px);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background var(--duration-fast, 120ms) ease,
              color    var(--duration-fast, 120ms) ease;
}
.dfd-up-button:hover {
  background: rgba(var(--accent-rgb, 0 165 84), 0.08);
  color: var(--accent-bright);
}
[data-theme="light"] .dfd-up-button       { color: var(--text-primary); }
[data-theme="light"] .dfd-up-button:hover { background: rgba(0,0,0,0.05); color: var(--text-primary); }

/* --- Breadcrumb --- */
.dfd-breadcrumb {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-family: var(--font-mono, ui-monospace);
  color: var(--text-muted);
}
.dfd-breadcrumb-sep {
  color: var(--text-muted);
  opacity: 0.5;
}
.dfd-breadcrumb-seg {
  color: var(--text-secondary);
}
.dfd-breadcrumb-seg--current {
  color: var(--accent-bright, #64c987);
}
.dfd-breadcrumb-link {
  background: none;
  border: none !important;
  border-style: none !important;
  padding: 0;
  color: var(--accent, #00a554);
  font-family: inherit;
  font-size: inherit;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-style: dotted;
}
.dfd-breadcrumb-link:hover {
  color: var(--accent-bright, #64c987);
}
[data-theme="light"] .dfd-breadcrumb-seg--current { color: #1a6e3c; }
[data-theme="light"] .dfd-breadcrumb-link         { color: #1a6e3c; }
[data-theme="light"] .dfd-breadcrumb-link:hover   { color: #0d4a28; }

/* --- fires_when badges (L2B guardrail_stage) --- */
.dfd-fires-badge {
  display: inline-block;
  font-size: 10px;
  font-family: var(--font-mono, ui-monospace);
  letter-spacing: 0.3px;
  padding: 2px 7px;
  border-radius: 3px;
  border: 1px solid transparent;
  text-transform: lowercase;
  white-space: nowrap;
}
.dfd-badge-pre-dispatch {
  background: rgba(0, 180, 200, 0.15);
  border-color: rgba(0, 180, 200, 0.4);
  color: #5ecfdb;
}
.dfd-badge-per-tool-call {
  background: rgba(200, 140, 0, 0.15);
  border-color: rgba(200, 140, 0, 0.4);
  color: #d4a840;
}
.dfd-badge-terminal-turn {
  background: rgba(0, 165, 84, 0.15);
  border-color: rgba(0, 165, 84, 0.4);
  color: #64c987;
}
.dfd-badge-after-turn {
  background: rgba(100, 100, 100, 0.15);
  border-color: rgba(120, 120, 120, 0.35);
  color: var(--text-muted);
}

[data-theme="light"] .dfd-badge-pre-dispatch  { background: rgba(0,180,200,0.07); border-color: rgba(0,180,200,0.3); color: #007a87; }
[data-theme="light"] .dfd-badge-per-tool-call { background: rgba(200,140,0,0.07); border-color: rgba(200,140,0,0.3); color: #7a5800; }
[data-theme="light"] .dfd-badge-terminal-turn { background: rgba(0,165,84,0.07);  border-color: rgba(0,165,84,0.3);  color: #1a6e3c; }
[data-theme="light"] .dfd-badge-after-turn    { background: rgba(0,0,0,0.04);     border-color: rgba(0,0,0,0.2);     color: #666; }

/* --- L2A tool node metadata table --- */
.dfd-tool-meta-table {
  border: 1px solid rgba(var(--border-subtle-rgb, 30 60 40), 0.4);
  border-radius: 3px;
  overflow: hidden;
  font-size: 11px;
  font-family: var(--font-mono, ui-monospace);
}
.dfd-tool-meta-row {
  display: flex;
  gap: 8px;
  padding: 3px 8px;
  border-bottom: 1px solid rgba(var(--border-subtle-rgb, 30 60 40), 0.3);
}
.dfd-tool-meta-row:last-child {
  border-bottom: none;
}
.dfd-tool-meta-key {
  flex: 0 0 46px;
  color: var(--text-muted);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  padding-top: 1px;
}
.dfd-tool-meta-val {
  color: #5bb8d4;
  font-size: 11px;
  word-break: break-all;
}

[data-theme="light"] .dfd-tool-meta-table   { border-color: rgba(0,0,0,0.12); background: #f5f5f3; }
[data-theme="light"] .dfd-tool-meta-row     { border-color: rgba(0,0,0,0.08); }
[data-theme="light"] .dfd-tool-meta-val     { color: #0773aa; }

/* --- Kind badges for new L2A/L2B kinds --- */
.dfd-kind-mcp {
  background: rgba(120, 0, 180, 0.15);
  border-color: rgba(150, 30, 200, 0.4);
  color: #c07ee8;
}
.dfd-kind-tool {
  background: rgba(0, 120, 160, 0.12);
  border-color: rgba(0, 140, 190, 0.35);
  color: #5bb8d4;
}
.dfd-kind-guardrail {
  background: rgba(180, 100, 0, 0.12);
  border-color: rgba(200, 120, 0, 0.35);
  color: #d4a840;
}

[data-theme="light"] .dfd-kind-mcp       { background: rgba(120,0,180,0.06);  border-color: rgba(120,0,180,0.25); color: #7b00c4; }
[data-theme="light"] .dfd-kind-tool      { background: rgba(0,120,160,0.06);  border-color: rgba(0,120,160,0.25); color: #0773aa; }
[data-theme="light"] .dfd-kind-guardrail { background: rgba(180,100,0,0.06);  border-color: rgba(180,100,0,0.25); color: #7a5800; }

/* --- L2A MCP host origin glow (applied via JS after render) --- */
.dfd-origin-glow {
  stroke: rgba(0, 165, 84, 0.8) !important;
  stroke-width: 2.5px !important;
  filter: drop-shadow(0 0 4px rgba(0, 165, 84, 0.4));
}
[data-theme="light"] .dfd-origin-glow {
  stroke: rgba(26, 110, 60, 0.7) !important;
  filter: drop-shadow(0 0 4px rgba(26, 110, 60, 0.3));
}

/* --- L2B subgraph labels — ensure visible in both themes --- */
/* Mermaid renders cluster labels as .cluster-label text elements */
.dfd-mermaid-host .cluster-label {
  font-family: var(--font-mono, ui-monospace) !important;
  font-size: 11px !important;
}
[data-theme="light"] .dfd-mermaid-host .cluster-label {
  fill: #1c1c1f !important;
}
[data-theme="light"] .dfd-mermaid-host .cluster rect {
  fill: #f0f0ec !important;
  stroke: #a0a09a !important;
}

/* --- L2C cron-job-specific side-panel styles --- */

/* Cron expression rendered in monospace with a subtle tint */
.dfd-cron-schedule {
  font-family: var(--font-mono, ui-monospace);
  font-size: 11px;
  padding: 1px 6px;
  border-radius: 3px;
  background: rgba(0, 100, 60, 0.12);
  border: 1px solid rgba(0, 140, 80, 0.25);
  color: #7dd4a8;
  letter-spacing: 0.2px;
}
[data-theme="light"] .dfd-cron-schedule {
  background: rgba(0, 100, 60, 0.06);
  border-color: rgba(0, 100, 60, 0.20);
  color: #1a6e3c;
}

/* Owner badge — root (amber) vs datalink (cyan) */
.dfd-owner-badge-root,
.dfd-owner-badge-datalink {
  display: inline-block;
  font-size: 10px;
  font-family: var(--font-mono, ui-monospace);
  padding: 1px 6px;
  border-radius: 3px;
  border: 1px solid;
}
.dfd-owner-badge-root {
  background: rgba(200, 120, 0, 0.12);
  border-color: rgba(220, 140, 0, 0.35);
  color: #d4a840;
}
.dfd-owner-badge-datalink {
  background: rgba(0, 120, 160, 0.10);
  border-color: rgba(0, 140, 190, 0.30);
  color: #5bb8d4;
}
[data-theme="light"] .dfd-owner-badge-root {
  background: rgba(200, 120, 0, 0.06);
  border-color: rgba(180, 100, 0, 0.25);
  color: #7a5800;
}
[data-theme="light"] .dfd-owner-badge-datalink {
  background: rgba(0, 120, 160, 0.06);
  border-color: rgba(0, 120, 160, 0.22);
  color: #0773aa;
}

/* Kind badge for cron_job nodes */
.dfd-kind-cron {
  background: rgba(0, 140, 100, 0.12);
  border-color: rgba(0, 160, 110, 0.35);
  color: #4ecb9e;
}
[data-theme="light"] .dfd-kind-cron {
  background: rgba(0, 120, 80, 0.06);
  border-color: rgba(0, 120, 80, 0.22);
  color: #0a6644;
}

/* --- L2C subgraph cluster styling — data sync / backup / monitoring / vault --- */
/* Mermaid cluster boxes for L2C groups; light backgrounds distinguish groups */
.dfd-mermaid-host .cluster rect {
  rx: 4px;
  ry: 4px;
}
/* Ensure L2C cluster labels remain readable in both themes (inherits .cluster-label rule above) */

