/*
 * cortex-components.css - Shared interactive component patterns
 *
 * LOAD ORDER:
 *   1. design-system.css  - Tokens, reset, foundation components
 *   2. cortex-components.css (this file) - Tray, pills, banners, tabs, notifications
 *   3. cortex.css - Layout, nav, modules, page-specific styles
 *
 * All tokens come from design-system.css. Uses shorthand aliases (--bg, --t1, etc.).
 */

/* ============================================================
   DETAIL TRAY (Slide-in right panel)
   ============================================================
   Usage: overlay div + tray div, toggle .open class on both.
   Width customizable via --tray-width (default 520px).

   HTML structure:
     <div class="tray-overlay" onclick="closeTray()"></div>
     <div class="tray" style="--tray-width: 560px">
       <div class="tray-header">
         <div class="tray-title">Title</div>
       </div>
       <div class="tray-body">
         <div class="tray-section">
           <div class="tray-label">Section</div>
           <div class="tray-value">Content</div>
         </div>
       </div>
     </div>

   TRAY RULES:
   - No close button. Users dismiss via overlay click or Escape key.
   - The phone exit (cortex-dashboard-driver A-11 amendment, 2026-10-01): at
     640px and under the tray fills the viewport, so the overlay has no visible
     target and a phone has no Escape key. The tray then shows ONE back line at
     the top of its header, "← {the list it came from}" (.tray-back, rendered by
     CortexTray.scaffold({ back: 'Notes' })), and the browser Back gesture
     closes it (CortexTray pushes one history entry per open). The back line is
     the back gesture made visible, never a close button: it renders only on a
     phone (display none above 640px). Closing by any path pops the history entry
     the open pushed, so the overlay, Escape, the back line and the Back gesture
     leave the same history.
   - The tray is a dialog: role="dialog" aria-labelledby="cortexTrayTitle", aria-hidden
     while shut (visibility hidden too, so it leaves the tab order), aria-modal while
     open; a page moves focus to the title on open and back to its opener on close.
   - All hyperlinks inside trays MUST open in a new tab (target="_blank" rel="noopener").
   ============================================================ */
.tray-overlay {
  position: fixed; top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,0.4);
  z-index: 998;
  opacity: 0; pointer-events: none;
  transition: opacity 200ms;
}
.tray-overlay.open { opacity: 1; pointer-events: auto; }

.tray {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: var(--tray-width, 520px);
  max-width: 90vw;
  background: var(--bg);
  border-left: 1px solid var(--border-med);
  z-index: 999;
  transform: translateX(100%);
  visibility: hidden; /* a closed tray leaves the tab order and the accessibility tree */
  transition: transform 250ms ease, visibility 0s linear 250ms;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain; /* a scroll that reaches the tray's end never drags the page behind it */
  display: flex; flex-direction: column;
}
.tray.open { transform: translateX(0); visibility: visible; transition: transform 250ms ease, visibility 0s; }

/* The phone exit: see TRAY RULES above. Hidden above 640px by design. */
.tray-back { display: none; }
@media (max-width: 640px) {
  .tray { max-width: 100vw; }
  .tray-header { flex-wrap: wrap; padding-top: calc(10px + env(safe-area-inset-top, 0px)); }
  .tray-body { padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px)); }
  .tray-back {
    display: inline-flex; align-items: center; gap: 6px;
    flex: 0 0 100%; order: -1;
    min-height: 44px; margin: -4px 0 2px; padding: 0 2px;
    background: transparent; border: 0;
    color: var(--t3); font: inherit; font-size: var(--fs-sm); font-weight: 600;
    text-align: left; cursor: pointer;
  }
  .tray-back:active { color: var(--t1); }
  .tray-back:focus-visible { color: var(--t1); outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
  /* While a tray is open on a phone the page behind it holds still (CortexTray
     toggles the class on <html>); the tray itself scrolls. */
  html.cortex-tray-open, html.cortex-tray-open body { overflow: hidden; }
}
.tray.open .tray-header,
.tray.open .tray-body,
.tray.open .tray-footer {
  animation: t-tray-content-reveal var(--panel-open-dur) var(--panel-ease) both;
  will-change: transform, opacity, filter;
}
.tray.open .tray-body { animation-delay: 35ms; }
.tray.open .tray-footer { animation-delay: 70ms; }
@keyframes t-tray-content-reveal {
  from { opacity: 0; transform: translateY(8px); filter: blur(1px); }
  to { opacity: 1; transform: translateY(0); filter: blur(0); }
}
@media (prefers-reduced-motion: reduce) {
  .tray.open .tray-header,
  .tray.open .tray-body,
  .tray.open .tray-footer { animation: none !important; }
}

.tray-header {
  padding: 16px 24px 12px;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: flex-start;
  justify-content: space-between; gap: 12px;
  flex-shrink: 0;
  min-width: 0;
}
.tray-title {
  font-size: var(--fs-xl); font-weight: 700;
  color: var(--t1);
  line-height: 1.3;
  overflow-wrap: anywhere;
  word-break: break-word;
}
/* .tray-close removed - design system rule: no close buttons on trays.
   Dismiss via overlay click or Escape key. */
/* A page moves keyboard focus onto the title when the tray opens (so a screen
   reader announces the item and the next Tab lands inside the tray); the
   browser's focus ring on a programmatically focused heading is noise. */
.tray-title[tabindex]:focus { outline: none; }

.tray-body {
  padding: 16px 24px 24px;
  flex: 0 0 auto;
  display: flex; flex-direction: column; gap: 16px;
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}
/* Force wrap on every text-bearing descendant so long file paths,
   URLs, and code identifiers can never produce horizontal scroll.
   Pill chips with `white-space: nowrap` (.tray-tag, .pill) opt out
   via the more-specific selectors below. */
.tray-body p,
.tray-body li,
.tray-body code,
.tray-body pre,
.tray-body span,
.tray-body div { min-width: 0; overflow-wrap: anywhere; word-break: break-word; }
.tray-body pre { white-space: pre-wrap; }
/* Re-assert nowrap for chip-style elements (otherwise wrap rule above
   would break their visual contract). */
.tray-body .tray-tag,
.tray-body .pill,
.tray-body .ui-pill { white-space: nowrap; }
.tray-section { display: flex; flex-direction: column; gap: 2px; }
.tray-label {
  font-size: var(--fs-xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--t4);
}
.tray-value {
  font-size: var(--fs-sm);
  color: var(--t2);
  line-height: 1.6;
}
.tray-value code {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  background: rgba(255,255,255,0.04);
  padding: 2px 6px; border-radius: 3px;
  color: var(--t3);
}

/* Tray meta grid (2-column field layout) */
.tray-meta-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.tray-meta-item { display: flex; flex-direction: column; gap: 2px; }
.tray-meta-lbl {
  font-size: var(--fs-xs);
  color: var(--t4);
  text-transform: uppercase; letter-spacing: 0.04em;
}
.tray-meta-val {
  font-size: var(--fs-md); font-weight: 600;
  color: var(--t1);
}

/* Person Links (shared standard: every person name links to manifest view).
   Person identity is data, not brand — use neutral text per the accent budget rule.
   Hover lifts to text-primary instead of recoloring to accent. */
.person-link {
  color: var(--text-secondary);
  text-decoration: none;
  font-weight: 500;
  transition: color var(--transition-fast);
}
.person-link:hover { color: var(--text-primary); }

.person-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-xs);
  font-weight: 500;
  padding: 4px 10px;
  border-radius: var(--radius-md);
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  text-decoration: none;
  transition: border-color var(--transition-fast), background var(--transition-fast), color var(--transition-fast);
  margin: 0 4px 4px 0;
}
.person-pill:hover {
  border-color: var(--border-default);
  background: rgba(255,255,255,0.06);
  color: var(--text-primary);
}

/* Tray tags (chips) — Plus Jakarta Sans 600; tags are not receipts, so not
   mono (productai-brand-typography-driver Axiom 2). */
.tray-tags { display: flex; flex-wrap: wrap; gap: 5px; }
.tray-tag {
  font-size: var(--fs-xs); padding: 3px 10px; border-radius: 5px;
  font-family: var(--font-sans); font-weight: 600;
  border: 1px solid var(--border);
  background: rgba(255,255,255,0.04);
  color: var(--t3);
}

/* Tray list items */
.tray-list { display: flex; flex-direction: column; gap: 4px; }
.tray-list-item {
  font-size: var(--fs-xs);
  color: var(--t2);
  padding: 4px 0;
}

/* ============================================================
   STATUS PILL (Colored status indicators)
   ============================================================
   Usage: <span class="pill pill-green">Active</span>
   ============================================================ */
.pill {
  font-size: var(--fs-xs); font-weight: 600;
  padding: 2px 8px; border-radius: 10px;
  text-transform: uppercase; letter-spacing: 0.03em;
  white-space: nowrap; display: inline-flex;
}
.pill-green  { color: var(--green); background: var(--green-bg); }
/* mint + red-muted: Conviction Ladder tiers 2 + 5 (cortex-dashboard-driver A-31 —
   mint is the green-family shade between green and yellow; red-muted keeps the
   loud red reserved for tier 6). Previously undefined, so tier-2/tier-5 pills
   rendered as uncolored base .pill.
   Brand status set 2026-09-29: the retired emerald-300 mint becomes verified
   green at 85% on a lighter tint (5.85:1 on --bg-base); red-muted keeps full
   error red for AA (85% red measured 4.03:1) and mutes through its fill. */
.pill-mint      { color: rgba(2,187,100,0.85); background: rgba(2,187,100,0.07); }
.pill-red-muted { color: var(--red); background: rgba(239,68,68,0.06); }
.pill-yellow { color: var(--yellow); background: var(--yellow-bg); }
.pill-red    { color: var(--red); background: var(--red-bg); }
.pill-blue   { color: var(--blue); background: var(--blue-bg); }
.pill-purple { color: var(--purple); background: var(--purple-bg); }
.pill-orange { color: var(--orange); background: var(--orange-bg); }
.pill-muted  { color: var(--t4); background: rgba(255,255,255,0.04); }

/* ============================================================
   STATUS BANNER (Full-width status indicator in trays)
   ============================================================
   Usage: <div class="status-banner status-banner-ok">Healthy</div>
   ============================================================ */
.status-banner {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px; border-radius: 6px;
  font-size: var(--fs-sm); font-weight: 600;
}
.status-banner-ok    { background: var(--green-bg); color: var(--green); }
.status-banner-error { background: var(--red-bg); color: var(--red); }
.status-banner-warn  { background: var(--yellow-bg); color: var(--yellow); }
.status-banner-info  { background: var(--blue-bg); color: var(--blue); }
.status-banner-muted { background: rgba(255,255,255,0.04); color: var(--t4); }

/* ============================================================
   TAB GROUP (Segmented toggle control)
   ============================================================
   One control, any element. Since 2026-10-08 the item carries its own
   reset, so a real <button class="tab-item"> (the right element for a
   view switch) paints the same as the <div role="tab"> the older pages
   use. Before that a button wore the browser's grey default chrome and
   2px outset border (the /dashboards view switch, 2026-10-07). The group
   sizes to its labels (inline-flex); a page that wants the segments to
   share one fixed box sets `display:flex; max-width:…` on the group, as
   /lex does inside its nav row.
   Usage:
     <div class="tab-group" role="tablist" aria-label="View">
       <button type="button" class="tab-item active" role="tab" aria-selected="true">Tab A</button>
       <button type="button" class="tab-item" role="tab" aria-selected="false">Tab B</button>
     </div>
   Look: an inset dark track (--bg-raised) with the active segment raised
   on --surface-active behind a --border-strong hairline. Elevation, never
   accent (the accent budget in dashboard/CLAUDE.md); accent appears only
   on the keyboard focus ring, like .filter-pill and .ui-btn.
   ============================================================ */
.tab-group {
  display: inline-flex; vertical-align: top; gap: 3px;
  max-width: 100%;
  padding: 4px;
  background: var(--bg-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.35);
}
.tab-item {
  appearance: none; -webkit-appearance: none;
  flex: 1 1 auto;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 40px; padding: 0 16px;
  background: transparent;
  border: 0; border-radius: var(--radius-md);
  font: inherit; font-size: var(--fs-sm); font-weight: 500; line-height: 1.2;
  text-align: center; text-decoration: none;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: color 120ms, background 120ms, box-shadow 120ms;
}
.tab-item:hover {
  color: var(--text-secondary);
  background: var(--surface-hover);
}
.tab-item.active,
.tab-item[aria-selected="true"] {
  color: var(--text-primary);
  font-weight: 600;
  background: var(--surface-active);
  box-shadow: inset 0 0 0 1px var(--border-strong), var(--shadow-sm); /* the hairline as a ring: no border, so a segment never shifts width when it turns active */
  cursor: default;
}
.tab-item.active:hover,
.tab-item[aria-selected="true"]:hover { background: var(--surface-active); }
.tab-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tab-item:disabled,
.tab-item[aria-disabled="true"] { opacity: 0.4; cursor: default; }
.tab-item:disabled:hover,
.tab-item[aria-disabled="true"]:hover { color: var(--text-tertiary); background: transparent; }
.tab-count {
  font-size: var(--fs-xs); font-weight: 700;
  margin-left: 6px; padding: 1px 7px; border-radius: 10px;
}

/* ── Secondary segmented nav (lex IA 2026-06-16) ──
   A quiet PEER of .tab-group: a hairline divider + a quieter bordered segment of
   secondary nav items. Same active grammar as .tab-item (raised surface + shadow,
   NOT accent), one register down (text --t2 not --t1; surface --surface-hover not
   --card). Used by /lex for Activity + Stewardship alongside the four type tabs. */
.tab-divider { align-self: center; width: 1px; height: 20px; background: var(--border-default); flex: 0 0 auto; }
.tab-sec-group { display: inline-flex; vertical-align: top; gap: 3px; padding: 4px; border-radius: var(--radius-lg); background: transparent; border: 1px solid var(--border-default); flex: 0 0 auto; }
.tab-item--secondary { appearance: none; -webkit-appearance: none; display: inline-flex; align-items: center; justify-content: center; min-height: 40px; padding: 0 14px; background: transparent; border: 0; font: inherit; font-size: var(--fs-xs); font-weight: 500; line-height: 1.2; color: var(--text-tertiary); cursor: pointer; border-radius: var(--radius-md); white-space: nowrap; transition: color 120ms, background 120ms, box-shadow 120ms; }
.tab-item--secondary:hover { color: var(--text-secondary); background: var(--surface-hover); }
.tab-item--secondary.active { color: var(--text-secondary); font-weight: 600; background: var(--surface-hover); box-shadow: inset 0 0 0 1px var(--border-default), var(--shadow-sm); cursor: default; }
.tab-item--secondary:focus-visible { outline: 2px solid var(--accent-hover); outline-offset: 2px; }
@media (max-width: 640px) {
  .tab-divider { display: none; }
  .tab-sec-group { width: 100%; display: flex; }
  .tab-item--secondary { flex: 1 1 0; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; font-size: var(--fs-sm); }
}

/* ============================================================
   MARKDOWN CONTENT (Rendered markdown for text blocks)
   ============================================================
   Usage: <div class="md-content">renderMd(text)</div>
   Use renderMd() from cortex-shared.js to generate the inner HTML.
   ============================================================ */
.md-content {
  font-size: var(--fs-sm);
  color: var(--t2);
  line-height: 1.75;
}
.md-content p {
  margin: 0 0 12px 0;
}
.md-content p:last-child { margin-bottom: 0; }
.md-content strong {
  color: var(--t1);
  font-weight: 600;
}
.md-content em {
  font-style: italic;
  color: var(--t2);
}
.md-content code {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  background: rgba(255,255,255,0.04);
  padding: 2px 6px; border-radius: 3px;
  color: var(--t3);
}
.md-content a.md-link {
  color: var(--purple);
  text-decoration: none;
  border-bottom: 1px solid rgba(181,162,254,0.3);
}
.md-content a.md-link:hover {
  color: var(--t1);
  border-bottom-color: var(--t1);
}

/* ============================================================
   PAGE WORK BUTTON (Page-level "Work on X" grounding prompt)
   ============================================================
   Usage: <button class="page-work-btn" onclick="copyPagePrompt(this, 'Work on X', prompt)">Work on X</button>
   Placed in .page-hdr right-aligned area. Green accent, prominent.
   ============================================================ */
.page-work-btn {
  padding: 6px 16px;
  border-radius: 5px;
  font-size: var(--fs-xs); font-weight: 600;
  cursor: pointer;
  border: 1px solid rgba(2,187,100,0.3);
  background: rgba(2,187,100,0.1);
  color: var(--status-green, #02BB64);
  font-family: inherit;
  transition: all 100ms;
  white-space: nowrap;
  align-self: center;
}
.page-work-btn:hover { background: rgba(2,187,100,0.2); }
.page-work-btn.copied { background: rgba(2,187,100,0.25); }

/* Compact variant for card previews (less spacing) */
.md-content-sm {
  font-size: var(--fs-xs);
  color: var(--t2);
  line-height: 1.65;
}
.md-content-sm p { margin: 0 0 6px 0; }
.md-content-sm p:last-child { margin-bottom: 0; }
.md-content-sm strong { color: var(--t1); font-weight: 600; }

/* ============================================================
   TRAY FOOTER (Prompt box + Work button, scrolls with content)
   ============================================================
   Lives at the bottom of every tray. Contains the "Work on this"
   button and the LLM prompt textarea with submit/copy actions.
   Scrolls with body content (not sticky).

   HTML structure (appended inside .tray, after .tray-body):
     <div class="tray-footer">
       <button class="tray-work-btn" onclick="...">
         <svg>copy icon</svg> Work on this
       </button>
       <div class="tray-footer-divider"></div>
       <div class="tray-prompt-area">
         <textarea class="tray-prompt-input" placeholder="Ask anything..."></textarea>
         <div class="tray-prompt-actions">
           <button class="tray-submit-btn" onclick="...">Submit</button>
           <button class="tray-copy-btn" onclick="...">Copy</button>
           <span class="tray-prompt-status"></span>
         </div>
       </div>
       <div class="tray-prompt-hint">Grounded with full cortex context</div>
       <div class="tray-prompt-response"></div>
     </div>
   ============================================================ */
.tray-footer {
  padding: 12px 24px 16px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
/* Tray CTA + prompt-action buttons carry a 44px touch-target floor (measured
   35/29/29px at 375px pre-fix).
   [NO-XG: operator-ordered UX-v2 tap-target repair on team-owned shared chrome — pure CSS, no Soma content in diff | low | none] */
.tray-work-btn {
  display: flex; align-items: center; justify-content: center;
  gap: 6px; width: 100%;
  min-height: 44px;
  padding: 8px 14px;
  border-radius: 6px;
  font-size: var(--fs-sm); font-weight: 600;
  font-family: inherit; cursor: pointer;
  transition: all 120ms ease-out;
  border: 1px solid var(--btn-brand-bg, #B5A2FE);
  background: var(--btn-brand-bg, #B5A2FE);
  color: var(--btn-brand-ink, #000);
}
.tray-work-btn:hover {
  background: var(--btn-brand-bg-hover, #956FF8);
  border-color: var(--btn-brand-bg-hover, #956FF8);
}
.tray-work-btn:active {
  background: var(--btn-brand-bg-pressed, #8B5CF6);
  border-color: var(--btn-brand-bg-pressed, #8B5CF6);
}
.tray-work-btn.copied {
  background: var(--status-green);
  border-color: var(--status-green);
  color: #000; /* black on #02BB64 8.29:1; white failed at 2.53:1 */
  animation: t-cortex-success-pop var(--check-bob-dur) var(--check-ease-bob) both;
}
.tray-work-btn.copied::before,
.page-work-btn.copied::before {
  content: "";
  width: 12px;
  height: 7px;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transform-origin: center;
  animation: t-cortex-check-draw var(--check-path-dur) var(--check-ease-path) both;
}
@keyframes t-cortex-success-pop {
  from { transform: translateY(var(--check-y-amount)) rotate(var(--check-rotate-from)); filter: blur(var(--check-blur-from)); }
  to { transform: translateY(0) rotate(0deg); filter: blur(0); }
}
@keyframes t-cortex-check-draw {
  from { opacity: 0; clip-path: inset(0 100% 0 0); }
  to { opacity: 1; clip-path: inset(0 0 0 0); }
}
@media (prefers-reduced-motion: reduce) {
  .tray-work-btn.copied,
  .tray-work-btn.copied::before,
  .page-work-btn.copied::before { animation: none !important; }
}
.tray-work-btn svg {
  width: 14px; height: 14px;
  flex-shrink: 0;
}
.tray-footer-divider {
  height: 1px;
  background: var(--border);
  margin: 10px 0;
}
.tray-prompt-area { margin-bottom: 6px; }
.tray-prompt-input {
  width: 100%;
  min-height: 56px; max-height: 140px;
  padding: 10px 12px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--t1);
  font-size: var(--fs-sm);
  font-family: inherit;
  line-height: 1.5;
  resize: vertical;
  box-sizing: border-box;
}
.tray-prompt-input::placeholder { color: var(--t4); }
.tray-prompt-input:focus {
  outline: none;
  border-color: var(--border-accent, rgba(139,92,246,0.4));
}
.tray-prompt-actions {
  display: flex; gap: 8px; align-items: center;
  margin-top: 8px;
}
.tray-submit-btn {
  min-height: 44px; /* [NO-XG: operator-ordered UX-v2 tap-target repair on team-owned shared chrome — pure CSS, no Soma content in diff | low | none] */
  padding: 6px 14px;
  border-radius: 4px;
  font-size: var(--fs-xs); font-weight: 600;
  font-family: inherit; cursor: pointer;
  border: 1px solid rgba(181,162,254,0.3);
  background: rgba(181,162,254,0.12);
  color: var(--purple);
  transition: all 120ms ease-out;
}
.tray-submit-btn:hover {
  background: rgba(181,162,254,0.2);
  border-color: rgba(181,162,254,0.5);
}
.tray-submit-btn:disabled {
  opacity: 0.4; cursor: default;
}
.tray-copy-btn {
  min-height: 44px;
  padding: 6px 14px;
  border-radius: 4px;
  font-size: var(--fs-xs); font-weight: 600;
  font-family: inherit; cursor: pointer;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--t3);
  transition: all 120ms ease-out;
}
.tray-copy-btn:hover {
  background: rgba(255,255,255,0.04);
  color: var(--t2);
}
.tray-prompt-status {
  font-size: var(--fs-label);
  color: var(--t4);
  margin-left: auto;
}
.tray-prompt-hint {
  font-size: var(--fs-label);
  color: var(--t4);
  margin-top: 4px;
}
.tray-prompt-response {
  display: none;
  margin-top: 12px;
  padding: 12px;
  background: rgba(255,255,255,0.02);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: var(--fs-xs);
  color: var(--t1);
  line-height: 1.65;
  max-height: 400px;
  overflow-y: auto;
}

/* Prompt Log - accumulates entries for each prompt submitted in this tray session */
.tray-prompt-log {
  display: none;
  margin-top: 12px;
  max-height: 400px;
  overflow-y: auto;
}
.tray-log-entry {
  padding: 10px 12px;
  background: rgba(255,255,255,0.02);
  border: 1px solid var(--border);
  border-radius: 6px;
  margin-bottom: 8px;
}
.tray-log-entry:last-child { margin-bottom: 0; }
.tray-log-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}
.tray-log-ts {
  font-size: var(--fs-xs);
  color: var(--t4);
  font-variant-numeric: tabular-nums;
}
.tray-log-status {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.03em;
}
.tray-log-running { color: var(--status-yellow); }
.tray-log-done { color: var(--status-green); }
.tray-log-error { color: var(--status-red); }
.tray-log-prompt {
  font-size: var(--fs-xs);
  color: var(--t2);
  line-height: 1.5;
  white-space: pre-wrap;
  padding: 6px 8px;
  background: rgba(255,255,255,0.03);
  border-radius: 4px;
  border-left: 2px solid rgba(181,162,254,0.3);
}
.tray-log-result {
  display: none;
  margin-top: 8px;
  font-size: var(--fs-xs);
  color: var(--t3);
  line-height: 1.55;
  padding: 6px 8px;
  background: rgba(2,187,100,0.03);
  border-radius: 4px;
  border-left: 2px solid rgba(2,187,100,0.2);
}

/* ============================================================
   NOTIFICATION BAR (Bottom-center status notifications)
   ============================================================
   A persistent-until-dismissed notification strip at the bottom
   center of the viewport. Different from toast (ephemeral).
   Shows LLM job status, background task progress, etc.

   HTML: <div id="cortexNotifyBar" class="notify-bar"></div>
   JS:  CortexTray.notify('Processing...', 'running');
        CortexTray.notify('Response ready', 'done');
        CortexTray.clearNotify();
   ============================================================ */
.notify-bar {
  position: fixed;
  bottom: 24px; left: 50%;
  transform: translateX(-50%);
  z-index: 1001;
  display: flex; align-items: center; gap: 8px;
  padding: 8px 16px;
  border-radius: 8px;
  font-size: var(--fs-xs); font-weight: 500;
  font-family: inherit;
  background: var(--card);
  border: 1px solid var(--border-med);
  box-shadow: 0 8px 24px rgba(0,0,0,0.5);
  opacity: 0; pointer-events: none;
  transition: opacity 200ms, transform 200ms;
}
.notify-bar.visible {
  opacity: 1; pointer-events: auto;
}
.notify-bar-running { border-color: rgba(181,162,254,0.3); }
.notify-bar-done    { border-color: rgba(2,187,100,0.3); }
.notify-bar-error   { border-color: rgba(239,68,68,0.3); }

.notify-spinner {
  display: inline-block;
  width: 10px; height: 10px;
  border: 2px solid var(--border);
  border-top-color: var(--purple);
  border-radius: 50%;
  animation: cortex-spin 0.8s linear infinite;
}
.notify-dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
}
.notify-dot-done  { background: var(--green); }
.notify-dot-error { background: var(--red); }

.notify-dismiss {
  background: none; border: none;
  color: var(--t4);
  cursor: pointer; padding: 0 2px;
  font-size: var(--fs-md); line-height: 1;
  margin-left: 4px;
}
.notify-dismiss:hover { color: var(--t2); }

@keyframes cortex-spin { to { transform: rotate(360deg); } }

/* ══════════════════════════════════════════════════
   TRAY SPEC RENDERER (CortexTray.openFromSpec)
   Shared styles for declarative tray sections.
   ══════════════════════════════════════════════════ */

.tray-spec-label {
  font-size: var(--fs-xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-quaternary, #898992);
  margin-bottom: 2px; margin-top: 4px;
}
.tray-section:first-child .tray-spec-label { margin-top: 0; }

.tray-spec-value {
  font-size: var(--fs-sm); line-height: 1.55;
  color: var(--text-secondary, #D4D4D8);
  padding: 2px 0;
}

/* Evidence entries */
.tray-spec-ev {
  font-size: var(--fs-xs); line-height: 1.5;
  color: var(--text-secondary, #D4D4D8);
  padding: 3px 0;
  border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.05));
}
.tray-spec-ev:last-child { border-bottom: none; }
.tray-spec-ev-date {
  font-family: var(--font-mono, monospace);
  font-size: var(--fs-xs); color: var(--text-quaternary, #898992);
  margin-right: 8px;
}

/* Metadata rows */
.tray-spec-meta-row {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 3px 10px; font-size: var(--fs-xs);
  border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.05));
}
.tray-spec-meta-row:last-child { border-bottom: none; }
.tray-spec-meta-key {
  color: var(--text-quaternary, #898992);
  font-weight: 500; min-width: 100px;
}
.tray-spec-meta-val {
  color: var(--text-secondary, #D4D4D8);
  text-align: right;
}

/* Links - neutral text, not accent-colored. Links are navigation aids, not status. */
.tray-spec-link {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 8px;
  border-radius: var(--radius-sm, 4px);
  text-decoration: none;
  color: var(--text-secondary, #D4D4D8);
  transition: background 120ms ease, color 120ms ease;
}
.tray-spec-link:hover {
  background: rgba(255,255,255,0.06);
  color: var(--text-primary, #F4F4F5);
  text-decoration: none;
}
.tray-spec-link-icon { flex-shrink: 0; opacity: 0.35; }
.tray-spec-link:hover .tray-spec-link-icon { opacity: 0.6; }
.tray-spec-link-label { flex: 1; font-size: var(--fs-sm); }
.tray-spec-link-type {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-quaternary, #898992);
}

/* Bullet list — short scannable bullets for human-readable content.
   Used by the tray "bullets" section type. Padding matches tray-spec-value. */
.tray-spec-bullets {
  margin: 4px 0 0; padding: 0 0 0 18px;
  list-style: none;
  font-size: var(--fs-sm); line-height: 1.55;
  color: var(--text-secondary, #D4D4D8);
}
.tray-spec-bullets li {
  position: relative;
  padding: 4px 0 4px 0;
  border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.04));
}
.tray-spec-bullets li:last-child { border-bottom: none; }
.tray-spec-bullets li::before {
  content: "›";
  position: absolute; left: -14px; top: 4px;
  color: var(--text-quaternary, #898992);
  font-weight: 600;
}
.tray-spec-bullets a {
  color: inherit; text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 120ms, border-color 120ms;
}
.tray-spec-bullets a:hover {
  color: var(--text-primary);
  border-bottom-color: var(--border-strong);
}

/* Lead-in line above a bullet list, and single-statement prose fallback.
   Paired with .tray-spec-bullets for the CortexText.bulletize() tray treatment
   (cortex-dashboard-driver A-11 + S-8: tray content is bulleted-not-prose). */
.tray-spec-lead {
  font-size: var(--fs-sm); line-height: 1.5;
  color: var(--text-primary); font-weight: 500;
  margin-bottom: 8px;
}
.tray-spec-prose {
  font-size: var(--fs-sm); line-height: 1.6;
  color: var(--text-secondary);
}
/* Bullet content is never italic, even inside an italic container (e.g. a boxed
   evidence criterion). Leading labels (ONBOARDING, PLUS, "Without it:") pop. */
.tray-spec-bullets, .tray-spec-lead, .tray-spec-prose { font-style: normal; }
.tray-spec-bullets li strong, .tray-spec-lead strong { color: var(--text-primary); font-weight: 600; }
.tray-spec-bullet-sub {
  display: block;
  font-size: var(--fs-xs); color: var(--text-tertiary);
  margin-top: 2px;
}

/* Callout box (recommended action, warnings) */
.tray-spec-callout {
  margin: 4px 0; padding: 10px 14px;
  border-radius: var(--radius-md, 6px);
  border: 1px solid rgba(139,92,246,0.15);
  background: var(--accent-subtle, rgba(139,92,246,0.06));
}
.tray-spec-callout-hdr {
  font-size: var(--fs-label); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--accent, #8B5CF6); margin-bottom: 4px;
}
.tray-spec-callout-body {
  font-size: var(--fs-sm); line-height: 1.5;
  color: var(--text-secondary, #D4D4D8);
}
.tray-spec-callout-green { border-color: rgba(2,187,100,0.15); background: var(--status-green-muted, rgba(2,187,100,0.08)); }
.tray-spec-callout-green .tray-spec-callout-hdr { color: var(--status-green); }
.tray-spec-callout-red { border-color: rgba(239,68,68,0.2); background: var(--status-red-muted, rgba(239,68,68,0.08)); }
.tray-spec-callout-red .tray-spec-callout-hdr { color: var(--status-red); }
.tray-spec-callout-red .tray-spec-callout-body a { color: var(--status-red); }

/* Action buttons (resolve, archive) */
.tray-spec-actions {
  display: flex; gap: 8px;
  padding: 16px 0 8px;
  border-top: 1px solid var(--border-subtle, rgba(255,255,255,0.05));
  margin-top: 12px;
}
.tray-spec-btn-resolve, .tray-spec-btn-archive, .tray-spec-btn {
  flex: 1; padding: 8px 12px;
  border: 1px solid var(--border-default, rgba(255,255,255,0.08));
  border-radius: var(--radius-md, 6px);
  background: var(--surface-primary, #161619);
  color: var(--text-secondary, #D4D4D8);
  font-size: var(--fs-sm); font-weight: 500;
  cursor: pointer; transition: all 120ms ease;
}
.tray-spec-btn-resolve:hover {
  background: var(--status-green-muted, rgba(2,187,100,0.12));
  border-color: rgba(2,187,100,0.3);
  color: var(--status-green);
}
.tray-spec-btn-archive:hover {
  background: var(--status-yellow-muted, rgba(251,191,36,0.12));
  border-color: rgba(251,191,36,0.3);
  color: var(--status-yellow);
}

/* Metadata footer (standard bottom-of-tray provenance section) */
.tray-metadata-footer {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border-subtle, rgba(255,255,255,0.05));
}

/* ── Tray markdown density ──
   Tighter vertical rhythm for rendered markdown inside trays.
   Page-level md-content (design-system.css) stays loose for readability;
   tray context compresses for information density. */
.tray-body .md-bullet { margin: 1px 0; }
.tray-body .md-numlist { margin: 1px 0; }
.tray-body .md-gap { height: 6px; }
.tray-body .md-checkbox { margin: 1px 0; }
.tray-md { line-height: 1.5; }

/* Markdown tables and fenced code inside a tray. Before this, .tray-md carried
   line-height alone: a table had no column sizing, so a long cell broke words
   mid-word (cortex.produc / t.ai), and a ``` block had no styling because the
   renderer did not know fences at all. */
.tray-md table {
  width: 100%; border-collapse: collapse; margin: 10px 0;
  display: block; overflow-x: auto;     /* wide tables scroll, the page never does */
}
.tray-md th, .tray-md td {
  text-align: left; padding: 8px 10px; vertical-align: top;
  border-bottom: 1px solid var(--border-subtle);
  font-size: 13px; overflow-wrap: anywhere;
}
.tray-md th {
  font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-quaternary);
}
.tray-md td:first-child { color: var(--text-primary); }
.tray-md pre.md-pre {
  background: var(--bg-base); border: 1px solid var(--border-default);
  border-radius: var(--radius-md); padding: 10px 12px; margin: 10px 0; overflow-x: auto;
}
.tray-md pre.md-pre code {
  font-family: var(--font-mono); font-size: 12.5px;
  color: var(--text-secondary); white-space: pre;
}

/* ── Responsive Filter Drawer ──────────────────────────────────────────
   Mobile-collapsible filter sidebar pattern. Per cortex-dashboard-driver
   A-10 + S-7: any page with a sidebar+main two-column layout adds
   .responsive-filter-drawer to its sidebar element to hide it on mobile
   and surface it via an explicit toggle button. Desktop (>900px) the
   class is a no-op — sidebar persists as a normal grid column.

   Pages opt in by:
   1. add `responsive-filter-drawer` to sidebar's class list
   2. add `<button class="filter-toggle-btn">` to toolbar/page-hdr
   3. add `<div class="responsive-filter-drawer-backdrop"></div>` once in body
   4. call `UI.wireFilterDrawer('#toggle-id', '#sidebar-id')` from page JS

   See driver §3 A-10 + §4 S-7 for the full contract. */

.filter-toggle-btn {
  display: none;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 14px;
  background: var(--surface-primary);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: 13px;
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
  transition: color 100ms ease, border-color 100ms ease, background 100ms ease;
}
.filter-toggle-btn:hover { color: var(--text-primary); border-color: var(--border-strong); }
.filter-toggle-btn[aria-expanded="true"] {
  background: var(--surface-active, var(--surface-hover));
  color: var(--text-primary);
  border-color: var(--border-strong);
}
.filter-toggle-btn .filter-toggle-icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
}
.filter-toggle-btn .filter-toggle-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  margin-left: 2px;
  background: var(--accent);
  color: #000;
  border-radius: 9px;
  font-size: 11px;
  font-weight: 600;
  font-family: var(--font-sans);
  line-height: 1;
}

.responsive-filter-drawer-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  z-index: 998;
  cursor: pointer;
  animation: filter-drawer-fade-in 180ms ease-out;
}

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

@keyframes filter-drawer-slide-in {
  from { transform: translateX(-100%); }
  to { transform: translateX(0); }
}

/* Mobile/tablet: hide sidebar by default, surface toggle button.
   When drawer opens, sidebar becomes a left-edge overlay with backdrop. */
@media (max-width: 900px) {
  .filter-toggle-btn { display: inline-flex; }
  .responsive-filter-drawer { display: none; }

  body[data-filters-drawer-open="true"] .responsive-filter-drawer {
    display: block;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 85vw;
    max-width: 360px;
    max-height: 100vh;
    z-index: 999;
    overflow-y: auto;
    box-shadow: 4px 0 24px rgba(0, 0, 0, 0.4);
    animation: filter-drawer-slide-in 200ms ease-out;
  }
  body[data-filters-drawer-open="true"] .responsive-filter-drawer-backdrop {
    display: block;
  }
}
