/*
 * Brand v2 UI primitives for Watch (#73) -- the styles behind
 * templates/components/primitives.html. Every page links this file after
 * brand-v2.css, which owns every colour, size and radius used here: no hex value
 * and no new token is written in this file.
 *
 * Status is an icon, a text label and a colour together, never colour alone.
 * Unknown (--status-unknown, "?") is a different colour and icon from Critical
 * (--status-failure, "✕"): an observation gap is not a dataset outage.
 *
 * Change badge decision (#73 open question): Studio has no informational status
 * token, and none is invented here. A Change reuses the neutral surface tokens
 * (--muted, --border, --muted-foreground) with the "ⓘ" glyph, so it can never be
 * mistaken for a health state. A breaking change shows up through the Incident it
 * opens, not through the Change's own colour.
 */

/* ---- HealthSummary: a headline, a decorative ratio bar, then counts. ---- */

.health-headline {
  margin: 0 0 8px;
  font-size: var(--text-section-title);
  line-height: var(--text-section-title--line-height);
  font-weight: var(--text-section-title--font-weight);
}

/* Decorative only (aria-hidden): `.summary-counts` below says the same thing in
   text, so the bar's colour is never the only way to read the proportions. */
.status-ratio-bar {
  display: flex;
  width: 100%;
  height: 8px;
  margin: 0 0 12px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--muted);
}

.status-ratio-segment {
  height: 100%;
}

.status-ratio-segment--healthy {
  background: var(--status-success-solid);
}

.status-ratio-segment--degraded {
  background: var(--status-warning-solid);
}

.status-ratio-segment--critical {
  background: var(--status-failure-solid);
}

.status-ratio-segment--unknown {
  background: var(--status-unknown-solid);
}

.summary-counts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.count {
  display: flex;
  align-items: baseline;
  gap: 4px;
  padding: 4px 10px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--card);
  font-size: var(--text-table);
  line-height: var(--text-table--line-height);
}

.count-value {
  font-weight: 700;
}

.count-healthy .count-icon,
.count-healthy .count-value {
  color: var(--status-success);
}

.count-degraded .count-icon,
.count-degraded .count-value {
  color: var(--status-warning);
}

.count-critical .count-icon,
.count-critical .count-value {
  color: var(--status-failure);
}

.count-unknown .count-icon,
.count-unknown .count-value {
  color: var(--status-unknown);
}

/* ---- Dataset rows: simple when Healthy, detailed only with an issue. ---- */

.dataset-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--border);
}

.dataset-row {
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
  transition: background-color 0.15s ease;
}

.dataset-row:hover {
  background: var(--muted);
}

.dataset-main {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
}

.dataset-name {
  font-weight: 600;
}

.dataset-provider {
  color: var(--muted-foreground);
  font-size: var(--text-table);
  line-height: var(--text-table--line-height);
}

.dataset-status-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
}

.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: var(--text-table);
  line-height: var(--text-table--line-height);
  font-weight: 600;
  border: 1px solid transparent;
}

.status-badge.status-healthy {
  color: var(--status-success);
  background: var(--status-success-subtle);
  border-color: var(--status-success-border);
}

.status-badge.status-degraded {
  color: var(--status-warning);
  background: var(--status-warning-subtle);
  border-color: var(--status-warning-border);
}

.status-badge.status-critical {
  color: var(--status-failure);
  background: var(--status-failure-subtle);
  border-color: var(--status-failure-border);
}

.status-badge.status-unknown {
  color: var(--status-unknown);
  background: var(--status-unknown-subtle);
  border-color: var(--status-unknown-border);
}

.timestamp {
  color: var(--muted-foreground);
  font-size: var(--text-table);
  line-height: var(--text-table--line-height);
}

.dataset-issue {
  margin: 4px 0 0;
  font-size: var(--text-table);
  line-height: var(--text-table--line-height);
}

.dataset-row.status-degraded .dataset-issue {
  color: var(--status-warning);
}

.dataset-row.status-critical .dataset-issue {
  color: var(--status-failure);
}

.dataset-row.status-unknown .dataset-issue {
  color: var(--status-unknown);
}

/* Change is informational and never a health colour (PRD §46, §53). */
.dataset-change {
  margin: 4px 0 0;
  font-size: var(--text-table);
  line-height: var(--text-table--line-height);
  color: var(--muted-foreground);
}

/* ---- ChangeBadge: informational, never a health colour. ---- */

.change-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--muted);
  color: var(--muted-foreground);
  font-size: var(--text-table);
  line-height: var(--text-table--line-height);
  font-weight: 600;
}

/* ---- Panel ---- */

.panel {
  margin: 0 0 24px;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  color: var(--card-foreground);
  box-shadow: var(--shadow-card);
}

.panel-title {
  margin: 0 0 var(--density-card-gap);
  font-size: var(--text-section-title);
  line-height: var(--text-section-title--line-height);
  font-weight: var(--text-section-title--font-weight);
}

/* ---- Metadata ---- */

.metadata {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 4px 16px;
  margin: 0;
  font-size: var(--text-body);
  line-height: var(--text-body--line-height);
}

.metadata dt {
  color: var(--muted-foreground);
}

.metadata dd {
  margin: 0;
  overflow-wrap: anywhere;
}

.technical-id {
  font-family: var(--font-mono);
  font-size: var(--text-technical);
  line-height: var(--text-technical--line-height);
}

/* ---- ContractDiff: the sign and a hidden word say what changed, not colour. ---- */

.contract-diff {
  list-style: none;
  margin: 0;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--muted);
  font-family: var(--font-mono);
  font-size: var(--text-technical);
  line-height: var(--text-technical--line-height);
  overflow-x: auto;
}

.contract-diff code {
  font-family: inherit;
}

.diff-sign {
  display: inline-block;
  width: 1.5ch;
}

/* An additive change is informational; it must not look like an outage. */
.diff-added {
  color: var(--muted-foreground);
}

.diff-removed {
  color: var(--status-failure);
}

.diff-changed {
  color: var(--status-warning);
}

/* ---- EmptyState ---- */

.empty-state {
  margin: 0;
  padding: 16px;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  color: var(--muted-foreground);
  text-align: center;
  font-size: var(--text-body);
  line-height: var(--text-body--line-height);
}

/* ---- Utilities ---- */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---- Accessibility ---- */

@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}

/* ---- No page-level horizontal scroll at 390px. ---- */

@media (max-width: 390px) {
  .dataset-name,
  .dataset-provider {
    word-break: keep-all;
    overflow-wrap: anywhere;
  }
}

/* ---- CheckStatus (#86): a check result, with its own icon and label. ---- */

.check-status {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--text-table);
  line-height: var(--text-table--line-height);
  font-weight: 600;
}

.check-pass {
  color: var(--status-success);
}

.check-warn {
  color: var(--status-warning);
}

.check-fail {
  color: var(--status-failure);
}

.check-unknown {
  color: var(--status-unknown);
}

.check-not_applicable {
  color: var(--muted-foreground);
  font-weight: 500;
}

/* ---- EvidenceChart (issue 111): expected-vs-observed mini charts, server-rendered
   inline SVG on a shared 0-300 viewBox (see presentation.py). No JS, no chart
   library, no animation -- `width: 100%` plus each SVG's own viewBox is what
   keeps every shape inside a 390px viewport. Colour is never the only signal: a
   tone always pairs with the accessible summary carried as the SVG's own
   role="img"/aria-label/title (quality/freshness/availability), or with
   ContractDiff's own sign-and-word chips (contract). ---- */

.evidence-chart {
  margin: 0 0 12px;
}

.evidence-svg {
  display: block;
  width: 100%;
  height: auto;
}

.evidence-axis {
  stroke: var(--border);
  stroke-width: 2;
}

/* The expected range or window: the same subtle fill HistoryGrid and CheckMatrix
   give a passing/healthy cell, so "expected" reads the same way everywhere. */
.evidence-band {
  fill: var(--status-success-subtle);
  stroke: var(--status-success-border);
  stroke-width: 1;
}

/* The "now" line (freshness window's snapshot time, freshness age's allowed-age
   boundary): neutral and dashed, never a status colour -- it marks a reference
   point, not a health state. */
.evidence-now {
  stroke: var(--foreground);
  stroke-width: 2;
  stroke-dasharray: 4 3;
}

.evidence-text {
  font-family: var(--font-mono);
  font-size: var(--text-meta);
  font-weight: 600;
}

.evidence-caption {
  margin: 4px 0 0;
  color: var(--muted-foreground);
  font-size: var(--text-table);
  line-height: var(--text-table--line-height);
}

/* A mark's tone borrows the health vocabulary (never Unknown mistaken for
   Critical): healthy is the observed dot landing inside the expected band,
   the rest are the incident's own severity tone (SEVERITY_TONE). */
.evidence-mark.tone-healthy,
.evidence-text.tone-healthy {
  fill: var(--status-success-solid);
  stroke: var(--status-success-solid);
}

.evidence-mark.tone-degraded,
.evidence-text.tone-degraded {
  fill: var(--status-warning-solid);
  stroke: var(--status-warning-solid);
}

.evidence-mark.tone-critical,
.evidence-text.tone-critical {
  fill: var(--status-failure-solid);
  stroke: var(--status-failure-solid);
}

.evidence-mark.tone-unknown,
.evidence-text.tone-unknown {
  fill: var(--status-unknown-solid);
  stroke: var(--status-unknown-solid);
}

/* ---- CheckMatrix (issue 110): A/F/C/Q as four small cells, reused in catalog.html. ---- */

.check-matrix {
  display: flex;
  gap: 4px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.check-cell {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 20px;
  padding: 0 2px;
  border-radius: 4px;
  border: 1px solid var(--border);
  font-size: var(--text-meta);
  line-height: 1;
  font-weight: 600;
}

.check-cell:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

/* A passing check keeps the subtle fill; only a problem takes the solid fill, so
   the eye finds trouble across the row without colour being the only signal
   (same rule as HistoryGrid). */
.check-cell-pass {
  color: var(--status-success);
  background: var(--status-success-subtle);
  border-color: var(--status-success-border);
}

.check-cell-warn {
  background: var(--status-warning-solid);
  color: var(--status-warning-subtle);
  border-color: var(--status-warning-solid);
}

.check-cell-fail {
  background: var(--status-failure-solid);
  color: var(--status-failure-subtle);
  border-color: var(--status-failure-solid);
}

.check-cell-unknown {
  background: var(--status-unknown-solid);
  color: var(--status-unknown-subtle);
  border-color: var(--status-unknown-solid);
}

/* Not applicable is not a health state: neutral surface tokens only, never a
   --status-* colour, so it cannot be mistaken for Pass or any problem state. */
.check-cell-not_applicable {
  background: var(--muted);
  color: var(--muted-foreground);
  border-color: var(--border);
  font-weight: 500;
}

/* ---- HistoryStrip (#86): one mark per day; focus or hover gives the detail. ---- */

.history-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.history-day {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 4px;
  border: 1px solid var(--border);
  font-size: var(--text-meta);
  line-height: 1;
}

.history-day:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.history-day.status-healthy {
  color: var(--status-success);
  background: var(--status-success-subtle);
  border-color: var(--status-success-border);
}

.history-day.status-degraded {
  color: var(--status-warning);
  background: var(--status-warning-subtle);
  border-color: var(--status-warning-border);
}

.history-day.status-critical {
  color: var(--status-failure);
  background: var(--status-failure-subtle);
  border-color: var(--status-failure-border);
}

.history-day.status-unknown {
  color: var(--status-unknown);
  background: var(--status-unknown-subtle);
  border-color: var(--status-unknown-border);
}

a.dataset-name {
  color: var(--foreground);
  text-decoration: none;
}

a.dataset-name:hover {
  text-decoration: underline;
}

/* ---- HistoryGrid (issue 109): the dataset x 30-day heatmap, built on HistoryDay. ---- */

.history-grid {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-table);
  line-height: var(--text-table--line-height);
}

.history-grid th,
.history-grid td {
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.history-grid thead th {
  color: var(--muted-foreground);
  font-weight: 600;
  text-align: left;
}

.history-grid tbody th[scope="row"] {
  text-align: left;
  font-weight: 600;
}

.history-grid tbody th[scope="row"] a {
  color: var(--foreground);
  text-decoration: none;
}

.history-grid tbody th[scope="row"] a:hover {
  text-decoration: underline;
}

.history-grid tbody tr:last-child th,
.history-grid tbody tr:last-child td {
  border-bottom: 0;
}

/* A HistoryDay cell keeps its colour rules but lays out as a table cell here,
   not the HistoryStrip's inline-flex box. */
.history-grid td.history-day {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}

/* Healthy keeps HistoryDay's subtle fill; only an abnormal day takes the solid
   fill, so the eye finds trouble without colour being the only signal. */
.history-grid td.history-day.status-degraded {
  background: var(--status-warning-solid);
  color: var(--status-warning-subtle);
  border-color: var(--status-warning-solid);
}

.history-grid td.history-day.status-critical {
  background: var(--status-failure-solid);
  color: var(--status-failure-subtle);
  border-color: var(--status-failure-solid);
}

.history-grid td.history-day.status-unknown {
  background: var(--status-unknown-solid);
  color: var(--status-unknown-subtle);
  border-color: var(--status-unknown-solid);
}

.history-grid-count {
  text-align: right;
  color: var(--muted-foreground);
}

/* ---- DailyCountsBar (issue 109): one stacked column per day, no library or SVG. ---- */

.daily-bar-list {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  list-style: none;
  margin: 0;
  padding: 0;
  height: 64px;
  min-width: max-content;
}

.daily-bar-day {
  display: flex;
  align-items: flex-end;
  height: 100%;
  width: 16px;
  flex: none;
}

.daily-bar-day:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.daily-bar-stack {
  display: flex;
  flex-direction: column-reverse;
  width: 100%;
}

.daily-bar-segment {
  width: 100%;
}

.daily-bar-segment--degraded {
  background: var(--status-warning-solid);
}

.daily-bar-segment--critical {
  background: var(--status-failure-solid);
}

.daily-bar-segment--unknown {
  background: var(--status-unknown-solid);
}
