// DYNEX Website — Components (Editorial / Augen Pro adaptation, multi-theme)
// Babel JSX. Globally exposes components via window.

const { useState, useEffect, useRef } = React;

// ---------- Tokens ----------
const T = {
  bg1: "#f2f2f4",        // Ghost White (light)
  bg2: "#fdfdfd",        // Canvas (paper)
  bg3: "#e6e6e8",        // Soft gray break
  bgInk: "#0f1012",      // Dark surface
  bgInk2: "#1a1b1e",     // Dark elevated
  bgAccent: "#00D2BE",   // Primary turquoise surface
  ink: "#0f1012",
  graphite: "#020201",
  slate: "#8f8f8f",
  skyline: "#868788",
  accent: "#00D2BE",
  accentHover: "#00E8D0",
  accentDeep: "#08312D", // ink-on-turquoise
  accentSoft: "rgba(0,210,190,0.08)",
  borderSubtle: "rgba(15,16,18,0.08)",
  borderFaint: "rgba(15,16,18,0.04)",
  borderOnDark: "rgba(255,255,255,0.10)",
  borderOnDarkStrong: "rgba(255,255,255,0.18)",
  borderOnAccent: "rgba(8,49,45,0.14)",
  borderOnAccentStrong: "rgba(8,49,45,0.30)",
  fontDisplay: "'Syne', sans-serif",
  fontBody: "'Instrument Sans', sans-serif",
  fontStat: "'Plus Jakarta Sans', sans-serif",
  fontEyebrow: "'Urbanist', sans-serif",
  ease: "cubic-bezier(0.4,0,0.2,1)",
};

// Theme palette per surface — { fg1, fg2, fg3, accent, border, borderStrong, eyebrow }
const themes = {
  light: { bg: T.bg1, fg1: T.ink, fg2: T.slate, fg3: T.skyline, accent: T.accent, border: T.borderSubtle, borderStrong: T.ink, eyebrowDim: T.skyline },
  paper: { bg: T.bg2, fg1: T.ink, fg2: T.slate, fg3: T.skyline, accent: T.accent, border: T.borderSubtle, borderStrong: T.ink, eyebrowDim: T.skyline },
  gray:  { bg: T.bg3, fg1: T.ink, fg2: "#5b5c5e", fg3: "#727377", accent: T.accent, border: "rgba(15,16,18,0.10)", borderStrong: T.ink, eyebrowDim: "#727377" },
  dark:  { bg: T.bgInk, fg1: "#fafafa", fg2: "rgba(250,250,250,0.62)", fg3: "rgba(250,250,250,0.42)", accent: T.accent, border: T.borderOnDark, borderStrong: "#fafafa", eyebrowDim: "rgba(250,250,250,0.45)" },
  primary:{ bg: T.bgAccent, fg1: T.accentDeep, fg2: "rgba(8,49,45,0.72)", fg3: "rgba(8,49,45,0.55)", accent: T.accentDeep, border: T.borderOnAccent, borderStrong: T.accentDeep, eyebrowDim: "rgba(8,49,45,0.55)" },
};

// Reusable wordmark: "dynex" with a gradient that goes ink → primary → ink.
// One simple span — no stacking, no transitions on the gradient (gradients
// don't interpolate, so a transition would tear). Mode swaps the gradient
// instantly; the change is invisible to the user because it happens during
// scroll between sections.
function Wordmark({ size = 19, mode = "light", weight = 700 }) {
  const accent = T.accent;
  const accentDeep = T.accentDeep;
  const lightInk = T.ink;
  const darkInk = "#fafafa";

  // "dynex" → 5 chars, ~20% per char. Gradient transitions from base ink to
  // primary, starting at the middle of the "e" (50% of the wordmark width)
  // and reaching full primary at the end of the "x" (100%).
  let gradient;
  if (mode === "dark") {
    gradient = `linear-gradient(95deg, ${darkInk} 0%, ${darkInk} 50%, ${accent} 100%)`;
  } else if (mode === "primary") {
    gradient = `linear-gradient(95deg, ${accentDeep} 0%, ${accentDeep} 50%, ${darkInk} 100%)`;
  } else {
    gradient = `linear-gradient(95deg, ${lightInk} 0%, ${lightInk} 50%, ${accent} 100%)`;
  }

  return (
    <span style={{
      fontFamily: T.fontDisplay,
      fontSize: size,
      fontWeight: weight,
      letterSpacing: "-0.03em",
      lineHeight: 1,
      display: "inline-block",
      backgroundImage: gradient,
      WebkitBackgroundClip: "text",
      backgroundClip: "text",
      WebkitTextFillColor: "transparent",
      color: "transparent",
    }}>dynex</span>
  );
}

// ---------- Hooks ----------
function useScrollReveal(threshold = 0.15) {
  const ref = useRef(null);
  const [visible, setVisible] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setVisible(true); obs.disconnect(); }
    }, { threshold });
    obs.observe(el);
    return () => obs.disconnect();
  }, [threshold]);
  return [ref, visible];
}

// ---------- Icons ----------
const I = {
  Arrow: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
  ),
  ArrowUR: ({ size = 12 }) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><line x1="7" y1="17" x2="17" y2="7"/><polyline points="7 7 17 7 17 17"/></svg>
  ),
  Terminal: ({ size = 20 }) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>
  ),
  Globe: ({ size = 20 }) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
  ),
  Cart: ({ size = 20 }) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.7 13.4a2 2 0 0 0 2 1.6h9.7a2 2 0 0 0 2-1.6L23 6H6"/></svg>
  ),
  WhatsApp: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/></svg>
  ),
  Instagram: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1112.63 8 4 4 0 0116 11.37z"/><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"/></svg>
  ),
};

// ---------- Pill ----------
function Pill({ children, href, accent, dark, light, theme = "light", small }) {
  const [h, setH] = useState(false);
  const th = themes[theme];
  let style = {
    display: "inline-flex", alignItems: "center", gap: 6,
    fontFamily: T.fontBody, fontWeight: 500, fontSize: small ? 12.5 : 13.5,
    letterSpacing: "-0.01em",
    padding: small ? "6px 14px" : "8px 16px",
    borderRadius: 999, textDecoration: "none", cursor: "pointer",
    transition: `all 0.3s ${T.ease}`,
    border: "1px solid " + th.border,
    background: h ? (theme === "dark" ? "rgba(255,255,255,0.06)" : theme === "primary" ? "rgba(8,49,45,0.06)" : "rgba(15,16,18,0.04)") : "transparent",
    color: th.fg1,
    whiteSpace: "nowrap",
  };
  if (accent) {
    style.background = h ? T.accentHover : T.accent;
    style.color = T.accentDeep;
    style.border = "1px solid transparent";
    style.fontWeight = 600;
  }
  if (dark) {
    style.background = T.ink;
    style.color = "#fafafa";
    style.border = "1px solid " + T.ink;
  }
  if (light) {
    style.background = h ? "#fff" : T.bg2;
    style.color = T.ink;
    style.border = "1px solid " + T.borderSubtle;
  }
  return (
    <a href={href || "#"} onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)} style={style}>{children}</a>
  );
}

// ---------- Eyebrow ----------
function Eyebrow({ children, color, mb = 14 }) {
  return (
    <div style={{ fontFamily: T.fontEyebrow, fontWeight: 700, fontSize: 11,
      letterSpacing: "0.12em", textTransform: "uppercase", color: color || T.accent, marginBottom: mb }}>{children}</div>
  );
}

// ---------- Navbar ----------
function Navbar({ revealDelay = 0 } = {}) {
  const [scrolled, setScrolled] = useState(false);
  const [section, setSection] = useState("light");
  const [revealed, setRevealed] = useState(false);
  useEffect(() => {
    // Navbar reveals immediately on mount with the same fade-up effect as the
    // hero subtitle — no waiting for the typewriter.
    const t = setTimeout(() => setRevealed(true), 80);
    return () => clearTimeout(t);
  }, []);
  useEffect(() => {
    // Determine which section is currently under the navbar by checking which
    // [data-theme] element's top has crossed the header line (~120px from top).
    // This avoids the observer-based approach where the "active" section can
    // momentarily flip back to a previous one when intersection ratios overlap.
    const HEADER_LINE = 120;
    const updateSection = () => {
      setScrolled(window.scrollY > 60);
      const sections = document.querySelectorAll("[data-theme]");
      let activeTheme = "light";
      sections.forEach(s => {
        const rect = s.getBoundingClientRect();
        if (rect.top <= HEADER_LINE && rect.bottom > HEADER_LINE) {
          activeTheme = s.dataset.theme;
        }
      });
      setSection(prev => prev === activeTheme ? prev : activeTheme);
    };
    updateSection();
    window.addEventListener("scroll", updateSection, { passive: true });
    window.addEventListener("resize", updateSection);
    return () => {
      window.removeEventListener("scroll", updateSection);
      window.removeEventListener("resize", updateSection);
    };
  }, []);

  const onDark = section === "dark";
  const onAccent = section === "primary";
  const navFg = onDark ? "#fafafa" : onAccent ? T.accentDeep : T.ink;
  const navFgDim = onDark ? "rgba(250,250,250,0.55)" : onAccent ? "rgba(8,49,45,0.62)" : T.slate;
  // Glass: same translucent surface across all themes; only fg colors invert.
  const navBg = "rgba(242,242,244,0.10)";
  const navBorder = "transparent";

  const links = [
    { label: "Servicios", href: "#servicios" },
    { label: "Portfolio", href: "#portfolio" },
    { label: "Nosotros", href: "#nosotros" },
    { label: "Contacto", href: "#contacto" },
  ];
  return (
    <nav style={{
      position: "fixed", top: 0, left: 0, right: 0, zIndex: 100, padding: "18px 0",
      background: navBg,
      backdropFilter: "blur(22px) saturate(160%)",
      WebkitBackdropFilter: "blur(22px) saturate(160%)",
      borderBottom: "1px solid " + navBorder,
      transition: `background 0.5s ${T.ease}, border-color 0.5s ${T.ease}`,
    }}>
      <div style={{ width: "100%", padding: "0 32px",
        display: "flex", alignItems: "center", justifyContent: "space-between", gap: 24,
        transition: `opacity 1.0s ${T.ease} 0.15s, transform 1.0s ${T.ease} 0.15s`,
        opacity: revealed ? 1 : 0,
        transform: revealed ? "translateY(0)" : "translateY(12px)",
      }}>
        <a href="#" style={{ textDecoration: "none", display: "inline-flex", alignItems: "center" }}>
          <Wordmark size={20} mode={onDark ? "dark" : onAccent ? "primary" : "light"}/>
        </a>
        <div className="nav-links" style={{ display: "flex", gap: 6, alignItems: "center" }}>
          {links.map(l => <NavLink key={l.label} {...l} fg={navFg} fgDim={navFgDim} onDark={onDark} onAccent={onAccent} />)}
        </div>
        {onDark ? (
          <a href="#contacto" style={{
            display: "inline-flex", alignItems: "center", gap: 6,
            fontFamily: T.fontBody, fontWeight: 600, fontSize: 12.5, letterSpacing: "-0.01em",
            padding: "6px 14px", borderRadius: 999, textDecoration: "none",
            background: "#fafafa", color: T.ink, border: "1px solid #fafafa",
            transition: `all 0.4s ${T.ease}`,
          }}>Conversemos <I.Arrow size={12}/></a>
        ) : onAccent ? (
          <a href="#contacto" style={{
            display: "inline-flex", alignItems: "center", gap: 6,
            fontFamily: T.fontBody, fontWeight: 600, fontSize: 12.5, letterSpacing: "-0.01em",
            padding: "6px 14px", borderRadius: 999, textDecoration: "none",
            background: T.accentDeep, color: T.accent, border: "1px solid " + T.accentDeep,
            transition: `all 0.4s ${T.ease}`,
          }}>Conversemos <I.Arrow size={12}/></a>
        ) : (
          <Pill accent small href="#contacto">Conversemos <I.Arrow size={12}/></Pill>
        )}
      </div>
    </nav>
  );
}

function NavLink({ label, href, fg, fgDim, onDark, onAccent }) {
  const [hover, setHover] = useState(false);
  const hoverBg = onDark ? "rgba(255,255,255,0.06)" : onAccent ? "rgba(8,49,45,0.08)" : "rgba(15,16,18,0.03)";
  const hoverBorder = onDark ? T.borderOnDark : onAccent ? T.borderOnAccent : T.borderSubtle;
  return (
    <a href={href} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
       style={{
         fontFamily: T.fontBody, fontSize: 13, fontWeight: 500, letterSpacing: "-0.01em",
         color: hover ? fg : fgDim,
         padding: "6px 14px", borderRadius: 999,
         border: "1px solid " + (hover ? hoverBorder : "transparent"),
         background: hover ? hoverBg : "transparent",
         textDecoration: "none",
         transition: `all 0.3s ${T.ease}`,
       }}>{label}</a>
  );
}

// ---------- Hero (light) ----------
function Hero() {
  const fullTitle = "Transformamos ideas en software.";
  const splitAt = "Transformamos ideas".length; // before space, where line break goes
  const [typed, setTyped] = useState(0);
  const [revealed, setRevealed] = useState(false);
  useEffect(() => {
    // Typewriter
    const start = setTimeout(() => {
      let i = 0;
      const tick = () => {
        i += 1;
        setTyped(i);
        if (i < fullTitle.length) {
          // mild rhythm jitter
          const ch = fullTitle[i - 1];
          const delay = ch === " " ? 70 : ch === "." ? 220 : 38 + Math.round(Math.random() * 28);
          setTimeout(tick, delay);
        } else {
          setTimeout(() => {
            setRevealed(true);
            window.__heroRevealed = true;
            window.dispatchEvent(new CustomEvent("hero-revealed"));
          }, 240);
        }
      };
      tick();
    }, 600);
    return () => clearTimeout(start);
  }, []);

  const beforeBreak = fullTitle.slice(0, Math.min(typed, splitAt));
  const afterBreak = typed > splitAt ? fullTitle.slice(splitAt + 1, typed) : "";
  const showBreak = typed > splitAt;
  const accentStart = "Transformamos ideas en ".length;
  const renderAfter = () => {
    if (!showBreak) return null;
    if (typed <= accentStart) {
      return <span>{afterBreak}</span>;
    }
    const black = fullTitle.slice(splitAt + 1, accentStart);
    const acc = fullTitle.slice(accentStart, typed);
    return <><span>{black}</span><span style={{ color: T.accent }}>{acc}</span></>;
  };
  const finishedTyping = typed >= fullTitle.length;

  return (
    <section data-theme="light" style={{
      position: "relative", width: "100%", minHeight: "100vh",
      background: T.bg1, overflow: "hidden",
    }}>
      <div className="hero-visual-wrap" style={{
        position: "absolute", inset: 0,
        display: "flex", alignItems: "center", justifyContent: "center",
        padding: "120px 32px 220px",
        opacity: 1,
        perspective: "1400px",
      }}>
        <div style={{ width: "100%", maxWidth: 1100, aspectRatio: "1040 / 600", position: "relative",
          transformStyle: "preserve-3d",
        }}>
          <HeroVisual/>
        </div>
      </div>

      <div style={{
        position: "absolute", top: 96, right: 32,
        display: "flex", alignItems: "center", gap: 10,
        fontFamily: T.fontEyebrow, fontWeight: 700, fontSize: 10.5,
        letterSpacing: "0.18em", textTransform: "uppercase", color: T.skyline,
        opacity: revealed ? 1 : 0,
        transform: revealed ? "translateY(0)" : "translateY(-6px)",
        transition: `all 0.9s ${T.ease}`,
      }}>
        <span style={{ width: 24, height: 1, background: T.skyline, display: "inline-block" }}/>
        <span>Estudio · Chile</span>
      </div>

      <div className="hero-copy" style={{
        position: "absolute", bottom: 64, left: 32, maxWidth: 560,
      }}>
        <div style={{
          marginBottom: 18,
          opacity: revealed ? 1 : 0,
          transform: revealed ? "translateY(0)" : "translateY(10px)",
          transition: `all 0.9s ${T.ease} 0.05s`,
        }}>
          <Wordmark size={15} weight={700} mode="light"/>
        </div>

        <h1 style={{
          margin: 0,
          fontFamily: T.fontDisplay, fontWeight: 400,
          fontSize: "clamp(26px, 3.2vw, 38px)",
          lineHeight: 1.18, letterSpacing: "-0.02em", color: T.ink,
          minHeight: "2.36em",
        }}>
          <span>{beforeBreak}</span>
          {showBreak && <br/>}
          {renderAfter()}
          <span aria-hidden="true" style={{
            display: "inline-block", width: 2, height: "0.95em",
            background: T.ink, marginLeft: 3, verticalAlign: "-0.12em",
            opacity: finishedTyping ? 0 : 1,
            animation: "hero-caret 1s steps(2) infinite",
            transition: "opacity 0.4s ease",
          }}/>
        </h1>

        <p style={{
          margin: "20px 0 0",
          fontFamily: T.fontBody, fontSize: 13.5, fontWeight: 400,
          lineHeight: 1.65, letterSpacing: "-0.01em", color: T.slate,
          maxWidth: 380,
          opacity: revealed ? 1 : 0,
          transform: revealed ? "translateY(0)" : "translateY(12px)",
          transition: `all 1.0s ${T.ease} 0.15s`,
        }}>
          Estudio de software y tecnología.<br/>
          Construimos productos digitales a medida — desde la idea hasta producción.
        </p>

        <div style={{ display: "flex", gap: 8, marginTop: 28, flexWrap: "wrap", alignItems: "center",
          opacity: revealed ? 1 : 0,
          transform: revealed ? "translateY(0)" : "translateY(12px)",
          transition: `all 1.0s ${T.ease} 0.28s`,
        }}>
          <Pill href="#servicios">Software</Pill>
          <span style={{ color: T.skyline, fontSize: 12 }}>·</span>
          <Pill href="#servicios">Sitios web</Pill>
          <span style={{ color: T.skyline, fontSize: 12 }}>·</span>
          <Pill href="#servicios">E-commerce</Pill>
        </div>
      </div>

      <div className="hero-chapter" style={{
        position: "absolute", bottom: 64, right: 32,
        textAlign: "right",
        opacity: revealed ? 1 : 0,
        transform: revealed ? "translateY(0)" : "translateY(10px)",
        transition: `all 1.0s ${T.ease} 0.35s`,
      }}>
        <div style={{
          fontFamily: T.fontEyebrow, fontWeight: 700, fontSize: 10.5,
          letterSpacing: "0.18em", textTransform: "uppercase", color: T.skyline,
          marginBottom: 8,
        }}>—  Cap.  01 / 06</div>
        <div style={{ fontFamily: T.fontBody, fontSize: 12, color: T.slate, letterSpacing: "-0.01em" }}>
          Tu próximo paso digital
        </div>
      </div>
    </section>
  );
}

// ---------- Editorial section header (theme-aware) ----------
function SectionHeader({ index, eyebrow, title, lede, theme = "light" }) {
  const th = themes[theme];
  const [ref, visible] = useScrollReveal();
  return (
    <div ref={ref} style={{
      marginBottom: 80, maxWidth: 880,
      opacity: visible ? 1 : 0, transform: visible ? "translateY(0)" : "translateY(20px)",
      transition: `all 0.7s ${T.ease}`,
    }}>
      <div style={{
        display: "flex", alignItems: "center", gap: 14, marginBottom: 28,
        fontFamily: T.fontEyebrow, fontWeight: 700, fontSize: 11,
        letterSpacing: "0.18em", textTransform: "uppercase",
      }}>
        <span style={{ color: th.accent }}>{index}</span>
        <span style={{ width: 24, height: 1, background: th.border }}/>
        <span style={{ color: th.eyebrowDim }}>{eyebrow}</span>
      </div>
      <h2 style={{
        margin: 0, fontFamily: T.fontDisplay, fontWeight: 400,
        fontSize: "clamp(36px, 5vw, 64px)", lineHeight: 1.06,
        letterSpacing: "-0.04em", color: th.fg1,
      }}>{title}</h2>
      {lede && (
        <p style={{
          margin: "22px 0 0", fontFamily: T.fontBody, fontSize: 16, fontWeight: 400,
          lineHeight: 1.6, letterSpacing: "-0.01em", color: th.fg2,
          maxWidth: 620,
        }}>{lede}</p>
      )}
    </div>
  );
}

// ---------- Services (paper / canvas) ----------
function ServiceRow({ num, icon, title, body, tags, delay, theme }) {
  const th = themes[theme];
  const [ref, visible] = useScrollReveal();
  const [hover, setHover] = useState(false);
  return (
    <div ref={ref} className="service-row"
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{
        display: "grid", gridTemplateColumns: "60px 1fr 2fr 1fr",
        gap: 32, alignItems: "start",
        padding: "36px 0",
        borderTop: "1px solid " + th.border,
        opacity: visible ? 1 : 0,
        transform: visible ? "translateY(0)" : "translateY(14px)",
        transition: `all 0.6s ${T.ease}`, transitionDelay: `${delay}ms`,
      }}>
      <div className="service-num" style={{ fontFamily: T.fontEyebrow, fontWeight: 700, fontSize: 11, letterSpacing: "0.18em", color: th.fg3 }}>{num}</div>
      <div style={{ display: "flex", alignItems: "flex-start", gap: 14 }}>
        <span style={{ color: hover ? th.accent : th.fg1, transition: `color 0.3s ${T.ease}`, marginTop: 2 }}>{icon}</span>
        <h3 style={{ margin: 0, fontFamily: T.fontDisplay, fontSize: 22, fontWeight: 400, color: th.fg1, letterSpacing: "-0.03em", lineHeight: 1.2 }}>{title}</h3>
      </div>
      <p style={{ margin: 0, fontFamily: T.fontBody, fontSize: 14, fontWeight: 400, color: th.fg2, lineHeight: 1.7, letterSpacing: "-0.01em", maxWidth: 460 }}>{body}</p>
      <div className="service-tags" style={{ display: "flex", flexWrap: "wrap", gap: 6, justifyContent: "flex-end" }}>
        {tags.map(t => (
          <span key={t} style={{
            fontFamily: T.fontBody, fontSize: 11.5, color: th.fg2,
            padding: "4px 10px", border: "1px solid " + th.border, borderRadius: 999,
            letterSpacing: "-0.01em",
          }}>{t}</span>
        ))}
      </div>
    </div>
  );
}

function Services() {
  const theme = "paper";
  const th = themes[theme];
  const items = [
    { num: "S/01", icon: <I.Terminal/>, title: "Software a medida",
      body: "Sistemas y aplicaciones web diseñadas para tu operación. Sistemas de gestión, plataformas internas, automatización de procesos — construidas para durar y crecer con tu negocio.",
      tags: ["Laravel", "Vue 3", "React", "PostgreSQL"] },
    { num: "S/02", icon: <I.Globe/>, title: "Sitios web",
      body: "Tu negocio visible las 24 horas, los 7 días de la semana. Sitios rápidos, responsivos y optimizados para que tus clientes te encuentren y confíen en ti.",
      tags: ["Landing", "Corporativo", "SEO"] },
    { num: "S/03", icon: <I.Cart/>, title: "Tiendas online",
      body: "Vende en internet 24/7, con una tienda profesional. Catálogo, carrito de compras, pagos integrados y gestión de pedidos.",
      tags: ["E-commerce", "Pagos", "Catálogo", "Transacciones"] },
  ];
  return (
    <section id="servicios" data-theme={theme} style={{ background: th.bg, padding: "120px 32px 140px" }}>
      <div style={{ maxWidth: 1320, margin: "0 auto" }}>
        <SectionHeader theme={theme} index="01" eyebrow="Servicios" title={<>¿Qué hacemos?</>}
          lede="Software, sitios web y tiendas online para tu negocio. Un solo equipo, de principio a fin."/>
        <div style={{ borderBottom: "1px solid " + th.border }}>
          {items.map((s, i) => <ServiceRow key={s.num} {...s} theme={theme} delay={i * 80}/>)}
        </div>
        <p style={{
          marginTop: 48, fontFamily: T.fontBody, fontSize: 13.5,
          color: th.fg2, lineHeight: 1.75, letterSpacing: "-0.01em", maxWidth: 640,
        }}>
          <span style={{ color: th.fg1 }}>También construimos productos propios.</span>{" "}
          NuFood y FinanzasApp son plataformas SaaS desarrolladas internamente — la misma tecnología y los mismos estándares que aplicamos a los proyectos de nuestros clientes.
        </p>
      </div>
    </section>
  );
}

// ---------- HowWeWork (DARK) ----------
function HowWeWork() {
  const theme = "dark";
  const th = themes[theme];
  const [ref, visible] = useScrollReveal();
  const steps = [
    { num: "01", title: "Conversamos", body: "Entendemos tu negocio, tus problemas y tus objetivos. Sin jerga, sin compromiso." },
    { num: "02", title: "Proponemos", body: "Te presentamos una solución clara con alcance, plazo y precio definidos. Sin sorpresas." },
    { num: "03", title: "Construimos", body: "Desarrollamos tu solución con entregas parciales. Ves avance real cada semana." },
    { num: "04", title: "Entregamos", body: "Implementación, capacitación y soporte. No desaparecemos después de entregar." },
  ];
  return (
    <section id="como" data-theme={theme} style={{
      background: th.bg, padding: "140px 32px 160px",
      position: "relative", overflow: "hidden",
    }}>
      {/* Subtle dotted grid bg */}
      <div aria-hidden style={{
        position: "absolute", inset: 0, pointerEvents: "none",
        backgroundImage: "radial-gradient(rgba(255,255,255,0.05) 1px, transparent 1px)",
        backgroundSize: "32px 32px",
        maskImage: "radial-gradient(ellipse at center, black 30%, transparent 80%)",
        WebkitMaskImage: "radial-gradient(ellipse at center, black 30%, transparent 80%)",
      }}/>
      <div style={{ maxWidth: 1320, margin: "0 auto", position: "relative" }}>
        <SectionHeader theme={theme} index="02" eyebrow="Proceso" title={<>¿Cómo trabajamos?</>}
          lede="Proceso claro, comunicación directa y un equipo que se involucra."/>
        <div ref={ref} className="how-grid" style={{
          display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 40,
        }}>
          {steps.map((s, i) => (
            <div key={s.num} style={{
              borderTop: "1px solid " + th.fg1, paddingTop: 22,
              opacity: visible ? 1 : 0,
              transform: visible ? "translateY(0)" : "translateY(14px)",
              transition: `all 0.6s ${T.ease}`, transitionDelay: `${i * 100}ms`,
            }}>
              <div style={{ fontFamily: T.fontStat, fontWeight: 800, fontSize: 14, color: th.accent, marginBottom: 18 }}>{s.num}</div>
              <h3 style={{ margin: "0 0 10px", fontFamily: T.fontDisplay, fontWeight: 400, fontSize: 22, color: th.fg1, letterSpacing: "-0.03em" }}>{s.title}</h3>
              <p style={{ margin: 0, fontFamily: T.fontBody, fontSize: 13.5, color: th.fg2, lineHeight: 1.7, letterSpacing: "-0.01em" }}>{s.body}</p>
            </div>
          ))}
        </div>
        <div style={{
          marginTop: 80, paddingTop: 28, borderTop: "1px solid " + th.border,
          display: "flex", justifyContent: "space-between", flexWrap: "wrap", gap: 16,
          fontFamily: T.fontBody, fontSize: 12, color: th.fg2, letterSpacing: "-0.01em",
        }}>
          <span style={{ color: th.fg3, textTransform: "uppercase", letterSpacing: "0.16em", fontSize: 10.5 }}>
            Stack tecnológico
          </span>
          <span>Laravel · Vue 3 · TypeScript · PostgreSQL · React · Tailwind CSS</span>
        </div>
      </div>
    </section>
  );
}

// ---------- Portfolio (light) ----------
function PortfolioItem({ num, badge, title, body, meta, accent, delay, theme, href }) {
  const th = themes[theme];
  const [ref, visible] = useScrollReveal();
  const [hover, setHover] = useState(false);
  const isLink = !!href;
  return (
    <a ref={ref} href={href || "#"}
       target={isLink ? "_blank" : undefined}
       rel={isLink ? "noopener noreferrer" : undefined}
       onClick={isLink ? undefined : (e) => e.preventDefault()}
       onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
       style={{
         display: "block", textDecoration: "none",
         padding: "30px 0",
         borderTop: "1px solid " + th.border,
         opacity: visible ? 1 : 0,
         transform: visible ? "translateY(0)" : "translateY(14px)",
         transition: `all 0.6s ${T.ease}`, transitionDelay: `${delay}ms`,
         cursor: isLink ? "pointer" : "default",
       }}>
      <div className="port-row" style={{ display: "grid", gridTemplateColumns: "60px 1fr 2.2fr 1fr 24px", gap: 32, alignItems: "center" }}>
        <span className="port-num" style={{ fontFamily: T.fontEyebrow, fontWeight: 700, fontSize: 11, letterSpacing: "0.18em", color: th.fg3 }}>{num}</span>
        <span style={{ fontFamily: T.fontEyebrow, fontWeight: 700, fontSize: 11, letterSpacing: "0.14em", color: accent ? th.accent : th.fg3, textTransform: "uppercase" }}>{badge}</span>
        <h3 style={{
          margin: 0, fontFamily: T.fontDisplay, fontSize: 32, fontWeight: 400,
          color: hover ? th.accent : th.fg1, letterSpacing: "-0.03em", lineHeight: 1.1,
          transition: `color 0.3s ${T.ease}`,
        }}>{title}</h3>
        <span style={{ fontFamily: T.fontBody, fontSize: 13, color: th.fg2, letterSpacing: "-0.01em" }}>{meta}</span>
        <span style={{
          color: hover ? th.accent : th.fg1,
          transform: hover ? "translate(2px,-2px)" : "translate(0,0)",
          transition: `all 0.3s ${T.ease}`,
        }}><I.ArrowUR size={18}/></span>
      </div>
      <p className="port-body" style={{
        margin: "12px 0 0", paddingLeft: 92,
        fontFamily: T.fontBody, fontSize: 13.5, color: th.fg2,
        lineHeight: 1.7, letterSpacing: "-0.01em", maxWidth: 720,
      }}>{body}</p>
    </a>
  );
}

function Portfolio() {
  const theme = "light";
  const th = themes[theme];
  const items = [
    { num: "P/01", badge: "Producto SaaS", title: "NuFood", meta: "POS gastronómico · 2025", accent: true, href: null,
      body: "Inventario, ventas, compras y métricas en una sola plataforma para negocios gastronómicos." },
    { num: "P/02", badge: "Aplicación web", title: "FinanzasApp", meta: "Finanzas personales · 2024", href: "https://www.finanzasapp.cl/",
      body: "App de gestión financiera personal con seguimiento de gastos, presupuestos y metas de ahorro. Datos en tiempo real." },
    { num: "P/03", badge: "Sitio web", title: "Buenos Humos", meta: "Catering · 2026", href: null,
      body: "Sitio web para empresa de gastronómica de eventos — catering de asados y parrillas premium. Buenos Humos." },
  ];
  return (
    <section id="portfolio" data-theme={theme} style={{ background: th.bg, padding: "140px 32px 160px" }}>
      <div style={{ maxWidth: 1320, margin: "0 auto" }}>
        <SectionHeader theme={theme} index="03" eyebrow="Portfolio" title={<>Trabajo seleccionado.</>}
          lede="Productos propios y proyectos para clientes — todos en producción."/>
        <div style={{ borderBottom: "1px solid " + th.border }}>
          {items.map((p, i) => <PortfolioItem key={p.num} {...p} theme={theme} delay={i * 90}/>)}
        </div>
      </div>
    </section>
  );
}

// ---------- About (GRAY) ----------
function About() {
  const theme = "gray";
  const th = themes[theme];
  const [ref, visible] = useScrollReveal();
  const stats = [
    { value: "10+", label: "años de experiencia" },
    { value: "30+", label: "proyectos en producción" },
    { value: "02", label: "productos SaaS propios" },
  ];
  return (
    <section id="nosotros" data-theme={theme} style={{ background: th.bg, padding: "140px 32px 160px",
      borderTop: "1px solid " + th.border, borderBottom: "1px solid " + th.border }}>
      <div style={{ maxWidth: 1320, margin: "0 auto" }}>
        <SectionHeader theme={theme} index="04" eyebrow="Estudio" title={<>¿Quiénes somos?</>}
          lede="Tecnología con criterio humano — la IA potencia nuestro proceso, las decisiones siempre son humanas."/>
        <div ref={ref} className="about-grid" style={{
          display: "grid", gridTemplateColumns: "1.6fr 1fr", gap: 80, alignItems: "start",
          opacity: visible ? 1 : 0, transform: visible ? "translateY(0)" : "translateY(20px)",
          transition: `all 0.8s ${T.ease}`,
        }}>
          <div style={{ display: "flex", flexDirection: "column", gap: 22 }}>
            <p style={{ margin: 0, fontFamily: T.fontBody, fontSize: 18, fontWeight: 400,
              color: th.fg1, lineHeight: 1.65, letterSpacing: "-0.02em" }}>
              Dynex es un estudio de desarrollo de software con base en Viña del Mar, Chile. Fundado por <span style={{ color: th.fg1 }}>Alonso Ugarte</span>, ingeniero de software con más de 10 años construyendo aplicaciones web, plataformas digitales y soluciones a medida.
            </p>
            <p style={{ margin: 0, fontFamily: T.fontBody, fontSize: 14.5, fontWeight: 400,
              color: th.fg2, lineHeight: 1.75, letterSpacing: "-0.01em", maxWidth: 620 }}>
              Trabajamos directo con cada cliente, entendiendo su negocio antes de escribir una línea de código. El nombre <span style={{ color: th.fg1 }}>dynex</span> viene de <span style={{ color: th.fg1 }}>dyne</span> — la unidad de medida que Tesla usó en sus cálculos, padre de la tecnología actual — y la <span style={{ color: th.fg1 }}>x</span>, la variable a resolver de cada cliente.
            </p>
          </div>
          <div className="about-stats" style={{ display: "flex", flexDirection: "column", gap: 32 }}>
            {stats.map((s, i) => (
              <div key={s.label} className="about-stat" style={{
                paddingTop: 22, borderTop: "1px solid " + th.border,
                display: "grid", gridTemplateColumns: "1.2fr 1fr", alignItems: "baseline", gap: 12,
              }}>
                <span className="about-stat-value" style={{
                  fontFamily: T.fontStat, fontWeight: 800, fontSize: 56,
                  color: i === 0 ? th.accent : th.fg1, letterSpacing: "-0.04em", lineHeight: 1,
                }}>{s.value}</span>
                <span className="about-stat-label" style={{ fontFamily: T.fontBody, fontSize: 12.5, color: th.fg2,
                  letterSpacing: "-0.01em", lineHeight: 1.45 }}>{s.label}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

// ---------- Contact (PRIMARY / TURQUOISE) ----------
function Contact() {
  const theme = "primary";
  const th = themes[theme];
  const [ref, visible] = useScrollReveal();
  return (
    <section id="contacto" data-theme={theme} style={{
      background: th.bg, padding: "160px 32px 140px",
      position: "relative", overflow: "hidden",
    }}>
      {/* Decorative outline circles to echo the hero motif */}
      <div aria-hidden style={{
        position: "absolute", top: -200, right: -180, width: 640, height: 640,
        borderRadius: "50%", border: "1px solid rgba(8,49,45,0.18)",
      }}/>
      <div aria-hidden style={{
        position: "absolute", top: -120, right: -100, width: 480, height: 480,
        borderRadius: "50%", border: "1px solid rgba(8,49,45,0.10)",
      }}/>

      <div ref={ref} style={{
        maxWidth: 1320, margin: "0 auto", position: "relative",
        opacity: visible ? 1 : 0, transform: visible ? "translateY(0)" : "translateY(20px)",
        transition: `all 0.8s ${T.ease}`,
      }}>
        <div style={{
          display: "flex", alignItems: "center", gap: 14, marginBottom: 32,
          fontFamily: T.fontEyebrow, fontWeight: 700, fontSize: 11,
          letterSpacing: "0.18em", textTransform: "uppercase",
        }}>
          <span style={{ color: th.fg1 }}>05</span>
          <span style={{ width: 24, height: 1, background: th.borderStrong, opacity: 0.5 }}/>
          <span style={{ color: th.fg2 }}>Contacto</span>
        </div>
        <h2 style={{
          margin: 0, fontFamily: T.fontDisplay, fontWeight: 400,
          fontSize: "clamp(48px, 9vw, 140px)", lineHeight: 0.96,
          letterSpacing: "-0.05em", color: th.fg1, maxWidth: 1200,
        }}>
          ¿Conversemos?
        </h2>
        <p style={{
          margin: "32px 0 0", fontFamily: T.fontBody, fontSize: 17, fontWeight: 400,
          color: th.fg1, lineHeight: 1.55, letterSpacing: "-0.02em", maxWidth: 540,
        }}>
          Cuéntanos qué necesitas. Te respondemos en menos de 24 horas — sin formularios, sin compromiso.
        </p>

        <div className="contact-grid" style={{
          marginTop: 80, paddingTop: 36,
          borderTop: "1px solid " + th.borderStrong,
          display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 48,
        }}>
          <div>
            <Eyebrow color={th.fg2} mb={10}>WhatsApp</Eyebrow>
            <a href="https://wa.me/56964049857?text=Hola%2C%20me%20interesa%20cotizar%20un%20proyecto%20con%20Dynex." target="_blank" rel="noopener noreferrer"
              style={{ fontFamily: T.fontStat, fontSize: 26, fontWeight: 600,
                color: th.fg1, letterSpacing: "-0.02em", textDecoration: "none",
                fontVariantNumeric: "tabular-nums",
                display: "inline-flex", alignItems: "center", gap: 8 }}>
              +56 9 6404 9857
            </a>
            <p style={{ margin: "10px 0 18px", fontFamily: T.fontBody, fontSize: 13, color: th.fg2, letterSpacing: "-0.01em" }}>
              Respuesta directa, sin formularios.
            </p>
            <a href="https://wa.me/56964049857?text=Hola%2C%20me%20interesa%20cotizar%20un%20proyecto%20con%20Dynex." target="_blank" rel="noopener noreferrer" style={{
              display: "inline-flex", alignItems: "center", gap: 6,
              fontFamily: T.fontBody, fontWeight: 600, fontSize: 13, letterSpacing: "-0.01em",
              padding: "8px 16px", borderRadius: 999, textDecoration: "none",
              background: T.accentDeep, color: T.accent, border: "1px solid " + T.accentDeep,
            }}>
              <I.WhatsApp size={13}/> Escríbenos <I.Arrow size={12}/>
            </a>
          </div>
          <div>
            <Eyebrow color={th.fg2} mb={10}>Instagram</Eyebrow>
            <a href="https://instagram.com/dynex.cl" target="_blank" rel="noopener noreferrer"
              style={{ fontFamily: T.fontDisplay, fontSize: 26, fontWeight: 400,
                color: th.fg1, letterSpacing: "-0.03em", textDecoration: "none" }}>
              @dynex.cl
            </a>
            <p style={{ margin: "10px 0 18px", fontFamily: T.fontBody, fontSize: 13, color: th.fg2, letterSpacing: "-0.01em" }}>
              Trabajos recientes y detrás de escena.
            </p>
            <a href="https://instagram.com/dynex.cl" target="_blank" rel="noopener noreferrer" style={{
              display: "inline-flex", alignItems: "center", gap: 6,
              fontFamily: T.fontBody, fontWeight: 600, fontSize: 13, letterSpacing: "-0.01em",
              padding: "8px 16px", borderRadius: 999, textDecoration: "none",
              background: "transparent", color: T.accentDeep, border: "1px solid " + T.accentDeep,
            }}>
              <I.Instagram size={13}/> Síguenos <I.Arrow size={12}/>
            </a>
          </div>
          <div>
            <Eyebrow color={th.fg2} mb={10}>Estudio</Eyebrow>
            <div style={{ fontFamily: T.fontDisplay, fontSize: 26, fontWeight: 400,
              color: th.fg1, letterSpacing: "-0.03em" }}>
              Viña del Mar, Chile
            </div>
            <p style={{ margin: "10px 0 0", fontFamily: T.fontBody, fontSize: 13, color: th.fg2, letterSpacing: "-0.01em" }}>
              Lun – Vie · 09:00 – 18:00 (CLT)<br/>
              dynex.cl
            </p>
          </div>
        </div>
      </div>
    </section>
  );
}

// ---------- Footer (DARK) ----------
function Footer() {
  const theme = "dark";
  const th = themes[theme];
  const [hovered, setHovered] = useState(null);
  const nav = [
    { label: "Servicios", href: "#servicios" },
    { label: "Portfolio", href: "#portfolio" },
    { label: "Nosotros", href: "#nosotros" },
    { label: "Contacto", href: "#contacto" },
  ];
  const social = [
    { label: "Instagram", href: "https://instagram.com/dynex.cl" },
    { label: "WhatsApp", href: "https://wa.me/56964049857?text=Hola%2C%20me%20interesa%20cotizar%20un%20proyecto%20con%20Dynex." },
  ];
  return (
    <footer data-theme={theme} style={{ background: th.bg, padding: "0 32px 28px" }}>
      <div style={{ maxWidth: 1320, margin: "0 auto", paddingTop: 64 }}>
        <div style={{
          margin: "0 0 64px",
          display: "flex", alignItems: "flex-end", gap: 12,
          lineHeight: 0.9,
        }}>
          <Wordmark size={"clamp(96px, 18vw, 240px)"} weight={700} mode="dark"/>
        </div>

        <div className="footer-grid" style={{
          display: "grid", gridTemplateColumns: "2fr 1fr 1fr", gap: 44,
          paddingTop: 28, borderTop: "1px solid " + th.border,
        }}>
          <div>
            <p style={{ margin: 0, fontFamily: T.fontBody, fontSize: 13.5, color: th.fg2,
              lineHeight: 1.7, letterSpacing: "-0.01em", maxWidth: 380 }}>
              También construimos productos propios. NuFood y FinanzasApp son plataformas SaaS desarrolladas internamente — la misma tecnología y los mismos estándares que aplicamos a los proyectos de nuestros clientes.
            </p>
            <p style={{ margin: "14px 0 0", fontFamily: T.fontBody, fontSize: 12.5, color: th.fg3, letterSpacing: "-0.01em" }}>
              Viña del Mar, Chile · dynex.cl
            </p>
          </div>
          <div>
            <Eyebrow color={th.fg3} mb={12}>Navegación</Eyebrow>
            <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
              {nav.map(l => (
                <a key={l.label} href={l.href}
                   onMouseEnter={() => setHovered(l.label)} onMouseLeave={() => setHovered(null)}
                   style={{ fontFamily: T.fontBody, fontSize: 13,
                     color: hovered === l.label ? th.accent : th.fg1,
                     textDecoration: "none", letterSpacing: "-0.01em",
                     transition: `color 0.2s ${T.ease}` }}>{l.label}</a>
              ))}
            </div>
          </div>
          <div>
            <Eyebrow color={th.fg3} mb={12}>Conecta</Eyebrow>
            <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
              {social.map(l => (
                <a key={l.label} href={l.href} target="_blank" rel="noopener noreferrer"
                   onMouseEnter={() => setHovered(l.label)} onMouseLeave={() => setHovered(null)}
                   style={{ fontFamily: T.fontBody, fontSize: 13,
                     color: hovered === l.label ? th.accent : th.fg1, letterSpacing: "-0.01em",
                     textDecoration: "none", transition: `color 0.2s ${T.ease}`,
                     display: "inline-flex", alignItems: "center", gap: 4 }}>
                  {l.label} <I.ArrowUR size={10}/>
                </a>
              ))}
            </div>
          </div>
        </div>

        <div style={{
          marginTop: 56, paddingTop: 20, borderTop: "1px solid " + th.border,
          display: "flex", justifyContent: "space-between", flexWrap: "wrap", gap: 8,
          fontFamily: T.fontBody, fontSize: 11.5, color: th.fg3, letterSpacing: "-0.01em",
        }}>
          <span>© 2026 dynex. Todos los derechos reservados.</span>
          <span>Hecho con <span style={{ color: th.accent }}>☕</span> en Viña del Mar, Chile</span>
        </div>
      </div>
    </footer>
  );
}

Object.assign(window, { Navbar, Hero, Services, HowWeWork, Portfolio, About, Contact, Footer, Pill, Eyebrow, I });
