/* ============================================================
   CAMH Energy Dashboard — ERCOT-operator visual register

   Light theme matching ercot.com/gridmktinfo/dashboards: white card
   surfaces on an off-white background, ERCOT navy-blue accents,
   monospace tabular numerals for live values, fuel-coded color rules
   on the sparkline + label so the eye can scan-read across cards.

   Carroll's "indestructible language" constraint: no animation, no
   gradients, no chartjunk, no gamified colors. Failure modes (stale /
   error / offline / cache) carry text badges + non-color border
   patterns so they read in greyscale and at exhibit distance.
   ============================================================ */

:root {
  /* Palette — warm paper ground with ERCOT navy as the structural ink.
     The paper, rules and type are borrowed from the Peak Mining 4CP
     "research desk brief"; the ink stays ERCOT navy rather than
     BrightWire violet, because a consultancy's brand does not belong
     inside an artist's work. Teal is reserved for live-data signals. */
  --bg:                #faf8f4;
  --surface:           #ffffff;
  --surface-2:         #f0ede6;
  --border:            #e7e3da;
  --border-strong:     #d8d2c6;
  --text:              #23212b;
  --text-muted:        #6e6a75;
  --text-faint:        #9b96a3;
  --accent:            #003366;   /* ERCOT brand navy */
  --accent-strong:     #0066cc;
  --live:              #0e8a7b;   /* deep teal — the live-data signal */
  --live-dot:          #0e8a7b;
  --stale-fg:          #b45309;
  --stale-bg:          #fdf8ec;
  --stale-border:      #d97706;
  --error-fg:          #b91c1c;
  --error-bg:          #fdf2f0;
  --error-border:      #b91c1c;
  --renewable:         #0e8a7b;
  --fossil:            #8a7f6d;

  /* Type — editorial serif display, grotesk UI, tabular mono numerals.
     Self-hosted in fonts.css; the stacks below carry the page if a face
     ever fails to load. */
  --font-serif:        "Newsreader", Georgia, "Times New Roman", serif;
  --font-sans:         "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI",
                       Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono:         "Spline Sans Mono", "SF Mono", "Menlo", "Consolas",
                       "Roboto Mono", ui-monospace, monospace;

  /* Card shadow — barely-there paper lift */
  --card-shadow:       0 1px 2px rgba(42, 24, 70, 0.05);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body { min-height: 100vh; }

.dashboard {
  min-height: 100vh;
  padding: 2rem 2.5rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  max-width: 1600px;
  margin: 0 auto;
}

/* ─── Header ─── */

.dashboard-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  padding-bottom: 0.9rem;
  border-bottom: 2px solid var(--accent);
}

.dashboard-titleblock {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.dashboard-eyebrow {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
}

.dashboard-eyebrow::before {
  content: "";
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--live-dot);
  margin-right: 0.55rem;
  vertical-align: middle;
}

.dashboard-title {
  margin: 0;
  font-family: var(--font-serif);
  font-size: 2.1rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--text);
}

.dashboard-asof {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.15rem;
}

.dashboard-asof-label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--text-faint);
  font-family: var(--font-sans);
}

.dashboard-asof-value {
  font-family: var(--font-mono);
  font-size: 0.92rem;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* ─── Headline summary band (Total + Renewable share) ─── */

.dashboard-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11.25rem, 1fr));
  gap: 1rem;
  padding: 1rem 1.25rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  box-shadow: var(--card-shadow);
}

.summary-stat {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding-right: 1rem;
  border-right: 1px solid var(--border);
}
.summary-stat:last-child { border-right: none; }

.summary-stat-label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.summary-stat-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.7rem;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.01em;
  line-height: 1.1;
}

.summary-stat-unit {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 0.85rem;
  color: var(--text-muted);
  letter-spacing: 0.04em;
  margin-left: 0.25rem;
}

/* ─── Fuel-mix horizontal stacked bar ─── */

.fuel-mix-bar-wrap {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.fuel-mix-bar-label {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.fuel-mix-bar-label .fuel-mix-total {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  font-size: 0.78rem;
  color: var(--text-muted);
  text-transform: none;
  letter-spacing: 0;
}

.fuel-mix-bar {
  display: flex;
  width: 100%;
  height: 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  overflow: hidden;
  box-shadow: var(--card-shadow);
}

.fuel-mix-segment {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.18);
  white-space: nowrap;
  overflow: hidden;
  min-width: 0;
}
.fuel-mix-segment[data-fuel="solar"]       { background: #f7b500; color: #4a3300; text-shadow: none; }
.fuel-mix-segment[data-fuel="wind"]        { background: #00a4b8; }
.fuel-mix-segment[data-fuel="battery"]     { background: #8b5cf6; }
.fuel-mix-segment[data-fuel="natural_gas"] { background: #d97706; }
.fuel-mix-segment[data-fuel="coal"]        { background: #4b5563; }
.fuel-mix-segment[data-fuel="nuclear"]     { background: #14b8a6; }
.fuel-mix-segment[data-fuel="hydro"]       { background: #2563eb; }
.fuel-mix-segment[data-fuel="other"]       { background: #94a3b8; color: #1a2236; text-shadow: none; }

.fuel-mix-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.1rem;
  font-size: 0.72rem;
  color: var(--text-muted);
  font-family: var(--font-sans);
}
.fuel-mix-legend-item {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}
.fuel-mix-legend-swatch {
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 2px;
  display: inline-block;
}

/* ─── Houston Settlement Prices section (dual-line chart) ─── */

.price-section {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.9rem 1.25rem 1rem;
  box-shadow: var(--card-shadow);
}

.price-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
}
.price-section-eyebrow {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--accent);
}
.price-section-meta {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.72rem;
  color: var(--text-faint);
}
.price-section-empty {
  font-size: 0.85rem;
  color: var(--text-faint);
  font-style: italic;
  margin: 0.25rem 0;
}

.price-chart-wrap {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 0.5rem;
}
.price-chart {
  flex: 1;
  height: 5.625rem;
  width: 100%;
  display: block;
  overflow: visible;
}
.price-chart-axis {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.65rem;
  color: var(--text-faint);
  text-align: right;
  min-width: 4rem;
  padding: 0.05rem 0;
}

.price-line {
  fill: none;
  stroke-width: 1.4;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
}
.price-line-lz { stroke: #d97706; }   /* warm orange — load zone */
/* The two series usually sit within cents of each other and overlap exactly.
   Dashing the hub lets both read as present instead of the top line hiding
   the one beneath it. */
.price-line-hb { stroke: #2563eb; stroke-dasharray: 2 1.6; }   /* settle-blue — hub */

.price-dot { stroke: var(--surface); stroke-width: 0.4; }
.price-dot-lz { fill: #d97706; }
.price-dot-hb { fill: #2563eb; }

.price-chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.2rem;
  font-family: var(--font-sans);
  font-size: 0.78rem;
  color: var(--text-muted);
  align-items: baseline;
}
.price-legend-item {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.price-legend-item b {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  font-weight: 600;
  margin-left: 0.25rem;
}
.price-legend-swatch {
  width: 1.125rem;
  height: 3px;
  display: inline-block;
  border-radius: 1px;
}
.price-legend-lz .price-legend-swatch { background: #d97706; }
.price-legend-hb .price-legend-swatch { background: #2563eb; }
.price-legend-spread {
  margin-left: auto;
  color: var(--text-faint);
  font-size: 0.74rem;
}
.price-legend-spread b {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  margin-left: 0.25rem;
}

/* Fuel-coded color for the price modules' card sparklines. Match the
   chart line colors so the eye sees the same color on the small card
   sparkline and the big comparison chart for each zone. */
.metric-module[data-fuel="price_lz_houston"] { --fuel-color: #d97706; }
.metric-module[data-fuel="price_hb_houston"] { --fuel-color: #2563eb; }

/* ─── Module grid ─── */

.module-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16.25rem, 100%), 1fr));
  gap: 1rem;
}

.metric-module {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1.1rem 1.25rem 1rem;
  min-height: 11rem;
  display: flex;
  flex-direction: column;
  position: relative;
  box-shadow: var(--card-shadow);
}

.metric-module.hidden { display: none; }

.metric-label {
  margin: 0 0 0.5rem;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-muted);
  font-family: var(--font-sans);
}

.metric-readout {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  margin: 0.1rem 0 0.55rem;
}

.metric-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 2.6rem;
  font-weight: 600;
  line-height: 1;
  color: var(--text);
  letter-spacing: -0.02em;
}

.metric-unit {
  font-family: var(--font-sans);
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: 0.04em;
}

.metric-status {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0.4rem 0 0;
}

.metric-source-timestamp {
  margin: 0.3rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.metric-elapsed {
  color: var(--text-muted);
}

/* ─── Sparkline ─── */

.metric-spark {
  display: block;
  width: 100%;
  height: 3rem;
  margin: 0.05rem 0 0.55rem;
  overflow: visible;
}
.metric-spark .spark-line {
  fill: none;
  stroke: var(--fuel-color, var(--accent));
  stroke-width: 1.1;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
}
.metric-spark .spark-fill {
  fill: var(--fuel-color, var(--accent));
  opacity: 0.14;
}
.metric-spark .spark-dot {
  fill: var(--fuel-color, var(--accent));
}

/* Fuel-coded accent colors. Same hex codes as the fuel-mix bar so the
   eye builds one consistent color → fuel mapping across the page. */
.metric-module[data-fuel="solar"]       { --fuel-color: #f7b500; }
.metric-module[data-fuel="wind"]        { --fuel-color: #00a4b8; }
.metric-module[data-fuel="battery"]     { --fuel-color: #8b5cf6; }
.metric-module[data-fuel="natural_gas"] { --fuel-color: #d97706; }
.metric-module[data-fuel="coal"]        { --fuel-color: #4b5563; }
.metric-module[data-fuel="nuclear"]     { --fuel-color: #14b8a6; }
.metric-module[data-fuel="hydro"]       { --fuel-color: #2563eb; }
.metric-module[data-fuel="other"]       { --fuel-color: #94a3b8; }

/* The label text picks up a darker version of the fuel color so it stays
   legible on white. */
.metric-module[data-fuel] .metric-label {
  color: var(--fuel-color, var(--text-muted));
  filter: brightness(0.78);
}

/* ─── Day-context inline strip ─── */

.metric-daycontext {
  margin: 0 0 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  flex-wrap: wrap;
}
.metric-daycontext .dc-label {
  font-family: var(--font-sans);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-right: 0.15rem;
}
.metric-daycontext .dc-tag {
  color: var(--text-faint);
  margin-right: 0.15rem;
}
.metric-daycontext .dc-val {
  color: var(--text);
  margin-right: 0.4rem;
}

/* ─── Status states ─── */

.metric-module.module-ok { border-color: var(--border); }

.metric-module.module-stale {
  border-color: var(--stale-border);
  border-style: dashed;
  background: var(--stale-bg);
}
.metric-module.module-stale .metric-value { color: var(--stale-fg); }
.metric-module.module-stale::before {
  content: "[STALE]";
  position: absolute;
  top: 0.55rem;
  right: 0.65rem;
  padding: 0.12rem 0.45rem;
  background: var(--stale-fg);
  color: #fff7ed;
  font-family: var(--font-sans);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  border-radius: 2px;
}

.metric-module.module-error {
  border-color: var(--error-border);
  border-style: double;
  background: var(--error-bg);
}
.metric-module.module-error .metric-value { color: var(--error-fg); }
.metric-module.module-error::before {
  content: "[ERROR]";
  position: absolute;
  top: 0.55rem;
  right: 0.65rem;
  padding: 0.12rem 0.45rem;
  background: var(--error-fg);
  color: #fef2f2;
  font-family: var(--font-sans);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  border-radius: 2px;
}

/* ─── Whole-dashboard failure indicators ─── */

.dashboard.connection-lost::after {
  content: "CONNECTION LOST · serving last-known-good cache";
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  padding: 0.55rem 1rem;
  background: var(--error-border);
  color: #fff;
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-align: center;
  text-transform: uppercase;
  z-index: 1000;
}

.dashboard.connection-lost .metric-module.module-ok {
  border-color: var(--stale-border);
  border-style: dashed;
  background: var(--stale-bg);
}
.dashboard.connection-lost .metric-module.module-ok .metric-value { color: var(--stale-fg); }
.dashboard.connection-lost .metric-module.module-ok::before {
  content: "[OFFLINE]";
  position: absolute;
  top: 0.55rem;
  right: 0.65rem;
  padding: 0.12rem 0.45rem;
  background: var(--stale-fg);
  color: #fff7ed;
  font-family: var(--font-sans);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  border-radius: 2px;
}

.dashboard.snapshot-stale .metric-module.module-ok {
  border-color: var(--stale-border);
  border-style: dashed;
  background: var(--stale-bg);
}
.dashboard.snapshot-stale .metric-module.module-ok .metric-value { color: var(--stale-fg); }
.dashboard.snapshot-stale .metric-module.module-ok::before {
  content: "[CACHE]";
  position: absolute;
  top: 0.55rem;
  right: 0.65rem;
  padding: 0.12rem 0.45rem;
  background: var(--stale-fg);
  color: #fff7ed;
  font-family: var(--font-sans);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  border-radius: 2px;
}

/* ─── Source attribution footer ─── */

.source-attribution {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
  font-family: var(--font-sans);
  font-size: 0.74rem;
  color: var(--text-faint);
}

.source-attribution-label {
  font-weight: 700;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--accent);
}

.source-attribution-value { color: var(--text-muted); }

/* ─── Responsive ─── */

@media (max-width: 720px) {
  .dashboard { padding: 1.25rem 1rem; }
  .dashboard-header { flex-direction: column; align-items: flex-start; gap: 0.5rem; }
  .dashboard-asof { align-items: flex-start; }
  .metric-value { font-size: 2rem; }
  .summary-stat-value { font-size: 1.4rem; }
  .metric-module { min-height: 9rem; }
  .summary-stat { border-right: none; border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; }
  .summary-stat:last-child { border-bottom: none; }
}

/* ============================================================
   Building energy hero
   ============================================================ */

.icon-sprite { display: none; }

.building-hero {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  padding: 1.6rem 1.9rem 1.5rem;
  box-shadow: var(--card-shadow);
}

.building-hero.hidden { display: none; }

.hero-eyebrow {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
}

.hero-lead {
  margin: 0.55rem 0 0;
  font-family: var(--font-serif);
  font-size: 1.28rem;
  font-weight: 400;
  color: var(--text-muted);
  letter-spacing: -0.005em;
}

.hero-total {
  margin: 0.15rem 0 0;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
}

.hero-total-icon {
  width: 2.1rem;
  height: 2.1rem;
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  align-self: center;
  flex: none;
}

.hero-total-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: clamp(3rem, 7vw, 4.6rem);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text);
}

.hero-total-unit {
  font-family: var(--font-sans);
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--text-muted);
}

/* Split bar — one glance: how much of this building the wind is carrying. */
.hero-split-bar {
  display: flex;
  height: 0.85rem;
  margin: 1.15rem 0 0.9rem;
  border: 1px solid var(--border-strong);
  border-radius: 2px;
  overflow: hidden;
  background: var(--surface-2);
}

.hero-split-segment { display: block; height: 100%; }
.hero-split-renewable { background: var(--renewable); }
.hero-split-fossil { background: var(--fossil); }

.hero-parts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 2.6rem;
}

.hero-part {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.hero-part-icon {
  width: 1.35rem;
  height: 1.35rem;
  fill: none;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}

.hero-part-renewable .hero-part-icon { stroke: var(--renewable); }
.hero-part-fossil .hero-part-icon { stroke: var(--fossil); }

.hero-part-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.45rem;
  font-weight: 500;
  color: var(--text);
}

.hero-part-unit {
  font-family: var(--font-sans);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-left: -0.2rem;
}

.hero-part-label {
  font-family: var(--font-sans);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.hero-note {
  margin: 1.05rem 0 0;
  padding-top: 0.85rem;
  border-top: 1px solid var(--border);
  font-family: var(--font-sans);
  font-size: 0.86rem;
  color: var(--text-muted);
}

.hero-note-figure {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  color: var(--live);
  margin-right: 0.15rem;
}

.hero-unavailable {
  margin: 1.05rem 0 0;
  padding-top: 0.85rem;
  border-top: 1px dashed var(--stale-border);
  font-family: var(--font-sans);
  font-size: 0.86rem;
  color: var(--stale-fg);
}

/* ============================================================
   Fuel marks on the module cards
   ============================================================ */

.metric-label {
  display: flex;
  align-items: center;
  gap: 0.45rem;
}

.metric-icon {
  width: 1.05rem;
  height: 1.05rem;
  fill: none;
  stroke: var(--fuel-color, var(--accent));
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}

.metric-label-text { display: inline-block; }

/* ============================================================
   Document structure — page header, sections, boards

   Mirrors the information design of ercot.com/gridmktinfo/dashboards:
   a plain title, a short paragraph explaining what the reader is
   looking at, then named sections. The exhibit wall should read as a
   public document, not a product screen.
   ============================================================ */

.dashboard {
  padding: 2.6rem 3rem 2rem;
  gap: 2.2rem;
}

.page-header {
  border-bottom: 2px solid var(--accent);
  padding-bottom: 1.4rem;
}

.page-eyebrow {
  margin: 0 0 0.5rem;
  font-family: var(--font-sans);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
}

.page-eyebrow::before {
  content: "";
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--live-dot);
  margin-right: 0.55rem;
  vertical-align: middle;
}

.page-title {
  margin: 0 0 0.9rem;
  font-family: var(--font-serif);
  font-size: clamp(2.4rem, 4.2vw, 3.4rem);
  font-weight: 400;
  letter-spacing: -0.015em;
  line-height: 1.05;
  color: var(--text);
}

.page-intro {
  max-width: 74ch;
}

.page-intro p {
  margin: 0 0 0.5rem;
  font-family: var(--font-sans);
  font-size: 1.02rem;
  line-height: 1.6;
  color: var(--text-muted);
}

.page-note {
  font-size: 0.88rem !important;
  color: var(--text-faint) !important;
}

.page-asof {
  margin: 1rem 0 0;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.page-asof .dashboard-asof-label {
  font-family: var(--font-sans);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.page-asof .dashboard-asof-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.84rem;
  color: var(--text-muted);
}

/* ─── Sections ─── */

.board {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.section-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.3rem 1rem;
  padding-bottom: 0.55rem;
  border-bottom: 1px solid var(--border-strong);
}

.section-title {
  margin: 0;
  font-family: var(--font-serif);
  font-size: 1.6rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--text);
}

.section-sub {
  font-family: var(--font-sans);
  font-size: 0.86rem;
  color: var(--text-faint);
}

/* ─── Houston price readouts ─── */

.price-readouts {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 3rem;
  padding: 1.1rem 1.3rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  box-shadow: var(--card-shadow);
}

.price-readout {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.price-readout-icon {
  width: 1.5rem;
  height: 1.5rem;
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}

.price-readout-body {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.price-readout-label {
  font-family: var(--font-sans);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.price-readout-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.55rem;
  font-weight: 500;
  color: var(--text);
  line-height: 1.1;
}

.price-readout-unit {
  font-family: var(--font-sans);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-left: 0.15rem;
}

/* ─── Status-badge suppression ───
   Garrett asked to hide the [STALE] / [CACHE] / [OFFLINE] overlays on the
   exhibit floor. The rules stay defined above; this only suppresses them.
   Flip data-status-badges to "on" in index.html to restore.

   Trade-off, stated so it is not lost: those badges were the non-colour
   affordance that let a colourblind visitor tell a failed tile from a fresh
   one (adversarial review §5.3). With them off, the border pattern is the
   only remaining non-colour cue. */

.dashboard[data-status-badges="off"] .metric-module.module-stale::before,
.dashboard[data-status-badges="off"] .metric-module.module-error::before,
.dashboard[data-status-badges="off"].connection-lost .metric-module.module-ok::before,
.dashboard[data-status-badges="off"].snapshot-stale .metric-module.module-ok::before,
.dashboard[data-status-badges="off"].connection-lost::before,
.dashboard[data-status-badges="off"].snapshot-stale::before {
  display: none;
}

/* The module grid sits inside a section now, so it carries no top rule. */
.module-grid { margin-top: 0; }

.price-legend-swatch-dashed {
  background: repeating-linear-gradient(
    to right,
    #2563eb 0 4px,
    transparent 4px 7px
  ) !important;
}

/* ============================================================
   Renewable gauge — ERCOT Grid Conditions idiom
   ============================================================ */

.hero-layout {
  display: flex;
  align-items: center;
  gap: 2.5rem;
}

.hero-figures {
  flex: 1 1 auto;
  min-width: 0;
}

.hero-gauge {
  flex: 0 0 auto;
  width: 320px;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-left: 2.8rem;
  border-left: 1px solid var(--border);
  align-self: stretch;
  justify-content: center;
}

.hero-gauge-dial {
  width: 100%;
  height: auto;
  display: block;
}

.gauge-segment {
  fill: none;
  stroke: var(--surface-2);
  stroke-width: 17;
  stroke-linecap: butt;
}

.gauge-segment-on { stroke: var(--renewable); }

.gauge-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 44px;
  font-weight: 500;
  fill: var(--text);
}

.gauge-value-pct {
  font-family: var(--font-sans);
  font-size: 17px;
  font-weight: 600;
  fill: var(--text-muted);
}

.hero-gauge-caption {
  margin: 0.35rem 0 0;
  font-family: var(--font-sans);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-faint);
  text-align: center;
}

.hero-gauge-scale {
  display: flex;
  justify-content: space-between;
  width: 100%;
  margin: 0.45rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  color: var(--text-faint);
}

@media (max-width: 1100px) {
  .hero-layout { flex-direction: column; align-items: stretch; }
  .hero-gauge {
    width: 100%;
    padding-left: 0;
    padding-top: 1.4rem;
    border-left: none;
    border-top: 1px solid var(--border);
  }
  .hero-gauge-dial { max-width: 300px; margin: 0 auto; }
  .hero-gauge-scale { max-width: 300px; margin: 0.45rem auto 0; }
}

/* Pulse iframe embed: fill host panel */
html, body {
  min-height: 100%;
}
body {
  margin: 0;
}
main.dashboard {
  max-width: 1200px;
  margin: 0 auto;
  padding: 1.25rem 1rem 2rem;
}


/* Pulse embed: iframe has no internal scrollbar; parent sizes to content */
html, body {
  overflow-x: hidden;
  overflow-y: visible;
  height: auto;
  min-height: 0;
  background: var(--bg, #faf8f4);
}
body {
  min-height: 0;
}
main.dashboard {
  max-width: 1120px;
  margin: 0 auto;
  padding: 1.5rem 1.25rem 2.5rem;
}

/* ─── Full-bleed kiosk (LM11, 2026-10-07) ───
   The exhibit runs on large monitors (1080p and 4K). Instead of a centred
   1120px column with white side margins, the page fills the viewport and
   scales with it: the root size grows with the viewport width (16px at
   1920 wide, 32px at 3840), and every rem-based size, grid track and chart
   follows. SVG charts already stretch to their containers (viewBox, width
   100%); the fixed-pixel tracks and heights below become rem so they scale
   too. Narrow screens keep the 16px floor and the existing breakpoints. */
html { font-size: clamp(16px, 0.84vw, 36px); }
main.dashboard {
  max-width: none;
  width: 100%;
  margin: 0;
  padding: 1.5rem clamp(1.25rem, 2.5vw, 5rem) 2.5rem;
}
.hero-gauge { width: 20rem; }
@media (max-width: 1100px) {
  .hero-gauge { width: 100%; }
  .hero-gauge-dial, .hero-gauge-scale { max-width: 18.75rem; }
}
