// aero-home.jsx — Landing page

function PageHome({ lang, setLang }) {
  const t = window.WX.T[lang];
  const [data, setData] = useState(window.WX.DATA);
  const [locationName, setLocationName] = useState("Santa Maria, RS");
  const [coords, setCoords] = useState({ lat: -29.69, lon: -53.84, alt: 77 });

  useEffect(() => {
    let alive = true;
    
    const fetchLocationAndWeather = async () => {
      try {
        if (localStorage.getItem('aerograma_consent') !== 'granted') {
          window.WX.fetchWeather(-29.69, -53.84, 7).then(j => alive && setData(j));
          return;
        }
        
        navigator.geolocation.getCurrentPosition(async (pos) => {
          const { latitude: lat, longitude: lon, altitude: alt } = pos.coords;
          const roundedLat = Math.round(lat * 100) / 100;
          const roundedLon = Math.round(lon * 100) / 100;
          if (alive) setCoords({ lat: roundedLat, lon: roundedLon, alt: alt ? Math.round(alt) : 0 });
          
          try {
            const res = await fetch(`https://api.bigdatacloud.net/data/reverse-geocode-client?latitude=${lat}&longitude=${lon}&localityLanguage=${lang}`);
            const geo = await res.json();
            if (alive && geo.city) {
              setLocationName(`${geo.city}, ${geo.principalSubdivision || geo.countryCode}`);
            } else if (alive) {
              setLocationName(lang === "pt" ? "Sua Localização" : "Your Location");
            }
          } catch (e) {
            if (alive) setLocationName(lang === "pt" ? "Sua Localização" : "Your Location");
          }
          
          const wData = await window.WX.fetchWeather(lat, lon, 7);
          if (alive) setData(wData);
        }, () => {
          // Fallback if denied
          window.WX.fetchWeather(-29.69, -53.84, 7).then(j => alive && setData(j));
        }, { timeout: 10000 });
        
      } catch (e) {
        window.WX.fetchWeather(-29.69, -53.84, 7).then(j => alive && setData(j));
      }
    };

    fetchLocationAndWeather();
    
    const onConsent = () => fetchLocationAndWeather();
    window.addEventListener('aerograma_consent_granted', onConsent);
    
    return () => { 
      alive = false; 
      window.removeEventListener('aerograma_consent_granted', onConsent);
    };
  }, [lang]);

  const [inmetAlerts, setInmetAlerts] = useState(null); // null = loading
  const [alertFilter, setAlertFilter] = useState('Todos'); // 'Todos', 'Regional', 'Nacional', 'Internacional'

  const cur     = data.current_complete || window.WX.DATA.current_complete;
  const today   = (data.forecast && data.forecast[0]) ? data.forecast[0] : window.WX.DATA.forecast[0];
  const hour    = window.WX.hourOf(cur.time);
  const palette = window.WX.palette(cur.weathercode, hour);

  useEffect(() => {
    let alive = true;
    window.WX.fetchInmetAlerts().then(res => {
      if (alive) {
        // scope vem real do INMET via api.aerograma.pro/v1/alerts
        setInmetAlerts(res.alerts || []);
      }
    });
    return () => { alive = false; };
  }, []);

  const updatedTime = new Date().toLocaleTimeString(lang === "pt" ? "pt-BR" : "en-US", { hour: '2-digit', minute: '2-digit' });

  // Map INMET level to HomeAlert level prop
  function inmetLevel(al) {
    const lev = (al.level || '').toLowerCase();
    if (lev === 'extreme')  return 'warning';
    if (lev === 'warning')  return 'warning';
    if (lev === 'watch')    return 'watch';
    return 'advisory';
  }

  // Format expiry from ISO or "DD/MM/YYYY HH:mm" strings
  function fmtExpiry(str) {
    if (!str) return '';
    const m = str.match(/(\d{2})[\/\-](\d{2})[\/\-](\d{4})\s+(\d{2}:\d{2})/);
    if (m) return `${m[2]}/${m[1]} ${m[4]}`;
    const m2 = str.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}:\d{2})/);
    if (m2) return `${m2[3]}/${m2[2]} ${m2[4]}`;
    return str.slice(0, 16);
  }

  const filteredAlerts = React.useMemo(() => {
    if (!inmetAlerts) return null;
    if (alertFilter === 'Todos') return inmetAlerts;
    return inmetAlerts.filter(al => (al.scope || 'Regional') === alertFilter);
  }, [inmetAlerts, alertFilter]);

  return (
    <div>
      {/* ─── HERO ──────────────────────────────────────────────────── */}
      <HeroBlock palette={palette} cur={cur} data={data} lang={lang} t={t} locationName={locationName} coords={coords} />

      {/* ─── ACTIVE ALERTS BANNER ─────────────────────────────────── */}
      <Container style={{ marginTop: 56 }}>
        <SectionEyebrow hint={
          inmetAlerts === null
            ? (lang === "pt" ? "carregando…" : "loading…")
            : (lang === "pt"
              ? `${inmetAlerts.length} ativos · INMET · ${updatedTime}`
              : `${inmetAlerts.length} active · INMET · ${updatedTime}`)
        }>
          {lang === "pt" ? "Alertas ativos" : "Active alerts"}
        </SectionEyebrow>

        {inmetAlerts === null ? (
          /* Loading skeleton */
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginTop: 16 }}>
            {[0, 1].map(i => (
              <div key={i} style={{
                height: 110, background: AERO.surfaceA,
                border: `0.5px solid ${AERO.hair}`, borderRadius: 6,
                animation: 'pulse 1.4s ease-in-out infinite',
              }} />
            ))}
          </div>
        ) : inmetAlerts.length > 0 ? (
          <>
            <div style={{ display: 'flex', gap: 8, marginBottom: 20, marginTop: 16 }}>
              {['Todos', 'Regional', 'Nacional', 'Internacional'].map(f => (
                <button key={f} onClick={() => setAlertFilter(f)} style={{
                  padding: '6px 14px', borderRadius: 16, border: `1px solid ${alertFilter === f ? AERO.ink : AERO.line}`,
                  background: alertFilter === f ? AERO.ink : 'transparent',
                  color: alertFilter === f ? AERO.bg0 : AERO.ink,
                  fontFamily: "'JetBrains Mono', monospace", fontSize: 11, cursor: 'pointer',
                  transition: 'all 0.2s'
                }}>
                  {f}
                </button>
              ))}
            </div>
            {filteredAlerts.length > 0 ? (
              <div style={{
                display: 'grid',
                gridTemplateColumns: filteredAlerts.length === 1 ? '1fr' : 'repeat(auto-fill, minmax(340px, 1fr))',
                gap: 16,
              }}>
                {filteredAlerts.slice(0, 6).map((al, idx) => (
                  <HomeAlert
                    key={idx}
                    level={inmetLevel(al)}
                    lang={lang}
                    title={al.title}
                    area={al.area}
                    value={al.value || al.severity}
                    until={fmtExpiry(al.expires)}
                    description={al.description}
                    scope={al.scope}
                  />
                ))}
              </div>
            ) : (
              <div style={{
                padding: '24px 32px',
                background: AERO.surfaceA,
                border: `0.5px solid ${AERO.hair}`,
                borderRadius: 6,
              }}>
                <span className="aero-mono" style={{
                  fontSize: 11, letterSpacing: 1.2,
                  color: AERO.inkSoft, textTransform: 'uppercase',
                }}>
                  {lang === "pt"
                    ? `Nenhum alerta ${alertFilter.toLowerCase()} em vigor.`
                    : `No ${alertFilter.toLowerCase()} alerts in effect.`}
                </span>
              </div>
            )}
          </>
        ) : (
          <div style={{
            padding: '24px 32px',
            background: AERO.surfaceA,
            border: `0.5px solid ${AERO.hair}`,
            borderRadius: 6,
            marginTop: 16,
          }}>
            <span className="aero-mono" style={{
              fontSize: 11, letterSpacing: 1.2,
              color: AERO.inkSoft, textTransform: 'uppercase',
            }}>
              {lang === "pt"
                ? "Nenhum alerta meteorológico em vigor · fonte: INMET"
                : "No weather alerts in effect · source: INMET"}
            </span>
          </div>
        )}
      </Container>


      {/* ─── FEATURED CITIES ──────────────────────────────────────── */}
      <Container style={{ marginTop: 80 }}>
        <SectionEyebrow hint={lang === "pt" ? "12 cidades · clique para detalhar" : "12 cities · click for detail"}>
          {lang === "pt" ? "Observações em destaque" : "Featured observations"}
        </SectionEyebrow>
        <CityGrid lang={lang} />
      </Container>

      {/* ─── MINI RADAR ───────────────────────────────────────────── */}
      <Container style={{ marginTop: 80 }}>
        <SectionEyebrow hint="banda S · CPTEC + DHN">
          {lang === "pt" ? "Radar composto · Brasil" : "Composite radar · Brazil"}
        </SectionEyebrow>
        <MiniRadarBlock lang={lang} palette={palette} />
      </Container>

      {/* ─── EDITORIAL / ANALYSIS ─────────────────────────────────── */}
      <Container style={{ marginTop: 80 }}>
        <SectionEyebrow hint={lang === "pt" ? "Análise sinótica" : "Synoptic analysis"}>
          {lang === "pt" ? "Boletim do dia" : "Today's bulletin"}
        </SectionEyebrow>
        <div style={{ display: 'grid', gridTemplateColumns: '1.6fr 1fr 1fr', gap: 28 }}>
          <FeatureCard lang={lang} lead
            kicker={lang === "pt" ? "Análise" : "Analysis"}
            title={lang === "pt"
              ? "Frente fria pós-tropical avança pela Região Sul"
              : "Post-tropical cold front advances across southern Brazil"}
            excerpt={lang === "pt"
              ? "Centro de baixa pressão se posiciona sobre o Uruguai trazendo umidade do Atlântico Sul. Acumulados de chuva entre 30 e 60 mm são esperados em 24h sobre o Rio Grande do Sul, com queda de temperatura de até 8°C ao longo da semana."
              : "Low-pressure center positions over Uruguay drawing moisture from the South Atlantic. Rainfall totals of 30–60 mm expected in 24h over Rio Grande do Sul, with temperature drops of up to 8°C through the week."}
            time="08:14 GMT-3"
            author={lang === "pt" ? "Equipe Sinótica · CPTEC/INPE" : "Synoptic team · CPTEC/INPE"} />
          <FeatureCard lang={lang}
            kicker={lang === "pt" ? "Modelos" : "Models"}
            title={lang === "pt"
              ? "ECMWF e GFS convergem sobre persistência da chuva até 4ª feira"
              : "ECMWF and GFS converge on rain persistence through Wednesday"}
            excerpt={lang === "pt"
              ? "Spread entre membros do ensemble cai abaixo de 1°C nas próximas 48h."
              : "Ensemble spread drops below 1°C in the next 48h."}
            time="07:42 GMT-3" />
          <FeatureCard lang={lang}
            kicker={lang === "pt" ? "Oceano" : "Ocean"}
            title={lang === "pt"
              ? "Ressaca atinge faixa litorânea catarinense"
              : "Heavy seas hit Santa Catarina coast"}
            excerpt={lang === "pt"
              ? "Ondas de até 3.2m com período de 11s mantêm-se até quinta-feira."
              : "Waves up to 3.2m with 11s period persist through Thursday."}
            time="07:10 GMT-3" />
        </div>
      </Container>

      {/* ─── STATS STRIP ──────────────────────────────────────────── */}
      <Container style={{ marginTop: 96, marginBottom: 24 }}>
        <div style={{
          display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)',
          borderTop: `1px solid ${AERO.line}`,
          borderBottom: `0.5px solid ${AERO.hair}`,
          padding: '36px 0',
        }}>
          <BigStat value="847" unit={lang === "pt" ? "estações ativas" : "active stations"} />
          <BigStat value="0.3s" unit={lang === "pt" ? "latência média" : "median latency"} />
          <BigStat value="14" unit={lang === "pt" ? "modelos integrados" : "models integrated"} />
          <BigStat value="99.97%" unit="uptime · 90d" />
        </div>
      </Container>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// HERO — full-bleed atmospheric backdrop, gigantic editorial type
// ─────────────────────────────────────────────────────────────────────
function HeroBlock({ palette, cur, data, lang, t, locationName = "Santa Maria, RS", coords = { lat: -29.69, lon: -53.84, alt: 77 } }) {
  const today = data.forecast[0];
  return (
    <section style={{
      position: 'relative', minHeight: 640, overflow: 'hidden',
      borderBottom: `0.5px solid ${AERO.hair}`,
    }}>
      <AtmosphericBackdrop palette={palette}
        weathercode={cur.weathercode} hour={window.WX.hourOf(cur.time)}
        windDir={cur.wind_direction_10m} windSpd={cur.wind_speed_10m} />
      {/* paper wash so the cream chrome bleeds in */}
      <div style={{
        position: 'absolute', inset: 0,
        background: `linear-gradient(180deg, transparent 0%, ${AERO.paper}cc 100%)`,
      }} />
      <div style={{ position: 'relative' }}>
        <div style={{ maxWidth: 1320, margin: '0 auto', padding: '64px 36px 56px' }}>
          <div style={{
            display: 'flex', gap: 14, alignItems: 'center',
            color: palette.ink,
          }}>
            <span style={{
              display: 'inline-block', width: 7, height: 7, borderRadius: 4,
              background: AERO.danger,
            }} />
            <span className="aero-eyebrow" style={{ color: palette.ink, fontWeight: 600 }}>
              {lang === "pt" ? "Em destaque agora" : "Featured now"} · {locationName}
            </span>
            <span className="aero-eyebrow" style={{ color: palette.inkSoft }}>
              {cur.time.slice(11)} {data.timezone_abbr || Intl.DateTimeFormat().resolvedOptions().timeZone} · {Math.abs(coords.lat)}°{coords.lat >= 0 ? 'N' : 'S'}, {Math.abs(coords.lon)}°{coords.lon >= 0 ? 'E' : 'W'} · {coords.alt}m
            </span>
          </div>

          <h1 className="aero-serif" style={{
            fontStyle: 'italic', fontWeight: 400,
            fontSize: 'clamp(64px, 8vw, 132px)',
            lineHeight: 0.94, letterSpacing: -3,
            color: palette.ink, margin: '28px 0 0',
            textWrap: 'pretty', maxWidth: 980,
          }}>
            {(() => {
              const code = cur.weathercode;
              const desc = cur.weathercode_desc[lang];
              if (lang === "pt") {
                if (code <= 3) return `${desc} e tempo estável no Centro do Estado.`;
                if (code >= 45 && code <= 48) return `Baixa visibilidade com ${desc.toLowerCase()} na região.`;
                if (code >= 51 && code <= 67) return `${desc} contínua cobre o Centro do Estado.`;
                if (code >= 71 && code <= 77) return `Condições de ${desc.toLowerCase()} na serra e planalto.`;
                if (code >= 80 && code <= 82) return `Instabilidade traz pancadas de chuva isoladas.`;
                if (code >= 95) return `Alerta de tempestade severa se aproximando.`;
                return `${desc} no momento.`;
              } else {
                if (code <= 3) return `${desc} and stable weather in the central region.`;
                if (code >= 45 && code <= 48) return `Low visibility with ${desc.toLowerCase()} in the area.`;
                if (code >= 51 && code <= 67) return `Continuous ${desc.toLowerCase()} covers the region.`;
                if (code >= 71 && code <= 77) return `${desc} conditions over the highlands.`;
                if (code >= 80 && code <= 82) return `Instability brings isolated showers.`;
                if (code >= 95) return `Severe thunderstorm warning in effect.`;
                return `${desc} at the moment.`;
              }
            })()}
          </h1>

          {/* Live numbers row */}
          <div style={{
            display: 'grid', gridTemplateColumns: '380px 1fr',
            gap: 48, marginTop: 56, alignItems: 'flex-end',
          }}>
            <div>
              <div className="aero-eyebrow" style={{ color: palette.inkSoft }}>
                {t.now_label} · {cur.weathercode_desc[lang]}
              </div>
              <div className="aero-serif" style={{
                fontStyle: 'italic', fontSize: 200, lineHeight: 0.85,
                letterSpacing: -8, color: palette.ink, marginTop: 4,
                fontFeatureSettings: '"lnum"',
              }}>
                {Math.round(cur.temperature_2m)}<span style={{ fontSize: 110 }}>°</span>
              </div>
              <div className="aero-mono" style={{
                fontSize: 12, color: palette.inkDim, marginTop: 4,
                letterSpacing: 0.5,
              }}>
                {t.feels_like.toUpperCase()} {cur.apparent_temperature.toFixed(1)}° ·
                {" "}{t.min.toUpperCase()} {Math.round(today.temperature_2m_min)}° /
                {" "}{t.max.toUpperCase()} {Math.round(today.temperature_2m_max)}°
              </div>
            </div>

            <div style={{
              display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)',
              gap: 32,
              borderTop: `1px solid ${palette.line}`, paddingTop: 22,
            }}>
              <HeroStat label={t.humidity} value={cur.relative_humidity_2m} unit="%" palette={palette} />
              <HeroStat label={t.dewpoint} value={cur.dew_point_2m.toFixed(1)} unit="°C" palette={palette} />
              <HeroStat label={t.pressure} value={Math.round(cur.surface_pressure)} unit="hPa" palette={palette}
                trend={lang === "pt" ? "↘ caindo" : "↘ falling"} />
              <HeroStat label={t.wind} value={cur.wind_speed_10m.toFixed(1)} unit="m/s" palette={palette}
                sub={`${window.WX.compassLabel(cur.wind_direction_10m, lang)} · ${cur.wind_direction_10m}°`} />
              <HeroStat label={t.gusts} value={cur.wind_gusts_10m.toFixed(0)} unit="m/s" palette={palette} />
              <HeroStat label={t.cloud} value={cur.cloud_cover} unit="%" palette={palette} />
              <HeroStat label={t.uv} value={cur.uv_index.toFixed(1)} unit="" palette={palette}
                sub={lang === "pt" ? "baixo" : "low"} />
              <HeroStat label={t.precip} value={today.precipitation_sum.toFixed(1)} unit="mm" palette={palette}
                sub={`${today.precipitation_hours}h ${lang === "pt" ? "previstas" : "expected"}`} />
            </div>
          </div>

          {/* CTA row */}
          <div style={{ display: 'flex', gap: 14, marginTop: 56 }}>
            <a href="#/city/smr" style={{
              background: palette.ink, color: palette.bg0,
              padding: '14px 22px', borderRadius: 999,
              fontFamily: "'JetBrains Mono', monospace", fontSize: 11,
              letterSpacing: 1.6, textTransform: 'uppercase', fontWeight: 600,
            }}>
              {lang === "pt" ? "Abrir previsão completa →" : "Open full forecast →"}
            </a>
            <a href="#/radar" style={{
              border: `0.5px solid ${palette.line}`,
              padding: '14px 22px', borderRadius: 999,
              fontFamily: "'JetBrains Mono', monospace", fontSize: 11,
              letterSpacing: 1.6, textTransform: 'uppercase', color: palette.ink,
            }}>
              {lang === "pt" ? "Ver radar" : "View radar"}
            </a>
          </div>
        </div>
      </div>
    </section>
  );
}

function HeroStat({ label, value, unit, sub, trend, palette }) {
  return (
    <div>
      <div className="aero-mono" style={{
        fontSize: 10, letterSpacing: 1.4, textTransform: 'uppercase',
        color: palette.inkSoft,
      }}>{label}</div>
      <div className="aero-serif" style={{
        fontStyle: 'italic', fontSize: 36, color: palette.ink,
        lineHeight: 1, marginTop: 6,
        display: 'flex', alignItems: 'baseline', gap: 4,
      }}>
        {value}
        {unit && <span className="aero-mono" style={{
          fontStyle: 'normal', fontSize: 12, color: palette.inkDim,
        }}>{unit}</span>}
      </div>
      {(sub || trend) && <div className="aero-mono" style={{
        fontSize: 10, color: palette.inkSoft, marginTop: 6, letterSpacing: 0.5,
      }}>{sub || trend}</div>}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// ALERT CARDS (home)
// ─────────────────────────────────────────────────────────────────────
function HomeAlert({ level, lang, title, area, value, until, description, scope = "Regional" }) {
  const [isOpen, setIsOpen] = useState(false);

  const accent = level === "warning"
    ? AERO.danger
    : level === "watch"
      ? AERO.warm
      : AERO.accent; // advisory

  const levelLabel = level === "warning"
    ? (lang === "pt" ? "Alerta" : "Warning")
    : level === "watch"
      ? (lang === "pt" ? "Atenção" : "Watch")
      : (lang === "pt" ? "Aviso" : "Advisory");

  const scopeColor = scope === 'Internacional' ? '#8e44ad' : scope === 'Nacional' ? '#2980b9' : '#27ae60';

  return (
    <div 
      onClick={() => setIsOpen(!isOpen)}
      style={{
        display: 'block', position: 'relative',
        padding: '22px 26px 22px 30px',
        background: '#fff', border: `0.5px solid ${AERO.hair}`,
        borderRadius: 4, textDecoration: 'none',
        transition: 'box-shadow 0.18s',
        cursor: 'pointer',
      }}
      onMouseEnter={e => e.currentTarget.style.boxShadow = `0 4px 20px rgba(0,0,0,0.07)`}
      onMouseLeave={e => e.currentTarget.style.boxShadow = 'none'}
    >
      {/* colour bar */}
      <div style={{
        position: 'absolute', top: 0, bottom: 0, left: 0, width: 4,
        background: accent, borderRadius: '4px 0 0 4px',
      }} />

      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 20 }}>
        {/* left column */}
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
            <div className="aero-mono" style={{
              fontSize: 10, letterSpacing: 1.6, textTransform: 'uppercase',
              color: accent, fontWeight: 600,
            }}>{levelLabel}</div>
            <div className="aero-mono" style={{
              fontSize: 9, letterSpacing: 1.2, textTransform: 'uppercase',
              color: '#fff', background: scopeColor, padding: '2px 6px', borderRadius: 4, fontWeight: 600
            }}>{scope}</div>
          </div>
          <div className="aero-serif" style={{
            fontStyle: 'italic', fontSize: 28, color: AERO.ink,
            lineHeight: 1.1,
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>{title}</div>
          {area && (
            <div className="aero-mono" style={{
              fontSize: 10.5, color: AERO.inkSoft, marginTop: 6,
              letterSpacing: 0.7, textTransform: 'uppercase',
              lineHeight: 1.4,
            }}>{area}</div>
          )}
          {description && isOpen && (
            <div style={{
              fontSize: 12, color: AERO.inkDim, marginTop: 12,
              lineHeight: 1.5,
              background: AERO.surfaceA, padding: '12px', borderRadius: 4, border: `0.5px solid ${AERO.hair}`
            }}>{description}</div>
          )}
        </div>

        {/* right column */}
        <div style={{ textAlign: 'right', flexShrink: 0 }}>
          {value && (
            <div className="aero-serif" style={{
              fontStyle: 'italic', fontSize: 24, color: AERO.ink, lineHeight: 1,
            }}>{value}</div>
          )}
          {until && (
            <div className="aero-mono" style={{
              fontSize: 10, color: AERO.inkSoft, marginTop: 6, letterSpacing: 0.5,
              background: AERO.surfaceB, padding: '4px 8px', borderRadius: 4, display: 'inline-block'
            }}>
              {lang === "pt" ? "expira" : "expires"}<br />{until}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// CITY GRID
// ─────────────────────────────────────────────────────────────────────
// CITY_DEFS — metadados estáticos; dados meteorológicos são buscados live.
const CITY_DEFS = [
  { id: "smr", name: "Santa Maria",     region: "RS", lat: -29.69, lon: -53.84 },
  { id: "poa", name: "Porto Alegre",    region: "RS", lat: -30.03, lon: -51.23 },
  { id: "sao", name: "São Paulo",       region: "SP", lat: -23.55, lon: -46.63 },
  { id: "rio", name: "Rio de Janeiro",  region: "RJ", lat: -22.91, lon: -43.17 },
  { id: "bsb", name: "Brasília",        region: "DF", lat: -15.78, lon: -47.93 },
  { id: "rec", name: "Recife",          region: "PE", lat:  -8.05, lon: -34.88 },
  { id: "man", name: "Manaus",          region: "AM", lat:  -3.10, lon: -60.02 },
  { id: "for", name: "Fortaleza",       region: "CE", lat:  -3.72, lon: -38.54 },
  { id: "lis", name: "Lisboa",          region: "PT", lat:  38.72, lon:  -9.14 },
  { id: "lon", name: "London",          region: "UK", lat:  51.51, lon:  -0.13 },
  { id: "nyc", name: "New York",        region: "NY", lat:  40.71, lon: -74.01 },
  { id: "tok", name: "Tokyo",           region: "JP", lat:  35.68, lon: 139.69 },
];

function CityGrid({ lang }) {
  // Estado inicial: esqueleto com dados null (mostra placeholder de carregamento).
  const [cities, setCities] = useState(
    CITY_DEFS.map(c => ({ ...c, temp: null, code: null, lo: null, hi: null, hour: null, wind: null }))
  );

  useEffect(() => {
    // 1. Tenta via api.aerograma.pro/v1/cities (cache server-side, 1h)
    window.WX.fetchCities().then(serverCities => {
      if (serverCities && serverCities.length > 0) {
        setCities(serverCities.map(c => ({
          ...c,
          // Garante compatibilidade de campos
          code: c.code ?? c.dcode ?? 3,
          hour: c.hour ?? 12,
        })));
        return;
      }

      // 2. Fallback: batch direto
      const lats = CITY_DEFS.map(c => c.lat).join(",");
      const lons = CITY_DEFS.map(c => c.lon).join(",");
      const url = [
        "https://api.open-meteo.com/v1/forecast",
        `?latitude=${lats}&longitude=${lons}`,
        "&current=temperature_2m,apparent_temperature,weather_code,wind_speed_10m,wind_direction_10m,is_day",
        "&daily=temperature_2m_max,temperature_2m_min",
        "&wind_speed_unit=ms&timezone=auto&forecast_days=1&models=best_match",
      ].join("");

      fetch(url)
        .then(r => r.ok ? r.json() : Promise.reject("HTTP " + r.status))
        .then(results => {
          const arr = Array.isArray(results) ? results : [results];
          setCities(CITY_DEFS.map((def, i) => {
            const d = arr[i];
            if (!d) return { ...def, temp: null, code: null, lo: null, hi: null, hour: null, wind: null };
            const cur = d.current || {};
            const daily = d.daily || {};
            let hour = new Date().getUTCHours();
            if (d.utc_offset_seconds != null) {
              hour = Math.floor(((Date.now() / 1000 + d.utc_offset_seconds) % 86400) / 3600);
            }
            return {
              ...def,
              temp:  cur.temperature_2m                       ?? null,
              feels: cur.apparent_temperature                  ?? null,
              code:  cur.weather_code                          ?? null,
              lo:    (daily.temperature_2m_min || [])[0]       ?? null,
              hi:    (daily.temperature_2m_max || [])[0]       ?? null,
              hour,
              wind:  cur.wind_speed_10m                        ?? null,
              is_day: cur.is_day                               ?? 1,
            };
          }));
        })
        .catch(() => {
          // Mantém esqueleto (já está como null, UI mostra "carregando…")
        });
    });
  }, []);

  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16 }}>
      {cities.map((c) => <CityCard key={c.id} city={c} lang={lang} />)}
    </div>
  );
}

function CityCard({ city, lang }) {
  const loading = city.temp === null;
  const palette = window.WX.palette(city.code ?? 3, city.hour ?? 12);
  const desc = describeCode(city.code ?? 3, lang);
  return (
    <a href={"#/city/" + city.id} style={{
      display: 'block', position: 'relative', overflow: 'hidden',
      borderRadius: 6, height: 240,
      border: `0.5px solid ${AERO.hair}`,
    }}>
      <AtmosphericBackdrop palette={palette}
        weathercode={city.code} hour={city.hour}
        windDir={210} windSpd={city.wind} />
      <div style={{
        position: 'absolute', inset: 0,
        background: `linear-gradient(180deg, transparent 50%, ${palette.bg2}aa 100%)`,
      }} />
      <div style={{
        position: 'relative', height: '100%',
        padding: '18px 20px', display: 'flex', flexDirection: 'column',
        color: palette.ink, justifyContent: 'space-between',
      }}>
        <div>
          <div className="aero-mono" style={{
            fontSize: 9.5, letterSpacing: 1.4, textTransform: 'uppercase',
            color: palette.inkSoft,
          }}>{city.region}</div>
          <div className="aero-serif" style={{
            fontStyle: 'italic', fontSize: 28, lineHeight: 1, marginTop: 4,
            color: palette.ink,
          }}>{city.name}</div>
        </div>
        <div>
          <div className="aero-serif" style={{
            fontStyle: 'italic', fontSize: 64, lineHeight: 0.9,
            letterSpacing: -2, color: palette.ink,
          }}>
            {loading ? "—" : Math.round(city.temp)}
            <span style={{ fontSize: 32 }}>°</span>
          </div>
          <div className="aero-mono" style={{
            fontSize: 10, color: palette.inkSoft, marginTop: 6, letterSpacing: 0.5,
          }}>
            {loading
              ? (lang === "pt" ? "carregando…" : "loading…")
              : `${desc} · ${city.lo != null ? Math.round(city.lo) : "—"}° / ${city.hi != null ? Math.round(city.hi) : "—"}°`
            }
          </div>
        </div>
      </div>
    </a>
  );
}

function describeCode(code, lang) {
  if (code === 0) return lang === "pt" ? "Limpo" : "Clear";
  if (code <= 3) return lang === "pt" ? "Parc. nublado" : "Partly cloudy";
  if (code >= 45 && code <= 48) return lang === "pt" ? "Neblina" : "Fog";
  if (code >= 51 && code <= 57) return lang === "pt" ? "Garoa" : "Drizzle";
  if (code >= 61 && code <= 67) return lang === "pt" ? "Chuva" : "Rain";
  if (code >= 71 && code <= 77) return lang === "pt" ? "Neve" : "Snow";
  if (code >= 80) return lang === "pt" ? "Pancadas" : "Showers";
  if (code >= 95) return lang === "pt" ? "Tempestade" : "Thunderstorm";
  return "";
}

// ─────────────────────────────────────────────────────────────────────
// MINI RADAR — wide map preview that links to the full radar page
// ─────────────────────────────────────────────────────────────────────
function MiniRadarBlock({ lang, palette }) {
  return (
    <a href="#/radar" style={{
      display: 'block', position: 'relative', overflow: 'hidden',
      borderRadius: 6, height: 380,
      border: `0.5px solid ${AERO.hair}`,
    }}>
      <BrazilMiniMap />
      <div style={{
        position: 'absolute', top: 22, left: 24, display: 'flex',
        alignItems: 'center', gap: 10,
      }}>
        <span style={{ width: 7, height: 7, borderRadius: 4, background: AERO.danger }} />
        <span className="aero-mono" style={{
          fontSize: 11, letterSpacing: 1.4, textTransform: 'uppercase',
          color: AERO.paper, fontWeight: 600,
        }}>{lang === "pt" ? "Eco ativo" : "Active echo"}</span>
      </div>
      <div style={{
        position: 'absolute', bottom: 22, left: 24, color: AERO.paper,
      }}>
        <div className="aero-serif" style={{
          fontStyle: 'italic', fontSize: 36, lineHeight: 1,
        }}>{lang === "pt" ? "Núcleo convectivo ao oeste do RS" : "Convective core W of RS"}</div>
        <div className="aero-mono" style={{
          fontSize: 11, color: '#cfcab8', marginTop: 8, letterSpacing: 0.5,
        }}>
          {lang === "pt"
            ? "Refletividade 48 dBZ · deslocando NE a 32 km/h"
            : "48 dBZ · moving NE at 32 km/h"}
        </div>
      </div>
      <div style={{
        position: 'absolute', bottom: 22, right: 24,
        padding: '10px 14px', borderRadius: 999,
        border: `0.5px solid rgba(255,255,255,0.4)`, color: AERO.paper,
      }}>
        <span className="aero-mono" style={{
          fontSize: 11, letterSpacing: 1.4, textTransform: 'uppercase',
        }}>{lang === "pt" ? "Abrir mapa inteiro →" : "Open full map →"}</span>
      </div>
    </a>
  );
}

// Stylized Brazil outline + radar blobs — wide aspect.
function BrazilMiniMap() {
  // Simplified outline path. Approximate, decorative only.
  return (
    <svg width="100%" height="100%" viewBox="0 0 1200 380" preserveAspectRatio="xMidYMid slice"
      style={{ display: 'block', background: '#13202b' }}>
      <defs>
        <radialGradient id="ocean" cx="0.7" cy="0.5">
          <stop offset="0" stopColor="#1a2c3a" />
          <stop offset="1" stopColor="#0a131c" />
        </radialGradient>
      </defs>
      <rect width="1200" height="380" fill="url(#ocean)" />

      {/* lat/lon grid */}
      {[60, 120, 180, 240, 300].map((y, i) => (
        <line key={i} x1="0" y1={y} x2="1200" y2={y} stroke="#fff" strokeOpacity="0.05" strokeDasharray="2 6" />
      ))}
      {[150, 300, 450, 600, 750, 900, 1050].map((x, i) => (
        <line key={i} x1={x} y1="0" x2={x} y2="380" stroke="#fff" strokeOpacity="0.05" strokeDasharray="2 6" />
      ))}

      {/* stylized Brazil-ish landmass path (decorative) */}
      <path d="M 500 60
               C 560 50, 660 60, 740 90
               C 820 110, 880 140, 900 200
               C 920 250, 880 290, 820 320
               C 760 340, 700 340, 640 320
               C 580 310, 540 290, 500 280
               C 460 270, 430 240, 440 200
               C 450 160, 470 110, 500 60 Z"
        fill="#4a5648" opacity="0.9" />
      <path d="M 500 60 C 560 50, 660 60, 740 90 C 820 110, 880 140, 900 200
               C 920 250, 880 290, 820 320 C 760 340, 700 340, 640 320
               C 580 310, 540 290, 500 280 C 460 270, 430 240, 440 200
               C 450 160, 470 110, 500 60 Z"
        fill="none" stroke="#fff" strokeOpacity="0.18" strokeWidth="0.6" />

      {/* state divisions (decorative scribble) */}
      <g stroke="#fff" strokeOpacity="0.08" strokeWidth="0.5" fill="none">
        <path d="M 540 120 L 660 130 L 720 200 L 660 280" />
        <path d="M 540 220 L 700 240 L 800 280" />
        <path d="M 640 150 L 720 240" />
        <path d="M 580 80 L 600 200" />
      </g>

      {/* radar reflectivity blobs over RS area */}
      <g style={{ mixBlendMode: 'screen', filter: 'blur(8px)' }}>
        <circle cx="540" cy="280" r="60" fill="#5a9c5e" opacity="0.6" />
        <circle cx="520" cy="270" r="36" fill="#c5a23a" opacity="0.7" />
        <circle cx="510" cy="262" r="22" fill="#c97c3a" opacity="0.8" />
        <circle cx="502" cy="258" r="10" fill="#a8463a" opacity="0.9" />
        {/* secondary cells elsewhere */}
        <circle cx="700" cy="220" r="32" fill="#5a9c5e" opacity="0.45" />
        <circle cx="810" cy="160" r="28" fill="#5a9c5e" opacity="0.4" />
        <circle cx="850" cy="240" r="22" fill="#c5a23a" opacity="0.5" />
      </g>

      {/* city markers */}
      {[
        [510, 270, "Santa Maria"],
        [560, 290, "Porto Alegre"],
        [800, 240, "São Paulo"],
        [840, 220, "Rio de Janeiro"],
        [720, 140, "Brasília"],
        [600, 80, "Manaus"],
        [880, 90, "Recife"],
      ].map(([x, y, n], i) => (
        <g key={i}>
          <circle cx={x} cy={y} r="3" fill="#fff" />
          <text x={x + 6} y={y + 3} fill="#fff" fontSize="9"
            fontFamily="'JetBrains Mono', monospace" opacity="0.85">{n}</text>
        </g>
      ))}

      {/* reflectivity legend overlay */}
      <g transform="translate(900, 320)">
        <text x="0" y="-6" fill="#fff" fontSize="9" opacity="0.7"
          fontFamily="'JetBrains Mono', monospace" letterSpacing="1">REFLECTIVITY (dBZ)</text>
        {["#3a6f4b", "#5a9c5e", "#c5a23a", "#c97c3a", "#a8463a", "#7a2a6a"].map((c, i) => (
          <rect key={i} x={i * 36} y={0} width={36} height={4} fill={c} />
        ))}
        {[5, 20, 30, 40, 50, 60].map((v, i) => (
          <text key={i} x={i * 36} y={16} fill="#fff" fontSize="8" opacity="0.6"
            fontFamily="'JetBrains Mono', monospace">{v}</text>
        ))}
      </g>
    </svg>
  );
}

// ─────────────────────────────────────────────────────────────────────
// EDITORIAL CARDS
// ─────────────────────────────────────────────────────────────────────
function FeatureCard({ lang, kicker, title, excerpt, time, author, lead }) {
  return (
    <article style={{
      borderTop: `1px solid ${AERO.line}`, paddingTop: 18,
    }}>
      <div className="aero-eyebrow">{kicker} · {time}</div>
      <h3 className="aero-serif" style={{
        fontStyle: 'italic', fontWeight: 400,
        fontSize: lead ? 38 : 22,
        lineHeight: 1.1, letterSpacing: lead ? -0.5 : 0,
        color: AERO.ink, margin: '12px 0 0',
        textWrap: 'pretty',
      }}>{title}</h3>
      <p style={{
        fontSize: lead ? 16 : 13.5,
        color: AERO.inkDim, marginTop: 14, lineHeight: 1.55,
        textWrap: 'pretty',
      }}>{excerpt}</p>
      {author && <div className="aero-mono" style={{
        fontSize: 10, color: AERO.inkSoft, marginTop: 14,
        letterSpacing: 0.5, textTransform: 'uppercase',
      }}>{author}</div>}
    </article>
  );
}

// ─────────────────────────────────────────────────────────────────────
// BIG STATS
// ─────────────────────────────────────────────────────────────────────
function BigStat({ value, unit }) {
  return (
    <div>
      <div className="aero-serif" style={{
        fontStyle: 'italic', fontSize: 64, color: AERO.ink, lineHeight: 1,
        letterSpacing: -1.5, fontFeatureSettings: '"lnum"',
      }}>{value}</div>
      <div className="aero-mono" style={{
        fontSize: 10.5, color: AERO.inkSoft, marginTop: 10,
        letterSpacing: 1.4, textTransform: 'uppercase',
      }}>{unit}</div>
    </div>
  );
}

Object.assign(window, { PageHome });
