// splash-shared.jsx — theme, primitives, Bae waveform, sticky nav
// All globals exported via window so subsequent script files can use them.

const baux = {
  navy:        '#0A1628',
  navyRaised:  '#0E1B30',
  gold:        '#C8A96E',
  goldDeep:    '#A88845',
  gold100:     '#E4D2A5',
  bone:        '#F6F1E7',
  ink:         '#1A1A1A',
  navy85:      'rgba(10,22,40,0.85)',
  navy60:      'rgba(10,22,40,0.60)',
  navy40:      'rgba(10,22,40,0.40)',
  navy12:      'rgba(10,22,40,0.12)',
  navy04:      'rgba(10,22,40,0.04)',
  white100:    'rgba(255,255,255,1)',
  white72:     'rgba(255,255,255,0.72)',
  white48:     'rgba(255,255,255,0.48)',
  white24:     'rgba(255,255,255,0.24)',
  white12:     'rgba(255,255,255,0.12)',
  white06:     'rgba(255,255,255,0.06)',
  fontSans:    "'Inter', -apple-system, system-ui, sans-serif",
  fontSerif:   "'Fraunces', 'Lora', Georgia, serif",
};

// ── Eyebrow ──────────────────────────────────────────────────────────────────
function Eyebrow({ children, color, style }) {
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 8,
      fontFamily: baux.fontSans,
      fontSize: 13, fontWeight: 500,
      letterSpacing: '0.14em',
      textTransform: 'uppercase',
      color: color || baux.gold,
      ...style,
    }}>{children}</div>
  );
}

// 4-point sparkle icon
function Sparkle({ size = 12, color }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" aria-hidden>
      <path d="M12 2 L13.5 9.5 L21 12 L13.5 14.5 L12 22 L10.5 14.5 L3 12 L10.5 9.5 Z"
            fill={color || baux.gold}/>
    </svg>
  );
}

// ── Button ───────────────────────────────────────────────────────────────────
function Button({ tone = 'accent', children, href = '#', onClick, type, icon, style, ariaLabel }) {
  const tones = {
    accent:        { background: baux.gold, color: baux.navy, border: 'none' },
    primary:       { background: baux.navy, color: baux.bone, border: 'none' },
    ghost:         { background: 'transparent', color: baux.navy, border: `1px solid ${baux.navy12}` },
    'ghost-dark':  { background: 'transparent', color: baux.bone, border: `1px solid ${baux.white24}` },
  }[tone];
  const Tag = type === 'submit' ? 'button' : 'a';
  return (
    <Tag href={Tag === 'a' ? href : undefined}
         type={Tag === 'button' ? (type || 'button') : undefined}
         onClick={onClick}
         aria-label={ariaLabel}
         style={{
           display: 'inline-flex', alignItems: 'center', gap: 10,
           padding: '13px 22px',
           borderRadius: 9999,
           fontFamily: baux.fontSans,
           fontSize: 15, fontWeight: 600,
           letterSpacing: 0,
           textDecoration: 'none',
           cursor: 'pointer',
           transition: 'background 200ms cubic-bezier(0.22,1,0.36,1), transform 120ms, border-color 200ms',
           whiteSpace: 'nowrap',
           ...tones, ...style,
         }}
         onMouseEnter={(e) => {
           if (tone === 'accent') e.currentTarget.style.background = baux.goldDeep;
           if (tone === 'ghost-dark') e.currentTarget.style.borderColor = baux.gold;
           if (tone === 'ghost') e.currentTarget.style.borderColor = baux.navy40;
         }}
         onMouseLeave={(e) => Object.assign(e.currentTarget.style, tones)}
         onMouseDown={(e) => (e.currentTarget.style.transform = 'scale(0.98)')}
         onMouseUp={(e)   => (e.currentTarget.style.transform = 'scale(1)')}>
      {children}{icon}
    </Tag>
  );
}

// ── BaeWaveform — gold bars that pulse while playing ─────────────────────────
function BaeWaveform({ playing = false, bars = 24, height = 36, color }) {
  const arr = React.useMemo(() => {
    // Each bar gets a per-bar phase delay + max height. Build once.
    const r = [];
    for (let i = 0; i < bars; i++) {
      // pseudo-random but stable
      const seed = Math.sin(i * 12.9898) * 43758.5453;
      const f = seed - Math.floor(seed); // 0..1
      r.push({
        max: 0.45 + f * 0.55,           // 0.45..1.0
        delay: -(f * 900) + 'ms',
      });
    }
    return r;
  }, [bars]);

  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 3,
      height,
    }}>
      {arr.map((b, i) => (
        <span
          key={i}
          className="bae-bar"
          data-playing={String(playing)}
          style={{
            height: Math.round(height * b.max),
            background: color || baux.gold,
            animationDelay: b.delay,
          }}
        />
      ))}
    </div>
  );
}

// ── Bae voice sample player ──────────────────────────────────────────────────
// Pure visual — no audio file. "Plays" for ~9s then auto-stops, so the page
// stays calm without actual sound.
function BaeSample({ dark = true, quote, place = 'Mills 50 · Orlando' }) {
  const [playing, setPlaying] = React.useState(false);
  const [progress, setProgress] = React.useState(0); // 0..1
  const DURATION = 9000;

  React.useEffect(() => {
    if (!playing) return;
    const start = performance.now();
    let raf;
    const tick = (t) => {
      const p = Math.min(1, (t - start) / DURATION);
      setProgress(p);
      if (p >= 1) { setPlaying(false); setProgress(0); return; }
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [playing]);

  const fg = dark ? baux.bone : baux.navy;
  const fgMuted = dark ? baux.white48 : baux.navy60;
  const border = dark ? baux.white12 : baux.navy12;
  const bg = dark ? 'rgba(255,255,255,0.03)' : 'rgba(10,22,40,0.025)';

  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 16,
      padding: '14px 16px 14px 14px',
      borderRadius: 9999,
      border: `1px solid ${border}`,
      background: bg,
      maxWidth: 460,
      width: '100%',
      backdropFilter: 'blur(8px)',
      WebkitBackdropFilter: 'blur(8px)',
    }}>
      <button
        onClick={() => setPlaying((p) => !p)}
        aria-label={playing ? 'Pause Bae sample' : 'Play Bae sample'}
        style={{
          width: 40, height: 40, flex: '0 0 40px',
          borderRadius: '50%',
          background: baux.gold,
          border: 'none',
          color: baux.navy,
          cursor: 'pointer',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          transition: 'background 200ms',
        }}
        onMouseEnter={(e) => (e.currentTarget.style.background = baux.goldDeep)}
        onMouseLeave={(e) => (e.currentTarget.style.background = baux.gold)}>
        {playing ? (
          <svg width="14" height="14" viewBox="0 0 14 14" aria-hidden>
            <rect x="2" y="1" width="3.2" height="12" rx="0.8" fill="currentColor"/>
            <rect x="8.8" y="1" width="3.2" height="12" rx="0.8" fill="currentColor"/>
          </svg>
        ) : (
          <svg width="14" height="14" viewBox="0 0 14 14" aria-hidden>
            <path d="M3 1.5 L3 12.5 L12 7 Z" fill="currentColor"/>
          </svg>
        )}
      </button>

      <div style={{
        flex: 1, minWidth: 0,
        display: 'flex', flexDirection: 'column', gap: 4,
      }}>
        <div style={{
          fontFamily: baux.fontSans, fontSize: 11, fontWeight: 500,
          letterSpacing: '0.14em', textTransform: 'uppercase',
          color: baux.gold,
          display: 'inline-flex', alignItems: 'center', gap: 6,
          whiteSpace: 'nowrap',
        }}>
          <Sparkle size={10}/> Bae · sample
        </div>
        <div style={{
          fontFamily: baux.fontSans, fontSize: 13, fontWeight: 400,
          color: fgMuted,
          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
        }}>{place}</div>
      </div>

      <div style={{ flex: '0 0 auto', display: 'flex', alignItems: 'center', gap: 10 }}>
        <BaeWaveform playing={playing} bars={14} height={28} color={baux.gold}/>
        <div style={{
          fontFamily: baux.fontSans, fontSize: 12, fontVariantNumeric: 'tabular-nums',
          color: fgMuted, minWidth: 36, textAlign: 'right',
        }}>
          {playing
            ? `0:${String(Math.floor(progress * 9)).padStart(2, '0')}`
            : '0:09'}
        </div>
      </div>
    </div>
  );
}

// ── iPhone bezel ─────────────────────────────────────────────────────────────
// Hand-rolled — uses the iOS Orlando screenshot directly (it already contains
// its own status bar).
function PhoneFrame({ src, width = 320, alt = 'BAUX iOS app' }) {
  const aspect = 1320 / 2868;
  const height = Math.round(width / aspect);
  return (
    <div style={{
      position: 'relative',
      width, height,
      borderRadius: width * 0.13,
      padding: 8,
      background: 'linear-gradient(180deg, #1A2840 0%, #050B17 100%)',
      boxShadow: `
        0 40px 80px -20px rgba(0,0,0,0.55),
        0 16px 32px -8px rgba(0,0,0,0.35),
        inset 0 0 0 1.5px rgba(255,255,255,0.06),
        inset 0 1px 0 rgba(255,255,255,0.12)
      `,
    }}>
      {/* screen */}
      <div style={{
        position: 'absolute',
        inset: 8,
        borderRadius: width * 0.11,
        overflow: 'hidden',
        background: baux.navy,
      }}>
        <img src={src} alt={alt} draggable="false" style={{
          display: 'block',
          width: '100%',
          height: '100%',
          objectFit: 'cover',
          objectPosition: 'top',
          userSelect: 'none',
        }}/>
      </div>
      {/* side button suggestion */}
      <div style={{
        position: 'absolute', left: -2, top: '24%',
        width: 3, height: 56,
        borderRadius: 2,
        background: '#0A1322',
      }}/>
      <div style={{
        position: 'absolute', right: -2, top: '20%',
        width: 3, height: 80,
        borderRadius: 2,
        background: '#0A1322',
      }}/>
    </div>
  );
}

// ── Section wrapper with optional reveal-on-scroll ───────────────────────────
function Section({ children, dark, padY = 'var(--space-8)', style, id }) {
  return (
    <section id={id} style={{
      background: dark ? baux.navy : baux.bone,
      color: dark ? baux.bone : baux.ink,
      padding: `${padY} 32px`,
      ...style,
    }}>
      <div style={{
        maxWidth: 1200, margin: '0 auto', position: 'relative',
      }}>
        {children}
      </div>
    </section>
  );
}

// ── useMedia — subscribe to a media query, return boolean ────────────────────
function useMedia(query) {
  const [matches, setMatches] = React.useState(() =>
    typeof window !== 'undefined'
      ? window.matchMedia(query).matches
      : false
  );
  React.useEffect(() => {
    const mql = window.matchMedia(query);
    const onChange = () => setMatches(mql.matches);
    if (mql.addEventListener) mql.addEventListener('change', onChange);
    else mql.addListener(onChange);
    setMatches(mql.matches);
    return () => {
      if (mql.removeEventListener) mql.removeEventListener('change', onChange);
      else mql.removeListener(onChange);
    };
  }, [query]);
  return matches;
}

// Breakpoint shortcuts
const useIsMobile = () => useMedia('(max-width: 720px)');
const useIsTablet = () => useMedia('(max-width: 980px)');

function Reveal({ children, delay = 0, as: As = 'div', style }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          setTimeout(() => el.classList.add('in'), delay);
          io.unobserve(el);
        }
      });
    }, { threshold: 0.12 });
    io.observe(el);
    return () => io.disconnect();
  }, [delay]);
  return <As ref={ref} className="reveal" style={style}>{children}</As>;
}

// ── BAUX wordmark (inline SVG so it inherits color) ──────────────────────────
function Wordmark({ size = 22, color }) {
  // Stacked: BA on top of UX, with the gold period anchored to the bottom-right.
  const lineH = size * 0.92;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'flex-end',
      fontFamily: baux.fontSans,
      fontWeight: 700,
      letterSpacing: '-0.04em',
      color: color || 'currentColor',
      lineHeight: 1,
    }}>
      <span style={{
        display: 'inline-flex', flexDirection: 'column',
        fontSize: size,
        lineHeight: lineH + 'px',
      }}>
        <span>BA</span>
        <span>UX</span>
      </span>
      <span style={{
        color: baux.gold,
        fontSize: size,
        lineHeight: lineH + 'px',
        marginLeft: 1,
      }}>.</span>
    </span>
  );
}

// ── HeroMap — stylized abstract street map for hero background ───────────────
// Renders as decoration only. The wrapping .hero-map-bg div applies the
// radial mask. Uses currentColor for strokes so light/dark variants are
// driven by a single inline color prop.
function HeroMap({ dark = true }) {
  const stroke = dark ? 'rgba(255,255,255,1)' : 'rgba(10,22,40,1)';
  const water  = dark ? 'rgba(200,169,110,0.06)' : 'rgba(10,22,40,0.04)';
  const block  = dark ? 'rgba(255,255,255,0.025)' : 'rgba(10,22,40,0.025)';
  return (
    <div className="hero-map-bg" aria-hidden style={{ color: stroke }}>
      <svg viewBox="0 0 1600 1000" preserveAspectRatio="xMidYMid slice">
        {/* River / coastline — a soft curve through the lower-left, with a
            tributary. Very subtle fill, never reads as "water" overtly. */}
        <path
          d="M -50 760 C 220 700, 460 880, 760 770 S 1280 580, 1700 660 L 1700 1050 L -50 1050 Z"
          fill={water}
        />
        <path
          d="M 380 -50 C 420 180, 520 320, 700 380 S 980 540, 1100 720"
          fill="none" stroke="currentColor" strokeOpacity="0.06" strokeWidth="14"
          strokeLinecap="round"
        />

        {/* Faint block fills — slightly rotated for grain */}
        <g transform="rotate(-6 800 500)">
          {[
            [120, 180, 220, 140], [380, 220, 180, 120], [620, 160, 260, 160],
            [960, 220, 180, 140], [1200, 160, 240, 160],
            [180, 420, 200, 160], [440, 460, 220, 140], [720, 440, 220, 160],
            [1000, 460, 200, 140], [1260, 420, 220, 160],
            [120, 660, 240, 140], [420, 680, 200, 140], [720, 660, 240, 140],
          ].map(([x, y, w, h], i) => (
            <rect key={i} x={x} y={y} width={w} height={h}
              fill={block} rx="4"/>
          ))}
        </g>

        {/* A pocket park — soft rounded shape */}
        <g transform="translate(380 540)">
          <path d="M -90 -40 C -90 -90, 90 -90, 90 -40 S 90 60, 0 60 S -90 10, -90 -40 Z"
                fill={block} stroke="currentColor" strokeOpacity="0.08"
                strokeWidth="1"/>
        </g>

        {/* Compass tick — a single hairline cross, top-left, very small */}
        <g transform="translate(140 140)" stroke="currentColor" strokeOpacity="0.18"
           strokeWidth="1" strokeLinecap="round">
          <line x1="-14" y1="0" x2="14" y2="0"/>
          <line x1="0"  y1="-14" x2="0" y2="14"/>
        </g>

        {/* Gold map pins — sparingly placed, pulsing softly */}
        <g fill={baux.gold}>
          {[
            [430, 320, 0],
            [820, 560, 1.2],
            [1180, 280, 2.4],
            [620, 720, 0.6],
            [1320, 660, 1.8],
          ].map(([cx, cy, d], i) => (
            <g key={i} transform={`translate(${cx} ${cy})`}>
              <circle className="pin-pulse" r="14" fillOpacity="0.18"
                      style={{ animationDelay: `-${d}s` }}/>
              <circle r="4.5"/>
            </g>
          ))}
        </g>
      </svg>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────────
// Inline email signup form — used in both the hero and the bottom CTA.
// ────────────────────────────────────────────────────────────────────────────
function InlineEmailForm({ dark = true, onSubmit, autoFocus = false, compact = false }) {
  const [email, setEmail] = React.useState('');
  const [submitting, setSubmitting] = React.useState(false);
  const [error, setError] = React.useState(null);
  const inputRef = React.useRef(null);
  const isMobile = useIsMobile();

  React.useEffect(() => {
    if (autoFocus && inputRef.current) inputRef.current.focus();
  }, [autoFocus]);

  const handleSubmit = (e) => {
    e.preventDefault();
    const v = email.trim();
    if (!v || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)) {
      setError('Please enter a valid email.');
      return;
    }
    setError(null);
    setSubmitting(true);
    setTimeout(() => {
      setSubmitting(false);
      setEmail('');
      onSubmit && onSubmit(v);
    }, 600);
  };

  const fg = dark ? baux.bone : baux.navy;
  const border = dark ? baux.white24 : baux.navy12;
  const bg = dark ? 'rgba(255,255,255,0.06)' : 'rgba(10,22,40,0.025)';

  // On very narrow viewports the pill is fragile — fall back to a stacked
  // layout: full-width input above, full-width button below.
  if (isMobile) {
    return (
      <form onSubmit={handleSubmit}>
        <input
          ref={inputRef}
          type="email"
          autoComplete="email"
          placeholder="you@somewhere.com"
          value={email}
          onChange={(e) => { setEmail(e.target.value); setError(null); }}
          style={{
            width: '100%',
            display: 'block',
            appearance: 'none',
            background: bg,
            border: `1px solid ${border}`,
            borderRadius: 9999,
            outline: 'none',
            color: fg,
            fontFamily: baux.fontSans,
            fontSize: 16,
            padding: '14px 18px',
          }}
        />
        <Button
          tone="accent"
          type="submit"
          onClick={handleSubmit}
          style={{
            marginTop: 10,
            width: '100%',
            display: 'flex', justifyContent: 'center',
            padding: '14px 22px',
            opacity: submitting ? 0.7 : 1,
            pointerEvents: submitting ? 'none' : 'auto',
          }}>
          {submitting ? 'Sending…' : 'Join the BETA'}
        </Button>
        {error && (
          <div style={{
            marginTop: 10,
            fontFamily: baux.fontSans, fontSize: 13,
            color: dark ? '#F4A89C' : '#B73A2A',
          }}>{error}</div>
        )}
      </form>
    );
  }

  return (
    <form onSubmit={handleSubmit}>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 6,
        background: bg,
        border: `1px solid ${border}`,
        borderRadius: 9999,
        padding: 6,
        maxWidth: compact ? 460 : 520,
        backdropFilter: 'blur(12px)',
        WebkitBackdropFilter: 'blur(12px)',
        transition: 'border-color 200ms',
      }}>
        <input
          ref={inputRef}
          type="email"
          autoComplete="email"
          placeholder="you@somewhere.com"
          value={email}
          onChange={(e) => { setEmail(e.target.value); setError(null); }}
          className="baux-email"
          style={{ color: fg, textAlign: 'left' }}
        />
        <Button
          tone="accent"
          type="submit"
          onClick={handleSubmit}
          style={{
            padding: '13px 22px',
            opacity: submitting ? 0.7 : 1,
            pointerEvents: submitting ? 'none' : 'auto',
          }}>
          {submitting ? 'Sending…' : 'Join the BETA'}
        </Button>
      </div>
      {error && (
        <div style={{
          marginTop: 10,
          fontFamily: baux.fontSans, fontSize: 13,
          color: dark ? '#F4A89C' : '#B73A2A',
        }}>{error}</div>
      )}
    </form>
  );
}

// expose to other babel scripts
Object.assign(window, {
  baux, Eyebrow, Sparkle, Button, BaeWaveform, BaeSample,
  PhoneFrame, Section, Reveal, Wordmark, HeroMap, InlineEmailForm,
  useMedia, useIsMobile, useIsTablet,
});
