/*
 * The Kitchen — Out Sauce Portal
 * Design System: Clean flat + batch colour accent
 */

/* CSS Variables - Design System */
:root {
  /* Batch Colours */
  --os-aqua: #00F5D4;
  --os-lilac: #C4A8FF;
  --os-peach: #FFBE98;
  --os-blue: #6B8CFF;
  --os-coral: #FF6B6B;

  /* Active batch colour (set by JS) */
  --batch: var(--os-aqua);
  --batch-subtle: color-mix(in srgb, var(--batch) 15%, transparent);
  --batch-hover: color-mix(in srgb, var(--batch) 25%, transparent);

  /* Backgrounds */
  --bg-primary: #F5F5F5;
  --bg-card: #FFFFFF;
  --bg-sidebar: #0A0A0A;
  --bg-sidebar-hover: #1A1A1A;

  /* Text */
  --text-primary: #0A0A0A;
  --text-body: #4A4E5A;
  --text-secondary: #888888;
  --text-muted: #9CA3AF;
  --text-on-sidebar: #FFFFFF;
  --text-on-sidebar-muted: #888888;

  /* Borders */
  --border-default: #E5E7EB;
  --border-strong: #D1D5DB;
  --border-weight: 2px;

  /* Semantic */
  --color-success: #34D399;
  --color-danger: #EF4444;
  --color-warning: #FBBF24;
  --color-info: #94A3B8;

  /* Typography */
  --font-display: 'Archivo Black', 'Arial Black', Impact, sans-serif;
  --font-mono: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

  /* Spacing */
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;

  /* Sizing */
  --button-height: 40px;
  --button-height-lg: 48px;
  --icon-button-size: 40px;
  --header-height: 60px;
  --sidebar-width: 260px;
  --sidebar-collapsed-width: 72px;

  /* Borders */
  --border-radius-sm: 6px;
  --border-radius-md: 8px;
  --border-radius-lg: 12px;
  --border-radius-xl: 20px;

  /* Effects — flat only, no glows */
  --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.06);
  --shadow-elevated: 0 4px 12px rgba(0, 0, 0, 0.08);
  --transition-fast: 150ms ease-out;
  --transition-medium: 300ms ease-out;

  /* POC token aliases (used by dashboard + shared components) */
  --block-bg: #0A0A0A;
  --block-text: #FFFFFF;
  --block-muted: #555555;
  --block-tag: #888888;
  --block-surface: rgba(255,255,255,0.06);
  --content-bg: #FFFFFF;
  --content-text: #1A1D26;
  --content-secondary: #4A4E5A;
  --content-muted: #6B7085;
  --content-border: #E5E7EB;
  --content-surface: #F7F7F8;
  --table-stripe: #FAFBFC;
  --success: #34D399;
  --danger: #EF4444;
  --warning: #FBBF24;
  --info: #94A3B8;
}

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

body {
  font-family: var(--font-body);
  background: var(--bg-primary);
  color: var(--text-body);
  min-height: 100vh;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Monospace class for data elements */
.mono {
  font-family: var(--font-mono);
}

/* App Shell Layout */
.app-shell {
  display: flex;
  min-height: 100vh;
}

.app-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  margin-left: var(--sidebar-width);
  transition: margin-left var(--transition-medium);
  min-width: 0;
  /* `clip` (not `hidden`) so this does NOT become a scroll container: `hidden`
     makes the computed overflow-y `auto`, which hijacks `position: sticky` for
     descendants (e.g. the chaptered TOC) and traps their internal scroll. `clip`
     still suppresses horizontal bleed but keeps the viewport as the scroll root. */
  overflow-x: clip;
}

.app-main {
  flex: 1;
  padding: var(--spacing-xl);
}

/* Buttons — `.btn-primary` / `.btn-secondary` evicted in D7.45 (CQ-23
   §6.4 task 3 — closes Phase 3). All authenticated-app call-sites now
   use `brand-btn brand-btn--{primary,secondary}` from brand.css. The
   sole survivor (`survey_responses/show.html.erb` on the public survey
   layout, which does not load brand.css) carries an inline `<style>`
   block that fully overrides any base `.btn-primary` cascade — safe. */

/* Cards */
.card {
  background: var(--bg-card);
  border: 1px solid var(--border-default);
  border-radius: var(--border-radius-lg);
  padding: var(--spacing-lg);
}

/* Form Inputs */
input, textarea, select {
  width: 100%;
  height: var(--button-height);
  padding: 0 var(--spacing-md);
  background: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border-default);
  border-radius: var(--border-radius-sm);
  font-family: var(--font-body);
  transition: all var(--transition-fast);
}

input:hover, textarea:hover, select:hover {
  border-color: var(--border-strong);
}

input:focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--batch);
}

input::placeholder, textarea::placeholder {
  color: var(--text-muted);
}

/* Full-bleed: break out of .app-main padding */
.body-content {
  margin-left: calc(-1 * var(--spacing-xl));
  margin-right: calc(-1 * var(--spacing-xl));
}

/* ══════════════════════════════════════
   BODY CONTENT
   ══════════════════════════════════════ */
.body-content {
  padding: 36px 48px 60px;
  background: var(--content-surface);
}

.section-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
  padding-top: 4px;
}

.section-header-accent {
  width: 4px;
  height: 22px;
  background: var(--batch);
  border-radius: 2px;
  flex-shrink: 0;
  transition: background-color 0.5s ease;
}

.section-header-text {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--content-text);
  letter-spacing: 0.01em;
}

.section-description {
  font-size: 14px;
  color: var(--content-secondary);
  margin-bottom: 20px;
  line-height: 1.6;
}

.section-label {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--content-muted);
}

.divider {
  height: 1px;
  background: var(--content-border);
  margin: 36px 0;
}

/* ══════════════════════════════════════
   TABLES
   ══════════════════════════════════════ */
.table-wrap {
  border: 1px solid var(--content-border);
  overflow-x: auto;
  background: var(--content-bg);
}

.data-table {
  width: 100%;
  border-collapse: collapse;
}

.data-table thead tr {
  background: var(--block-bg);
}

.data-table thead th {
  padding: 12px 16px;
  text-align: left;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--block-tag);
  white-space: nowrap;
}

.data-table tbody tr {
  border-bottom: 1px solid var(--content-border);
  border-left: 3px solid transparent;
  transition: background-color 0.15s, border-color 0.15s;
}

.data-table tbody tr:last-child { border-bottom: none; }
.data-table tbody tr:nth-child(even) { background: var(--table-stripe); }
.data-table tbody tr:hover {
  background: color-mix(in srgb, var(--batch) 6%, transparent);
  border-left-color: var(--batch);
}

.data-table tbody td {
  padding: 14px 16px;
  font-size: 14px;
  color: var(--content-secondary);
  vertical-align: middle;
}

.data-table .col-name {
  font-weight: 600;
  color: var(--content-text);
}

/* ══════════════════════════════════════
   BADGES
   ══════════════════════════════════════ */
.badge {
  display: inline-block;
  padding: 4px 10px;
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.badge-success { background: #E8F5E9; color: #2E7D32; }
.badge-batch { background: var(--batch); color: #0A0A0A; transition: background-color 0.5s ease; }

/* ══════════════════════════════════════
   DARK BLOCKS & ACTION CARDS
   ══════════════════════════════════════ */
.dark-block {
  background: var(--block-bg);
  padding: 24px 28px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 32px;
  gap: 16px;
}

.block-title {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--batch);
  margin-bottom: 4px;
  transition: color 0.5s ease;
}

.block-body {
  font-family: var(--font-body);
  font-size: 13px;
  color: rgba(255,255,255,0.55);
}

.action-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.action-card {
  background: var(--block-bg);
  padding: 32px 28px;
  cursor: pointer;
  transition: all 0.2s ease;
  border: 1px solid transparent;
  text-decoration: none;
  display: block;
}

.action-card:hover {
  border-color: var(--batch);
  transform: translateY(-2px);
  box-shadow: 0 4px 16px rgba(0,0,0,0.12);
}

.action-card-icon {
  font-size: 28px;
  margin-bottom: 16px;
  display: block;
  color: var(--batch);
  transition: color 0.5s ease;
}

.action-card-title {
  font-family: var(--font-display);
  font-size: 15px;
  color: #FFFFFF;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  margin-bottom: 8px;
}

.action-card-desc {
  font-family: var(--font-body);
  font-size: 13px;
  color: rgba(255,255,255,0.5);
  line-height: 1.5;
}

/* ══════════════════════════════════════
   RESPONSIVE
   ══════════════════════════════════════ */
@media (max-width: 900px) {
  .kpi-grid { grid-template-columns: repeat(2, 1fr); }
  .action-cards { grid-template-columns: 1fr; }
}

@media (max-width: 768px) {
  .body-content { padding: 24px; }
  .kpi-grid { grid-template-columns: 1fr; }
  .dark-block { flex-direction: column; align-items: flex-start; }
}

/* ══════════════════════════════════════
   CONVERSATION LAYOUT
   ══════════════════════════════════════ */
.conversation-layout {
  display: flex;
  flex-direction: column;
  /* viewport - app-header - app-main padding (top+bottom) - page hero
     box (~210px hero + 32px margin-bottom). Hero now lives in
     content_for(:hero) above the layout (D8 alignment with the
     dm-layout pattern), so the math mirrors .dm-layout. */
  height: calc(100vh - var(--header-height) - var(--spacing-xl) * 2 - 210px);
  min-height: 500px;
  background: var(--content-bg, var(--bg-card));
  border: 1px solid var(--content-border, var(--border-default));
  /* Full-bleed to the content edges, aligning with the full-bleed
     brand-compact-hero above (which breaks out of app-main padding). */
  margin-left: calc(-1 * var(--spacing-xl));
  margin-right: calc(-1 * var(--spacing-xl));
  overflow: hidden;
}

/* Embedded variant — for thread chrome that lives inside an already-sized
   flex parent (e.g. .dm-conversation-pane inside .dm-layout). Drops the
   standalone box (viewport-height, side margins, border) so the parent
   pane provides the bounds. Locked as part of CQ-23 §10.3 #1 (thread
   chrome design candidate). */
.conversation-layout--embedded {
  height: 100%;
  min-height: 0;
  margin-left: 0;
  margin-right: 0;
  border: none;
  background: transparent;
}

/* <turbo-frame> is inline by default — without this, the embedded
   .conversation-layout's height:100% has nothing to resolve against
   and the composer floats to natural-content height. */
.dm-conversation-pane > turbo-frame {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Thread chrome — D8 messaging unification. The bespoke dark
   .conversation-header was replaced by a page-level brand-compact-hero
   rendered via content_for(:hero), identical to every other rebranded
   page. The message stream / composer live in .conversation-layout
   below it. */

/* DM identity bar — per-thread chrome inside dm-conversation-pane.
   Lighter than the page hero (which sits above the whole dm-layout);
   mono eyebrow + display-font name. */
.dm-identity-bar {
  padding: 14px 24px;
  background: var(--content-bg, var(--bg-card));
  border-bottom: 1px solid var(--content-border, var(--border-default));
  flex-shrink: 0;
}

.dm-identity-bar-eyebrow {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--content-muted, var(--text-muted));
  margin-bottom: 4px;
}

.dm-identity-bar-title {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--content-text, var(--text-primary));
  letter-spacing: -0.01em;
  line-height: 1.1;
}

/* ══════════════════════════════════════
   PINNED ANNOUNCEMENTS
   ══════════════════════════════════════
   D7.5: .pinned-banner/.pinned-header/.pinned-icon/.pinned-body/
   .pinned-footer/.pinned-meta/.pinned-unpin removed — broadcasts/
   _broadcast_banner now renders a brand-kit `_status_card`.
   .pinned-area kept for conversations/show wrapper border.        */
.pinned-area {
  flex-shrink: 0;
  border-bottom: 1px solid var(--content-border, var(--border-default));
}

/* ══════════════════════════════════════
   MESSAGE STREAM
   ══════════════════════════════════════ */
.message-stream {
  flex: 1;
  overflow-y: auto;
  padding: 0 24px;
  display: flex;
  flex-direction: column;
  background: var(--content-bg, var(--bg-card));
}

.date-separator {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 0 8px;
}

.date-separator-line {
  flex: 1;
  height: 1px;
  background: var(--content-border, var(--border-default));
}

.date-separator-label {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--content-muted, var(--text-muted));
  flex-shrink: 0;
}

.message-group {
  display: flex;
  gap: 12px;
  padding: 10px 12px;
  border-left: 3px solid transparent;
  transition: background-color 0.12s ease, border-color 0.12s ease;
  /* #21 — positioning context for the hover-revealed admin delete control. */
  position: relative;
}

.message-group:hover {
  background: var(--content-surface, var(--bg-primary));
  border-left-color: var(--batch);
}

.message-group + .message-group {
  border-top: 1px solid var(--content-border, var(--border-default));
}

.message-group.consecutive {
  padding-top: 2px;
  padding-left: 63px;
  border-top: none;
}

.message-group.consecutive:hover {
  border-left-color: var(--batch);
}

.avatar-circle {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--batch);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: 12px;
  color: #0A0A0A;
  flex-shrink: 0;
  transition: background-color 0.5s ease;
}

.avatar-circle.sm {
  width: 34px;
  height: 34px;
  font-size: 11px;
}

/* #35 — per-speaker colour ("Bright Spectrum" palette, operator pick).
   speaker_colour_class hashes author_id -> one of 8 slots and stamps a
   .speaker-N class on the .message-group of human-author kinds
   (_text/_file_link/_kb_card). Avatar fill + author name then read the
   slot's custom props, giving each person a stable differentiator.
   Deliberately distinct from the 5 batch/system colours so the speaker
   palette and the batch theme never get confused. System kinds
   (hold/complete/kb_announce) carry no .speaker-* class and keep their
   semantic avatar colours. Name tints are the darker, saturated variants
   for contrast on the white (.conversation-layout) thread. */
.message-group.speaker-0 { --speaker-bg: #EF476F; --speaker-fg: #0A0A0A; --speaker-name: #C42852; }
.message-group.speaker-1 { --speaker-bg: #06D6A0; --speaker-fg: #0A0A0A; --speaker-name: #067D5E; }
.message-group.speaker-2 { --speaker-bg: #FFD166; --speaker-fg: #0A0A0A; --speaker-name: #9A7B1E; }
.message-group.speaker-3 { --speaker-bg: #118AB2; --speaker-fg: #0A0A0A; --speaker-name: #0C6486; }
.message-group.speaker-4 { --speaker-bg: #F78C6B; --speaker-fg: #0A0A0A; --speaker-name: #C25638; }
.message-group.speaker-5 { --speaker-bg: #9B5DE5; --speaker-fg: #0A0A0A; --speaker-name: #6E37AE; }
.message-group.speaker-6 { --speaker-bg: #83E377; --speaker-fg: #0A0A0A; --speaker-name: #3E8A33; }
.message-group.speaker-7 { --speaker-bg: #4CC9F0; --speaker-fg: #0A0A0A; --speaker-name: #1A7C9C; }

.message-group[class*="speaker-"] .avatar-circle {
  background: var(--speaker-bg);
  color: var(--speaker-fg);
}

.message-group[class*="speaker-"] .message-author {
  color: var(--speaker-name);
}

/* #21 — admin delete control. Hidden until the message-group is hovered (or
   the control itself is focused, for keyboard users). button_to wraps the
   button in a <form>, so reset that form's box. */
.message-delete-control {
  position: absolute;
  top: 8px;
  right: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 1px solid var(--content-border, #E5E7EB);
  border-radius: 50%;
  background: var(--content-bg, #FFFFFF);
  color: var(--content-muted, #6B7085);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}

.message-group:hover .message-delete-control,
.message-delete-control:focus-visible {
  opacity: 1;
}

.message-delete-control:hover {
  color: var(--danger, #EF4444);
  border-color: var(--danger, #EF4444);
}

/* #21 — soft-delete tombstone. Muted, italic, no per-speaker colour. */
.message-group--tombstone .tombstone-avatar {
  background: var(--content-surface, #F7F7F8);
  color: var(--content-muted, #6B7085);
}

.message-group--tombstone .tombstone-text {
  color: var(--content-muted, #6B7085);
  font-style: italic;
  font-weight: 500;
}

.message-content {
  flex: 1;
  min-width: 0;
}

.message-meta {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 2px;
}

.message-author {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  color: var(--content-text, var(--text-primary));
}

.message-timestamp {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--content-muted, var(--text-muted));
}

.message-body {
  font-family: var(--font-body);
  font-size: 13.5px;
  color: var(--content-secondary, var(--text-body));
  line-height: 1.6;
}

.message-body p { margin-bottom: 0; }
.message-body p + p { margin-top: 8px; }

.mention-highlight {
  background: var(--batch-subtle);
  color: var(--content-text, var(--text-primary));
  font-weight: 600;
  padding: 1px 6px;
  font-size: 13px;
  transition: background-color 0.5s ease;
}

/* File attachment cards */
.attachment-file {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--content-border, var(--border-default));
  background: var(--content-bg, var(--bg-card));
  padding: 8px 12px;
  margin-top: 6px;
  max-width: 300px;
  cursor: pointer;
  transition: border-color 0.5s ease;
  text-decoration: none;
}

.attachment-file:hover { border-color: var(--batch); }

.attachment-icon {
  width: 28px;
  height: 28px;
  background: var(--batch-subtle);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 8px;
  font-weight: 700;
  color: var(--content-text, var(--text-primary));
  letter-spacing: 0.06em;
  flex-shrink: 0;
  transition: background-color 0.5s ease;
}

.attachment-info { min-width: 0; }

.attachment-name {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 500;
  color: var(--content-text, var(--text-primary));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.attachment-size {
  font-family: var(--font-mono);
  font-size: 8px;
  color: var(--content-muted, var(--text-muted));
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.attachment-download {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--batch);
  margin-left: auto;
  flex-shrink: 0;
  transition: color 0.5s ease;
  text-decoration: none;
}

.attachment-image {
  margin-top: 6px;
  display: block;
}

.attachment-image img {
  max-width: 280px;
  max-height: 180px;
  display: block;
  border: 1px solid var(--content-border, var(--border-default));
  object-fit: cover;
  /* A failed/unauthorized fetch (cross-visibility viewer hitting the
     authenticated inline endpoint) collapses to a quiet alt-text box
     instead of a broken-image glyph. */
  background: var(--content-surface, #F7F7F8);
  color: var(--content-muted, #6B7085);
  font-size: 12px;
}

/* Load older messages */
.load-older {
  display: flex;
  justify-content: center;
  padding: 14px 0 6px;
}

.load-older-btn {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--content-muted, var(--text-muted));
  background: var(--content-surface, var(--bg-primary));
  border: 1px solid var(--content-border, var(--border-default));
  padding: 6px 18px;
  cursor: pointer;
  text-decoration: none;
  transition: border-color 0.5s ease, color 0.15s, background 0.15s;
}

.load-older-btn:hover { border-color: var(--batch); color: var(--content-text, var(--text-primary)); background: var(--batch-subtle); }

/* Typing indicator */
.typing-indicator {
  padding: 4px 24px;
  font-family: var(--font-body);
  font-size: 12px;
  font-style: italic;
  color: var(--content-muted, var(--text-muted));
  min-height: 24px;
  flex-shrink: 0;
  background: var(--content-bg, var(--bg-card));
}

/* New messages indicator */
.new-messages-indicator {
  display: flex;
  justify-content: center;
  padding: 6px 0;
  flex-shrink: 0;
  background: var(--content-bg, var(--bg-card));
}

.new-messages-pill {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: #0A0A0A;
  background: var(--batch);
  border: none;
  padding: 4px 14px;
  cursor: pointer;
  transition: background-color 0.5s ease;
}

.new-messages-pill:hover { opacity: 0.85; }

/* ══════════════════════════════════════
   MESSAGE COMPOSER
   ══════════════════════════════════════ */
.message-composer {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 10px 24px 12px;
  background: var(--block-bg);
  flex-shrink: 0;
}

.message-textarea {
  flex: 1;
  width: auto;
  height: auto;
  font-family: var(--font-body);
  font-size: 13.5px;
  color: #1A1A1A;
  background: #FFFFFF;
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 0;
  padding: 9px 14px;
  resize: none;
  outline: none;
  line-height: 1.5;
  min-height: 40px;
  max-height: 120px;
  transition: border-color 0.5s ease;
}

.message-textarea:focus { border-color: var(--batch); }
.message-textarea::placeholder { color: rgba(26, 26, 26, 0.45); }

.composer-btn {
  width: 38px;
  min-width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 0;
  color: rgba(255,255,255,0.45);
  cursor: pointer;
  flex-shrink: 0;
  transition: border-color 0.5s ease, color 0.15s;
}

.composer-btn:hover { border-color: var(--batch); color: var(--block-text, #FFFFFF); }

.composer-send {
  width: auto;
  height: 38px;
  padding: 0 20px;
  background: var(--batch);
  border: none;
  border-radius: 0;
  font-family: var(--font-display);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #0A0A0A;
  cursor: pointer;
  flex-shrink: 0;
  transition: background-color 0.5s ease;
}

.composer-send:hover { opacity: 0.9; }

/* ══════════════════════════════════════
   DM SPLIT-PANE
   ══════════════════════════════════════ */
.dm-layout {
  display: flex;
  /* viewport - app-header - app-main padding (top+bottom) - page hero
     box (~210px hero + 32px margin-bottom). The page-level compact-hero
     anchors /messages now; the layout fills the rest of the viewport.
     Full-bleed to the content edges, aligning with the full-bleed
     brand-compact-hero above. */
  height: calc(100vh - var(--header-height) - var(--spacing-xl) * 2 - 210px);
  min-height: 500px;
  margin-left: calc(-1 * var(--spacing-xl));
  margin-right: calc(-1 * var(--spacing-xl));
  border: 1px solid var(--content-border, var(--border-default));
  background: var(--content-bg, var(--bg-card));
  overflow: hidden;
}

.dm-conversation-pane {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  border-right: 1px solid var(--content-border, var(--border-default));
}

/* ══════════════════════════════════════
   THREAD LIST SIDEBAR
   ══════════════════════════════════════ */
.thread-list-sidebar {
  width: 320px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
}

/* D8 — page hero owns "+ New Message"; the rail just labels the list.
   No dark band; clean mono section label flush with brand typography. */
.thread-list-rail-head {
  padding: 18px 20px 12px;
  flex-shrink: 0;
  border-bottom: 1px solid var(--content-border, var(--border-default));
  background: var(--content-bg, var(--bg-card));
}

.thread-list-rail-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--content-muted, var(--text-muted));
}

.thread-list {
  flex: 1;
  overflow-y: auto;
  background: var(--content-bg, var(--bg-card));
}

.thread-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--content-border, var(--border-default));
  cursor: pointer;
  border-left: 3px solid transparent;
  text-decoration: none;
  color: inherit;
  transition: background-color 0.15s, border-color 0.5s ease;
}

.thread-item:hover { background: var(--content-surface, var(--bg-primary)); }

.thread-item.active {
  background: var(--batch-subtle);
  border-left-color: var(--batch);
}

.thread-item.unread .thread-item-name { font-weight: 700; }

.thread-item-body { flex: 1; min-width: 0; }

.thread-item-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 2px;
}

.thread-item-name {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  color: var(--content-text, var(--text-primary));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.thread-item-time {
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--content-muted, var(--text-muted));
  flex-shrink: 0;
  margin-left: 8px;
}

.thread-item-preview {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--content-muted, var(--text-muted));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.thread-unread-badge {
  background: var(--batch);
  color: #0A0A0A;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  padding: 2px 7px;
  flex-shrink: 0;
  align-self: center;
  margin-left: 6px;
  transition: background-color 0.5s ease;
}

/* D7.9 — Flex-fill wrapper that centers the shared _empty_state primitive
   inside the .dm-conversation-pane when no thread is active. Replaces the
   bespoke .dm-empty-state + .dm-empty-icon + .dm-empty-title + .dm-empty-body
   + .dm-empty-btn family (CQ-23 §6.1). */
.dm-empty-state-wrap {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

/* D7.9 — Sidebar's "No conversations yet" fallback. Tiny class-based
   replacement for the previous inline-style block; _empty_state would be
   visually heavy in the 320px sidebar column. */
.thread-list-empty {
  padding: 32px 20px;
  text-align: center;
  color: var(--content-muted, var(--text-muted));
}

.thread-list-empty-text {
  font-family: var(--font-body);
  font-size: 13px;
  margin: 0 0 8px;
}

.thread-list-empty-link {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--batch);
  text-decoration: none;
}

.thread-list-empty-link:hover { text-decoration: underline; }

/* ══════════════════════════════════════
   NEW REQUEST FORM
   ══════════════════════════════════════ */
.request-layout {
  max-width: 680px;
  margin: 0 auto;
  padding: 32px 0 48px;
}

.request-hero {
  background: var(--block-bg);
  padding: 24px 28px;
  margin-bottom: 24px;
  border-left: 4px solid var(--batch);
  transition: border-color 0.5s ease;
}

.request-hero-label {
  font-family: var(--font-mono);
  font-size: 8px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--batch);
  margin-bottom: 6px;
  transition: color 0.5s ease;
}

.request-hero-title {
  font-family: var(--font-display);
  font-size: 24px;
  color: var(--block-text, #FFFFFF);
  letter-spacing: -0.02em;
  text-transform: uppercase;
  margin-bottom: 6px;
}

.request-hero-subtitle {
  font-family: var(--font-body);
  font-size: 13px;
  color: rgba(255,255,255,0.55);
  line-height: 1.5;
}

.request-error-box {
  border: 1px solid var(--danger, var(--color-danger));
  border-left: 4px solid var(--danger, var(--color-danger));
  background: rgba(239,68,68,0.04);
  padding: 12px 16px;
  margin-bottom: 20px;
}

.request-error-title {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--danger, var(--color-danger));
  margin-bottom: 4px;
}

.request-error-list {
  list-style: none;
  padding: 0;
}

.request-error-list li {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--danger, var(--color-danger));
  padding: 1px 0;
}

.request-error-list li::before { content: "\2022  "; }

.request-card {
  background: var(--content-bg, var(--bg-card));
  border: 1px solid var(--content-border, var(--border-default));
  padding: 28px;
}

.request-section-label {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--content-border, var(--border-default));
}

.request-section-label::before {
  content: '';
  width: 4px;
  height: 22px;
  background: var(--batch);
  border-radius: 2px;
  flex-shrink: 0;
  transition: background-color 0.5s ease;
}

.request-section-label-text {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--content-text, var(--text-primary));
  letter-spacing: 0.01em;
}

.form-field { margin-bottom: 22px; }

.form-label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  color: var(--content-text, var(--text-primary));
  margin-bottom: 6px;
}

.form-required { color: var(--danger, var(--color-danger)); font-size: 12px; }

.form-hint {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--content-muted, var(--text-muted));
  margin-top: 4px;
}

.form-input,
.form-select,
.form-textarea {
  width: 100%;
  height: auto;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--content-text, var(--text-primary));
  background: var(--content-bg, var(--bg-card));
  border: 1px solid var(--content-border, var(--border-default));
  border-radius: 0;
  padding: 10px 14px;
  outline: none;
  transition: border-color 0.5s ease;
  appearance: none;
}

.form-input:focus,
.form-select:focus,
.form-textarea:focus { border-color: var(--batch); }

.form-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%236B7085' d='M0 0l6 8 6-8z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 36px;
  cursor: pointer;
}

.form-textarea { resize: vertical; line-height: 1.6; }

.form-file-zone {
  width: 100%;
  border: 2px dashed var(--content-border, var(--border-default));
  background: var(--content-surface, var(--bg-primary));
  padding: 24px;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.5s ease, background 0.15s;
  position: relative;
}

.form-file-zone:hover { border-color: var(--batch); background: var(--batch-subtle); }

.form-file-zone-icon {
  font-size: 24px;
  color: var(--content-muted, var(--text-muted));
  margin-bottom: 6px;
}

.form-file-zone-text {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--content-muted, var(--text-muted));
}

.form-file-zone-text strong {
  color: var(--content-text, var(--text-primary));
  font-weight: 600;
}

.form-file-zone input[type="file"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
  width: 100%;
  height: 100%;
}

.request-actions {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 8px;
  padding-top: 24px;
  border-top: 1px solid var(--content-border, var(--border-default));
}

.btn-cancel {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--content-muted, var(--text-muted));
  background: transparent;
  border: none;
  cursor: pointer;
  text-decoration: none;
  transition: color 0.15s;
}

.btn-cancel:hover { color: var(--content-text, var(--text-primary)); }

/* ══════════════════════════════════════
   NEW DM FORM
   ══════════════════════════════════════ */
.dm-new-page {
  max-width: 680px;
  margin: 0 auto;
  padding: 32px 0 48px;
}

/* Scrollbar */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: var(--bg-primary);
}

::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--text-muted);
}

/* Animations */
@keyframes fadeSlideIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes expandIn {
  from {
    opacity: 0;
    transform: scale(0.95);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

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

/* Utility Classes */
.text-muted {
  color: var(--text-muted);
}

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

.coming-soon {
  opacity: 0.5;
  position: relative;
}

.coming-soon::after {
  content: "Coming Soon";
  font-size: 10px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-left: var(--spacing-sm);
}

/* Flash Messages — branded flat banners (D5.3) */
.brand-flash {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 20px;
  margin-bottom: var(--spacing-lg);
  background: var(--content-bg);
  border: 1px solid var(--content-border);
  border-left-width: 4px;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.5;
  color: var(--content-text);
}

.brand-flash::before {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 4px 9px;
}

.brand-flash-notice {
  border-left-color: var(--color-success);
}

.brand-flash-notice::before {
  content: "Notice";
  background: color-mix(in srgb, var(--color-success) 16%, transparent);
  color: #047857;
}

.brand-flash-alert,
.brand-flash-error {
  border-left-color: var(--color-danger);
}

.brand-flash-alert::before {
  content: "Alert";
  background: color-mix(in srgb, var(--color-danger) 12%, transparent);
  color: var(--color-danger);
}

.brand-flash-error::before {
  content: "Error";
  background: color-mix(in srgb, var(--color-danger) 12%, transparent);
  color: var(--color-danger);
}

/* Pagination — branded pagy series-nav chrome (D5.3) */
.pagination-wrapper {
  margin-top: var(--spacing-lg);
  padding: var(--spacing-md);
  display: flex;
  justify-content: center;
}

.pagination-wrapper nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--spacing-xs);
}

.pagination-wrapper nav a,
.pagination-wrapper nav span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 36px;
  padding: 0 10px;
  border: 1px solid var(--content-border);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  color: var(--content-secondary);
  text-decoration: none;
  transition: all var(--transition-fast);
}

.pagination-wrapper nav a:not([aria-disabled="true"]):hover {
  border-color: var(--batch);
  background: var(--batch-subtle);
  color: var(--content-text);
}

.pagination-wrapper nav a.current,
.pagination-wrapper nav span.current,
.pagination-wrapper nav [aria-current="page"] {
  background: var(--block-bg);
  border-color: var(--block-bg);
  color: var(--batch);
}

.pagination-wrapper nav a[aria-disabled="true"]:not([aria-current="page"]) {
  color: var(--text-muted);
  cursor: default;
}

.pagination-wrapper nav .gap {
  border-color: transparent;
  color: var(--text-muted);
}

/* Empty states — branded placeholder for empty listings (D5.3) */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 56px 32px;
  background: var(--content-surface);
  border: 1px solid var(--content-border);
}

.empty-state-title {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--content-text);
}

.empty-state-body {
  margin: 10px auto 0;
  max-width: 440px;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.6;
  color: var(--content-muted);
}

.empty-state .brand-btn--primary {
  margin-top: 20px;
}

/* Toast Notifications */
.toast-container {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 9999;
  display: flex;
  flex-direction: column-reverse;
  gap: 8px;
  pointer-events: none;
}

.toast-notification {
  background: var(--bg-card);
  border: var(--border-weight) solid var(--batch);
  border-radius: 8px;
  padding: 12px 16px;
  min-width: 300px;
  max-width: 400px;
  opacity: 0;
  transform: translateX(100%);
  transition: all 0.3s ease;
  pointer-events: auto;
  box-shadow: var(--shadow-elevated);
}

.toast-visible {
  opacity: 1;
  transform: translateX(0);
}

.toast-hiding {
  opacity: 0;
  transform: translateX(100%);
}

.toast-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;
}

.toast-title {
  color: var(--batch);
  font-weight: 600;
  font-size: 0.9375rem;
}

.toast-close {
  background: transparent;
  border: none;
  color: var(--text-muted);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color var(--transition-fast);
}

.toast-close:hover {
  color: var(--text-primary);
}

.toast-body {
  color: var(--text-secondary);
  font-size: 0.875rem;
  line-height: 1.4;
}

.toast-warning { border-color: var(--warning, #FBBF24); }
.toast-warning .toast-title { color: var(--warning, #FBBF24); }
.toast-error { border-color: var(--danger, #EF4444); }
.toast-error .toast-title { color: var(--danger, #EF4444); }

/* ══════════════════════════════════════
   Auth pages — page-local chrome only (CQ-23 closeout).
   Inputs, labels, buttons, errors all live on brand-kit primitives
   (brand-form-*, brand-btn--*). What remains here is the per-page
   header (title + subtitle outside the card), the "or" divider that
   splits the email/password form from the SSO button, the SSO
   button's row layout, and the footer link rhythm.
   ══════════════════════════════════════ */
.auth-page {
  width: 100%;
}

.auth-page-header {
  margin-bottom: 24px;
}

.auth-page-title {
  font-family: var(--font-display, 'Archivo Black', 'Arial Black', Impact, sans-serif);
  font-size: 22px;
  color: var(--content-text, #0A0A0A);
  margin-bottom: 8px;
}

.auth-page-subtitle {
  font-size: 14px;
  color: var(--content-secondary, #4A4E5A);
  margin: 0;
}

.auth-divider {
  text-align: center;
  padding: 16px 0;
  color: var(--content-muted, #6B7085);
  font-size: 13px;
  position: relative;
}

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

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

/* Auth pages keep prominent full-width submit + SSO buttons — the
   form lives inside a narrow 448px right-panel column. */
.auth-page .brand-form-actions {
  display: block;
}

.auth-page .brand-form-actions .brand-btn {
  width: 100%;
}

.auth-sso-btn {
  width: 100%;
}

.auth-hint {
  text-align: center;
  font-size: 12px;
  color: var(--content-muted, #9CA3AF);
  margin-top: 8px;
}

.auth-link {
  text-align: center;
  margin-top: 16px;
  font-size: 13px;
  color: var(--content-muted, #6B7085);
}

.auth-link a {
  color: var(--batch, #00F5D4);
  text-decoration: none;
  font-weight: 500;
  transition: color 0.5s ease;
}

/* ══════════════════════════════════════
   Surveys — Out Sauce
   ══════════════════════════════════════ */

.surveys-page .page-header h1 {
  font-family: var(--font-display, 'Archivo Black', sans-serif);
  color: #0A0A0A;
}

.surveys-page .data-table th {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: #6B7280;
}

.surveys-page .data-table td {
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: 13px;
  color: #0A0A0A;
}

.surveys-page .data-table tbody tr:hover {
  border-left: 3px solid var(--batch, #00F5D4);
}

.surveys-page .surveys-table-card {
  background: #FFFFFF;
  border: 1px solid #E5E7EB;
}

.survey-show-page .survey-form-card {
  background: #FFFFFF;
  border: 1px solid #E5E7EB;
}

.survey-banner {
  background: #0A0A0A;
  border-bottom: 3px solid var(--batch, #00F5D4);
}

.survey-banner-text h3 {
  font-family: var(--font-display, 'Archivo Black', sans-serif);
  color: rgba(255, 255, 255, 0.9);
}

.survey-banner-text p {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.5);
}

.survey-card {
  background: #FFFFFF;
  border: 1px solid #E5E7EB;
}

.survey-card .meta-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: #6B7280;
}

/* W4-3 message kind components — file_link, kb_card, system_kb_announce */

/* T13 — file_link kind: subtle <hr> + paperclip + filename hyperlink */
.message-file-link {
  display: inline-flex;
  align-items: center;
  color: var(--batch, #00F5D4);
  font-size: 13px;
  text-decoration: none;
  padding: 2px 0;
}

.message-file-link:hover {
  text-decoration: underline;
}

.message-file-link--unavailable {
  color: rgba(255, 255, 255, 0.4);
  font-style: italic;
  pointer-events: none;
}

.message-file-link-name {
  font-family: var(--font-mono);
  font-size: 12px;
}

.message-file-link-status {
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* Screenshot thumbnails (paste + lightbox feature). The clickable wrapper is
   a <button>, never an <a> — an anchor inside the DM turbo frame would get
   intercepted and swap the pane with the image response. Sizing rides on the
   existing .attachment-image img rules; if a rule misbehaves on job threads
   only, check jobs.css (loads after this bundle, alphabetical) and use the
   two-class specificity trick documented at the breadcrumb avatar below. */
.attachment-thumb-btn {
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
  display: block;
}

.attachment-thumb-btn:focus-visible {
  outline: 2px solid var(--batch, #00F5D4);
  outline-offset: 2px;
}

/* Reserved-box fallback when blob metadata (width/height) isn't analyzed yet —
   stops late image decode pushing the reading position under newest-at-top. */
.attachment-thumb-btn--reserve {
  min-height: 120px;
}

/* Fixed "Scanning..." placeholder for a pending Document thumbnail; the
   scan-status controller swaps it for the real image once the scan lands. */
.attachment-thumb--scanning {
  width: 280px;
  height: 120px;
  margin-top: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--content-border, #E5E7EB);
  color: var(--content-muted, #6B7085);
  font-family: var(--font-mono);
  font-size: 12px;
}

/* T26/T27 — kb_card and system_kb_announce card. Renders inside the (light,
   theme-stable) message thread, so it uses content-* surface tokens. Sub-
   element selectors are scoped under .kb-card to avoid colliding with the
   identically-named .kb-card-title used by the KB index article card. */
.kb-card {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: var(--content-surface, #F7F7F8);
  border: 1px solid var(--content-border, #E5E7EB);
  color: var(--content-text, #1A1D26);
  text-decoration: none;
  max-width: 480px;
}

.kb-card:hover {
  background: color-mix(in srgb, var(--batch) 8%, var(--content-surface, #F7F7F8));
  border-color: var(--batch, #00F5D4);
}

.kb-card--unavailable {
  pointer-events: none;
  opacity: 0.5;
}

.kb-card .kb-card-icon {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--content-secondary, #4A4E5A);
}

.kb-card .kb-card-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.kb-card .kb-card-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--content-text, #1A1D26);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.kb-card .kb-card-scope {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--content-muted, #6B7085);
}

.kb-card .kb-card-scope--firm { color: var(--content-secondary, #4A4E5A); }
.kb-card .kb-card-scope--shared { color: var(--content-secondary, #4A4E5A); }
.kb-card .kb-card-scope--os_internal { color: var(--danger, #EF4444); }

/* ══════════════════════════════════════
   THE JOB-THREAD BREADCRUMB (REWORK-6 / Q12.3)

   One block, serving every system event in a thread. It replaces three
   near-identical blocks (.hold-*, .complete-*, and the kb-announce avatar),
   and it covers the two kinds — system_reassign and system_pipeline — that
   shipped with NO css at all and rendered as round aqua avatars outside the
   family entirely. Adding quote and rework to the old shape would have made
   seven skeletons and seven chances to forget the stylesheet entry.

   Q12.6 — roughly eleven events against four semantic colours plus the brand
   aqua. Colour therefore carries only the COARSE family and the icon + label
   carry the actual distinction:

     warning  needs someone to act        hold placed, quote submitted/revised,
                                          rework lodged, rework classified
     success  a good outcome landed       job complete, quote accepted,
                                          rework closed
     info     neutral, nobody must act    work resumed, job reassigned,
                                          upcoming pipeline
     danger   a bad outcome landed        quote rejected
     batch    knowledge, not job state    new KB article

   ⚠️ The green collision Q12.6 names (system_complete and hold-resumed
   identical, separated only by the glyph) is fixed by moving RESUME to slate,
   not by moving completion off green: completion is THE good-outcome event in
   a job thread, and a resume is a return to the status quo rather than an
   achievement. --info and --danger were both unused before this.

   Styles live here rather than inline in the partial so the partial emits no
   <style> sibling, which would break the .message-group + .message-group
   adjacency (divider) selector.
   ══════════════════════════════════════ */

/* Square, semantic-tinted "avatar" so a breadcrumb reads as a system event at
   a glance against the round initials avatars of people. Two-class specificity so it
   wins over the single-class .avatar-circle redefined in jobs.css on job-thread
   conversations; size is left to inherit so it matches the thread's others. */
.message-breadcrumb .avatar-circle.breadcrumb-avatar {
  border-radius: 0;
  background: var(--breadcrumb-colour, var(--content-text));
  color: #0A0A0A;
}

.breadcrumb-label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--breadcrumb-colour, var(--content-secondary));
}

.breadcrumb-body {
  font-family: var(--font-body);
}

.breadcrumb-headline {
  margin: 0;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--content-text);
  line-height: 1.4;
}

.breadcrumb-detail {
  margin: 2px 0 0;
  font-size: 13px;
  color: var(--content-secondary);
  line-height: 1.5;
}

/* Free multi-paragraph body (the contractor's completion note). */
.breadcrumb-body p:not(.breadcrumb-headline):not(.breadcrumb-detail) {
  margin: 0;
  font-size: 13.5px;
  color: var(--content-secondary);
  line-height: 1.6;
}

.breadcrumb-body p:not(.breadcrumb-headline):not(.breadcrumb-detail) + p {
  margin-top: 8px;
}

/* One custom property per variant — the two rules above read it, so a new
   breadcrumb family is one line here and nothing else. */
.message-breadcrumb--hold            { --breadcrumb-colour: var(--warning); }
.message-breadcrumb--resume          { --breadcrumb-colour: var(--info); }
.message-breadcrumb--complete        { --breadcrumb-colour: var(--success); }
.message-breadcrumb--reassign        { --breadcrumb-colour: var(--info); }
.message-breadcrumb--pipeline        { --breadcrumb-colour: var(--info); }
.message-breadcrumb--kb-announce     { --breadcrumb-colour: var(--batch); }
.message-breadcrumb--quote           { --breadcrumb-colour: var(--warning); }
.message-breadcrumb--quote-accepted  { --breadcrumb-colour: var(--success); }
.message-breadcrumb--quote-rejected  { --breadcrumb-colour: var(--danger); }
.message-breadcrumb--rework          { --breadcrumb-colour: var(--warning); }
.message-breadcrumb--rework-closed   { --breadcrumb-colour: var(--success); }

/* --info and --danger are light enough / dark enough respectively that the
   #0A0A0A glyph above needs help only on danger. */
.message-breadcrumb--quote-rejected .avatar-circle.breadcrumb-avatar {
  color: #FFFFFF;
}

/* ══════════════════════════════════════
   File-upload preview list (REG-03 — shared by message composer +
   new-request form). Lifted from app/views/messages/_form.html.erb so
   the new-request file picker can reuse the same Stimulus controller
   (file_upload_controller.js). Form-specific blocks (.composer-input-row,
   .preview-category for T13) stay inline at messages/_form.html.erb.
   ══════════════════════════════════════ */
.file-preview-area {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 8px;
}

.file-preview-area:empty { margin-bottom: 0; }

.file-preview-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
}

.preview-image {
  width: 48px;
  height: 48px;
  object-fit: cover;
  flex-shrink: 0;
}

.preview-icon {
  font-size: 1.5rem;
  flex-shrink: 0;
  width: 48px;
  text-align: center;
  color: rgba(255, 255, 255, 0.6);
}

.preview-icon.pdf { color: #e74c3c; }

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

.preview-name {
  color: #FFFFFF;
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.preview-size {
  color: rgba(255, 255, 255, 0.4);
  font-size: 10px;
  font-family: var(--font-mono);
}

.preview-remove {
  width: 24px;
  height: 24px;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: rgba(255, 255, 255, 0.5);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
}

.preview-remove:hover {
  border-color: var(--batch);
  color: var(--batch);
}

/* ══════════════════════════════════════
   #31 — Horizontal file cards (new-job "Attach Files" only).
   Opted into via .file-preview-area--cards + the controller's
   card-style value; the dark message composer keeps the row layout
   above. Each staged file is a bordered card with a coloured
   file-extension badge (or image thumbnail), filename, and size.
   ══════════════════════════════════════ */
.file-preview-area--cards {
  flex-direction: row;
  flex-wrap: wrap;
  gap: 12px;
}

.file-card {
  position: relative;
  width: 130px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 18px 12px 14px;
  background: #FFFFFF;
  border: 1px solid var(--content-border);
  border-radius: 8px;
  text-align: center;
}

.file-card-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  overflow: hidden;
  flex-shrink: 0;
}

.file-card-badge img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.file-card--pdf   .file-card-badge { color: #DC2626; background: color-mix(in srgb, #DC2626 12%, transparent); }
.file-card--sheet .file-card-badge { color: #16A34A; background: color-mix(in srgb, #16A34A 12%, transparent); }
.file-card--doc   .file-card-badge { color: #2563EB; background: color-mix(in srgb, #2563EB 12%, transparent); }
.file-card--image .file-card-badge { color: var(--text-muted); background: var(--content-border); }
.file-card--default .file-card-badge { color: #6B7280; background: color-mix(in srgb, #6B7280 12%, transparent); }

.file-card-name {
  width: 100%;
  font-size: 12px;
  font-weight: 500;
  color: var(--content-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-card-size {
  font-size: 11px;
  color: var(--text-muted);
  font-family: var(--font-mono);
}

.file-card-remove {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 4px;
  color: var(--text-muted);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}

.file-card-remove:hover {
  color: #DC2626;
  background: color-mix(in srgb, #DC2626 10%, transparent);
}

/* New-request form-specific dropzone wrapper (REG-03) — visible "Choose
   Files" affordance + drag-and-drop hint. Composer reuses .composer-input-row
   for its own dropzone and is unaffected. */
.file-upload-dropzone {
  /* #30 — match the form inputs above (1.5px solid var(--content-border)) so the
     drop area reads as clearly present; kept dashed for the drop-zone affordance. */
  border: 1.5px dashed var(--content-border);
  padding: var(--spacing-md);
  background: var(--bg-card);
  transition: border-color var(--transition-fast), background var(--transition-fast);
}

.file-upload-dropzone.drag-over {
  border-color: var(--batch);
  background: var(--batch-subtle);
}

.file-upload-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-sm);
  padding: var(--spacing-sm) var(--spacing-md);
  cursor: pointer;
  color: var(--text-primary);
  font-weight: 500;
}

.file-upload-trigger:hover { color: var(--batch); }

.file-upload-hint {
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 400;
}

/* ══════════════════════════════════════
   LIGHTBOX (screenshot paste feature)

   One page-level native <dialog> host (shared/_lightbox, layout-rendered in
   the authed branch next to the toast host). Opened by click@document
   delegation on [data-lightbox-src] thumbnails; closed by Esc (native),
   backdrop click, and turbo:before-cache. Flat design doctrine: no radius,
   2px border, no glow.
   ══════════════════════════════════════ */

.lightbox-dialog {
  /* Native <dialog> centres via `margin: auto`; the global `* { margin: 0 }`
     reset kills that — restore it explicitly (feedback-dialog precedent). */
  inset: 0;
  margin: auto;
  padding: 0;
  border: 2px solid #0A0A0A;
  background: #FFFFFF;
}

.lightbox-dialog::backdrop {
  background: rgba(10, 10, 10, 0.55);
  cursor: pointer;
}

.lightbox-dialog img {
  display: block;
  max-width: 90vw;
  max-height: 85vh;
  cursor: default;
}
