/* services/ui/src/ui/static/app.css
 * Shared UI shell + page surfaces for desktop and iPhone 16+.
 */

:root {
  --bg:        #f6f7f9;
  --card:      #ffffff;
  --ink:       #1a1d23;
  --muted:     #6b7280;
  --line:      #e5e7eb;
  --accent:    #2563eb;
  --import:    #e8743b;     /* power flowing FROM grid (positive) */
  --export:    #2eb67d;     /* power flowing TO grid   (negative) */
  --stale:     #9ca3af;
  --radius:    14px;
  --shadow:    0 1px 2px rgba(15, 23, 42, 0.04),
               0 4px 12px rgba(15, 23, 42, 0.04);
  --shadow-strong:
               0 18px 50px rgba(38, 56, 88, 0.08),
               0 6px 18px rgba(15, 23, 42, 0.06);
  --card-border: rgba(133, 149, 173, 0.18);
  --shell-border: rgba(110, 128, 156, 0.16);
  --shell-glow: rgba(216, 120, 74, 0.12);
  --font-ui: "Avenir Next", "Segoe UI", "Helvetica Neue", "Arial Nova", sans-serif;
  --font-display: "Iowan Old Style", "Palatino Linotype", "Book Antiqua", Georgia, serif;
  /* Resolve to 0 in browsers that don't support env(); resolve to the
   * notch/home-indicator inset on iPhone with viewport-fit=cover. */
  --safe-top:    env(safe-area-inset-top, 0px);
  --safe-right:  env(safe-area-inset-right, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left:   env(safe-area-inset-left, 0px);
}

/* iOS: kill the grey tap highlight; we have our own focus/hover styles.
 * Plus border-box everywhere so padding/border are part of declared widths
 * — otherwise main + cards would overflow tight viewports by their padding. */
*, *::before, *::after {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

/* Defensive: nothing should produce a horizontal scrollbar at the page
 * level on a phone. `overflow-x: clip` (rather than `hidden`) is the
 * modern choice — preserves position:sticky on .topbar. */
html, body {
  overflow-x: clip;
  max-width: 100vw;
  margin: 0;
  padding: 0;
  background:
    radial-gradient(circle at top left, rgba(232, 116, 59, 0.12), transparent 28rem),
    radial-gradient(circle at top right, rgba(46, 182, 125, 0.1), transparent 26rem),
    linear-gradient(180deg, #fdfdfc 0%, #f6f7f9 28%, #eef2f7 100%);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 16px;
  line-height: 1.45;
}
body {
  min-height: 100vh;
}

a, button {
  touch-action: manipulation;
}

a:focus-visible,
button:focus-visible {
  outline: 3px solid rgba(37, 99, 235, 0.28);
  outline-offset: 3px;
}

.skip-link {
  position: absolute;
  left: calc(1rem + var(--safe-left));
  top: calc(0.6rem + var(--safe-top));
  transform: translateY(-160%);
  padding: 0.7rem 0.95rem;
  border-radius: 999px;
  background: var(--ink);
  color: #fff;
  text-decoration: none;
  z-index: 50;
  transition: transform 120ms ease;
}
.skip-link:focus-visible {
  transform: translateY(0);
}

.topbar {
  padding: 0.95rem 1.25rem 0.6rem;
  padding-top:  calc(0.85rem + var(--safe-top));
  padding-left: calc(1.25rem + var(--safe-left));
  padding-right: calc(1.25rem + var(--safe-right));
  position: sticky;       /* stays put when scrolling — feels native on iOS */
  top: 0;
  z-index: 20;
  background: linear-gradient(180deg, rgba(253, 253, 252, 0.94), rgba(253, 253, 252, 0.74));
  backdrop-filter: blur(18px);
  border-bottom: 1px solid rgba(133, 149, 173, 0.12);
}
.topbar-inner {
  max-width: 1160px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 1rem 1.4rem;
}

.brand-block {
  display: grid;
  gap: 0.15rem;
  min-width: 0;
}
.brand {
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.01em;
}
.brand-note {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--muted);
}

.tabs {
  display: flex;
  gap: 0.35rem;
  min-width: 0;
  justify-content: flex-end;
  align-items: center;
  flex-wrap: wrap;
  padding: 0.35rem;
  border: 1px solid var(--shell-border);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.72);
  box-shadow: 0 10px 32px rgba(31, 45, 73, 0.06);
}
.tabs .tab {
  display: inline-block;
  padding: 0.55rem 0.95rem;     /* min 44pt touch target on mobile */
  border-radius: 999px;
  text-decoration: none;
  color: var(--muted);
  font-size: 0.92rem;
  border: 1px solid transparent;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease,
              box-shadow 120ms ease, transform 120ms ease;
  white-space: nowrap;
}
.tabs .tab:hover {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.92);
  border-color: rgba(133, 149, 173, 0.16);
}
.tabs .tab.active {
  color: var(--ink);
  background: linear-gradient(180deg, #fff6f0, #ffffff);
  border-color: rgba(232, 116, 59, 0.22);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7),
              0 4px 12px rgba(232, 116, 59, 0.12);
}

main {
  max-width: 1160px;
  margin: 0 auto;
  padding: 1.4rem 1.25rem 2rem;
  padding-left:  calc(1.25rem + var(--safe-left));
  padding-right: calc(1.25rem + var(--safe-right));
}

.bottombar {
  padding: 0 1.25rem calc(1rem + var(--safe-bottom));
  color: var(--muted);
  font-size: 0.8rem;
}
.bottombar-inner {
  max-width: 1160px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  gap: 0.85rem;
  padding: 0.95rem 1.1rem;
  border-top: 1px solid rgba(133, 149, 173, 0.12);
  align-items: center;
}
.muted { color: var(--muted); }

.page-intro {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 1rem 1.2rem;
  align-items: end;
  padding: 1.45rem 1.5rem;
  margin-bottom: 1.25rem;
  border: 1px solid var(--shell-border);
  border-radius: 22px;
  background:
    radial-gradient(circle at top right, rgba(46, 182, 125, 0.12), transparent 30%),
    linear-gradient(135deg, rgba(255, 255, 255, 0.95), rgba(249, 250, 252, 0.88));
  box-shadow: var(--shadow-strong);
}
.page-intro-copy {
  display: grid;
  gap: 0.45rem;
}
.page-kicker {
  font-size: 0.72rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-weight: 700;
}
.page-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(2rem, 4vw, 3rem);
  line-height: 0.98;
  letter-spacing: -0.02em;
}
.page-lead {
  margin: 0;
  max-width: 50rem;
  font-size: 1rem;
  color: #475467;
}
.page-intro-aside {
  display: flex;
  justify-content: flex-end;
}
.page-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.5rem 0.85rem;
  border-radius: 999px;
  border: 1px solid rgba(46, 182, 125, 0.2);
  background: rgba(255, 255, 255, 0.8);
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #176a3e;
  font-weight: 700;
}
.page-badge::before {
  content: "";
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 999px;
  background: var(--export);
  box-shadow: 0 0 0 0.24rem rgba(46, 182, 125, 0.14);
}

.page { display: grid; gap: 1.25rem; }
/* Grid items default to min-width: auto = min-content. Long unbreakable
 * captions ("all-in koop (spot + markup + heffingen)") then push cards
 * past parent width. Letting items shrink + wrapping long words keeps
 * cards within the available column. */
.page > * { min-width: 0; }
/* Apply hard wrapping only to body-text elements where one long token
 * (e.g. "all-in koop (spot + markup + heffingen)") can blow a card past
 * the column. Targeted classes only — `.muted` is too generic and would
 * break short adverbs like "geleden" mid-word. */
.page p,
.page .caption,
.page .hero-sub,
.page .pv-sub,
.page .battery-meta,
.page .advice-rationale,
.page .next-change {
  overflow-wrap: anywhere;
}

@keyframes surface-enter {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.page-intro {
  animation: surface-enter 320ms ease both;
}
.page > * {
  animation: surface-enter 420ms ease both;
}
.page > :nth-child(1) { animation-delay: 0.04s; }
.page > :nth-child(2) { animation-delay: 0.08s; }
.page > :nth-child(3) { animation-delay: 0.12s; }
.page > :nth-child(4) { animation-delay: 0.16s; }

.hero,
.tile,
.pv-total,
.meter,
.battery-hero,
.advice-card,
.combined-card,
.schedule-card,
.forecast-card,
.prices-hero,
.prices-chart-card,
.overview-card,
.price-strip,
.dess-strip {
  border: 1px solid var(--card-border);
  box-shadow: var(--shadow-strong);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    scroll-behavior: auto;
  }
  .page-intro,
  .page > * {
    animation: none;
  }
}

/* ---------------- Hero (total grid power) ---------------- */

.hero {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.75rem 1.5rem;
  text-align: center;
  border-top: 4px solid var(--line);
  transition: border-color 200ms ease;
}
.hero.dir-import { border-top-color: var(--import); }
.hero.dir-export { border-top-color: var(--export); }
.hero.dir-idle   { border-top-color: var(--line); }
.hero.dir-stale  { border-top-color: var(--stale); }

.hero-label {
  font-size: 0.85rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.hero-value {
  margin-top: 0.5rem;
  font-feature-settings: "tnum";
}
.hero-value .num {
  font-size: clamp(2.6rem, 6vw, 3.6rem);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;        /* keep "9,3 kW" / "531 W" on one line */
}
.hero-sub {
  margin-top: 0.5rem;
  color: var(--muted);
  font-size: 0.9rem;
}
.hero-sub .dot { margin: 0 0.5rem; opacity: 0.5; }

/* ---------------- Phase tiles ---------------- */

.phases {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
}
@media (max-width: 720px) {
  .phases { grid-template-columns: 1fr; }
}

/* ---------------- Totalisators ---------------- */

.totals {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
}
@media (max-width: 720px) {
  .totals { grid-template-columns: 1fr; }
}

/* ---------------- Tile primitives ---------------- */

.tile {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1rem 1.1rem;
}
.tile-title {
  font-size: 0.78rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.tile-value {
  margin-top: 0.4rem;
  font-size: 1.6rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.tile-sub {
  margin-top: 0.35rem;
  color: var(--muted);
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}

.tile.phase .row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.35rem 0;
  border-bottom: 1px dashed var(--line);
}
.tile.phase .row:last-child { border-bottom: none; }
.tile.phase .k { color: var(--muted); font-size: 0.85rem; }
.tile.phase .v {
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}

/* Direction colors for power values. */
.dir-import { color: var(--import); }
.dir-export { color: var(--export); }
.dir-idle   { color: var(--ink); }
.dir-stale  { color: var(--stale); }

/* Threshold-based colours for AC voltage / AC current.
 * V: <245 ok, 245-250 warn, ≥251 alert.
 * A: |a|<30 ok, 30-35 warn, |a|>35 alert.
 * Apply via fmt.voltageClass()/currentClass() — DC (MPPT) values must
 * NOT use these classes; their range is unrelated. */
.val-ok    { color: #176a3e; font-weight: 500; }
.val-warn  { color: #b45309; font-weight: 500; }
.val-alert { color: #b91c1c; font-weight: 600; }

/* ---------------- /pv: combined totalisator ---------------- */

.pv-total {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.4rem 1.5rem;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1.5rem;
  align-items: center;
  border-top: 4px solid var(--line);
  transition: border-color 200ms ease;
}
.pv-total.dir-import { border-top-color: var(--import); }
.pv-total.dir-export { border-top-color: var(--export); }
.pv-total.dir-idle   { border-top-color: var(--line); }
.pv-total.dir-stale  { border-top-color: var(--stale); }

.pv-total-hero {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 0.75rem 1rem;
  align-items: baseline;
}
.pv-total-hero .hero-label {
  font-size: 0.78rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  white-space: nowrap;
}
.pv-total-hero .num {
  font-size: clamp(2.2rem, 5vw, 3rem);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  white-space: nowrap;        /* keep "743 W" / "11,8 kW" on one line */
}
.pv-total-hero .hero-sub {
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

.pv-total-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, auto));
  gap: 0 1.25rem;
  text-align: right;
}
.pv-total-stats > div {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.pv-total-stats .muted {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.pv-total-stats strong {
  font-size: 1.05rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 720px) {
  .pv-total {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
  .pv-total-stats { text-align: left; }
}

/* ---------------- /pv: side-by-side meter cards ---------------- */

.meters {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}
@media (max-width: 720px) {
  .meters { grid-template-columns: 1fr; }
}

.meter {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.1rem 1.2rem;
  display: grid;
  gap: 1rem;
}

.meter-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
}
.meter-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 600;
}
.meter-sub {
  color: var(--muted);
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}

/* Compact hero variant for the side-by-side meter cards. */
.hero.compact {
  padding: 1rem 0.75rem;
  box-shadow: none;
  background: var(--bg);
  border-radius: 10px;
  border-top-width: 3px;
}
.hero.compact .hero-value .num {
  font-size: clamp(1.8rem, 4vw, 2.4rem);
}

.phases-stacked {
  display: grid;
  gap: 0.25rem;
}
.phase-row {
  display: grid;
  grid-template-columns: 2.4rem 1fr auto auto;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.4rem 0.1rem;
  border-bottom: 1px dashed var(--line);
  font-variant-numeric: tabular-nums;
}
.phase-row:last-child { border-bottom: none; }
.phase-row .k { color: var(--muted); font-size: 0.85rem; }
.phase-row .v { font-weight: 500; text-align: right; }
.phase-row .muted { font-size: 0.85rem; }

.totals-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--line);
}
.totals-row > div {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.totals-row .muted {
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.totals-row strong {
  font-size: 1.05rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ---------------- /pv: inverter sub-section ---------------- */

[x-cloak] { display: none !important; }

.inverter {
  border-top: 1px solid var(--line);
  padding-top: 0.85rem;
  display: grid;
  gap: 0.6rem;
}
.inverter.inverter-error {
  background: linear-gradient(0deg, rgba(232, 116, 59, 0.06), transparent 30%);
  border-radius: 8px;
  padding: 0.85rem 0.6rem 0.6rem;
}

.inverter-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
}
.inverter-title {
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.inverter-title code {
  background: var(--bg);
  border: 1px solid var(--line);
  padding: 0.05rem 0.4rem;
  border-radius: 4px;
  font-family: ui-monospace, "SF Mono", "Menlo", monospace;
  font-size: 0.78rem;
  color: var(--ink);
}

.status-pill {
  font-size: 0.72rem;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.status-pill.status-ok      { background: #e7f6ee; color: #176a3e; }
.status-pill.status-stale   { background: #fff5e6; color: #8a4a00; }
.status-pill.status-error   { background: #fde9e0; color: #a13a17; }
.status-pill.status-unknown { background: #eef0f4; color: var(--muted); }

.inverter-summary {
  display: flex;
  align-items: baseline;
  gap: 0.85rem;
  flex-wrap: wrap;
}
.inverter-summary .num {
  font-size: 1.4rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.inverter-summary .muted {
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

.limit-pill {
  font-size: 0.72rem;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: #fff5e6;
  color: #8a4a00;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.inverter-error-text {
  background: #fde9e0;
  border-left: 3px solid var(--import);
  color: #6e2e0f;
  padding: 0.5rem 0.6rem;
  border-radius: 4px;
  font-size: 0.82rem;
  font-family: ui-monospace, "SF Mono", "Menlo", monospace;
  word-break: break-word;
}

.inverter-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem 1rem;
}
.inverter-col h3 {
  margin: 0 0 0.25rem;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.kv-row {
  display: grid;
  grid-template-columns: 3rem 1fr auto;
  gap: 0.4rem;
  align-items: baseline;
  padding: 0.2rem 0;
  font-variant-numeric: tabular-nums;
  font-size: 0.88rem;
}
.kv-row .k { color: var(--muted); font-size: 0.82rem; }
.kv-row .v { font-weight: 500; text-align: right; }
.kv-row .muted { font-size: 0.82rem; }

@media (max-width: 720px) {
  .inverter-grid { grid-template-columns: 1fr; }
}

/* ---------------- /battery ---------------- */

.battery-hero {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.4rem 1.5rem;
  display: grid;
  gap: 0.95rem;
  border-top: 4px solid var(--line);
  transition: border-color 200ms ease;
}
.battery-hero.dir-import { border-top-color: var(--import); }
.battery-hero.dir-export { border-top-color: var(--export); }
.battery-hero.dir-idle   { border-top-color: var(--line); }
.battery-hero.dir-stale  { border-top-color: var(--stale); }

.battery-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.battery-title { margin: 0; font-size: 1.1rem; font-weight: 600; }
.battery-pills { display: flex; gap: 0.65rem; align-items: center; }
.battery-pills .muted { font-size: 0.82rem; }

.soc-display {
  display: flex;
  align-items: baseline;
  gap: 0.95rem;
  flex-wrap: wrap;
}
.soc-num {
  font-size: clamp(2.6rem, 6vw, 3.6rem);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.soc-cap {
  font-size: 0.95rem;
  font-variant-numeric: tabular-nums;
}

.soc-rail {
  position: relative;
  height: 32px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: visible;        /* ticks are allowed to poke past edges */
  margin-top: 0.25rem;
}
.soc-rail-fill {
  position: absolute;
  top: 0; left: 0; bottom: 0;
  background: linear-gradient(90deg, #4ec79a, #2eb67d);
  border-radius: 5px 0 0 5px;
  transition: width 600ms ease;
}
.soc-rail-tick {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 2px;
  transform: translateX(-1px);  /* center the 2px line on its left% anchor */
  pointer-events: auto;
}
.soc-rail-tick.min, .soc-rail-tick.max {
  background: rgba(26, 29, 35, 0.45);
}
.soc-rail-tick.target {
  background: var(--accent);
  width: 3px;
  transform: translateX(-1.5px);
  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.12);
}

.soc-axis {
  display: flex;
  justify-content: space-between;
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.battery-power {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  border-top: 1px solid var(--line);
  padding-top: 0.85rem;
  gap: 0.5rem;
}
.power-label {
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.power-value {
  font-size: 1.5rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ---------------- /battery: advice card ---------------- */

.advice-card {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.2rem 1.5rem;
  display: grid;
  gap: 0.8rem;
}
.advice-card.advice-stale {
  background: linear-gradient(0deg, rgba(156, 163, 175, 0.06), transparent 30%);
}

.advice-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
}
.advice-title { margin: 0; font-size: 1.05rem; font-weight: 600; }

.advice-action {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 0.95rem;
}
.advice-action .muted {
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.action-label {
  font-size: 1.2rem;
  font-weight: 600;
}
.target-soc {
  font-size: 0.95rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.advice-rationale {
  font-style: italic;
  color: var(--muted);
  font-size: 0.92rem;
  border-left: 2px solid var(--line);
  padding-left: 0.75rem;
}

.advice-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.85rem;
  border-top: 1px solid var(--line);
  padding-top: 0.85rem;
}
.advice-stats > div {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.advice-stats .muted {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.advice-stats strong {
  font-size: 1.05rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 720px) {
  .advice-stats { grid-template-columns: 1fr; }
}

/* ---------------- /battery: combined plan + forecast card ---------------- */

.combined-card {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.2rem 1.4rem;
  display: grid;
  gap: 0.9rem;
}
.combined-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.combined-title { margin: 0; font-size: 1.05rem; font-weight: 600; }

/* One continuous chart frame containing three stacked layers. The
 * outer frame draws the border + background; the inner layers render
 * their own content edge-to-edge with no gaps so the eye reads it as
 * a single chart with three horizontal bands. */
.combined-frame {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  display: grid;
  grid-template-rows: auto auto auto;
}
/* High specificity so these wins over the standalone .schedule-rail /
 * .day-chart / .batt-strip rules below — they're shared with the
 * non-combined views (if any) but here we want the unified frame. */
.combined-frame .combined-layer {
  border: 0;
  border-radius: 0;
  background: transparent;
  margin: 0;
}
.combined-frame .combined-layer + .combined-layer {
  border-top: 1px solid var(--line);   /* light separator only */
}

/* Combined legend: two groups (actions + energy series) — wraps on
 * mobile but keeps related pills together. */
.combined-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  border-top: 1px dashed var(--line);
  padding-top: 0.65rem;
}
.combined-legend .legend-group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.combined-legend .legend-pill { font-size: 0.7rem; padding: 0.2rem 0.65rem; }
/* Legend pills mirror the actual data colors. Backgrounds are tinted
 * versions (15-20% saturation) of each accent so the text stays
 * readable; foreground is the saturated accent itself. */
.combined-legend .act-charge-grid    { background: #dbe7fc; color: #1e40af; }
.combined-legend .act-charge-pv      { background: #dcfce7; color: #166534; }
.combined-legend .act-hold           { background: #eef0f4; color: var(--muted); }
.combined-legend .act-discharge      { background: #fee2e2; color: #991b1b; }
/* Energy series — distinct hue families from action bands above. */
.combined-legend .ser-pv             { background: #ecfccb; color: #4d7c0f; }
.combined-legend .ser-cons           { background: #ffedd5; color: #9a3412; }
.combined-legend .batt-legend-charge    { background: #cffafe; color: #155e75; }
.combined-legend .batt-legend-discharge { background: #fae8ff; color: #86198f; }

/* ---------------- /battery: DESS schedule strip ---------------- */

:root {
  /* DESS action-band palette (used by the per-15-min schedule strip).
   * Picked to be visibly distinct from the three energy-series hues
   * below — same conceptual family but different shade/saturation. */
  --act-charge-grid: #2563eb;     /* deep blue: charging from grid */
  --act-charge-pv:   #16a34a;     /* saturated green: PV-driven charge */
  --act-hold:        #94a3b8;     /* slate gray: pause */
  --act-discharge:   #dc2626;     /* red: discharging */
  --act-neutral:     #cbd5e1;

  /* Energy-series palette (hourly bars + battery flow). Different hues
   * from the action palette so the legend pills don't read as duplicates. */
  --ser-pv:          #84cc16;     /* chartreuse: PV production volume */
  --ser-cons:        #fb923c;     /* coral: consumption volume */
  --batt-charge:     #06b6d4;     /* cyan: planned battery charge */
  --batt-discharge:  #c026d3;     /* magenta: planned battery discharge */
}

.schedule-card {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.2rem 1.4rem;
  display: grid;
  gap: 0.75rem;
}
.schedule-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.schedule-title { margin: 0; font-size: 1.05rem; font-weight: 600; }

.schedule-rail {
  position: relative;
  height: 140px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
}
.schedule-soc {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
}
.schedule-soc polyline {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}
/* The soc-area is just the polyline for now; could be filled with a
 * gradient if we close the path with the bottom-right + bottom-left
 * corner. Keeping it as a line for legibility. */

/* Action color-bands at the bottom 18px of the rail. */
.schedule-bands {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 14px;
  display: flex;
  gap: 0;
}
.schedule-band {
  height: 100%;
  flex-basis: 0;
  flex-shrink: 1;
  border-radius: 2px;
}
.schedule-band.act-charge-grid { background: var(--act-charge-grid); }
.schedule-band.act-charge-pv   { background: var(--act-charge-pv); }
.schedule-band.act-hold        { background: var(--act-hold); opacity: 0.4; }
.schedule-band.act-discharge   { background: var(--act-discharge); }
.schedule-band.act-neutral     { background: var(--act-neutral); }
/* Beyond the DESS schedule horizon — band rendered as a thin neutral
 * tick so the time-axis stays visually divided into hours. */
.schedule-band.act-empty       { background: var(--line); opacity: 0.4; }

/* "Nu"-marker: thin vertical line. */
.schedule-now-line {
  position: absolute;
  top: 0; bottom: 14px;
  width: 2px;
  background: var(--ink);
  transform: translateX(-1px);
  opacity: 0.45;
}

.schedule-axis {
  position: relative;
  height: 1.1rem;
  font-size: 0.7rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.schedule-axis-cell {
  position: absolute;
  transform: translateX(-50%);
  white-space: nowrap;
}

.schedule-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  border-top: 1px dashed var(--line);
  padding-top: 0.65rem;
}
.schedule-legend .legend-pill { font-size: 0.72rem; padding: 0.2rem 0.7rem; }
.schedule-legend .act-charge-grid { background: #dbe7fc; color: #1e40af; }
.schedule-legend .act-charge-pv   { background: var(--tier-cheap-bg); color: #176a3e; }
.schedule-legend .act-hold        { background: #eef0f4; color: var(--muted); }
.schedule-legend .act-discharge   { background: var(--tier-expensive-bg); color: #a13a17; }

/* ---------------- /battery: DESS hourly forecast ---------------- */

.forecast-card {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.2rem 1.4rem;
  display: grid;
  gap: 0.75rem;
}
.forecast-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.forecast-title { margin: 0; font-size: 1.05rem; font-weight: 600; }

.forecast-summary {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.75rem;
}
.forecast-stat {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.forecast-stat .muted {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.forecast-stat strong {
  font-size: 1.05rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
@media (max-width: 480px) {
  .forecast-summary { grid-template-columns: 1fr; gap: 0.5rem; }
}

/* Diverging bar chart — zero-line in the middle. Height bands are
 * positioned with an absolute top/bottom anchored at 50 % of the rail. */
.forecast-chart {
  position: relative;
  height: 140px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
}
.forecast-bars {
  position: absolute;
  inset: 0;
  display: flex;
  gap: 1px;
  align-items: stretch;
}
.forecast-bar-wrap {
  flex: 1 1 0;
  position: relative;
  height: 100%;
}
.forecast-bar {
  position: absolute;
  left: 0; right: 0;
  border-radius: 2px;
}
.forecast-bar.dir-import { background: var(--import); }
.forecast-bar.dir-export { background: var(--export); }
.forecast-bar.dir-idle   { background: var(--stale); opacity: 0.4; }

.forecast-zero {
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  border-top: 1px solid var(--line);
  pointer-events: none;
}
.forecast-now-line {
  position: absolute;
  top: 0; bottom: 0;
  width: 2px;
  background: var(--ink);
  transform: translateX(-1px);
  opacity: 0.45;
  pointer-events: none;
}

.forecast-axis {
  position: relative;
  height: 1.1rem;
  font-size: 0.7rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.forecast-axis-cell {
  position: absolute;
  transform: translateX(-50%);
  white-space: nowrap;
}

/* ---------------- /battery: rolling 24h day-forecast ---------------- */

.day-chart {
  position: relative;
  height: 160px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
}
.day-bars {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  gap: 0;
}
.day-bar-wrap {
  flex: 1 1 0;
  height: 100%;
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.day-bar-wrap.is-past { opacity: 0.4; }
.day-bar-wrap.is-now {
  background: rgba(37, 99, 235, 0.08);
  outline: 1px dashed rgba(37, 99, 235, 0.5);
}
.day-bar {
  position: absolute;
  bottom: 0;
  border-radius: 2px 2px 0 0;
}
.day-bar.pv {
  left: 8%; right: 8%;
  background: var(--ser-pv);
  opacity: 0.7;
}
.day-bar.consumption {
  left: 30%; right: 30%;
  background: var(--ser-cons);
  opacity: 0.95;
}

.day-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  border-top: 1px dashed var(--line);
  padding-top: 0.65rem;
}
.day-legend .legend-pill { font-size: 0.72rem; padding: 0.2rem 0.7rem; }
.day-legend .act-charge-pv  { background: var(--tier-cheap-bg); color: #176a3e; }
.day-legend .act-discharge  { background: var(--tier-expensive-bg); color: #a13a17; }

/* Battery flow strip below the day chart — diverging around its own
 * mid-line. Charge above zero (blue), discharge below (orange). */
.batt-strip {
  position: relative;
  height: 36px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
  display: flex;
  gap: 0;
  margin-top: 0.4rem;
}
.batt-cell {
  flex: 1 1 0;
  position: relative;
  height: 100%;
}
.batt-cell.is-past { opacity: 0.4; }
.batt-fill {
  position: absolute;
  left: 8%; right: 8%;
  border-radius: 1px;
}
.batt-fill.battery-charge    { background: var(--batt-charge); }
.batt-fill.battery-discharge { background: var(--batt-discharge); }
.batt-fill.battery-idle      { background: var(--act-hold); opacity: 0.3; }
.batt-fill.battery-none      { display: none; }
.batt-zero {
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  border-top: 1px dashed var(--line);
  pointer-events: none;
}

.batt-charge    { color: var(--act-charge-grid); font-weight: 600; }
.batt-discharge { color: var(--act-discharge); font-weight: 600; }

.day-legend .batt-legend-charge    { background: #dbe7fc; color: #1e40af; }
.day-legend .batt-legend-discharge { background: var(--tier-expensive-bg); color: #a13a17; }

/* ---------------- /tarieven ---------------- */

:root {
  --tier-cheap:     #2eb67d;     /* groen — productiezijde van het palet */
  --tier-cheap-bg:  #e7f6ee;
  --tier-normal:    #6b7280;
  --tier-normal-bg: #eef0f4;
  --tier-expensive: #e8743b;     /* oranje — importzijde */
  --tier-expensive-bg: #fde9e0;
  --tier-unknown:   #cbd5e1;
}

.prices-hero {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.4rem 1.5rem;
  display: grid;
  gap: 0.7rem;
  border-top: 4px solid var(--line);
  transition: border-color 200ms ease;
}
.prices-hero.tier-cheap     { border-top-color: var(--tier-cheap); }
.prices-hero.tier-normal    { border-top-color: var(--tier-normal); }
.prices-hero.tier-expensive { border-top-color: var(--tier-expensive); }

.prices-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.prices-title { margin: 0; font-size: 1.1rem; font-weight: 600; }

.prices-now {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 1rem;
}
.prices-num {
  font-size: clamp(2.2rem, 5vw, 3rem);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.prices-tier-pill {
  font-size: 0.78rem;
}
.prices-tier-pill.tier-cheap     { background: var(--tier-cheap-bg);     color: #176a3e; }
.prices-tier-pill.tier-normal    { background: var(--tier-normal-bg);    color: var(--ink); }
.prices-tier-pill.tier-expensive { background: var(--tier-expensive-bg); color: #a13a17; }
.prices-tier-pill.tier-unknown   { background: var(--tier-normal-bg);    color: var(--muted); }

.prices-sub, .prices-next {
  font-size: 0.88rem;
  font-variant-numeric: tabular-nums;
}

/* ---------- chart card ---------- */

.prices-chart-card {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.2rem 1.4rem;
  display: grid;
  gap: 0.8rem;
}

/* Chart = [y-axis column] [scrollable rail with bars+x-axis].
 * Y-axis labels stay visible while the user scrolls horizontally. */
.prices-chart {
  display: grid;
  grid-template-columns: 3.2rem 1fr;
  gap: 0;
}

.prices-y-axis {
  position: relative;
  height: 220px;
  border-right: 1px solid var(--line);
  margin-right: 0.4rem;
}
.prices-y-tick {
  position: absolute;
  right: 0.35rem;
  font-size: 0.7rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  transform: translateY(-50%);
  white-space: nowrap;
}

/* Wraps bars + axis. On desktop the rail spans 100% so bars flex.
 * On mobile the rail gets a fixed wider min-width and the scroll
 * container scrolls both children in sync. */
.prices-scroll {
  overflow-x: hidden;
  position: relative;
}
.prices-rail {
  display: grid;
  gap: 0.35rem;
  min-width: 0;
  position: relative;
}

/* Grid-lines that overlay the bars (positioned by JS via top:%). */
.prices-grid {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 220px;
  pointer-events: none;
  z-index: 0;
}
.prices-grid-line {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 1px dashed var(--line);
}
.prices-bars { position: relative; z-index: 1; }

.prices-bars {
  display: flex;
  align-items: flex-end;
  height: 220px;
  gap: 1px;
  background: linear-gradient(180deg, transparent 0%, transparent 99%, var(--line) 100%);
}
.prices-bar-wrap {
  flex: 1 1 0;
  height: 100%;
  display: flex;
  align-items: flex-end;
  position: relative;
  min-width: 0;
}
.prices-bar {
  width: 100%;
  border-radius: 2px 2px 0 0;
  transition: opacity 200ms ease;
}
.prices-bar.tier-cheap     { background: var(--tier-cheap); }
.prices-bar.tier-normal    { background: var(--tier-normal); }
.prices-bar.tier-expensive { background: var(--tier-expensive); }
.prices-bar.tier-unknown   { background: var(--tier-unknown); }

/* Past hours: fade bars to half opacity. */
.prices-bar-wrap.is-past .prices-bar { opacity: 0.32; }

/* Now marker: a contrasting outline on the active hour. */
.prices-bar-wrap.is-now {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: 4px;
}
.prices-bar-wrap.is-now .prices-bar { opacity: 1; }

/* X-axis row: same column widths as bars so labels align with their hour. */
.prices-axis {
  display: flex;
  gap: 1px;
}
.prices-axis-cell {
  flex: 1 1 0;
  min-width: 0;
  font-size: 0.7rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  text-align: center;
  position: relative;
  white-space: nowrap;
  overflow: visible;
}
.prices-axis-cell .hour-label {
  display: inline-block;
  transform: translateX(-50%);
  margin-left: 50%;
  white-space: nowrap;
}
.prices-axis-cell.is-day-start .hour-label {
  font-weight: 600;
  color: var(--ink);
}

.prices-footnote {
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
  text-align: center;
  border-top: 1px dashed var(--line);
  padding-top: 0.6rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  align-items: center;
}
.prices-footnote .net-totals { font-size: 0.82rem; }
.net-import-text { color: #9a3412; font-weight: 600; }   /* coral, matching cons */
.net-export-text { color: #4d7c0f; font-weight: 600; }   /* chartreuse, matching pv */

/* Net consumption strip below the price bars. Diverging around its
 * own zero-line — positive = forecast import need, negative = forecast
 * surplus. Same flex/grid as the bars above so cells line up x-wise. */
.prices-net {
  display: flex;
  align-items: stretch;
  height: 32px;
  position: relative;
  margin-top: 0.25rem;
  background: var(--bg);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  gap: 1px;
}
.prices-net-cell {
  flex: 1 1 0;
  height: 100%;
  position: relative;
  min-width: 0;
}
.prices-net-cell.is-past { opacity: 0.35; }
.prices-net-fill {
  position: absolute;
  left: 12%; right: 12%;
  border-radius: 1px;
}
.prices-net-fill.net-import { background: var(--ser-cons); }   /* coral */
.prices-net-fill.net-export { background: var(--ser-pv); }     /* chartreuse */
.prices-net-fill.net-idle   { background: var(--act-hold); opacity: 0.4; }
.prices-net-fill.net-none   { display: none; }
.prices-net-zero {
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  border-top: 1px dashed var(--line);
  pointer-events: none;
}

/* Mobile: cells get fixed widths to match the 14px bar-cells above so
 * scroll-positions stay aligned. */
@media (max-width: 480px) {
  .prices-net-cell { flex: 0 0 14px; }
}

/* Legend pills for the new net series. */
.prices-legend .net-import-pill { background: #ffedd5; color: #9a3412; }
.prices-legend .net-export-pill { background: #ecfccb; color: #4d7c0f; }

/* ---------- legend ---------- */

.prices-legend {
  display: flex;
  flex-wrap: wrap;        /* let pills break to new row at narrow widths */
  gap: 0.5rem;
  justify-content: center;
}
.legend-pill {
  font-size: 0.72rem;
  padding: 0.2rem 0.7rem;
  border-radius: 999px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;    /* keep pill labels on one line */
  overflow-wrap: normal;  /* never split a word mid-character */
}
.legend-pill.tier-cheap     { background: var(--tier-cheap-bg);     color: #176a3e; }
.legend-pill.tier-normal    { background: var(--tier-normal-bg);    color: var(--ink); }
.legend-pill.tier-expensive { background: var(--tier-expensive-bg); color: #a13a17; }

/* Pricing-mode toggle (incl/excl belasting) */
.pricing-toggle {
  display: inline-flex;
  background: var(--card);
  border-radius: 999px;
  padding: 0.25rem;
  box-shadow: var(--shadow);
  align-self: center;
  gap: 0.15rem;
}
.pricing-toggle button {
  appearance: none;
  border: 0;
  background: transparent;
  padding: 0.4rem 0.95rem;
  border-radius: 999px;
  font: inherit;
  font-size: 0.85rem;
  color: var(--muted);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.pricing-toggle button.active {
  background: var(--bg);
  color: var(--ink);
  font-weight: 500;
}

/* ---------------- /warmtepomp ---------------- */

.hp-stats, .hp-extras {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.85rem;
  border-top: 1px solid var(--line);
  padding-top: 0.85rem;
}
.hp-stats > div, .hp-extras > div {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.hp-stats .muted, .hp-extras .muted {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.hp-stats strong, .hp-extras strong {
  font-size: 1.05rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.hp-power { font-size: 1.4rem; }

@media (max-width: 720px) {
  .hp-stats, .hp-extras { grid-template-columns: 1fr; }
}

.hp-conflict {
  background: var(--tier-expensive-bg);
  border-left: 3px solid var(--tier-expensive);
  padding: 0.55rem 0.7rem;
  border-radius: 4px;
  font-size: 0.88rem;
  color: #6e2e0f;
}

/* ---------------- /overzicht ---------------- */

.overview-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}
/* All iPhone 16 variants stack to 1 column (393–440px content area is too
 * narrow for 2-col without truncating "Stal + Werkplaats" sub-labels).
 * 2x2 kicks in at 460px+ where there's actual room. */
@media (max-width: 459px) {
  .overview-grid { grid-template-columns: 1fr; }
}

.overview-card {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.1rem 1.25rem;
  display: grid;
  gap: 0.4rem;
  text-decoration: none;
  color: inherit;
  border-top: 4px solid var(--line);
  transition: border-color 200ms ease, transform 120ms ease, box-shadow 120ms ease;
}
.overview-card:hover {
  transform: translateY(-1px);
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.06),
    0 8px 18px rgba(15, 23, 42, 0.07);
}
/* Tap-feedback for iOS — without this the user gets nothing because we
 * disabled the system grey highlight earlier. */
.overview-card:active,
.price-strip:active,
.tabs .tab:active {
  transform: translateY(0);
  background: var(--bg);
  transition: transform 60ms ease, background 60ms ease;
}
.overview-card.dir-import { border-top-color: var(--import); }
.overview-card.dir-export { border-top-color: var(--export); }
.overview-card.dir-idle   { border-top-color: var(--line); }
.overview-card.dir-stale  { border-top-color: var(--stale); }

.overview-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.overview-title {
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.overview-sub { font-size: 0.78rem; }

.overview-value {
  font-size: 1.7rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.overview-value.dir-import { color: var(--import); }
.overview-value.dir-export { color: var(--export); }
.overview-value.dir-idle   { color: var(--ink); }
.overview-value.dir-stale  { color: var(--stale); }
.overview-value .big-num { font-size: 2rem; }

.overview-detail {
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

/* Price strip */
.price-strip {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.85rem 1.25rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
  text-decoration: none;
  color: inherit;
  border-left: 4px solid var(--line);
  transition: border-color 200ms ease, transform 120ms ease;
}
.price-strip:hover { transform: translateY(-1px); }
.price-strip.tier-cheap     { border-left-color: var(--tier-cheap); }
.price-strip.tier-normal    { border-left-color: var(--tier-normal); }
.price-strip.tier-expensive { border-left-color: var(--tier-expensive); }

.price-strip-left {
  display: flex;
  align-items: baseline;
  gap: 0.65rem;
  flex-wrap: wrap;
}
.price-strip-left .muted {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.price-strip-left strong {
  font-size: 1.15rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.price-strip-right { font-size: 0.85rem; }

/* DESS strip — same shape as price strip, different accent so the two
 * are visually distinguishable when stacked. */
.dess-strip {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.85rem 1.25rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
  text-decoration: none;
  color: inherit;
  border-left: 4px solid var(--accent);
  transition: transform 120ms ease;
}
.dess-strip:hover { transform: translateY(-1px); }
.dess-strip-left {
  display: flex;
  align-items: baseline;
  gap: 0.65rem;
  flex-wrap: wrap;
}
.dess-strip-left .muted {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.dess-strip-left strong {
  font-size: 1.05rem;
  font-weight: 600;
}
.dess-strip-right { font-size: 0.85rem; }

/* ============================================================
 * iPhone / small-screen refinements
 * ------------------------------------------------------------
 * Targets portrait phones (iPhone 13/14/15 are 390-430 CSS px).
 * Tablet portrait (768-820) keeps the desktop layout via the
 * existing 720px breakpoint.
 * ============================================================ */
@media (max-width: 480px) {

  /* --- topbar: drop flex on mobile, plain block layout --- *
   * stretch + intrinsic-wide tabs = item rendered at content-size
   * regardless of min-width:0. Block layout sidesteps the issue:
   * children become block elements that respect parent width. */
  .topbar {
    padding: calc(0.7rem + var(--safe-top)) 0.9rem 0.55rem;
  }
  .topbar-inner {
    grid-template-columns: 1fr;
    align-items: start;
    gap: 0.8rem;
  }
  .brand-block {
    padding: 0 calc(0.15rem + var(--safe-left));
  }
  .brand {
    font-size: 1.35rem;
  }
  .brand-note {
    font-size: 0.64rem;
  }
  .tabs {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    justify-content: flex-start;
    padding: 0.35rem calc(0.2rem + var(--safe-left));
    scroll-padding: 0.85rem;
    scroll-snap-type: x proximity;
    /* Keep the scrolled-out edges from looking abrupt. */
    mask-image: linear-gradient(90deg,
      transparent 0, #000 16px,
      #000 calc(100% - 16px), transparent 100%);
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs .tab {
    flex: 0 0 auto;
    scroll-snap-align: start;
    padding: 0.55rem 0.95rem;     /* taller for thumb-tap */
    font-size: 0.92rem;
  }

  /* --- main container: edge-padding only, no max-width --- */
  main {
    padding: 0.9rem calc(0.9rem + var(--safe-right)) 1rem
                    calc(0.9rem + var(--safe-left));
  }
  .page-intro {
    grid-template-columns: 1fr;
    gap: 0.85rem;
    padding: 1.15rem 1.1rem;
    margin-bottom: 0.95rem;
    border-radius: 16px;
  }
  .page-intro-aside {
    justify-content: flex-start;
  }
  .page-title {
    font-size: clamp(1.8rem, 10vw, 2.35rem);
  }
  .page-lead {
    font-size: 0.95rem;
  }
  .page { gap: 0.85rem; }

  /* --- cards: tighter, smaller radius, less shadow --- */
  .hero, .battery-hero, .pv-total, .meter, .tile,
  .advice-card, .prices-hero, .prices-chart-card, .price-strip,
  .overview-card, .dess-strip, .combined-card {
    padding: 1rem 1.1rem;
    border-radius: 12px;
  }
  .hero { padding: 1.4rem 1.1rem; }
  .battery-hero, .pv-total { padding: 1.1rem 1.1rem; }

  /* --- hero numerals: targets iPhone 16/Plus/Pro/Pro Max (393–440px).
       More generous than older small-screen rules — these phones can
       take a bigger statement number without truncating context. */
  .hero-value .num,
  .pv-total-hero .num,
  .prices-num { font-size: clamp(2.4rem, 10vw, 3rem); }
  .soc-num    { font-size: clamp(2.6rem, 12vw, 3.4rem); }

  /* Meter + advice + battery internal spacing */
  .meter { gap: 0.75rem; }

  /* --- phase cards (P1) stay stacked but tighter --- */
  .tile.phase .row { padding: 0.3rem 0; }

  /* --- /pv: SDM630 phase rows on very narrow screens.
   * Layout: row1 = [L1] [power] [voltage], row2 = [-] [current right-aligned]
   * Selectors use :nth-child(N) — the V/A spans get val-ok / val-warn /
   * val-alert classes via fmt.*Class(), so a class-based selector here
   * would silently miss when thresholds shift. */
  .phase-row {
    grid-template-columns: 1.8rem 1fr auto;
    grid-template-rows: auto auto;
    column-gap: 0.5rem;
    row-gap: 0.1rem;
  }
  .phase-row > :nth-child(1) { grid-column: 1; grid-row: 1; }                   /* L<n> */
  .phase-row > :nth-child(2) { grid-column: 2; grid-row: 1; }                   /* power */
  .phase-row > :nth-child(3) { grid-column: 3; grid-row: 1; text-align: right; }/* voltage */
  .phase-row > :nth-child(4) { grid-column: 2 / span 2; grid-row: 2; text-align: right; }  /* current */

  /* --- inverter sub-section: 1-col on iPhone --- */
  .inverter-grid { grid-template-columns: 1fr; gap: 0.4rem; }

  /* --- /tarieven price-strip: stack the right-side hint --- */
  .price-strip {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.35rem;
  }

  /* --- /tarieven chart: horizontal scroll, wider bars (≥12px) so
       colors and "now" outline stay readable on a 390px screen --- */
  .prices-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    scroll-snap-type: x proximity;
  }
  .prices-scroll::-webkit-scrollbar { display: none; }
  .prices-rail {
    /* 48 hours × 14px + gaps ≈ 720px — guarantees overflow on mobile. */
    min-width: 720px;
  }
  .prices-bar-wrap {
    flex: 0 0 14px;
    scroll-snap-align: start;
  }
  .prices-axis-cell {
    flex: 0 0 14px;
  }
  .prices-bars { height: 180px; gap: 1px; }

  /* --- /overzicht: 2x2 already; just compact value font --- */
  .overview-value { font-size: 1.45rem; }
  .overview-value .big-num { font-size: 1.7rem; }

  /* --- footer above home indicator --- */
  .bottombar {
    padding: 0.9rem 0.9rem calc(0.9rem + var(--safe-bottom));
  }
  .bottombar-inner {
    flex-direction: column;
    align-items: flex-start;
    padding: 0.8rem 0.95rem;
  }
}

/* Wider iPhones / small landscape: relax the most aggressive tweaks */
@media (min-width: 481px) and (max-width: 720px) {
  .topbar {
    padding-top: calc(0.85rem + var(--safe-top));
  }
  .topbar-inner {
    grid-template-columns: 1fr;
    align-items: start;
  }
  .tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    justify-content: flex-start;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs .tab { flex: 0 0 auto; white-space: nowrap; }
  .page-intro {
    grid-template-columns: 1fr;
  }
}

/* ============================================================
   /pv page — Curtailment section
   ============================================================ */
.curtailment {
  margin-top: 1.5rem;
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  padding: 1rem;
  background: var(--card);
  box-shadow: var(--shadow);
}
.curtailment-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 1rem;
}
.curtailment-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 600;
}
.curtailment-sub {
  font-size: 0.85rem;
}
.curtailment-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem;
}
.curtailment-card {
  padding: 0.75rem;
  background: var(--bg);
  border: 1px solid var(--card-border);
  border-radius: calc(var(--radius) - 4px);
}
.curtailment-card h3 {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}
.curtailment-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.25rem 0;
  font-size: 0.9rem;
  border-bottom: 1px solid var(--line);
}
.curtailment-row:last-of-type {
  border-bottom: none;
}
.curtailment-field {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.75rem 0;
  font-size: 0.9rem;
}
.curtailment-field input {
  width: 7em;
  padding: 0.25rem 0.5rem;
  font-family: inherit;
  font-size: 0.95rem;
  border: 1px solid var(--card-border);
  border-radius: 4px;
  background: var(--card);
  color: var(--ink);
}
.curtailment-field input:disabled {
  opacity: 0.5;
}
