// Solo Secure — shared primitives.
// Built strictly to the Solo Brand Identity Guidelines (Version 1.0, 2026).
// Monochrome palette. Eurostile-extended-style headings (Michroma). Helvetica body.

const { useState, useEffect, useMemo, useRef } = React;

/* ──────────────── BRAND TOKENS ────────────────
 * Exposed as a JS object AND as CSS variables on :root (set by app.jsx).
 *
 * Per brand book:
 *   Primary:    #000000 (black), #FFFFFF (white), gradient #545454
 *   Secondary:  #2B2B2B (dark grey), #EAEAEA (near-white), gradient #AFAFAF
 */
const BRAND = {
  black:    "#000000",
  white:    "#FFFFFF",
  grey900:  "#0A0A0A",  // slightly off-pure-black for surfaces
  grey800:  "#1A1A1A",
  grey700:  "#2B2B2B",  // brand secondary dark
  grey500:  "#545454",  // brand primary mid
  grey400:  "#7A7A7A",
  grey300:  "#AFAFAF",  // brand secondary mid
  grey200:  "#D4D4D4",
  grey100:  "#EAEAEA",  // brand secondary light
  grey50:   "#F4F4F4",
};

window.BRAND = BRAND;

/* ──────────────── LOGO ──────────────── */
// Uses the cropped brand-pack PNGs. Switches white/black automatically.
function SoloLogo({ size = 32, variant = "auto", showText = true }) {
  // variant: "auto" → use theme to pick black or white. "black", "white" force.
  const isDark = variant === "auto"
    ? document.documentElement.dataset.theme === "dark"
    : variant === "white";
  const src = showText
    ? (isDark ? "assets/solo-logo-white.png" : "assets/solo-logo.png")
    : (isDark ? "assets/solo-mark-white.png" : "assets/solo-mark.png");
  // Aspect ratios: mark ~0.92 (218x240), full logo ~3.77 (904x240)
  const aspect = showText ? 3.77 : 0.92;
  return (
    <img
      src={src}
      alt="Solo Secure"
      style={{
        height: size,
        width: size * aspect,
        display: "block",
        userSelect: "none",
      }}
      draggable={false}
    />
  );
}

/* ──────────────── SECTION NUMERAL ────────────────
 * Originally a huge two-digit numeral (01, 02...) used to mark sections.
 * Removed per design direction — kept as a no-op so existing call sites
 * remain valid without needing to edit every page. */
function SectionNumeral() {
  return null;
}

/* ──────────────── EYEBROW ────────────────
 * Used everywhere — small caps Helvetica, very tight letterspacing, monochrome only. */
function Eyebrow({ children, style = {} }) {
  return (
    <div style={{
      fontFamily: "var(--font-body)",
      fontSize: 12,
      letterSpacing: "0.22em",
      textTransform: "uppercase",
      color: "var(--fg-dim)",
      fontWeight: 500,
      ...style,
    }}>{children}</div>
  );
}

/* ──────────────── HEADINGS ──────────────── */
// All headings are CAPS in Michroma (Eurostile-Extended substitute).
// Use these wrappers so the type system is consistent.
function H1({ children, style = {} }) {
  return (
    <h1 style={{
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: "clamp(48px, 7.5vw, 116px)",
      lineHeight: 0.96,
      letterSpacing: "-0.01em",
      textTransform: "uppercase",
      color: "var(--fg)",
      margin: 0,
      ...style,
    }}>{children}</h1>
  );
}
function H2({ children, style = {} }) {
  return (
    <h2 style={{
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: "clamp(36px, 4.5vw, 64px)",
      lineHeight: 1.02,
      letterSpacing: "-0.005em",
      textTransform: "uppercase",
      color: "var(--fg)",
      margin: 0,
      ...style,
    }}>{children}</h2>
  );
}
function H3({ children, style = {} }) {
  return (
    <h3 style={{
      fontFamily: "var(--font-display)",
      fontWeight: 700,
      fontSize: "clamp(20px, 1.5vw, 24px)",
      lineHeight: 1.15,
      letterSpacing: "0.01em",
      textTransform: "uppercase",
      color: "var(--fg)",
      margin: 0,
      ...style,
    }}>{children}</h3>
  );
}

/* ──────────────── STAT BLOCK ──────────────── */
function Stat({ value, label, large, dark }) {
  return (
    <div>
      <div style={{
        fontFamily: "var(--font-display)",
        fontWeight: 700,
        fontSize: large ? "clamp(48px, 5.5vw, 80px)" : "clamp(32px, 3.6vw, 48px)",
        letterSpacing: "-0.02em",
        lineHeight: 0.95,
        color: dark ? "var(--invert-fg)" : "var(--fg)",
      }}>{value}</div>
      <div style={{
        fontFamily: "var(--font-body)",
        fontSize: 11,
        letterSpacing: "0.18em",
        textTransform: "uppercase",
        color: dark ? "var(--invert-fg-dim)" : "var(--fg-dim)",
        marginTop: 14,
        fontWeight: 500,
      }}>{label}</div>
    </div>
  );
}

/* ──────────────── STAT ROW LIST ────────────────
 * Vertical, downward-flowing list of label/value rows — the fix for the
 * rigid N-column stat grid layout bug. A CSS grid of stat cells (value
 * heading stacked above a caption label) breaks the moment ONE cell's
 * value or label is longer than its siblings and wraps to an extra line:
 * Grid does not keep sibling cells' internal content vertically synced,
 * so the wrapped cell grows taller while its neighbours stay short,
 * throwing every label out of alignment across the row (a visible
 * jagged/zig-zag effect). Found on the Gold/Platinum/Exclusive Regions
 * pages, then confirmed across most of the site wherever <Stat> (or an
 * equivalent inline value+label block) was placed inside a shared grid
 * row alongside stats of very different text lengths.
 *
 * Stacking each stat in its own full-width row sidesteps the problem
 * entirely — every stat's wrapping is now completely independent of its
 * siblings, so there is nothing left to misalign.
 *
 * `stats`: array of { value, label } objects OR [value, label] tuples.
 * `large`: bigger value type size (matches <Stat large />).
 * `dark`:  light-text-on-dark-background variant (e.g. a black hero band).
 */
function StatRow({ stats, large, dark }) {
  const lineColor = dark ? "rgba(255,255,255,0.14)" : "var(--line)";
  return (
    <div style={{ borderTop: `1px solid ${lineColor}` }}>
      {stats.map((s, i) => {
        const value = Array.isArray(s) ? s[0] : s.value;
        const label = Array.isArray(s) ? s[1] : s.label;
        return (
          <div key={i} style={{
            display: "flex", flexWrap: "wrap",
            alignItems: "baseline", justifyContent: "space-between",
            gap: "8px 32px",
            padding: large ? "32px 0" : "24px 0",
            borderBottom: `1px solid ${lineColor}`,
          }}>
            <span style={{
              fontFamily: "var(--font-body)", fontSize: 12,
              letterSpacing: "0.2em", textTransform: "uppercase",
              color: dark ? "rgba(255,255,255,0.55)" : "var(--fg-dim)",
              fontWeight: 500,
            }}>{label}</span>
            <span style={{
              fontFamily: "var(--font-display)", fontWeight: 700,
              fontSize: large ? "clamp(30px, 4vw, 52px)" : "clamp(26px, 3.2vw, 42px)",
              lineHeight: 1, letterSpacing: "-0.01em", textAlign: "right",
              color: dark ? "#fff" : "var(--fg)",
            }}>{value}</span>
          </div>
        );
      })}
    </div>
  );
}

/* ──────────────── BUTTON ──────────────── */
function Button({ children, primary, onClick, dark, small, white }) {
  const [hover, setHover] = useState(false);
  let style;
  if (primary) {
    style = {
      background: hover ? "var(--grey700)" : "var(--fg)",
      color: "var(--bg)",
      border: "1px solid var(--fg)",
    };
  } else if (white) {
    style = {
      background: hover ? "var(--bg)" : "transparent",
      color: hover ? "var(--fg)" : "var(--invert-fg)",
      border: "1px solid var(--invert-fg)",
    };
  } else if (dark) {
    style = {
      background: hover ? "var(--invert-fg)" : "transparent",
      color: hover ? "var(--bg)" : "var(--invert-fg)",
      border: "1px solid var(--invert-fg)",
    };
  } else {
    style = {
      background: hover ? "var(--surface)" : "transparent",
      color: "var(--fg)",
      border: "1px solid var(--line-strong)",
    };
  }
  return (
    <button onClick={onClick}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        ...style,
        fontFamily: "var(--font-body)",
        fontWeight: 500,
        fontSize: small ? 12 : 13,
        letterSpacing: "0.16em",
        textTransform: "uppercase",
        padding: small ? "12px 18px" : "16px 24px",
        cursor: "pointer",
        transition: "background 140ms, color 140ms",
        display: "inline-flex",
        alignItems: "center",
        gap: 12,
      }}>
      {children}
    </button>
  );
}

/* ──────────────── LIVE CLOCK ──────────────── */
function LiveClock() {
  const [t, setT] = useState(() => new Date());
  useEffect(() => {
    const i = setInterval(() => setT(new Date()), 1000);
    return () => clearInterval(i);
  }, []);
  const pad = (n) => String(n).padStart(2, "0");
  return (
    <span style={{ fontVariantNumeric: "tabular-nums" }}>
      {pad(t.getUTCHours())}:{pad(t.getUTCMinutes())}:{pad(t.getUTCSeconds())} UTC
    </span>
  );
}

/* ──────────────── TOWER SCHEMATIC ──────────────── */
// Clean monochrome line drawing of a CCTV tower — used as placeholder until real product photos drop in.
function TowerSchematic({ width = 280, height = 420, stroke }) {
  const s = stroke || "currentColor";
  return (
    <svg width={width} height={height} viewBox="0 0 280 420" style={{ display: "block", color: s }}>
      <g fill="none" stroke={s} strokeWidth="1.4" strokeLinecap="square">
        {/* Trailer chassis */}
        <rect x="40" y="350" width="200" height="22" />
        <line x1="40" y1="361" x2="240" y2="361" />
        <circle cx="80" cy="385" r="18" />
        <circle cx="200" cy="385" r="18" />
        <circle cx="80" cy="385" r="6" />
        <circle cx="200" cy="385" r="6" />
        <line x1="40" y1="372" x2="20" y2="400" />
        <line x1="240" y1="372" x2="260" y2="400" />
        {/* Cabinet */}
        <rect x="95" y="285" width="90" height="65" />
        <line x1="95" y1="305" x2="185" y2="305" />
        <line x1="95" y1="325" x2="185" y2="325" />
        <rect x="105" y="293" width="14" height="6" />
        {/* Solar wings */}
        <polygon points="40,290 95,272 95,302 40,320" />
        <polygon points="240,290 185,272 185,302 240,320" />
        <line x1="50" y1="285" x2="90" y2="277" />
        <line x1="55" y1="296" x2="92" y2="289" />
        <line x1="48" y1="307" x2="93" y2="298" />
        <line x1="230" y1="285" x2="190" y2="277" />
        <line x1="225" y1="296" x2="188" y2="289" />
        <line x1="232" y1="307" x2="187" y2="298" />
        {/* Mast */}
        <line x1="135" y1="285" x2="135" y2="80" />
        <line x1="145" y1="285" x2="145" y2="80" />
        <line x1="130" y1="150" x2="150" y2="150" />
        <line x1="130" y1="215" x2="150" y2="215" />
        {/* Camera head */}
        <rect x="95" y="50" width="90" height="30" />
        <line x1="95" y1="65" x2="185" y2="65" />
        <circle cx="110" cy="65" r="6" />
        <circle cx="125" cy="65" r="6" />
        <circle cx="140" cy="65" r="6" />
        <circle cx="155" cy="65" r="6" />
        <circle cx="170" cy="65" r="6" />
        {/* PTZ dome */}
        <path d="M 115 50 Q 140 25 165 50 Z" />
        <circle cx="140" cy="40" r="4" />
      </g>
    </svg>
  );
}

/* ──────────────── SOLAR PANEL SCHEMATIC ────────────────
 * Used as a placeholder for the RS1 / RS2 solar add-ons. Two-piece
 * lightweight design — drawn as two angled panels on simple stands. */
function SolarPanelSchematic({ width = 280, height = 320, stroke }) {
  const s = stroke || "currentColor";
  return (
    <svg width={width} height={height} viewBox="0 0 280 320" style={{ display: "block", color: s }}>
      <g fill="none" stroke={s} strokeWidth="1.4" strokeLinecap="square">
        {/* Ground line */}
        <line x1="20" y1="280" x2="260" y2="280" />
        {/* Left panel — angled */}
        <polygon points="30,180 130,140 130,220 30,260" />
        {/* Cell divisions on left panel */}
        <line x1="55" y1="170" x2="55" y2="250" />
        <line x1="80" y1="160" x2="80" y2="240" />
        <line x1="105" y1="150" x2="105" y2="230" />
        <line x1="30" y1="200" x2="130" y2="170" />
        <line x1="30" y1="220" x2="130" y2="190" />
        <line x1="30" y1="240" x2="130" y2="210" />
        {/* Left stand */}
        <line x1="80" y1="220" x2="60" y2="280" />
        <line x1="80" y1="220" x2="100" y2="280" />
        {/* Right panel — angled */}
        <polygon points="150,140 250,180 250,260 150,220" />
        {/* Cell divisions on right */}
        <line x1="175" y1="148" x2="175" y2="228" />
        <line x1="200" y1="158" x2="200" y2="238" />
        <line x1="225" y1="168" x2="225" y2="248" />
        <line x1="150" y1="170" x2="250" y2="200" />
        <line x1="150" y1="190" x2="250" y2="220" />
        <line x1="150" y1="210" x2="250" y2="240" />
        {/* Right stand */}
        <line x1="200" y1="220" x2="180" y2="280" />
        <line x1="200" y1="220" x2="220" y2="280" />
        {/* Cable between */}
        <path d="M 130 180 Q 140 195 150 180" />
      </g>
    </svg>
  );
}

/* ──────────────── MONITORING UI OVERLAY ──────────────── */
function MonitoringOverlay() {
  return (
    <div style={{
      position: "absolute",
      bottom: 28,
      right: 28,
      width: "min(400px, 40%)",
      background: "rgba(10,10,10,0.92)",
      backdropFilter: "blur(14px)",
      border: "1px solid rgba(255,255,255,0.10)",
      padding: 18,
      fontFamily: "var(--font-body)",
      color: "#ffffff",
      fontSize: 11,
      boxShadow: "0 24px 60px rgba(0,0,0,0.4)",
    }}>
      <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 14, alignItems: "center" }}>
        <span style={{
          fontSize: 10, letterSpacing: "0.2em",
          color: "rgba(255,255,255,0.55)",
          textTransform: "uppercase",
        }}>
          Unit Pro / 1184
        </span>
        <span style={{
          fontSize: 10, letterSpacing: "0.2em",
          textTransform: "uppercase",
          display: "flex", alignItems: "center", gap: 6,
        }}>
          <span style={{
            width: 6, height: 6, background: "#ffffff",
            animation: "solo-pulse 1.6s ease-in-out infinite",
          }} />
          Live
        </span>
      </div>
      <style>{`@keyframes solo-pulse { 0%,100% { opacity: 1 } 50% { opacity: 0.3 } }`}</style>
      {/* Camera tiles */}
      <div style={{
        display: "grid", gridTemplateColumns: "1fr 1fr 1fr",
        gap: 1, background: "rgba(255,255,255,0.08)", marginBottom: 14,
      }}>
        {[1, 2, 3].map((i) => (
          <div key={i} style={{
            aspectRatio: "16/10",
            background: `linear-gradient(${135 + i*40}deg, #2b2b2b 0%, #0a0a0a 100%)`,
            display: "flex", alignItems: "flex-end", padding: 6,
            fontSize: 8, letterSpacing: "0.14em", color: "rgba(255,255,255,0.7)",
            position: "relative", textTransform: "uppercase",
          }}>
            <span style={{ position: "absolute", top: 6, left: 6, color: "#fff", fontSize: 8 }}>● Rec</span>
            Cam 0{i}
          </div>
        ))}
      </div>
      <div style={{
        fontSize: 10, letterSpacing: "0.2em",
        color: "rgba(255,255,255,0.55)", marginBottom: 8,
        textTransform: "uppercase",
      }}>
        Event log
      </div>
      {[
        ["18:24:11", "Motion · Zone A",   "Gate",   "ALERT"],
        ["18:21:08", "Vehicle on site",   "Zone B", "Info"],
        ["18:17:42", "Strobe trigger",    "Zone A", "Info"],
      ].map(([t, c, z, lv], i) => (
        <div key={i} style={{
          display: "grid", gridTemplateColumns: "60px 1fr 60px 60px",
          gap: 6, padding: "4px 0",
          borderTop: i ? "1px solid rgba(255,255,255,0.08)" : "none",
          fontSize: 10,
          color: lv === "Fltr" ? "rgba(255,255,255,0.4)" : "rgba(255,255,255,0.92)",
          textTransform: "uppercase", letterSpacing: "0.06em",
        }}>
          <span style={{ opacity: 0.6 }}>{t}</span>
          <span>{c}</span>
          <span style={{ opacity: 0.6 }}>{z}</span>
          <span style={{
            color: lv === "ALERT" ? "#ffffff" : lv === "Fltr" ? "rgba(255,255,255,0.4)" : "rgba(255,255,255,0.7)",
            textAlign: "right", fontSize: 9, fontWeight: 600,
            letterSpacing: "0.14em",
          }}>{lv}</span>
        </div>
      ))}
    </div>
  );
}

/* ══════════════════════ BakedPhoto ══════════════════════
 * Ship-ready replacement for <image-slot> — renders a plain <img>
 * from /assets/slots/{id}.webp with optional pan/zoom baked in from
 * the image-slots state at photo-freeze time. Falls back to `null`
 * (empty container) when no photo exists for that id, so any
 * silhouette/placeholder behind it stays visible.
 *
 * Photo transforms are stored here (s = scale, x/y = %-offset) —
 * only slots where the user had adjusted crop need non-default values.
 */
const BAKED_PHOTOS = {
  "leader-uk-leadership-ben":     { s: 1, x: 0, y: 0 },
  "leader-uk-leadership-josh":    { s: 1, x: 0, y: 0 },
  "leader-uk-leadership-paige":   { s: 1, x: 0, y: 0 },
  "leader-uk-leadership-gareth":  { s: 1, x: 0, y: 0 },
  "leader-uk-leadership-georgie": { s: 1, x: 0, y: 0 },
  "leader-workshop-gary":         { s: 1, x: 0, y: 0 },
  "leader-workshop-matt":         { s: 1, x: 0, y: 0 },
  "leader-workshop-che":          { s: 1, x: 0, y: 0 },
  "leader-workshop-kanayo":       { s: 1, x: 0, y: 0 },
  "leader-workshop-craig":        { s: 1, x: 0, y: 0 },
  "leader-workshop-rob-w":        { s: 1, x: 0, y: 0 },
  "leader-workshop-shane":        { s: 1, x: 0, y: 0 },
  "leader-workshop-gleidston":    { s: 1, x: 0, y: 0 },
  "our-story-founder-portrait":   { s: 1, x: 0, y: 0 },
  "our-story-2025":               { s: 1, x: 0, y: 0, ext: "png" },
  "sponsor-tommy-portrait":       { s: 1, x: 0, y: 0 },
  "factory-M-01":                 { s: 1, x: 0, y: 0 },
  "factory-M-02":                 { s: 1, x: 0, y: 0 },
  "factory-M-03":                 { s: 1, x: 0, y: 0 },
};

function BakedPhoto({ id, alt = "", style, imgStyle }) {
  const cfg = BAKED_PHOTOS[id];
  if (!cfg) return null;                   // no photo → let placeholder show
  const src = `assets/slots/${id}.${cfg.ext || "webp"}`;
  const transform = (cfg.s !== 1 || cfg.x || cfg.y)
    ? `translate(${cfg.x}%, ${cfg.y}%) scale(${cfg.s})`
    : undefined;
  return (
    <div style={{
      position: "absolute", inset: 0, overflow: "hidden",
      ...(style || {}),
    }}>
      <img
        src={src}
        alt={alt}
        draggable={false}
        style={{
          position: "absolute", inset: 0,
          width: "100%", height: "100%",
          objectFit: "cover", display: "block",
          userSelect: "none",
          transform, transformOrigin: "center center",
          ...(imgStyle || {}),
        }}
      />
    </div>
  );
}

Object.assign(window, {
  SoloLogo, SectionNumeral, Eyebrow, H1, H2, H3, Stat, StatRow, Button, LiveClock, TowerSchematic, SolarPanelSchematic, MonitoringOverlay,
  BakedPhoto, BAKED_PHOTOS,
});
