// Forecast screen — Gridome Hour v2 aesthetic.
// Layout logic from EVCC /forecast (SolarChart + PriceChart, sync-scroll, 48h horizon).
// Reskinned entirely: Gridome dark surfaces, teal/amber/tier palette.
// NO consumption forecast line — Phase 2 ML, not built.

// ── Stub data (mirrors real schema from pv_forecast_cache.py + state.tariff.hourly_prices)
function buildForecastData(scenario) {
  const now = new Date();
  const nowH = now.getHours() + now.getMinutes() / 60;

  // 48h of hourly slots starting from current hour
  const slots = Array.from({ length: 48 }, (_, i) => {
    const h = (Math.floor(nowH) + i) % 24;
    const dayOffset = Math.floor((Math.floor(nowH) + i) / 24); // 0=today, 1=tomorrow

    // PV generation (kWh per hour) — bell curve, zero at night
    // Forecast.Solar returns watts_mean, watts_min, watts_max
    const pvPeak = 8.4;  // kWp × 0.7 efficiency × clear-sky factor
    const sunAngle = Math.max(0, Math.sin(((h - 6) / 12) * Math.PI));
    const cloudFactor = dayOffset === 0
      ? [0.9, 0.85, 0.95, 0.8, 0.75, 0.9, 1.0, 0.95, 0.9, 0.85, 0.8, 0.75,
         0.9, 1.0, 0.95, 0.9, 0.85, 0.8, 0.75, 0.9, 0, 0, 0, 0][h]
      : [0.7, 0.65, 0.8, 0.9, 0.85, 0.95, 1.0, 0.9, 0.85, 0.8, 0.7, 0.75,
         0.8, 0.9, 0.95, 0.85, 0.8, 0.75, 0.7, 0.65, 0, 0, 0, 0][h];
    const pvMean = pvPeak * sunAngle * cloudFactor;
    const variance = pvMean * 0.18;  // ±18% confidence band — realistic for Forecast.Solar
    const pvMin = Math.max(0, pvMean - variance);
    const pvMax = pvMean + variance;

    // Tariff price (gr/kWh all-in)
    const basePrice = [
      32, 28, 26, 29, 30, 35, 48, 72, 95, 84, 62, 44,
      38, 36, 42, 58, 82, 118, 142, 138, 112, 78, 52, 38,
    ][h];
    // Tomorrow prices vary ±15% from today — realistic day-ahead variation
    const price = dayOffset === 0
      ? basePrice
      : Math.round(basePrice * (0.88 + Math.random() * 0.24));
    const tier = price < 50 ? 'cheap' : price < 95 ? 'standard' : price < 130 ? 'peak' : 'high';

    return { i, h, dayOffset, pvMean, pvMin, pvMax, price, tier };
  });

  // Summary stats
  const todaySlots = slots.filter(s => s.dayOffset === 0);
  const tomorrowSlots = slots.filter(s => s.dayOffset === 1);
  const pvToday = todaySlots.reduce((a, s) => a + s.pvMean, 0).toFixed(1);
  const pvTomorrow = tomorrowSlots.reduce((a, s) => a + s.pvMean, 0).toFixed(1);

  // Find cheapest 2-hour window tomorrow (for croissant line)
  let bestWindow = { start: 0, sum: Infinity };
  for (let k = 24; k < 46; k++) {
    const sum = slots[k].price + slots[k+1].price;
    if (sum < bestWindow.sum) bestWindow = { start: k, sum };
  }
  const cheapH1 = slots[bestWindow.start].h;
  const cheapH2 = (cheapH1 + 2) % 24;
  const cheapAvg = Math.round(bestWindow.sum / 2);

  return { slots, pvToday, pvTomorrow, bestWindow, cheapH1, cheapH2, cheapAvg, nowH };
}

// ── Main component ─────────────────────────────────────────────────────────
function V2Forecast({ s }) {
  const { t } = useLocale();
  const data = React.useMemo(() => buildForecastData(s), [s.key]);
  const { slots, pvToday, pvTomorrow, bestWindow, cheapH1, cheapH2, cheapAvg } = data;

  const cropFood = foodFor(parseFloat(pvTomorrow) * 0.6 * (cheapAvg / 100));
  const cheapTime = `${String(cheapH1).padStart(2,'0')}:00–${String(cheapH2).padStart(2,'0')}:00`;

  return (
    <div>
      {/* Weather & Solar strip */}
      <WeatherSolarStrip s={s} pvToday={pvToday} pvTomorrow={pvTomorrow}/>

      {/* Croissant moment */}
      <div style={{
        marginBottom: 20, padding: '14px 18px',
        background: `${T.green}14`, border: `1px solid ${T.green}30`,
        borderRadius: 12, display: 'flex', alignItems: 'flex-start', gap: 14,
      }}>
        <LI name="sun" size={24} color={T.amber} />
        <div>
          <div style={{ fontSize: 13, fontWeight: 600, color: T.textPrimary, marginBottom: 3 }}>
            {t('forecast.cheapTomorrow')} <span style={{ color: T.green, fontFamily: T.fontMono }}>{cheapTime}</span>
            {' '}·{' '}{cheapAvg} gr/kWh
          </div>
          <div style={{ fontSize: 12, color: T.textSecondary, lineHeight: 1.5 }}>
            {t('forecast.croissantSuffix')} {cropFood.text} {t('forecast.savings')}.{' '}
            {t('forecast.pvAvailable')} <strong style={{ color: T.amber }}>{pvTomorrow} kWh</strong>.
          </div>
        </div>
      </div>

      {/* Section 1 — PV generation */}
      <Surface style={{ marginBottom: 18 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 16 }}>
          <div>
            <SurfaceLabel>{t('forecast.pvTitle')}</SurfaceLabel>
            <div style={{ fontSize: 11, color: T.textMuted, marginTop: 5, lineHeight: 1.5 }}>
              {t('forecast.pvDisclaimer')}
            </div>
          </div>
          <div style={{ display: 'flex', gap: 16, fontSize: 12, color: T.textMuted, flexShrink: 0 }}>
            <span>{t('forecast.pvToday')} · <strong style={{ color: T.amber, fontFamily: T.fontMono }}>{pvToday} kWh</strong></span>
            <span>{t('forecast.pvTomorrow')} · <strong style={{ color: T.amber, fontFamily: T.fontMono }}>{pvTomorrow} kWh</strong></span>
          </div>
        </div>
        <PVForecastChart slots={slots} nowH={data.nowH}/>
        <ForecastTimeAxis slots={slots} nowH={data.nowH}/>
      </Surface>

      {/* Section 2 — Tariff 48h */}
      <Surface style={{ marginBottom: 18 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 16 }}>
          <div>
            <SurfaceLabel>{t('forecast.tariffTitle')}</SurfaceLabel>
            <div style={{ fontSize: 11, color: T.textMuted, marginTop: 5 }}>
              {t('forecast.tariffSub')}
            </div>
          </div>
          <TariffMinMaxBadge slots={slots}/>
        </div>
        <TariffForecastStrip slots={slots} nowH={data.nowH}/>
        <ForecastTimeAxis slots={slots} nowH={data.nowH}/>
        <TierLegend/>
      </Surface>

      {/* Grid Health — between energy prices and consumption forecast */}
      <GridHealthCard/>

      {/* Section 3 — Consumption forecast stub */}
      <Surface>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
          <SurfaceLabel>{t('forecast.consumptionTitle')}</SurfaceLabel>
          <span style={{
            fontSize: 9, fontWeight: 700, letterSpacing: 0.8, textTransform: 'uppercase',
            color: T.violet, background: `${T.violet}18`,
            border: `1px solid ${T.violet}33`, padding: '3px 8px', borderRadius: 4,
          }}>Phase 2 · ML</span>
        </div>
        <div style={{ padding: '20px 0', textAlign: 'center', color: T.textMuted, fontSize: 13, lineHeight: 1.7 }}>
          {t('forecast.consumptionBody')}
          <div style={{ fontFamily: T.fontMono, fontSize: 11, color: T.textMuted, marginTop: 8 }}>
            nilm_helpers.py → demand_forecast() → state.consumption_forecast
          </div>
        </div>
      </Surface>
    </div>
  );
}

// ── PV chart: area with confidence band ────────────────────────────────────
function PVForecastChart({ slots, nowH }) {
  const { t } = useLocale();
  const W = 1000, H = 140, padY = 10;
  const maxPv = Math.max(...slots.map(s => s.pvMax), 1);

  const toY = (v) => H - padY - (v / maxPv) * (H - padY * 2);
  const toX = (i) => (i / (slots.length - 1)) * W;

  // Mean line points
  const meanPts = slots.map((s, i) => ({ x: toX(i), y: toY(s.pvMean) }));
  const minPts  = slots.map((s, i) => ({ x: toX(i), y: toY(s.pvMin) }));
  const maxPts  = slots.map((s, i) => ({ x: toX(i), y: toY(s.pvMax) }));

  const smoothPath = (pts) => pts.reduce((acc, { x, y }, i) => {
    if (i === 0) return `M${x} ${y}`;
    const prev = pts[i-1];
    const mx = (prev.x + x) / 2, my = (prev.y + y) / 2;
    return acc + ` Q${prev.x} ${prev.y} ${mx} ${my}`;
  }, '') + ` T${pts[pts.length-1].x} ${pts[pts.length-1].y}`;

  const meanPath = smoothPath(meanPts);
  const maxPath  = smoothPath(maxPts);
  const minPathR = smoothPath([...minPts].reverse());
  const bandPath = maxPath + ` L${maxPts[maxPts.length-1].x} ${H} L${maxPts[0].x} ${H} Z`;
  const confPath = maxPath + ' ' + minPathR.replace('M', 'L') + ' Z';

  // Day divider
  const todaySlots = slots.filter(s => s.dayOffset === 0).length;
  const divX = toX(todaySlots - 0.5);

  // Now marker
  const nowFrac = (nowH - Math.floor(nowH));
  const nowI = Math.min(slots.length - 1, 0);  // current hour is slot 0
  const nowX = toX(0);

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={H} preserveAspectRatio="none" style={{ display: 'block' }}>
      <defs>
        <linearGradient id="pvArea" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={T.amber} stopOpacity="0.35"/>
          <stop offset="100%" stopColor={T.amber} stopOpacity="0"/>
        </linearGradient>
      </defs>

      {/* Day divider */}
      <line x1={divX} y1={0} x2={divX} y2={H} stroke={T.border} strokeWidth="1"/>
      <text x={divX + 6} y={14} fontSize="9" fill={T.textMuted} style={{ fontFamily: T.fontMono }}>{t('forecast.tomorrowLabel')}</text>

      {/* Horizontal reference lines */}
      {[maxPv * 0.5, maxPv * 0.25].map((v, i) => (
        <line key={i} x1={0} y1={toY(v)} x2={W} y2={toY(v)}
              stroke={T.borderSubtle} strokeDasharray="2 4"/>
      ))}

      {/* Confidence band */}
      <path d={confPath} fill={T.amber} fillOpacity="0.12"/>

      {/* Area fill */}
      <path d={meanPath + ` L${W} ${H} L0 ${H} Z`} fill="url(#pvArea)"/>

      {/* Mean line */}
      <path d={meanPath} fill="none" stroke={T.amber} strokeWidth="2.2" strokeLinecap="round"/>

      {/* NOW marker */}
      <line x1={nowX} y1={0} x2={nowX} y2={H} stroke={T.textPrimary} strokeOpacity="0.3" strokeWidth="1"/>
      <circle cx={nowX} cy={toY(slots[0].pvMean)} r="4" fill={T.amber}/>
    </svg>
  );
}

// ── Tariff strip: extended to 48h ─────────────────────────────────────────
function TariffForecastStrip({ slots, nowH }) {
  const { t } = useLocale();
  const max = Math.max(...slots.map(s => s.price));
  const min = Math.min(...slots.map(s => s.price));
  const todaySlots = slots.filter(s => s.dayOffset === 0).length;

  const d = barDensity(slots.length);

  return (
    <div style={{ position: 'relative' }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', gap: d.gap, height: 80 }}>
        {slots.map((slot, i) => {
          const h = 8 + ((slot.price - min) / (max - min)) * 68;
          const isNow = i === 0;
          const tc = TIER_COLOR[slot.tier];
          const isDivider = i === todaySlots;
          return (
            <React.Fragment key={i}>
              {isDivider && (
                <div style={{ width: 1, height: 80, background: T.border, flexShrink: 0 }}/>
              )}
              <div style={{
                flex: 1, height: h,
                background: isNow ? tc : `${tc}55`,
                borderRadius: d.radius,
                boxShadow: isNow ? `0 0 14px ${tc}` : 'none',
                transition: 'all 160ms',
              }}/>
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
}

// ── Time axis (shared) ─────────────────────────────────────────────────────
function ForecastTimeAxis({ slots, nowH }) {
  const { t } = useLocale();
  const todayCount = slots.filter(s => s.dayOffset === 0).length;
  const tomorrowCount = slots.length - todayCount;
  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: `${todayCount}fr 1fr ${Math.max(1, tomorrowCount - 1)}fr`,
      marginTop: 6, fontFamily: T.fontMono, fontSize: 10, color: T.textMuted,
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between' }}>
        <span>{t('forecast.axisNow')}</span>
        <span>{String(Math.floor(nowH + 6)).padStart(2,'0')}:00</span>
        <span>{String(Math.floor(nowH + 12)).padStart(2,'0')}:00</span>
      </div>
      <div style={{ textAlign: 'center', color: T.textSecondary, fontSize: 9, fontWeight: 600, letterSpacing: 0.5, textTransform: 'uppercase', whiteSpace: 'nowrap', padding: '0 8px' }}>
        {t('forecast.axisTomorrow')}
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between' }}>
        <span>00:00</span>
        <span>12:00</span>
        <span>23:00</span>
      </div>
    </div>
  );
}

// ── Tariff min/max badge ───────────────────────────────────────────────────
function TariffMinMaxBadge({ slots }) {
  const { t } = useLocale();
  const prices = slots.map(s => s.price);
  const min = Math.min(...prices);
  const max = Math.max(...prices);
  const avg = Math.round(prices.reduce((a,b) => a+b, 0) / prices.length);
  return (
    <div style={{ display: 'flex', gap: 16, fontSize: 12, color: T.textMuted, flexShrink: 0 }}>
      <span>{t('forecast.min')} <strong style={{ color: T.green, fontFamily: T.fontMono }}>{min} gr</strong></span>
      <span>{t('forecast.avg')} <strong style={{ color: T.blue, fontFamily: T.fontMono }}>{avg} gr</strong></span>
      <span>{t('forecast.max')} <strong style={{ color: T.red, fontFamily: T.fontMono }}>{max} gr</strong></span>
    </div>
  );
}

// ── Tier legend ────────────────────────────────────────────────────────────
function TierLegend() {
  const { t } = useLocale();
  return (
    <div style={{ display: 'flex', gap: 18, marginTop: 12, fontSize: 11, color: T.textMuted }}>
      {[['cheap', t('forecast.tierCheap'),'< 50 gr'],['standard', t('forecast.tierStd'),'50–95 gr'],['peak', t('forecast.tierPeak'),'95–130 gr'],['high', t('forecast.tierHigh'),'> 130 gr']].map(([k, l, r]) => (
        <span key={k} style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
          <span style={{ width: 10, height: 10, borderRadius: 3, background: TIER_COLOR[k], display: 'inline-block' }}/>
          {l} <span style={{ color: T.textMuted, fontSize: 10 }}>{r}</span>
        </span>
      ))}
    </div>
  );
}

Object.assign(window, { V2Forecast, PVForecastChart, TariffForecastStrip, ForecastTimeAxis, TariffMinMaxBadge, TierLegend, WeatherSolarStrip, GridHealthCard });

// ── Weather & Solar strip ──────────────────────────────────────────────────
// Deterministic stub data — mirrors Open-Meteo /forecast + Forecast.Solar
// response shapes already used by pv_forecast_cache.py. Kept static so the
// numbers don't flicker across scenario swaps.
function WeatherSolarStrip({ s, pvToday, pvTomorrow }) {
  const { t } = useLocale();
  // Warszawa-ish early spring afternoon
  const tiles = [
    {
      label: t('weather.now'),
      icon: 'thermometer',
      color: T.textPrimary,
      value: '11.1',
      unit: '°C',
      sub: t('weather.mostlyClear', { pct: 60 }),
    },
    {
      label: t('weather.today'),
      icon: 'cloud-sun',
      color: T.textPrimary,
      value: '1° / 13°',
      unit: '',
      sub: t('weather.overcast'),
      chip: t('weather.dry'),
    },
    {
      label: t('weather.tomorrow'),
      icon: 'cloud-rain',
      color: T.textPrimary,
      value: '5° / 12°',
      unit: '',
      sub: t('weather.overcast'),
      chip: t('weather.dry'),
    },
    {
      label: t('weather.irradiance'),
      icon: 'sun',
      color: T.amber,
      value: '215',
      unit: 'W/m²',
      sub: t('weather.peak', { w: '1181' }),
    },
    {
      label: t('weather.pvToday'),
      icon: 'sun',
      color: T.amber,
      value: pvToday,
      unit: 'kWh',
      sub: null,
    },
    {
      label: t('weather.pvTomorrow'),
      icon: 'sun',
      color: T.amber,
      value: pvTomorrow,
      unit: 'kWh',
      sub: null,
      dim: true,
    },
  ];

  return (
    <div style={{ marginBottom: 18 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
        <LI name="cloud" size={14} color={T.textSecondary}/>
        <span style={{
          fontFamily: T.fontUI, fontWeight: 600, fontSize: 13,
          color: T.textPrimary, letterSpacing: 0.2,
        }}>{t('weather.title')}</span>
        <span style={{ marginLeft: 'auto', fontSize: 10, color: T.textMuted, fontFamily: T.fontMono }}>
          {t('weather.source')}
        </span>
      </div>
      <div style={{
        display: 'grid',
        gridTemplateColumns: 'repeat(6, minmax(0, 1fr))',
        gap: 10,
      }}>
        {tiles.map((tile, i) => (
          <WSTile key={i} {...tile}/>
        ))}
      </div>
    </div>
  );
}

function WSTile({ label, icon, color, value, unit, sub, chip, dim }) {
  return (
    <div style={{
      background: T.surface,
      border: `1px solid ${T.border}`,
      borderRadius: 12,
      padding: '12px 14px',
      opacity: dim ? 0.65 : 1,
      minHeight: 92,
      display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
        <LI name={icon} size={12} color={color === T.textPrimary ? T.textMuted : color}/>
        <span style={{
          fontSize: 9, fontWeight: 700, letterSpacing: 1.1,
          textTransform: 'uppercase', color: T.textMuted,
        }}>{label}</span>
      </div>
      <div>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 5, flexWrap: 'wrap' }}>
          <span style={{
            fontFamily: T.fontMono, fontSize: 20, fontWeight: 700,
            color, fontVariantNumeric: 'tabular-nums', letterSpacing: -0.5,
          }}>{value}</span>
          {unit && <span style={{ fontSize: 11, color: T.textMuted }}>{unit}</span>}
        </div>
        {(sub || chip) && (
          <div style={{ marginTop: 5, display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
            {sub && <span style={{ fontSize: 10, color: T.textMuted, lineHeight: 1.3 }}>{sub}</span>}
            {chip && (
              <span style={{
                fontSize: 9, fontWeight: 700,
                color: T.green, background: `${T.green}1C`,
                border: `1px solid ${T.green}33`,
                padding: '1px 6px', borderRadius: 4, letterSpacing: 0.3,
              }}>{chip}</span>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

// ── Grid Health card ───────────────────────────────────────────────────────
// Stub data mirrors ENTSO-E transparency API shape. Numbers picked to match
// a typical Polish weekday afternoon — renewable share mid, coal dominant.
const GRID_HEALTH = {
  carbonGpkwh: 141,
  carbonTier: 'low',   // low < 200, mid 200-400, high > 400
  renewablePct: 50,
  gridLoadMw: 21575,
  windPct: 14,
  solarPct: 35,
  // Generation mix percentages — sum ≈ 100
  mix: [
    { key: 'other',   pct: 39.8, color: '#8A93A8' },  // coal & other
    { key: 'solar',   pct: 35.1, color: T.amber },
    { key: 'wind',    pct: 14.3, color: T.blue },
    { key: 'gas',     pct: 7.9,  color: T.orange },
    { key: 'biomass', pct: 1.6,  color: T.violet },
    { key: 'oil',     pct: 0.7,  color: '#D07070' },
    { key: 'hydro',   pct: 0.5,  color: T.green },
  ],
};

function GridHealthCard() {
  const { t } = useLocale();
  const g = GRID_HEALTH;
  const tierLabel =
    g.carbonTier === 'low'  ? t('grid.co2Low')  :
    g.carbonTier === 'mid'  ? t('grid.co2Mid')  :
                              t('grid.co2High');
  const tierColor =
    g.carbonTier === 'low'  ? T.green :
    g.carbonTier === 'mid'  ? T.amber :
                              T.red;

  return (
    <Surface style={{ marginBottom: 18 }}>
      {/* Header row */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16 }}>
        <LI name="activity" size={14} color={T.textSecondary}/>
        <SurfaceLabel style={{ fontSize: 11 }}>{t('grid.title')}</SurfaceLabel>
        <span style={{
          fontSize: 9, fontWeight: 700, letterSpacing: 0.8, textTransform: 'uppercase',
          color: T.textSecondary, background: T.raised,
          border: `1px solid ${T.border}`,
          padding: '3px 8px', borderRadius: 4,
        }}>{t('grid.weekday')}</span>
        <span style={{ marginLeft: 'auto', fontSize: 10, color: T.textMuted, fontFamily: T.fontMono }}>
          {t('grid.source', { time: '14:30' })}
        </span>
      </div>

      {/* Carbon hero row */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 14, marginBottom: 16,
        paddingBottom: 16, borderBottom: `1px solid ${T.border}`,
      }}>
        <div style={{ flex: 1 }}>
          <SurfaceLabel style={{ fontSize: 9, marginBottom: 6 }}>{t('grid.carbonIntensity')}</SurfaceLabel>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 5 }}>
            <span style={{
              fontFamily: T.fontMono, fontSize: 30, fontWeight: 700,
              color: tierColor, fontVariantNumeric: 'tabular-nums', letterSpacing: -0.8,
            }}>{g.carbonGpkwh}</span>
            <span style={{ fontSize: 12, color: T.textMuted }}>g/kWh</span>
          </div>
        </div>
        <span style={{
          fontSize: 10, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.8,
          color: tierColor, background: `${tierColor}1C`,
          border: `1px solid ${tierColor}40`,
          padding: '5px 12px', borderRadius: 999,
        }}>{tierLabel}</span>
      </div>

      {/* Stats grid */}
      <div style={{
        display: 'grid', gridTemplateColumns: '1fr 1fr',
        gap: '14px 32px', marginBottom: 20,
      }}>
        <GHStat label={t('grid.renewable')} value={`${g.renewablePct}`} unit="%" color={T.green}/>
        <GHStat label={t('grid.load')} value={g.gridLoadMw.toLocaleString('en-US').replace(/,/g, ',')} unit="MW" color={T.textPrimary}/>
        <GHStat label={t('grid.wind')} value={`${g.windPct}`} unit="%" color={T.blue}/>
        <GHStat label={t('grid.solar')} value={`${g.solarPct}`} unit="%" color={T.amber}/>
      </div>

      {/* Generation mix */}
      <SurfaceLabel style={{ fontSize: 9, marginBottom: 10 }}>{t('grid.genMix')}</SurfaceLabel>
      <GenMixStack mix={g.mix}/>
      <GenMixLegend mix={g.mix} t={t}/>
    </Surface>
  );
}

function GHStat({ label, value, unit, color }) {
  return (
    <div>
      <div style={{
        fontSize: 9, fontWeight: 700, letterSpacing: 1, textTransform: 'uppercase',
        color: T.textMuted, marginBottom: 4,
      }}>{label}</div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 4 }}>
        <span style={{
          fontFamily: T.fontMono, fontSize: 18, fontWeight: 700,
          color, fontVariantNumeric: 'tabular-nums', letterSpacing: -0.3,
        }}>{value}</span>
        <span style={{ fontSize: 11, color: T.textMuted }}>{unit}</span>
      </div>
    </div>
  );
}

function GenMixStack({ mix }) {
  return (
    <div style={{
      display: 'flex', height: 12, borderRadius: 4,
      overflow: 'hidden', background: T.raised, marginBottom: 14,
    }}>
      {mix.map(m => (
        <div key={m.key} style={{
          width: `${m.pct}%`,
          background: m.color,
        }}/>
      ))}
    </div>
  );
}

function GenMixLegend({ mix, t }) {
  const max = Math.max(...mix.map(m => m.pct));
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      {mix.map(m => (
        <div key={m.key} style={{
          display: 'grid',
          gridTemplateColumns: '112px 1fr 56px',
          alignItems: 'center', gap: 10,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span style={{
              width: 10, height: 10, borderRadius: 3,
              background: m.color, flexShrink: 0,
            }}/>
            <span style={{ fontSize: 11, color: T.textSecondary }}>
              {t(`grid.mix.${m.key}`)}
            </span>
          </div>
          <div style={{ height: 4, background: T.raised, borderRadius: 2, overflow: 'hidden' }}>
            <div style={{
              width: `${(m.pct / max) * 100}%`, height: '100%',
              background: m.color, borderRadius: 2,
            }}/>
          </div>
          <span style={{
            fontFamily: T.fontMono, fontSize: 11, fontWeight: 600,
            color: T.textSecondary, fontVariantNumeric: 'tabular-nums',
            textAlign: 'right',
          }}>{m.pct.toFixed(1)}%</span>
        </div>
      ))}
    </div>
  );
}
