/*
 * Design tokens: light palette (default) and dark palette overrides.
 * Every color/spacing/radius/font value used elsewhere in this file must
 * reference one of these custom properties; no raw hex/rgb literals are
 * allowed outside this :root block (review requirement, task 9.1).
 */
:root {
  /* Colors */
  --color-bg: #f8f9fa;
  --color-surface: #ffffff;
  --color-border: #dee2e6;
  --color-text: #212529;
  --color-text-muted: #6c757d;
  --color-text-heading: #495057;
  --color-accent: #2563eb;
  --color-accent-contrast: #ffffff;
  --color-focus-ring: #2563eb;
  --color-error-bg: #fdecea;
  --color-error-border: #f5c2c0;
  --color-error-text: #7a1f1a;
  --color-skeleton-base: #e9ecef;
  --color-skeleton-highlight: #f5f6f7;

  /* Pipeline Health traffic-light tokens (FEATURE-012, task 12.11) */
  --color-status-green: #2f9e44;
  --color-status-green-bg: #ebfbee;
  --color-status-yellow: #e8a400;
  --color-status-yellow-bg: #fff9db;
  --color-status-red: #e03131;
  --color-status-red-bg: #fff5f5;

  /* Spacing */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;

  /* Radius */
  --radius-sm: 0.25rem;
  --radius-md: 0.375rem;
  --radius-lg: 0.75rem;

  /* Fonts */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-size-base: 1rem;
  --font-size-sm: 0.875rem;
  --font-size-lg: 1.5rem;
  --font-weight-normal: 400;
  --font-weight-semibold: 600;
}

/* Dark palette — explicit user override wins over system preference. */
[data-theme="dark"] {
  --color-bg: #14181c;
  --color-surface: #1e2328;
  --color-border: #343a40;
  --color-text: #e9ecef;
  --color-text-muted: #adb5bd;
  --color-text-heading: #ced4da;
  --color-accent: #60a5fa;
  --color-accent-contrast: #0b1220;
  --color-focus-ring: #60a5fa;
  --color-error-bg: #3a1f1f;
  --color-error-border: #7a3a38;
  --color-error-text: #f8b4b0;
  --color-skeleton-base: #2a2f34;
  --color-skeleton-highlight: #343a40;

  /* Pipeline Health traffic-light tokens (FEATURE-012, task 12.11) */
  --color-status-green: #40c057;
  --color-status-green-bg: #1a2e20;
  --color-status-yellow: #fab005;
  --color-status-yellow-bg: #332b0f;
  --color-status-red: #ff6b6b;
  --color-status-red-bg: #3a1f1f;
}

/* System dark preference — only applies when there is no explicit override.
   [data-theme="light"] is declared after this block so it always wins the
   cascade over the media query, even on a dark OS. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --color-bg: #14181c;
    --color-surface: #1e2328;
    --color-border: #343a40;
    --color-text: #e9ecef;
    --color-text-muted: #adb5bd;
    --color-text-heading: #ced4da;
    --color-accent: #60a5fa;
    --color-accent-contrast: #0b1220;
    --color-focus-ring: #60a5fa;
    --color-error-bg: #3a1f1f;
    --color-error-border: #7a3a38;
    --color-error-text: #f8b4b0;
    --color-skeleton-base: #2a2f34;
    --color-skeleton-highlight: #343a40;

    /* Pipeline Health traffic-light tokens (FEATURE-012, task 12.11) */
    --color-status-green: #40c057;
    --color-status-green-bg: #1a2e20;
    --color-status-yellow: #fab005;
    --color-status-yellow-bg: #332b0f;
    --color-status-red: #ff6b6b;
    --color-status-red-bg: #3a1f1f;
  }
}

[data-theme="light"] {
  --color-bg: #f8f9fa;
  --color-surface: #ffffff;
  --color-border: #dee2e6;
  --color-text: #212529;
  --color-text-muted: #6c757d;
  --color-text-heading: #495057;
  --color-accent: #2563eb;
  --color-accent-contrast: #ffffff;
  --color-focus-ring: #2563eb;
  --color-error-bg: #fdecea;
  --color-error-border: #f5c2c0;
  --color-error-text: #7a1f1a;
  --color-skeleton-base: #e9ecef;
  --color-skeleton-highlight: #f5f6f7;
}

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

body {
  font-family: var(--font-sans);
  background: var(--color-bg);
  color: var(--color-text);
  line-height: 1.5;
}

header {
  padding: var(--space-5) var(--space-6) var(--space-4);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
  border-top: 3px solid var(--color-accent);
}

.header-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
}

header h1 {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

header .subtitle {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  margin-top: var(--space-1);
}

.header-controls {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Language dropdown reuses .scope-dropdown chrome; .lang-current shows the
   active locale's 2-letter code so the control stays compact in the header. */
.lang-dropdown .lang-current {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
}

.lang-dropdown .scope-options {
  right: 0;
  left: auto;
  min-width: 160px;
}

.lang-options label {
  justify-content: flex-start;
}

/* Theme toggle — a simple icon button in the header, >=44x44px touch target. */
#theme-toggle {
  min-width: 44px;
  min-height: 44px;
  padding: var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: var(--font-size-lg);
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

#theme-toggle:hover {
  border-color: var(--color-accent);
}

main {
  padding: var(--space-5) var(--space-6);
  max-width: 1200px;
  margin: 0 auto;
}

.chart-section {
  margin-bottom: var(--space-6);
}

.chart-container {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  min-height: 400px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
  /* Prevent Plotly SVG from breaking out of its container */
  overflow: hidden;
  width: 100%;
}

/* Mobile legends wrap onto several rows (neighbourhood-per-trace charts can
   have a dozen+ entries) — legend.automargin (chart_theme.js) borrows extra
   bottom margin to fit them without overlapping the plot, so the container
   itself needs more total height on narrow viewports or that borrowed
   margin comes entirely out of the actual plot area, squeezing charts down
   to a sliver. */
@media (max-width: 767px) {
  .chart-container {
    min-height: 480px;
  }
}

/* Filter bar: Population toggle + Districts/Neighborhoods scope filters sit
   in a single row above the KPIs, so a selection's effect on every KPI/chart
   is visible without scrolling. All three controls stretch to fill the row
   evenly and share the same height (align-items: stretch), regardless of
   whether one control's label happens to wrap onto a second line. Wraps to
   stacked rows on narrow viewports. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}

/* District/neighborhood scope filters. display:contents removes this
   element from the flex layout entirely so its children (the two dropdowns
   + reset button) become direct flex items of .filter-bar, sized/aligned
   identically to the population toggle rather than being squeezed into a
   nested sub-row. */
.scope-filters {
  display: contents;
}

.scope-dropdown {
  position: relative;
  display: flex;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  /* Same flex-basis so Population/Districts/Neighborhoods end up equal
     width, spanning the full row. */
  flex: 1 1 240px;
}

.scope-dropdown > summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  min-height: 44px;
  width: 100%;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
  cursor: pointer;
  list-style: none;
  user-select: none;
}

/* Hide the default disclosure triangle across browsers; we render our own
   affordance via the badge + summary styling instead. */
.scope-dropdown > summary::-webkit-details-marker {
  display: none;
}
.scope-dropdown > summary::marker {
  content: '';
}

.scope-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5rem;
  padding: 0 var(--space-2);
  border-radius: var(--radius-lg);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  font-size: 0.75rem;
  font-weight: var(--font-weight-normal);
  color: var(--color-text-muted);
}

.scope-badge[data-active] {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-contrast);
}

.scope-options {
  position: absolute;
  z-index: 10;
  top: calc(100% + var(--space-2));
  left: 0;
  min-width: 220px;
  max-height: 280px;
  overflow-y: auto;
  margin: 0;
  padding: var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.15);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.scope-options label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
  cursor: pointer;
}

.scope-options label:hover {
  background: var(--color-bg);
}

.scope-options input[type="checkbox"]:disabled ~ span {
  color: var(--color-text-muted);
  cursor: not-allowed;
}

.scope-options .scope-empty {
  padding: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.scope-reset {
  align-self: center;
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  cursor: pointer;
}

.scope-reset:hover {
  color: var(--color-text-heading);
  border-color: var(--color-text-muted);
}

footer {
  padding: var(--space-5) var(--space-6);
  max-width: 1200px;
  margin: 0 auto;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2);
}

footer a {
  color: var(--color-accent);
}

/* Screen-reader-only utility for the aria-live status announcer. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* KPI row — mobile-first: 1 column, growing to a responsive grid at wider viewports. */
.kpi-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}

@media (min-width: 768px) {
  .kpi-row {
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  }
}

.kpi-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.kpi-card .kpi-label {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.kpi-card .kpi-value {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

/* Chart grid — mobile-first: 1 card per row by default, 2 per row at >=768px. */
.chart-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
}

@media (min-width: 768px) {
  .chart-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.chart-grid .chart-section {
  margin-bottom: 0;
  position: relative;
}

/* Loading skeleton — pulsing placeholder shown until Plotly renders into
   the sibling .chart-container. app.js toggles the 'is-loaded' class. */
.chart-skeleton {
  position: absolute;
  inset: 0;
  border-radius: var(--radius-md);
  background: linear-gradient(
    90deg,
    var(--color-skeleton-base) 25%,
    var(--color-skeleton-highlight) 37%,
    var(--color-skeleton-base) 63%
  );
  background-size: 400% 100%;
  animation: skeleton-pulse 1.4s ease infinite;
}

.chart-section.is-loaded .chart-skeleton {
  display: none;
}

@keyframes skeleton-pulse {
  0% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0 50%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .chart-skeleton {
    animation: none;
  }
}

/* Global error/retry block. */
.dashboard-error {
  background: var(--color-error-bg);
  border: 1px solid var(--color-error-border);
  color: var(--color-error-text);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-bottom: var(--space-5);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  justify-content: space-between;
}

/* BUGFIX: an author-stylesheet `display` rule on the same element beats the
   UA stylesheet's `[hidden] { display: none }` rule at equal specificity, so
   without this override the error banner stayed visible permanently
   regardless of the `hidden` attribute app.js toggles. */
.dashboard-error[hidden] {
  display: none;
}

/* Touch targets: every interactive control is >= 44x44px at mobile widths. */
#retry-button,
.scope-options label,
.scope-options input[type="radio"],
.scope-options input[type="checkbox"] {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

#retry-button {
  min-width: 44px;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-sm);
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
}

#retry-button:hover {
  filter: brightness(0.95);
}

/* Visible keyboard-focus outline for every interactive control, using the
   theme's focus-ring token so it stays legible in both palettes. */
:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  #theme-toggle {
    transition: none;
  }
}

/* Dashboard tab bar — mobile-first: horizontally scrollable row of tabs,
   each a >=44px touch target per the project's existing convention. */
.tab-bar {
  display: flex;
  gap: var(--space-2);
  padding: 0 var(--space-6);
  overflow-x: auto;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.tab-button {
  flex: 0 0 auto;
  min-height: 44px;
  padding: var(--space-3) var(--space-4);
  border: none;
  border-bottom: 3px solid transparent;
  background: transparent;
  color: var(--color-text-muted);
  font-family: var(--font-sans);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  white-space: nowrap;
}

.tab-button:hover {
  color: var(--color-text-heading);
}

.tab-button[aria-selected="true"] {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}

.tab-panel[hidden] {
  display: none;
}

@media (min-width: 768px) {
  .tab-bar {
    overflow-x: visible;
  }
}

/* Pipeline Health tab — overall badge + one row per sub-light check
   (FEATURE-012, task 12.11). Colors reference the --color-status-* tokens
   declared in :root/[data-theme="dark"] above so both palettes stay in
   sync automatically. */
.pipeline-health-overall {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  font-weight: var(--font-weight-semibold);
  margin-bottom: var(--space-5);
}

.pipeline-health-overall[data-status="green"] {
  background: var(--color-status-green-bg);
  color: var(--color-status-green);
}

.pipeline-health-overall[data-status="yellow"] {
  background: var(--color-status-yellow-bg);
  color: var(--color-status-yellow);
}

.pipeline-health-overall[data-status="red"] {
  background: var(--color-status-red-bg);
  color: var(--color-status-red);
}

.pipeline-health-sublights {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.pipeline-health-sublight {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
}

.pipeline-health-sublight-dot {
  flex: 0 0 auto;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
}

.pipeline-health-sublight[data-status="green"] .pipeline-health-sublight-dot {
  background: var(--color-status-green);
}

.pipeline-health-sublight[data-status="yellow"] .pipeline-health-sublight-dot {
  background: var(--color-status-yellow);
}

.pipeline-health-sublight[data-status="red"] .pipeline-health-sublight-dot {
  background: var(--color-status-red);
}

.pipeline-health-sublight-label {
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.pipeline-health-sublight-summary {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

.pipeline-health-unavailable {
  color: var(--color-text-muted);
}

.pipeline-health-unavailable[hidden] {
  display: none;
}

/* Pipeline Health tab — Medallion diagram, detail chart sections, and
   threshold captions (FEATURE-013, task 13.13). Uses the same
   --color-status-*/--color-surface/--color-border tokens as the sublight
   rows above so light/dark themes stay in sync automatically; the diagram
   is an injected inline SVG (renderDiagramSvg() in
   src/pipeline_health_diagram.js) that itself reads currentColor/status
   tokens are not applied inline, so we scope fills via nested selectors on
   the well-known node/edge classes the SVG renderer emits. */
.pipeline-health-diagram {
  margin: var(--space-5) 0;
  overflow-x: auto;
}

.pipeline-health-diagram svg {
  display: block;
  max-width: 100%;
  height: auto;
}

/* renderDiagramSvg() (src/pipeline_health_diagram.js, task 13.11) already
   colors each node's <rect> inline from a fixed green/yellow/red/grey
   palette chosen to read clearly on both the light and dark --color-surface
   backgrounds, so only the node/edge label text needs a CSS color here —
   white reads clearly on all 4 saturated fill colors, in both themes. */
.pipeline-health-diagram svg g text {
  fill: #ffffff;
  font-family: var(--font-sans);
}

.pipeline-health-diagram svg line {
  stroke: var(--color-text-muted);
}

.pipeline-health-detail {
  margin-top: var(--space-6);
}

.pipeline-health-detail h3 {
  color: var(--color-text-heading);
  font-size: var(--font-size-md, 1rem);
  margin-bottom: var(--space-2);
}

.pipeline-health-threshold {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  margin: 0 0 var(--space-3);
  /* Long localized captions (e.g. German compound words, Arabic RTL text)
     must wrap onto multiple lines rather than overflow or force a wide
     container — overflow-wrap covers unbroken long words in either
     direction. */
  overflow-wrap: break-word;
}

.pipeline-health-chart {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  min-height: 360px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
  overflow: hidden;
  width: 100%;
}

/* Common mobile widths (≤767px): match the Data Basis chart-container
   breakpoint above so Plotly's legend/axis-label automargin has enough
   room without the chart overflowing the viewport horizontally. */
@media (max-width: 767px) {
  .pipeline-health-chart {
    min-height: 420px;
  }
}

/* Data Basis tab — search-config definition list + intro/map copy. */
.data-basis-intro,
.data-basis-map-description {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  margin-bottom: var(--space-4);
}

.data-basis-search-config {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-bottom: var(--space-5);
}

.data-basis-search-config h2 {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
  margin-bottom: var(--space-3);
}

.data-basis-search-config dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--space-2) var(--space-4);
}

.data-basis-search-config dt {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

.data-basis-search-config dd {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
}
