:root {
  --ostrom-teal: #21c0b0;
  --ostrom-dark: #1b232c;
  --ink: #182028;
  --muted: #66707a;
  --line: #dce7e7;
  --paper: #f6faf9;
  --card: #ffffff;
  --amber: #f1b94b;
  --coral: #ee6a5f;
  --green: #3fbb78;
  --shadow: 0 18px 55px rgba(var(--shade-rgb), 0.11);
  --card-border: rgba(var(--shade-rgb), 0.13);
  --tile-border: rgba(var(--shade-rgb), 0.08);
  --tile-bg: rgba(239, 247, 245, 0.94);
  /* Rohwert des Ink-Tons für Schatten/Overlays (im Dark heller) */
  --shade-rgb: 27, 35, 44;
  /* Deckende Karten-/Panel-Flächen (ersetzen hartkodierte Weißtöne, dark-fähig) */
  --surface: #ffffff;
  --surface-2: #f2f7f6;
  /* Wert-Chip im Verbrauch-Chart: eigene „erhöhte" Ebene, die sich klar vom Popup abhebt.
     In Hell dezent getönt (+ Ring/Schatten). Der Dark-Wert ist deutlich HELLER als die
     Popup-Fläche, weil ein Schatten auf dunklem Grund kaum trägt. */
  --chip-bg: #f2f7f6;
  --overlay-scrim: rgba(var(--shade-rgb), 0.32);
  /* Trennlinien/Divider: brauchen Kontrast GEGEN die Fläche (im Dark hell, nicht schwarz) */
  --hairline: rgba(27, 35, 44, 0.14);
  /* Diagonal-Schraffur der vergangenen Chart-Balken: Linien in der BALKENFARBE, nur
     leicht abgesetzt. `--hatch-mix` = Ziel, zu dem die Balkenfarbe gemischt wird — in Hell
     Richtung Dunkel, im Dark Richtung Hell, damit dieselbe Farbfamilie in beiden Themes
     dezent sichtbar bleibt (siehe `.bar-wrap.is-past .bar.<klasse>`). */
  --hatch-mix: #0b1013;
  --thumb: #ffffff; /* Segmented-Control-Thumb: hell, hebt sich vom Track ab */
  color-scheme: light;
}

/* ── Dark-Theme ──────────────────────────────────────────────────────────────
   Folgt standardmäßig dem System (prefers-color-scheme). Der Moon-Toggle setzt
   data-theme am <html> und überschreibt das System IMMER (dank :not() unten). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --ostrom-dark: #f2f7f7;
    --ink: #eef4f4;
    --muted: #96a2ab;
    --line: #27313a;
    --paper: #0b1013;
    --card: #161d23;
    /* Dark: hellen Top-Bevel dezent halten, sonst wirkt nur die Oberkante hell
       statt einer gleichmäßig umlaufenden Kontur. */
    --gloss-strength: 0.05;
    --shadow: 0 20px 55px rgba(0, 0, 0, 0.6);
    --card-border: rgba(255, 255, 255, 0.14);
    --tile-border: rgba(255, 255, 255, 0.12);
    --tile-bg: rgba(255, 255, 255, 0.045);
    --shade-rgb: 0, 0, 0;
    --surface: #161d23;
    --surface-2: #1c242b;
    --chip-bg: #2b3540; /* deutlich heller als die Popup-Fläche → Chip schwebt sichtbar */
    --overlay-scrim: rgba(0, 0, 0, 0.58);
    --hairline: rgba(255, 255, 255, 0.12);
    --hatch-mix: #ffffff; /* Dark: Balkenfarbe Richtung Hell mischen → heller Ton derselben Farbe */
    --thumb: #313b45;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --ostrom-dark: #f2f7f7;
  --ink: #eef4f4;
  --muted: #96a2ab;
  --line: #27313a;
  --paper: #0b1013;
  --card: #161d23;
  --gloss-strength: 0.05; /* Dark: Top-Bevel dezent → gleichmäßig umlaufende Kontur */
  --shadow: 0 20px 55px rgba(0, 0, 0, 0.6);
  --card-border: rgba(255, 255, 255, 0.14);
  --tile-border: rgba(255, 255, 255, 0.12);
  --tile-bg: rgba(255, 255, 255, 0.045);
  --shade-rgb: 0, 0, 0;
  --surface: #161d23;
  --surface-2: #1c242b;
  --chip-bg: #2b3540; /* deutlich heller als die Popup-Fläche → Chip schwebt sichtbar */
  --overlay-scrim: rgba(0, 0, 0, 0.58);
  --hairline: rgba(255, 255, 255, 0.12);
  --hatch-mix: #ffffff; /* Dark: Balkenfarbe Richtung Hell mischen → heller Ton derselben Farbe */
    --thumb: #313b45;
}
:root[data-theme="light"] {
  color-scheme: light; /* explizit Hell: escaped die System-Dark-Override oben */
}

/* ── Weiche Theme-Überblendung ────────────────────────────────────────────────
   JS setzt `.theme-anim` für ~380 ms auf <html>, WENN der Moon-Toggle das Theme
   wechselt (nicht beim Laden). Nur dann faden Farben, Schatten, Icons, Statusfarben
   und Rahmen weich über — so gibt es weder Dauer-Transition-Overhead noch einen
   Load-Flash. Der Moon-Toggle ist ausgenommen, damit seine eigene Sonne↔Mond-
   Animation (Scale/Opacity) nicht überfahren wird. Auf sehr alten Browsern ohne
   komplexes :not() fällt die Regel einfach weg → sofortiger Wechsel wie bisher. */
:root.theme-anim,
:root.theme-anim *:not(.moon-toggle):not(.moon-toggle *) {
  transition:
    background-color 320ms ease,
    color 320ms ease,
    border-color 320ms ease,
    box-shadow 320ms ease,
    fill 320ms ease,
    stroke 320ms ease !important;
}
@media (prefers-reduced-motion: reduce) {
  :root.theme-anim,
  :root.theme-anim * {
    transition: none !important;
  }
}

* {
  box-sizing: border-box;
}

html {
  min-height: 100%;
  background: var(--paper);
}

body {
  min-height: 100%;
  margin: 0;
  color: var(--ink);
  background:
    radial-gradient(circle at 12% -8%, rgba(33, 192, 176, 0.34), transparent 29rem),
    radial-gradient(circle at 95% 12%, rgba(63, 187, 120, 0.2), transparent 21rem),
    radial-gradient(circle at 52% 78%, rgba(33, 192, 176, 0.12), transparent 22rem),
    linear-gradient(180deg, #e2faf4 0%, #f8fbfa 42%, #edf4f1 100%);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  letter-spacing: 0;
}

/* Dark: dunkler Seiten-Hintergrund (statt der hellen Verlauf-Fläche) */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body {
    background:
      radial-gradient(circle at 12% -8%, rgba(33, 192, 176, 0.16), transparent 29rem),
      radial-gradient(circle at 95% 12%, rgba(63, 187, 120, 0.1), transparent 21rem),
      linear-gradient(180deg, #0e1519 0%, #0b1013 55%, #090e11 100%);
  }
}
:root[data-theme="dark"] body {
  background:
    radial-gradient(circle at 12% -8%, rgba(33, 192, 176, 0.16), transparent 29rem),
    radial-gradient(circle at 95% 12%, rgba(63, 187, 120, 0.1), transparent 21rem),
    linear-gradient(180deg, #0e1519 0%, #0b1013 55%, #090e11 100%);
}

button,
input {
  font: inherit;
}

.app-shell {
  width: min(100%, 720px);
  min-height: 100vh;
  margin: 0 auto;
  padding: calc(18px + env(safe-area-inset-top)) 14px calc(22px + env(safe-area-inset-bottom));
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 10px 2px 18px;
}

.kicker,
.eyebrow {
  margin: 0 0 5px;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* v0.22.0 — kleine Wegweiser-Icons auf Hero + Wertekacheln:
   Jetzt ⚡ (Hero), Günstig ↓ (Minimum), Teuerster ↑ (Maximum).
   Inline vor dem Text, in em-Einheiten (skaliert mit dem Label), dezent.
   (Ø-Kachel bewusst ohne ≈-Icon — zu eng mit Umschalter; „Ø" reicht.) */
.card-icon {
  width: 0.95em;
  height: 0.95em;
  margin-right: 0.32em;
  vertical-align: -0.14em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.72;
}

/* „Jetzt"-Blitz: gefüllt + Teal-Akzent → zieht den Blick auf den aktuellen Preis. */
.card-icon--bolt {
  fill: var(--ostrom-teal);
  stroke: none;
  opacity: 0.9;
}

h1,
h2,
p {
  margin: 0;
}

h1 {
  color: var(--ostrom-dark);
  font-size: clamp(2rem, 12vw, 3.6rem);
  line-height: 0.95;
  font-weight: 850;
}

h2 {
  font-size: 1rem;
  line-height: 1.15;
}

.source-logo {
  width: 64px;
  max-width: 22vw;
  height: auto;
}
/* Ostrom-Wortmarke ist dunkel (#1B232C) → auf Dark unsichtbar; hell monochrom einfärben. */
:root[data-theme="dark"] .source-logo {
  filter: brightness(0) invert(0.82);
  opacity: 0.8;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .source-logo {
    filter: brightness(0) invert(0.82);
    opacity: 0.8;
  }
}

.status-card,
.summary-panel,
.consumption-panel,
.quick-grid .quick-card,
.panel {
  background: var(--surface);
  border: 1.5px solid var(--card-border);
  box-shadow: var(--shadow);
}

.status-card {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  min-height: 0;
  padding: 23px 18px 18px;
  border-radius: 28px;
  /* Kontur kommt aus dem theme-aware `--card-border` (Basis-Regel) — kein
     `--shade-rgb`-Override, das im Dark schwarz-auf-schwarz = unsichtbar wäre. */
  box-shadow:
    0 20px 58px rgba(var(--shade-rgb), 0.13),
    inset 0 1px 0 rgba(255, 255, 255, var(--gloss-strength, 0.82));
}

.price-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.price-value {
  color: var(--ostrom-dark);
  font-size: clamp(3.45rem, 22vw, 6.6rem);
  line-height: 0.86;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

.price-unit {
  color: var(--muted);
  font-size: 0.95rem;
  font-weight: 800;
}

.hero-meta {
  display: block;
  margin-top: 17px;
}

.hero-meta div {
  min-height: 58px;
  padding: 10px 12px;
  border: 1px solid var(--tile-border);
  border-radius: 16px;
  background: var(--tile-bg);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, var(--gloss-strength, 0.72));
}

.hero-meta .slot-tile {
  display: grid;
  grid-template-columns: minmax(116px, 0.95fr) 1px minmax(0, 2fr);
  align-items: center;
  min-height: 78px;
  gap: 0;
}

.hero-meta .slot-tile div {
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

.slot-now,
.slot-next {
  display: grid;
  gap: 5px;
  min-width: 0;
}

.hero-meta .slot-tile .slot-now {
  padding-right: 12px;
  overflow: hidden;
}

.slot-next {
  grid-template-columns: minmax(52px, 0.72fr) minmax(76px, 1fr);
  align-items: center;
  gap: 8px;
}

.hero-meta .slot-tile .slot-next {
  padding-left: 12px;
}

.slot-next-price {
  display: grid;
  justify-items: end;
  gap: 4px;
  text-align: right;
}

.slot-divider {
  width: 1px;
  align-self: stretch;
  background: var(--hairline);
}

.hero-meta .slot-tile > .slot-divider {
  min-height: 42px;
  background: var(--hairline);
}

.hero-meta span,
.hero-meta small {
  display: block;
  color: var(--muted);
  font-size: 0.7rem;
  font-weight: 800;
}

.hero-meta strong {
  display: block;
  margin-top: 5px;
  color: var(--ostrom-dark);
  font-size: 1.2rem;
  line-height: 1;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

.hero-meta .slot-now strong {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 0;
  font-size: clamp(1.85rem, 8vw, 2.45rem);
  letter-spacing: 0;
  white-space: nowrap;
  max-width: 100%;
  /* KEIN overflow:hidden hier: das clippte bündig an der Text-Advance-Breite und schnitt
     in Safari die rechte Seitenkante der fetten „min"-Glyphe an („Restzeit rechts angeschnitten").
     Der Roll wird bereits pro Ziffer (.slot-digit{overflow:hidden}) vertikal geclippt, und die
     Spalte wird ohnehin durch `.slot-now{overflow:hidden;padding-right:12px}` sauber begrenzt. */
  overflow: visible;
}

.slot-digits {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  min-width: 1.25em;
  height: 1.2em;
  white-space: nowrap;
  color: var(--ostrom-dark);
  font: inherit;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

.slot-digit {
  position: relative;
  display: inline-block;
  width: 0.62em;
  height: 1.2em;
  overflow: hidden;
  line-height: 1.2;
  color: var(--ostrom-dark);
  font: inherit;
  font-weight: 900;
}

.slot-roll-old,
.slot-roll-new {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transform: translateY(0);
}

.slot-roll-new {
  transform: translateY(-112%);
}

.slot-digit.is-rolling .slot-roll-old {
  animation: slot-old-down 430ms cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}

.slot-digit.is-rolling .slot-roll-new {
  animation: slot-new-down 430ms cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}

.slot-unit {
  font-size: 0.72em;
  font-weight: 900;
}

.hero-meta .slot-now .slot-digits,
.hero-meta .slot-now .slot-digits span {
  color: inherit;
  font-size: inherit;
  font-weight: inherit;
}

.hero-meta .slot-now .slot-unit {
  color: inherit;
  font-size: 0.72em;
  font-weight: inherit;
}

@keyframes slot-old-down {
  to {
    transform: translateY(112%);
  }
}

@keyframes slot-new-down {
  to {
    transform: translateY(0);
  }
}

.hero-meta .slot-next strong {
  margin-top: 0;
  font-size: clamp(1rem, 4vw, 1.35rem);
  white-space: nowrap;
}

.month-cost {
  display: block;
  margin-top: 5px;
  color: var(--ostrom-dark);
  font-size: 0.96rem;
  line-height: 1;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

.month-cost[hidden] {
  display: none;
}

.hero-meta small {
  margin-top: 4px;
  font-size: 0.62rem;
}

@media (min-width: 720px) {
  .hero-meta .slot-tile {
    display: grid;
    grid-template-columns: minmax(0, 0.95fr) 1px minmax(0, 2fr);
  }

  .hero-meta .slot-tile strong {
    margin-top: 7px;
    font-size: clamp(1.7rem, 3vw, 2.15rem);
  }
}

.trend-cluster {
  display: inline-grid;
  grid-template-columns: 1fr;
  align-items: center;
  justify-items: center;
  gap: 3px;
  max-width: 100%;
  text-align: center;
}

.hero-meta .trend-cluster {
  min-height: 0;
  padding: 0;
  border-radius: 0;
  background: transparent;
}

.trend-badge {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  width: 28px;
  height: 28px;
  min-width: 28px;
  min-height: 28px;
  aspect-ratio: 1;
  padding: 0;
  border-radius: 999px;
  color: #fff;
  background: var(--ostrom-teal);
  font-size: 1rem;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

.hero-meta .slot-tile .trend-badge {
  width: 28px;
  height: 28px;
  min-width: 28px;
  min-height: 28px;
  padding: 0;
  border-radius: 999px;
  background: var(--ostrom-teal);
  color: #fff;
}

.hero-meta .slot-tile .trend-badge.rising,
.hero-meta .slot-tile .trend-badge.rising-strong {
  background: var(--coral);
}

.hero-meta .slot-tile .trend-badge.falling,
.hero-meta .slot-tile .trend-badge.falling-strong {
  background: var(--green);
}

.hero-meta .slot-tile .trend-badge.neutral,
.hero-meta .slot-tile .trend-badge.flat {
  background: var(--amber);
  color: #38270d;
}

.trend-label {
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 850;
  line-height: 1.05;
  text-align: center;
}

.trend-badge.rising {
  background: var(--coral);
}

.trend-badge.rising-strong {
  background: var(--coral);
}

.trend-badge.falling {
  background: var(--green);
}

.trend-badge.falling-strong {
  background: var(--green);
}

.trend-badge.neutral,
.trend-badge.flat {
  background: var(--amber);
  color: #38270d;
}

.summary-panel,
.consumption-panel {
  margin-top: 16px;
  padding: 13px;
  border-radius: 22px;
}

.summary-head {
  display: flex;
  justify-content: space-between;
  margin: 0 2px 10px;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.quick-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: stretch;
  gap: 8px;
  margin: 0;
}

.quick-grid .quick-card {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 100%;
  min-height: 86px;
  padding: 13px 12px;
  border-radius: 18px;
  color: inherit;
  text-align: left;
}

button.quick-card {
  border: 1.5px solid var(--card-border);
  cursor: pointer;
  font: inherit;
  /* v0.19.0 — weiches Tap-Feedback: Skalierung, Kontur und Schatten animiert. */
  transition: transform 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease;
}

/* iOS-Feeling: Tap → minimale Skalierung, aktive Teal-Kontur, weicher Schatten. */
button.quick-card:active {
  transform: scale(0.98);
  border-color: color-mix(in srgb, var(--ostrom-teal) 55%, var(--card-border));
  box-shadow: 0 2px 10px rgba(var(--shade-rgb), 0.12);
}

/* v0.24.0 — klickbare Kacheln (öffnen ein Popup) tragen schon im Ruhezustand eine
   dickere 2px-Kontur → „tappbar" ist sofort erkennbar, nicht erst bei Hover. Info-Karten
   (<article>) behalten ihre dünnere 1–1.5px-Kontur. Nur die BREITE wächst — die Farbe
   bleibt der theme-aware Rahmen-Token (im Dark hell/sichtbar, siehe Dark-Kontur-Smoke);
   ein teal-Tönung hier würde den Rahmen im Dark zu blass + rot-arm machen. Hover/Active
   (Pseudo-Klasse) setzen weiterhin die Teal-Kontur. Spezifität bewusst über den
   Basis-Rahmenregeln (.quick-grid .quick-card = 0,2,0 · .consumption-tile = 0,1,0). */
.quick-grid button.quick-card,
.consumption-tile.consumption-tile-button {
  border-width: 2px;
}

.quick-grid .quick-card.average-card {
  position: relative;
  overflow: visible;
  z-index: 2;
}

.quick-grid .quick-card.average-card.menu-open {
  z-index: 8;
}

.quick-grid .quick-card.good {
  border-color: rgba(63, 187, 120, 0.46);
  background: linear-gradient(180deg, rgba(63, 187, 120, 0.17), var(--surface));
}

.quick-grid .quick-card.bad {
  border-color: rgba(238, 106, 95, 0.46);
  background: linear-gradient(180deg, rgba(238, 106, 95, 0.16), var(--surface));
}

.quick-grid span {
  display: block;
  min-height: 30px;
  color: var(--muted);
  font-size: 0.73rem;
  font-weight: 800;
  line-height: 1.15;
}

.quick-grid strong {
  display: block;
  margin-top: 8px;
  color: var(--ostrom-dark);
  font-size: 1.16rem;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.average-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 6px;
  min-height: 30px;
}

.quick-grid .average-top span {
  min-height: 0;
}

.average-toggle {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  min-height: 24px;
  padding: 0 8px;
  border: 0;
  border-radius: 999px;
  color: var(--ostrom-dark);
  background: var(--surface-2);
  font-size: 0.68rem;
  font-weight: 900;
  line-height: 1;
  cursor: pointer;
}

.average-toggle[aria-expanded="true"] {
  background: var(--ink);
  color: var(--paper);
}

.average-menu {
  position: absolute;
  top: 44px;
  right: 10px;
  display: grid;
  gap: 3px;
  width: 126px;
  padding: 5px;
  border: 1px solid rgba(var(--shade-rgb), 0.08);
  border-radius: 15px;
  background: var(--surface);
  box-shadow: 0 16px 34px rgba(var(--shade-rgb), 0.16);
}

.average-menu[hidden] {
  display: none;
}

.average-menu button {
  min-height: 32px;
  border: 0;
  border-radius: 11px;
  color: var(--muted);
  background: transparent;
  font-size: 0.76rem;
  font-weight: 900;
  text-align: left;
  cursor: pointer;
}

.average-menu button[aria-checked="true"] {
  color: var(--ostrom-dark);
  background: var(--surface-2);
}

.average-menu button:disabled {
  color: rgba(102, 112, 122, 0.45);
  cursor: default;
}

.panel {
  margin-top: 16px;
  padding: 16px;
  border-radius: 22px;
  /* Kontur aus dem theme-aware `--card-border` (Basis-Regel), nicht aus einem
     `--shade-rgb`-Override (im Dark unsichtbar). */
  box-shadow:
    0 18px 48px rgba(var(--shade-rgb), 0.1),
    inset 0 1px 0 rgba(255, 255, 255, var(--gloss-strength, 0.82));
}

.consumption-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.consumption-tile {
  min-height: 78px;
  padding: 12px;
  border: 1px solid var(--tile-border);
  border-radius: 16px;
  background: var(--tile-bg);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, var(--gloss-strength, 0.72));
}

.consumption-tile span,
.consumption-tile small {
  display: block;
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 800;
}

.consumption-tile strong {
  display: block;
  margin-top: 6px;
  color: var(--ostrom-dark);
  font-size: 1.1rem;
  line-height: 1;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

.panel-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 12px;
}

.panel-head p {
  margin-top: 4px;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 750;
}

.chart-panel.is-morphing {
  transition: height 320ms cubic-bezier(0.2, 0.8, 0.2, 1);
  will-change: height;
}

.chart {
  display: grid;
  gap: 12px;
  padding-top: 8px;
  cursor: pointer; /* v0.24.0 — Tap öffnet das Verbrauch-Popup (Touch-Abkürzung) */
}

.chart-band {
  display: grid;
  gap: 6px;
  min-height: 112px;
}

.chart-band-title {
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 900;
  line-height: 1.1;
  text-align: left;
}

.chart-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  align-items: end;
  gap: 6px;
  padding: 10px 8px 0;
  border-radius: 16px;
  background: var(--surface-2);
  border: 1px solid rgba(var(--shade-rgb), 0.07);
  border-bottom-color: rgba(var(--shade-rgb), 0.12);
}

.bar-wrap {
  display: grid;
  grid-template-rows: 24px 1fr 26px;
  align-items: end;
  height: 102px;
  min-width: 0;
}

.bar-price {
  align-self: start;   /* Preis UNTEN direkt am Balkenfuß (oben in der Fußzeile) */
  margin-top: 3px;
  color: var(--ostrom-dark);
  font-size: 0.62rem;
  font-weight: 600;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.bar {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 8px;
  border-radius: 8px 8px 0 0;
  background: var(--ostrom-teal);
}

.bar.cheap {
  --current-slot-icon-color: var(--green);
  background: var(--green);
}

.bar.normal {
  --current-slot-icon-color: var(--ostrom-teal);
  background: var(--ostrom-teal);
}

.bar.expensive {
  --current-slot-icon-color: var(--coral);
  background: var(--coral);
}

.bar.current {
  box-shadow: none;
  z-index: 2;
}

/* Aktueller Slot leuchtet in seiner eigenen Slot-Farbe und hebt sich damit klar
   von den matten (vergangenen) und blassen (künftigen) Balken ab. */
.bar-wrap.is-current .bar.cheap {
  box-shadow: 0 3px 15px rgba(63, 187, 120, 0.55);
}
.bar-wrap.is-current .bar.normal {
  box-shadow: 0 3px 15px rgba(33, 192, 176, 0.55);
}
.bar-wrap.is-current .bar.expensive {
  box-shadow: 0 3px 15px rgba(238, 106, 95, 0.55);
}

/* Zeitliche Tönung: vergangene Slots VERBLASST (Farbton bleibt), künftige nur
   umrissen, der aktuelle leuchtet (Glow + Blitz-Marker).
   Bewusst opacity statt saturate/brightness: Entsättigen machte aus den warmen
   Coral-/Rot-Tönen Matsch/Braun. Ausbleichen behält den Farbton — ein
   vergangener teurer Slot bleibt rosa, ein günstiger grün (Preisklasse bleibt
   ablesbar) — ohne aufdringlich zu sein. */
.bar-wrap.is-past .bar {
  opacity: 0.4;
  /* Schraffur-Linie = Balkenfarbe: die liegt je Preisklasse bereits in
     `--current-slot-icon-color` (.bar.cheap/.normal/.expensive), nur ~22 % Richtung
     `--hatch-mix` verschoben → derselbe Farbton, eine Spur abgesetzt = „in der Balkenfarbe". */
  --hatch-line: color-mix(in srgb, var(--current-slot-icon-color), var(--hatch-mix) 22%);
}

/* Vergangene Slots zusätzlich mit dezenter Diagonal-Schraffur markieren („erledigt").
   Als Overlay (::after), damit die Preisklassen-Füllfarbe darunter erhalten bleibt.
   Liegt im 0.4-opacity-Balken → die Linien wirken automatisch dezent. */
.bar-wrap.is-past .bar::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: repeating-linear-gradient(
    45deg,
    var(--hatch-line, transparent) 0,
    var(--hatch-line, transparent) 1px,
    transparent 1px,
    transparent 6px
  );
  pointer-events: none;
}

/* Künftige Slots: „steht noch aus" — dünne 1px-Kontur nur OBEN + an den SEITEN
   (kein Rahmen an der unteren Balkenkante, der Balken sitzt offen auf der
   Grundlinie) + halbe Füllung. Kontur pro Preisklasse, damit die Farbe bleibt. */
.bar-wrap.is-future .bar {
  border-style: solid;
  border-width: 1px 1px 0 1px;   /* oben · rechts · KEINE unten · links */
}
.bar-wrap.is-future .bar.cheap {
  background: rgba(63, 187, 120, 0.5);
  border-color: var(--green);
}
.bar-wrap.is-future .bar.normal {
  background: rgba(33, 192, 176, 0.5);
  border-color: var(--ostrom-teal);
}
.bar-wrap.is-future .bar.expensive {
  background: rgba(238, 106, 95, 0.5);
  border-color: var(--coral);
}

.bar-wrap.is-past .bar-price {
  color: var(--muted);
}

/* Stundenwechsel-Animation: feiner Knister-Lichtbogen zwischen altem und neuem
   Slot, in Balkenfarbe (Verlauf bei Farbwechsel) + dezenter Glow. Overlay liegt
   über dem #chart (das bei jedem Render neu gebaut wird), daher am .chart-panel. */
.chart-panel {
  position: relative;
}
.chart-crackle {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
  z-index: 4;
  overflow: visible;
}
.chart-crackle .cc-glow {
  fill: none;
  stroke: url(#chart-crackle-grad);
  stroke-width: 3.4;
  opacity: 0.22;
  filter: blur(1.4px);
  stroke-linecap: round;
  stroke-linejoin: round;
}
.chart-crackle .cc-core {
  fill: none;
  stroke: url(#chart-crackle-grad);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* ⚡ blendet im neuen aktuellen Balken ein (nur Opacity — kein transform, damit
   die current-outside-Positionierung nicht überschrieben wird). */
@keyframes current-slot-icon-enter {
  from { opacity: 0; }
  to { opacity: 1; }
}
.current-slot-icon-enter {
  animation: current-slot-icon-enter 0.3s ease;
}
@media (prefers-reduced-motion: reduce) {
  .chart-crackle { display: none; }
  .current-slot-icon-enter { animation: none; }
}

.current-slot-icon {
  width: 16px;
  height: 16px;
  fill: #fff;
  filter: drop-shadow(0 1px 4px rgba(var(--shade-rgb), 0.55));
  pointer-events: none;
}

.bar.current-outside .current-slot-icon {
  position: absolute;
  top: -18px;
  left: 50%;
  fill: var(--current-slot-icon-color, var(--ostrom-teal));
  transform: translateX(-50%);
  filter: drop-shadow(0 1px 2px rgba(var(--shade-rgb), 0.18));
}

.hour-label {
  align-self: start;   /* Zeit OBEN in der Zelle, klare Kopfzeile über den Balken */
  color: var(--muted);
  font-size: 0.58rem;
  font-weight: 750;
  text-align: center;
  line-height: 1.1;
}

.chart-full-day {
  gap: 8px;
}

.chart-full-day .chart-band {
  min-height: 128px;
}

.chart-full-day .chart-grid {
  grid-template-columns: repeat(24, minmax(0, 1fr));
  gap: 2px;
  padding-inline: 5px;
}

.chart-full-day .bar-wrap {
  grid-template-rows: 20px 1fr 20px;
  height: 112px;
}

.chart-full-day .bar-price {
  font-size: 0.5rem;
  font-weight: 550;
  letter-spacing: -0.04em;
}

.chart-full-day .bar {
  border-radius: 5px 5px 0 0;
}

.chart-full-day .bar.current {
  box-shadow: none;
}

.chart-full-day .current-slot-icon {
  width: 11px;
  height: 11px;
}

.chart-full-day .bar.current-outside .current-slot-icon {
  top: -15px;
}

.chart-full-day .hour-label {
  height: 18px;
  margin-top: 5px;
  font-size: 0.5rem;
}

.legend {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 14px;
  color: var(--muted);
  font-size: 0.77rem;
  font-weight: 750;
}

.legend span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.legend i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
}

.cheap-dot {
  background: var(--green);
}

.normal-dot {
  background: var(--ostrom-teal);
}

.expensive-dot {
  background: var(--coral);
}

.period-list {
  display: grid;
  gap: 8px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.period-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 42px;
  padding: 10px 11px;
  border-radius: 14px;
  background: var(--surface-2);
  font-size: 0.9rem;
  font-weight: 800;
}

.period-list li.empty {
  color: var(--muted);
  justify-content: flex-start;
}

.period-list small {
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 750;
}

.period-dialog {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-items: end center;
  /* Popups sitzen ein Stück höher, damit die Aktionsleiste am unteren
     Sheet-Rand in der Daumen-Zone liegt (Einhandbedienung). */
  padding: 18px 18px calc(7vh + env(safe-area-inset-bottom));
}

.period-dialog[hidden] {
  display: none;
}

.period-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(var(--shade-rgb), 0.28);
  /* v0.28.0 (Apple-Feeling) — Frosted-Glass hinter dem Popup. iOS Safari rendert
     `backdrop-filter` NUR mit `-webkit-`-Prefix → ohne ihn blieb der Blur am iPhone
     ganz aus. `saturate` gibt die typische iOS-Vibrancy. */
  -webkit-backdrop-filter: blur(10px) saturate(1.3);
  backdrop-filter: blur(10px) saturate(1.3);
  opacity: 0; /* fadet mit dem Sheet ein/aus */
  transition: opacity 220ms ease;
}

.period-sheet {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  width: min(100%, 680px);
  max-height: min(80vh, 600px);
  overflow: hidden;
  /* Kontur: hebt das Popup klar vom (im Dark sehr dunklen) Hintergrund ab —
     `--hairline` ist theme-aware (helle Kante auf Dunkel, dunkle Kante auf Hell). */
  border: 1px solid var(--hairline);
  /* v0.28.0 (Apple-Feeling) — großzügigerer Sheet-Radius + zweilagiger Schatten
     (weiter, weicher Ambient + enger Kontakt-Schatten) → mehr Tiefe/„Premium". */
  border-radius: 32px;
  background: var(--surface);
  box-shadow: 0 36px 90px rgba(var(--shade-rgb), 0.30), 0 6px 18px rgba(var(--shade-rgb), 0.12);
  /* Erscheinen: Fade-up (von unten einblendend); Schließen: Fade-down (nach unten aus). */
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 220ms ease, transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* v0.24.1 — die Sheets sind `tabindex="-1"`-Container und werden beim Öffnen per
   `.focus()` fokussiert (Fokus-Management). iOS Safari zeichnet dafür eine blaue
   Default-Fokus-Kontur ums ganze Popup. Der Container ist kein Bedien-Element und
   nie ein Tab-Ziel → Kontur entfernen. Die interaktiven Kinder (Buttons, Balken)
   behalten ihre eigene `:focus-visible`-Teal-Kontur. */
.period-sheet:focus {
  outline: none;
}

.period-dialog.is-open .period-backdrop {
  opacity: 1;
}

.period-dialog.is-open .period-sheet {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .period-backdrop,
  .period-sheet {
    transition: none;
  }
}

/* Scrollbereich = Popup-Inhalt; Day-Nav + Aktionsleiste bleiben darunter fix am Daumen. */
.sheet-scroll {
  flex: 1;
  min-height: 0;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  padding: 18px 18px 12px;
}

/* Bedien-Zeile am unteren Sheet-Rand: Umschalter/Aktion MITTIG (bester
   Daumen-Sweet-Spot), Schließen rechts. 3-Spalten-Grid (1fr auto 1fr) hält den
   Umschalter exakt zentriert, egal wie breit er ist. */
.sheet-actions {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  padding: 11px 16px calc(11px + env(safe-area-inset-bottom));
  border-top: 1px solid rgba(var(--shade-rgb), 0.08);
  background: var(--surface);
}

.sheet-actions .seg-switch {
  grid-column: 2; /* Mitte */
}

.sheet-actions .icon-button {
  grid-column: 3;
  justify-self: end; /* Schließen immer unten rechts */
}

/* Zurücksetzen-Button (Balkenauswahl leeren) unten links in der Daumen-Zone, spiegelt
   den Schließen-Button. Icon = Pfeil GEGEN den Uhrzeigersinn (zurücksetzen, nicht Refresh). */
.sheet-actions .consumption-reset {
  grid-column: 1;
  justify-self: start;
}

.consumption-reset:disabled {
  opacity: 0.32;
  cursor: default;
}

/* v0.30.3 — Reset-Icon als Unicode-Glyph ↺ (U+21BA) statt SVG (Albrecht-Wunsch). Sitzt zentriert
   im runden .icon-button; Größe so gewählt, dass es optisch zum Schließen-X passt. */
.reset-glyph {
  font-size: 1.45rem;
  line-height: 1;
  font-weight: 500;
}

/* WICHTIG: `.icon-button { display: grid }` überstimmt sonst das UA-`[hidden]`
   → der Reset-Button bliebe in Listen-/Leer-Ansicht sichtbar + fokussierbar.
   Gleiches Muster wie .consumption-list[hidden] / .consumption-empty[hidden] etc. */
.consumption-reset[hidden] {
  display: none;
}

.period-sheet-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 12px;
}

.period-sheet-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.period-sheet h3 {
  margin: 0;
  color: var(--ostrom-dark);
  font-size: 0.92rem;
  line-height: 1.15;
}

.icon-button {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 0;
  border-radius: 999px;
  color: var(--ostrom-dark);
  background: var(--surface-2);
  cursor: pointer;
  transition: transform 0.13s ease, background-color 0.13s ease;
}

/* v0.19.0 — spürbarer Druck auf runden Bedien-Buttons. */
.icon-button:not(:disabled):active {
  transform: scale(0.9);
}

.icon-button svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 2.4;
}

body.period-dialog-open {
  overflow: hidden;
}

/* ---- Verbrauch-Tagesverlauf (Popup) ---- */

.consumption-tile-button {
  display: block;
  width: 100%;
  text-align: left;
  cursor: pointer;
  transition: transform 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease;
}

/* Nur auf Zeigergeräten: sonst bleibt der Hover-Rand nach dem Tap auf Touch „kleben". */
@media (hover: hover) {
  .consumption-tile-button:hover {
    border-color: rgba(33, 192, 176, 0.5);
  }
}

/* v0.19.0 — gleiches Tap-Feedback wie die Quick-Cards (iOS-Feeling). */
.consumption-tile-button:active {
  transform: scale(0.98);
  border-color: color-mix(in srgb, var(--ostrom-teal) 55%, var(--card-border));
  box-shadow: 0 2px 10px rgba(var(--shade-rgb), 0.12);
}

.consumption-tile-button:focus-visible {
  outline: 2px solid var(--ostrom-teal);
  outline-offset: 2px;
}

.tile-cta {
  display: block;
  margin-top: 8px;
  color: var(--ostrom-teal);
  font-size: 0.66rem;
  font-weight: 800;
}

.consumption-sheet {
  width: min(100%, 560px);
}

/* Tag-Navigation sitzt in der Daumen-Zone: feste Foot-Zeile über der Bedienleiste. */
.day-nav {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px 6px;
  border-top: 1px solid rgba(var(--shade-rgb), 0.08);
}

/* Day-Nav liefert schon die Trennlinie → Bedienleiste im Verbrauch-Popup ohne
   eigene Oberkante (sonst Doppellinie). */
.consumption-sheet .sheet-actions {
  border-top: 0;
  padding-top: 4px;
}

.day-nav-btn {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: 0 0 auto;
  border: 1px solid var(--tile-border);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ostrom-dark);
  cursor: pointer;
  transition: transform 0.13s ease, border-color 0.13s ease;
}

/* v0.19.0 — Druck-Feedback auf der Tag-Navigation. */
.day-nav-btn:not(:disabled):active {
  transform: scale(0.9);
  border-color: color-mix(in srgb, var(--ostrom-teal) 55%, var(--tile-border));
}

.day-nav-btn svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 2.4;
}

.day-nav-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

.day-picker {
  position: relative;
  flex: 1 1 auto;
  display: grid;
  place-items: center;
  min-height: 44px;
  padding: 8px 12px;
  border: 1px solid var(--tile-border);
  border-radius: 14px;
  background: var(--tile-bg);
  cursor: pointer;
}

.day-picker-label {
  color: var(--ostrom-dark);
  font-size: 0.95rem;
  font-weight: 850;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

/* Nativer Date-Picker: transparent über der Kachel, öffnet den iOS-Kalender. */
.day-picker-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  cursor: pointer;
}

/* v0.33.0 — Tagesauswahl im Tagesverlauf: ‹ Heute › über dem Chart (Pfeile = .day-nav-btn). */
/* Tages-Nav sitzt in der panel-head (rechts, wo früher der 6h/24h-Schalter war) → kompakt. */
.chart-day-nav {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
}

.chart-day-nav .day-nav-btn {
  width: 34px;
  height: 34px;
}

.chart-day-label {
  /* v0.34.1 — FESTE Breite (fasst „Heute"…„Do., 30.09."): sonst wächst/schrumpft die Pille
     je nach Label und der linke Blätterpfeil springt. box-sizing sichert die Breite inkl. Padding. */
  width: 118px;
  box-sizing: border-box;
  padding: 6px 12px;
  border: 1px solid var(--tile-border);
  border-radius: 999px;
  background: var(--tile-bg);
  color: var(--ostrom-dark);
  font-size: 0.9rem;
  font-weight: 850;
  font-variant-numeric: tabular-nums;
  text-align: center;
  cursor: pointer;
}

.chart-day-label:active {
  transform: scale(0.97);
}

/* Leerzustand (z. B. morgen vor der Day-Ahead-Freigabe ~14 Uhr). */
.chart-empty {
  display: grid;
  place-items: center;
  width: 100%;
  min-height: 168px;
  padding: 28px 22px;
  text-align: center;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.5;
}

.consumption-summary {
  display: flex;
  align-items: flex-start; /* v0.32.0 — Pille oben bündig zur kWh-Schlagzeile (Block ist jetzt bis zu 3-zeilig) */
  justify-content: space-between;
  gap: 12px;
  /* v0.31.1 — Divider unter der Zusammenfassung: trennt „13,14 kWh · 6 % teurer" klar vom
     Chart/der Liste darunter → saubere Sektionen. */
  padding-bottom: 12px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--hairline);
}

.consumption-totals {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 3px 8px;
  min-width: 0;
}

.consumption-totals strong {
  color: var(--ostrom-dark);
  font-size: 1.6rem;
  line-height: 1;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

.consumption-totals small {
  flex-basis: 100%;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 800;
}
/* v0.32.0 — Kosten-Aufschlüsselung unter der Tages-Schlagzeile: „Energie X + Grundpreis Y ·
   effektiv Z ct/kWh". Volle Breite, dezenter/kleiner als die Kosten-Zeile, darf umbrechen. */
/* v0.32.1 — Selektor mit `.consumption-totals`-Präfix, sonst gewinnt `.consumption-totals small`
   (0,1,1) über die font-size/-weight und die Zeile käme so groß/fett wie die Kosten-Zeile daher. */
.consumption-totals .consumption-breakdown {
  flex-basis: 100%;
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 700;
  line-height: 1.3;
  opacity: 0.92;
}
.consumption-breakdown[hidden] {
  display: none;
}

/* v0.27.0 — Ersparnis-Kennzahl: kompakte Pille rechts im Kopf. Grün = günstiger als der
   Tagesschnitt verbraucht, Coral = teurer, neutral ≈ Schnitt. Kein `display` in der
   Basisregel → `[hidden]` greift (siehe LEARNINGS v0.22.1), zusätzlich explizit abgesichert. */
.consumption-savings {
  flex: 0 0 auto;
  margin: 0;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 850;
  white-space: nowrap;
  border: 1px solid transparent;
}
.consumption-savings[hidden] {
  display: none;
}
.consumption-savings.is-good {
  color: var(--green);
  background: rgba(63, 187, 120, 0.14);
  border-color: rgba(63, 187, 120, 0.28);
}
.consumption-savings.is-bad {
  color: var(--coral);
  background: rgba(238, 106, 95, 0.14);
  border-color: rgba(238, 106, 95, 0.28);
}
.consumption-savings.is-neutral {
  color: var(--muted);
  background: rgba(var(--shade-rgb), 0.06);
}

.seg-switch {
  position: relative;
  display: inline-grid;
  grid-template-columns: repeat(2, minmax(40px, 1fr));
  gap: 3px;
  padding: 3px;
  flex: 0 0 auto;
  border-radius: 999px;
  background: var(--surface-2);
  isolation: isolate;
}

.seg-switch::before {
  content: "";
  position: absolute;
  inset: 3px auto 3px 3px;
  z-index: 0;
  width: calc((100% - 9px) / 2);
  border-radius: 999px;
  background: var(--thumb);
  box-shadow: 0 8px 18px rgba(var(--shade-rgb), 0.11);
  transform: translateX(0);
  transition: transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.seg-switch[data-view="list"]::before {
  transform: translateX(calc(100% + 3px));
}

.seg-switch button {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 32px;
  padding: 0 14px;
  border: 0;
  border-radius: 999px;
  color: var(--muted);
  background: transparent;
  cursor: pointer;
  transition: color 180ms ease;
}

/* Icons statt Wörter — Farbe folgt dem aktiven Zustand des Umschalters. */
.seg-switch button svg {
  display: block;
  width: 19px;
  height: 19px;
  fill: currentColor;
}

.seg-switch button[aria-pressed="true"] {
  color: var(--ostrom-dark);
}

.seg-switch button:disabled {
  opacity: 0.4;
  cursor: default;
}

.consumption-chart {
  position: relative; /* Bezug für die absolute Preislinien-Overlay (v0.23.0) */
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 186px;
  /* Oben genug Platz für den zweizeiligen Wert-Chip ÜBER dem höchsten Balken. Seitlich KEIN
     `overflow: hidden` mehr (v0.22.2): das schnitt die Chips der Randstunden (00/23) ab. Die
     Chips dürfen jetzt ins Sheet-Polster (18px) hineinragen — der Scroll-Container clippt erst
     an seiner eigenen Kante, die weit genug außen liegt. Oben reicht das 44px-Polster. */
  /* v0.31.1 — links/rechts Gutters für die Achsen-Beschriftung (außerhalb der Balken). */
  padding: 44px 30px 0 34px;
  overflow: visible;
  /* eigener Stacking-Context, damit die Rasterlinien (z-index:-1) HINTER den Balken
     bleiben, aber nicht hinter die Sheet-Fläche rutschen. */
  isolation: isolate;
}

/* v0.23.0 — Preislinie (Marktpreis) über den Verbrauchsbalken. Deckt exakt die Track-
   Fläche der Balken ab (oben 44px Chart-Polster, unten die Stunden-Label-Zeile ~19px,
   seitlich das 12px-Chart-Polster). Liegt ÜBER den Balken, aber UNTER den Wert-Chips (z-index 3). */
.cchart-price {
  position: absolute;
  top: 44px;
  bottom: 19px;
  left: 34px;  /* v0.31.1 — an die Gutters angepasst (deckt exakt den Balkenbereich ab) */
  right: 30px;
  z-index: 2;
  pointer-events: none;
}
.cchart-price-svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.cchart-price-line {
  fill: none;
  stroke: var(--ink);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
  opacity: 0.82;
}

/* v0.31.1 — Echte Dual-Achsen mit Raster. Beschriftung AUSSERHALB der Balken in Rand-Spalten
   (links kWh, rechts ct); horizontale Rasterlinien + linke/rechte y-Achsenlinie liegen HINTER
   den Balken (z-index:-1 im Stacking-Context der `.consumption-chart`, s. `isolation` dort). */
.cchart-axes {
  position: absolute;
  top: 44px;
  bottom: 19px;
  left: 0;
  right: 0;
  pointer-events: none;
}
/* Rasterfläche = Balkenbereich (zwischen den Gutters). Rahmen links/rechts = y-Achsenlinien. */
.cchart-grid {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 34px;   /* = Chart-Padding links (Gutter für die kWh-Skala) */
  right: 30px;  /* = Chart-Padding rechts (Gutter für die ct-Skala) */
  z-index: -1;  /* hinter die Balken */
  border-left: 1px solid var(--hairline);
  border-right: 1px solid var(--hairline);
}
.cchart-gridline {
  position: absolute;
  left: 0;
  right: 0;
  height: 0;
  border-top: 1px solid var(--hairline);
  opacity: 0.65;
}
/* Achsen-Spalten (Gutters) für die Labels — außerhalb der Balken. */
.cchart-axis {
  position: absolute;
  top: 0;
  bottom: 0;
}
.cchart-axis-left { left: 0; width: 34px; }
.cchart-axis-right { right: 0; width: 30px; }
.cax {
  position: absolute;
  transform: translateY(-50%); /* mittig auf der Rasterlinie */
  font-size: 0.54rem;
  font-weight: 800;
  color: var(--muted);
  line-height: 1;
  white-space: nowrap;
}
.cchart-axis-left .cax { right: 4px; text-align: right; }
.cchart-axis-right .cax { left: 4px; text-align: left; }
/* Einheiten-Kopf (einmal, über der Max-Marke, im Chip-Polster oberhalb des Plots). */
.cax-unit {
  position: absolute;
  top: -13px;
  font-size: 0.5rem;
  font-weight: 800;
  color: var(--muted);
  opacity: 0.75;
  white-space: nowrap;
}
.cchart-axis-left .cax-unit { right: 4px; }
.cchart-axis-right .cax-unit { left: 4px; }

/* v0.23.0 — Legende über dem Chart: welche Serie ist Verbrauch (Balken), welche Preis (Linie). */
.consumption-legend {
  display: flex;
  gap: 16px;
  margin: 0 2px 8px;
  font-size: 0.66rem;
  font-weight: 800;
  color: var(--muted);
}
.consumption-legend[hidden] { display: none; }
.cleg {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.cleg-swatch { flex: 0 0 auto; }
.cleg-bars {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  background: var(--ostrom-teal);
}
.cleg-line {
  width: 15px;
  height: 0;
  border-top: 2px solid var(--ink);
  opacity: 0.82;
}

.consumption-chart[hidden] {
  display: none;
}

.cbar-col {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: 100%;
  min-width: 0;
  /* Jede Stunde ist ein Button (Tap blendet den Wert ein) → Button-Defaults zurücksetzen. */
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.cbar-col:focus-visible {
  outline: 2px solid var(--ostrom-teal);
  outline-offset: 2px;
  border-radius: 6px;
}

/* Antipp-Chip: Sprechblase mit zwei Zeilen — Verbrauch (kWh) oben, Kosten (€) darunter.
   Schwebt ABSOLUT über dem Balkenkopf (kein Flex-Platz im Spalten-Fluss), damit hohe
   Balken die Spalte nicht nach unten drücken → alle Balken sitzen bündig auf einer Linie. */
.cbar-val {
  position: absolute;
  bottom: 100%; /* direkt über der Balken-Oberkante */
  left: 50%;
  transform: translateX(-50%);
  margin-bottom: 5px; /* Abstand Chip → Balken (Platz für die Sprechblasen-Spitze) */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px; /* mehr Zeilenabstand: sonst berührt das Komma der kWh-Zeile die €-Zeile darunter */
  /* Rundum Luft; oben etwas mehr als unten, weil Ziffern (ohne Unterlänge) sonst
     optisch nach oben rutschen → so sitzt der Text mittig in der Blase. Unten genug
     Polster, damit die Sprechblasen-Spitze nicht in den Text ragt. */
  padding: 6px 8px 5px;
  border-radius: 8px;
  line-height: 1.1;
  font-weight: 850;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  z-index: 3; /* über die Nachbarbalken heben, sonst verdeckt ein höherer Balken den Wert */
  visibility: hidden; /* sichtbar nur mit `.show-val` (Default: teuerste + günstigste; sonst per Tap) */
}

.cbar-val-kwh {
  font-size: 0.56rem;
  color: var(--ink);
}
.cbar-val-eur {
  font-size: 0.52rem;
  color: var(--muted);
}

.cbar-col.show-val .cbar-val {
  visibility: visible;
  /* Chip muss sich klar vom Popup abheben — `--surface` wäre exakt die Popup-Farbe
     (Chip verschwindet). `--chip-bg` ist die erhöhte Ebene (im Dark deutlich heller als der
     Grund, in Hell leicht getönt); Ring (theme-aware) + Schlagschatten lassen die
     Sprechblase sichtbar über der Fläche schweben. */
  background: var(--chip-bg);
  box-shadow:
    0 0 0 1px var(--hairline),
    0 6px 16px rgba(var(--shade-rgb), 0.32);
}

/* Sprechblasen-Spitze: gedrehtes Quadrat unten mittig → nur die untere Ecke schaut
   als Dreieck heraus; die zwei unteren Kanten tragen die Hairline (auch in Hell
   sichtbar). Liegt vor dem Chip-Body → deckt die Naht der Chip-Unterkante ab. */
.cbar-col.show-val .cbar-val::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  width: 6px;
  height: 6px;
  transform: translate(-50%, -50%) rotate(45deg);
  background: var(--chip-bg); /* muss zum Chip-Body passen (sonst sichtbare Naht) */
  border-right: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  border-radius: 0 0 2px 0; /* leicht gerundete Spitze */
}

/* Farbe der Primärzeile (kWh) für teuerste/günstigste Stunde */
.cbar-col.is-peak .cbar-val-kwh {
  color: var(--coral);
}
.cbar-col.is-low .cbar-val-kwh {
  color: var(--green);
}

/* Balken-Track: nimmt den Platz zwischen den (schwebenden) Chips oben und dem
   Stunden-Label unten; der Balken sitzt immer an dessen Unterkante → bündige Basis. */
.cbar-track {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.cbar {
  position: relative; /* Positionierungskontext für den schwebenden Chip */
  flex-shrink: 0; /* nie stauchen → Höhe entspricht exakt dem Prozentwert */
  width: 100%;
  max-width: 15px;
  border-radius: 5px 5px 2px 2px;
  background: linear-gradient(180deg, #3ad3c2 0%, var(--ostrom-teal) 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4);
  transition: filter 0.12s ease; /* v0.19.0 — sanftes Tap-Feedback */
}

/* v0.19.0 — dezenter Druck: angetippter Balken wird kurz heller. */
.cbar-col:active .cbar {
  filter: brightness(1.12);
}

.cbar.is-peak {
  background: linear-gradient(180deg, #f2897e 0%, var(--coral) 100%);
}

.cbar.is-low {
  background: linear-gradient(180deg, #63e0a3 0%, var(--green) 100%);
}

.cbar-hour {
  flex-shrink: 0; /* feste Höhe → Balken-Basis bleibt auf einer Linie */
  margin-top: 6px;
  height: 0.8rem;
  font-size: 0.58rem;
  font-weight: 800;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* v0.30.0 — farb-unabhängiger Peak/Low-Marker (▲ teuerste / ▼ günstigste Stunde). Die FORM
   unterscheidet sie auch bei Rot-Grün-Schwäche, nicht nur die Farbe (WCAG „nicht allein Farbe").
   v0.30.2 — nur noch in der Liste (Balken-Marker entfernt, s. app.js). */
.clist-mark {
  font-weight: 900;
  line-height: 1;
  font-size: 0.66rem;
}
/* v0.30.1 — eigene Marker-Spalte in der Liste (mittig; leer bei normalen Stunden). */
.clist-mark-col {
  text-align: center;
}
.clist-mark.is-peak {
  color: var(--coral);
}
.clist-mark.is-low {
  color: var(--green);
}

.consumption-dialog.is-loading .consumption-chart,
.consumption-dialog.is-loading .consumption-list {
  opacity: 0.45;
  transition: opacity 0.15s ease;
}

/* ── Listenansicht: eine Zeile je Stunde (Stunde · Verbrauch · Kosten) ───────── */
.consumption-list {
  display: flex;
  flex-direction: column;
  max-height: 300px; /* kompakt wie der Chart-Bereich → scrollt intern, Foot-Leiste bleibt erreichbar */
  overflow-y: auto;
  /* v0.30.2 — KEIN oberes Padding: sonst bleibt über dem sticky-Kopf ein 2px-Spalt, durch den
     die durchscrollenden Zeilen durchscheinen („Werte über dem Kopf"). Kopf sitzt jetzt bündig. */
  padding: 0 2px 2px;
  -webkit-overflow-scrolling: touch;
}
.consumption-list[hidden] {
  display: none;
}
.clist-row {
  display: grid;
  /* v0.31.2 — Marker · Stunde · Verbrauch · Markt · Abgaben · Kosten (Markt/Abgaben als eigene Spalten). */
  grid-template-columns: 1.2rem 2.7rem 1fr 0.85fr 0.9fr 0.95fr;
  align-items: baseline;
  column-gap: 7px;
  padding: 8px 10px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap; /* v0.31.2 — vererbt auf alle Zellen: 6 Spalten dürfen nie umbrechen */
  transition: background-color 0.12s ease; /* v0.20.0 — weiches Row-Highlight */
}
/* v0.31.5 — Zebra zurück (Albrecht: Divider + horizontale Linien = Unruhe statt Ordnung).
   Jede zweite DATEN-Zeile dezent getönt; der sticky-Kopf ist Kind 1 (ungerade) → bleibt untönt.
   Spezifität 0,2,0 = gleich wie Peak/Low → die stehen weiter unten und gewinnen per Source-Order;
   Hover (0,3,0) und is-selected (box-shadow) überschreiben ohnehin. */
.clist-row:nth-child(even) {
  background: color-mix(in srgb, var(--surface), var(--ink) 4%);
}
.clist-hour {
  color: var(--muted);
  font-weight: 800;
  font-size: 0.78rem;
}
.clist-kwh {
  text-align: right;
  font-weight: 850;
  font-size: 0.78rem;
  color: var(--ostrom-dark);
}
/* v0.31.2 — Preis-Aufschlüsselung als eigene Spalten (Markt + Steuern/Abgaben, ct/kWh). */
.clist-markt,
.clist-abgaben {
  text-align: right;
  font-weight: 800;
  font-size: 0.78rem;
  color: var(--muted);
}
.clist-eur {
  text-align: right;
  font-weight: 850;
  font-size: 0.78rem;
  color: var(--ostrom-dark);
}
/* Kopfzeile: klein, sticky oben beim Scrollen. v0.30.2 — deckt jetzt lückenlos ab: bündig oben
   (Container ohne Top-Padding), opake Fläche + Hairline unten + höherer z-index, damit KEINE
   durchscrollende Zeile mehr über dem Kopf durchscheint. */
.clist-head {
  position: sticky;
  top: 0;
  z-index: 3;
  padding: 6px 10px 6px;
  background: var(--surface);
  border-bottom: 1px solid var(--hairline);
  border-radius: 0;
  align-items: start; /* v0.31.5 — Term oben bündig; die Einheit hängt als 2. Zeile darunter */
}
.clist-head span {
  font-size: 0.56rem; /* v0.31.2 — etwas kleiner: 6 Spalten (inkl. Markt/Abgaben) sollen passen */
  font-weight: 800;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--muted);
}
/* v0.31.5 — Einheit als 2. Kopfzeile (kWh / ct/kWh). Transparent statt geschönt: macht klar,
   dass Markt/Abgaben Preise pro kWh sind und sich NICHT mit den € der Kosten-Spalte addieren.
   text-transform:none — sonst erbt „ct/kWh" das uppercase des Kopfes. */
.clist-unit {
  display: block;
  margin-top: 2px;
  font-size: 0.48rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  text-transform: none;
  opacity: 0.7;
}
.clist-row.is-peak {
  background: rgba(238, 106, 95, 0.14); /* Coral-Tönung für die teuerste Stunde */
}
.clist-row.is-peak .clist-kwh,
.clist-row.is-peak .clist-eur {
  color: var(--coral);
}
.clist-row.is-low {
  background: rgba(63, 187, 120, 0.14); /* Grün-Tönung für die günstigste Stunde */
}
.clist-row.is-low .clist-kwh,
.clist-row.is-low .clist-eur {
  color: var(--green);
}

/* v0.24.0 — Slot-Sync: in der Balkenansicht ausgewählte Stunden bekommen in der Liste
   einen teal Balken links (inset box-shadow folgt dem border-radius). Koexistiert mit
   Peak/Low, die den Hintergrund tönen — die Auswahl-Markierung sitzt am Rand, nicht im BG. */
.clist-row.is-selected {
  box-shadow: inset 3px 0 0 var(--ostrom-teal);
}
.clist-row.is-selected .clist-hour {
  color: var(--ostrom-dark);
  font-weight: 850;
}

/* v0.25.0 — Datenzeilen sind antippbare Toggles (Slot-Sync Liste→Balken). Nur die
   Zeilen mit role="button" (nicht die Kopfzeile) sind klickbar. Hover-Highlight +
   is-selected-Balken links liefern das visuelle Feedback; hier nur Cursor + Fokus. */
.clist-row[role="button"] {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.clist-row[role="button"]:focus-visible {
  outline: 2px solid var(--ostrom-teal);
  outline-offset: -2px;
}

/* v0.20.0 — ganze Zeile bei Hover hervorheben (nicht nur eine Zelle). Nur auf
   Zeigergeräten (kein „sticky hover" nach Tap auf Touch). Steht NACH Zebra +
   Peak/Low und hat höhere Spezifität (:hover) → gewinnt auf jeder Datenzeile. */
@media (hover: hover) {
  .clist-row:not(.clist-head):hover {
    background: color-mix(in srgb, var(--surface), var(--ostrom-teal) 14%);
  }
}

.consumption-empty {
  margin: 6px 0 4px;
  padding: 26px 12px;
  text-align: center;
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 700;
}

.consumption-empty[hidden] {
  display: none;
}

.footer {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 18px 4px 0;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 750;
}

.refresh-status {
  position: fixed;
  top: calc(12px + env(safe-area-inset-top));
  left: 50%;
  z-index: 60;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 42px;
  padding: 0 16px;
  border: 1px solid rgba(var(--shade-rgb), 0.12);
  border-radius: 999px;
  color: var(--ostrom-dark);
  background: var(--surface);
  box-shadow: 0 16px 36px rgba(var(--shade-rgb), 0.18);
  font-size: 0.78rem;
  font-weight: 850;
  transform: translateX(-50%);
  -webkit-backdrop-filter: blur(12px); /* v0.28.0 — iOS-Safari-Prefix (sonst kein Blur am iPhone) */
  backdrop-filter: blur(12px);
}

.refresh-status[hidden] {
  display: none;
}

.refresh-spinner {
  width: 15px;
  height: 15px;
  border: 2px solid rgba(33, 192, 176, 0.22);
  border-top-color: var(--ostrom-teal);
  border-radius: 50%;
  animation: refresh-spin 820ms linear infinite;
}

@keyframes refresh-spin {
  to {
    transform: rotate(360deg);
  }
}

.error-toast {
  position: fixed;
  right: 14px;
  bottom: calc(14px + env(safe-area-inset-bottom));
  left: 14px;
  max-width: 680px;
  margin: 0 auto;
  padding: 14px 16px;
  border-radius: 18px;
  color: #fff;
  background: var(--coral);
  box-shadow: var(--shadow);
  font-weight: 800;
}

@media (max-width: 440px) {
  .app-shell {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 100svh;
    padding: calc(10px + env(safe-area-inset-top)) 8px calc(10px + env(safe-area-inset-bottom));
  }

  .topbar {
    padding: 0 2px 13px;
  }

  .kicker,
  .eyebrow {
    margin-bottom: 2px;
    font-size: 0.58rem;
  }

  h1 {
    font-size: clamp(1.82rem, 10vw, 2.65rem);
  }

  .source-logo {
    width: 76px;
  }

  .status-card {
    min-height: 0;
    padding: 17px 15px 15px;
    border-radius: 22px;
  }

  .price-value {
    font-size: clamp(2.65rem, 18vw, 4.55rem);
  }

  .price-unit {
    font-size: 0.82rem;
  }

  .trend-label {
    font-size: 0.58rem;
  }

  .hero-meta {
    margin-top: 11px;
  }

  .hero-meta div {
    min-height: 52px;
    padding: 10px;
    border-radius: 14px;
  }

  .hero-meta .slot-tile {
    grid-template-columns: minmax(104px, 0.95fr) 1px minmax(0, 2fr);
    min-height: 64px;
  }

  .hero-meta .slot-now strong {
    font-size: clamp(1.6rem, 6.8vw, 2rem);
  }

  .hero-meta .slot-next strong {
    font-size: clamp(0.92rem, 3.8vw, 1.15rem);
  }

  .hero-meta strong {
    font-size: 1rem;
  }

  .hero-meta span,
  .hero-meta small {
    font-size: 0.62rem;
  }

  .slot-now,
  .slot-next,
  .slot-next-price {
    gap: 3px;
  }

  .month-cost {
    font-size: 0.82rem;
  }

  .trend-cluster {
    min-height: 0;
    gap: 2px;
    padding: 0;
    border-radius: 0;
    background: transparent;
  }

  .trend-badge {
    width: 24px;
    height: 24px;
    min-width: 24px;
    min-height: 24px;
    padding: 0;
    border-radius: 999px;
    font-size: 0.9rem;
  }

  .hero-meta .slot-tile .trend-badge {
    width: 24px;
    height: 24px;
    min-width: 24px;
    min-height: 24px;
    padding: 0;
    border-radius: 999px;
    background: var(--ostrom-teal);
    color: #fff;
  }

  .hero-meta .slot-tile .trend-badge.rising,
  .hero-meta .slot-tile .trend-badge.rising-strong {
    background: var(--coral);
  }

  .hero-meta .slot-tile .trend-badge.falling,
  .hero-meta .slot-tile .trend-badge.falling-strong {
    background: var(--green);
  }

  .hero-meta .slot-tile .trend-badge.neutral,
  .hero-meta .slot-tile .trend-badge.flat {
    background: var(--amber);
    color: #38270d;
  }

  .trend-label {
    font-size: 0.58rem;
    text-align: right;
  }

  .quick-grid .quick-card {
    min-height: 78px;
    padding: 10px;
    border-radius: 16px;
  }

  .summary-panel,
  .consumption-panel {
    margin-top: 13px;
    padding: 10px;
    border-radius: 20px;
  }

  .summary-head {
    margin-bottom: 8px;
    font-size: 0.62rem;
  }

  .quick-grid {
    margin: 0;
  }

  .panel {
    margin-top: 13px;
  }

  .quick-grid strong {
    margin-top: 4px;
    font-size: 0.88rem;
    white-space: nowrap;
  }

  .quick-grid span {
    min-height: 24px;
    font-size: 0.62rem;
  }

  .average-menu {
    top: 38px;
    right: 6px;
  }

  .chart {
    gap: 10px;
    padding-top: 6px;
  }

  .panel-head {
    align-items: stretch;
    margin-bottom: 8px;
  }

  .panel {
    padding: 16px;
    border-radius: 24px;
  }

  .consumption-grid {
    gap: 7px;
  }

  .consumption-tile {
    min-height: 74px;
    padding: 10px;
    border-radius: 15px;
  }

  .consumption-tile strong {
    font-size: 1rem;
  }

  .consumption-tile span,
  .consumption-tile small {
    font-size: 0.62rem;
  }

  .chart-full-day .chart-band {
    min-height: 126px;
  }

  .chart-full-day .bar-wrap {
    height: 110px;
  }

  .legend {
    display: none;
  }

  .period-dialog {
    /* Auch auf kleinen Screens angehoben, Aktionsleiste in die Daumen-Zone. */
    padding: 10px 10px calc(6vh + env(safe-area-inset-bottom));
  }

  .period-sheet {
    max-height: 84vh;
    border-radius: 24px;
  }

  .sheet-scroll {
    padding: 16px 16px 10px;
  }

  .period-sheet-grid {
    grid-template-columns: 1fr;
    gap: 18px;
  }
}

/* Muss nach den generischen .hero-meta span-Regeln stehen. */
.hero-meta .slot-now .slot-digits {
  display: inline-flex;
}

.hero-meta .slot-now .slot-digit {
  display: inline-block;
}

.hero-meta .slot-now .slot-roll-old,
.hero-meta .slot-now .slot-roll-new {
  display: flex;
}

/* ── Moon-Toggle (Theme-Umschalter) ───────────────────────────────────────────
   Basiert auf „moon toggle" von Jhey Tomkins (@jh3y), MIT-Lizenz:
   https://codepen.io/jh3y/pen/ByBjxrW — für die App stark vereinfacht/gescoped:
   Mond verkleinert (bleibt IN der Pille, .face clippt), Jheys 3D-Weiß-Schatten/
   Glow-Ebenen entfernt (verursachten weiße Kanten in den Radien), Farben
   theme-token-getrieben statt light-dark(), gekoppelt an aria-pressed (true ⟺ HELL). */
.topbar-actions {
  display: flex;
  align-items: center;
  flex: none;
}
.moon-toggle {
  --step: 0.4s;
  --ease: linear(0 0%, 0.42 25%, 0.73 50%, 0.9 68%, 1 100%);
  --mt-socket: #d7dee0;
  --mt-plate: #b9c0c6;
  --glow: hsl(182 90% 88%);
  font-size: 11px;
  height: 3em;
  aspect-ratio: 1.8 / 1;
  padding: 0;
  border: 0;
  border-radius: 3em;
  background: transparent;
  position: relative;
  cursor: pointer;
  flex: none;
  overflow: hidden; /* clippt exakt auf die Pillenform → keine Ecken-Artefakte in den Radien */
  -webkit-tap-highlight-color: transparent;
}
.moon-toggle:focus-visible { outline: 2px solid var(--ostrom-teal); outline-offset: 3px; }
/* nicht gebrauchte Deko-Ebenen aus Jheys Demo abschalten (weiße Kanten/Bulge weg) */
.moon-toggle .face-shadow,
.moon-toggle .face-glowdrop,
.moon-toggle .face-shine,
.moon-toggle .face-glows,
.moon-toggle .socket-shadow,
.moon-toggle .trail-holder,
.moon-toggle .trail,
.moon-toggle .inner { display: none; }
.moon-toggle .socket,
.moon-toggle .face,
.moon-toggle .face-plate { position: absolute; border-radius: 3em; }
.moon-toggle .socket {
  inset: 0;
  background: var(--mt-socket);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05), 0 1px 2px rgba(0, 0, 0, 0.22);
  transition: background-color var(--step) var(--ease);
}
.moon-toggle .face {
  inset: 0.14em;
  /* KEIN overflow:hidden hier — der Face-Clip erzeugte an den Radien-Tangenten
     helle Kanten-Ticks. Der Mond bleibt durch das overflow:hidden am .moon-toggle
     (Button) in der Pille. */
  scale: 1;
  transition: scale var(--step) var(--ease);
}
.moon-toggle .face-plate {
  inset: 0;
  background: radial-gradient(120% 130% at 30% 12%, rgba(255, 255, 255, 0.16), transparent 55%), var(--mt-plate);
  transition: background-color var(--step) var(--ease);
}
.moon-toggle .face svg {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  width: auto;
  height: 62%;
  overflow: visible;
}
.moon-toggle .face svg path { transform-box: fill-box; transform-origin: center; }
.moon-toggle .glow {
  z-index: 3;
  filter: drop-shadow(0 0 0.1em var(--glow));
  opacity: 1;
  transition: opacity var(--step) var(--ease);
}
.moon-toggle .glow-path { fill: var(--glow); stroke: var(--glow); stroke-width: 0; }
.moon-toggle .outline {
  fill: #121821;
  stroke: #121821;
  transition: fill var(--step) var(--ease), stroke var(--step) var(--ease);
}

/* pressed = HELL: Mond dunkel (Glow aus), Face minimal größer */
.moon-toggle[aria-pressed="true"] .glow { opacity: 0; }
.moon-toggle[aria-pressed="true"] .face { scale: 1.06; }
.moon-toggle:active .face { scale: 0.97; }

/* Dark-Farbtöne für den Toggle */
:root[data-theme="dark"] .moon-toggle { --mt-socket: #05080c; --mt-plate: #0e151c; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .moon-toggle { --mt-socket: #05080c; --mt-plate: #0e151c; }
}

@media (prefers-reduced-motion: reduce) {
  .moon-toggle .glow,
  .moon-toggle .face,
  .moon-toggle .socket,
  .moon-toggle .outline { transition-duration: 0.001s; }
}

/* Ostrom-Logo sitzt jetzt im Footer (statt Topbar) */
.footer-source {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.footer-source .source-logo {
  width: 52px;
  max-width: none;
}

/* ── Pull-to-Refresh: zwei Knister-Lichtbögen + Ostrom-Logo → Haken ───────────
   Arc-Canvas + Icon liegen fix am oberen Rand und zeichnen NUR in der Zieh-Lücke
   (0…pull); die App-Shell wird beim Ziehen nach unten geschoben und gibt den
   festen Body-Verlauf frei — daher braucht es keine Verdeckung. */
html, body { overscroll-behavior-y: contain; } /* zähmt den nativen Overscroll-Bounce */
.app-shell { will-change: transform; }
#ptr-arc {
  position: fixed; top: 0; left: 0; width: 100%; height: 240px;
  pointer-events: none; z-index: 40;
}
#ptr-icon {
  position: fixed; top: 0; left: 50%; z-index: 41;
  width: 34px; height: 34px; margin: -17px 0 0 -17px; pointer-events: none;
}
#ptr-icon .ptr-spin { position: absolute; inset: 0; }
#ptr-icon svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.ptr-ostrom { opacity: 0; transform: scale(0.4); transform-origin: center; }
.ptr-ostrom path { fill: var(--ostrom-teal); filter: drop-shadow(0 0 5px rgba(33, 192, 176, 0.5)); }
#ptr-icon.spin .ptr-spin { animation: ptr-spin 0.72s linear infinite; }
@keyframes ptr-spin { to { transform: rotate(-360deg); } }
.ptr-check {
  opacity: 0; transform: scale(0.4); transform-origin: center;
  transition: opacity 0.3s ease, transform 0.42s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.ptr-check circle { fill: none; stroke: var(--green); stroke-width: 2; opacity: 0.28; }
.ptr-check path {
  fill: none; stroke: var(--green); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 22; stroke-dashoffset: 22; filter: drop-shadow(0 0 5px rgba(63, 187, 120, 0.5));
}
#ptr-icon.done .ptr-check { opacity: 1; transform: scale(1); }
#ptr-icon.done .ptr-check path { stroke-dashoffset: 0; transition: stroke-dashoffset 0.4s ease 0.18s; }
@media (prefers-reduced-motion: reduce) {
  #ptr-icon.spin .ptr-spin { animation: none; }
  #ptr-icon.done .ptr-check path { transition: none; stroke-dashoffset: 0; }
}
