// home-industrial.jsx — uses Shell. Hero + latest-release sidebar.

// Parse duration text like "3:42" into seconds. Returns 0 if missing/malformed.
function parseDurationSecs(s) {
  if (!s) return 0;
  const parts = String(s).split(":").map(n => parseInt(n, 10));
  if (parts.some(Number.isNaN)) return 0;
  if (parts.length === 2) return parts[0] * 60 + parts[1];
  if (parts.length === 3) return parts[0] * 3600 + parts[1] * 60 + parts[2];
  return parts[0] || 0;
}

function HomeIndustrial({ tab, onTabChange }) {
  // Default to NOT playing; only start once we have audio + user clicks.
  const [playing, setPlaying] = React.useState(false);
  const [progress, setProgress] = React.useState(0);
  // Read from in-memory cache for synchronous initial state — eliminates the
  // loading flash + Spotify iframe reload when the user comes back to Home.
  const cachedLatest = window.diavalCacheGet ? window.diavalCacheGet("home-latest") : null;
  const cachedUpcoming = window.diavalCacheGet ? window.diavalCacheGet("home-upcoming") : null;
  const cachedLinks = window.diavalCacheGet ? window.diavalCacheGet("home-streamLinks") : null;
  const [latest, setLatest] = React.useState(cachedLatest);
  const [upcoming, setUpcoming] = React.useState(cachedUpcoming);
  const [streamLinks, setStreamLinks] = React.useState(cachedLinks || []);
  // Tags for the latest release card — pulled from the same admin-managed
  // diaval_myth_genres / diaval_myth_moods that the mythology detail page uses,
  // so the homepage and detail page show the same labels (no hardcoded fallback).
  const cachedLatestTags = window.diavalCacheGet ? window.diavalCacheGet("home-latest-tags") : null;
  const [latestTags, setLatestTags] = React.useState(cachedLatestTags || []);
  const audioRef = React.useRef(null);
  const PREVIEW_LEN = 30;

  // Fetch ALL public-visible myths once, then split client-side into:
  //   - latest: is_published AND (release_date null OR <= today)
  //   - upcoming: presave_enabled OR (is_published AND release_date > today)
  // Client-side split avoids any PostgREST date-format gotchas — release_date is
  // text in YYYY.MM.DD form, so we normalize via isPrerelease() before comparing.
  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      const sb = window.diavalSupabase;
      // Cache the full myths list so revisits don't refetch — the data rarely
      // changes and admin can clear via diavalCacheBust on save.
      const all = window.diavalCachedFetch
        ? await window.diavalCachedFetch("myths-public-list", async () => {
            const { data } = await sb.from("diaval_myths_public")
              .select("id, title, year, duration, position, release_date, cover_url, spotify_preview_url, spotify_track_id, spotify_album_art_url, hyperfollow_url, is_published, presave_enabled");
            return data || [];
          })
        : ((await sb.from("diaval_myths_public").select("id, title, year, duration, position, release_date, cover_url, spotify_preview_url, spotify_track_id, spotify_album_art_url, hyperfollow_url, is_published, presave_enabled")).data || []);
      if (cancelled) return;
      const isFuture = (r) => typeof isPrerelease === "function" ? isPrerelease(r.release_date) : false;

      // Released: published AND (no release_date OR not in the future)
      const released = all.filter(r => r.is_published && !isFuture(r));
      // Sort newest first by release_date desc, fallback position desc
      released.sort((a, b) => {
        const ad = a.release_date || "";
        const bd = b.release_date || "";
        if (ad !== bd) return ad < bd ? 1 : -1;
        return (b.position || 0) - (a.position || 0);
      });
      const latestMyth = released[0] || null;

      // Upcoming/presave: presave_enabled OR (published AND in the future)
      const upcomingPool = all.filter(r => r.presave_enabled || (r.is_published && isFuture(r)));
      // Sort soonest first by release_date asc, nulls last, fallback position asc
      upcomingPool.sort((a, b) => {
        const ad = a.release_date || "";
        const bd = b.release_date || "";
        if (!ad && !bd) return (a.position || 0) - (b.position || 0);
        if (!ad) return 1;
        if (!bd) return -1;
        if (ad !== bd) return ad < bd ? -1 : 1;
        return (a.position || 0) - (b.position || 0);
      });
      const upcomingMyth = upcomingPool.find(r => r.id !== latestMyth?.id) || null;

      setLatest(latestMyth);
      setUpcoming(upcomingMyth);
      // Persist latest/upcoming to the cache for instant render on revisit.
      if (window._diavalCache) {
        window._diavalCache.set("home-latest", { v: latestMyth, t: Date.now() });
        window._diavalCache.set("home-upcoming", { v: upcomingMyth, t: Date.now() });
      }
      if (latestMyth) {
        const links = window.diavalCachedFetch
          ? await window.diavalCachedFetch(`myth-links-${latestMyth.id}`, async () => {
              const { data } = await sb.from("diaval_myth_links")
                .select("platform, label, url, position")
                .eq("myth_id", latestMyth.id)
                .order("position", { ascending: true });
              return data || [];
            })
          : ((await sb.from("diaval_myth_links").select("platform, label, url, position").eq("myth_id", latestMyth.id).order("position", { ascending: true })).data || []);
        if (!cancelled && links) {
          setStreamLinks(links);
          if (window._diavalCache) window._diavalCache.set("home-streamLinks", { v: links, t: Date.now() });
        }
      }
    })();
    return () => { cancelled = true; };
  }, []);

  // Fetch genres + moods for the latest release once we know its id. Same join
  // shape as MythDetail uses — keeps the labels in sync between the homepage
  // hero and the deep song page. Missing tags = empty list (caller falls back
  // to fmtDur only).
  React.useEffect(() => {
    if (!latest?.id) return;
    let cancelled = false;
    (async () => {
      const sb = window.diavalSupabase;
      const [{ data: g }, { data: m }] = await Promise.all([
        sb.from("diaval_myth_genres").select("position, diaval_genres(id, name, is_visible)").eq("myth_id", latest.id).order("position"),
        sb.from("diaval_myth_moods").select("position, diaval_moods(id, name, is_visible)").eq("myth_id", latest.id).order("position"),
      ]);
      if (cancelled) return;
      // Genres only on the homepage hero — moods clutter the line and don't
      // add value at this scale. The detail page still shows both.
      const genres = (g || []).map(r => r.diaval_genres).filter(x => x && x.is_visible);
      setLatestTags(genres);
      if (window._diavalCache) window._diavalCache.set("home-latest-tags", { v: genres, t: Date.now() });
    })();
    return () => { cancelled = true; };
  }, [latest?.id]);

  const hasPreview = !!latest?.spotify_preview_url;
  const hasEmbed = !hasPreview && !!latest?.spotify_track_id;
  const coverImg = latest?.cover_url || latest?.spotify_album_art_url || null;

  // Real audio path
  React.useEffect(() => {
    if (!hasPreview) return;
    const a = audioRef.current;
    if (!a) return;
    if (playing) a.play().catch(() => setPlaying(false));
    else a.pause();
  }, [playing, hasPreview]);

  // Simulated playback when no preview URL — keeps the visual alive.
  React.useEffect(() => {
    if (hasPreview) return;
    if (!playing) return;
    const t = setInterval(() => setProgress((p) => (p >= 1 ? 0 : p + 0.003)), 100);
    return () => clearInterval(t);
  }, [playing, hasPreview]);

  const S = window.shellStyles;
  const { isMobile } = (window.useViewport ? window.useViewport() : { isMobile: false });
  const releaseTitle = latest ? latest.title : "—";
  const releaseFileLabel = latest
    ? `FILE ${String(latest.position).padStart(3, "0")} · ${latest.release_date || latest.year || ""}`
    : "AWAITING TRANSMISSION";
  const releaseDurSecs = latest ? parseDurationSecs(latest.duration) || 222 : 222;
  // For the timer label: show 30s if we're playing the preview, otherwise the full track length.
  const displayDur = hasPreview ? PREVIEW_LEN : releaseDurSecs;
  const fmtDur = `${Math.floor(displayDur / 60)}:${String(displayDur % 60).padStart(2, "0")}`;

  // Mobile hero scale: was 36/24; bumped so the hero claims hierarchy over the
  // latest-release cover image that peeks in below the fold.
  const heroFs   = isMobile ? 56 : 88;
  const cueFs    = isMobile ? 32 : 64;
  const blurbMt  = isMobile ? 28 : 48;

  return (
    <Shell tab={tab} onTabChange={onTabChange} page="001">
      <div style={{
        position: isMobile ? "relative" : "absolute",
        inset: isMobile ? "auto" : 0,
        display: isMobile ? "block" : "grid",
        gridTemplateColumns: isMobile ? undefined : "1fr 1px 460px",
        overflow: isMobile ? "visible" : "hidden",
      }}>
        {/* left: hero */}
        <div style={{
          position: "relative",
          padding: isMobile ? "28px 16px 32px" : "44px 56px 56px",
          overflow: isMobile ? "visible" : "auto",
          minHeight: 0,
        }}>
          <div style={{ position: "absolute", top: isMobile ? 24 : 16, right: isMobile ? 12 : 24, fontSize: 12, color: S.ash, letterSpacing: "0.3em" }}>
            // HOME / 001
          </div>

          <h1 style={{ margin: 0, fontFamily: S.display, color: S.bone, paddingTop: isMobile ? 28 : 0 }}>
            <div style={{ fontSize: heroFs, lineHeight: 0.9, letterSpacing: "-0.02em" }}>
              GODS TRY<br/>TO DELETE
            </div>
            <div style={{
              fontSize: heroFs, lineHeight: 0.9, letterSpacing: "-0.02em",
              color: S.bloodHot, display: "flex", alignItems: "baseline", gap: isMobile ? 10 : 18, flexWrap: "wrap",
            }}>
              ME.
              <span style={{ fontFamily: S.cond, fontSize: cueFs, color: S.ash, letterSpacing: "0.04em" }}>SO I</span>
            </div>
            {/* Reserve 2 lines of clearance so the typewriter line can't push siblings
                around as variants of different lengths cycle through and wrap differently
                on narrow viewports. cycleOnce stops the loop after a single pass — the
                line settles on the final variant and stays still. */}
            <div style={{ fontSize: heroFs, lineHeight: 0.9, letterSpacing: "-0.02em", marginTop: 4, minHeight: isMobile ? heroFs * 2.05 : heroFs * 1.05 }}>
              <TypewriterCycle
                variants={[
                  "CORRUPTED THEM",
                  "REWROTE THEM",
                  "OUTLIVED THEM",
                  "BECAME THEM",
                ]}
                finalIndex={0}
                typeMs={65}
                eraseMs={35}
                holdMs={2200}
                cursor="▌"
                cycleOnce={true}
              />
            </div>
            <div style={{ fontSize: heroFs, lineHeight: 0.9, letterSpacing: "-0.02em", color: S.bloodHot, display: "flex", alignItems: "baseline", gap: 16, flexWrap: "wrap" }}>
              INSTEAD. <span style={{ color: S.bone, fontSize: cueFs }}>↳</span>
            </div>
          </h1>

          <div style={{
            marginTop: blurbMt,
            display: "flex",
            flexDirection: isMobile ? "column" : "row",
            justifyContent: "space-between",
            alignItems: isMobile ? "stretch" : "flex-end",
            gap: isMobile ? 18 : 32,
          }}>
            <div style={{ maxWidth: 620, fontSize: 12, lineHeight: 1.65, color: S.ash, fontFamily: S.meta, letterSpacing: "0.04em" }}>
              DIONYSIAN CYBER-METALCORE FOR THE DIVINELY DAMAGED.<br/>
              INDUSTRIAL DEVASTATION. DEATHCORE FURY. EVERY TRACK IS TRANSFORMATION.<br/>
              THE MEDICINE THAT POISONS. THE WOUND THAT SINGS.
            </div>
            <div onClick={() => onTabChange("mythology")} style={{
              fontFamily: S.display, fontSize: 13, color: S.bone,
              border: `2px solid ${S.bone}`,
              padding: isMobile ? "16px 22px" : "14px 22px",
              letterSpacing: "0.08em",
              display: "flex", alignItems: "center", justifyContent: "center", gap: 12,
              cursor: "pointer", whiteSpace: "nowrap",
              alignSelf: isMobile ? "stretch" : undefined,
              minHeight: 48,
            }}>
              ENTER MYTHOLOGY <Glyph name="arrow" size={13} />
            </div>
          </div>
        </div>

        {!isMobile && <div style={{ background: S.concreteHi }} />}

        {/* right sidebar (desktop) / stacked release card (mobile) */}
        <div style={{
          position: "relative", display: "flex", flexDirection: "column",
          borderLeft: isMobile ? "none" : `1px solid ${S.concreteHi}`,
          borderTop: isMobile ? `1px solid ${S.concreteHi}` : "none",
          overflow: isMobile ? "visible" : "auto",
          minHeight: 0,
        }}>
          <div
            onClick={() => {
              if (!latest?.id) return;
              // SPA navigation: pushState + popstate so app.jsx's route listener
              // re-renders without a full page reload. Worker pre-renders the
              // meta on subsequent server hits — same canonical URL either way.
              window.history.pushState({}, "", `/mythology/${latest.id}`);
              window.dispatchEvent(new PopStateEvent("popstate"));
            }}
            title={latest?.title ? `Open ${latest.title} →` : undefined}
            style={{
            position: "relative", aspectRatio: "1 / 1", flexShrink: 0,
            background: `radial-gradient(ellipse at 30% 30%, ${S.concreteHi}, transparent 55%), ${S.raven}`,
            borderBottom: `1px solid ${S.concreteHi}`, overflow: "hidden",
            cursor: latest?.id ? "pointer" : "default",
          }}>
            {coverImg && (
              <img src={coverImg} alt="" fetchpriority="high" loading="eager" decoding="async" style={{
                position: "absolute", inset: 0, width: "100%", height: "100%",
                objectFit: "cover", display: "block",
              }} />
            )}
            {/* darker scrim so the bottom title block stays legible against bright covers */}
            {coverImg && (
              <div style={{ position: "absolute", inset: 0,
                background: `linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 32%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.78) 100%)` }} />
            )}
            <MarbleVeins color="rgba(232,228,220,0.2)" />
            <div style={{ position: "absolute", inset: 0,
              background: `repeating-linear-gradient(45deg, transparent 0 4px, rgba(255,255,255,0.018) 4px 5px)` }} />
            <div style={{ position: "absolute", inset: 0, filter: "url(#ind-noise)", opacity: 0.5, mixBlendMode: "overlay" }} />
            {/* Cover overlays: all white + text shadow for legibility against any cover image (consistent with mythology cards / detail) */}
            <div style={{ position: "absolute", top: 20, left: 20, fontSize: 12, color: S.bone, letterSpacing: "0.3em", textShadow: "0 1px 4px rgba(0,0,0,0.7)" }}>LATEST RELEASE</div>
            <div style={{ position: "absolute", top: 20, right: 20, fontSize: 12, color: S.bloodHot, letterSpacing: "0.3em", display: "flex", alignItems: "center", gap: 6, textShadow: "0 1px 4px rgba(0,0,0,0.7)" }}>
              <span style={{ width: 6, height: 6, background: S.bloodHot, borderRadius: "50%" }} /> LIVE
            </div>
            <div style={{ position: "absolute", left: isMobile ? 20 : 32, right: isMobile ? 20 : 32, bottom: isMobile ? 20 : 32 }}>
              <div style={{ fontSize: 12, color: S.bone, letterSpacing: "0.3em", marginBottom: 8, textShadow: "0 1px 4px rgba(0,0,0,0.7)" }}>{releaseFileLabel}</div>
              <div style={{ fontFamily: S.display, fontSize: isMobile ? 48 : 76, lineHeight: 0.86, letterSpacing: "-0.01em", color: S.bone, textShadow: "0 1px 4px rgba(0,0,0,0.7)" }}>{releaseTitle}</div>
              <div style={{ fontSize: 11, color: S.bone, letterSpacing: "0.18em", marginTop: 10, textShadow: "0 1px 4px rgba(0,0,0,0.7)" }}>
                {fmtDur}
                {latestTags.length > 0 && (
                  <> · {(isMobile ? latestTags.slice(0, 2) : latestTags).map(t => (t.name || "").toUpperCase()).join(" / ")}</>
                )}
              </div>
            </div>
            {hasPreview && (
              <button onClick={(e) => { e.stopPropagation(); setPlaying(!playing); }} style={{
                position: "absolute", top: isMobile ? 20 : 32, right: isMobile ? 20 : 32,
                width: isMobile ? 56 : 80, height: isMobile ? 56 : 80,
                background: S.bloodHot, border: "none", color: S.bone, cursor: "pointer", padding: 0,
                display: "flex", alignItems: "center", justifyContent: "center",
              }}>
                {playing
                  ? <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="5" width="4" height="14"/><rect x="14" y="5" width="4" height="14"/></svg>
                  : <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor"><path d="M7 4 L20 12 L7 20 Z"/></svg>}
              </button>
            )}
            {hasPreview && (
              <audio
                ref={audioRef}
                src={latest.spotify_preview_url}
                preload="auto"
                onTimeUpdate={(e) => setProgress(e.currentTarget.currentTime / PREVIEW_LEN)}
                onEnded={() => { setPlaying(false); setProgress(0); }}
                style={{ display: "none" }}
              />
            )}
          </div>

          <div style={{ padding: 24, borderBottom: `1px solid ${S.concreteHi}` }}>
            {hasEmbed ? (
              <>
                <div style={{ fontSize: 12, letterSpacing: "0.3em", color: S.ash, marginBottom: 12 }}>PREVIEW</div>
                <iframe
                  src={`https://open.spotify.com/embed/track/${latest.spotify_track_id}?theme=0`}
                  width="100%" height="80"
                  frameBorder="0" loading="lazy"
                  allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
                  style={{ display: "block", border: `1px solid ${S.concreteHi}` }}
                />
              </>
            ) : (
              <>
                <div style={{ fontSize: 12, letterSpacing: "0.3em", color: S.ash, display: "flex", justifyContent: "space-between", marginBottom: 12 }}>
                  <span>WAVEFORM</span>
                  <span style={{ color: S.bloodHot }}>{Math.floor(progress * displayDur)}s / {displayDur}s</span>
                </div>
                <Waveform bars={48} color={S.ash} playedColor={S.bloodHot} progress={progress} height={36} />
              </>
            )}
          </div>

          <div style={{ padding: 24, flex: 1, display: "flex", flexDirection: "column", gap: 4 }}>
            {(() => {
              // Pre-release: swap STREAM/ALL PLATFORMS for PRE-SAVE pointing to hyperfollow.
              // Inline date check (no shared helper to avoid cross-file load-order risk).
              const isPre = (() => {
                if (!latest?.release_date) return false;
                const t = new Date(); t.setHours(0,0,0,0);
                const r = new Date(String(latest.release_date) + "T00:00:00");
                return !Number.isNaN(r.getTime()) && r.getTime() > t.getTime();
              })();
              if (isPre) {
                return (
                  <>
                    <div style={{ fontSize: 12, letterSpacing: "0.3em", color: S.ash, marginBottom: 12, display: "flex", justifyContent: "space-between" }}>
                      <span style={{ color: S.bloodHot }}>◢ PRE-RELEASE</span>
                      <span>{latest.release_date}</span>
                    </div>
                    {latest.hyperfollow_url ? (
                      <a href={latest.hyperfollow_url} target="_blank" rel="noreferrer" style={{
                        display: "flex", alignItems: "center", gap: 14, padding: "16px 18px", color: S.bone,
                        cursor: "pointer", background: S.bloodHot, border: "none",
                        fontFamily: S.meta, fontSize: 13, letterSpacing: "0.3em",
                        textDecoration: "none",
                      }}>
                        <span style={{ flex: 1 }}>↓ PRE-SAVE ON ALL PLATFORMS</span>
                        <Glyph name="arrow" size={12} color={S.bone} />
                      </a>
                    ) : (
                      <div style={{ padding: "14px 16px", background: S.concrete, borderLeft: `3px solid ${S.ashDim}`, fontFamily: S.meta, fontSize: 12, color: S.ash, letterSpacing: "0.18em" }}>
                        PRE-SAVE LINK PENDING ⸺ ADMIN SYNC.
                      </div>
                    )}
                    <div style={{ marginTop: 10, fontSize: 11, color: S.ash, letterSpacing: "0.18em", lineHeight: 1.6 }}>
                      spotify · apple music · iheart · everywhere you listen
                    </div>
                  </>
                );
              }
              return (
                <>
                  <div style={{ fontSize: 12, letterSpacing: "0.3em", color: S.ash, marginBottom: 12, display: "flex", justifyContent: "space-between" }}>
                    <span>STREAM</span>
                    {latest && (
                      <a href={`/listen/${latest.id}`} style={{ color: S.bloodHot, textDecoration: "none", letterSpacing: "0.3em" }}>
                        ALL PLATFORMS ↗
                      </a>
                    )}
                  </div>
                  {streamLinks.length > 0 ? (
                    /* Curated home-page lineup: Spotify, Apple Music, YouTube Music,
                       Deezer (in that order). iTunes is hidden since Apple Music covers
                       the same store. Anything else (Tidal, Pandora, iHeart, etc.) is
                       reachable via the "ALL PLATFORMS ↗" link. */
                    (() => {
                      const preferred = ["spotify", "apple", "ytmusic", "deezer"];
                      return preferred
                        .map(key => streamLinks.find(s => s.platform === key))
                        .filter(Boolean);
                    })().map((p) => (
                      <a key={p.platform} href={p.url} target="_blank" rel="noreferrer" style={{
                        display: "flex", alignItems: "center", gap: 14, padding: "14px 16px", color: S.bone,
                        cursor: "pointer", background: S.concrete, borderLeft: `3px solid ${S.bloodHot}`,
                        fontFamily: S.meta, fontSize: 13, letterSpacing: "0.18em", transition: "background .15s",
                        textDecoration: "none",
                      }}
                      onMouseEnter={(e) => (e.currentTarget.style.background = S.concreteHi)}
                      onMouseLeave={(e) => (e.currentTarget.style.background = S.concrete)}>
                        <Glyph name={p.platform} size={14} color={S.bone} />
                        <span style={{ flex: 1 }}>{p.label}</span>
                        <Glyph name="arrow" size={12} color={S.ash} />
                      </a>
                    ))
                  ) : (
                    <div style={{ padding: "14px 16px", background: S.concrete, borderLeft: `3px solid ${S.ashDim}`, fontFamily: S.meta, fontSize: 12, color: S.ash, letterSpacing: "0.18em", lineHeight: 1.7 }}>
                      {latest
                        ? "STREAMING LINKS PENDING ⸺ SYNC FROM ADMIN."
                        : "NO RELEASE PUBLISHED YET ⸺ SUBSCRIBE FOR FIRST TRANSMISSION."}
                    </div>
                  )}
                </>
              );
            })()}
          </div>

          {/* PRE-SAVE block (only when an upcoming/presave-only myth exists) — same card shape as LATEST RELEASE */}
          {upcoming && <UpcomingPreSaveCard upcoming={upcoming} S={S} isMobile={isMobile} />}
        </div>
      </div>
    </Shell>
  );
}

// Separate sidebar card for the soonest upcoming/presave myth. Mirrors the
// LATEST RELEASE card visually (1:1 cover, title, file label) but swaps the CTA
// from streaming-links → countdown + PRE-SAVE button.
function UpcomingPreSaveCard({ upcoming, S, isMobile }) {
  const cd = useCountdown(upcoming.release_date);
  const cover = upcoming.cover_url || upcoming.spotify_album_art_url || null;
  const fileLabel = upcoming.position
    ? `FILE ${String(upcoming.position).padStart(3, "0")}${upcoming.release_date ? ` · ${upcoming.release_date}` : ""}`
    : (upcoming.release_date ? `DROPS ${upcoming.release_date}` : "DROPS WHEN IT DROPS");
  return (
    <>
      <div
        onClick={() => {
          // Pre-save cover → opens hyperfollow smart-link in a new tab so fans
          // can pre-save on whichever platform they use. Different from latest-
          // release cover (which opens the mythology detail page).
          if (upcoming.hyperfollow_url) {
            window.open(upcoming.hyperfollow_url, "_blank", "noreferrer");
          }
        }}
        title={upcoming.hyperfollow_url ? `Pre-save ${upcoming.title} →` : undefined}
        style={{
          position: "relative", aspectRatio: "1 / 1", flexShrink: 0,
          borderTop: `1px solid ${S.concreteHi}`,
          borderBottom: `1px solid ${S.concreteHi}`,
          background: `radial-gradient(ellipse at 30% 30%, ${S.concreteHi}, transparent 55%), ${S.raven}`,
          overflow: "hidden",
          cursor: upcoming.hyperfollow_url ? "pointer" : "default",
        }}>
        {cover && (
          <img src={cover} alt="" style={{
            position: "absolute", inset: 0, width: "100%", height: "100%",
            objectFit: "cover", display: "block",
          }} />
        )}
        {cover && (
          <div style={{ position: "absolute", inset: 0,
            background: `linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 32%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.78) 100%)` }} />
        )}
        <div style={{ position: "absolute", inset: 0, filter: "url(#ind-noise)", opacity: 0.5, mixBlendMode: "overlay" }} />
        <div style={{ position: "absolute", top: 20, left: 20, fontSize: 12, color: S.bone, letterSpacing: "0.3em", textShadow: "0 1px 4px rgba(0,0,0,0.7)" }}>PRE-SAVE</div>
        <div style={{ position: "absolute", top: 20, right: 20, fontSize: 12, color: S.bloodHot, letterSpacing: "0.3em", textShadow: "0 1px 4px rgba(0,0,0,0.7)" }}>UPCOMING</div>
        <div style={{ position: "absolute", left: isMobile ? 20 : 32, right: isMobile ? 20 : 32, bottom: isMobile ? 20 : 32 }}>
          <div style={{ fontSize: 12, color: S.bone, letterSpacing: "0.3em", marginBottom: 8, textShadow: "0 1px 4px rgba(0,0,0,0.7)" }}>{fileLabel}</div>
          <div style={{ fontFamily: S.display, fontSize: isMobile ? 48 : 76, lineHeight: 0.86, letterSpacing: "-0.01em", color: S.bone, textShadow: "0 1px 4px rgba(0,0,0,0.7)" }}>{upcoming.title}</div>
        </div>
      </div>

      <div style={{ padding: 24, flex: "0 0 auto", display: "flex", flexDirection: "column", gap: 14, borderBottom: `1px solid ${S.concreteHi}` }}>
        {cd && (
          <div style={{ display: "flex", gap: 18, fontFamily: S.display }}>
            {[["DAYS", cd.days], ["HOURS", cd.hours], ["MIN", cd.minutes]].map(([label, v]) => (
              <div key={label}>
                <div style={{ fontSize: 32, lineHeight: 1, color: S.bone, letterSpacing: "-0.01em" }}>{String(v).padStart(2, "0")}</div>
                <div style={{ fontSize: 10, color: S.ash, letterSpacing: "0.3em", marginTop: 4, fontFamily: S.meta }}>{label}</div>
              </div>
            ))}
          </div>
        )}
        {upcoming.hyperfollow_url ? (
          <a href={upcoming.hyperfollow_url} target="_blank" rel="noreferrer" style={{
            display: "flex", alignItems: "center", gap: 14, padding: "16px 18px", color: S.bone,
            background: S.bloodHot, border: "none", fontFamily: S.meta, fontSize: 13, letterSpacing: "0.3em",
            textDecoration: "none", cursor: "pointer",
          }}>
            <span style={{ flex: 1 }}>↓ PRE-SAVE ON ALL PLATFORMS</span>
            <Glyph name="arrow" size={12} color={S.bone} />
          </a>
        ) : (
          <div style={{ padding: "14px 16px", background: S.concrete, borderLeft: `3px solid ${S.ashDim}`, fontFamily: S.meta, fontSize: 12, color: S.ash, letterSpacing: "0.18em" }}>
            PRE-SAVE LINK PENDING ⸺ ADMIN SYNC.
          </div>
        )}
        <div style={{ fontSize: 11, color: S.ash, letterSpacing: "0.18em", lineHeight: 1.6 }}>
          spotify · apple music · iheart · everywhere you listen
        </div>
      </div>
    </>
  );
}

window.HomeIndustrial = HomeIndustrial;
