// App + Tweaks shell

const { useState, useEffect } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "accentHue": 26,
  "heroVisual": "ledger",
  "motion": "full",
  "typography": "editorial"
}/*EDITMODE-END*/;

function applyCSSVars(tweaks) {
  const root = document.documentElement;
  root.dataset.theme = tweaks.theme;
  root.style.setProperty('--accent-h', String(tweaks.accentHue));
  // motion
  const m = tweaks.motion === 'off' ? 0 : tweaks.motion === 'subtle' ? 0.5 : 1;
  root.style.setProperty('--motion', String(m));
  // typography
  const pairs = {
    editorial:   ["'Geist', 'Pretendard Variable', sans-serif", "'Geist Mono', 'IBM Plex Mono', 'Pretendard Variable', 'Pretendard', ui-monospace, monospace", "'Newsreader', 'Noto Serif KR', Georgia, serif"],
    geist:       ["'Geist', 'Pretendard Variable', sans-serif", "'Geist Mono', 'IBM Plex Mono', 'Pretendard Variable', 'Pretendard', ui-monospace, monospace", "'Geist', sans-serif"],
    ibm:         ["'IBM Plex Sans', 'Pretendard Variable', sans-serif", "'IBM Plex Mono', 'Pretendard Variable', 'Pretendard', ui-monospace, monospace", "'IBM Plex Sans', sans-serif"],
  };
  const p = pairs[tweaks.typography] || pairs.editorial;
  root.style.setProperty('--font-sans', p[0]);
  root.style.setProperty('--font-mono', p[1]);
  root.style.setProperty('--font-display', p[2]);
}

// Mono faces carry no Hangul. Any .mono node holding Korean falls back to a
// glyphless face at 9–10px with heavy tracking, so upgrade it to the sans stack
// with a legible size/tracking floor. Data-driven, so done at runtime.
const HANGUL_RE = /[\u3130-\u318F\uAC00-\uD7A3]/;
function upgradeHangulMono(root) {
  (root || document).querySelectorAll('.mono').forEach((el) => {
    if (el.dataset.koFixed) return;
    if (!HANGUL_RE.test(el.textContent || '')) return;
    el.dataset.koFixed = '1';
    el.classList.add('mono-ko');
    el.style.setProperty('letter-spacing', '.06em', 'important');
    const fs = parseFloat(getComputedStyle(el).fontSize) || 0;
    if (fs && fs < 11.5) el.style.setProperty('font-size', '11.5px', 'important');
  });
}

function App() {
  const [tweaks, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const [lang, setLang] = useState(() => {
    const l = (navigator.language || '').toLowerCase();
    if (l.startsWith('ko')) return 'ko';
    if (l.startsWith('ja')) return 'ja';
    if (l.startsWith('zh')) return 'zh';
    return 'en';
  });

  useEffect(() => { applyCSSVars(tweaks); }, [tweaks]);

  // Re-run after every render pass and on language switch; MutationObserver
  // catches nodes added later (Eddy chat messages, tab panels).
  useEffect(() => {
    upgradeHangulMono();
    const id = setTimeout(upgradeHangulMono, 400);
    const mo = new MutationObserver((muts) => {
      for (const m of muts) {
        for (const n of m.addedNodes) {
          if (n.nodeType === 1) upgradeHangulMono(n.parentNode || n);
        }
      }
    });
    mo.observe(document.body, { childList: true, subtree: true });
    return () => { clearTimeout(id); mo.disconnect(); };
  }, [lang, tweaks.typography]);

  const t = window.COPY[lang];

  return (
    <>
      <Header t={t} lang={lang} setLang={setLang} tweaks={tweaks} setTweak={setTweak} />
      <main>
        <Hero t={t} tweaks={tweaks} />
        <window.Products t={t} />
        <Stats t={t} />
        <window.Method t={t} />
        <window.Trust t={t} />
        <EcodeTeam t={t} />
        <Services t={t} />
        <TrackRecord t={t} />
        <CEO t={t} tweaks={tweaks} />
        <Team t={t} />
        <AIDemo t={t} />
        <Contact t={t} />
      </main>
      <Footer t={t} />

      {/* Mobile floating contact FAB */}
      <a
        href="#contact"
        aria-label={t.hero.cta1}
        title={t.hero.cta1}
        className="fab-contact"
        style={{
          position: 'fixed', right: 18, bottom: 18, zIndex: 70,
          width: 56, height: 56, borderRadius: 999,
          background: 'var(--accent)', color: '#0a0a0a',
          display: 'none', alignItems: 'center', justifyContent: 'center',
          boxShadow: '0 14px 30px -8px var(--accent-glow), 0 0 0 1px color-mix(in srgb, var(--accent) 60%, transparent)',
          transition: 'transform .2s'
        }}
        onTouchStart={(e) => { e.currentTarget.style.transform = 'scale(0.94)'; }}
        onTouchEnd={(e) => { e.currentTarget.style.transform = 'none'; }}
      >
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
          <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
        </svg>
        <span style={{
          position: 'absolute', inset: -4, borderRadius: 999,
          border: '2px solid var(--accent)', opacity: 0.4,
          animation: 'fabPulse 2s ease-out infinite'
        }}></span>
      </a>

      <window.TweaksPanel title="Tweaks">
        <window.TweakSection label="Theme">
          <window.TweakRadio
            label="Mode"
            value={tweaks.theme}
            onChange={v => setTweak('theme', v)}
            options={[{ value: 'light', label: 'Paper' }, { value: 'dark', label: 'Ink' }]}
          />
          <window.TweakColor
            label="Accent"
            value={tweaks.accentHue}
            onChange={v => setTweak('accentHue', v)}
            options={[
              { value: 26, color: '#ff6a00' },
              { value: 220, color: '#14284f' },
              { value: 158, color: '#00795c' },
              { value: 358, color: '#b42318' },
            ]}
          />
        </window.TweakSection>

        <window.TweakSection label="Hero">
          <window.TweakRadio
            label="Visual"
            value={tweaks.heroVisual}
            onChange={v => setTweak('heroVisual', v)}
            options={[
              { value: 'ledger', label: 'Ledger' },
              { value: 'neural', label: 'Neural' },
              { value: 'code', label: 'Code' },
            ]}
          />
        </window.TweakSection>

        <window.TweakSection label="Motion">
          <window.TweakRadio
            label="Intensity"
            value={tweaks.motion}
            onChange={v => setTweak('motion', v)}
            options={[
              { value: 'off', label: 'Off' },
              { value: 'subtle', label: 'Subtle' },
              { value: 'full', label: 'Full' },
            ]}
          />
        </window.TweakSection>

        <window.TweakSection label="Typography">
          <window.TweakSelect
            label="Pairing"
            value={tweaks.typography}
            onChange={v => setTweak('typography', v)}
            options={[
              { value: 'editorial', label: 'Newsreader serif + Geist (default)' },
              { value: 'geist', label: 'Geist only' },
              { value: 'ibm', label: 'IBM Plex Sans + Plex Mono' },
            ]}
          />
        </window.TweakSection>
      </window.TweaksPanel>

      <style>{`
        @media (max-width: 1200px) {
          .team-grid { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
        }
        @media (min-width: 901px) and (max-width: 1100px) {
          .services-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
          .ecodeteam-grid { grid-template-columns: 1fr !important; gap: 40px !important; }
          .products-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
          .method-rail { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; row-gap: 40px; }
          .method-rule, .method-chevron { display: none !important; }
          .partner-bar { grid-template-columns: 1fr 1fr !important; }
          .partner-bar > div:first-child { grid-column: 1 / -1; border-right: none !important; border-bottom: 1px solid var(--line); }
          .partner-bar > div:nth-child(3) { border-right: none !important; }
        }
        @media (max-width: 960px) {
          .record-grid, .team-head, .ceo-grid, .contact-grid { grid-template-columns: 1fr !important; gap: 32px !important; }
          .team-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
          .trust-head { grid-template-columns: 1fr !important; gap: 18px !important; }
          .trust-awards { grid-template-columns: 1fr !important; }
          .trust-creds { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
          .trust-creds > div:nth-child(3) { border-left: none !important; }
          .trust-creds > div:nth-child(n+3) { border-top: 1px solid var(--line); }
          .trust-logos { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
          .trust-logos > div { border-left: 1px solid var(--line) !important; }
          .trust-logos > div:nth-child(3n+1) { border-left: none !important; }
          .trust-logos > div:nth-child(n+4) { border-top: 1px solid var(--line); }
          .method-grid { grid-template-columns: 1fr !important; }
          .method-arrow { display: none !important; }
          header > div {
            flex-wrap: wrap !important;
            row-gap: 8px !important;
          }
          header .desktop-nav {
            display: flex !important;
            order: 3 !important;
            width: 100% !important;
            flex-wrap: wrap !important;
            justify-content: flex-start !important;
            gap: 2px 4px !important;
            padding-top: 8px !important;
            border-top: 1px solid var(--line) !important;
          }
          header .desktop-nav a {
            padding: 6px 10px !important;
            font-size: 12.5px !important;
          }
        }
        @media (max-width: 700px) {
          .services-grid, .team-grid { grid-template-columns: 1fr !important; gap: 16px !important; }
          .trust-grid { grid-template-columns: 1fr !important; }
          .product-card { padding: 22px !important; }
        }
      `}</style>
    </>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
