/* ============================================================
   Power Demo — style.css
   AC real / reactive / apparent power, ECE 215

   Built on the design system's light theme: ../_shared/ece-tokens.css
   (GENERATED --ece-* variables) and ../_shared/ece-base.css (the shared
   header, cards, buttons, sliders), both loaded before this file. This file
   keeps the demo's own layout and maps its long-standing variable names
   onto the tokens, so no color literal lives here.
   ============================================================ */

/* ── Tokens (mapped onto --ece-*) ── */
:root {
  --bg: var(--ece-bg);
  --surface: var(--ece-paper);
  --surface2: var(--ece-bg);
  --surface3: var(--ece-rule);      /* the unfilled part of a slider track (app.js paints it) */
  --border: var(--ece-rule);

  --accent: var(--ece-brand);       /* the filled part of a slider track (app.js paints it) */
  --accent-light: var(--ece-brand-dk);

  --text-primary: var(--ece-ink);
  --text-secondary: var(--ece-ink-2);
  --text-muted: var(--ece-ink-3);   /* the quietest TEXT token (tokens.ts contract) */

  --green: var(--ece-ok);

  /* Series colors — the same series app.js reads from ECE_TOKENS.series, so
     a trace, its legend chip and its slider thumb always agree. */
  --c-voltage: var(--ece-series-1); /* blue      — v(t) */
  --c-current: var(--ece-series-5); /* raspberry — i(t) */
  --c-pinst:   var(--ece-series-3); /* plum      — p(t) */
  --c-preal:   var(--ece-series-4); /* teal      — P    */
  --c-sapp:    var(--ece-series-6); /* olive     — S    */
  --c-qreac:   var(--ece-series-2); /* orange    — Q    */

  --radius: var(--ece-radius-card);
  --radius-sm: var(--ece-radius-chip);
  --radius-xs: 4px;

  --font: var(--ece-font-sans);
  --mono: var(--ece-font-mono);

  --sidebar-w: 300px;
  --transition: var(--ece-dur) var(--ece-ease);
}

/* ── Reset ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 14px; }
body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text-primary);
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* The header (.app-header, .back-btn, .header-title, .header-subtitle) and
   the scrollbars come from ece-base.css unchanged. */

/* ════════════════════════════════════════════
   MAIN LAYOUT
   ════════════════════════════════════════════ */
.app-main {
  flex: 1;
  display: flex;
  overflow: hidden;
  min-height: 0;
}

/* ── Sidebar ── */
.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: var(--bg);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px 14px;
  overflow-y: auto;
}

/* ── Info cards ── */
.info-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  flex-shrink: 0;
}

.info-card-header {
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent-light);
  border-bottom: 1px solid var(--border);
  background: var(--surface2);
}

.info-body {
  padding: 11px 14px 13px;
  font-size: 12px;
  line-height: 1.55;
  color: var(--text-secondary);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.info-body sub { font-size: 9px; vertical-align: sub; }

.eq {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-primary);
  white-space: nowrap;
}

/* --text-secondary, not --text-muted: ELI the ICEman is required teaching copy
   (§4.4), so it should not be the dimmest text on the page. */
.info-note {
  color: var(--text-secondary);
  border-top: 1px solid var(--border);
  padding-top: 8px;
}

.info-note strong { color: var(--text-primary); }

.try-list {
  margin: 0;
  padding-left: 17px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.try-list li { padding-left: 2px; }

/* ── Controls ── */
.controls-section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  flex-shrink: 0;
}

.section-header {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  letter-spacing: 0.3px;
  text-transform: uppercase;
}

.section-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.source-dot { background: var(--c-voltage); }

/* Slider Groups */
.slider-group { display: flex; flex-direction: column; gap: 5px; }

.slider-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.slider-header label {
  font-size: 12px;
  color: var(--text-secondary);
  cursor: pointer;
}

.slider-header label sub { font-size: 9px; vertical-align: sub; }

.slider-val {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--accent-light);
  font-weight: 500;
  min-width: 62px;
  text-align: right;
  flex-shrink: 0;
}

/* Range sliders take the shared look from ece-base.css; three thumbs wear the
   color of the quantity they set. */
#sl-vm::-webkit-slider-thumb    { background: var(--c-voltage); }
#sl-r::-webkit-slider-thumb     { background: var(--c-current); }
#sl-theta::-webkit-slider-thumb { background: var(--c-sapp); }
#sl-vm::-moz-range-thumb        { background: var(--c-voltage); }
#sl-r::-moz-range-thumb         { background: var(--c-current); }
#sl-theta::-moz-range-thumb     { background: var(--c-sapp); }

.slider-ticks {
  display: flex;
  justify-content: space-between;
  font-size: 9.5px;
  color: var(--text-muted);
  padding: 0 1px;
}

/* Presets: secondary buttons (ece-base.css), left-aligned in a column. */
.preset-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.preset-btn {
  justify-content: flex-start;
  text-align: left;
  font-size: 11.5px;
  padding: 7px 10px;
  letter-spacing: 0.2px;
}

.reset-btn {
  width: 100%;
  font-size: 12px;
  padding: 9px 16px;
  letter-spacing: 0.3px;
}

/* ════════════════════════════════════════════
   PLOT PANEL — 2×2 grid
   ════════════════════════════════════════════ */
.plot-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 0;
}

.chart-grid {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 12px;
  padding: 14px 16px;
  overflow: hidden;
  min-height: 0;
}

.chart-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 14px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}

.chart-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: 0.2px;
  text-transform: uppercase;
  flex-shrink: 0;
}

.chart-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.dot-voltage { background: var(--c-voltage); }
.dot-pinst   { background: var(--c-pinst); }
.dot-sapp    { background: var(--c-sapp); }
.dot-preal   { background: var(--c-preal); }

.chart-sublabel {
  margin-left: auto;
  font-size: 10.5px;
  font-weight: 400;
  color: var(--text-muted);
  text-transform: none;
  letter-spacing: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chart-legend-chips {
  margin-left: auto;
  display: flex;
  gap: 5px;
  flex-shrink: 0;
}

/* P / Q / S legend chips: the series color is a swatch (a graphic, held to
   3:1), the letter is ink — orange (series-2) is too light to be text. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
  padding: 3px 6px;
  border-radius: var(--radius-xs);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
  text-transform: none;
}

.chip::before {
  content: '';
  width: 10px;
  height: 3px;
  border-radius: 2px;
  background: var(--chip-color);
}

.chip-preal { --chip-color: var(--c-preal); }
.chip-qreac { --chip-color: var(--c-qreac); }
.chip-sapp  { --chip-color: var(--c-sapp); }

/* Chart.js canvases fill their wrapper; the !important pair is the demos'
   guard against Chart.js growing the element past its card. */
.chart-wrap {
  flex: 1;
  min-height: 0;
  position: relative;
}

.chart-wrap canvas {
  width: 100% !important;
  height: 100% !important;
}

/* Raw canvases size themselves (DPR-aware) from a ResizeObserver — no
   !important here, or the JS could never set a backing-store-matched size. */
.canvas-wrap {
  flex: 1;
  min-height: 0;
  min-width: 0;
  position: relative;
  overflow: hidden;
}

.canvas-wrap canvas {
  display: block;
  max-width: 100%;
  max-height: 100%;
}

/* ── Power-factor card ── */
.pf-card { overflow: hidden; }

.pf-body {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  gap: 14px;
  overflow: hidden;
}

/* 18px taller than the 180×110 canvas: the pf numeral sits inside the dial
   above the needle hub, and the θ sub-label drops below the canvas so it
   clears the hub and the 0 / 1 tick labels. */
.gauge-wrap {
  position: relative;
  width: 180px;
  height: 128px;
  flex-shrink: 0;
}

.gauge-center-label {
  position: absolute;
  bottom: 46px;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
  line-height: 1.1;
}

#pf-value {
  font-family: var(--mono);
  font-size: 22px;
  font-weight: 600;
  color: var(--text-primary);
}

.gauge-unit {
  position: absolute;
  bottom: 1px;
  left: 50%;
  transform: translateX(-50%);
  display: block;
  font-size: 11px;
  color: var(--text-muted);
  letter-spacing: 0.5px;
  font-family: var(--mono);
  white-space: nowrap;
}

/* Seven readouts, so this is a wrapping grid rather than modulation's
   three-across flex row. Same .metric / .metric-label / .metric-val parts. */
.gauge-metrics {
  flex: 1;
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
  gap: 6px;
  align-content: center;
}

.metric {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 6px 8px;
  text-align: center;
  min-width: 0;
}

/* NOT uppercase, unlike the other demos' metric labels: these seven carry
   course notation, and §3.3 fixes V_rms / pf / θ as lowercase. text-transform
   is paint-only — it would have shown "V RMS", "PF", and a capital Θ while
   textContent still read "pf" and "θ", so no DOM assertion can catch it. */
.metric-label {
  display: block;
  font-size: 10px;
  color: var(--text-muted);
  letter-spacing: 0.5px;
  margin-bottom: 2px;
  text-transform: none;
}

.metric-label sub { font-size: 8px; vertical-align: sub; }

.metric-val {
  font-family: var(--mono);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--accent-light);
  white-space: nowrap;
}

/* ── Status pill ──
   The state's color marks the dot and the border (graphics); the words stay
   ink-2, because orange (lagging) cannot carry text on paper. */
.status-pill {
  display: flex;
  align-items: center;
  gap: 7px;
  align-self: flex-start;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 99px;
  padding: 5px 13px 5px 8px;
  font-size: 12px;
  color: var(--text-secondary);
  transition: border-color var(--transition);
  flex-shrink: 0;
}

.status-pill .status-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--surface3);
  transition: background-color var(--transition);
}

.status-pill.active-unity .status-dot { background: var(--green); }
.status-pill.active-unity { border-color: var(--green); }

.status-pill.active-lagging .status-dot { background: var(--c-qreac); }
.status-pill.active-lagging { border-color: var(--c-qreac); }

.status-pill.active-leading .status-dot { background: var(--c-voltage); }
.status-pill.active-leading { border-color: var(--c-voltage); }

/* ── Animations ── */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

.sidebar    { animation: fadeInUp 0.4s ease both; }
.plot-panel { animation: fadeInUp 0.4s 0.1s ease both; }

/* ════════════════════════════════════════════
   RESPONSIVE
   Breakpoints are new values chosen for the 2×2 grid; the structure follows
   filter-demo, the only demo with media queries.
   ════════════════════════════════════════════ */
@media (max-width: 1100px) {
  .chart-grid {
    grid-template-columns: 1fr;
    grid-template-rows: repeat(4, minmax(240px, 1fr));
    overflow-y: auto;
  }
  .pf-body { flex-wrap: wrap; }
}

@media (max-width: 800px) {
  html, body { height: auto; overflow: auto; }
  .app-main { flex-direction: column; overflow: visible; }
  .sidebar {
    width: 100%;
    border-right: none;
    border-bottom: 1px solid var(--border);
    overflow-y: visible;
  }
  .plot-panel { overflow: visible; }
  /* Fixed row heights, not 1fr: in an auto-height page the grid has no
     definite height to divide, and 1fr rows would collapse the canvases. */
  .chart-grid {
    overflow: visible;
    grid-template-rows: repeat(4, 300px);
  }
  .header-subtitle { display: none; }
}
