// Survival — app root + comprehensive Tweaks wiring
// Every editable piece of content + visuals flows through `t` (the tweak state).

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "arctic",
  "customInk": "#0B0F14",
  "customPaper": "#F4EFE6",
  "customEmber": "#B8895A",
  "useCustomColors": false,
  "displayFont": "cormorant",
  "heroVariant": "fullbleed",
  "grain": true,
  "accessGated": false,

  "filmTitle": "Survival",
  "filmYear": "2026",
  "filmStage": "In Post-Production",
  "filmRuntime": "60 minutes",
  "filmTerritory": "Alaska, USA",
  "filmRoute": "750 miles · 1925",

  "heroKicker": "— A Documentary Film  /  In Post-Production  /  2026",
  "heroTagline": "One hundred years after the 1925 Serum Run saved the children of Nome, four men and a team of Seppala Siberians retrace the 750-mile route — in the darkest, coldest weeks of the year — to discover what we lose when the dogs stop running.",
  "heroSplitSub": "Where machines faltered, the dogs endured. A century later, we went back.",

  "marqueeItems": "750 MILES | 1925 / 2025 | NOME, ALASKA | SEPPALA SIBERIAN SLEDDOGS | −60°F | THE NORTON BAY SEA ICE | TWO CROSSINGS",

  "filmKicker": "Synopsis",
  "filmHeading": "Where machines faltered, the dogs endured. A century later, four men went back to find out why.",

  "trailerTagline": "A first look — filmed on the trail, across 750 miles.",
  "trailerYouTubeId": "YcdO5fczcHU",
  "trailerRuntime": "1:42",

  "parallelKicker": "— Two expeditions, one trail, one hundred years apart",

  "routeKicker": "750 miles, ten waypoints",
  "routeHeading": "Nenana to Nome — as the serum traveled, as the dogs remember.",

  "teamKicker": "Four men, one dog team",
  "teamHeading": "The expedition was filmed from inside. No outside crew. No helicopter.",
  "dogsHeading": "The dogs are not a metaphor. They are the reason.",

  "productionKicker": "Status",
  "productionHeading": "The film is shot. What remains is making it ready.",

  "opportunityKicker": "For producers, investors, partners",
  "opportunityHeading": "We're assembling the finishing team.",
  "ctaHeading": "Read the deck. Watch the reel.",
  "ctaButton": "Begin a conversation →",
  "contactEmail": "producers@survival.film"
}/*EDITMODE-END*/;

const PALETTES = {
  arctic:   { ink: '#0B0F14', ink2: '#1A2028', paper: '#F4EFE6', paper2: '#E8E1D2', ember: '#B8895A', ember2: '#8A6640' },
  midnight: { ink: '#07090C', ink2: '#14181F', paper: '#EDEAE3', paper2: '#D9D4C8', ember: '#6B8CAE', ember2: '#4A6B8A' },
  ember:    { ink: '#120B08', ink2: '#1F1611', paper: '#F2E9DC', paper2: '#E2D4BE', ember: '#C2603A', ember2: '#8F4424' },
  paper:    { ink: '#1C1914', ink2: '#2A2620', paper: '#F7F2E8', paper2: '#EBE4D3', ember: '#8A7A5F', ember2: '#5E513E' },
};

const DISPLAY_FONTS = {
  cormorant: "'Cormorant Garamond', 'Times New Roman', serif",
  fraunces:  "'Fraunces', 'Times New Roman', serif",
};

// Lightly shade a hex color toward white or black
function shade(hex, amt) {
  const n = parseInt(hex.replace('#',''), 16);
  const r = Math.floor(n / 65536) % 256;
  const g = Math.floor(n / 256) % 256;
  const b = n % 256;
  const f = (c) => Math.max(0, Math.min(255, Math.round(c + (amt > 0 ? (255 - c) : c) * amt)));
  return '#' + [f(r), f(g), f(b)].map(x => x.toString(16).padStart(2,'0')).join('');
}

function applyPalette(t) {
  let p = PALETTES[t.palette] || PALETTES.arctic;
  if (t.useCustomColors) {
    p = {
      ink: t.customInk,
      ink2: shade(t.customInk, 0.08),
      paper: t.customPaper,
      paper2: shade(t.customPaper, -0.08),
      ember: t.customEmber,
      ember2: shade(t.customEmber, -0.25),
    };
  }
  return p;
}

function hexToRgb(hex) {
  const n = parseInt(hex.replace('#',''), 16);
  return [Math.floor(n / 65536) % 256, Math.floor(n / 256) % 256, n % 256];
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [inquiryOpen, setInquiryOpen] = React.useState(false);
  const [gateOpen, setGateOpen] = React.useState(t.accessGated);

  React.useEffect(() => { setGateOpen(t.accessGated); }, [t.accessGated]);

  // Apply palette (preset or custom) + fonts to :root
  React.useEffect(() => {
    const p = applyPalette(t);
    const r = document.documentElement.style;
    r.setProperty('--ink', p.ink);
    r.setProperty('--ink-2', p.ink2);
    r.setProperty('--paper', p.paper);
    r.setProperty('--paper-2', p.paper2);
    r.setProperty('--ember', p.ember);
    r.setProperty('--ember-2', p.ember2);
    const [pr, pg, pb] = hexToRgb(p.paper);
    r.setProperty('--rule', `rgba(${pr},${pg},${pb},0.14)`);
    r.setProperty('--mute', `rgba(${pr},${pg},${pb},0.55)`);
    r.setProperty('--display', DISPLAY_FONTS[t.displayFont] || DISPLAY_FONTS.cormorant);
  }, [t.palette, t.displayFont, t.useCustomColors, t.customInk, t.customPaper, t.customEmber]);

  React.useEffect(() => {
    document.body.classList.toggle('grain', t.grain);
  }, [t.grain]);

  return (
    <>
      {gateOpen && <AccessGate onEnter={() => setGateOpen(false)} onRequest={() => { setGateOpen(false); setInquiryOpen(true); }} />}

      <Nav onInquire={() => setInquiryOpen(true)} filmTitle={t.filmTitle} />

      <Hero heroVariant={t.heroVariant} t={t} />
      <Marquee itemsText={t.marqueeItems} />
      <FilmSection t={t} />
      <VisionSection />
      <TrailerSection t={t} />
      <ParallelSection t={t} />
      <RouteSection t={t} />
      <TeamSection t={t} />
      <ProductionSection t={t} />
      <OpportunitySection onInquire={() => setInquiryOpen(true)} t={t} />
      <Footer t={t} />

      <InquiryModal open={inquiryOpen} onClose={() => setInquiryOpen(false)} />

      <TweaksPanel title="Tweaks · Survival">
        {/* -- Palette + typography -- */}
        <TweakSection label="Palette" />
        <TweakRadio
          label="Preset"
          value={t.palette}
          options={[
            { value: 'arctic', label: 'Arctic' },
            { value: 'midnight', label: 'Midnight' },
            { value: 'ember', label: 'Ember' },
            { value: 'paper', label: 'Paper' },
          ]}
          onChange={(v) => { setTweak('palette', v); setTweak('useCustomColors', false); }}
        />
        <TweakToggle label="Custom colors" value={t.useCustomColors}
          onChange={(v) => setTweak('useCustomColors', v)} />
        {t.useCustomColors && (
          <>
            <TweakColor label="Ink (background)" value={t.customInk}
              onChange={(v) => setTweak('customInk', v)} />
            <TweakColor label="Paper (text)" value={t.customPaper}
              onChange={(v) => setTweak('customPaper', v)} />
            <TweakColor label="Accent" value={t.customEmber}
              onChange={(v) => setTweak('customEmber', v)} />
          </>
        )}

        <TweakSection label="Typography" />
        <TweakRadio
          label="Display face"
          value={t.displayFont}
          options={[
            { value: 'cormorant', label: 'Cormorant' },
            { value: 'fraunces', label: 'Fraunces' },
          ]}
          onChange={(v) => setTweak('displayFont', v)}
        />

        <TweakSection label="Hero / Treatment" />
        <TweakRadio
          label="Hero layout"
          value={t.heroVariant}
          options={[
            { value: 'fullbleed', label: 'Full-bleed' },
            { value: 'split', label: 'Editorial split' },
          ]}
          onChange={(v) => setTweak('heroVariant', v)}
        />
        <TweakToggle label="Film grain" value={t.grain} onChange={(v) => setTweak('grain', v)} />
        <TweakToggle label="Access gate" value={t.accessGated} onChange={(v) => setTweak('accessGated', v)} />

        {/* -- Film meta -- */}
        <TweakSection label="Film" />
        <TweakText label="Title" value={t.filmTitle} onChange={(v) => setTweak('filmTitle', v)} />
        <TweakText label="Year" value={t.filmYear} onChange={(v) => setTweak('filmYear', v)} />
        <TweakText label="Stage" value={t.filmStage} onChange={(v) => setTweak('filmStage', v)} />
        <TweakText label="Runtime" value={t.filmRuntime} onChange={(v) => setTweak('filmRuntime', v)} />
        <TweakText label="Territory" value={t.filmTerritory} onChange={(v) => setTweak('filmTerritory', v)} />
        <TweakText label="Route spec" value={t.filmRoute} onChange={(v) => setTweak('filmRoute', v)} />

        {/* -- Hero copy -- */}
        <TweakSection label="Hero copy" />
        <TweakText label="Kicker" value={t.heroKicker} onChange={(v) => setTweak('heroKicker', v)} />
        <TweakText label="Logline" value={t.heroTagline} onChange={(v) => setTweak('heroTagline', v)} />
        <TweakText label="Split sub" value={t.heroSplitSub} onChange={(v) => setTweak('heroSplitSub', v)} />

        {/* -- Marquee -- */}
        <TweakSection label="Marquee" />
        <TweakText label="Items (pipe-separated)" value={t.marqueeItems}
          onChange={(v) => setTweak('marqueeItems', v)} />

        {/* -- Section headings -- */}
        <TweakSection label="Film section" />
        <TweakText label="Kicker" value={t.filmKicker} onChange={(v) => setTweak('filmKicker', v)} />
        <TweakText label="Heading" value={t.filmHeading} onChange={(v) => setTweak('filmHeading', v)} />

        <TweakSection label="Trailer" />
        <TweakText label="YouTube ID" value={t.trailerYouTubeId}
          onChange={(v) => setTweak('trailerYouTubeId', v)} />
        <TweakText label="Tagline" value={t.trailerTagline}
          onChange={(v) => setTweak('trailerTagline', v)} />
        <TweakText label="Runtime" value={t.trailerRuntime}
          onChange={(v) => setTweak('trailerRuntime', v)} />

        <TweakSection label="1925 / 2025" />
        <TweakText label="Kicker" value={t.parallelKicker}
          onChange={(v) => setTweak('parallelKicker', v)} />

        <TweakSection label="Route section" />
        <TweakText label="Kicker" value={t.routeKicker} onChange={(v) => setTweak('routeKicker', v)} />
        <TweakText label="Heading" value={t.routeHeading} onChange={(v) => setTweak('routeHeading', v)} />

        <TweakSection label="Team section" />
        <TweakText label="Kicker" value={t.teamKicker} onChange={(v) => setTweak('teamKicker', v)} />
        <TweakText label="Heading" value={t.teamHeading} onChange={(v) => setTweak('teamHeading', v)} />
        <TweakText label="Dogs heading" value={t.dogsHeading} onChange={(v) => setTweak('dogsHeading', v)} />

        <TweakSection label="Production" />
        <TweakText label="Kicker" value={t.productionKicker}
          onChange={(v) => setTweak('productionKicker', v)} />
        <TweakText label="Heading" value={t.productionHeading}
          onChange={(v) => setTweak('productionHeading', v)} />

        {/* -- CTA / contact -- */}
        <TweakSection label="Opportunity / CTA" />
        <TweakText label="Kicker" value={t.opportunityKicker}
          onChange={(v) => setTweak('opportunityKicker', v)} />
        <TweakText label="Heading" value={t.opportunityHeading}
          onChange={(v) => setTweak('opportunityHeading', v)} />
        <TweakText label="CTA heading" value={t.ctaHeading}
          onChange={(v) => setTweak('ctaHeading', v)} />
        <TweakText label="CTA button" value={t.ctaButton}
          onChange={(v) => setTweak('ctaButton', v)} />
        <TweakText label="Contact email" value={t.contactEmail}
          onChange={(v) => setTweak('contactEmail', v)} />
      </TweaksPanel>
    </>
  );
}

// Invite-only access gate — a restrained lock screen
function AccessGate({ onEnter, onRequest }) {
  const [code, setCode] = React.useState('');
  const [err, setErr] = React.useState(false);
  const submit = () => {
    if (code.trim().toLowerCase() === 'togo' || code.trim().toLowerCase() === 'seppala') {
      onEnter();
    } else {
      setErr(true);
    }
  };
  return (
    <div style={{
      position: 'fixed', inset: 0, zIndex: 300,
      background: 'var(--ink)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 40,
    }}>
      <div style={{ maxWidth: 440, width: '100%', textAlign: 'center' }}>
        <Wordmark />
        <h2 style={{
          fontFamily: 'var(--display)',
          fontWeight: 300, fontStyle: 'italic',
          fontSize: 44, lineHeight: 1.1,
          margin: '56px 0 20px',
        }}>By invitation.</h2>
        <p style={{ color: 'var(--mute)', fontSize: 14, lineHeight: 1.7, marginBottom: 40 }}>
          This page is shared privately with producers, investors, and partners.
          Enter your access word to continue.
        </p>
        <input
          value={code}
          onChange={(e) => { setCode(e.target.value); setErr(false); }}
          onKeyDown={(e) => e.key === 'Enter' && submit()}
          placeholder="Access word"
          style={{
            width: '100%',
            background: 'transparent',
            border: 'none',
            borderBottom: `1px solid ${err ? 'var(--ember)' : 'var(--rule)'}`,
            color: 'var(--paper)',
            fontFamily: 'var(--mono)',
            fontSize: 14,
            letterSpacing: '0.2em',
            textTransform: 'uppercase',
            textAlign: 'center',
            padding: '16px 0',
            outline: 'none',
            marginBottom: 8,
          }}
        />
        <div style={{ height: 18, fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.18em', color: 'var(--ember)', textTransform: 'uppercase' }}>
          {err ? 'Not recognized' : ''}
        </div>
        <button onClick={submit} style={{
          marginTop: 24,
          appearance: 'none', border: 'none',
          background: 'var(--ember)', color: 'var(--ink)',
          fontFamily: 'var(--mono)', fontSize: 12,
          letterSpacing: '0.22em', textTransform: 'uppercase',
          fontWeight: 600,
          padding: '16px 28px',
          width: '100%',
          cursor: 'pointer',
        }}>Enter →</button>
        <button onClick={onRequest} style={{
          marginTop: 20, appearance: 'none', background: 'transparent', border: 'none',
          color: 'var(--mute)', fontFamily: 'var(--mono)', fontSize: 11,
          letterSpacing: '0.16em', textTransform: 'uppercase', cursor: 'pointer',
        }}>Request access →</button>
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('app')).render(<App />);
