/* global React, ReactDOM */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

// =============================================================
// Globe — wraps the cobe WebGL library
// =============================================================
function Globe({ markers, theme, focusLng }) {
  const canvasRef = useRef(null);
  const pointerInteracting = useRef(null);
  const pointerInteractionMovement = useRef(0);
  const phiRef = useRef(0);
  const targetPhiRef = useRef(0);
  const widthRef = useRef(0);
  const themeRef = useRef(theme);
  themeRef.current = theme;

  // When focus changes (user picks a country), set a new target phi.
  // The render loop will lerp toward it then resume normal drift.
  useEffect(() => {
    if (focusLng == null) return;
    // Cobe phi: rotating positively shifts the view east. We want the focused longitude
    // to be 'facing' the viewer, so target = -lng * (π/180).
    const target = -focusLng * (Math.PI / 180);
    // Snap target close to current phi (mod 2π) so we take the shortest path.
    const TWO_PI = Math.PI * 2;
    const cur = phiRef.current;
    const base = Math.round(cur / TWO_PI) * TWO_PI;
    let candidate = base + target;
    if (candidate - cur > Math.PI) candidate -= TWO_PI;
    if (cur - candidate > Math.PI) candidate += TWO_PI;
    targetPhiRef.current = candidate;
  }, [focusLng]);

  useEffect(() => {
    let globe = null;
    let frame = 0;
    let active = true;

    function init() {
      if (!window.createGlobe) {
        frame = requestAnimationFrame(init);
        return;
      }
      if (!canvasRef.current || !active) return;

      const onResize = () => {
        if (canvasRef.current) widthRef.current = canvasRef.current.offsetWidth;
      };
      window.addEventListener('resize', onResize);
      onResize();

      globe = window.createGlobe(canvasRef.current, {
        devicePixelRatio: 2,
        width: widthRef.current * 2,
        height: widthRef.current * 2,
        phi: 0,
        theta: 0.25,
        dark: 1,
        diffuse: 1.2,
        mapSamples: 16000,
        mapBrightness: 6,
        baseColor: themeRef.current.base,
        markerColor: themeRef.current.marker,
        glowColor: themeRef.current.glow,
        markers,
        onRender: (state) => {
          const target = targetPhiRef.current;
          if (!pointerInteracting.current) {
            // Lerp toward target (snappy when far, gentle when close)
            const delta = target - phiRef.current;
            phiRef.current += delta * 0.06;
            // Keep the target slowly drifting so the globe keeps spinning
            targetPhiRef.current += 0.003;
          }
          state.phi = phiRef.current + pointerInteractionMovement.current / 200;
          state.width = widthRef.current * 2;
          state.height = widthRef.current * 2;
        }
      });

      // Fade in
      setTimeout(() => {
        if (canvasRef.current) canvasRef.current.style.opacity = '1';
      }, 80);

      // cleanup attached via closure
      Globe.__cleanup = () => {
        window.removeEventListener('resize', onResize);
        if (globe) globe.destroy();
      };
    }

    init();

    return () => {
      active = false;
      cancelAnimationFrame(frame);
      if (Globe.__cleanup) {
        Globe.__cleanup();
        Globe.__cleanup = null;
      }
    };
  }, [markers]);

  return (
    <div className="globe-wrap">
      <canvas
        ref={canvasRef}
        className="globe-canvas"
        onPointerDown={(e) => {
          pointerInteracting.current = e.clientX - pointerInteractionMovement.current;
          canvasRef.current.style.cursor = 'grabbing';
        }}
        onPointerUp={() => {
          pointerInteracting.current = null;
          canvasRef.current.style.cursor = 'grab';
        }}
        onPointerOut={() => {
          pointerInteracting.current = null;
          if (canvasRef.current) canvasRef.current.style.cursor = 'grab';
        }}
        onMouseMove={(e) => {
          if (pointerInteracting.current !== null) {
            const delta = e.clientX - pointerInteracting.current;
            pointerInteractionMovement.current = delta;
          }
        }}
        onTouchMove={(e) => {
          if (pointerInteracting.current !== null && e.touches[0]) {
            const delta = e.touches[0].clientX - pointerInteracting.current;
            pointerInteractionMovement.current = delta;
          }
        }} />
      
    </div>);

}

// =============================================================
// Helpers
// =============================================================
function fmt(n, digits = 2) {
  if (n === '' || n === null || n === undefined || Number.isNaN(n)) return '—';
  if (!Number.isFinite(n)) return '∞';
  if (n === 0) return '0';
  const abs = Math.abs(n);
  if (abs >= 1000) return n.toLocaleString(undefined, { maximumFractionDigits: 0 });
  if (abs >= 10) return n.toLocaleString(undefined, { maximumFractionDigits: 1 });
  return n.toLocaleString(undefined, { maximumFractionDigits: digits });
}

function parseNum(v) {
  if (v === '' || v === null || v === undefined) return null;
  const n = parseFloat(v);
  return Number.isFinite(n) ? n : null;
}

// =============================================================
// Number Field — large tappable input
// =============================================================
function Field({ label, sub, unit, value, onChange, accent, placeholder, hint, locked }) {
  return (
    <label className={"field" + (locked ? " field--locked" : "") + (accent ? " field--accent" : "")}>
      <div className="field-head">
        <span className="field-label">{label}</span>
        {sub ? <span className="field-sub">{sub}</span> : null}
      </div>
      <div className="field-body">
        <input
          className="field-input"
          type="text"
          inputMode="decimal"
          value={value}
          placeholder={placeholder || '0'}
          onChange={(e) => {
            const v = e.target.value.replace(/[^0-9.]/g, '');
            onChange(v);
          }} />
        
        <span className="field-unit">{unit}</span>
      </div>
      {hint ? <div className="field-hint">{hint}</div> : null}
    </label>);

}

// =============================================================
// Preset chip
// =============================================================
function Preset({ label, onClick, active }) {
  return (
    <button className={"preset" + (active ? " preset--active" : "")} onClick={onClick}>
      {label}
    </button>);

}

// =============================================================
// App
// =============================================================
function App() {
  // ---- Country / region preference ----
  const [countryCode, setCountryCode] = useState(() => {
    try {
      return localStorage.getItem('voltflow.country') || null;
    } catch (e) {
      return null;
    }
  });
  const [pickerOpen, setPickerOpen] = useState(false);
  const country = window.findCountry(countryCode || 'US');
  const firstRun = !countryCode;

  // ---- Language preference (null = auto from country) ----
  const [languageOverride, setLanguageOverride] = useState(() => {
    try {
      return localStorage.getItem('voltflow.lang') || null;
    } catch (e) {
      return null;
    }
  });
  const lang = languageOverride || window.defaultLangFor(country.code) || 'en';
  // Translation shortcut bound to current language.
  const t = (key, ...args) => window.translate(lang, key, ...args);
  const setLang = (code) => {
    setLanguageOverride(code);
    try {
      if (code) localStorage.setItem('voltflow.lang', code);else
      localStorage.removeItem('voltflow.lang');
    } catch (e) {}
  };

  // Live inputs — stored as strings to allow empty.
  // On boot, read saved country (if any) and use its voltage/rate as the starting numbers.
  const savedCode = (() => {try {return localStorage.getItem('voltflow.country');} catch (e) {return null;}})();
  const bootCountry = window.findCountry(savedCode || 'US');
  const [volts, setVolts] = useState(String(bootCountry.voltage));
  const [amps, setAmps] = useState('7');
  const [hours, setHours] = useState('8');
  const [rate, setRate] = useState(String(bootCountry.rate));
  const [carBattery, setCarBattery] = useState('60'); // kWh

  // Solar panel sizing — country-aware default (grid-tied scenario starts at country voltage)
  const [solarW, setSolarW] = useState('400');
  const [solarV, setSolarV] = useState(String(bootCountry.voltage));
  const [solarHours, setSolarHours] = useState('5');

  // ---- Phase (1‑phase vs 3‑phase electrical supply) ----
  // 1-phase: P = V × A
  // 3-phase: P = √3 × V_line × A   (assuming power factor = 1)
  const SQRT3 = Math.sqrt(3);
  const [phase, setPhase] = useState('1');
  const phaseFactor = phase === '3' ? SQRT3 : 1;

  // When user switches phase, jump voltage to the country's typical for that phase.
  // Only auto-overwrite if the current value matches the *other* phase's default (so we don't
  // clobber a user-edited value).
  const switchPhase = (newPhase) => {
    const current = parseNum(volts);
    const otherDefault = newPhase === '3' ? country.voltage : country.voltage3p;
    const nextDefault = newPhase === '3' ? country.voltage3p : country.voltage;
    if (current === otherDefault) setVolts(String(nextDefault));
    setPhase(newPhase);
  };

  // Solar panel sizing — independent calculator
  // (solar inputs already declared above near boot defaults)

  // Apply a country: update volts, rate, solarV, persist
  const applyCountry = (c) => {
    // Only overwrite volts if currently matches the old country defaults (don't clobber edits)
    setCountryCode(c.code);
    setVolts((cur) => {
      const n = parseNum(cur);
      // overwrite if current matches old country's voltage/voltage3p
      if (n === country.voltage || n === country.voltage3p) {
        return String(phase === '3' ? c.voltage3p : c.voltage);
      }
      return cur;
    });
    setRate(String(c.rate));
    // Solar voltage follows country too (matches user's bill comment)
    setSolarV((cur) => {
      const n = parseNum(cur);
      if (n === country.voltage || n === country.voltage3p) {
        return String(solarPhase === '3' ? c.voltage3p : c.voltage);
      }
      return cur;
    });
    try {localStorage.setItem('voltflow.country', c.code);} catch (e) {}
    setPickerOpen(false);
  };

  // Auto-open picker on first run
  useEffect(() => {
    if (firstRun) setPickerOpen(true);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Which two electrical quantities the user is driving — the third is computed.
  // 'va' = V and A are inputs → W computed
  // 'vw' = V and W are inputs → A computed
  // 'aw' = A and W are inputs → V computed
  const [mode, setMode] = useState('va');
  const [wattsInput, setWattsInput] = useState('1540');

  // Derived values
  const V = parseNum(volts);
  const A = parseNum(amps);
  const Win = parseNum(wattsInput);
  const H = parseNum(hours);
  const R = parseNum(rate);
  const BAT = parseNum(carBattery);

  let watts = null;
  let computedV = V;
  let computedA = A;
  if (mode === 'va') {
    watts = V != null && A != null ? V * A * phaseFactor : null;
  } else if (mode === 'vw') {
    watts = Win;
    computedA = V != null && Win != null && V !== 0 ? Win / (V * phaseFactor) : null;
  } else if (mode === 'aw') {
    watts = Win;
    computedV = A != null && Win != null && A !== 0 ? Win / (A * phaseFactor) : null;
  }

  const kW = watts != null ? watts / 1000 : null;
  const kWh = kW != null && H != null ? kW * H : null;
  const cost = kWh != null && R != null ? kWh * R : null;
  const fullChargeHours = kW != null && BAT != null && kW > 0 ? BAT / kW : null;

  // Solar derived — also affected by phase (3-phase inverters output √3 × V × A)
  const [solarPhase, setSolarPhase] = useState('1');
  const solarPhaseFactor = solarPhase === '3' ? SQRT3 : 1;
  // When the solar phase toggles, swap the system voltage to the country's typical for that phase
  // (only if currently matching the *other* phase's default — don't clobber user edits).
  const switchSolarPhase = (newPhase) => {
    const current = parseNum(solarV);
    const otherDefault = newPhase === '3' ? country.voltage : country.voltage3p;
    const nextDefault = newPhase === '3' ? country.voltage3p : country.voltage;
    if (current === otherDefault) setSolarV(String(nextDefault));
    setSolarPhase(newPhase);
  };
  const sW = parseNum(solarW);
  const sV = parseNum(solarV);
  const sH = parseNum(solarHours);
  const solarAmps = sW != null && sV != null && sV > 0 ? sW / (sV * solarPhaseFactor) : null;
  const solarDailyKWh = sW != null && sH != null ? sW * sH / 1000 : null;
  const solarDaysToCharge =
  solarDailyKWh != null && BAT != null && solarDailyKWh > 0 ? BAT / solarDailyKWh : null;

  // Preset appliances — wattage-based. Amps are computed from the user's
  // country voltage so the same preset says "32 A" in Thailand (220 V) and
  // "60 A" in Japan (100 V).
  const presetsByPhase = {
    '1': [
      { id: 'ac-9k',  label: t('preset.ac9k.name'),  sub: t('preset.ac9k.sub'),  w: 900 },
      { id: 'ac-12k', label: t('preset.ac12k.name'), sub: t('preset.ac12k.sub'), w: 1200 },
      { id: 'ac-24k', label: t('preset.ac24k.name'), sub: t('preset.ac24k.sub'), w: 2400 },
      { id: 'ev',     label: t('preset.ev.name'),    sub: t('preset.ev.sub'),    w: 7000 },
      { id: 'oven',   label: t('preset.oven.name'),  sub: t('preset.oven.sub'),  w: 2400 },
      { id: 'pump',   label: t('preset.pump.name'),  sub: t('preset.pump.sub'),  w: 750 },
      { id: 'iron',   label: t('preset.iron.name'),  sub: t('preset.iron.sub'),  w: 1200 },
    ],
    '3': [
      { id: 'ev-11',  label: t('preset.ev11.name'),  sub: t('preset.ev11.sub'),  w: 11000 },
      { id: 'ev-22',  label: t('preset.ev22.name'),  sub: t('preset.ev22.sub'),  w: 22000 },
      { id: 'ev-43',  label: t('preset.ev43.name'),  sub: t('preset.ev43.sub'),  w: 43000 },
      { id: 'ac-cen', label: t('preset.accen.name'), sub: t('preset.accen.sub'), w: 7000 },
      { id: 'oven-i', label: t('preset.ovenI.name'), sub: t('preset.ovenI.sub'), w: 7000 },
      { id: 'pump-i', label: t('preset.pumpI.name'), sub: t('preset.pumpI.sub'), w: 2200 },
    ],
  };
  const baseV = phase === '3' ? country.voltage3p : country.voltage;
  const presets = presetsByPhase[phase].map((p) => ({
    ...p,
    v: baseV,
    a: Math.round((p.w / (baseV * phaseFactor)) * 100) / 100,
  }));
  const applyPreset = (p) => {
    setMode('va');
    setVolts(String(p.v));
    setAmps(String(p.a));
  };
  const activePreset = presets.find(
    (p) => mode === 'va' && parseNum(volts) === p.v && parseNum(amps) === p.a
  );

  // Globe markers — base set of world cities + highlight for selected country
  const markers = useMemo(
    () => {
      const base = [
      { location: [37.7595, -122.4367], size: 0.03 }, // SF
      { location: [40.7128, -74.006], size: 0.03 }, // NY
      { location: [51.5072, -0.1276], size: 0.03 }, // London
      { location: [52.52, 13.405], size: 0.03 }, // Berlin
      { location: [35.6762, 139.6503], size: 0.03 }, // Tokyo
      { location: [31.2304, 121.4737], size: 0.03 }, // Shanghai
      { location: [-33.8688, 151.2093], size: 0.03 }, // Sydney
      { location: [19.4326, -99.1332], size: 0.03 }, // CDMX
      { location: [28.6139, 77.209], size: 0.03 }, // Delhi
      { location: [-23.5505, -46.6333], size: 0.03 }, // São Paulo
      { location: [55.7558, 37.6173], size: 0.03 }, // Moscow
      { location: [1.3521, 103.8198], size: 0.03 } // Singapore
      ];
      if (country.lat != null && country.lng != null) {
        // Big bright marker for the user's country
        base.push({ location: [country.lat, country.lng], size: 0.12 });
      }
      return base;
    },
    [country.code, country.lat, country.lng]
  );

  // Theme
  const theme = useMemo(
    () => ({
      base: [0.35, 0.35, 0.55],
      marker: [0.96, 0.85, 0.4],
      glow: [0.55, 0.45, 1.0]
    }),
    []
  );

  // Equation strip — shows the active math sentence in plain English
  const equation = useMemo(() => {
    const sqrt3 = <span className="var var--mul">√3</span>;
    if (mode === 'va') {
      return (
        <>
          {phase === '3' ? <>{sqrt3} × </> : null}
          <Var>{fmt(V)}</Var> volts × <Var>{fmt(A)}</Var> amps ={' '}
          <Var hi>{fmt(watts)}</Var> watts
        </>);

    }
    if (mode === 'vw') {
      return (
        <>
          <Var>{fmt(Win)}</Var> watts ÷ <Var>{fmt(V)}</Var> volts
          {phase === '3' ? <> ÷ {sqrt3}</> : null}
          {' '}= <Var hi>{fmt(computedA)}</Var> amps
        </>);

    }
    return (
      <>
        <Var>{fmt(Win)}</Var> watts ÷ <Var>{fmt(A)}</Var> amps
        {phase === '3' ? <> ÷ {sqrt3}</> : null}
        {' '}= <Var hi>{fmt(computedV)}</Var> volts
      </>);

  }, [mode, phase, V, A, Win, watts, computedA, computedV]);

  return (
    <div className="app">
      <div className="bg-glow" aria-hidden="true" />

      {/* Floating globe — background accent */}
      <div className="globe-bg" aria-hidden="true">
        <Globe markers={markers} theme={theme} focusLng={country.lng} />
      </div>

      {/* Country picker modal */}
      <window.CountryPicker
        open={pickerOpen}
        firstRun={firstRun}
        currentCode={countryCode}
        onSelect={applyCountry}
        onClose={() => setPickerOpen(false)}
        lang={lang}
        languageOverride={languageOverride}
        onLanguageChange={setLang}
        autoLangFor={window.defaultLangFor} />
      

      {/* Header */}
      <header className="hdr">
        <div className="hdr-mark">
          <span className="hdr-dot" />
          <span className="hdr-name">{t('app.name')}</span>
        </div>
        <window.CountryChip country={country} onClick={() => setPickerOpen(true)} lang={lang} />
      </header>

      {/* Equation hero — compact, no globe */}
      <section className="hero hero--compact">
        <h1 className="hero-title">
          {t('hero.line1')}<br />
          <span>{t('hero.line2')}</span>
        </h1>
        <div className="hero-eq">
          <div className="hero-eq-line">{equation}</div>
          <div className="hero-eq-cap">
            {t('hero.power')} <b>{fmt(kW)}</b> kW
            {kWh != null ? <>  ·  {t('hero.total', fmt(H), fmt(kWh))}</> : null}
          </div>
        </div>
      </section>

      {/* Mode switcher */}
      <section className="card">
        <div className="card-head">
          <h2>{t('mode.title')}</h2>
          <p>{t('mode.sub')}</p>
        </div>

        {/* Phase selector */}
        <PhaseSelector phase={phase} onChange={switchPhase} country={country} t={t} />

        <div className="seg">
          <SegBtn active={mode === 'va'} onClick={() => setMode('va')}>
            <em>V × A</em>
            <span>{t('mode.find.watts')}</span>
          </SegBtn>
          <SegBtn active={mode === 'vw'} onClick={() => setMode('vw')}>
            <em>W ÷ V</em>
            <span>{t('mode.find.amps')}</span>
          </SegBtn>
          <SegBtn active={mode === 'aw'} onClick={() => setMode('aw')}>
            <em>W ÷ A</em>
            <span>{t('mode.find.volts')}</span>
          </SegBtn>
        </div>

        <div className="grid grid--core">
          {mode !== 'aw' &&
          <Field
            label={t('field.voltage')}
            sub={phase === '3' ? t('field.voltage.sub.line') : t('field.voltage.sub.pressure')}
            unit="V"
            value={volts}
            onChange={setVolts}
            hint={phase === '3' ? t('field.voltage.hint.3p', country) : t('field.voltage.hint.1p', country)} />

          }
          {mode === 'aw' &&
          <Field label={t('field.voltage')} sub={t('field.voltage.sub.computed')} unit="V" value={fmt(computedV)} onChange={() => {}} locked accent />
          }

          {mode !== 'vw' &&
          <Field
            label={t('field.current')}
            sub={t('field.current.sub.flow')}
            unit="A"
            value={amps}
            onChange={setAmps}
            hint={t('field.current.hint')} />

          }
          {mode === 'vw' &&
          <Field label={t('field.current')} sub={t('field.current.sub.computed')} unit="A" value={fmt(computedA)} onChange={() => {}} locked accent />
          }

          {mode === 'va' &&
          <Field
            label={t('field.power')}
            sub={t('field.power.sub.computed')}
            unit="W"
            value={fmt(watts)}
            onChange={() => {}}
            locked
            accent
            hint={t('field.power.hint.kw')} />

          }
          {mode !== 'va' &&
          <Field
            label={t('field.power')}
            sub={t('field.power.sub.watts')}
            unit="W"
            value={wattsInput}
            onChange={setWattsInput}
            hint={t('field.power.hint.label')} data-comment-anchor="dc85ef3d57-input-169-9" />

          }
        </div>

        {/* Presets */}
        <div className="presets" data-comment-anchor="949054ca0b-div-572-9">
          <div className="presets-label">{t('presets.label')}</div>
          <div className="presets-row">
            {presets.map((p) =>
            <Preset
              key={p.id}
              active={activePreset && activePreset.id === p.id}
              onClick={() => applyPreset(p)}
              label={
              <>
                    <span className="preset-name">{p.label}</span>
                    <span className="preset-sub">{p.sub}</span>
                    <span className="preset-vals">
                      {p.v}V · {p.a}A
                    </span>
                  </>
              } />

            )}
          </div>
        </div>
      </section>

      {/* Energy & cost */}
      <section className="card">
        <div className="card-head">
          <h2>{t('energy.title')}</h2>
          <p>{t('energy.sub', t('energy.kwh'))}</p>
        </div>

        <div className="grid grid--time">
          <Field
            label={t('field.time')}
            sub={t('field.time.sub')}
            unit={t('field.time.unit')}
            value={hours}
            onChange={setHours} />
          
          <Field
            label={t('field.rate')}
            sub={t('field.rate.sub', country.currency)}
            unit={`${country.symbol}/kWh`}
            value={rate}
            onChange={setRate}
            hint={t('field.rate.hint', country)} />
          
        </div>

        <div className="results">
          <ResultCell big label={t('result.energy')} value={fmt(kWh)} unit="kWh" tone="primary" />
          <ResultCell label={t('result.cost')} value={window.formatMoney(cost, country)} unit="" tone="ok" />
          <ResultCell
            label={t('result.power')}
            value={fmt(kW)}
            unit="kW"
            tone="muted"
            note={watts != null ? fmt(watts) + ' W' : null} />
          
        </div>
      </section>

      {/* EV-specific */}
      <section className="card">
        <div className="card-head">
          <h2>{t('ev.title')}</h2>
          <p>{t('ev.sub')}</p>
        </div>
        <div className="grid grid--ev">
          <Field
            label={t('field.battery')}
            sub={t('field.battery.sub')}
            unit="kWh"
            value={carBattery}
            onChange={setCarBattery}
            hint={t('field.battery.hint')} />
          
          <div className="ev-out">
            <div className="ev-out-label">{t('ev.full')}</div>
            <div className="ev-out-value">
              <span>{fmt(fullChargeHours, 1)}</span>
              <small>{t('ev.unit')}</small>
            </div>
            <div className="ev-out-sub">
              {fullChargeHours != null && Number.isFinite(fullChargeHours) ?
              t('ev.roughly', formatHM(fullChargeHours), fmt(kW)) :
              t('ev.empty')}
            </div>
          </div>
        </div>
      </section>

      {/* Solar */}
      <section className="card card--solar">
        <div className="card-head">
          <h2>
            <span className="sun" aria-hidden="true">☀</span> {t('solar.title')}
          </h2>
          <p>{t('solar.sub')}</p>
        </div>

        <PhaseSelector phase={solarPhase} onChange={switchSolarPhase} country={country} compact t={t} />

        <div className="grid grid--solar">
          <Field
            label={t('field.solar.power')}
            sub={t('field.solar.power.sub')}
            unit="W"
            value={solarW}
            onChange={setSolarW}
            hint={t('field.solar.power.hint')} />
          
          <Field
            label={t('field.solar.voltage')}
            sub={t('field.solar.voltage.sub')}
            unit="V"
            value={solarV}
            onChange={setSolarV}
            hint={t('field.solar.voltage.hint', country)} data-comment-anchor="0747eb4a85-input-169-9" />
          
          <Field
            label={t('field.solar.amps')}
            sub={solarPhase === '3' ? t('field.solar.amps.sub.3p') : t('field.solar.amps.sub.1p')}
            unit="A"
            value={fmt(solarAmps)}
            onChange={() => {}}
            locked
            accent />
          
        </div>

        <div className="sv-presets">
          <div className="presets-label">{t('solar.sv.label')}</div>
          <div className="sv-row">
            {(solarPhase === '3' ?
            [country.voltage3p, 200, 208, 380, 400, 415].filter((v, i, a) => a.indexOf(v) === i) :
            [country.voltage, 12, 24, 48, 120, 240].filter((v, i, a) => a.indexOf(v) === i)).
            map((v) =>
            <button
              key={v}
              className={"sv-chip" + (parseNum(solarV) === v ? " sv-chip--active" : "")}
              onClick={() => setSolarV(String(v))}>
              
                {v} V
              </button>
            )}
          </div>
        </div>

        <div className="solar-day">
          <div className="solar-day-head">
            <span>{t('solar.day.label')}</span>
            <Field
              label={t('field.sun')}
              sub={t('field.sun.sub')}
              unit="h"
              value={solarHours}
              onChange={setSolarHours}
              hint={t('field.sun.hint')} />
            
          </div>
          <div className="results">
            <ResultCell
              big
              label={t('result.solar.day')}
              value={fmt(solarDailyKWh)}
              unit="kWh"
              tone="primary" />
            
            <ResultCell
              label={t('result.solar.days')}
              value={
              solarDaysToCharge != null && Number.isFinite(solarDaysToCharge) ?
              fmt(solarDaysToCharge, 1) :
              '—'
              }
              unit={t('result.solar.days.unit')}
              tone="ok"
              note={BAT != null ? t('result.battery.note', BAT) : null} />
            
            <ResultCell
              label={t('result.solar.saved')}
              value={
              solarDailyKWh != null && R != null ?
              window.formatMoney(solarDailyKWh * R, country) :
              '—'
              }
              unit={t('result.solar.saved.unit')}
              tone="muted"
              note={R != null ? t('result.solar.saved.note', country.symbol, R) : null} />
            
          </div>
        </div>
      </section>

      {/* Cheat sheet */}
      <section className="card card--cheat">
        <div className="card-head">
          <h2>{t('cheat.title')}</h2>
          <p>{t('cheat.sub')}</p>
        </div>
        <div className="cheat">
          <CheatRow
            term="Volts (V)"
            plain="The 'push' behind the electricity. Like water pressure."
            ex="A wall outlet pushes at 120 or 220 volts." />
          
          <CheatRow
            term="Amps (A)"
            plain="How much electricity is flowing. Like water flow rate."
            ex="A phone charger pulls ~2 A. An EV pulls 7–80 A." />
          
          <CheatRow
            term="Watts (W)"
            plain="Volts × Amps. The total power being used right now."
            ex="A 1500 W kettle uses 1.5 kW while it's on." />
          
          <CheatRow
            term="1-phase vs 3-phase"
            plain="1-phase is a single 'live' wire — every regular home outlet. 3-phase has three live wires; it carries about 1.73× more power, so big EV chargers and factory equipment use it."
            ex="7 kW EV charger → 1-phase (230 V × 32 A). 22 kW EV charger → 3-phase (400 V × 32 A × √3)." />
          
          <CheatRow
            term="kWh"
            plain="Watts × time. The total energy used. This is the unit on your bill."
            ex="1 kW running for 1 hour = 1 kWh." />
          
        </div>
      </section>

      <footer className="ftr">
        <span>{t('app.tagline')}</span>
        <span><a href="https://aijo.dev" target="_blank" rel="noopener" className="ftr-credit">{t('credit')}</a></span>
      </footer>
    </div>);

}

// PhaseSelector — user-friendly toggle between single- and three-phase
function PhaseSelector({ phase, onChange, country, compact, t }) {
  const tx = t || ((k) => window.translate('en', k));
  return (
    <div className={"phase" + (compact ? " phase--compact" : "")}>
      <div className="phase-label">
        <span>{tx('phase.label')}</span>
        {!compact &&
        <span className="phase-hint">{tx('phase.hint')}</span>
        }
      </div>
      <div className="phase-row">
        <PhaseOpt
          active={phase === '1'}
          onClick={() => onChange('1')}
          name={tx('phase.1.name')}
          short={tx('phase.1.short')}
          desc={tx('phase.1.desc')}
          formula="V × A"
          volts={country.voltage}
          wires={1} />
        
        <PhaseOpt
          active={phase === '3'}
          onClick={() => onChange('3')}
          name={tx('phase.3.name')}
          short={tx('phase.3.short')}
          desc={tx('phase.3.desc')}
          formula="√3 × V × A"
          volts={country.voltage3p}
          wires={3} />
        
      </div>
    </div>);

}

function PhaseOpt({ active, onClick, name, short, desc, formula, volts, wires }) {
  return (
    <button className={"phase-opt" + (active ? " phase-opt--active" : "")} onClick={onClick}>
      <div className="phase-opt-top">
        <div className="phase-wires">
          {Array.from({ length: wires }).map((_, i) =>
          <span key={i} className="phase-wire" style={{ animationDelay: `${i * 0.18}s` }} />
          )}
        </div>
        <div className="phase-opt-head">
          <div className="phase-opt-name">{name}</div>
          <div className="phase-opt-short">{short}</div>
        </div>
      </div>
      <div className="phase-opt-desc">{desc}</div>
      <div className="phase-opt-meta">
        <span className="phase-opt-formula">{formula}</span>
        <span className="phase-opt-volts">~{volts} V</span>
      </div>
    </button>);

}

function Var({ children, hi }) {
  return <span className={"var" + (hi ? " var--hi" : "")}>{children}</span>;
}

function SegBtn({ active, onClick, children }) {
  return (
    <button className={"seg-btn" + (active ? " seg-btn--active" : "")} onClick={onClick}>
      {children}
    </button>);

}

function ResultCell({ label, value, unit, tone, big, note }) {
  return (
    <div className={"res res--" + tone + (big ? " res--big" : "")}>
      <div className="res-label">{label}</div>
      <div className="res-value">
        <span className="res-num">{value}</span>
        {unit ? <span className="res-unit">{unit}</span> : null}
      </div>
      {note ? <div className="res-note">{note}</div> : null}
    </div>);

}

function CheatRow({ term, plain, ex }) {
  return (
    <div className="cheat-row">
      <div className="cheat-term">{term}</div>
      <div className="cheat-plain">{plain}</div>
      <div className="cheat-ex">{ex}</div>
    </div>);

}

function formatHM(hours) {
  const h = Math.floor(hours);
  const m = Math.round((hours - h) * 60);
  if (m === 60) return h + 1 + 'h 0m';
  return `${h}h ${m}m`;
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);