// CodeObscura main site — single-page React build
const { useEffect, useRef } = React;

// ---------- atoms ----------
// Sun-and-moon mark: CSS mask so the SVG inherits theme colour via currentColor.
const SunMoon = ({ size = 28, style = {} }) => (
  <span
    aria-hidden="true"
    style={{
      display: "inline-block",
      verticalAlign: "middle",
      width: size,
      height: size,
      backgroundColor: "currentColor",
      WebkitMask: "url(css/img/sun-moon.svg) center / contain no-repeat",
      mask: "url(css/img/sun-moon.svg) center / contain no-repeat",
      ...style,
    }}
  />
);

const Reveal = ({ children, delay = 0, as: As = "div", className = "", ...rest }) => {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const obs = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) { setTimeout(() => el.classList.add("in"), delay); obs.disconnect(); } },
      { threshold: 0.12 }
    );
    obs.observe(el);
    return () => obs.disconnect();
  }, [delay]);
  return <As ref={ref} {...rest} className={("reveal " + className).trim()}>{children}</As>;
};

const ArrowUp = () => (
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
    <path d="M5 19L19 5M9 5h10v10" strokeLinecap="round" strokeLinejoin="round"/>
  </svg>
);

// ---------- nav ----------
function Nav() {
  return (
    <nav className="top">
      <div className="top-inner">
        <a href="/" className="brand">
          <span className="brand-mark"><SunMoon size={28} /></span>
          <span className="brand-name">Code<em>Obscura</em></span>
        </a>
        <div className="top-meta">
          <a className="nav-link" href="#work">Work</a>
          <a className="nav-link" href="#services">Services</a>
          <a className="nav-link" href="#about">About</a>
          <a className="nav-link" href="#contact">Contact</a>
          <span><span className="live-dot"></span>EST. 2024 · LDN</span>
        </div>
      </div>
    </nav>
  );
}

// ---------- hero ----------
function Hero() {
  return (
    <section className="hero">
      <Reveal delay={80}>
        <h1 className="hero-title">
          Thoughtfully designed apps<br/>made in <em>London.</em>
        </h1>
      </Reveal>

      <Reveal className="hero-sub-row" delay={180}>
        <p className="hero-lede">
          CodeObscura is a small, opinionated studio shipping iOS and Android apps for founders
          and brands who care about craft. We design, build, and ship — quietly, end-to-end, from
          concept to App Store.
        </p>
        <div className="hero-actions">
          <a className="btn" href="#contact">Start a project <ArrowUp/></a>
          <a className="btn ghost" href="#work">See our work</a>
        </div>
      </Reveal>

      <Reveal className="hero-strip" delay={260}>
        <span className="hero-strip-item"><b>iOS</b> · iPhone · iPad · Apple Watch</span>
        <span className="hero-strip-item"><b>Android</b> · Phone · Tablet</span>
        <span className="hero-strip-item"><b>AI</b> · Vision · LLM · On-device</span>
        <span className="hero-strip-item"><b>End-to-end</b> · Design → Ship</span>
      </Reveal>
    </section>
  );
}

// ---------- stats ----------
function Stats() {
  const years = Math.max(1, new Date().getFullYear() - 2024);
  return (
    <section className="stats">
      <div className="shell">
        <div className="stats-grid">
          <Reveal className="stat">
            <div className="eyebrow" style={{marginBottom: 10}}>Time on the market</div>
            <div className="stat-num"><em>{years}</em></div>
            <div className="stat-label">Years building thoughtful apps from London.</div>
          </Reveal>
          <Reveal className="stat" delay={120}>
            <div className="eyebrow" style={{marginBottom: 10}}>Lines of code</div>
            <div className="stat-num">5<em>B+</em></div>
            <div className="stat-label">Code written across the team's careers — every line considered.</div>
          </Reveal>
          <Reveal className="stat" delay={240}>
            <div className="eyebrow" style={{marginBottom: 10}}>Possibilities</div>
            <div className="stat-num"><em>∞</em></div>
            <div className="stat-label">Ideas waiting for the right team. Maybe yours.</div>
          </Reveal>
        </div>
      </div>
    </section>
  );
}

// ---------- featured app card ----------
function Featured({ id, badge, name, nameEm, desc, bg, icon, appstore, learnMore, reverse }) {
  return (
    <section className="featured" id={id}>
      <div className="shell">
        <Reveal className="feature-card">
          <div
            className="feature-art"
            style={{ backgroundImage: `url(${bg})`, order: reverse ? 2 : 1 }}
          >
            <span className="meta">[ {badge} ]</span>
          </div>
          <div className="feature-body" style={{ order: reverse ? 1 : 2 }}>
            <div>
              <div className="feature-icon-row">
                {icon && <img className="feature-icon" src={icon} alt={`${name}${nameEm} icon`} />}
                <span className="eyebrow">{badge}</span>
              </div>
              <h3 className="feature-name" style={{marginTop: 22}}>
                {name} <em>{nameEm}</em>
              </h3>
              <p className="feature-desc" style={{marginTop: 18}}>{desc}</p>
            </div>
            <div className="feature-foot">
              {appstore && (
                <a href={appstore} className="appstore" target="_blank" rel="noopener noreferrer">
                  <img src="css/image/abc.svg" alt="Download on the App Store" />
                </a>
              )}
              {learnMore && <a href={learnMore} className="btn ghost lg">Learn more <ArrowUp/></a>}
            </div>
          </div>
        </Reveal>
      </div>
    </section>
  );
}

// ---------- bespoke ----------
function Bespoke() {
  const rows = [
    { num: "01", label: "Discovery", em: "& strategy", desc: "Problem framing, user research, scoping. We define what's worth building before we build." },
    { num: "02", label: "Product", em: "design", desc: "End-to-end UX & UI. Pixel-perfect interfaces, motion, prototyping in Figma." },
    { num: "03", label: "Native", em: "engineering", desc: "Swift, SwiftUI, Kotlin, Compose. AI on-device, real-time data, offline-first." },
    { num: "04", label: "Launch", em: "& iterate", desc: "App Store submission, analytics, post-launch tuning. We stay after the ship." },
  ];
  return (
    <section className="bespoke" id="services">
      <div className="shell">
        <Reveal className="sec-head">
          <div>
            <h2 className="sec-title">
              Apps built from <em>scratch.</em><br/>
              No templates. No <em>shortcuts.</em>
            </h2>
          </div>
          <p className="sec-blurb">
            Every app starts with a deep understanding of the problem it needs to solve. We design and develop
            custom iOS and Android applications tailored to your business goals, audience, and market —
            from initial concept through App Store launch.
          </p>
        </Reveal>

        <div className="bespoke-grid">
          <Reveal className="bespoke-list" delay={120}>
            {rows.map((r) => (
              <div className="bespoke-row" key={r.num}>
                <span className="num">{r.num}</span>
                <div>
                  <div className="label">{r.label} <em>{r.em}</em></div>
                  <div className="desc">{r.desc}</div>
                </div>
              </div>
            ))}
          </Reveal>
          <Reveal className="bespoke-copy" delay={220}>
            <p>
              We specialise in <em style={{fontStyle: "italic", color: "var(--accent)"}}>AI-powered features</em>,
              real-time data processing, and intuitive interfaces that keep users engaged and coming back.
            </p>
            <p>
              From early prototypes to long-term partnerships, we work as a quiet extension of your team — focused on
              what to ship next, and how to ship it well.
            </p>
            <p style={{marginTop: 28}}>
              <a className="btn" href="#contact">Book an intro call <ArrowUp/></a>
            </p>
          </Reveal>
        </div>
      </div>
    </section>
  );
}

// ---------- apps grid ----------
const APPS = [
  { name: "Life in the ", em: "UK", tag: "Education · Test prep", desc: "Pass the Life in the UK test first time. 22 mock tests, 1,100+ questions, fully offline.", bg: "css/img/bg_lifeinuk.jpg", status: "Featured", href: "https://codeobscura.com/lifeinuk/" },
  { name: "Sneaker", em: "Lens", tag: "AI · Vision", desc: "Point your camera at any sneaker — instant ID, colourway, and resale value.", bg: "css/img/bg_sneakerlens.jpg", status: "Featured", href: "https://sneakerlens.codeobscura.com/" },
  { name: "", em: "Words", tag: "Game · Multiplayer", desc: "A creative word game that improves memory and broadens vocabulary. Wi-Fi or Bluetooth.", bg: "css/img/bg_words.jpg", status: "Live", href: "https://itunes.apple.com/us/app/words-a-game-about-letters/id909997428" },
  { name: "Live", em: "Longer", tag: "Wellness · Data", desc: "50+ articles, 25 hours of video, life-expectancy calculator. Live well, live longer.", bg: "css/img/bg_livelonger.jpg", status: "Live", href: "https://itunes.apple.com/ru/app/livelonger/id533006757" },
  { name: "Daily ", em: "Impulse", tag: "Health · AI", desc: "Personal AI health coach — habits, sleep, activity. Quietly nudging you forward.", bg: "css/img/bg_dailyimpulse.jpg", status: "Live" },
  { name: "Road", em: "Signs", tag: "Reference · Travel", desc: "European road signs and driving rules — designed with love for iPhone and iPad.", bg: "css/img/bg_roadsigns.jpg", status: "Live" },
];

function AppsGrid() {
  return (
    <section className="apps" id="work">
      <div className="shell">
        <Reveal className="sec-head">
          <div>
            <h2 className="sec-title">Dozens of <em>live apps</em> on the App Store.</h2>
          </div>
          <p className="sec-blurb">
            Here are our favourites. Each was built with the same belief — that mobile devices can change
            people's lives, and that an app can be more than a product.
          </p>
        </Reveal>

        <div className="apps-grid">
          {APPS.map((a, i) => (
            <Reveal
              as={a.href ? "a" : "article"}
              href={a.href}
              target={a.href ? "_blank" : undefined}
              rel={a.href ? "noopener noreferrer" : undefined}
              className="app-card"
              key={a.em}
              delay={i * 60}
              style={a.href ? undefined : { cursor: "default" }}
            >
              <div className="app-cover" style={{ backgroundImage: `url(${a.bg})` }}>
                <span className="badge">{a.status}</span>
              </div>
              <div className="app-meta">
                <h3>{a.name}<em>{a.em}</em></h3>
                <p>{a.desc}</p>
                <div className="row">
                  <span>{a.tag}</span>
                  <span className="arrow"><ArrowUp/></span>
                </div>
              </div>
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
}

// ---------- services ----------
const SERVICES = [
  { num: "01", title: "Reasonable", em: "approach", desc: "Every order treated individually. We listen carefully and answer honestly." },
  { num: "02", title: "Real", em: "responsibility", desc: "We commit to the deadline and to the quality of what we ship — not one or the other." },
  { num: "03", title: "Flexible", em: "payments", desc: "Development split into stages. Pay as the work moves forward, not all up front." },
  { num: "04", title: "Long-term", em: "support", desc: "After launch we stay — improvements, updates, and the small fixes that matter." },
];

function Services() {
  return (
    <section className="services">
      <div className="shell">
        <Reveal className="sec-head">
          <div>
            <h2 className="sec-title">Quiet <em>principles.</em><br/>Clear delivery.</h2>
          </div>
          <p className="sec-blurb">
            A handful of things we hold to on every project, regardless of size or scope.
          </p>
        </Reveal>
        <div className="services-grid">
          {SERVICES.map((s, i) => (
            <Reveal className="service" key={s.num} delay={i * 80}>
              <span className="num">[ {s.num} ]</span>
              <h4>{s.title} <em>{s.em}</em></h4>
              <p>{s.desc}</p>
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
}

// ---------- testimonials ----------
const QUOTES = [
  { who: "James", role: "Meetwire", img: "css/img/person1.jpg", text: "During half a year of working together, we created a foundation for a series of mobile productivity services. Even despite unexpected shifts, the team caught up quickly on every phase.", emWords: ["productivity", "every phase"] },
  { who: "William", role: "Wanderlist", img: "css/img/person2.jpg", text: "CodeObscura finished all our tasks in the smallest time frame, proposed creative solutions, and helped us create a top-notch user interface. We know who we'll hire for our next app.", emWords: ["creative", "next app"] },
  { who: "Oliver", role: "Words", img: "css/img/person3.jpg", text: "I came in with nothing but an idea and the team helped with the concept, the logic, the design and animations from scratch. Online 24/7. Took every wish into consideration.", emWords: ["nothing but an idea", "every wish"] },
];

function highlightQuote(text, words) {
  let out = text;
  words.forEach(w => { out = out.replace(w, `__EM__${w}__/EM__`); });
  return out.split(/(__EM__.*?__\/EM__)/).map((part, i) => {
    if (part.startsWith("__EM__")) {
      return <em key={i}>{part.replace(/^__EM__|__\/EM__$/g, "")}</em>;
    }
    return <React.Fragment key={i}>{part}</React.Fragment>;
  });
}

function Testimonials() {
  return (
    <section className="testimonials">
      <div className="shell">
        <Reveal className="sec-head">
          <div>
            <h2 className="sec-title">What <em>founders</em><br/>have said.</h2>
          </div>
          <p className="sec-blurb">
            Three short notes from people we've shipped with — collected over coffee and Slack threads.
          </p>
        </Reveal>
        <div className="quote-grid">
          {QUOTES.map((q, i) => (
            <Reveal className="quote" key={q.who} delay={i * 100}>
              <span className="quote-mark">“</span>
              <div className="quote-text">{highlightQuote(q.text, q.emWords)}</div>
              <div className="quote-foot">
                <img className="quote-avatar" src={q.img} alt={`${q.who}, ${q.role}`} />
                <div>
                  <div className="quote-name">{q.who}</div>
                  <div className="quote-role">{q.role}</div>
                </div>
              </div>
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
}

// ---------- about ----------
function About() {
  return (
    <section className="about" id="about">
      <div className="shell">
        <Reveal className="sec-head">
          <div>
            <h2 className="sec-title">Why <em>us.</em></h2>
          </div>
        </Reveal>
        <div className="about-row">
          <Reveal>
            <p className="about-statement">
              We never settle, and never make compromises. We strive for <em>perfection</em> in everything we do —
              and we love the time we live in, where small teams can make <em>big things</em>.
            </p>
          </Reveal>
          <Reveal className="about-detail" delay={120}>
            <p>
              Founded in London in 2024, CodeObscura is a small studio focused on carefully designed apps for today's
              digital environment. We craft thoughtful, user-centric iOS and Android applications that solve real
              problems with elegance and precision.
            </p>
            <p>
              Our apps are made out of a strong belief that mobile devices can change people's lives — that an app can
              be not just a product, but something close to art. Since day one we've worked across iOS and Android, to
              meet people where they already are.
            </p>
            <p>
              The team is small on purpose. It means whoever picks up the call is who designs and ships your work.
            </p>
          </Reveal>
        </div>
      </div>
    </section>
  );
}

// ---------- contact ----------
function Contact() {
  return (
    <section className="contact" id="contact">
      <div className="shell" style={{position: "relative"}}>
        <Reveal delay={120}>
          <h2 className="contact-title">
            Have an <em>idea?</em><br/>
            Let's <em>build it.</em>
          </h2>
        </Reveal>
        <Reveal delay={180}>
          <p className="contact-sub">
            Tell us about the app you want to make. We read every message and reply when we have something useful to say.
          </p>
        </Reveal>
        <Reveal delay={240}>
          <a className="contact-mail" href="mailto:hello@codeobscura.com">
            hello<span style={{color: "var(--accent)"}}>@</span>codeobscura.com
            <ArrowUp/>
          </a>
        </Reveal>
      </div>
    </section>
  );
}

function Footer() {
  const year = new Date().getFullYear();
  return (
    <footer className="foot">
      <div className="foot-inner">
        <span style={{display: "inline-flex", alignItems: "center", gap: 10}}>
          <SunMoon size={18} /> CodeObscura · Made with ♥ in London
        </span>
        <span>© 2024 — {year} ObscuraCode Ltd.</span>
        <span>hello@codeobscura.com</span>
      </div>
    </footer>
  );
}

// ---------- root app ----------
function App() {
  return (
    <>
      <Nav />
      <Hero />
      <Stats />

      <Featured
        id="lifeinuk"
        badge="Featured · Education"
        name="Life in the"
        nameEm="UK"
        desc="Pass your Life in the UK Test first time with all 10 official handbook chapters, 22 timed mock tests, 1,100+ real-style questions, smart flashcards, and a searchable terms glossary. Study offline, with no ads or trackers."
        bg="css/img/bg_lifeinuk.jpg"
        icon="lifeinuk/assets/app-icon.png"
        appstore="https://apps.apple.com/us/app/life-in-the-uk-test-2026-pro/id6761489205"
        learnMore="https://codeobscura.com/lifeinuk/"
      />

      <Featured
        id="sneakerlens"
        badge="Featured · AI vision"
        name="Sneaker"
        nameEm="Lens"
        desc="Point your camera at any sneaker to instantly identify the brand, model, colourway, and current resale value. Powered by advanced AI vision — the ultimate tool for collectors, resellers, and sneakerheads."
        bg="css/img/bg_sneakerlens.jpg"
        icon="css/img/sneakerlens-icon.png"
        appstore="https://apps.apple.com/us/app/kick-identifier-sneakerlens/id6758642437"
        learnMore="https://sneakerlens.codeobscura.com/"
        reverse
      />

      <Bespoke />
      <AppsGrid />
      <Services />
      <Testimonials />
      <About />
      <Contact />
      <Footer />
    </>
  );
}

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