/* The Watch — purple shell. Design tokens + chrome ported from Cyber Exposure. */

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --bg: #ffffff;
  --bg-card: var(--bg);
  --bg-page: #f5f6fa;
  --bg-hover: #f0f1f5;
  --text: #1a1a2e;
  --text-secondary: #4a4a68;
  --text-muted: #8e8ea0;
  --border: #e2e4ea;
  --border-light: #eef0f4;
  --accent: #6c47ff;
  --accent-light: rgba(108,71,255,0.08);
  --accent-hover: #5a38e0;
  --critical: #ef4444;
  --critical-bg: rgba(239,68,68,0.1);
  --high: #f59e0b;
  --high-bg: rgba(245,158,11,0.1);
  --medium: #eab308;
  --medium-bg: rgba(234,179,8,0.1);
  --low: #6b7280;
  --low-bg: rgba(107,114,128,0.08);
  --success: #22c55e;
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.04);
  --shadow: 0 2px 8px rgba(0,0,0,0.06);
  --shadow-md: 0 4px 16px rgba(0,0,0,0.08);
  --radius: 8px;
  --radius-lg: 12px;
  --transition: 0.15s ease;
}

[data-theme="dark"] {
  color-scheme: dark;
  --bg: #1a1a2e;
  --bg-page: #12121f;
  --bg-hover: #22223a;
  --text: #e8e8f0;
  --text-secondary: #b0b0c8;
  --text-muted: #8c8ca8;
  --border: #2a2a42;
  --border-light: #22223a;
  --accent: #8b6aff;
  --accent-light: rgba(139,106,255,0.12);
  --accent-hover: #7c5af0;
  --critical: #f87171;
  --critical-bg: rgba(248,113,113,0.15);
  --high: #fbbf24;
  --high-bg: rgba(251,191,36,0.15);
  --medium: #facc15;
  --medium-bg: rgba(250,204,21,0.12);
  --low: #9ca3af;
  --low-bg: rgba(156,163,175,0.12);
  --success: #4ade80;
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.2);
  --shadow: 0 2px 8px rgba(0,0,0,0.3);
  --shadow-md: 0 4px 16px rgba(0,0,0,0.4);
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  background: var(--bg-page);
  color: var(--text);
  line-height: 1.5;
  min-height: 100vh;
}

/* App shell stacks vertically once auth resolves; #mainContent absorbs the
   remaining height so the footer always pins to the viewport bottom. */
#appShell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
#mainContent { flex: 1; }

/* Auth loading screen — visible until Keycloak resolves. */
.auth-screen {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-page);
  color: var(--text-muted);
}
.auth-screen-inner { text-align: center; }
.auth-spinner {
  width: 48px;
  height: 48px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  margin: 0 auto 16px;
  animation: spin 0.8s linear infinite;
}
.auth-message { font-size: 15px; }
.auth-error {
  font-size: 18px;
  margin-bottom: 8px;
  color: var(--critical);
}
.auth-error-detail { font-size: 13px; color: var(--text-muted); }
.auth-error-retry {
  margin-top: 16px;
  padding: 8px 20px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  font-family: inherit;
}

.material-icons-round {
  font-family: 'Material Icons Round';
  font-weight: normal;
  font-style: normal;
  display: inline-block;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  word-wrap: normal;
  direction: ltr;
  -webkit-font-feature-settings: 'liga';
  font-feature-settings: 'liga';
  -webkit-font-smoothing: antialiased;
}

/* TOP HEADER */
.top-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
  height: 52px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 100;
}

.header-left { display: flex; align-items: center; gap: 8px; }
.header-title-group { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.header-title { font-weight: 600; font-size: 15px; color: var(--text); letter-spacing: -0.2px; }
.header-dot {
  font-size: 18px;
  font-weight: 400;
  color: var(--text-muted);
  line-height: 1;
  /* Nudge up slightly — `·` sits below typographic centre in most fonts. */
  transform: translateY(-1px);
}
.header-subtitle {
  font-weight: 500;
  font-size: 13px;
  color: var(--text-muted);
  letter-spacing: 0;
}

.header-center {
  position: absolute; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; pointer-events: none;
}
.cih-logo { height: 38px; width: auto; flex-shrink: 0; opacity: 0.85; }
[data-theme="dark"] .cih-logo { filter: invert(1); }

.header-right { display: flex; align-items: center; gap: 10px; }

.btn {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text-secondary);
  font-size: 13px; font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: all var(--transition);
  white-space: nowrap;
}
.btn:hover { background: var(--bg-hover); }

.header-btn {
  border: none;
  background: none;
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 400;
}
.header-btn:hover { background: var(--bg-hover); color: var(--text); border: none; }
.btn .material-icons-round { font-size: 16px; }

.header-btn[disabled],
.header-btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}
.header-btn[disabled]:hover,
.header-btn[aria-disabled="true"]:hover {
  background: none;
  color: var(--text-muted);
}

.header-btn.concierge-header-btn {
  color: var(--accent);
  border: 1.5px solid var(--accent);
  border-radius: 8px;
  font-weight: 600;
}
.header-btn.concierge-header-btn:hover { background: var(--accent-light); color: var(--accent-hover); }
.header-btn.concierge-header-btn[aria-disabled="true"] {
  color: var(--text-muted);
  border-color: var(--border);
}
.header-btn.concierge-header-btn[aria-disabled="true"]:hover {
  background: none;
  color: var(--text-muted);
}

/* Locked (free-tier) state — softer accent so it reads as gated, with a
   small lock badge after the label. Click still opens the panel which
   shows the activation CTA. */
.header-btn.concierge-header-btn--locked {
  color: var(--text-muted);
  border-color: var(--border);
  font-weight: 500;
}
.header-btn.concierge-header-btn--locked:hover {
  background: var(--bg-hover);
  color: var(--text-secondary);
}
.concierge-lock-icon {
  font-size: 14px !important;
  margin-left: 2px;
  opacity: 0.75;
  vertical-align: middle;
}

/* USER AVATAR + MENU */
.user-avatar-wrap { position: relative; }
.user-avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--accent-light);
  color: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 13px;
  cursor: pointer;
}
[data-theme="dark"] .user-avatar { background: var(--accent); color: #fff; }
.user-avatar:hover { opacity: 0.8; }

.user-menu {
  display: none;
  position: absolute;
  top: 40px; right: 0;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.15);
  min-width: 180px;
  z-index: 1000;
  padding: 4px 0;
}
.user-menu.open { display: block; }
.user-menu-name {
  padding: 8px 14px 4px;
  font-size: 12px;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
  word-break: break-all;
}
.user-menu-item {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 14px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
  font-family: inherit;
}
.user-menu-item:hover { background: var(--bg-hover); }

/* MODULE SWITCHER (app-switcher waffle in header) */
.module-switcher-wrap { position: relative; display: inline-flex; }
.module-switcher-btn { padding: 6px 8px; }
.module-switcher-btn .material-icons-round { font-size: 20px; }
.module-menu { min-width: 200px; left: 0; right: auto; }
.module-menu .user-menu-item .module-ext-icon { font-size: 15px; opacity: 0.5; margin-left: auto; }
.module-menu .module-current { cursor: default; color: var(--text-muted); }
.module-menu .module-current:hover { background: none; }
.module-current-badge {
  margin-left: auto;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--accent);
  background: var(--accent-light);
  border-radius: 4px;
  padding: 1px 6px;
}

/* NAV BAR */
.nav-bar-wrap {
  position: sticky;
  top: 52px;
  z-index: 99;
  background: var(--bg);
}
.nav-bar {
  display: flex;
  align-items: center;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  padding: 0 24px;
  overflow-x: auto;
  overflow-y: visible;
  flex-wrap: nowrap;
  scrollbar-width: none;
}
.nav-bar::-webkit-scrollbar { display: none; }

.nav-scroll-hint {
  position: absolute;
  top: 0; bottom: 1px;
  width: 32px;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s;
  z-index: 2;
}
.nav-scroll-hint.visible { opacity: 1; pointer-events: auto; cursor: pointer; }
.nav-scroll-hint-left { left: 0; background: linear-gradient(to right, var(--bg) 60%, transparent); }
.nav-scroll-hint-right { right: 0; background: linear-gradient(to left, var(--bg) 60%, transparent); }
.nav-scroll-hint .material-icons-round { font-size: 18px; color: var(--text-muted); }

/* Responsive header + nav — same pattern as cemoddule: header buttons
   collapse to icon-only below 1500px, paddings tighten below 768px. The
   centered logo and title subtitle (purple-specific) drop out on phone
   widths so the header never overflows; the nav-bar itself already
   scrolls horizontally with the gradient hint chevrons. */
@media (max-width: 1500px) {
  .header-btn { font-size: 0; padding: 6px 8px; gap: 0; }
  .header-btn .material-icons-round { font-size: 18px; }
}
@media (max-width: 768px) {
  .top-header { padding: 0 16px; }
  .nav-bar { padding: 0 16px; }
  .nav-scroll-hint { width: 24px; }
  .header-dot, .header-subtitle { display: none; }
}
@media (max-width: 640px) {
  .header-center { display: none; }
}

.nav-tab {
  padding: 12px 12px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: all var(--transition);
  white-space: nowrap;
  flex-shrink: 0;
  background: none;
  border-left: none;
  border-right: none;
  border-top: none;
  font-family: inherit;
}
.nav-tab:hover { color: var(--text-secondary); }
.nav-tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  font-weight: 600;
}

/* BREADCRUMB + PAGE HEADER — ported from cemoddule. */
.breadcrumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0;
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 16px;
}
.breadcrumb a {
  color: var(--accent);
  text-decoration: none;
  font-weight: 500;
}
.breadcrumb a:hover { text-decoration: underline; }
.breadcrumb .sep {
  margin: 0 8px;
  color: var(--border);
}
/* "← Back to <previous>" link at the start of the breadcrumb row
   (mirrors the cemoddule cep-frontend back-nav pattern). Sits before
   the canonical breadcrumb chain with a divider gap. */
/* Selector specificity bumped via `.breadcrumb a.breadcrumb-back` so it
   beats the `.breadcrumb a:hover { text-decoration: underline }` rule
   above — otherwise the inline-flex icon and text inside the link get
   two separate underlines on hover, which reads as broken.  */
.breadcrumb a.breadcrumb-back {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-right: 14px;
  padding-right: 14px;
  border-right: 1px solid var(--border);
  font-size: 12px;
  color: var(--accent);
  text-decoration: none;
  font-weight: 500;
  transition: opacity 0.15s;
}
.breadcrumb a.breadcrumb-back:hover {
  opacity: 0.7;
  text-decoration: none;
}
.breadcrumb a.breadcrumb-back .material-icons-round { font-size: 14px; }
.breadcrumb-status-pill {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
  min-height: 14px;
}
.breadcrumb-status-pill .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
  background: var(--text-muted);
}
.breadcrumb-status-pill .dot--ok   { background: var(--success); }
.breadcrumb-status-pill .dot--warn { background: var(--high); }

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.page-title {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.3px;
  color: var(--text);
  line-height: 1.25;
}
.page-subtitle {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 4px;
}
.page-actions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* PAGE CONTAINER */
.page {
  padding: 24px;
  max-width: 1400px;
  width: 100%;
  margin: 0 auto;
}

.loading {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 48px;
  justify-content: center;
  color: var(--text-muted);
}
.spinner {
  width: 16px; height: 16px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.placeholder-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 32px;
  text-align: center;
  color: var(--text-muted);
}
.placeholder-card h2 {
  color: var(--text);
  font-size: 18px;
  font-weight: 600;
  margin-bottom: 8px;
}

/* CATEGORY TABS — above the live feed */
.category-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
}
.category-tabs:empty { display: none; }
.category-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 16px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  transition: all var(--transition);
  font-family: inherit;
  white-space: nowrap;
  line-height: 1;
}
.category-tab:hover { background: var(--bg-hover); }
.category-tab.active { color: #fff; border-color: transparent; }
.category-tab .tab-icon {
  display: inline-flex;
  align-items: center;
  font-size: 13px;
  line-height: 1;
}
.category-tab .tab-label {
  display: inline-flex;
  align-items: center;
  line-height: 1;
}
.category-tab .tab-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 600;
  background: var(--bg-page);
  color: var(--text-muted);
  padding: 0 8px;
  height: 16px;
  border-radius: 10px;
  line-height: 1;
}
.category-tab.active .tab-count {
  background: rgba(255,255,255,0.22);
  color: #fff;
}

.view-toggle {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  flex-shrink: 0;
}
.view-toggle button {
  background: var(--bg);
  color: var(--text-secondary);
  border: none;
  padding: 5px 12px;
  font-size: 11px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: all var(--transition);
}
.view-toggle button:hover { background: var(--bg-hover); }
.view-toggle button.active {
  background: var(--accent);
  color: #fff;
}
.view-toggle button + button { border-left: 1px solid var(--border); }

/* GROUPED VIEW — category-clustered cards inside the live-feed-scroll. */
.grouped-feed {
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.category-group-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.category-group-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: var(--bg-hover);
  border-bottom: 1px solid var(--border-light);
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
}
.category-group-header .group-icon { font-size: 14px; }
.category-group-header .group-count {
  margin-left: auto;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-muted);
}
.category-group-body {
  display: flex;
  flex-direction: column;
  max-height: 360px;
  overflow-y: auto;
}
.category-group-body::-webkit-scrollbar { width: 6px; }
.category-group-body::-webkit-scrollbar-track { background: var(--bg); }
.category-group-body::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
.category-group-body::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

/* LIVE FEED — ports the watch-app.html container with design tokens. */
.live-feed-container {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 24px;
}

/* Viewport-fill layout, applied only on the Live Feed route. The route
   handler in pages/live.js toggles `body.live-feed-page` so other pages
   keep their default block-stack scroll. The flex chain is:
     #appShell (column, height 100vh — NOT min-height; we need an upper
                bound so the inner overflow:auto can engage)
       └─ #mainContent (flex:1, flex column, min-height:0)
            └─ .live-feed-container (flex:1, flex column, min-height:0)
                 └─ .live-feed-body (flex:1, min-height:0)
                      └─ .live-feed-scroll (flex:1, min-height:0, overflow-y:auto)
   `min-height: 0` on every flex parent stops the standard "min-content"
   shrink behaviour from clamping the scroll area to the natural item-list
   height. The `height: 100vh` override on #appShell is the load-bearing
   bit — without it the shell happily grows past the viewport and the
   inner scroll never has a finite height to scroll within. */
body.live-feed-page #appShell {
  height: 100vh;
  min-height: 0;
}
body.live-feed-page #mainContent {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
body.live-feed-page .live-feed-container {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  margin-bottom: 0;
}
body.live-feed-page .live-feed-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
body.live-feed-page .live-feed-scroll {
  flex: 1;
  min-height: 0;
  max-height: none;
}
body.live-feed-page .live-feed-scroll.is-grouped {
  flex: 1;
  min-height: 0;
  max-height: none;
  overflow-y: auto;
}
.live-feed-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 20px;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.live-feed-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: 0.12em;
}
.live-indicator {
  width: 6px; height: 6px;
  background: var(--critical);
  border-radius: 50%;
  animation: live-pulse 2.5s ease-in-out infinite;
}
@keyframes live-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.3; }
}
.live-feed-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  color: var(--text-muted);
}

/* Sort-direction toggle in the live-feed-header. Visually mirrors a single
   button from the .view-toggle group sitting next to it (same padding,
   border-radius, font, hover) so the two controls read as one toolbar. */
.sort-toggle-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  font-family: inherit;
  cursor: pointer;
  transition: all var(--transition);
}
.sort-toggle-btn:hover {
  background: var(--bg-hover);
  border-color: var(--text-muted);
  color: var(--text);
}
.sort-toggle-btn .sort-arrow {
  font-size: 13px;
  line-height: 1;
}

.live-feed-body { display: flex; flex-direction: column; }
.live-feed-scroll {
  max-height: 600px;
  overflow-y: auto;
  scroll-behavior: smooth;
  position: relative;
}
.live-feed-scroll::-webkit-scrollbar { width: 6px; }
.live-feed-scroll::-webkit-scrollbar-track { background: var(--bg); }
.live-feed-scroll::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
.live-feed-scroll::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

/* Grouped view: drop the scroll cap so category cards flow naturally. */
.live-feed-scroll.is-grouped {
  max-height: none;
  overflow-y: visible;
}

.feed-item {
  display: flex;
  gap: 12px;
  padding: 10px 20px;
  border-bottom: 1px solid var(--border-light);
  transition: background var(--transition);
}
.feed-item:last-child { border-bottom: none; }
.feed-item:hover { background: var(--bg-hover); }

.feed-item-time {
  flex: 0 0 130px;
  font-size: 11px;
  font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', monospace;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  line-height: 1.4;
}
.feed-item-time .live-ts { color: var(--text-secondary); font-weight: 500; }
.feed-item-time .content-ts {
  display: block;
  font-size: 10px;
  color: var(--text-muted);
  opacity: 0.7;
  margin-top: 2px;
}

.feed-item-icon {
  flex-shrink: 0;
  font-size: 13px;
  opacity: 0.75;
  line-height: 1.5;
}

.feed-item-content { flex: 1; min-width: 0; }
.feed-item-headline {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  line-height: 1.45;
  word-break: break-word;
}
.feed-item-detail {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.5;
  margin-top: 2px;
  word-break: break-word;
}
.feed-item-detail code {
  background: var(--bg-hover);
  color: var(--critical);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 11px;
  font-family: 'SF Mono', Monaco, monospace;
  border: 1px solid var(--border-light);
}

.feed-category-badge {
  display: inline-block;
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 2px 6px;
  border-radius: 3px;
  margin-right: 4px;
  vertical-align: middle;
  opacity: 0.85;
}

@keyframes drip-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.feed-item.drip-new { animation: drip-in 0.3s ease-out; }

@keyframes bloom-row {
  0%   { background: transparent; }
  20%  { background: var(--accent-light); }
  100% { background: transparent; }
}
.feed-item.bloom-in { animation: drip-in 0.3s ease-out, bloom-row 2.4s ease-out; }
.feed-item.last-published { box-shadow: inset 3px 0 0 var(--accent); }

.new-items-badge {
  position: sticky;
  bottom: 12px;
  margin: 0 auto;
  width: max-content;
  background: var(--accent);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  padding: 7px 14px;
  border-radius: 999px;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(108,71,255,0.35);
  display: none;
  z-index: 10;
}
.new-items-badge:hover { background: var(--accent-hover); }

.feed-empty,
.feed-error {
  padding: 40px 24px;
  text-align: center;
  font-size: 13px;
}
.feed-empty { color: var(--text-muted); }
.feed-error { color: var(--critical); }

@media (max-width: 720px) {
  .live-feed-scroll { max-height: 60vh; }
  .feed-item { padding: 10px 12px; gap: 8px; }
  .feed-item-time { flex: 0 0 90px; font-size: 10px; }
  .feed-item-icon { display: none; }
}

/* FULL SCREEN OVERLAY — wall-display ticker, 4 themes. */
.fs-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9999;
  font-family: var(--fs-font);
  overflow: hidden;
  background: var(--fs-bg);
  color: var(--fs-text);
}
.fs-overlay.active { display: flex; flex-direction: column; }

/* Default — Office Dark */
.fs-overlay,
.fs-overlay[data-theme="office-dark"] {
  --fs-bg: #0a0a0f;
  --fs-text: #e0e0e8;
  --fs-header-bg: linear-gradient(180deg, rgba(10,10,15,0.95) 0%, rgba(10,10,15,0) 100%);
  --fs-title-color: #c0c0cc;
  --fs-subtitle-color: #6b6b7b;
  --fs-clock-color: #9090a0;
  --fs-clock-date-color: #55556a;
  --fs-time-color: #55556a;
  --fs-headline-color: #e0e0e8;
  --fs-detail-color: #8888a0;
  --fs-border-color: rgba(255,255,255,0.04);
  --fs-latest-bg: rgba(192,57,43,0.06);
  --fs-latest-border: rgba(192,57,43,0.4);
  --fs-code-bg: rgba(192,57,43,0.12);
  --fs-code-color: #c0392b;
  --fs-accent: #7c3aed;
  --fs-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --fs-picker-bg: rgba(255,255,255,0.06);
  --fs-picker-hover: rgba(255,255,255,0.12);
  --fs-picker-text: #8888a0;
}
.fs-overlay[data-theme="office-light"] {
  --fs-bg: #f8f8fa;
  --fs-text: #1f2937;
  --fs-header-bg: linear-gradient(180deg, rgba(248,248,250,0.97) 0%, rgba(248,248,250,0) 100%);
  --fs-title-color: #374151;
  --fs-subtitle-color: #9ca3af;
  --fs-clock-color: #4b5563;
  --fs-clock-date-color: #9ca3af;
  --fs-time-color: #9ca3af;
  --fs-headline-color: #1f2937;
  --fs-detail-color: #6b7280;
  --fs-border-color: rgba(0,0,0,0.06);
  --fs-latest-bg: rgba(124,58,237,0.04);
  --fs-latest-border: rgba(124,58,237,0.4);
  --fs-code-bg: rgba(192,57,43,0.08);
  --fs-code-color: #c0392b;
  --fs-accent: #7c3aed;
  --fs-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --fs-picker-bg: rgba(0,0,0,0.04);
  --fs-picker-hover: rgba(0,0,0,0.08);
  --fs-picker-text: #6b7280;
}
.fs-overlay[data-theme="hacker-dark"] {
  --fs-bg: #000000;
  --fs-text: #00ff41;
  --fs-header-bg: linear-gradient(180deg, rgba(0,0,0,0.97) 0%, rgba(0,0,0,0) 100%);
  --fs-title-color: #00ff41;
  --fs-subtitle-color: #005f15;
  --fs-clock-color: #00cc33;
  --fs-clock-date-color: #005f15;
  --fs-time-color: #005f15;
  --fs-headline-color: #00ff41;
  --fs-detail-color: #00aa2a;
  --fs-border-color: rgba(0,255,65,0.08);
  --fs-latest-bg: rgba(0,255,65,0.05);
  --fs-latest-border: rgba(0,255,65,0.4);
  --fs-code-bg: rgba(0,255,65,0.1);
  --fs-code-color: #00ff41;
  --fs-accent: #00ff41;
  --fs-font: "SF Mono", Monaco, "Cascadia Code", "Fira Code", monospace;
  --fs-picker-bg: rgba(0,255,65,0.06);
  --fs-picker-hover: rgba(0,255,65,0.12);
  --fs-picker-text: #00aa2a;
}
.fs-overlay[data-theme="hacker-light"] {
  --fs-bg: #f0f5f0;
  --fs-text: #0a3d0a;
  --fs-header-bg: linear-gradient(180deg, rgba(240,245,240,0.97) 0%, rgba(240,245,240,0) 100%);
  --fs-title-color: #0a5c0a;
  --fs-subtitle-color: #5a8a5a;
  --fs-clock-color: #0a5c0a;
  --fs-clock-date-color: #5a8a5a;
  --fs-time-color: #5a8a5a;
  --fs-headline-color: #0a3d0a;
  --fs-detail-color: #3a6a3a;
  --fs-border-color: rgba(10,61,10,0.1);
  --fs-latest-bg: rgba(10,140,10,0.06);
  --fs-latest-border: rgba(10,140,10,0.4);
  --fs-code-bg: rgba(10,140,10,0.08);
  --fs-code-color: #0a5c0a;
  --fs-accent: #0a8c0a;
  --fs-font: "SF Mono", Monaco, "Cascadia Code", "Fira Code", monospace;
  --fs-picker-bg: rgba(10,61,10,0.06);
  --fs-picker-hover: rgba(10,61,10,0.1);
  --fs-picker-text: #3a6a3a;
}

.fs-header {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 20px 32px;
  background: var(--fs-header-bg);
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 10;
}
.fs-brand { display: flex; align-items: center; gap: 14px; }
.fs-logo {
  width: 40px; height: 40px;
  border: 2px solid var(--fs-accent);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 13px; color: var(--fs-accent);
}
.fs-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--fs-title-color);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.fs-subtitle { font-size: 11px; color: var(--fs-subtitle-color); margin-top: 1px; }
.fs-live-badge {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 600; color: #c0392b;
  text-transform: uppercase; letter-spacing: 0.1em;
}
.fs-live-dot {
  width: 8px; height: 8px;
  background: #c0392b;
  border-radius: 50%;
  animation: live-pulse 2s infinite;
}
.fs-theme-picker { display: flex; gap: 6px; align-items: center; }
.fs-theme-btn {
  width: 22px; height: 22px;
  border-radius: 50%;
  cursor: pointer;
  border: 2px solid transparent;
  transition: border-color 0.2s;
}
.fs-theme-btn:hover { border-color: var(--fs-accent); }
.fs-theme-btn.active { border-color: var(--fs-accent); box-shadow: 0 0 6px var(--fs-accent); }
.fs-theme-btn[data-t="office-dark"] { background: #0a0a0f; border-color: #333; }
.fs-theme-btn[data-t="office-light"] { background: #f8f8fa; border-color: #ccc; }
.fs-theme-btn[data-t="hacker-dark"] { background: #000; border-color: #005f15; }
.fs-theme-btn[data-t="hacker-light"] { background: #f0f5f0; border-color: #5a8a5a; }
.fs-theme-label {
  font-size: 10px;
  color: var(--fs-picker-text);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-right: 4px;
}
.fs-sort-toggle-btn {
  background: var(--fs-picker-bg);
  color: var(--fs-picker-text);
  border: 1px solid transparent;
  border-radius: 4px;
  padding: 4px 10px;
  font-size: 12px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-weight: 500;
  font-family: inherit;
  transition: background 0.15s;
}
.fs-sort-toggle-btn:hover { background: var(--fs-picker-hover); }
.fs-clock {
  margin-left: auto;
  text-align: right;
  font-family: 'SF Mono', Monaco, monospace;
  font-variant-numeric: tabular-nums;
}
.fs-clock-time { font-size: 22px; font-weight: 600; color: var(--fs-clock-color); }
.fs-clock-date { font-size: 12px; color: var(--fs-clock-date-color); margin-top: 2px; }

.fs-feed {
  flex: 1;
  overflow: hidden;
  padding: 100px 32px 32px;
  display: flex;
  flex-direction: column;
  position: relative;
}
.fs-feed-scroll {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
}
.fs-feed-scroll::-webkit-scrollbar { display: none; }

.fs-item {
  display: flex;
  gap: 16px;
  padding: 16px 24px;
  border-bottom: 1px solid var(--fs-border-color);
  align-items: flex-start;
  opacity: 0.92;
  transition: opacity 0.3s;
}
.fs-item:hover { opacity: 1; }
.fs-item.fs-latest {
  opacity: 1;
  background: var(--fs-latest-bg);
  border-left: 3px solid var(--fs-latest-border);
  border-bottom-color: transparent;
}
.fs-item-time {
  flex-shrink: 0;
  min-width: 80px;
  font-size: 14px;
  font-family: 'SF Mono', Monaco, monospace;
  font-variant-numeric: tabular-nums;
  color: var(--fs-time-color);
}
.fs-item-icon { flex-shrink: 0; font-size: 18px; opacity: 0.7; }
.fs-item-content { flex: 1; min-width: 0; }
.fs-item-headline {
  font-size: 20px;
  font-weight: 500;
  color: var(--fs-headline-color);
  line-height: 1.4;
  word-break: break-word;
}
.fs-item-detail {
  font-size: 15px;
  color: var(--fs-detail-color);
  margin-top: 4px;
  line-height: 1.5;
  word-break: break-word;
}
.fs-item-detail code {
  background: var(--fs-code-bg);
  color: var(--fs-code-color);
  padding: 1px 6px;
  border-radius: 3px;
  font-family: 'SF Mono', Monaco, monospace;
  font-size: 13px;
}
.fs-category-badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 3px;
  margin-right: 6px;
  vertical-align: middle;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

@keyframes fs-slide-in {
  from { opacity: 0; transform: translateY(30px); }
  to   { opacity: 0.92; transform: translateY(0); }
}
.fs-item.fs-new { animation: fs-slide-in 0.6s cubic-bezier(0.22, 1, 0.36, 1); }

.fs-reconnecting {
  position: absolute;
  bottom: 24px; left: 50%;
  transform: translateX(-50%);
  background: rgba(234,179,8,0.15);
  color: #eab308;
  padding: 8px 20px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  display: none;
}
.fs-reconnecting.visible { display: block; }

/* Promoted Full Screen launcher in the page-header actions slot. The
   feature is a key selling point (wall display, themes, auto-scroll) so it
   reads as a primary CTA next to the page title rather than being buried
   in the live-feed-header toolbar. */
.fs-launch-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 600;
}
.fs-launch-cta .fs-launch-icon { font-size: 14px; line-height: 1; }

/* Legacy in-header full-screen button — kept around for any other surface
   that still references it; the live-feed page no longer uses it. */
.fs-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  background: none;
  border: 1px solid var(--border);
  border-radius: 3px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  font-family: inherit;
  cursor: pointer;
  transition: all var(--transition);
}
.fs-btn:hover {
  background: var(--bg-hover);
  border-color: var(--text-muted);
  color: var(--text);
}

/* DAILY BRIEFING — activity calendar (last 60 days). */
.briefing-calendar {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px 20px;
  margin-bottom: 24px;
  overflow-x: auto;
}
.calendar-title {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin-bottom: 12px;
}
.calendar-month-row {
  height: 12px;
  line-height: 1;
  margin-left: 22px; /* offset past the day-of-week labels column */
  position: relative;
  margin-bottom: 10px;
  white-space: nowrap;
}
.calendar-month-label {
  font-size: 9px;
  line-height: 1;
  color: var(--text-muted);
  display: inline-block;
  vertical-align: top;
}
.calendar-grid { display: flex; gap: 6px; }
.calendar-labels { display: flex; flex-direction: column; gap: 3px; }
.calendar-label {
  font-size: 9px;
  color: var(--text-muted);
  height: 13px;
  line-height: 13px;
  width: 16px;
}
.calendar-weeks { display: flex; gap: 3px; }
.calendar-week { display: flex; flex-direction: column; gap: 3px; }
.calendar-cell {
  width: 13px;
  height: 13px;
  border-radius: 2px;
  position: relative;
  cursor: pointer;
  transition: outline 0.15s;
}
.calendar-cell:hover { outline: 1px solid var(--accent); outline-offset: 1px; }
.calendar-cell.cal-0 { background: var(--bg-hover); cursor: default; }
.calendar-cell.cal-0:hover { outline: none; }
.calendar-cell.cal-1 { background: color-mix(in srgb, var(--accent) 55%, var(--bg)); }
.calendar-cell.cal-2 { background: var(--accent); }
.calendar-cell.empty { visibility: hidden; cursor: default; }
/* Free-tier marker: the cell still renders so the activity pattern is
   visible, but jump-to-day is gated, so swap the click affordance for the
   not-allowed cursor and tone down the hover outline. */
.calendar-cell.cal-cell-locked { cursor: not-allowed; }
.calendar-cell.cal-cell-locked:hover { outline-color: var(--text-muted); }

/* Free-tier 2-column layout — promo lives INSIDE the calendar container so
   it shares the same border + chrome. Calendar content (title/hint/grid)
   on the left, promo filling the slack on the right. Premium tier omits
   the modifier and the calendar stacks normally. Stacks vertically on
   narrow viewports. */
.briefing-calendar--with-promo {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 24px;
  align-items: stretch;
  overflow: visible;
}
.briefing-calendar-content { display: flex; flex-direction: column; }
@media (max-width: 768px) {
  .briefing-calendar--with-promo { grid-template-columns: 1fr; }
}

/* Caption under the calendar title. Two flavours: premium gets the click
   instruction, free tier gets an upgrade hint with an inline link. */
.calendar-hint {
  font-size: 12px;
  color: var(--text-muted);
  margin: -4px 0 12px 0;
  line-height: 1.5;
}
.calendar-hint a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
}
.calendar-hint a:hover { text-decoration: underline; }
.calendar-tooltip {
  position: absolute;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--text);
  color: var(--bg);
  font-size: 11px;
  padding: 4px 8px;
  border-radius: 4px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s;
  z-index: 10;
}
.calendar-cell:hover .calendar-tooltip { opacity: 1; }

@keyframes day-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(108,71,255,0.45); }
  60%  { box-shadow: 0 0 0 8px rgba(108,71,255,0); }
  100% { box-shadow: 0 0 0 0 rgba(108,71,255,0); }
}
.day-container.is-highlighted .daily-overview-card {
  animation: day-pulse 1.4s ease-out;
}

/* DAILY BRIEFING — timeline of dated cards with word cloud + prose. */
.briefing-section { margin-bottom: 24px; }
.briefing-section-title {
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin-bottom: 12px;
}

.day-container { margin-bottom: 24px; scroll-margin-top: 120px; }
.day-container.is-latest .daily-overview-card { border-color: var(--accent); }
.day-container.is-latest .daily-overview-header {
  background: color-mix(in srgb, var(--accent) 18%, var(--bg));
  border-bottom-color: color-mix(in srgb, var(--accent) 30%, var(--border));
}
.day-container.is-latest .daily-overview-title { color: var(--accent); }

.daily-overview-card {
  background: var(--bg);
  border: 2px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.daily-overview-header {
  padding: 16px 20px;
  background: var(--bg-hover);
  border-bottom: 1px solid var(--border);
}
.daily-overview-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.daily-overview-title .latest-pill {
  background: var(--accent-light);
  color: var(--accent);
  font-size: 11px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 6px;
}
.daily-overview-meta { font-size: 12px; color: var(--text-muted); margin-top: 4px; }
.daily-overview-body { padding: 20px; }

/* Top Actors / Top Entities chip strip at the bottom of each daily-briefing
   card. Reuses .entity-section-header (matches the accent-purple dividers
   Stage 3 emits inside the prose overview) and .tag-pill.tag-industry for
   the chips. Sections render only when the API returns items. */
.briefing-chip-section { margin-top: 12px; }
.briefing-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

/* Prose overview */
.prose-overview {
  font-size: 15px;
  line-height: 1.7;
  color: var(--text-secondary);
}
.prose-overview p { margin-bottom: 16px; }
.prose-overview p:last-child { margin-bottom: 0; }
.prose-overview strong { color: var(--text); }
.prose-overview code {
  background: var(--bg-hover);
  color: var(--text);
  padding: 2px 6px;
  border-radius: 4px;
  font-family: 'SF Mono', Monaco, monospace;
  font-size: 13px;
}
.prose-overview ul { margin: 8px 0 16px 20px; }
.prose-overview li { margin-bottom: 4px; }
.entity-section-header {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent);
  margin-top: 20px;
  margin-bottom: 6px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.entity-section-header:first-child { margin-top: 0; }

/* INTELLIGENCE BRIEFINGS (premium) */
.premium-locked-overlay {
  background: var(--bg);
  border: 2px dashed var(--border);
  border-radius: var(--radius-lg);
  padding: 48px 32px;
  text-align: center;
  max-width: 540px;
  margin: 40px auto;
}
/* Inline variant — used on the Daily Briefing page where the promo sits
   inside the calendar container as a side panel. Drops the centring
   margins, narrows the padding, and centres the content (icon, title,
   description, button) within the side slot. The button stays content-
   sized via align-self: center on the inline-flex .btn-primary; without
   that override the column's default align-items: stretch makes it span
   the full panel width. Borderless because the parent calendar already
   carries the border + radius. */
.premium-locked-overlay--inline {
  margin: 0;
  max-width: none;
  padding: 8px 20px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
}
.premium-locked-overlay--inline .lock-icon { margin-bottom: 8px; }
.premium-locked-overlay--inline h3 { font-size: 17px; margin-bottom: 6px; }
.premium-locked-overlay--inline p { font-size: 13px; max-width: 380px; }
.premium-locked-overlay--inline .btn-primary {
  align-self: center;
  text-decoration: none;
}
.premium-locked-overlay .lock-icon {
  font-size: 36px;
  margin-bottom: 12px;
}
.premium-locked-overlay h3 {
  font-size: 20px;
  color: var(--text);
  margin-bottom: 8px;
  font-weight: 600;
}
.premium-locked-overlay p {
  font-size: 14px;
  color: var(--text-muted);
  line-height: 1.6;
  margin-bottom: 8px;
}
.premium-locked-overlay .activate-status {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 8px;
  min-height: 16px;
}

.premium-section h3 {
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
}

.profile-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 12px;
}
.profile-card .profile-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.profile-card .profile-name {
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
}
.profile-card .profile-meta {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 6px;
}
.profile-card .profile-instructions {
  margin-top: 4px;
  font-style: italic;
  font-size: 13px;
  color: var(--text-muted);
}
.profile-card .profile-actions {
  display: inline-flex;
  gap: 6px;
}

.profile-form-card {
  background: var(--bg);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 16px;
}
.profile-form-card h4 {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 14px;
}
.profile-form-fields { display: grid; gap: 10px; }
.profile-form-fields input,
.profile-form-fields textarea,
.profile-form-fields select {
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 14px;
  font-family: inherit;
  background: var(--bg);
  color: var(--text);
}
.profile-form-fields input:focus,
.profile-form-fields textarea:focus,
.profile-form-fields select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-light);
}
.profile-form-fields textarea { resize: vertical; min-height: 60px; }
.profile-form-actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.briefing-output { margin-top: 16px; }
.briefing-output .briefing-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  font-size: 13px;
  color: var(--text-muted);
}
.briefing-output .briefing-meta strong {
  color: var(--text);
  font-size: 15px;
}
/* Customer-facing briefing header — replaces the older meta-line layout
   so the rendered output reads as a real intelligence document instead
   of an operator dashboard row. Operator request 2026-05-07: drop the
   model name + observation count (irrelevant to the customer who reads
   the briefing) and surface the document type, profile name, and the
   period covered as the first three lines. */
.briefing-output .briefing-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.briefing-output .briefing-header-text { min-width: 0; }
.briefing-output .briefing-doctype {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.1px;
}
.briefing-output .briefing-subtype {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-secondary);
  margin-top: 2px;
}
.briefing-output .briefing-period {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 6px;
}
.briefing-output .briefing-period strong { color: var(--text-secondary); font-weight: 600; }
.briefing-output .briefing-actions { flex-shrink: 0; }
.briefing-output .briefing-content {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-secondary);
}
.briefing-output .briefing-content strong { color: var(--text); }
.briefing-output .briefing-content code {
  background: var(--bg-hover);
  color: var(--text);
  padding: 2px 6px;
  border-radius: 4px;
  font-family: 'SF Mono', Monaco, monospace;
  font-size: 13px;
}
.briefing-output .briefing-content h1,
.briefing-output .briefing-content h2,
.briefing-output .briefing-content h3,
.briefing-output .briefing-content h4,
.briefing-output .briefing-content h5 {
  color: var(--text);
  margin: 18px 0 8px;
  font-weight: 600;
}
.briefing-output .briefing-content h3 { font-size: 16px; }
.briefing-output .briefing-content h4 { font-size: 15px; }
.briefing-output .briefing-content h5 { font-size: 14px; }
.briefing-output .briefing-content .briefing-section-header {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  margin: 22px 0 10px;
  letter-spacing: -0.1px;
}
.briefing-output .briefing-content .briefing-section-header:first-child {
  margin-top: 0;
}
.briefing-output .briefing-content p { margin-bottom: 12px; }
.briefing-output .briefing-content ul { margin: 8px 0 16px 20px; padding-left: 4px; }
.briefing-output .briefing-content li { margin-bottom: 4px; list-style: disc; }
.briefing-output .briefing-content li > ul {
  margin: 4px 0 4px 20px;
}
.briefing-output .briefing-content li > ul > li { list-style: circle; }
.briefing-output .briefing-content li > ul > li > ul > li { list-style: square; }
.briefing-output .briefing-content table {
  border-collapse: collapse;
  width: 100%;
  margin: 14px 0;
  font-size: 13px;
}
.briefing-output .briefing-content th,
.briefing-output .briefing-content td {
  padding: 8px 12px;
  text-align: left;
  vertical-align: top;
  border: 1px solid var(--border);
}
.briefing-output .briefing-content th {
  background: var(--bg-hover);
  font-weight: 600;
  color: var(--text);
}
.briefing-output .briefing-content tr:nth-child(even) td {
  background: color-mix(in srgb, var(--bg-hover) 50%, var(--bg));
}
.briefing-output .briefing-content hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: 16px 0;
}

.briefing-loading {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 18px;
  font-size: 13px;
  color: var(--text-muted);
}
.briefing-error {
  background: var(--critical-bg);
  border: 1px solid var(--critical);
  border-radius: var(--radius);
  padding: 14px 16px;
  color: var(--critical);
  font-size: 13px;
}

/* shared button styles for premium UI */
.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  background: var(--accent);
  color: #fff;
  border: 1px solid var(--accent);
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: background var(--transition);
}
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn-primary[disabled] { opacity: 0.5; cursor: not-allowed; }
.btn-secondary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: background var(--transition);
}
.btn-secondary:hover { background: var(--bg-hover); }
.btn-sm { padding: 5px 10px; font-size: 12px; }

/* SHARED LIST TOOLBAR — ported from cemoddule. Used by History and any
   future search/list page. Pattern: <list-toolbar> contains <filter-row>
   (search + filter selects) and <list-count> (count text + btn-groups
   + spacer + action buttons). */
.list-toolbar {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  margin-bottom: 14px;
}
.filter-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.filter-select {
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 12px;
  font-family: inherit;
  color: var(--text-secondary);
  background: var(--bg);
  cursor: pointer;
  outline: none;
}
.filter-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-light);
}
.filter-select.filter-select--active {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-light);
}
.search-input-wrap {
  position: relative;
  flex: 1;
  min-width: 200px;
  display: flex;
  align-items: center;
}
.search-input-wrap .search-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 18px;
  color: var(--text-muted);
  pointer-events: none;
}

.search-input {
  flex: 1;
  width: 100%;
  padding: 8px 12px 8px 36px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 13px;
  font-family: inherit;
  color: var(--text);
  background: var(--bg);
  outline: none;
  transition: border-color var(--transition), box-shadow var(--transition);
}
.search-input::placeholder { color: var(--text-muted); }
.search-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-light);
}

.list-count {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
  background: var(--bg-hover);
  border-radius: var(--radius);
  padding: 5px 12px;
}
.list-count strong { color: var(--text-secondary); font-weight: 600; }
.list-count .count-spacer { flex: 1; }

/* Variant for the count when it lives inside .live-feed-header (e.g.
   /purple/#ransomware-victims). Drops the toolbar-style chip background
   so it reads as a quiet right-side label next to the LIVE FEED title. */
.list-count--header {
  background: transparent;
  padding: 0;
  font-size: 11px;
  text-transform: none;
  letter-spacing: normal;
  color: var(--text-muted);
}

.btn-group {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  height: 28px;
  box-sizing: border-box;
}
.btn-group button {
  border: none;
  border-right: 1px solid var(--border);
  border-radius: 0;
  background: none;
  padding: 0 12px;
  height: 100%;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
  color: var(--text-muted);
  transition: var(--transition);
  white-space: nowrap;
}
.btn-group button:last-child { border-right: none; }
.btn-group button:hover { background: var(--bg-hover); color: var(--text); }
.btn-group button.active {
  background: var(--accent-light);
  color: var(--accent);
  font-weight: 600;
}

.history-feed {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.history-feed .feed-item {
  display: flex;
  gap: 14px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border-light);
}
.history-feed .feed-item:last-child { border-bottom: none; }
.history-feed .feed-item-time {
  flex: 0 0 auto;
  min-width: 130px;
  font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  color: var(--text-muted);
  line-height: 1.45;
}
.history-feed .feed-item-icon { flex: 0 0 18px; font-size: 14px; }
.history-feed .feed-item-content { flex: 1; min-width: 0; }
.history-feed .feed-item-headline {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  line-height: 1.45;
  word-break: break-word;
}
.history-feed .feed-item-detail {
  margin-top: 4px;
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.5;
  word-break: break-word;
}
.history-feed .feed-item-detail code {
  background: var(--bg-hover);
  color: var(--text);
  padding: 1px 5px;
  border-radius: 3px;
  font-family: 'SF Mono', Monaco, monospace;
  font-size: 11px;
}
.feed-item-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 6px;
}
.meta-tag {
  display: inline-block;
  padding: 1px 7px;
  font-size: 10px;
  font-weight: 500;
  border-radius: 3px;
  cursor: pointer;
  transition: filter var(--transition);
  user-select: none;
}
.meta-tag.entity { background: var(--accent-light); color: var(--accent); }
.meta-tag.actor  { background: var(--high-bg); color: var(--high); }
.meta-tag.geo    { background: var(--bg-hover); color: var(--text-secondary); }
.meta-tag:hover { filter: brightness(0.92); }

.load-more-container { display: flex; justify-content: center; padding: 16px 0; }
.load-more-container.hidden { display: none; }
.load-more-btn {
  padding: 8px 16px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  font-family: inherit;
  transition: all var(--transition);
}
.load-more-btn:hover:not(:disabled) {
  background: var(--bg-hover);
  border-color: var(--text-muted);
  color: var(--text);
}
.load-more-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.state-message {
  padding: 48px 24px;
  text-align: center;
  color: var(--text-muted);
}
.state-message .state-icon { font-size: 32px; margin-bottom: 12px; }
.state-message .state-spinner {
  width: 28px;
  height: 28px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  margin: 0 auto 12px;
  animation: spin 0.8s linear infinite;
}
.state-message .state-text { font-size: 14px; font-weight: 500; }
.state-message .state-hint { font-size: 12px; margin-top: 4px; opacity: 0.7; }

/* THREAT ACTORS */
.actor-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 14px;
}
.actor-card {
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px 18px;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  transition: border-color var(--transition), box-shadow var(--transition);
}
.actor-card:hover {
  border-color: var(--accent);
  box-shadow: 0 4px 14px rgba(108,71,255,0.08);
}
.actor-card .card-top {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.actor-card .actor-name {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.actor-card .card-desc {
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-secondary);
  margin-bottom: 10px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.actor-card .card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 10px;
}
.actor-card .card-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 12px;
  color: var(--text-muted);
  margin-top: auto;
}
.actor-card .card-stats .stat-value {
  color: var(--text);
  font-weight: 600;
}

.type-badge,
.status-badge {
  display: inline-block;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 500;
  border-radius: 3px;
  white-space: nowrap;
}
.type-badge.type-apt              { background: #dbeafe; color: #1e40af; }
.type-badge.type-ransomware       { background: #fee2e2; color: #991b1b; }
.type-badge.type-organized-crime  { background: #fef3c7; color: #92400e; }
.type-badge.type-hacktivist       { background: #ede9fe; color: #6d28d9; }
.type-badge.type-individual       { background: #f3f4f6; color: #4b5563; }
.type-badge.type-default          { background: var(--bg-hover); color: var(--text-secondary); }

.status-badge.status-active   { background: rgba(34,197,94,0.12); color: #15803d; }
.status-badge.status-inactive { background: var(--bg-hover); color: var(--text-muted); }
.status-badge.status-defunct  { background: var(--bg-hover); color: var(--text-muted); text-decoration: line-through; }
.status-badge.status-arrested { background: var(--critical-bg); color: var(--critical); }

.tag-pill {
  display: inline-block;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 500;
  background: var(--bg-hover);
  color: var(--text-secondary);
  border-radius: 3px;
  white-space: nowrap;
}
.tag-pill.tag-industry {
  background: var(--accent-light);
  color: var(--accent);
}

.actors-pagination {
  display: flex;
  justify-content: center;
  gap: 4px;
  margin-top: 24px;
  flex-wrap: wrap;
}
.actors-pagination .page-btn {
  min-width: 32px;
  height: 32px;
  padding: 0 10px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  font-family: inherit;
  transition: all var(--transition);
}
.actors-pagination .page-btn:hover:not(:disabled) {
  background: var(--bg-hover);
  border-color: var(--text-muted);
  color: var(--text);
}
.actors-pagination .page-btn.active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
.actors-pagination .page-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.actors-pagination .page-ellipsis {
  display: inline-flex;
  align-items: center;
  padding: 0 6px;
  font-size: 12px;
  color: var(--text-muted);
}

/* Detail overlay — right-side panel. Reusable. Pattern matches the
   Cyber Exposure (cemoddule) panel: scrim fades in, panel slides in
   from the right via transform. */
.detail-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.3);
  z-index: 200;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.detail-overlay.visible {
  opacity: 1;
  pointer-events: auto;
}

.detail-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: clamp(600px, 50vw, 800px);
  max-width: 92vw;
  background: var(--bg);
  border-left: 1px solid var(--border);
  box-shadow: -4px 0 24px rgba(0,0,0,0.1);
  z-index: 201;
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform 0.25s ease;
}
.detail-panel.visible { transform: translateX(0); }

.detail-panel-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 24px;
  border-bottom: 1px solid var(--border-light);
  flex-shrink: 0;
}
/* Title block (name + meta) consumes the slack so any actions area and the
   close button stay packed against the right edge, instead of getting
   space-between'd into the middle of the header. */
.detail-panel-header > div:first-child { flex: 1; min-width: 0; }
.detail-panel-header .detail-name {
  font-size: 19px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.2px;
  margin-bottom: 6px;
}
.detail-panel-header .detail-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.detail-panel-header .detail-meta .alias {
  font-size: 11px;
  color: var(--text-muted);
}
.detail-panel-header .detail-close {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  background: var(--bg-page);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  transition: all var(--transition);
  flex-shrink: 0;
}
.detail-panel-header .detail-close:hover {
  background: var(--border);
  color: var(--text);
}
.detail-panel-header .detail-close .material-icons-round { font-size: 18px; }

.detail-panel-body {
  padding: 18px 24px 32px;
  overflow-y: auto;
  flex: 1;
}
.detail-panel-body h3 {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  margin: 18px 0 8px;
}
.detail-panel-body h3:first-child { margin-top: 0; }
.detail-panel-body p {
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-secondary);
  margin-bottom: 12px;
  white-space: pre-wrap;
}
.detail-panel-body .detail-tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* Live Activity panel — accent-tinted card with key stats */
.live-activity {
  background: color-mix(in srgb, var(--accent) 8%, var(--bg));
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border));
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 18px;
}
.live-activity h3 {
  margin: 0 0 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
}
.live-activity.is-empty {
  background: var(--bg-hover);
  border-color: var(--border);
}
.live-activity.is-empty h3 { color: var(--text-muted); }
.live-activity.is-empty p {
  font-size: 12px;
  color: var(--text-muted);
  margin: 0;
}
.live-activity-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
.live-activity-stat {
  text-align: center;
}
.live-activity-stat .value {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.live-activity-stat .label {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  margin-top: 2px;
}

/* Linked handles */
.handle-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 0;
  border-bottom: 1px solid var(--border-light);
  font-size: 12px;
}
.handle-row:last-child { border-bottom: none; }
.handle-row .handle-name {
  font-family: 'SF Mono', Monaco, monospace;
  font-size: 12px;
  color: var(--text);
  font-weight: 500;
}
.cred-badge {
  display: inline-block;
  padding: 1px 7px;
  font-size: 10px;
  font-weight: 600;
  border-radius: 3px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.cred-badge.cred-threat_actor { background: var(--critical-bg); color: var(--critical); }
.cred-badge.cred-established  { background: color-mix(in srgb, var(--accent) 15%, var(--bg)); color: var(--accent); }
.cred-badge.cred-new          { background: var(--bg-hover); color: var(--text-muted); }
.handle-row .handle-stat {
  font-size: 11px;
  color: var(--text-muted);
}

/* IOCs grouped by type */
.ioc-group { margin-bottom: 12px; }
.ioc-group .ioc-type-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.ioc-group .ioc-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.ioc-pill {
  display: inline-block;
  padding: 2px 7px;
  background: var(--bg-hover);
  border: 1px solid var(--border-light);
  border-radius: 3px;
  font-family: 'SF Mono', Monaco, monospace;
  font-size: 10px;
  color: var(--text-secondary);
  word-break: break-all;
}

/* Underground Communications */
.site-content-block {
  margin-bottom: 12px;
  padding: 10px 14px;
  background: color-mix(in srgb, var(--high) 8%, var(--bg));
  border: 1px solid color-mix(in srgb, var(--high) 30%, var(--border));
  border-radius: var(--radius);
}
.site-content-block .sc-header {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.site-content-block .sc-type {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--high);
  color: #fff;
  padding: 1px 7px;
  border-radius: 3px;
}
.site-content-block .sc-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
}
.site-content-block .sc-date {
  margin-left: auto;
  font-size: 10px;
  color: var(--text-muted);
}
.site-content-block .sc-body {
  font-family: 'SF Mono', Monaco, monospace;
  font-size: 11px;
  color: var(--text-secondary);
  white-space: pre-wrap;
  line-height: 1.5;
}

/* Recent observations section under the detail panel */
#actorObsSection { margin-top: 28px; }

.detail-obs-row {
  padding: 8px 10px;
  border: 1px solid var(--border-light);
  border-radius: var(--radius);
  background: var(--bg);
  margin-bottom: 6px;
}
.detail-obs-row .obs-cat {
  display: inline-block;
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--bg-hover);
  color: var(--text-muted);
  padding: 1px 6px;
  border-radius: 3px;
  margin-right: 6px;
}
.detail-obs-row .obs-headline {
  font-size: 12px;
  color: var(--text);
  font-weight: 500;
}
.detail-obs-row .obs-meta {
  font-size: 10px;
  color: var(--text-muted);
  margin-top: 4px;
}

/* References */
.detail-references a {
  display: block;
  font-size: 12px;
  color: var(--accent);
  text-decoration: none;
  margin-bottom: 4px;
}
.detail-references a:hover { text-decoration: underline; }
.detail-references .ref-date { color: var(--text-muted); margin-left: 4px; font-size: 11px; }

/* BACK TO TOP — global floating button. */
.back-to-top {
  position: fixed;
  right: 24px;
  bottom: 24px;
  width: 40px;
  height: 40px;
  display: none;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 50%;
  font-size: 18px;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(108,71,255,0.35);
  transition: background 0.15s, transform 0.15s;
  z-index: 50;
}
.back-to-top.visible { display: inline-flex; }
.back-to-top:hover {
  background: var(--accent-hover);
  transform: translateY(-2px);
}

/* SITE FOOTER */
.site-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 32px;
  height: 52px;
  border-top: 1px solid var(--border);
  background: var(--bg);
  flex-shrink: 0;
}
.site-footer-left { display: flex; align-items: center; gap: 20px; }
.site-footer-logo {
  height: 38px;
  width: auto;
  flex-shrink: 0;
  opacity: 0.85;
}
[data-theme="dark"] .site-footer-logo { filter: invert(1); }
.site-footer-links { display: flex; align-items: center; gap: 20px; }
.site-footer-links a {
  font-size: 12px;
  color: var(--text-muted);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 3px;
}
.site-footer-links a:hover { color: var(--text); }
.site-footer-modules {
  display: flex;
  align-items: center;
  gap: 20px;
  padding-left: 20px;
  margin-left: 4px;
  border-left: 1px solid var(--border);
}
.site-footer-copy { font-size: 12px; color: var(--text-muted); }

@media (max-width: 640px) {
  .site-footer { flex-direction: column; height: auto; padding: 12px 16px; gap: 10px; }
  .site-footer-left { flex-direction: column; gap: 10px; }
  .site-footer-links { flex-wrap: wrap; justify-content: center; }
  .site-footer-modules { border-left: none; padding-left: 0; margin-left: 0; }
}


/* ============================================================
   INTELLIGENCE CONCIERGE — slide-in side panel.
   Layout mirrors the cemoddule cyber-exposure concierge:
   pill input + round send, grouped suggestion pills, soft
   shadow, 6px left-edge resize handle.
   ============================================================ */

/* No body lock — cemoddule lets the background page stay scrollable while
   the concierge is open. The overlay + fixed panel capture pointer events
   in their own area; locking body would remove the scrollbar and shift
   the centered .page container, which the user reads as the page
   "shrinking" when the panel opens. */

.cnc-overlay {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.2);
  display: none;
  z-index: 9000;
}
.cnc-overlay.open { display: block; }

.cnc-panel {
  position: fixed; top: 0; right: 0;
  width: 600px; max-width: 95vw; height: 100vh;
  background: var(--bg);
  border-left: 1px solid var(--border);
  display: flex; flex-direction: column;
  transform: translateX(100%);
  transition: transform 0.25s ease;
  box-shadow: -4px 0 24px rgba(0, 0, 0, 0.1);
  z-index: 9001;
}
.cnc-panel.open { transform: translateX(0); }
@media (max-width: 768px) {
  .cnc-panel { width: 100%; max-width: 100vw; }
}

.cnc-resize-handle {
  position: absolute; left: 0; top: 0;
  width: 6px; height: 100%;
  cursor: ew-resize; z-index: 10;
}
.cnc-resize-handle:hover, .cnc-resize-handle.dragging {
  background: var(--accent); opacity: 0.3;
}

.cnc-header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border-light);
  display: flex; align-items: center; justify-content: space-between;
  flex-shrink: 0;
}
.cnc-header-left { display: flex; align-items: center; gap: 10px; }
.cnc-header-icon { font-size: 22px; color: var(--accent); }
.cnc-title { font-size: 14px; font-weight: 600; color: var(--text); }

.cnc-header-actions { display: flex; align-items: center; gap: 6px; }
/* Reuse the same .detail-close visual (circular bg-page button) cemoddule
   uses in its concierge header. Existing .detail-panel-header .detail-close
   rule stays for the threat actors detail panel; this one applies in the
   concierge context. */
.cnc-header .detail-close {
  width: 32px; height: 32px; border-radius: 50%;
  border: none; background: var(--bg-page);
  color: var(--text-muted);
  cursor: pointer; transition: all var(--transition);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  padding: 0;
}
.cnc-header .detail-close:hover { background: var(--border); color: var(--text); }
.cnc-header .detail-close .material-icons-round { font-size: 18px; }

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

.cnc-messages {
  flex: 1; overflow-y: auto;
  padding: 16px;
  display: flex; flex-direction: column; gap: 10px;
}

/* Chat bubbles */
.cnc-msg {
  max-width: 90%;
  padding: 10px 14px;
  border-radius: var(--radius-lg);
  font-size: 13px; line-height: 1.6;
  text-align: left;
  word-break: break-word;
  overflow-wrap: anywhere;
}
.cnc-msg-user {
  align-self: flex-end;
  background: var(--accent); color: #fff;
  border-bottom-right-radius: 4px;
  white-space: pre-wrap;
}
.cnc-msg-assistant {
  align-self: flex-start;
  background: var(--bg-page);
  border: 1px solid var(--border-light);
  border-bottom-left-radius: 4px;
  color: var(--text);
}
.cnc-msg-assistant h3, .cnc-msg-assistant h4, .cnc-msg-assistant h5 {
  font-size: 13px; font-weight: 600; color: var(--text);
  margin: 12px 0 4px;
}
.cnc-msg-assistant h3:first-child,
.cnc-msg-assistant h4:first-child,
.cnc-msg-assistant h5:first-child { margin-top: 0; }
.cnc-msg-assistant ul, .cnc-msg-assistant ol {
  padding-left: 22px; margin: 4px 0 8px;
  text-align: left;
}
.cnc-msg-assistant li { margin: 2px 0; }
.cnc-msg-assistant li > ul, .cnc-msg-assistant li > ol { margin: 2px 0; }
.cnc-msg-assistant strong { font-weight: 600; color: var(--text); }
.cnc-msg-assistant em { font-style: italic; }
.cnc-msg-assistant code {
  background: var(--bg); padding: 1px 6px; border-radius: 3px;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 12.5px; color: var(--accent);
}
.cnc-msg-assistant hr {
  border: none; border-top: 1px solid var(--border-light);
  margin: 10px 0;
}
.cnc-section-header {
  font-size: 13px; font-weight: 600; color: var(--text);
  margin: 12px 0 4px;
  letter-spacing: 0.01em;
}
.cnc-msg-assistant > .cnc-section-header:first-child { margin-top: 0; }
.cnc-msg-thinking {
  display: flex; align-items: center; gap: 8px;
  color: var(--text-muted); font-style: italic;
}
.cnc-thinking-dot {
  display: inline-block; width: 8px; height: 8px;
  border-radius: 50%; background: var(--accent);
  animation: cnc-pulse 1.2s infinite;
}
@keyframes cnc-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.4; transform: scale(0.85); }
}

/* Welcome state with grouped suggestion pills */
.cnc-welcome {
  text-align: center;
  padding: 20px 16px 16px;
}
.cnc-welcome-icon {
  font-size: 40px; color: var(--accent);
  margin-bottom: 10px; display: inline-block;
}
.cnc-welcome-title { font-weight: 600; font-size: 15px; margin-bottom: 6px; color: var(--text); }
.cnc-welcome-sub {
  color: var(--text-secondary); font-size: 12px;
  max-width: 320px; margin: 0 auto;
}
.cnc-suggestions {
  text-align: left;
  margin-top: 16px;
  max-width: 400px;
  margin-left: auto; margin-right: auto;
}
.cnc-prompt-category-group { margin-bottom: 10px; }
.cnc-prompt-category-label {
  font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.6px;
  color: var(--text-muted); margin-bottom: 5px;
  padding-left: 2px;
}
.cnc-prompt-category-items { display: flex; flex-wrap: wrap; gap: 5px; }
.cnc-suggestion-pill {
  padding: 5px 11px;
  background: var(--bg-page);
  border: 1px solid var(--border);
  border-radius: 20px;
  font-size: 11px; color: var(--text-secondary);
  cursor: pointer; transition: var(--transition);
  font-family: inherit; line-height: 1.4;
}
.cnc-suggestion-pill:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-light);
}

/* Input area — pill textarea + round send */
.cnc-input-area {
  padding: 12px 16px 28px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
.cnc-input-row { display: flex; gap: 8px; align-items: flex-end; }
.cnc-input {
  flex: 1;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 24px;
  background: var(--bg-page);
  color: var(--text);
  font-size: 13px; font-family: inherit;
  outline: none; transition: var(--transition);
  resize: none; overflow: hidden;
  line-height: 1.4;
  max-height: 180px;
}
.cnc-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-light);
}
/* Round send button — overrides the default rectangular .btn padding so
   the round shape and 38×38 size match cemoddule's `.concierge-send`. */
.cnc-send-btn.btn {
  width: 38px; height: 38px;
  border-radius: 50%;
  padding: 0;
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.cnc-send-btn .material-icons-round { font-size: 18px; }

/* Locked state inside panel */
.cnc-locked {
  padding: 40px 28px; text-align: center;
  display: flex; flex-direction: column; align-items: center;
  height: 100%; justify-content: center;
}
.cnc-lock-icon { font-size: 44px; margin-bottom: 12px; }
.cnc-locked h3 { font-size: 18px; font-weight: 600; margin-bottom: 10px; color: var(--text); }
.cnc-locked p { font-size: 14px; color: var(--text-secondary); line-height: 1.55; max-width: 380px; }
.cnc-locked .btn-primary {
  padding: 10px 20px; background: var(--accent); color: #fff;
  border: none; border-radius: var(--radius);
  font-family: inherit; font-size: 14px; font-weight: 500;
  cursor: pointer; transition: var(--transition); margin-top: 18px;
}
.cnc-locked .btn-primary:hover { background: var(--accent-hover); }

/* Settings — branding editor (PROJECT_PLAN.md Phase 2) */
.settings-page { max-width: 100%; }
.settings-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px 24px;
  background: var(--bg);
  margin-bottom: 16px;
}
.settings-card-header { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.settings-card-icon { font-size: 20px; color: var(--accent); }
.settings-card-title { margin: 0; font-size: 15px; }

/* Free-tier "PDF Branding" card — softer chrome, lock pill alongside the
   title to make the gated state legible. */
.settings-card--locked {
  background: var(--bg-page, var(--bg));
  border-style: dashed;
}
.settings-card--locked .settings-card-icon { color: var(--text-muted); }
.settings-card--locked .settings-card-subtitle { margin-bottom: 0; }
.premium-lock-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  padding: 2px 8px;
  border-radius: 999px;
  color: var(--accent);
  background: var(--accent-light);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border));
}
.premium-lock-pill .material-icons-round { font-size: 13px; }
.settings-card-subtitle { font-size: 12px; color: var(--text-muted); margin: 0 0 20px 0; line-height: 1.5; }

.settings-field { margin-bottom: 16px; }
.settings-label { display: block; font-size: 12px; font-weight: 600; color: var(--text-secondary); margin-bottom: 4px; }
.settings-input {
  width: 100%; padding: 8px 12px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg-page, var(--bg)); color: var(--text);
  font-size: 13px; box-sizing: border-box;
  font-family: inherit;
}
.settings-hint { font-size: 11px; color: var(--text-muted); margin: 4px 0 0 0; }
.settings-file-input { font-size: 12px; }
.settings-logo-preview { margin-bottom: 8px; }
.settings-logo-img { max-width: 200px; max-height: 80px; border: 1px solid var(--border); border-radius: 4px; padding: 4px; background: #fff; }

.settings-color-row { display: flex; align-items: center; gap: 10px; }
.settings-color-picker {
  width: 40px; height: 32px;
  border: 1px solid var(--border); border-radius: var(--radius);
  cursor: pointer; padding: 2px;
}
.settings-color-hex {
  width: 90px; padding: 6px 8px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg-page, var(--bg)); color: var(--text);
  font-size: 12px; font-family: monospace;
}

.settings-actions {
  border-top: 1px solid var(--border);
  padding-top: 16px;
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin-top: 8px;
}
.settings-actions-hint { font-size: 12px; color: var(--text-muted); line-height: 1.5; }
.settings-actions-hint a { color: var(--accent); text-decoration: none; }
.settings-actions-hint a:hover { text-decoration: underline; }
/* Inline status div + conflict modal styles retired 2026-05-04 (ISSUE-016):
   /purple/#settings now surfaces save/load feedback as toasts (showToast in
   pages/settings.js), matching cemoddule's UX. Toasts are inline-styled in
   the JS so no CSS class is needed here. */

/* Watch Premium subscription card — PROJECT_PLAN.md Phase 6.
   State pill + tier comparison + meta grid + activate/cancel actions.
   Lives next to PDF Branding so AC 6.10 (no sub-modal drilldown) holds. */
.premium-state-pill {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: 999px;
  font-size: 11px; font-weight: 600;
  background: var(--bg-page, #f5f5f7); color: var(--text-muted);
  border: 1px solid var(--border);
}
.premium-state-pill .dot {
  width: 6px; height: 6px; border-radius: 50%; background: currentColor;
  display: inline-block;
}
.premium-state-pill--active-locked,
.premium-state-pill--active-unlocked {
  background: #dcfce7; color: #166534; border-color: #86efac;
}
.premium-state-pill--recently-cancelled {
  background: #fef9c3; color: #854d0e; border-color: #facc15;
}
.premium-state-pill--never-active {
  background: var(--bg-page, #f5f5f7); color: var(--text-muted);
}

.premium-tier-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
  margin: 12px 0 16px 0;
}
/* Caption above the tier-comparison block when shown to active subscribers
   ("Your subscription includes"). Free tier doesn't render this label —
   the Activate CTA below the grid carries the framing. */
.premium-included-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin: 18px 0 0 0;
}
@media (max-width: 640px) { .premium-tier-grid { grid-template-columns: 1fr; } }
.premium-tier {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 14px 16px; background: var(--bg-page, #fafafa);
}
.premium-tier--premium {
  border-color: var(--accent, #0c345b);
  background: color-mix(in srgb, var(--accent, #0c345b) 5%, var(--bg, white));
}
.premium-tier-header {
  font-size: 12px; font-weight: 700; text-transform: uppercase;
  color: var(--text-secondary); letter-spacing: 0.4px;
  margin-bottom: 8px;
}
.premium-tier--premium .premium-tier-header { color: var(--accent, #0c345b); }
.premium-tier-features {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 6px;
  font-size: 13px;
}
.premium-tier-features li {
  display: flex; align-items: flex-start; gap: 6px;
  color: var(--text);
}
.premium-tier-features .material-icons-round {
  font-size: 16px; flex-shrink: 0; margin-top: 1px;
  color: #166534;
}
.premium-tier-feature--disabled { color: var(--text-muted); }
.premium-tier-feature--disabled .material-icons-round { color: #9ca3af; }

.premium-meta-grid {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  padding: 12px 16px; margin: 0 0 16px 0;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg-page, #fafafa);
}
@media (max-width: 640px) { .premium-meta-grid { flex-direction: column; align-items: stretch; } }
.premium-meta {
  flex: 1 1 0;
  min-width: 100px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.premium-meta-label {
  font-size: 11px; font-weight: 600; text-transform: uppercase;
  color: var(--text-muted); letter-spacing: 0.4px;
}
.premium-meta-value { font-size: 13px; color: var(--text); font-weight: 500; }
/* Inline Cancel button rendered inside the meta-grid once the lock period
   has passed. Pushed to the right edge with margin-left:auto so the metas
   on the left keep their equal-width flex distribution. */
.premium-meta-action { flex-shrink: 0; margin-left: auto; }

.premium-activate-actions { gap: 12px; }
#premiumAddSlotsBtn { text-decoration: none; display: inline-flex; align-items: center; }

.premium-cost-callout {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 12px 16px; margin: 0 0 16px 0;
  background: var(--bg-page, #fafafa);
  display: flex; flex-direction: column; gap: 12px;
}
.premium-cost-callout-row {
  display: flex; align-items: flex-start; gap: 10px;
}
.premium-cost-icon {
  color: var(--accent, #0c345b);
  font-size: 20px; flex-shrink: 0; margin-top: 2px;
}
.premium-cost-label {
  font-size: 12px; font-weight: 600; color: var(--text-secondary);
  margin-bottom: 2px;
}
.premium-cost-detail {
  font-size: 13px; color: var(--text); line-height: 1.5;
}

/* Export PDF button — used on briefing detail, intelligence briefing detail,
   and threat-actor detail panel. Inherits from .btn but reserves an accent
   colour for the icon and slightly tighter padding so it sits cleanly in
   action rows next to other small controls. */
.btn-export-pdf {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  font-size: 13px; font-weight: 500;
  cursor: pointer;
  transition: var(--transition);
}
.btn-export-pdf:hover:not(:disabled) {
  background: var(--bg-hover);
  border-color: var(--accent);
  color: var(--accent);
}
.btn-export-pdf:disabled { opacity: 0.6; cursor: progress; }
.btn-export-pdf .material-icons-round { color: var(--accent); }
.btn-export-pdf.btn-sm { padding: 4px 9px; font-size: 12px; }
.btn-export-pdf.btn-sm .material-icons-round { font-size: 13px; }

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

/* Locked state for the export button — same visual pattern as the Concierge
   header button when the tenant lacks Watch Premium. The button stays
   visible (so users discover the gate) but is muted, has a lock icon, and
   shows a tooltip on hover. Click still fires; the handler surfaces the
   upgrade CTA toast instead of attempting the export. */
.btn-export-pdf--locked {
  color: var(--text-muted);
  border-color: var(--border);
  cursor: help;
  opacity: 0.85;
  position: relative;
}
.btn-export-pdf--locked:hover {
  background: var(--bg-hover);
  color: var(--text-secondary);
  border-color: var(--border);
}
.btn-export-pdf--locked .material-icons-round {
  color: var(--text-muted);
}
/* Custom hover tooltip for the locked-state PDF button. Native `title`
   tooltips kick in after ~500–1500ms depending on browser/OS — too slow
   for a one-line gate hint. Custom tooltip uses `data-tooltip` and a
   100ms transition for a snappy reveal. */
.btn-export-pdf--locked[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  background: var(--text);
  color: var(--bg);
  font-size: 11px;
  font-weight: 500;
  padding: 4px 8px;
  border-radius: 4px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
  z-index: 100;
}
.btn-export-pdf--locked[data-tooltip]:hover::after { opacity: 1; }
.btn-export-pdf-lock-icon {
  font-size: 13px !important;
  margin-left: 4px;
  opacity: 0.75;
  vertical-align: middle;
}

/* Ransomware Victims page (PROJECT_PLAN.md Phase 7).
   Patterned on the History page chrome — list-toolbar + state-message
   + load-more-container come from there. New rules below cover the
   stats summary card, the per-victim row, and the top-groups bar list. */

.ransom-page { display: flex; flex-direction: column; gap: 16px; }

.intel-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 16px;
  align-items: start;
}
.intel-layout--ransom {
  grid-template-columns: minmax(0, 1fr) 640px;
}
.intel-main { min-width: 0; }
.intel-side {
  position: sticky;
  top: 112px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.intel-side-panel {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  padding: 14px 16px;
}
.intel-side-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--text-secondary);
  letter-spacing: 0.4px;
  margin-bottom: 8px;
}
.intel-side-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.intel-side-list button {
  width: 100%;
  text-align: left;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-page);
  color: var(--text-secondary);
  font-size: 12px;
  padding: 7px 9px;
  cursor: pointer;
}
.intel-side-list button:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-light);
}
.intel-side-list-count {
  color: var(--text-muted);
  font-size: 11px;
  margin-left: 6px;
}
@media (max-width: 1140px) {
  .intel-layout { grid-template-columns: 1fr; }
  .intel-side { position: static; }
}

.ransom-stats-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 20px;
  background: var(--bg);
  display: flex; flex-direction: column; gap: 16px;
}
/* Vertical gap between the two stats cards (RANSOMWARE VICTIMS and
   TOP RANSOMWARE GROUPS) when stacked together in the side panel. */
.ransom-stats-card + .ransom-stats-card { margin-top: 16px; }
.ransom-stats-card--error {
  align-items: center; text-align: center;
  padding: 24px;
  color: var(--text-muted);
}
.ransom-stat-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.ransom-stat-row--secondary { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 720px) {
  .ransom-stat-row,
  .ransom-stat-row--secondary { grid-template-columns: repeat(2, 1fr); }
}
.ransom-stat-tile {
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-page, #fafafa);
  display: flex; flex-direction: column; gap: 4px;
}
.ransom-stat-value {
  font-size: 22px; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.ransom-stat-label {
  font-size: 11px; font-weight: 600; text-transform: uppercase;
  color: var(--text-muted); letter-spacing: 0.4px;
}
.intel-side .ransom-stat-row,
.intel-side .ransom-stat-row--secondary {
  grid-template-columns: repeat(2, 1fr);
}
.intel-side .ransom-stat-value {
  font-size: 18px;
}
.intel-side .ransom-stat-tile {
  padding: 10px 10px;
}

/* Ransomware Victims side panel — two cards (totals + line chart, then
   group counts + horizontal bars). PROJECT_PLAN.md Phase 7 refinement
   2026-05-05: matches the cep-frontend Live module's two-column inner
   layout (tiles on the left, visualisation on the right). */
.ransom-side-section-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--text-secondary);
  letter-spacing: 0.4px;
}
.ransom-side-grid {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: 16px;
  align-items: stretch;
}
.ransom-side-tiles {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* Row variant — 4-up tile grid for the Ransomware Victims summary, with
   the chart sitting full-width underneath. Operator request 2026-05-06. */
.ransom-side-tiles--row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
.ransom-side-chart--full { width: 100%; margin-top: 4px; }
@media (max-width: 720px) {
  .ransom-side-tiles--row { grid-template-columns: repeat(2, 1fr); }
}
/* Side-panel stat tiles styled like the cemoddule dashboard's .stat-card —
   clean white card with light border + subtle shadow, default dark text
   for the value (the purple gradient is reserved for the dashboard's
   special "total" tile in cemoddule and we don't want every tile shouting
   in accent colour). Operator feedback 2026-05-06. */
.intel-side .ransom-side-tiles .ransom-stat-tile {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
  transition: box-shadow 0.15s;
}
.intel-side .ransom-side-tiles .ransom-stat-tile:hover {
  box-shadow: 0 2px 6px rgba(0,0,0,0.06);
}
.intel-side .ransom-side-tiles .ransom-stat-value {
  font-size: 18px;
  color: var(--text);
  font-weight: 700;
  letter-spacing: -0.2px;
  line-height: 1.1;
}
.intel-side .ransom-side-tiles .ransom-stat-label {
  margin-top: 4px;
  font-size: 10px;
}
.ransom-side-chart {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
}
@media (max-width: 1280px) {
  .ransom-side-grid { grid-template-columns: 1fr; }
}

/* Small title above the trend chart so the user knows what they're
   looking at without inferring it from the axes. */
.ransom-chart-title {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-muted);
  margin: 4px 0 8px 4px;
}

/* ApexCharts trend chart container — pinned via ApexCharts options
   (height: 240, width: 100%). Wrapper rules keep the chart from
   overflowing the surrounding card. */
.ransom-apex-chart {
  width: 100%;
  min-height: 240px;
}
.ransom-apex-chart .apexcharts-tooltip {
  font-size: 12px;
  font-family: inherit;
}

/* Single horizontal summary strip — replaces the four separate stat
   tiles with one card showing all counts in a row, separated by light
   dividers. Operator request 2026-05-06. */
.ransom-summary-strip {
  /* Auto-columns so the same strip class works for both the 4-item
     Victims card and the 3-item Top Groups card. */
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
  overflow: hidden;
}
.ransom-summary-item {
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 4px;
  min-width: 0;
}
.ransom-summary-value {
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.2px;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ransom-summary-label {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--text-muted);
  letter-spacing: 0.4px;
}
@media (max-width: 720px) {
  .ransom-summary-strip {
    grid-auto-flow: row;
    grid-template-columns: repeat(2, 1fr);
  }
}

.ransom-top-groups {
  display: flex; flex-direction: column; gap: 6px;
}
.ransom-top-groups-title {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  color: var(--text-secondary); letter-spacing: 0.4px;
  margin-bottom: 4px;
}
.ransom-top-group {
  display: grid;
  grid-template-columns: 130px minmax(0, 1fr) 56px 44px;
  align-items: center;
  gap: 10px;
  font-size: 12px;
}
.ransom-top-group-name {
  color: var(--text);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ransom-top-group-bar {
  position: relative;
  height: 16px;
  border-radius: 3px;
  background: color-mix(in srgb, var(--accent, #0c345b) 8%, transparent);
  overflow: hidden;
}
.ransom-top-group-bar-fill {
  height: 100%;
  background: var(--accent, #0c345b);
}
.ransom-top-group-count {
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  text-align: right;
}
.ransom-top-group-pct {
  font-size: 11px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* Group pill lives in the detail row below the company headline so
   long names ("EVEREST RANSOMWARE GROUP", "SAFEPAY RANSOMWARE", etc.)
   never run out of space. The detail row is a flex container so the
   chip and country chip sit shoulder-to-shoulder. */
.ransom-feed .feed-item-detail {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}
.ransom-feed .feed-item-detail .ransom-group-pill {
  white-space: nowrap;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  font-weight: 600;
}

.ransom-trend {
  border-top: 1px solid var(--border);
  padding-top: 14px;
}
.ransom-trend-bars {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 6px;
  align-items: end;
  margin-top: 6px;
}
.ransom-trend-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.ransom-trend-bar {
  width: 100%;
  max-width: 14px;
  border-radius: 3px 3px 0 0;
  background: var(--accent);
  opacity: 0.9;
}
.ransom-trend-label {
  font-size: 9px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.2px;
}

.ransom-feed { display: flex; flex-direction: column; gap: 0; }
.ransom-row {
  display: flex; align-items: center; gap: 16px;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.ransom-row:hover {
  border-color: color-mix(in srgb, var(--accent, #0c345b) 30%, var(--border));
  box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}
.ransom-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.ransom-row-name {
  font-size: 14px; font-weight: 600; color: var(--text);
  word-break: break-word;
}
.ransom-row-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ransom-group-pill {
  display: inline-flex; align-items: center;
  padding: 3px 10px; border-radius: 3px;
  font-size: 11px; font-weight: 600;
  background: #fde8e8; color: #991b1b;
  border: none;
  cursor: pointer;
}
.ransom-group-pill:hover { background: #fbd5d5; }
.ransom-group-pill--square {
  border-radius: 3px;
}
.ransom-row-country {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 12px; color: var(--text-muted);
}
.ransom-row-country .material-icons-round { font-size: 14px; }
.ransom-row-date {
  font-size: 12px; color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
@media (max-width: 640px) {
  .ransom-row { flex-direction: column; align-items: flex-start; gap: 8px; }
  .ransom-row-date { align-self: flex-end; }
}

/* Data Breaches page (PROJECT_PLAN.md Phase 7).
   Breach rows reuse .feed-item layout (time on left, content on right),
   matching the Ransomware Victims feed. The time block stacks relative
   date + absolute date (no time component since breaches only carry a
   leak date). Slightly more vertical padding than the default .feed-item
   to accommodate the multi-line description block. */
.ransom-feed .feed-item.breach-row {
  align-items: flex-start;
  padding-top: 14px;
  padding-bottom: 14px;
}
/* Tighter time column for breach rows — date-only content fits in
   ~95 px ("2 May 2026" / "Yesterday"), so the saved width goes to the
   content column where the headline + company + 3-line description sit. */
.ransom-feed .feed-item.breach-row .feed-item-time {
  flex: 0 0 95px;
}
.breach-row-company {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: -2px;
}
.breach-row-desc {
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.5;
  margin-top: 4px;
}
.breach-industry-pill {
  background: #dbeafe;
  color: #1e40af;
  border-color: #93c5fd;
}
.breach-industry-pill:hover { background: #c7d8f7; }

/* From the News page (PROJECT_PLAN.md Phase 7).
   Card list with optional thumbnail image. Reuses .ransom-page wrapper
   for the toolbar layout; its own card grid below. */
.news-feed { display: flex; flex-direction: column; gap: 12px; }
.news-card {
  display: flex; gap: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  background: var(--bg);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.news-card:hover {
  border-color: color-mix(in srgb, var(--accent, #0c345b) 30%, var(--border));
  box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}
.news-card-image {
  flex-shrink: 0;
  width: 120px; height: 80px;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-page, #fafafa);
}
.news-card-image img { width: 100%; height: 100%; object-fit: cover; display: block; }
.news-card-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.news-card-date {
  font-size: 11px; font-weight: 600; text-transform: uppercase;
  color: var(--text-muted); letter-spacing: 0.4px;
}
.news-card-title { font-size: 15px; font-weight: 600; line-height: 1.35; }
.news-card-title a { color: var(--text); text-decoration: none; }
.news-card-title a:hover { color: var(--accent, #0c345b); text-decoration: underline; }
.news-card-desc {
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.5;
}
/* Source URLs in news article descriptions — rendered on their own line
   in dark grey with no underline so they sit quietly under the prose. */
.news-card-desc a.news-link {
  color: var(--text-secondary);
  text-decoration: none;
  word-break: break-all;
}
.news-card-desc a.news-link:hover {
  color: var(--text);
}
.news-card-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.news-tag-pill {
  display: inline-flex; align-items: center;
  padding: 2px 9px; border-radius: 999px;
  font-size: 11px; font-weight: 500;
  background: #f3e8ff; color: #6b21a8; border: 1px solid #d8b4fe;
  cursor: pointer;
}
.news-tag-pill:hover { background: #e9d5ff; }
@media (max-width: 640px) {
  .news-card { flex-direction: column; }
  .news-card-image { width: 100%; height: 160px; }
}

.news-pagination { padding: 16px 0; }
.news-pagination-inner {
  display: flex; align-items: center; justify-content: center; gap: 16px;
}
.news-pagination-text { font-size: 13px; color: var(--text-muted); }
.news-pagination .btn[disabled] { opacity: 0.4; pointer-events: none; }

/* Attack Campaigns page (PROJECT_PLAN.md Phase 7).
   Responsive 3-column card grid (auto-fits on smaller viewports). */
.campaigns-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
}
.campaign-card {
  display: flex; flex-direction: column; gap: 10px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s, transform 0.1s;
}
.campaign-card:hover {
  border-color: color-mix(in srgb, var(--accent, #0c345b) 30%, var(--border));
  box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}
.campaign-card:focus-visible {
  outline: 2px solid var(--accent, #0c345b);
  outline-offset: 2px;
}
.campaign-card:active { transform: translateY(1px); }
.campaign-card-name { font-size: 14px; font-weight: 600; color: var(--text); }
.campaign-card-desc {
  font-size: 13px; color: var(--text-muted); line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.campaign-card-stats {
  display: flex;
  gap: 16px;
  justify-content: space-between;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  margin-top: auto;
}
.campaign-card-stat { display: flex; flex-direction: column; gap: 2px; }
.campaign-card-stat + .campaign-card-stat { text-align: right; align-items: flex-end; }
.campaign-card-stat--recent .campaign-card-stat-value { color: var(--accent); }
.campaign-card-stat--recent .campaign-card-stat-label { color: var(--accent); }
.campaign-card-stat-value {
  font-size: 16px; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.campaign-card-stat-label {
  font-size: 10px; font-weight: 600; text-transform: uppercase;
  color: var(--text-muted); letter-spacing: 0.4px;
}

/* Skeleton placeholder cards shown while /api/profiles resolves. Mirrors
   the real card geometry (title, two desc lines, stat row) so there's no
   layout shift when the data arrives. Reuses the .ransom-skel shimmer. */
.campaign-card--skeleton {
  cursor: default;
  pointer-events: none;
}
.campaign-card--skeleton:hover {
  border-color: var(--border);
  box-shadow: none;
}
.campaign-skel-name {
  width: 60%;
  height: 14px;
  border-radius: 4px;
}
.campaign-skel-desc {
  width: 100%;
  height: 12px;
  border-radius: 4px;
  margin-top: -2px;
}
.campaign-skel-desc--short { width: 75%; }
.campaign-skel-stat-value {
  display: block;
  width: 36px;
  height: 16px;
  border-radius: 4px;
  margin-bottom: 4px;
}
.campaign-skel-stat-label {
  display: block;
  width: 50px;
  height: 10px;
  border-radius: 4px;
}

/* Attack Campaigns — side-panel detail view. Mirrors actors.js detail
   panel pattern; reuses .detail-overlay / .detail-panel chrome. */
.campaign-detail-desc-block {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.55;
  padding: 10px 12px;
  background: var(--bg-page, #fafafa);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 16px;
  white-space: pre-wrap;
}
.campaign-detail-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px;
  margin-bottom: 4px;
}
.campaign-stat-tile {
  padding: 12px 14px;
  background: var(--bg-page, #fafafa);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.campaign-stat-value {
  font-size: 22px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.campaign-stat-label {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--text-muted);
  letter-spacing: 0.4px;
  margin-top: 4px;
}
/* Campaign findings — finding-card layout ported from the Cyber Exposure
   module (cemoddule). Field set mirrors cep-frontend's Live findings:
   title (source_title), source domain, summary/snippet, source URL, tags.
   Class names prefixed `cf-` (campaign finding) to keep the namespace
   isolated from any future generic .finding-card use. */
.cf-finding-card {
  background: var(--bg);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-lg);
  padding: 14px 16px;
  box-shadow: var(--shadow-sm);
  margin-bottom: 8px;
}
.cf-finding-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.cf-finding-meta {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 4px;
  flex-wrap: wrap;
}
.cf-finding-meta .material-icons-round {
  font-size: 13px;
  vertical-align: -2px;
  margin-right: 2px;
}
/* Raw snippet box with keyword highlight — ported from cemoddule's
   .snippet-box / .snippet-box .kw treatment so the visual matches Cyber
   Exposure findings. */
.cf-snippet-box {
  background: var(--bg-page);
  border: 1px solid var(--border-light);
  border-radius: var(--radius);
  padding: 10px 14px;
  margin: 8px 0 0;
  font-size: 11px;
  color: var(--text-secondary);
  line-height: 1.5;
  font-family: 'SF Mono', 'Fira Code', monospace;
  white-space: pre-wrap;
  word-break: break-word;
}
.cf-snippet-kw {
  background: #fef3c7;
  color: #92400e;
  padding: 0 2px;
  border-radius: 2px;
  font-weight: 700;
}
.cf-finding-url {
  font-size: 11px;
  color: var(--text-muted);
  margin: 0 0 6px;
  word-break: break-all;
  font-family: 'SF Mono', 'Fira Code', monospace;
}
.cf-finding-tags {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.cf-tag {
  font-size: 10px;
  font-weight: 500;
  padding: 2px 7px;
  border-radius: 4px;
  background: var(--bg-page);
  color: var(--text-muted);
  border: 1px solid var(--border-light);
}
.campaign-alerts-empty {
  padding: 24px 12px;
  text-align: center;
  color: var(--text-muted);
}
.campaign-alerts-empty .state-icon { font-size: 24px; margin-bottom: 6px; }
.campaign-alerts-empty .state-text { font-size: 13px; color: var(--text); margin-bottom: 4px; }
.campaign-alerts-empty .state-hint { font-size: 11px; color: var(--text-muted); }

/* "Findings by source" horizontal bar rows. Mirrors the cep-frontend
   Live module campaign-detail layout: label / proportional bar / pct. */
.campaign-source-rows {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 4px;
}
.campaign-source-row {
  display: grid;
  grid-template-columns: 110px 1fr 56px;
  align-items: center;
  gap: 8px;
  font-size: 12px;
}
.campaign-source-label {
  color: var(--text-secondary);
  font-weight: 500;
}
.campaign-source-bar-wrap {
  height: 18px;
  background: var(--bg-page, #fafafa);
  border-radius: 3px;
  overflow: hidden;
  position: relative;
}
.campaign-source-bar {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 6px;
  border-radius: 3px;
  transition: width 0.25s ease;
  min-width: 2px;
}
.campaign-source-bar-value {
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.campaign-source-pct {
  font-size: 11px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.campaign-trend-chart {
  margin-top: 4px;
  margin-bottom: 12px;
}

/* Ransomware Victims partial-gate — operator decision 2026-05-06.
   Free tier sees stats + latest 25 victims only. Search and filters are
   rendered disabled with lock affordances; Load-more becomes a CTA to
   /purple/#settings. Premium tier sees the unlocked controls. */
.ransom-locked-control {
  cursor: not-allowed;
  background: var(--bg-page, #fafafa);
  color: var(--text-muted);
  border-color: var(--border);
  opacity: 0.85;
}
.ransom-locked-control:focus,
.ransom-locked-control:hover { outline: none; box-shadow: none; }
.ransom-locked-search { position: relative; }
.ransom-locked-search .ransom-locked-icon {
  position: absolute;
  right: 10px; top: 50%; transform: translateY(-50%);
  color: var(--text-muted);
  font-size: 16px;
  pointer-events: none;
}
.ransom-locked-search .search-input.ransom-locked-control { padding-right: 32px; }

.ransom-premium-cta {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 12px; margin-top: 8px;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent, #0c345b) 5%, transparent);
  color: var(--text-secondary);
  font-size: 12px;
}
.ransom-premium-cta .material-icons-round {
  font-size: 14px;
  color: var(--accent, #0c345b);
}
.ransom-premium-cta a {
  color: var(--accent, #0c345b);
  font-weight: 600;
  text-decoration: none;
}
.ransom-premium-cta a:hover { text-decoration: underline; }

/* Ransomware Victims toolbar — keep search + group + date preset on one
   line. Date filtering uses a preset dropdown ("Any time / Today / Last
   24h / 7 days / 30 days / 90 days / Custom range…"), matching the
   cemoddule findings page. From/To inputs only render on a second row
   when "Custom range…" is selected, keeping the main toolbar tight. */
.ransom-page .filter-row { flex-wrap: nowrap; align-items: center; }
.ransom-page .search-input-wrap {
  flex: 1 1 320px;
  min-width: 200px;
}
.ransom-page #ransomGroupSelect,
.ransom-page #breachIndustrySelect {
  flex: 0 1 200px;
  max-width: 220px;
  min-width: 140px;
  text-overflow: ellipsis;
}
.ransom-page #ransomDatePreset,
.ransom-page #breachDatePreset {
  flex: 0 0 auto;
  min-width: 130px;
}

.ransom-custom-date-row {
  margin-top: 8px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-page, #fafafa);
  gap: 8px;
}
.ransom-custom-date-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-muted);
}
.ransom-custom-date-row input[type="date"] {
  font-size: 12px;
  padding: 5px 8px;
}

@media (max-width: 880px) {
  .ransom-page .filter-row { flex-wrap: wrap; }
}

/* Paginator on the Ransomware Victims feed (operator request 2026-05-06,
   replacing the previous Load-more pattern). Mirrors the cep-frontend
   PaginatorComponent visual: <<  <  [1] [2] ... [N]  >  >> with the
   active page highlighted. The wrapper also doubles as the host for the
   free-tier "See all N older victims with Watch Premium" CTA when
   isPremium is false. */
.ransom-pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 4px;
  padding: 16px 0 4px;
}
.ransom-pagination.hidden { display: none; }
.ransom-pagination--free { gap: 0; }
.ransom-pagination-btn {
  min-width: 30px;
  height: 30px;
  padding: 0 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.ransom-pagination-btn:hover:not([disabled]):not(.active) {
  border-color: var(--accent, #0c345b);
  color: var(--accent, #0c345b);
}
.ransom-pagination-btn[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
}
.ransom-pagination-btn.active {
  background: var(--accent, #0c345b);
  border-color: var(--accent, #0c345b);
  color: white;
  cursor: default;
}
.ransom-pagination-btn--icon { padding: 0; }
.ransom-pagination-btn--icon .material-icons-round {
  font-size: 18px;
  line-height: 1;
}
.ransom-pagination-ellipsis {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  font-size: 12px;
  color: var(--text-muted);
}

/* Free-tier upgrade banner that sits above the Live Feed on the
   Ransomware Victims page. Reads "See all N Ransomware Victims with The
   Watch Premium" and links to /purple/#settings. Operator request
   2026-05-06: replaces the inline filter-row CTA that was removed when
   the search/filter toolbar was hidden for free tier. */
.ransom-premium-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  margin-bottom: 16px;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent, #0c345b) 6%, var(--bg));
  color: var(--text);
  font-size: 13px;
  text-decoration: none;
  transition: background 0.15s;
}
/* Bottom banner sits inside the .ransom-pagination wrapper which already
   provides its own top padding — drop the margin so spacing isn't doubled. */
.ransom-pagination .ransom-premium-banner { margin-bottom: 0; }
.ransom-premium-banner:hover {
  background: color-mix(in srgb, var(--accent, #0c345b) 12%, var(--bg));
}
.ransom-premium-banner-icon {
  font-size: 18px;
  color: var(--accent, #0c345b);
  flex-shrink: 0;
}
.ransom-premium-banner-text { flex: 1; line-height: 1.4; }
.ransom-premium-banner-text strong { color: var(--accent, #0c345b); font-weight: 700; }

/* Data Breaches "Most Breached Industries" 2×2 mini-chart grid — matches
   the legacy Live module's industries breakdown (last 30d / current YTD
   / previous year / overall). Each section has its own small title and
   reuses .ransom-top-group bar rows. Operator request 2026-05-06. */
/* Single-column stack of the four mini bar charts (operator request
   2026-05-06, reverted from 2×2 grid). Each section keeps its own
   small title and reuses .ransom-top-group bar rows at the panel-wide
   default sizing. */
.ransom-industries-grid {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.ransom-industries-section {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.ransom-industries-section .ransom-chart-title {
  margin: 0 0 6px 0;
}

/* Loading skeletons for the Data Breaches stats panel — mirrors the
   eventual layout (4-up summary strip + chart, then industries list)
   so the page doesn't reflow when the fetch resolves. Operator request
   2026-05-06: too much empty space during the load window. */
.ransom-skel {
  background: linear-gradient(90deg,
    var(--bg-page, #f5f5f7) 0%,
    color-mix(in srgb, var(--bg-page, #f5f5f7) 60%, var(--border)) 50%,
    var(--bg-page, #f5f5f7) 100%);
  background-size: 200% 100%;
  border-radius: 4px;
  animation: ransom-skel-shimmer 1.4s linear infinite;
}
@keyframes ransom-skel-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.ransom-summary-item .ransom-skel--value {
  width: 64px;
  height: 22px;
  margin-bottom: 6px;
}
.ransom-summary-item .ransom-skel--label {
  width: 80px;
  height: 11px;
}
.ransom-chart-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 180px;
  padding: 24px 12px;
  color: var(--text-muted);
}
.ransom-chart-loading .state-text {
  font-size: 12px;
}

/* From the News page (PROJECT_PLAN.md Phase 7).
   Single-column layout — no aside.intel-side panel, no live-feed-container
   chrome (news isn't a streaming feed; it's a curated article list).
   Trending tags sit above the list as clickable pills (operator request
   2026-05-06, mirrors the Live Feed category-tab row). Tight vertical
   spacing — operator request 2026-05-06: too much whitespace between
   the toolbar / pills / count for the small amount of content. */
.news-page {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.news-list-header {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.news-list-header .list-count {
  background: transparent;
  padding: 0;
  font-size: 11px;
}
/* Skeleton placeholders for the news article cards while Strapi responds.
   Uses the .ransom-skel shimmer animation from the stats panel. */
.news-card.news-card--skeleton { pointer-events: none; }
.news-card--skeleton .ransom-skel { border-radius: 4px; }
.news-skel-image { width: 100%; height: 100%; border-radius: var(--radius); }
.news-skel-date { width: 80px; height: 11px; }
.news-skel-title { width: 70%; height: 18px; margin-top: 4px; }
.news-skel-desc { width: 100%; height: 12px; margin-top: 2px; }
.news-skel-desc + .news-skel-desc { width: 85%; }
