const { useState, useEffect, useRef, useCallback, useContext, createContext, useMemo } = React;

/* ========= DATA (English-only identifiers; translatable text lives in locales) ========= */
const PROJECTS = [
  {
    num: "01",
    cat: "BOT",
    nameKey: "autoListings",
    name: "Auto Listings Bot",
    tech: ["Python 3", "aiogram", "Google Sheets API", "APScheduler", "Docker"],
    categoryKey: "Bot",
    techKey: ["Python"],
    links: [{ labelKey: "autoListings_channel", href: "https://t.me/carstoeu" }],
    codeFile: "requirements.txt",
    code: `# Auto Listings Bot

aiogram==3.3.0
gspread==6.0.0
aiohttp==3.9.1
beautifulsoup4==4.12.2
APScheduler==3.10.4
python-dotenv==1.0.0`,
  },
  {
    num: "02",
    cat: "MOBILE",
    nameKey: "clarios",
    name: "Clarios ConnectHub",
    tech: ["Flutter", "Dart", "BLoC", "Azure AD", "SQLite", "ML Kit"],
    categoryKey: "Mobile",
    techKey: ["Flutter"],
    links: [
      { labelKey: "clarios_appstore", href: "https://apps.apple.com/pl/app/clarios-connecthub/id6754656681" },
      { labelKey: "clarios_googleplay", href: "https://play.google.com/store/apps/details?id=com.clarios.cs.hub.connect.droid" },
    ],
    codeFile: "pubspec.yaml",
    code: `# IoT Field Service App

name: iot_field_service
sdk: flutter ^3.x

# Key dependencies
dependencies:
  flutter_bloc, go_router, drift
  dio, azure_ad_oauth, get_it
  camera, google_ml_kit`,
  },
  {
    num: "03",
    cat: "ANDROID",
    nameKey: "sprayer",
    name: "Sprayer Monitor",
    tech: ["Kotlin", "RxJava", "Room", "Bluetooth LE", "Google Maps", "Firebase"],
    categoryKey: "Mobile",
    techKey: ["Kotlin"],
    links: [],
    codeFile: "build.gradle",
    code: `// Sprayer Monitor

android {
  compileSdk 35
  minSdk 21
}
dependencies {
  koin, rxjava3, retrofit
  room, rxandroidble, maps
}`,
  },
  {
    num: "04",
    cat: "WEB",
    nameKey: "artme",
    name: "ArtMe Book",
    tech: ["Next.js 14", "React 18", "TypeScript", "Tailwind CSS", "Stripe", "Vercel"],
    categoryKey: "Web",
    techKey: ["Next.js"],
    personal: true,
    links: [{ labelKey: "artme_website", href: "http://artmebook.com" }],
    codeFile: "package.json",
    code: `// ArtBook Kids

"dependencies": {
  "next": "14.x",
  "react": "18.x",
  "stripe": "latest",
  "@vercel/blob": "latest"
}`,
  },
  {
    num: "05",
    cat: "iOS",
    nameKey: "neutral",
    name: "Neutral",
    tech: ["Swift", "SwiftUI", "SwiftData", "Charts", "Face ID"],
    categoryKey: "Mobile",
    techKey: ["Swift"],
    personal: true,
    links: [{ labelKey: "neutral_view", href: "/neutral/" }],
    codeFile: "Package.swift",
    code: `// Neutral - Emotion Tracker

platforms: [.iOS(.v17)]

features: {
  SwiftUI, SwiftData,
  Charts, LocalAuth
}`,
  },
  {
    num: "06",
    cat: "iOS",
    nameKey: "sorano",
    name: "Sorano",
    tech: ["Swift", "SwiftUI", "WidgetKit", "Notifications"],
    categoryKey: "Mobile",
    techKey: ["Swift"],
    personal: true,
    links: [{ labelKey: "sorano_view", href: "/sorano/" }],
    codeFile: "Package.swift",
    code: `// Sorano - Beat Jet Lag

platforms: [.iOS(.v18)]

features: {
  SwiftUI, WidgetKit,
  UserNotifications, CBTmin
}`,
  },
];

const TAB_KEYS = ["work", "projects", "trading", "youtube"];

/* ========= I18N ========= */
function getByPath(obj, path) {
  return path.split(".").reduce((o, k) => (o == null ? o : o[k]), obj);
}

const I18nContext = createContext(null);

function I18nProvider({ children }) {
  const [translations, setTranslations] = useState(null);
  const [lang, setLangState] = useState(() => {
    const stored = localStorage.getItem("lang");
    if (stored === "en" || stored === "ru") return stored;
    const nav = (navigator.language || "en").slice(0, 2);
    return nav === "ru" ? "ru" : "en";
  });

  useEffect(() => {
    Promise.all([
      fetch("locales/en.json").then(r => r.json()),
      fetch("locales/ru.json").then(r => r.json()),
    ]).then(([en, ru]) => setTranslations({ en, ru }))
      .catch(err => {
        console.error("i18n load failed", err);
        setTranslations({ en: {}, ru: {} });
      });
  }, []);

  const setLang = useCallback((next) => {
    setLangState(next);
    try { localStorage.setItem("lang", next); } catch {}
    document.documentElement.lang = next;
  }, []);

  useEffect(() => { document.documentElement.lang = lang; }, [lang]);

  const value = useMemo(() => {
    const bag = translations ? translations[lang] : {};
    const fallback = translations ? translations.en : {};
    const t = (key) => {
      const v = getByPath(bag, key);
      if (v != null) return v;
      const f = getByPath(fallback, key);
      if (f != null) return f;
      return key;
    };
    return { lang, setLang, t, raw: bag, ready: translations != null };
  }, [translations, lang, setLang]);

  return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>;
}

function useT() {
  const ctx = useContext(I18nContext);
  if (!ctx) throw new Error("useT outside I18nProvider");
  return ctx;
}

/* ========= HERO TERMINAL ========= */
function HeroTerminal() {
  const lines = [
    { cls: "t-prompt", text: "$ whoami" },
    { cls: "t-out", text: "alexey_rokalo" },
    { cls: "t-comment", text: "# mobile dev · builder · trader" },
    { cls: "t-prompt", text: "$ cat stack.yaml" },
    { cls: "t-key", text: "languages: ", kv: "Dart, Kotlin, Swift, TypeScript" },
    { cls: "t-key", text: "mobile:    ", kv: "Flutter, Android, iOS" },
    { cls: "t-key", text: "backend:   ", kv: "Firebase, REST, SQL" },
    { cls: "t-key", text: "other:     ", kv: "Stripe, n8n, GPT, Shopify" },
    { cls: "t-prompt", text: "$ status" },
    { cls: "t-str", text: "▸ available_for_hire: true" },
    { cls: "t-str", text: "▸ open_to_side_projects: true" },
    { cls: "t-prompt", text: "$ _" },
  ];
  const [shown, setShown] = useState(0);
  useEffect(() => {
    if (shown >= lines.length) return;
    const t = setTimeout(() => setShown(s => s + 1), shown === 0 ? 300 : 180);
    return () => clearTimeout(t);
  }, [shown]);
  return (
    <div className="terminal">
      <div className="terminal-head">
        <span className="terminal-dot r"></span>
        <span className="terminal-dot y"></span>
        <span className="terminal-dot g"></span>
        <span className="terminal-title">~/portfolio — zsh — 80×24</span>
      </div>
      <div className="terminal-body">
        {lines.slice(0, shown).map((l, i) => (
          <span className="t-line" key={i}>
            <span className={l.cls}>{l.text}</span>
            {l.kv && <span className="t-cmd">{l.kv}</span>}
          </span>
        ))}
        {shown >= lines.length && <span className="hero-caret" style={{ background: "#FF66CC", width: 8, height: 14, display: "inline-block" }}></span>}
      </div>
    </div>
  );
}

/* ========= NAV ========= */
function Nav({ active }) {
  const { t, lang, setLang } = useT();
  const [menuOpen, setMenuOpen] = useState(false);
  const [scrolled, setScrolled] = useState(false);
  const links = [
    { id: "hero", k: "nav.home" },
    { id: "about", k: "nav.about" },
    { id: "work", k: "nav.work" },
    { id: "project", k: "nav.project" },
  ];
  useEffect(() => {
    document.body.style.overflow = menuOpen ? "hidden" : "";
    return () => { document.body.style.overflow = ""; };
  }, [menuOpen]);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 80);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  const close = () => setMenuOpen(false);
  const pastHero = scrolled;
  return (
    <nav className={`nav ${menuOpen ? "nav--open" : ""} ${pastHero ? "nav--past-hero" : ""}`}>
      <a href="#hero" className="nav-logo" onClick={close}>
        <span className="nav-logo-dot"></span>
        <span className="nav-logo-text">alexey.rokalo</span>
      </a>
      <div className="nav-links">
        {links.map(l => (
          <a
            key={l.id}
            href={`#${l.id}`}
            className={`nav-link ${active === l.id ? "active" : ""}`}
            onClick={close}
          >{t(l.k)}</a>
        ))}
      </div>
      <div className="nav-actions">
        <button
          className="lang-toggle"
          aria-label={t("aria.lang_toggle")}
          onClick={() => setLang(lang === "en" ? "ru" : "en")}
        >
          {t("nav.langToggle")}
        </button>
        <button
          className="nav-burger"
          aria-label="Toggle menu"
          aria-expanded={menuOpen}
          onClick={() => setMenuOpen(o => !o)}
        >
          <span></span><span></span><span></span>
        </button>
      </div>
    </nav>
  );
}

/* ========= HERO ========= */
function Hero({ wp }) {
  const { t } = useT();
  return (
    <section id="hero" className="hero">
      <HeroWallpaper wp={wp} />
      <div className="container-wide hero-grid">
        <div className="hero-left hero-enter-left">
          <div className="hero-prompt">{t("hero.prefix")}</div>
          <h1 className="hero-title">
            {t("hero.title_line1")}<br />
            <span className="hero-title-accent">{t("hero.title_line2")}</span>
            <span className="hero-caret"></span>
          </h1>
          <p className="hero-tagline" dangerouslySetInnerHTML={{ __html: t("hero.tagline_html") }} />
          <div className="hero-actions">
            <a href="#about" className="btn btn-primary">{t("hero.cta_about")}</a>
            <a href="/resume.pdf" className="btn">{t("hero.cta_resume")}</a>
            <a href="#project" className="btn">{t("hero.cta_projects")}</a>
          </div>
        </div>
        <div className="hero-right hero-enter-right">
          <HeroTerminal />
        </div>
      </div>
    </section>
  );
}

function HeroWallpaper({ wp }) {
  return (
    <div className="wallpaper-mount" aria-hidden="true">
      {window.Wallpaper ? React.createElement(window.Wallpaper, { id: wp, key: wp }) : null}
    </div>
  );
}

/* ========= ABOUT ========= */
function About() {
  const { t, raw } = useT();
  const stack = (raw.about && raw.about.card_stack_rows) || { languages: [], mobile: [], tools: [], other: [] };
  const langRows = (raw.about && raw.about.card_lang_rows) || [];
  const status = (raw.about && raw.about.card_lang_status) || {};
  return (
    <section id="about">
      <div className="container reveal">
        <div className="section-head">
          <div>
            <div className="section-tag">{t("about.tag")}</div>
            <h2 className="section-title"><span className="bracket">&lt;</span>{t("about.title")}<span className="bracket">/&gt;</span></h2>
          </div>
          <div className="section-meta">{t("about.meta_line1")}<br />{t("about.meta_line2")}</div>
        </div>

        <div className="about-grid">
          <div className="card" data-enter="left">
            <div className="card-label">{t("about.card_bio_label")}</div>
            <div className="card-title">{t("about.card_bio_title")}</div>
            <div className="card-body" dangerouslySetInnerHTML={{ __html: t("about.card_bio_body_html") }} />
          </div>

          <div className="card" data-enter="right">
            <div className="card-label">{t("about.card_stack_label")}</div>
            <div className="card-title">{t("about.card_stack_title")}</div>
            <div className="stack-list">
              {["languages", "mobile", "tools", "other"].map(row => (
                <div className="stack-row" key={row}>
                  <span className="stack-label">{row}</span>
                  <div className="stack-vals">
                    {(stack[row] || []).map((v, i) => <span key={i}>{v}</span>)}
                  </div>
                </div>
              ))}
            </div>
          </div>

          <div className="card" data-enter="left">
            <div className="card-label">{t("about.card_education_label")}</div>
            <div className="card-title">{t("about.card_education_title")}</div>
            <div className="card-body" dangerouslySetInnerHTML={{ __html: t("about.card_education_body_html") }} />
          </div>

          <div className="card" data-enter="right">
            <div className="card-label">{t("about.card_lang_label")}</div>
            <div className="card-title">{t("about.card_lang_title")}</div>
            <div className="lang-bars">
              {langRows.map((r, i) => (
                <div className="lang-row" key={i}>
                  <span className="lang-name">{r.name}</span>
                  <div className="lang-bar"><div className="lang-fill" style={{ width: `${r.pct}%` }} /></div>
                  <span className="lang-level">{r.level}</span>
                </div>
              ))}
            </div>
            <div className="status-grid">
              <div className="status-item"><div className="status-key">{status.nationality_key}</div><div className="status-val">{status.nationality_val}</div></div>
              <div className="status-item"><div className="status-key">{status.based_in_key}</div><div className="status-val">{status.based_in_val}</div></div>
              <div className="status-item"><div className="status-key">{status.available_key}</div><div className="status-val ok">{status.available_val}</div></div>
              <div className="status-item"><div className="status-key">{status.side_key}</div><div className="status-val ok">{status.side_val}</div></div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ========= WHAT I DO ========= */
function WhatIDo() {
  const { t } = useT();
  const [tab, setTab] = useState("work");
  const label = t(`work.tabs.${tab}.label`);
  const title = t(`work.tabs.${tab}.title`);
  const p1 = t(`work.tabs.${tab}.p1`);
  const p2 = t(`work.tabs.${tab}.p2`);
  const bullets = t(`work.tabs.${tab}.bullets`);
  return (
    <section id="work">
      <div className="container reveal">
        <div className="section-head">
          <div>
            <div className="section-tag">{t("work.tag")}</div>
            <h2 className="section-title"><span className="bracket">&lt;</span>{t("work.title")}<span className="bracket">/&gt;</span></h2>
          </div>
          <div className="section-meta">{t("work.meta_line1")}<br />{t("work.meta_line2")}</div>
        </div>

        <div className="do-tabs">
          {TAB_KEYS.map(k => (
            <button key={k} onClick={() => setTab(k)} className={`do-tab ${tab === k ? "active" : ""}`}>
              <span className="do-tab-icon">~/</span>{t(`work.tabs.${k}.label`)}
            </button>
          ))}
        </div>

        <div className="do-panel">
          <div className="do-panel-text" data-enter="left">
            <h3>{title}</h3>
            <p>{p1}</p>
            <p>{p2}</p>
            <ul className="do-panel-list">
              {Array.isArray(bullets) && bullets.map((b, i) => <li key={i}>{b}</li>)}
            </ul>
          </div>
          <div className="terminal" data-enter="right" style={{ alignSelf: "stretch" }}>
            <div className="terminal-head">
              <span className="terminal-dot r"></span>
              <span className="terminal-dot y"></span>
              <span className="terminal-dot g"></span>
              <span className="terminal-title">{(title || "").toLowerCase()}</span>
            </div>
            <div className="terminal-body">
              <span className="t-line"><span className="t-prompt">$ cat {label}.md</span></span>
              <span className="t-line"><span className="t-comment">## {title}</span></span>
              <span className="t-line"> </span>
              <span className="t-line"><span className="t-out">{p1}</span></span>
              <span className="t-line"> </span>
              {Array.isArray(bullets) && bullets.map((b, i) => (
                <span className="t-line" key={i}><span className="t-str">▸</span> <span className="t-cmd">{b}</span></span>
              ))}
              <span className="t-line"> </span>
              <span className="t-line"><span className="t-prompt">$ _</span></span>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ========= PROJECTS ========= */
function Projects() {
  const { t, raw } = useT();
  const CATEGORIES = (raw.projects && raw.projects.filter_cats) || ["All", "Mobile", "Web", "Bot"];
  const TECHS = (raw.projects && raw.projects.filter_techs) || ["All", "Python", "Flutter", "Kotlin", "Next.js", "Swift"];
  const [cat, setCat] = useState("All");
  const [tech, setTech] = useState("All");
  const filtered = PROJECTS.filter(p =>
    (cat === "All" || p.categoryKey === cat) &&
    (tech === "All" || p.techKey.includes(tech))
  );

  const highlight = (code) => {
    const lines = code.split("\n");
    return lines.map((ln, i) => {
      let el;
      if (/^\s*(#|\/\/)/.test(ln)) {
        el = <span className="code-comment">{ln}</span>;
      } else {
        const parts = [];
        let idx = 0;
        const regex = /("[^"]*"|\b\d+(\.\d+)?\b|\^?\d+\.x)/g;
        let m; let last = 0;
        while ((m = regex.exec(ln)) !== null) {
          if (m.index > last) parts.push(<span key={idx++}>{ln.slice(last, m.index)}</span>);
          const tok = m[0];
          if (tok.startsWith("\"")) parts.push(<span className="code-str" key={idx++}>{tok}</span>);
          else parts.push(<span className="code-num" key={idx++}>{tok}</span>);
          last = m.index + tok.length;
        }
        if (last < ln.length) parts.push(<span key={idx++}>{ln.slice(last)}</span>);
        el = <>{parts}</>;
      }
      return <div key={i}>{el || " "}</div>;
    });
  };

  const meta = (t("projects.meta_template") || "{n} of {total} shown")
    .replace("{n}", filtered.length)
    .replace("{total}", PROJECTS.length);

  return (
    <section id="project">
      <div className="container reveal">
        <div className="section-head">
          <div>
            <div className="section-tag">{t("projects.tag")}</div>
            <h2 className="section-title"><span className="bracket">&lt;</span>{t("projects.title")}<span className="bracket">/&gt;</span></h2>
          </div>
          <div className="section-meta">{meta}</div>
        </div>

        <div className="projects-intro">
          <div className="filter-group">
            <div className="filter-label">{t("projects.filter_cat_label")}</div>
            <div className="filter-row">
              {CATEGORIES.map(c => (
                <button key={c} onClick={() => setCat(c)} className={`filter-chip ${cat === c ? "active" : ""}`}>{c}</button>
              ))}
            </div>
          </div>
          <div className="filter-group">
            <div className="filter-label">{t("projects.filter_tech_label")}</div>
            <div className="filter-row">
              {TECHS.map(tk => (
                <button key={tk} onClick={() => setTech(tk)} className={`filter-chip ${tech === tk ? "active" : ""}`}>{tk}</button>
              ))}
            </div>
          </div>
        </div>

        <div>
          {filtered.map((p, i) => (
            <article key={p.num} className="project" data-enter={i % 2 === 0 ? "left" : "right"}>
              <div className="project-num">{p.num}</div>
              <div className="project-meta">
                <span className="project-cat">● {p.cat}{p.personal && ` · ${t("projects.personal_badge")}`}</span>
                <h3 className="project-name">{p.name}</h3>
                <p className="project-desc">{t(`projects.descs.${p.nameKey}`)}</p>
                <div className="project-tech">
                  {p.tech.map((tg, i) => <span key={i} className="tech-tag">{tg}</span>)}
                </div>
                {p.links.length > 0 && (
                  <div className="project-links">
                    {p.links.map((l, i) => (
                      <a key={i} href={l.href} target={l.href.startsWith("http") ? "_blank" : undefined} rel={l.href.startsWith("http") ? "noopener noreferrer" : undefined} className="project-link">[[ {t(`projects.link_labels.${l.labelKey}`)} ]]</a>
                    ))}
                  </div>
                )}
              </div>
              <div className="project-code">
                <div className="project-code-head">{p.codeFile}</div>
                <div className="project-code-body">{highlight(p.code)}</div>
              </div>
            </article>
          ))}
          {filtered.length === 0 && (
            <div className="card" style={{ textAlign: "center", padding: "64px" }}>
              <div className="card-label">{t("projects.no_match_label")}</div>
              <div className="card-title">{t("projects.no_match_title")}</div>
              <div className="card-body">{t("projects.no_match_body")}</div>
            </div>
          )}
        </div>
      </div>
    </section>
  );
}

/* ========= FOOTER (real social icons + version span for release.sh) ========= */
function Footer() {
  const { t, raw } = useT();
  const colophonLines = (raw.footer && raw.footer.colophon_lines) || [];
  return (
    <footer className="footer">
      <div className="footer-grid">
        <div className="footer-col">
          <h4>{t("footer.col_navigate")}</h4>
          <ul>
            <li><a href="#hero">{t("nav.home")}</a></li>
            <li><a href="#about">{t("nav.about")}</a></li>
            <li><a href="#work">{t("nav.work")}</a></li>
            <li><a href="#project">{t("nav.project")}</a></li>
          </ul>
        </div>
        <div className="footer-col">
          <h4>{t("footer.col_elsewhere")}</h4>
          <ul>
            <li>
              <a href="https://github.com/AlexRokalo" target="_blank" rel="noopener noreferrer" aria-label={t("aria.github")} className="footer-social-link">
                <svg className="footer-social-icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0 1 12 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"/></svg>
                <span>github →</span>
              </a>
            </li>
            <li>
              <a href="https://www.linkedin.com/in/alexey-rokalo-222a3616a/" target="_blank" rel="noopener noreferrer" aria-label={t("aria.linkedin")} className="footer-social-link">
                <svg className="footer-social-icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>
                <span>linkedin →</span>
              </a>
            </li>
            <li>
              <a href="https://t.me/alexRokalo" target="_blank" rel="noopener noreferrer" aria-label={t("aria.telegram")} className="footer-social-link">
                <svg className="footer-social-icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/></svg>
                <span>telegram →</span>
              </a>
            </li>
            <li>
              <a href="https://www.threads.net/@rokaloalex" target="_blank" rel="noopener noreferrer" aria-label={t("aria.threads")} className="footer-social-link">
                <svg className="footer-social-icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12.186 24h-.007c-3.581-.024-6.334-1.205-8.184-3.509C2.35 18.44 1.5 15.586 1.472 12.01v-.017c.03-3.579.879-6.43 2.525-8.482C5.845 1.205 8.6.024 12.18 0h.014c2.746.02 5.043.725 6.826 2.098 1.677 1.29 2.858 3.13 3.509 5.467l-2.04.569c-1.104-3.96-3.898-5.984-8.304-6.015-2.91.022-5.11.936-6.54 2.717C4.307 6.504 3.616 8.914 3.589 12c.027 3.086.718 5.496 2.057 7.164 1.43 1.783 3.631 2.698 6.54 2.717 2.623-.02 4.358-.631 5.8-2.045 1.647-1.613 1.618-3.593 1.09-4.798-.31-.71-.873-1.3-1.634-1.75-.192 1.352-.622 2.446-1.284 3.272-.886 1.102-2.14 1.704-3.73 1.79-1.202.065-2.361-.218-3.259-.801-1.063-.689-1.685-1.74-1.752-2.96-.065-1.182.408-2.256 1.333-3.022.887-.735 2.088-1.17 3.57-1.29 1.202-.096 2.313.018 3.302.34-.03-1.146-.312-2.018-.841-2.6-.6-.66-1.54-1.01-2.795-1.04l-.09-.002c-1.09 0-2.054.324-2.664.95-.49.5-.803 1.17-.93 2l-2.08-.31c.18-1.17.63-2.143 1.35-2.9.96-1.01 2.357-1.545 4.035-1.545l.12.001c1.754.03 3.153.56 4.16 1.573.945.953 1.44 2.282 1.47 3.952v.022c.018.493.012.988-.012 1.463 1.07.626 1.894 1.456 2.4 2.43.796 1.535.882 4.054-1.168 6.066C18.157 23.145 15.662 23.976 12.186 24zm-.09-8.143c-1.103.088-1.95.405-2.453.92-.347.355-.53.798-.505 1.217.022.356.168.685.435.963.38.394 1.003.625 1.757.652 1.1.039 1.991-.283 2.648-1.1.478-.591.804-1.406.963-2.412-.882-.246-1.833-.334-2.845-.24z"/></svg>
                <span>threads →</span>
              </a>
            </li>
            <li>
              <a href="https://www.instagram.com/rokaloalex" target="_blank" rel="noopener noreferrer" aria-label={t("aria.instagram")} className="footer-social-link">
                <svg className="footer-social-icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 0C8.74 0 8.333.015 7.053.072 5.775.132 4.905.333 4.14.63c-.789.306-1.459.717-2.126 1.384S.935 3.35.63 4.14C.333 4.905.131 5.775.072 7.053.012 8.333 0 8.74 0 12s.015 3.667.072 4.947c.06 1.277.261 2.148.558 2.913.306.788.717 1.459 1.384 2.126.667.666 1.336 1.079 2.126 1.384.766.296 1.636.499 2.913.558C8.333 23.988 8.74 24 12 24s3.667-.015 4.947-.072c1.277-.06 2.148-.262 2.913-.558.788-.306 1.459-.718 2.126-1.384.666-.667 1.079-1.335 1.384-2.126.296-.765.499-1.636.558-2.913.06-1.28.072-1.687.072-4.947s-.015-3.667-.072-4.947c-.06-1.277-.262-2.149-.558-2.913-.306-.789-.718-1.459-1.384-2.126C21.319 1.347 20.651.935 19.86.63c-.765-.297-1.636-.499-2.913-.558C15.667.012 15.26 0 12 0zm0 2.16c3.203 0 3.585.016 4.85.071 1.17.055 1.805.249 2.227.415.562.217.96.477 1.382.896.419.42.679.819.896 1.381.164.422.36 1.057.413 2.227.057 1.266.07 1.646.07 4.85s-.015 3.585-.074 4.85c-.061 1.17-.256 1.805-.421 2.227-.224.562-.479.96-.899 1.382-.419.419-.824.679-1.38.896-.42.164-1.065.36-2.235.413-1.274.057-1.649.07-4.859.07-3.211 0-3.586-.015-4.859-.074-1.171-.061-1.816-.256-2.236-.421-.569-.224-.96-.479-1.379-.899-.421-.419-.69-.824-.9-1.38-.165-.42-.359-1.065-.42-2.235-.045-1.26-.061-1.649-.061-4.844 0-3.196.016-3.586.061-4.861.061-1.17.255-1.814.42-2.234.21-.57.479-.96.9-1.381.419-.419.81-.689 1.379-.898.42-.166 1.051-.361 2.221-.421 1.275-.045 1.65-.06 4.859-.06l.045.03zm0 3.678c-3.405 0-6.162 2.76-6.162 6.162 0 3.405 2.76 6.162 6.162 6.162 3.405 0 6.162-2.76 6.162-6.162 0-3.405-2.76-6.162-6.162-6.162zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm7.846-10.405c0 .795-.646 1.44-1.44 1.44-.795 0-1.44-.646-1.44-1.44 0-.794.646-1.439 1.44-1.439.793-.001 1.44.645 1.44 1.439z"/></svg>
                <span>instagram →</span>
              </a>
            </li>
            <li><a href="/resume.pdf" aria-label={t("aria.resume")}>resume.pdf →</a></li>
          </ul>
        </div>
        <div className="footer-col">
          <h4>{t("footer.col_colophon")}</h4>
          <ul>
            {colophonLines.map((line, i) => (
              <li key={i} style={{ color: "var(--c-text-dim)" }}>{line}</li>
            ))}
          </ul>
        </div>
      </div>
      <div className="footer-bottom">
        <span id="app-version">v2.0.0</span>
        <span>{t("footer.bottom_location")}</span>
      </div>
    </footer>
  );
}

/* ========= ASCII RAIN ========= */
function AsciiRain({ on }) {
  const chars = ["▸","█","░","▒","▓","×","/","\\","$","{","}",";",">","_","•","◆","◇","◢","◣","◤","◥","║","═","╬","┼","┤","├","▼","▲","◆","0","1"];
  const count = 48;
  const items = useMemo(() =>
    Array.from({ length: count }).map((_, i) => ({
      id: i,
      left: Math.random() * 100,
      dur: 7 + Math.random() * 12,
      delay: Math.random() * -15,
      size: 10 + Math.random() * 10,
      char: chars[Math.floor(Math.random() * chars.length)],
      drift: (Math.random() - 0.5) * 80,
      opacity: 0.35 + Math.random() * 0.5,
    })), []);
  if (!on) return null;
  return (
    <>
      {items.map((it) => (
        <div
          key={it.id}
          className="ascii-flake"
          style={{
            left: `${it.left}%`,
            fontSize: `${it.size}px`,
            animationDuration: `${it.dur}s`,
            animationDelay: `${it.delay}s`,
            opacity: it.opacity,
            "--drift": `${it.drift}px`,
          }}
        >{it.char}</div>
      ))}
    </>
  );
}

function AsciiRainToggle({ on, onToggle }) {
  const { t } = useT();
  return (
    <div className="snow-btn">
      <span>{t("ascii.prefix")}</span>
      <span>$</span>
      <span>{t("ascii.key")}</span>
      <span>{t("ascii.eq")}</span>
      <button
        className={`tog ${on ? "on" : ""}`}
        onClick={onToggle}
        aria-label={t("aria.ascii_toggle")}
        aria-pressed={on}
      >
        {on ? t("ascii.on") : t("ascii.off")}
      </button>
    </div>
  );
}

/* ========= WALLPAPER PICKER ========= */
function WallpaperPicker({ current, onPick, onClose }) {
  const { t } = useT();
  const items = window.WALLPAPERS || [];
  return (
    <div className="wall-picker">
      <div className="wall-picker-head">
        <span>{t("wallpaper.picker_title")}</span>
        <span className="wall-picker-close" onClick={onClose}>×</span>
      </div>
      {items.map(w => (
        <button
          key={w.id}
          className={`wall-opt ${current === w.id ? "active" : ""}`}
          onClick={() => onPick(w.id)}
        >
          <span className="wall-opt-dot"></span>
          <span style={{ flex: 1 }}>
            <div className="wall-opt-label">{t(`wallpaper.options.${w.id}.label`)}</div>
            <div className="wall-opt-desc">{t(`wallpaper.options.${w.id}.desc`)}</div>
          </span>
        </button>
      ))}
    </div>
  );
}

/* ========= PAGE ENTRANCE (GSAP + reduced motion) ========= */
function PageEnterReveals() {
  useEffect(() => {
    if (typeof gsap === "undefined" || typeof ScrollTrigger === "undefined") return;
    if (window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    gsap.registerPlugin(ScrollTrigger);

    gsap.utils.toArray("[data-enter]").forEach((el) => {
      const dir = el.dataset.enter;
      const fromVars = { opacity: 0, filter: "blur(6px)" };
      if (dir === "left") fromVars.x = -56;
      else if (dir === "right") fromVars.x = 56;
      else fromVars.y = 32;
      gsap.fromTo(el, fromVars, {
        opacity: 1, x: 0, y: 0, filter: "blur(0px)",
        duration: 0.7, ease: "power2.out",
        scrollTrigger: { trigger: el, start: "top 85%", toggleActions: "play none none reverse" },
      });
    });

    gsap.utils.toArray(".section-head").forEach((el) => {
      gsap.fromTo(el, { opacity: 0, y: 40 }, {
        opacity: 1, y: 0, duration: 1, ease: "power2.out",
        scrollTrigger: { trigger: el, start: "top 88%", toggleActions: "play none none reverse" },
      });
    });

    const heroRight = document.querySelector(".hero-right");
    if (heroRight) {
      gsap.to(heroRight, {
        y: -60, ease: "none",
        scrollTrigger: { trigger: "#hero", start: "top top", end: "bottom top", scrub: 0.6 },
      });
    }

    gsap.utils.toArray(".project-num").forEach((el) => {
      gsap.fromTo(el,
        { scale: 0.7, opacity: 0, letterSpacing: "0em" },
        {
          scale: 1, opacity: 0.95, letterSpacing: "-0.08em",
          duration: 1, ease: "power3.out",
          scrollTrigger: { trigger: el, start: "top 80%", toggleActions: "play none none reverse" },
        });
    });

    return () => { ScrollTrigger.getAll().forEach((st) => st.kill()); };
  }, []);
  return null;
}

/* ========= APP ROOT ========= */
function App() {
  const { ready } = useT();
  const [active, setActive] = useState("hero");
  const [snow, setSnow] = useState(true);
  const [wp, setWp] = useState(() => localStorage.getItem("wp") || "grid");
  const [pickerOpen, setPickerOpen] = useState(false);

  useEffect(() => { try { localStorage.setItem("wp", wp); } catch {} }, [wp]);

  useEffect(() => {
    const sections = ["hero", "about", "work", "project"];
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) setActive(e.target.id); });
    }, { rootMargin: "-40% 0px -50% 0px" });
    sections.forEach(id => { const el = document.getElementById(id); if (el) io.observe(el); });
    return () => { io.disconnect(); };
  }, []);

  if (!ready) return null;

  return (
    <>
      <div className="grid-bg"></div>
      <AsciiRain on={snow} />
      <PageEnterReveals />
      <Nav active={active} />
      <main>
        <Hero wp={wp} />
        <About />
        <WhatIDo />
        <Projects />
      </main>
      <Footer />
      <AsciiRainToggle on={snow} onToggle={() => setSnow(s => !s)} />
      {pickerOpen ? (
        <WallpaperPicker current={wp} onPick={setWp} onClose={() => setPickerOpen(false)} />
      ) : (
        <button
          className="wall-picker"
          style={{ padding: "8px 12px", minWidth: 0, cursor: "pointer" }}
          onClick={() => setPickerOpen(true)}
          aria-label="Open wallpaper picker"
        >
          <span style={{ color: "var(--c-primary)" }}>◆ wallpaper.sh</span>
        </button>
      )}
    </>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(
  <I18nProvider><App /></I18nProvider>
);
