/* CrossCurrent Racing — shared site shell.
   Exports nav / footer / hero / discord beacon / band helpers + site data
   onto window so every page (each its own Babel scope) can use them. */
(function () {
  const D = window.CrossCurrentRacingDesignSystem_c4f6ec;
  const { CurrentStripe, Button, TextLink, Tag } = D;
  const { useState, useEffect, useRef } = React;

  const LOGO = "assets/logos/crosscurrent-logo.jpg";
  const DISCORD = "https://discord.gg/RUucJh26u7";
  const GUILD_ID = "1478477879926067335";

  /* ---- Global navigation (real hyperlinks between pages) ---- */
  const PAGES = [
    { label: "Home", href: "index.html" },
    { label: "About", href: "about.html" },
    { label: "Drivers", href: "drivers.html" },
    { label: "Races", href: "races.html" },
    { label: "Results", href: "results.html" },
    { label: "Gallery", href: "gallery.html" },
    { label: "Apps", href: "apps.html" },
    { label: "Contact", href: "contact.html" },
  ];

  /* ---- Shared Discord auth (real OAuth2 via /api/auth/*, see HANDOFF.md seam 1) ----
     Identity/permissions live server-side (signed httpOnly session cookie + a live
     Discord role check on every /api/auth/me call, so a role change in Discord takes
     effect immediately without forcing a re-login). The client just mirrors whatever
     the backend reports; there is nothing to trust on this side. */
  const SIGNED_OUT_AUTH = { authenticated: false, name: null, isMember: false, isManager: false, isAdmin: false, canManageRaces: false };
  let authFetchPromise = null; // de-dupe: pages that call useAuth() more than once share one request
  function fetchAuth() {
    if (!authFetchPromise) {
      authFetchPromise = fetch("/api/auth/me", { credentials: "include" })
        .then((r) => (r.ok ? r.json() : SIGNED_OUT_AUTH))
        .catch(() => SIGNED_OUT_AUTH)
        .finally(() => { authFetchPromise = null; });
    }
    return authFetchPromise;
  }
  function useAuth() {
    const [state, setState] = useState(SIGNED_OUT_AUTH);
    useEffect(() => {
      let alive = true;
      const load = () => fetchAuth().then((d) => { if (alive) setState(d); });
      load();
      window.addEventListener("cc-auth-change", load);
      return () => { alive = false; window.removeEventListener("cc-auth-change", load); };
    }, []);
    return {
      auth: state.authenticated ? { name: state.name } : null,
      isMember: state.isMember,
      isManager: state.isManager,
      isAdmin: state.isAdmin,
      canManageRaces: state.canManageRaces,
      signIn: () => { window.location.href = "/api/auth/discord/login?returnTo=" + encodeURIComponent(location.pathname); },
      signOut: () => {
        fetch("/api/auth/logout", { method: "POST", credentials: "include" })
          .finally(() => window.dispatchEvent(new CustomEvent("cc-auth-change")));
      },
    };
  }
  /* ---- Shared data store (races/results/drivers/tracks/stats, see HANDOFF.md
     seam 2). Reads go through /api/data/all so all visitors see the same
     admin-edited content; falls back to the static data.js constants if the
     backend is briefly unreachable, so the site still renders something. ---- */
  function liveFallback() {
    const D = window.CCData || {};
    return {
      roster: D.ROSTER || [], calendar: D.CALENDAR || [], results: D.RESULTS || [],
      tracks: D.TRACKS || [], stats: { racesEntered: "0", enduranceKm: "0" },
    };
  }
  let liveDataPromise = null;
  function fetchLiveData() {
    if (!liveDataPromise) {
      liveDataPromise = fetch("/api/data/all")
        .then((r) => (r.ok ? r.json() : null))
        .catch(() => null)
        .finally(() => { liveDataPromise = null; });
    }
    return liveDataPromise;
  }
  function useLiveData() {
    const [state, setState] = useState(liveFallback);
    const [loading, setLoading] = useState(true);
    const load = () => {
      setLoading(true);
      fetchLiveData().then((d) => { if (d) setState(d); setLoading(false); });
    };
    useEffect(() => { load(); }, []);
    return { ...state, loading, refresh: load };
  }

  function navAuthBtn(primary) {
    return {
      font: "var(--type-body-sm)", fontSize: "12px", letterSpacing: "1.5px", textTransform: "uppercase",
      cursor: "pointer", padding: "8px 14px", border: "1px solid " + (primary ? "var(--cc-red)" : "var(--cc-hairline)"),
      background: primary ? "var(--cc-red)" : "transparent", color: primary ? "#fff" : "var(--cc-body)",
    };
  }
  function AuthModal({ onClose, onSignIn }) {
    const mbtn = {
      font: "var(--type-body-sm)", fontWeight: 700, fontSize: "13px", letterSpacing: "1.5px", textTransform: "uppercase",
      cursor: "pointer", padding: "14px 18px", border: "none", background: "var(--cc-red)", color: "#fff", textAlign: "left",
    };
    return (
      <div onClick={onClose} style={{ position: "fixed", inset: 0, zIndex: 200, background: "rgba(0,0,0,0.72)", backdropFilter: "blur(4px)", display: "flex", alignItems: "center", justifyContent: "center", padding: "24px" }}>
        <div onClick={(e) => e.stopPropagation()} style={{ position: "relative", width: "min(440px,100%)", background: "var(--cc-surface-card)", border: "1px solid var(--cc-hairline-strong)", padding: "var(--space-xl)", display: "flex", flexDirection: "column", gap: "var(--space-md)", overflow: "hidden" }}>
          <div style={{ position: "absolute", top: 0, left: 0, right: 0, height: "4px", background: "var(--cc-stripe)" }} />
          <span style={{ font: "var(--type-body-sm)", fontWeight: 700, fontSize: "12px", letterSpacing: "var(--tracking-label)", textTransform: "uppercase", color: "var(--cc-cyan)" }}>CrossCurrent · Members</span>
          <h3 style={{ margin: 0, font: "var(--type-display-sm)", textTransform: "uppercase", letterSpacing: "-0.5px", color: "var(--cc-on-dark)" }}>Sign in with Discord</h3>
          <p style={{ margin: 0, font: "var(--type-body-md)", color: "var(--cc-body)" }}>We check your role in the CrossCurrent Discord to unlock members-only tools.</p>
          <div style={{ display: "flex", flexDirection: "column", gap: "10px", marginTop: "var(--space-xs)" }}>
            <button onClick={onSignIn} style={mbtn}>Continue with Discord ›</button>
          </div>
        </div>
      </div>
    );
  }

  function SiteNav({ active }) {
    const [hover, setHover] = useState(null);
    const { auth, signIn, signOut, isAdmin, canManageRaces } = useAuth();
    const [modal, setModal] = useState(false);
    const items = canManageRaces ? [...PAGES, { label: "Admin", href: "admin.html", admin: true }] : PAGES;
    return (
      <header
        style={{
          position: "sticky", top: 0, zIndex: 50,
          background: "rgba(0,0,0,0.86)", backdropFilter: "blur(8px)",
          borderBottom: "1px solid var(--cc-hairline-strong)",
        }}
      >
        <div
          style={{
            display: "flex", alignItems: "center", justifyContent: "space-between", gap: "var(--space-lg)",
            minHeight: "var(--nav-height)", padding: "10px var(--space-xl)",
            maxWidth: "var(--content-max)", margin: "0 auto", flexWrap: "wrap",
          }}
        >
          <a href="index.html" style={{ display: "inline-flex", alignItems: "center", gap: "12px", textDecoration: "none" }}>
            <CurrentStripe width="7px" height="24px" style={{ display: "inline-block" }} />
            <span style={{ font: "var(--type-title-md)", fontWeight: 700, fontSize: "19px", letterSpacing: "1px", textTransform: "uppercase", color: "var(--cc-on-dark)" }}>
              CROSSCURRENT
            </span>
          </a>
          <div style={{ display: "flex", alignItems: "center", gap: "22px", flexWrap: "wrap", justifyContent: "flex-end" }}>
            <nav style={{ display: "flex", gap: "22px", flexWrap: "wrap", justifyContent: "flex-end" }}>
              {items.map((p) => {
                const isActive = p.label === active;
                const isHover = hover === p.label;
                return (
                  <a
                    key={p.label}
                    href={p.href}
                    onMouseEnter={() => setHover(p.label)}
                    onMouseLeave={() => setHover(null)}
                    style={{
                      font: "var(--type-body-sm)", fontSize: "14px", letterSpacing: "0.5px",
                      textDecoration: "none",
                      color: p.admin ? "var(--cc-cyan)" : (isActive || isHover ? "var(--cc-on-dark)" : "var(--cc-body)"),
                      paddingBottom: "2px",
                      borderBottom: isActive ? "2px solid var(--cc-red)" : "2px solid transparent",
                      transition: "color var(--dur-fast) var(--ease-standard)",
                    }}
                  >
                    {p.admin ? "◈ Admin" : p.label}
                  </a>
                );
              })}
            </nav>
            {auth ? (
              <div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
                <span style={{ display: "inline-flex", alignItems: "center", gap: "8px", font: "var(--type-body-sm)", fontSize: "12px", letterSpacing: "0.5px", color: "var(--cc-body-strong)" }}>
                  <span className="cc-beacon-dot" style={{ background: "var(--cc-success)", boxShadow: "none", animation: "none" }} />
                  {auth.name}
                </span>
                <button onClick={signOut} style={navAuthBtn(false)}>Sign out</button>
              </div>
            ) : (
              <button onClick={() => setModal(true)} style={navAuthBtn(true)}>Sign in</button>
            )}
          </div>
        </div>
        {modal && <AuthModal onClose={() => setModal(false)} onSignIn={signIn} />}
      </header>
    );
  }

  /* ---- Content band + head ---- */
  function Band({ children, style }) {
    return (
      <section style={{ padding: "var(--space-section) var(--space-xl)", maxWidth: "var(--content-max)", margin: "0 auto", ...style }}>
        {children}
      </section>
    );
  }
  function BandHead({ eyebrow, title, link, href = "#" }) {
    return (
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", marginBottom: "var(--space-xl)", gap: "24px", flexWrap: "wrap" }}>
        <div style={{ display: "flex", flexDirection: "column", gap: "12px" }}>
          {eyebrow && <Tag accent>{eyebrow}</Tag>}
          <h2 style={{ margin: 0, font: "var(--type-display-lg)", textTransform: "uppercase", letterSpacing: "-0.5px", color: "var(--cc-on-dark)" }}>{title}</h2>
        </div>
        {link && <TextLink href={href}>{link}</TextLink>}
      </div>
    );
  }

  /* ---- Per-page hero (distinct treatment via props, one structure) ---- */
  function PageHero({ eyebrow, title, subtitle, align = "left", accent = "var(--cc-red)", meta, children, minHeight = 380 }) {
    const centered = align === "center";
    return (
      <section style={{ position: "relative", width: "100%", background: "var(--cc-canvas)", overflow: "hidden", borderBottom: "1px solid var(--cc-hairline-strong)" }}>
        {/* carbon telemetry field */}
        <div style={{
          position: "absolute", inset: 0,
          background: "repeating-linear-gradient(115deg, #101216 0px, #101216 2px, #0b0d10 2px, #0b0d10 9px), radial-gradient(120% 140% at 82% 8%, rgba(47,165,232,0.16), transparent 55%), radial-gradient(120% 140% at 12% 100%, rgba(224,31,38,0.16), transparent 55%)",
        }} />
        <div style={{ position: "absolute", inset: 0, background: "linear-gradient(90deg, rgba(0,0,0,0.9), rgba(0,0,0,0.45) 60%, rgba(0,0,0,0.2))" }} />
        <div style={{
          position: "relative", maxWidth: "var(--content-max)", margin: "0 auto",
          minHeight: `${minHeight}px`, display: "flex", flexDirection: "column",
          justifyContent: "flex-end", alignItems: centered ? "center" : "flex-start",
          textAlign: centered ? "center" : "left",
          gap: "var(--space-md)", padding: "var(--space-xxl) var(--space-xl) var(--space-xl)",
        }}>
          <div style={{ width: "60px", height: "4px", background: accent }} />
          {eyebrow && <span style={{ font: "var(--type-body-sm)", fontWeight: 700, fontSize: "13px", letterSpacing: "var(--tracking-label)", textTransform: "uppercase", color: "var(--cc-body-strong)" }}>{eyebrow}</span>}
          <h1 style={{ margin: 0, font: "var(--type-display-xl)", fontSize: "clamp(44px, 7vw, 80px)", letterSpacing: "var(--tracking-display)", textTransform: "uppercase", color: "var(--cc-on-dark)", whiteSpace: "pre-line" }}>{title}</h1>
          {subtitle && <p style={{ margin: 0, maxWidth: "620px", font: "var(--type-title-md)", fontWeight: 300, color: "var(--cc-body-strong)" }}>{subtitle}</p>}
          {meta && <div style={{ marginTop: "var(--space-xs)" }}>{meta}</div>}
          {children}
        </div>
      </section>
    );
  }

  /* ---- Discord "team radio" beacon — on-theme comms channel ---- */
  function DiscordBeacon({ compact = false, memberCount = 128 }) {
    const [online, setOnline] = useState(null);
    useEffect(() => {
      let alive = true;
      const load = () => fetch(`https://discord.com/api/guilds/${GUILD_ID}/widget.json`)
        .then((r) => (r.ok ? r.json() : null))
        .then((d) => { if (alive && d && typeof d.presence_count === "number") setOnline(d.presence_count); })
        .catch(() => {});
      load();
      const id = setInterval(load, 60000);
      return () => { alive = false; clearInterval(id); };
    }, []);
    const count = online != null ? online : memberCount;
    return (
      <div style={{
        position: "relative", background: "var(--cc-surface-card)",
        border: "1px solid var(--cc-hairline-strong)", padding: compact ? "var(--space-lg)" : "var(--space-xl)",
        display: "flex", flexDirection: "column", gap: "var(--space-lg)", overflow: "hidden",
      }}>
        <div style={{ position: "absolute", top: 0, left: 0, right: 0, height: "4px", background: "var(--cc-stripe)" }} />
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: "var(--space-md)", flexWrap: "wrap" }}>
          <div style={{ display: "flex", alignItems: "center", gap: "12px" }}>
            <span className="cc-beacon-dot" />
            <span style={{ font: "var(--type-body-sm)", fontWeight: 700, fontSize: "12px", letterSpacing: "var(--tracking-label)", textTransform: "uppercase", color: "var(--cc-cyan)" }}>
              Team radio · live
            </span>
          </div>
          <span style={{ font: "var(--type-body-sm)", fontSize: "12px", letterSpacing: "1px", textTransform: "uppercase", color: "var(--cc-muted)" }}>
            {count} online · on the paddock channel
          </span>
        </div>

        {/* waveform */}
        <div aria-hidden="true" style={{ display: "flex", alignItems: "flex-end", gap: "4px", height: compact ? "40px" : "64px" }}>
          {Array.from({ length: 40 }).map((_, i) => (
            <span key={i} className="cc-wave-bar" style={{ animationDelay: `${(i % 12) * 90}ms` }} />
          ))}
        </div>

        <div style={{ display: "flex", flexDirection: compact ? "column" : "row", alignItems: compact ? "stretch" : "center", justifyContent: "space-between", gap: "var(--space-md)" }}>
          <div style={{ display: "flex", flexDirection: "column", gap: "4px" }}>
            <span style={{ font: "var(--type-title-lg)", fontWeight: 700, textTransform: "uppercase", color: "var(--cc-on-dark)" }}>Open the comms</span>
            <span style={{ font: "var(--type-body-sm)", color: "var(--cc-body)" }}>
              Setups, stint planning, banter and other games — all in our Discord.
            </span>
          </div>
          <a href={DISCORD} target="_blank" rel="noopener" style={{ textDecoration: "none" }}>
            <Button variant="solid" iconAfter={<span aria-hidden="true">›</span>}>Tune in on Discord</Button>
          </a>
        </div>
      </div>
    );
  }

  function SiteFooter() {
    const columns = [
      { title: "Racing", links: [["Upcoming races", "races.html"], ["Race results", "results.html"], ["The grid", "drivers.html"]] },
      { title: "Team", links: [["About us", "about.html"], ["Gallery", "gallery.html"], ["Team apps", "apps.html"]] },
      { title: "Community", links: [["Discord", DISCORD], ["Contact", "contact.html"]] },
    ];
    return (
      <footer style={{ background: "var(--cc-canvas)", color: "var(--cc-body)", borderTop: "1px solid var(--cc-hairline-strong)" }}>
        <CurrentStripe height={4} />
        <div style={{ padding: "var(--space-xxl) var(--space-xl)", maxWidth: "var(--content-max)", margin: "0 auto" }}>
          <div style={{ display: "flex", flexWrap: "wrap", justifyContent: "space-between", gap: "var(--space-xl)" }}>
            <div style={{ maxWidth: "300px", display: "flex", flexDirection: "column", gap: "14px" }}>
              <div style={{ display: "inline-flex", alignItems: "center", gap: "10px" }}>
                <CurrentStripe width="6px" height="22px" />
                <span style={{ font: "var(--type-title-md)", fontWeight: 700, textTransform: "uppercase", letterSpacing: "1px", color: "var(--cc-on-dark)" }}>CrossCurrent Racing</span>
              </div>
              <p style={{ margin: 0, font: "var(--type-body-sm)", color: "var(--cc-muted)" }}>Different currents, one racing line. A global sim-racing community with roots in the UK and US.</p>
            </div>
            <div style={{ display: "flex", gap: "var(--space-xxl)", flexWrap: "wrap" }}>
              {columns.map((col) => (
                <div key={col.title} style={{ display: "flex", flexDirection: "column", gap: "var(--space-md)", minWidth: "150px" }}>
                  <div style={{ font: "var(--type-body-sm)", fontWeight: 700, fontSize: "12px", letterSpacing: "var(--tracking-label)", textTransform: "uppercase", color: "var(--cc-on-dark)" }}>{col.title}</div>
                  {col.links.map(([l, href]) => (
                    <a key={l} href={href} style={{ font: "var(--type-body-sm)", color: "var(--cc-muted)", textDecoration: "none" }}>{l}</a>
                  ))}
                </div>
              ))}
            </div>
          </div>
          <div style={{ marginTop: "var(--space-xxl)", paddingTop: "var(--space-lg)", borderTop: "1px solid var(--cc-hairline-strong)", display: "flex", justifyContent: "space-between", flexWrap: "wrap", gap: "12px" }}>
            <span style={{ font: "var(--type-body-sm)", fontSize: "12px", letterSpacing: "0.5px", color: "var(--cc-muted)" }}>© {new Date().getFullYear()} CrossCurrent Racing. A global sim-racing community. Not affiliated with any vehicle manufacturer.</span>
            <span style={{ font: "var(--type-body-sm)", fontSize: "12px", letterSpacing: "0.5px", color: "var(--cc-muted)" }}>United Kingdom · United States</span>
          </div>
        </div>
      </footer>
    );
  }

  /* Country flag (real flag image via ISO code; falls back to code text) */
  function isoFor(country) {
    const map = (window.CCData && window.CCData.COUNTRY_ISO) || {};
    return map[country] || map[(country || "").toUpperCase()] || null;
  }
  function flagUrl(country) {
    const iso = isoFor(country);
    return iso ? `https://flagcdn.com/${iso}.svg` : null;
  }
  function FlagChip({ country, size = 18 }) {
    const url = flagUrl(country);
    const iso = isoFor(country);
    return (
      <span style={{ display: "inline-flex", alignItems: "center", gap: "8px", font: "var(--type-body-sm)", fontSize: "12px", fontWeight: 700, letterSpacing: "1.5px", textTransform: "uppercase", color: "var(--cc-body)" }}>
        {url && <img src={url} alt="" onError={(e) => { e.currentTarget.style.display = "none"; }} style={{ width: `${size}px`, height: `${Math.round(size * 0.7)}px`, objectFit: "cover", border: "1px solid var(--cc-hairline)", display: "block" }} />}
        {iso ? iso.toUpperCase() : country}
      </span>
    );
  }

  /* ---- Inline admin ribbon (shown on manageable pages when signed in as admin) ---- */
  function AdminRibbon({ title, note, actions }) {
    return (
      <div style={{ position: "relative", display: "flex", alignItems: "center", justifyContent: "space-between", gap: "var(--space-md)", flexWrap: "wrap", background: "var(--cc-surface-card)", border: "1px solid var(--cc-hairline-strong)", borderLeft: "4px solid var(--cc-cyan)", padding: "var(--space-md) var(--space-lg)", marginBottom: "var(--space-xl)" }}>
        <div style={{ display: "flex", flexDirection: "column", gap: "2px" }}>
          <span style={{ font: "var(--type-body-sm)", fontWeight: 700, fontSize: "11px", letterSpacing: "1.5px", textTransform: "uppercase", color: "var(--cc-cyan)" }}>{title || "Admin mode"}</span>
          {note && <span style={{ font: "var(--type-body-sm)", fontSize: "13px", color: "var(--cc-body)" }}>{note}</span>}
        </div>
        {actions && <div style={{ display: "flex", gap: "10px", flexWrap: "wrap" }}>{actions}</div>}
      </div>
    );
  }
  /* ---- Local-timezone formatting for race sessions ---- */
  function localTZAbbr() {
    try {
      const parts = new Intl.DateTimeFormat("en-GB", { timeZoneName: "short" }).formatToParts(new Date());
      const p = parts.find((x) => x.type === "timeZoneName");
      return p ? p.value : "";
    } catch (e) { return ""; }
  }
  function fmtSessionLocal(iso) {
    const d = new Date(iso);
    return {
      day: d.toLocaleDateString([], { weekday: "short", day: "2-digit", month: "short" }),
      time: d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }),
    };
  }

  window.CCSite = {
    LOGO, DISCORD, PAGES,
    SiteNav, SiteFooter, Band, BandHead, PageHero, DiscordBeacon, FlagChip,
    useAuth, AuthModal, AdminRibbon, fmtSessionLocal, localTZAbbr, flagUrl,
    useLiveData,
  };
})();
