/* Hidro_cam · Recepción — Castro Design System v2.0
   Consumes only the semantic --color-* / --space-* / --radius-* tokens from
   tokens.css, so both themes and any future token change come for free.

   Two decisions worth stating, because both look like mistakes otherwise:

   1. Brand red is never a data series or a state here. CDS §7.8 reserves red
      fills for the primary action and deep red for error, and this dashboard's
      whole job is to distinguish "reading is wrong" from "reading is fine" — so
      red stays exclusively on error, and the value series takes cian, which
      §7.6 defines as the colour of data.
   2. Every state carries an icon and a word (§7.8, §8.3). Colour is never the
      only difference, which matters most for the green/amber pair.
*/

*, *::before, *::after { box-sizing: border-box }

/* El atributo hidden viene de la hoja del navegador y pierde contra cualquier
   regla de autor con display; sin esto, un botón con .btn (inline-flex) sigue
   visible aunque el rol no deba verlo. */
[hidden] { display: none !important }

body {
  margin: 0;
  font: var(--text-small);
  background: var(--color-bg-base);
  color: var(--color-text-primary);
}

.grow { flex: 1 }

/* ---------------------------------------------------------------- top bar */
/* CDS §17.2: 56 px, surface, hairline bottom border. */
.topbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  height: 56px;
  padding: 0 var(--space-5);
  background: var(--color-surface);
  border-bottom: var(--border-hairline) solid var(--color-border-subtle);
  position: sticky;
  top: 0;
  z-index: 10;
}

/* 28 px clears the 24 px digital minimum of §9.3 with room to spare. */
.brand { height: 28px; width: auto; display: block }
.topbar-sep {
  width: 1px;
  height: 24px;
  background: var(--color-border-subtle);
}
.product { font: var(--text-ui); color: var(--color-text-primary) }
.product-sub { color: var(--color-text-muted) }

.pill {
  font: var(--text-label);
  letter-spacing: var(--tracking-label);
  padding: var(--space-1) var(--space-3);
  border: var(--border-hairline) solid var(--color-border-subtle);
  border-radius: var(--radius-full);
  color: var(--color-text-muted);
  white-space: nowrap;
}
.pill.is-ok   { color: var(--color-success-text); border-color: currentColor }
.pill.is-bad  { color: var(--color-error-text);   border-color: currentColor }

/* ---------------------------------------------------------------- layout */
/* Three zones: a fixed navigator, the work surface, and the conditions panel.
   The navigator and the panel are sticky rather than scrolling with the page,
   so moving between columns never means scrolling back up to the tree. */
.workspace {
  display: grid;
  grid-template-columns: 236px minmax(0, 1fr) 360px;
  align-items: start;
  max-width: var(--container-max);
  margin: 0 auto;
}
.workspace.cond-collapsed { grid-template-columns: 236px minmax(0, 1fr) 46px }
/* Resumen de campaña: no hay columna abierta, luego no hay condiciones que
   mostrar, luego esa tercera pista no debe reservar ancho. */
.workspace.no-cond, .workspace.no-cond.cond-collapsed {
  grid-template-columns: 236px minmax(0, 1fr);
}

main {
  min-width: 0;
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

/* ------------------------------------------------------------- navigator */
.nav {
  position: sticky;
  top: 0;
  max-height: 100vh;
  overflow-y: auto;
  padding: var(--space-6) var(--space-4) var(--space-6) var(--space-6);
  border-right: var(--border-hairline) solid var(--color-border-subtle);
}
.nav-head { margin-bottom: var(--space-4) }

.nav-campaign + .nav-campaign { margin-top: var(--space-5) }
.nav-campaign > .nav-campaign-btn {
  font: var(--text-ui);
  font-weight: 500;
  margin: 0 0 var(--space-1);
  line-height: 1.3;
  display: block;
  width: 100%;
  text-align: left;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--color-text-primary);
  cursor: pointer;
}
.nav-campaign > .nav-campaign-btn:hover { text-decoration: underline }
.nav-campaign > .nav-campaign-btn[aria-current="true"] { color: var(--color-data) }
.nav-campaign > .nav-plant {
  font: var(--text-label);
  color: var(--color-text-muted);
  margin: 0 0 var(--space-3);
}
.nav-cols { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px }
.nav-col {
  width: 100%;
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  text-align: left;
  cursor: pointer;
  background: transparent;
  border: 0;
  border-left: 2px solid transparent;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  color: var(--color-text-secondary);
  font: var(--text-small);
}
.nav-col:hover { background: var(--color-bg-subtle); color: var(--color-text-primary) }
.nav-col[aria-current="true"] {
  border-left-color: var(--color-data);
  background: var(--color-bg-subtle);
  color: var(--color-text-primary);
  font-weight: 500;
}
.nav-col .nav-val {
  margin-left: auto;
  font: var(--text-label);
  font-variant-numeric: tabular-nums;
  color: var(--color-data);
}
.nav-col .nav-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--color-text-muted); flex: none;
  align-self: center;
}
.nav-col.is-running .nav-dot { background: var(--color-success-text) }

/* ------------------------------------------------------- conditions panel */
.cond {
  position: sticky;
  top: 0;
  max-height: 100vh;
  display: flex;
  flex-direction: column;
  border-left: var(--border-hairline) solid var(--color-border-subtle);
  background: var(--color-bg-base);
}
.cond-head {
  padding: var(--space-4) var(--space-4) var(--space-3);
  border-bottom: var(--border-hairline) solid var(--color-border-subtle);
}
.cond-toggle {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; padding: 0; cursor: pointer;
  background: transparent; border: 0;
  color: var(--color-text-secondary);
  font: var(--text-ui);
}
.cond-toggle:hover { color: var(--color-text-primary) }
.chev {
  width: 0; height: 0; flex: none;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 6px solid currentColor;
  transform: rotate(180deg);
  transition: transform 120ms ease;
}
.cond-body { overflow-y: auto; padding: 0 var(--space-4) var(--space-6) }
.cond-spine { display: none }

.workspace.cond-collapsed .cond-body { display: none }
.workspace.cond-collapsed .cond-title { display: none }
.workspace.cond-collapsed .chev { transform: rotate(0deg) }
.workspace.cond-collapsed .cond-head { padding: var(--space-4) 0; display: flex; justify-content: center }
.workspace.cond-collapsed .cond-toggle { width: auto }
/* Collapsed, the panel keeps a vertical title so the rail still says what it is */
.workspace.cond-collapsed .cond-spine {
  display: block;
  writing-mode: vertical-rl;
  margin: var(--space-4) auto 0;
  font: var(--text-label);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.cond-group + .cond-group { margin-top: var(--space-5) }
.cond-group > h4 {
  font: var(--text-label);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--color-brand-text);
  margin: 0 0 var(--space-2);
  padding-top: var(--space-4);
}
.cond-kv { margin: 0 }
.cond-kv > div {
  display: flex; align-items: baseline; gap: var(--space-2);
  padding: 6px 0;
  border-bottom: var(--border-hairline) solid var(--color-border-subtle);
}
.cond-kv > div:last-child { border-bottom: 0 }
.cond-kv dt { flex: 1; font: var(--text-small); color: var(--color-text-secondary) }
.cond-kv .u { font: var(--text-label); color: var(--color-text-muted); white-space: nowrap }
.cond-kv dd {
  margin: 0; font: var(--text-data); font-weight: 500;
  font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap;
}

/* ------------------------------------------------------------------ fotos */
.dlg-shot { max-width: min(96vw, 1180px); width: 100%; padding: 0 }
.dlg-shot::backdrop { background: rgb(20 23 21 / .68) }
.shot-head {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: var(--border-hairline) solid var(--color-border-subtle);
}
.shot-head h3 { margin: 0; font: var(--text-h3) }
.shot-body { padding: var(--space-4); max-height: 78vh; overflow: auto }
/* La foto del panel llega a 1600 px de ancho; encogerla para que quepa es lo
   contrario de lo que hace falta, así que se permite ampliar y desplazar. */
.shot-body img { display: block; max-width: 100%; height: auto; border-radius: var(--radius-sm) }

.device .btn-shot { padding: 4px 10px; font: var(--text-label) }

/* --------------------------------------------------------- column surface */
.col-card { padding: 0; overflow: hidden }

.infostrip {
  display: flex; flex-wrap: wrap;
  gap: var(--space-4) var(--space-7);
  padding: var(--space-4) var(--space-5);
  background: var(--color-bg-subtle);
  border-bottom: var(--border-hairline) solid var(--color-border-subtle);
}
.infostrip > div { display: flex; flex-direction: column; gap: 2px }
.infostrip b { font: var(--text-data); font-weight: 500 }

.col-hero {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-5);
  align-items: center;
  padding: var(--space-5);
}
.readout-panel {
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-sm);
  background: var(--color-bg-alternate);
  border: var(--border-hairline) solid var(--color-border-subtle);
  min-width: 180px;
}
.readout-value {
  display: flex; align-items: baseline; gap: 5px; margin-top: 4px;
  color: var(--color-data);
}
.readout-value b { font-family: var(--font-mono); font-size: 46px; font-weight: 700; line-height: 1;
  font-variant-numeric: tabular-nums }
.readout-value span { font: var(--text-data); color: var(--color-text-muted) }
.readout-stamp { margin-top: var(--space-3); font: var(--text-label); color: var(--color-text-muted) }

.col-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); gap: var(--space-4) }
.col-facts > div { display: flex; flex-direction: column; gap: 2px }
.col-facts b { font-family: var(--font-mono); font-size: 19px; font-weight: 500; font-variant-numeric: tabular-nums }

.col-chart { border-top: var(--border-hairline) solid var(--color-border-subtle); border-radius: 0 }
.col-chart figcaption { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) }
.col-chart figcaption > span:first-child { margin-right: auto }

.legend { display: flex; flex-wrap: wrap; gap: var(--space-4); padding: var(--space-2) var(--space-1) 0 }
.legend button {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  background: transparent; border: 0; padding: 2px 0;
  font: var(--text-small); color: var(--color-text-secondary);
}
.legend button[aria-pressed="false"] { opacity: .45; text-decoration: line-through }
.legend .sw { width: 14px; height: 3px; border-radius: 2px; flex: none }
.legend .sw.dash { height: 0; border-top: 2px dashed var(--chart-neutral) }
.legend .sw.band { height: 10px; border-radius: 3px; background: var(--color-data-fill);
  border: 1px solid var(--color-data) }

.plan { padding: var(--space-4) var(--space-5) var(--space-5);
  border-top: var(--border-hairline) solid var(--color-border-subtle) }
.plan > h4 { font: var(--text-label); letter-spacing: .08em; text-transform: uppercase;
  color: var(--color-text-muted); margin: 0 0 var(--space-3) }
.stages { display: grid; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
  gap: var(--space-2); list-style: none; margin: 0; padding: 0 }
.stage {
  padding: var(--space-3); border-radius: var(--radius-sm);
  border: var(--border-hairline) solid var(--color-border-subtle);
  background: var(--color-bg-subtle);
}
.stage.is-done { border-color: var(--color-data-fill) }
.stage.is-now { border-color: var(--color-data); border-width: var(--border-strong) }
.stage .d { font: var(--text-label); color: var(--color-text-muted) }
.stage b { display: block; margin-top: 3px; font-family: var(--font-mono); font-size: 18px;
  font-weight: 700; font-variant-numeric: tabular-nums }
.stage .t { display: block; margin-top: 4px; font: var(--text-label);
  letter-spacing: .06em; text-transform: uppercase; color: var(--color-text-muted) }
.stage.is-now .t { color: var(--color-data) }

@media (max-width: 1240px) {
  .workspace, .workspace.cond-collapsed { grid-template-columns: minmax(0, 1fr) }
  .nav, .cond { position: static; max-height: none; border: 0 }
  .nav { border-bottom: var(--border-hairline) solid var(--color-border-subtle) }
  .cond { border-top: var(--border-hairline) solid var(--color-border-subtle) }
  .workspace.cond-collapsed .cond-spine { display: none }
}
@media (max-width: 640px) {
  main { padding: var(--space-4) }
  .col-hero { grid-template-columns: minmax(0, 1fr) }
}
section { margin: 0 }

h2.label {
  margin: 0 0 var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: var(--border-hairline) solid var(--color-border-subtle);
}
h2.label span, #panelCount { color: var(--color-text-muted) }

.nota, .convenciones {
  margin: var(--space-3) 0 0;
  font: var(--text-small);
  color: var(--color-text-muted);
  max-width: var(--measure-max);
}
.convenciones { max-width: none }

.empty {
  margin: 0;
  padding: var(--space-6);
  border: var(--border-hairline) dashed var(--color-border-subtle);
  border-radius: var(--radius-md);
  color: var(--color-text-muted);
  text-align: center;
}
.empty b { color: var(--color-text-primary); display: block; margin-bottom: var(--space-1) }

/* ---------------------------------------------------------------- controls */
.controls {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}
.controls label { font: var(--text-ui); color: var(--color-text-secondary) }

select {
  height: 32px;
  padding: 0 var(--space-3);
  font: var(--text-ui);
  color: var(--color-text-primary);
  background: var(--color-bg-base);
  border: var(--border-hairline) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
}

/* CDS §18.1. Only one primary (red fill) action per view — the Excel export. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: 32px;
  padding: 0 var(--space-3);
  font: var(--text-ui);
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
  border: var(--border-hairline) solid transparent;
  transition: background var(--duration-fast) var(--easing-standard);
}
.btn-primary {
  background: var(--color-brand);
  color: var(--color-on-brand);
  border: none;
  font-weight: 600;
}
.btn-primary:hover { background: var(--color-brand-hover) }
.btn-secondary {
  background: transparent;
  color: var(--color-text-primary);
  border-color: var(--color-border-strong);
}
.btn-secondary:hover { background: var(--color-bg-subtle) }
.btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed }

.segmented { display: flex }
.segmented button {
  height: 32px;
  padding: 0 var(--space-3);
  font: var(--text-ui);
  color: var(--color-text-secondary);
  background: transparent;
  border: var(--border-hairline) solid var(--color-border-strong);
  border-right-width: 0;
  cursor: pointer;
}
.segmented button:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm) }
.segmented button:last-child {
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  border-right-width: var(--border-hairline);
}
/* Active is never colour alone: filled surface plus a 2 px brand underline. */
.segmented button.on {
  background: var(--color-bg-subtle);
  color: var(--color-text-primary);
  box-shadow: inset 0 -2px 0 var(--color-brand-text);
}

/* ---------------------------------------------------------------- cards */
.card {
  background: var(--color-surface);
  border: var(--border-hairline) solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  box-shadow: none;
}

/* ---------------------------------------------------------------- devices */
.devices { display: flex; flex-direction: column; gap: var(--space-2) }

.device {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  border: var(--border-hairline) solid var(--color-border-subtle);
  border-left: var(--border-strong) solid var(--color-success-text);
  border-radius: var(--radius-md);
}
.device.is-stale { border-left-color: var(--color-error-text) }
.device .id { font: var(--text-ui); font-weight: 600 }
.device .fw { font: var(--text-label); color: var(--color-text-muted) }
.device .banner { font: var(--text-ui); color: var(--color-error-text) }

/* ---------------------------------------------------------------- tiles */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
  gap: var(--space-3);
}

.tile {
  background: var(--color-surface);
  border: var(--border-hairline) solid var(--color-border-subtle);
  border-left: var(--border-strong) solid var(--color-border-strong);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  display: block;
  width: 100%;
}
.tile:hover { background: var(--color-bg-subtle) }

.tilehead { display: flex; align-items: flex-start; gap: var(--space-2) }
.tilehead .names { min-width: 0; flex: 1 }

/* Both names are always on the tile. The operator's name is what you read; the
   device's label is what identifies the calibrated ROI when one misreads. */
.tile .name {
  font: var(--text-ui);
  font-weight: 600;
  color: var(--color-text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tile .raw {
  font: var(--text-label);
  letter-spacing: var(--tracking-label);
  color: var(--color-text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rename {
  flex: none;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  padding: 0;
  background: transparent;
  border: var(--border-hairline) solid transparent;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  cursor: pointer;
}
.rename svg { width: 16px; height: 16px }
.rename:hover { color: var(--color-text-primary); border-color: var(--color-border-strong) }

/* §19.5: a number that has to be compared is mono with tabular figures. */
.tile .val {
  font-family: var(--font-mono);
  font-size: 30px;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
  margin: var(--space-1) 0;
}

.tile .state {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font: var(--text-label);
  letter-spacing: var(--tracking-label);
}
.tile .state svg { width: 14px; height: 14px; flex: none }
.tile .why, .tile .age {
  font: var(--text-small);
  color: var(--color-text-muted);
  margin-top: var(--space-1);
}
.tile .why { color: var(--color-text-secondary) }

/* State: border + icon + label. Never a fill — CDS §7.8. */
.tile.is-ok    { border-left-color: var(--color-success-text) }
.tile.is-ok    .state { color: var(--color-success-text) }
.tile.is-warn  { border-left-color: var(--color-warning-text) }
.tile.is-warn  .state { color: var(--color-warning-text) }
.tile.is-error { border-left-color: var(--color-error-text) }
.tile.is-error .state, .tile.is-error .val { color: var(--color-error-text) }
.tile.is-stale {
  border-style: dashed;
  border-left-style: solid;
  border-left-color: var(--color-text-muted);
}
.tile.is-stale .state, .tile.is-stale .val { color: var(--color-text-muted) }

/* A whole device gone quiet dims its displays, so a red tile always means
   "the device is alive and this one display failed". */
.tile.device-down { opacity: .5 }

.meter {
  height: 3px;
  margin-top: var(--space-3);
  background: var(--color-bg-alternate);
  border-radius: var(--radius-full);
  overflow: hidden;
}
.meter i { display: block; height: 100%; background: var(--color-text-muted) }
.tile.is-ok    .meter i { background: var(--color-success-text) }
.tile.is-warn  .meter i { background: var(--color-warning-text) }
.tile.is-error .meter i { background: var(--color-error-text) }

.spark { display: block; width: 100%; height: 28px; margin-top: var(--space-2) }
.spark path { fill: none; stroke: var(--chart-5); stroke-width: 1.5 }

/* ---------------------------------------------------------------- chart */
.chart-card { margin: 0; padding: var(--space-4) }
.chart-card figcaption {
  font: var(--text-ui);
  color: var(--color-text-primary);
  margin-bottom: var(--space-3);
}
.chartbox { position: relative }
#chart { width: 100%; height: 348px; display: block; touch-action: none }

.grid      { stroke: var(--chart-grid); stroke-width: 1 }
.axis      { fill: var(--color-text-muted); font: var(--text-label) }
.axisline  { stroke: var(--chart-grid); stroke-width: 1 }
.plotlabel { fill: var(--color-text-muted); font: var(--text-label) }

/* Cian is the colour of data (§7.6). Margin rides in neutral underneath, so
   the only saturated colour left on the chart means "error". */
.series        { fill: none; stroke: var(--color-data); stroke-width: 2;
                 stroke-linejoin: round; stroke-linecap: round }
.series.margin { stroke: var(--chart-5) }
.serieslabel   { font: var(--text-label); letter-spacing: var(--tracking-label) }
.serieslabel.value  { fill: var(--color-data) }
.serieslabel.margin { fill: var(--chart-5) }

/* §19.4: a specification limit is a dashed muted line with its value on it, and
   the out-of-spec zone is a warning fill — never a red one. */
.threshold { stroke: var(--color-text-muted); stroke-width: 1; stroke-dasharray: 4 4 }
.warnband  { fill: var(--color-warning-bg) }

.dot       { fill: var(--color-data) }
.rug       { stroke: var(--color-error-text); stroke-width: 2 }
.crosshair { stroke: var(--color-text-muted); stroke-width: 1; stroke-dasharray: 3 3 }

.readout {
  position: absolute;
  pointer-events: none;
  background: var(--color-surface-raised);
  border: var(--border-hairline) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  font: var(--text-data);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--color-text-primary);
}
.readout b { font-size: 16px }
.readout .err { color: var(--color-error-text) }

/* ---------------------------------------------------------------- dialog */
dialog {
  padding: var(--space-5);
  min-width: min(420px, 92vw);
  color: var(--color-text-primary);
}
dialog::backdrop { background: rgba(20, 23, 21, .6) }
dialog h3 { margin: 0 0 var(--space-3); font: var(--text-h3) }
dialog .ident {
  margin: 0 0 var(--space-4);
  font: var(--text-small);
  color: var(--color-text-muted);
}
dialog .ident b { font-family: var(--font-mono); color: var(--color-text-secondary) }

/* CDS §18.3: label always visible, help text under the field. */
dialog label {
  display: block;
  font: var(--text-ui);
  margin-bottom: var(--space-1);
}
dialog input {
  width: 100%;
  height: 40px;
  padding: 0 var(--space-3);
  font: var(--text-body);
  color: var(--color-text-primary);
  background: var(--color-bg-base);
  border: var(--border-hairline) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
}
dialog .help {
  margin: var(--space-1) 0 var(--space-4);
  font: var(--text-small);
  color: var(--color-text-muted);
}
.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-5);
}

/* Lo destructivo se va al otro extremo, lejos del par Cancelar/Guardar: es la
   distancia la que evita el clic por inercia, no un color. */
.dialog-actions .btn-danger { margin-right: auto }

/* Un display retirado reusa la fila de equipo, sin el color de estado a la
   izquierda: no está fallando -- ya no está. Pintarlo de rojo lo metería en la
   misma lectura que "Equipo sin reportar", que es justo lo contrario. */
.device.is-retired {
  border-left-color: var(--color-border-subtle);
  background: var(--color-bg-subtle);
}
.device.is-retired .id { color: var(--color-text-secondary) }

@media (max-width: 700px) {
  main { padding: var(--space-4) }
  .topbar { padding: 0 var(--space-4) }
}

/* ---------------------------------------------------------------- acceso */
.login-body { display: grid; place-items: center; min-height: 100vh }
.login {
  width: min(420px, 92vw);
  display: flex; flex-direction: column; align-items: center;
  padding: var(--space-6) 0;
}
.login-brand { height: 44px; width: auto; margin-bottom: var(--space-6) }
.login-title { font: var(--text-h2); letter-spacing: var(--tracking-h2); margin: 0 }
.login-sub { margin: var(--space-1) 0 var(--space-6); color: var(--color-text-muted) }
.login-card { width: 100%; padding: var(--space-5) }
.login-card label { display: block; font: var(--text-ui); margin-bottom: var(--space-1) }
.login-card input {
  width: 100%; height: 40px; padding: 0 var(--space-3);
  margin-bottom: var(--space-4);
  font: var(--text-body); color: var(--color-text-primary);
  background: var(--color-bg-base);
  border: var(--border-hairline) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
}
.login-submit { width: 100%; height: 40px }
/* Error: borde, icono y texto — nunca un relleno rojo (CDS §7.8). */
.login-error {
  margin: 0 0 var(--space-4);
  padding: var(--space-2) var(--space-3);
  border: var(--border-hairline) solid var(--color-error-text);
  border-radius: var(--radius-sm);
  color: var(--color-error-text);
  font: var(--text-small);
}
.login-error::before { content: '✕  ' }
.login-foot { margin-top: var(--space-5); color: var(--color-text-muted); font: var(--text-small) }

/* ------------------------------------------------------------- identidad */
.whoami { display: flex; align-items: center; gap: var(--space-2) }
.whoami .who-name { font: var(--text-ui) }
.whoami .who-role {
  font: var(--text-label); letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--color-text-muted);
}

/* -------------------------------------------------------- administración */
.admin-table { width: 100%; border-collapse: collapse; font: var(--text-small) }
.admin-table th {
  text-align: left; font: var(--text-label); letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--color-text-secondary);
  padding: var(--space-2) var(--space-3);
  border-bottom: var(--border-hairline) solid var(--color-border-subtle);
}
.admin-table td {
  padding: var(--space-2) var(--space-3);
  border-bottom: var(--border-hairline) solid var(--color-border-subtle);
  vertical-align: middle;
}
.admin-table tr:hover td { background: var(--color-bg-subtle) }
.admin-table .mono { font-family: var(--font-mono) }
.admin-table .actions { display: flex; gap: var(--space-2); justify-content: flex-end }
.btn-sm { height: 28px; padding: 0 var(--space-2); font: var(--text-label) }
.btn-ghost { background: transparent; border-color: transparent; color: var(--color-text-secondary) }
.btn-ghost:hover { color: var(--color-text-primary); background: var(--color-bg-subtle) }
.tag-off { color: var(--color-text-muted); text-decoration: line-through }

.nav-actions { display: flex; gap: var(--space-2); margin-top: var(--space-3) }

/* Formularios largos en diálogo: dos columnas cuando cabe */
dialog.wide { min-width: min(720px, 94vw); max-height: 92vh; overflow-y: auto }
.fgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--space-4) }
.fgrid .full { grid-column: 1 / -1 }
dialog select {
  width: 100%; height: 40px; margin-bottom: var(--space-4);
}
dialog textarea {
  width: 100%; min-height: 72px; padding: var(--space-2) var(--space-3);
  font: var(--text-body); color: var(--color-text-primary);
  background: var(--color-bg-base);
  border: var(--border-hairline) solid var(--color-border-strong);
  border-radius: var(--radius-sm); resize: vertical;
}
dialog .checks { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin-bottom: var(--space-4) }
dialog .checks label { display: flex; align-items: center; gap: var(--space-2); font: var(--text-small); margin: 0 }

/* editor de filas (plan por etapas, condiciones) */
.rows-editor { margin-bottom: var(--space-4) }
.rows-editor .row-head, .rows-editor .row {
  display: grid; gap: var(--space-2); align-items: center; margin-bottom: var(--space-1);
}
.rows-editor .row-head { font: var(--text-label); color: var(--color-text-muted); text-transform: uppercase }
.rows-editor .row input { margin: 0; height: 32px }
.rows-editor.plan .row-head, .rows-editor.plan .row { grid-template-columns: 1fr 1fr 1fr 1fr 32px }
.rows-editor.cond .row-head, .rows-editor.cond .row { grid-template-columns: 1.2fr 2fr .8fr 1.4fr 32px }
.rows-editor .del { height: 32px; width: 32px; padding: 0 }
.dialog-error { color: var(--color-error-text); font: var(--text-small); margin: 0 0 var(--space-3) }

.col-actions {
  display: flex; gap: var(--space-2); justify-content: flex-end;
  padding: var(--space-2) var(--space-5);
  border-bottom: var(--border-hairline) solid var(--color-border-subtle);
}
.admin { padding: var(--space-6) }

.admin-card { padding: var(--space-5); max-width: var(--container-max); margin: 0 auto }
.label.bare { margin: 0; border: 0; padding: 0 }
.scroll-x { overflow-x: auto }
dialog .subhead { font: var(--text-ui); margin: var(--space-2) 0 var(--space-2) }
.device-state { display: flex; align-items: center }
.device-state.is-ok { color: var(--color-success-text) }
.device-state.is-error { color: var(--color-error-text) }
.device-state svg { width: 16px; height: 16px }

/* ------------------------------------------------------------------ vistas */
/* Tres superficies, no tres pestañas decorativas: seguir campañas, vigilar
   cámaras y administrar cuentas son trabajos distintos, con públicos distintos.
   El estado de las cámaras colgaba del final de una columna, que es justo donde
   nadie lo busca cuando lo que falla es una cámara. */
.viewbar {
  display: flex;
  gap: var(--space-1);
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--space-6);
  border-bottom: var(--border-hairline) solid var(--color-border-subtle);
}
.viewbar button {
  padding: var(--space-3) var(--space-4);
  font: var(--text-ui);
  color: var(--color-text-secondary);
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  cursor: pointer;
}
.viewbar button:hover { color: var(--color-text-primary) }
.viewbar button.on {
  color: var(--color-text-primary);
  border-bottom-color: var(--color-data);
  font-weight: 500;
}

/* ------------------------------------------------- resumen de una campaña */
.camp-head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
}
.camp-head h2 { font: var(--text-h2); margin: 0 }
.camp-sub {
  font: var(--text-small);
  color: var(--color-text-muted);
  margin: var(--space-1) 0 0;
}
.camp-actions { display: flex; gap: var(--space-2); flex-wrap: wrap }

.camp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: var(--space-3);
}
.camp-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4);
  text-align: left;
  cursor: pointer;
  background: var(--color-bg-subtle);
  border: var(--border-hairline) solid var(--color-border-subtle);
  border-left: 2px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  color: var(--color-text-secondary);
  font: var(--text-small);
}
.camp-col:hover { border-color: var(--color-data); border-left-color: var(--color-data) }
.camp-col.is-running { border-left-color: var(--color-success-text) }
.camp-col b { font: var(--text-ui); font-weight: 500; color: var(--color-text-primary) }
.camp-col-state { font: var(--text-label); color: var(--color-text-muted) }
.camp-col-panel { font: var(--text-data) }
/* Sin display asociado no hay lecturas que mostrar: se dice, no se insinúa. */
.camp-col-panel.is-warn { color: var(--color-warning-text) }
.camp-col-seen { font: var(--text-label); color: var(--color-text-muted) }

.col-actions {
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
  margin-bottom: var(--space-4);
}

/* Destructivo, y con aspecto de serlo: contorno rojo, relleno sólo al pasar
   por encima, para que no compita con la acción principal de la tarjeta. */
.btn-danger {
  background: transparent;
  color: var(--color-error-text);
  border-color: currentColor;
}
.btn-danger:hover { background: var(--color-error-bg) }
