/* YALTA.CL — main app */
const { useState, useEffect, useRef, useMemo, Fragment } = React;

const LEY_DATE = new Date('2026-12-01T00:00:00-03:00');

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "paper",
  "logo": "serif",
  "cursor": "ring",
  "showCoords": true,
  "accentColor": "#8A3324",
  "antiCopy": true
}/*EDITMODE-END*/;

/* ========== LOGO ========== */
function Logo({ variant = 'serif', size = 26 }) {
  const cls = variant === 'sans' ? 'logo logo-sans' : variant === 'mono' ? 'logo logo-mono' : 'logo';
  return (
    <a href="#top" className={cls} aria-label="YALTA — inicio">
      <span className="logo-mark" style={{ fontSize: size }}>YALTA</span>
      <span className="logo-tag">LEX · TECH · ANTOFAGASTA</span>
    </a>
  );
}

/* ========== COUNTDOWN ========== */
function useCountdown(target) {
  const [now, setNow] = useState(() => new Date());
  useEffect(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const diff = Math.max(0, target - now);
  const days = Math.floor(diff / (1000 * 60 * 60 * 24));
  const hours = Math.floor((diff / (1000 * 60 * 60)) % 24);
  const minutes = Math.floor((diff / (1000 * 60)) % 60);
  const seconds = Math.floor((diff / 1000) % 60);
  return { days, hours, minutes, seconds };
}

function Countdown() {
  const { days, hours, minutes, seconds } = useCountdown(LEY_DATE);
  const totalHours = days * 24 + hours;
  return (
    <div className="countdown-bar">
      <div className="countdown-label">
        // CUENTA REGRESIVA
        <strong>Ley 21.719 entra en vigencia</strong>
        <span style={{ color: 'var(--ink-soft)' }}>1 dic 2026 · 00:00 CLT</span>
      </div>
      <Cell num={days} unit="días" />
      <Cell num={String(hours).padStart(2,'0')} unit="horas" />
      <Cell num={String(minutes).padStart(2,'0')} unit="minutos" />
      <Cell num={String(seconds).padStart(2,'0')} unit="segundos" />
    </div>
  );
}
function Cell({ num, unit }) {
  return (
    <div className="countdown-cell">
      <div className="countdown-num">{num}</div>
      <div className="countdown-unit">{unit}</div>
    </div>
  );
}

/* ========== HERO ========== */
function Hero() {
  return (
    <section id="top" className="hero container">
      <div className="hero-meta">
        <span>ANTOFAGASTA</span><span>23°39′S 70°23′W</span><span>EST. 2007</span>
        <span>13+ años en TI/OT</span><span>Habilitado de Derecho · Ley 18.120</span>
      </div>
      <h1 className="hero-title serif">
        Estrategia TI/OT <em>&amp;</em><br/><em>Cumplimiento legal digital.</em>
      </h1>
      <p className="hero-sub">
        Soy <strong>Miguel Yalta</strong>. Ingeniero en Informática y Habilitado de Derecho (Art. 2°, Ley 18.120).
        Diseño, ejecuto y garantizo el cumplimiento legal de la tecnología crítica de empresas de minería,
        logística, transportes, telecomunicaciones, casino y restaurantes — preparándolas para la
        Ley 21.719 desde el día uno.
      </p>
      <div className="hero-ctas">
        <a href="#contacto" className="btn btn-primary" data-cursor="active">
          Agenda diagnóstico gratuito <span>→</span>
        </a>
        <a href="#" className="btn btn-ghost" data-cursor="active" onClick={(e)=>{e.preventDefault(); alert('CV: este enlace descargaría /assets/cv-miguel-yalta.pdf');}}>
          Descargar CV <span>↓</span>
        </a>
      </div>
      <Countdown />
    </section>
  );
}

/* ========== FIGURES ========== */
function Figures() {
  const items = [
    ['13+', 'Años en TI / OT'],
    ['18', 'Proyectos IoT liderados'],
    ['6.000+', 'Dispositivos M2M integrados'],
    ['4', 'Sectores regulados atendidos'],
  ];
  return (
    <section className="figures container" aria-label="cifras">
      {items.map(([n, l]) => (
        <div className="figure" key={l}>
          <div className="figure-num serif">{n}</div>
          <div className="figure-label">{l}</div>
        </div>
      ))}
    </section>
  );
}

/* ========== SERVICES ========== */
const SERVICES = [
  {
    title: 'Tecnología crítica e Infraestructura (IT/OT)',
    desc: 'Diseño infraestructura que opera 24/7 en ambientes mineros y logísticos, donde cada hora de inactividad cuesta millones.',
    bullets: [
      'Redes industriales (PROFINET, Ethernet/IP, SCADA)',
      'Telemetría M2M y dispositivos GPS Teltonika / Jimi IoT',
      'Integración IoT y AVL multiproveedor',
      'Virtualización (VMware, Azure) y centros de datos',
      'CCTV corporativo (Dahua, Hikvision) y CGM',
    ],
  },
  {
    title: 'Compliance Digital y Ciberseguridad Legal',
    desc: 'Adecuación a la Ley 21.719, contratos tecnológicos blindados y respuesta a incidentes con criterio legal.',
    bullets: [
      'Adecuación Ley 21.719 / Ley 19.628 / Ley 21.663',
      'Delegado de Protección de Datos (DPO) externo',
      'Privacy by Design en proyectos IoT/OT',
      'Contratos SaaS, IaaS, encargados de tratamiento',
      'Peritaje informático y due diligence técnico-legal',
    ],
  },
  {
    title: 'Estrategia y Transformación Digital',
    desc: 'Proyectos integrales con gestión ágil, BI y arquitectura de soluciones para PyME e industria.',
    bullets: [
      'Gestión de proyectos (Jira, Azure DevOps, ágil)',
      'Dashboards BI (Power BI, Cognos)',
      'Integración ERP (SAP, Odoo, Softland, Maximise)',
      'Arquitectura cloud y de soluciones',
      'Capacitación y alfabetización digital',
    ],
  },
];

function Services() {
  return (
    <section id="servicios" className="section container" data-screen-label="03 Servicios">
      <div className="section-tag">Servicios · 02</div>
      <h2 className="section-title serif">Una sola contraparte. <em>Tres frentes</em> resueltos.</h2>
      <p className="section-sub">
        La mayoría de las empresas duplica costos contratando por separado a consultoras TI y
        estudios jurídicos para proyectos que exigen una visión integrada. YALTA elimina esa
        brecha y centralizo la responsabilidad.
      </p>
      <div className="services-grid">
        {SERVICES.map((s, i) => (
          <article className="service" key={i}>
            <div className="service-idx">
              <span>PILAR · 0{i+1}</span>
              <span>↗</span>
            </div>
            <h3 className="serif">{s.title}</h3>
            <p>{s.desc}</p>
            <ul>
              {s.bullets.map((b) => <li key={b}>{b}</li>)}
            </ul>
          </article>
        ))}
      </div>
    </section>
  );
}

/* ========== LEY 21.719 ALERT ========== */
function LeyAlert({ onMore }) {
  const stats = [
    ['20.000 UTM', 'Multa máxima (~$1.400M CLP)'],
    ['4%', 'Ingresos en reincidencia'],
    ['72h', 'Notificación de brechas'],
    ['ARCO+', 'Derechos del titular'],
  ];
  return (
    <section id="ley" className="alert-section" data-screen-label="04 Ley 21.719">
      <div className="container">
        <div className="section-tag">Alerta regulatoria · 03</div>
        <h2 className="section-title serif">
          Ley 21.719 entra en vigencia<br/><em>el 1 de diciembre de 2026.</em>
        </h2>
        <p className="section-sub" style={{ color: 'rgba(242,237,226,.8)' }}>
          La nueva Ley de Protección y Tratamiento de Datos Personales reemplaza el marco de la
          Ley 19.628 (vigente desde 1999) y eleva el estándar a nivel GDPR. Crea la Agencia de
          Protección de Datos Personales con potestades fiscalizadoras, sancionatorias y normativas reales.
        </p>
        <div className="alert-grid">
          {stats.map(([n, l]) => (
            <div key={l}>
              <div className="alert-stat-num serif">{n}</div>
              <div className="alert-stat-label">{l}</div>
            </div>
          ))}
        </div>
        <div style={{ marginTop: 48 }}>
          <button className="btn btn-ghost" data-cursor="active"
                  style={{ borderColor: 'var(--paper)', color: 'var(--paper)' }}
                  onClick={onMore}>
            Ver guía completa <span>→</span>
          </button>
        </div>
      </div>
    </section>
  );
}

/* ========== ABOUT ========== */
function About() {
  const creds = [
    ['Título', 'Ingeniero en Informática', 'INACAP, 2013 · Folio SRCeI 500673365289'],
    ['Habilitación', 'Habilitado de Derecho', 'Universidad del Alba · Vigente Dic 2026 · Art. 2° Inc. 1° Ley 18.120'],
    ['Postgrado', 'Computer Science for Lawyers', 'HarvardX CS50L · 2026'],
    ['Diplomado', 'Cooperativismo y Economía Social', 'Min. Economía + DIBAM, 2017'],
  ];
  const chips = ['Minería', 'Logística', 'Transportes', 'Telecomunicaciones', 'Casino', 'Restaurantes', 'Servicios jurídicos', 'Industrial'];
  return (
    <section id="perfil" className="section container" data-screen-label="02 Perfil">
      <div className="section-tag">Perfil · 01</div>
      <h2 className="section-title serif">Porque el riesgo regulatorio<br/><em>ya no se delega.</em></h2>
      <div className="about-grid">
        <div className="about-prose">
          <p>
            Llevo más de una década diseñando, integrando y operando tecnología en ambientes donde
            una falla paraliza la operación y detona contingencias legales: mineras, flotas, redes
            corporativas. Empecé en Proyecta S.A. y Fenner Dunlop — Conveyor Services, pasé por
            consultoría en redes para CRCMAQ, lideré 18 integraciones IoT en YAVANET con más de
            6.000 dispositivos M2M desplegados, y dirigí innovación y transformación digital en
            AMAY GROUP.
          </p>
          <p>
            En paralelo, estoy Habilitado de Derecho conforme al Art. 2° Inc. 1° de la Ley 18.120,
            con certificación vigente hasta diciembre 2026. Esta doble formación nació de una
            observación práctica: en cada proyecto serio aparecían preguntas legales que ninguna
            gerencia TI tenía cómo responder.
          </p>
          <p>
            Hoy ofrezco esa integración como servicio: ingeniería que cumple, sin la fricción de
            coordinar entre tu consultora TI y tu estudio jurídico. Un enfoque especialmente crítico
            ante las exigencias normativas que entran en vigencia el 1 de diciembre de 2026.
          </p>
          <div className="chips">
            {chips.map(c => <span className="chip" key={c}>{c}</span>)}
          </div>
        </div>
        <aside className="credentials">
          {creds.map(([k, t, m]) => (
            <div className="credential" key={t}>
              <div className="credential-label">{k}</div>
              <div className="credential-title serif">{t}</div>
              <div className="credential-meta">{m}</div>
            </div>
          ))}
        </aside>
      </div>
    </section>
  );
}

/* ========== REPOSITORY ========== */
const REPO_FOLDERS = [
  { id: 'compliance', icon: '▸', label: 'compliance_21719', count: 7 },
  { id: 'contracts', icon: '▸', label: 'contratos', count: 4 },
  { id: 'dpia', icon: '▸', label: 'dpias', count: 3 },
  { id: 'audits', icon: '▸', label: 'auditorías', count: 5 },
  { id: 'reports', icon: '▸', label: 'informes_técnicos', count: 9 },
];

const REPO_FILES = {
  compliance: [
    ['inventario_tratamientos_v3.xlsx', 'XLSX · 142 KB', '12 may 2026', 'ready'],
    ['gap_analysis_21719.pdf', 'PDF · 1.2 MB', '08 may 2026', 'signed'],
    ['protocolo_brechas_72h.pdf', 'PDF · 480 KB', '02 may 2026', 'ready'],
    ['designacion_dpo_externo.pdf', 'PDF · 312 KB', '28 abr 2026', 'signed'],
    ['registro_consentimientos.csv', 'CSV · 88 KB', '25 abr 2026', 'ready'],
    ['plan_capacitacion_personal.pdf', 'PDF · 740 KB', '20 abr 2026', 'review'],
    ['mapa_proveedores_encargados.xlsx', 'XLSX · 96 KB', '15 abr 2026', 'ready'],
  ],
  contracts: [
    ['encargo_tratamiento_modelo.docx', 'DOCX · 64 KB', '18 may 2026', 'ready'],
    ['nda_proyecto_minera.pdf', 'PDF · 220 KB', '14 may 2026', 'signed'],
    ['contrato_consultoría_2026.pdf', 'PDF · 312 KB', '10 may 2026', 'signed'],
    ['anexo_iot_telemetría.docx', 'DOCX · 48 KB', '05 may 2026', 'review'],
  ],
  dpia: [
    ['dpia_geolocalización_avl.pdf', 'PDF · 2.1 MB', '22 may 2026', 'signed'],
    ['dpia_biometría_acceso.pdf', 'PDF · 1.8 MB', '15 may 2026', 'review'],
    ['dpia_salud_ocupacional.pdf', 'PDF · 1.4 MB', '08 may 2026', 'ready'],
  ],
  audits: [
    ['audit_redes_OT_q2.pdf', 'PDF · 3.2 MB', '20 may 2026', 'ready'],
    ['penetration_test_externo.pdf', 'PDF · 4.8 MB', '12 may 2026', 'signed'],
    ['revisión_cctv_dahua.pdf', 'PDF · 980 KB', '04 may 2026', 'ready'],
    ['inventario_activos_TI.xlsx', 'XLSX · 124 KB', '28 abr 2026', 'ready'],
    ['matriz_riesgos_2026.xlsx', 'XLSX · 88 KB', '22 abr 2026', 'review'],
  ],
  reports: [
    ['informe_mensual_may_2026.pdf', 'PDF · 1.6 MB', '24 may 2026', 'ready'],
    ['kpi_compliance_dashboard.pdf', 'PDF · 720 KB', '18 may 2026', 'ready'],
    ['hallazgos_auditoría_q1.pdf', 'PDF · 1.2 MB', '12 may 2026', 'signed'],
    ['propuesta_arquitectura_v2.pdf', 'PDF · 2.4 MB', '08 may 2026', 'review'],
    ['benchmark_dispositivos_iot.xlsx', 'XLSX · 168 KB', '02 may 2026', 'ready'],
    ['reporte_incidentes_abr.pdf', 'PDF · 540 KB', '28 abr 2026', 'ready'],
    ['plan_migración_cloud.pdf', 'PDF · 1.8 MB', '22 abr 2026', 'review'],
    ['evaluación_proveedores.xlsx', 'XLSX · 92 KB', '15 abr 2026', 'ready'],
    ['acta_reunión_kickoff.pdf', 'PDF · 320 KB', '10 abr 2026', 'signed'],
  ],
};

function Repository() {
  const [authed, setAuthed] = useState(false);
  const [folder, setFolder] = useState('compliance');
  const [user, setUser] = useState('');
  const [pass, setPass] = useState('');
  const [err, setErr] = useState('');

  const handleLogin = (e) => {
    e.preventDefault();
    if (user.trim() && pass.trim()) {
      setAuthed(true);
      setErr('');
    } else {
      setErr('Credenciales requeridas.');
    }
  };

  return (
    <section id="repositorio" className="section container" data-screen-label="05 Repositorio">
      <div className="section-tag">Portal cliente · 04</div>
      <h2 className="section-title serif">Tu información, <em>siempre disponible.</em></h2>
      <p className="section-sub">
        Repositorio administrable para clientes activos: contratos firmados, inventarios de tratamiento,
        DPIAs, informes mensuales y artefactos de cumplimiento Ley 21.719. Acceso con doble factor,
        cifrado en tránsito (TLS 1.3) y registro de auditoría completo.
      </p>

      <div className="repo-frame">
        {!authed ? (
          <div className="repo-login">
            <h3 className="serif">Acceso clientes</h3>
            <p>
              Si tu empresa ya es cliente activo, accede con las credenciales que recibiste por correo.
              <br/><small style={{ color: 'var(--ink-muted)' }}>Demo: ingresa cualquier usuario y contraseña.</small>
            </p>
            <form className="repo-login-form" onSubmit={handleLogin}>
              <div className="field" style={{ margin: 0 }}>
                <label>Usuario o RUT</label>
                <input type="text" value={user} onChange={(e)=>setUser(e.target.value)} placeholder="empresa@dominio.cl" />
              </div>
              <div className="field" style={{ margin: 0 }}>
                <label>Contraseña</label>
                <input type="password" value={pass} onChange={(e)=>setPass(e.target.value)} placeholder="••••••••" />
              </div>
              {err && <div style={{ color: 'var(--accent)', fontSize: 12, fontFamily: 'JetBrains Mono' }}>{err}</div>}
              <button className="btn btn-primary" type="submit" style={{ justifyContent: 'center', marginTop: 8 }}>
                Iniciar sesión →
              </button>
              <div style={{ fontSize: 11, color: 'var(--ink-muted)', fontFamily: 'JetBrains Mono', letterSpacing: '.1em', textTransform: 'uppercase', marginTop: 8 }}>
                TLS 1.3 · 2FA obligatorio · Logs auditables
              </div>
            </form>
          </div>
        ) : (
          <Fragment>
            <aside className="repo-side">
              <div className="repo-side-label">// Carpetas</div>
              {REPO_FOLDERS.map(f => (
                <div key={f.id}
                     className={'repo-folder ' + (folder === f.id ? 'active' : '')}
                     onClick={() => setFolder(f.id)}
                     data-cursor="active">
                  <span className="ico">{folder === f.id ? '▾' : '▸'}</span>
                  <span>{f.label}</span>
                  <span className="count">{f.count}</span>
                </div>
              ))}
              <div style={{ marginTop: 'auto', paddingTop: 24, borderTop: '1px solid rgba(242,237,226,.1)' }}>
                <div className="repo-side-label">Sesión</div>
                <div style={{ fontFamily: 'JetBrains Mono', fontSize: 11, marginBottom: 8 }}>{user || 'demo@cliente.cl'}</div>
                <button onClick={() => setAuthed(false)}
                        style={{ fontFamily: 'JetBrains Mono', fontSize: 10, letterSpacing: '.12em', color: 'rgba(242,237,226,.7)', textTransform: 'uppercase', textDecoration: 'underline' }}>
                  Cerrar sesión
                </button>
              </div>
            </aside>
            <div className="repo-main">
              <div className="repo-breadcrumb">
                <span>yalta.cl</span><span>/</span><span>cliente</span><span>/</span><span style={{ color: 'var(--ink)' }}>{REPO_FOLDERS.find(f=>f.id===folder).label}</span>
              </div>
              <div className="repo-files">
                <div className="repo-file" style={{ borderTop: 0, color: 'var(--ink-muted)', fontFamily: 'JetBrains Mono', fontSize: 10, letterSpacing: '.12em', textTransform: 'uppercase' }}>
                  <span></span>
                  <span>Nombre</span>
                  <span>Tipo / Tamaño</span>
                  <span>Fecha</span>
                  <span>Estado</span>
                </div>
                {REPO_FILES[folder].map(([n, t, d, s]) => (
                  <div className="repo-file" key={n} data-cursor="active">
                    <span style={{ color: 'var(--accent)' }}>⌥</span>
                    <span className="file-name">{n}</span>
                    <span className="file-meta">{t}</span>
                    <span className="file-meta">{d}</span>
                    <span className={'file-status ' + s}>{s === 'ready' ? 'Listo' : s === 'review' ? 'Revisión' : 'Firmado'}</span>
                  </div>
                ))}
              </div>
            </div>
          </Fragment>
        )}
      </div>
    </section>
  );
}

/* ========== CONTACT ========== */
function ContactForm() {
  const [data, setData] = useState({
    name: '', email: '', company: '', phone: '', service: 'compliance', message: '', consent: false,
  });
  const [sent, setSent] = useState(false);
  const [errors, setErrors] = useState({});
  const [sending, setSending] = useState(false);

  const upd = (k) => (e) => setData(d => ({ ...d, [k]: e.target.type === 'checkbox' ? e.target.checked : e.target.value }));

  // Endpoint del formulario. FormSubmit.co: zero-config, sin cuenta.
  // Cambia EMAIL_DESTINO por tu correo real. La primera vez que alguien envíe el formulario,
  // FormSubmit te enviará un correo de verificación que debes confirmar.
  const FORM_ENDPOINT = 'https://formsubmit.co/ajax/miguel@yalta.cl';

  const submit = async (e) => {
    e.preventDefault();
    const errs = {};
    if (!data.name.trim()) errs.name = 'Requerido';
    if (!/^\S+@\S+\.\S+$/.test(data.email)) errs.email = 'Email no válido';
    if (!data.message.trim()) errs.message = 'Cuéntame brevemente tu consulta';
    if (!data.consent) errs.consent = 'Debes aceptar la política de privacidad';
    setErrors(errs);
    if (Object.keys(errs).length > 0) return;

    setSending(true);
    const payload = {
      _subject: `[yalta.cl] Nueva consulta de ${data.name}`,
      _template: 'table',
      _captcha: 'false',
      Nombre: data.name,
      Empresa: data.company || '—',
      Email: data.email,
      Telefono: data.phone || '—',
      Servicio: data.service,
      Mensaje: data.message,
      Origen: 'yalta.cl · formulario web',
    };

    try {
      const r = await fetch(FORM_ENDPOINT, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
        body: JSON.stringify(payload),
      });
      if (r.ok) {
        setSent(true);
      } else {
        throw new Error('http ' + r.status);
      }
    } catch (err) {
      // Fallback: abrir cliente de correo del usuario
      const body = encodeURIComponent(
        `Nombre: ${data.name}\nEmpresa: ${data.company}\nEmail: ${data.email}\nTeléfono: ${data.phone}\nServicio: ${data.service}\n\n${data.message}`
      );
      const subject = encodeURIComponent(`[yalta.cl] Consulta de ${data.name}`);
      window.location.href = `mailto:miguel@yalta.cl?subject=${subject}&body=${body}`;
      setSent(true);
    } finally {
      setSending(false);
    }
  };

  if (sent) {
    return (
      <div className="form-success">
        <div className="check">✓</div>
        <h3 className="serif" style={{ fontSize: 24, marginBottom: 8 }}>Mensaje recibido.</h3>
        <p style={{ color: 'var(--ink-soft)', marginBottom: 16 }}>
          Te responderé en menos de 24 horas hábiles al correo <strong>{data.email}</strong>.
        </p>
        <div className="mono-note" style={{ fontFamily: 'JetBrains Mono', fontSize: 10, letterSpacing: '.12em', color: 'var(--ink-muted)', textTransform: 'uppercase' }}>
          Folio temporal #YLT-{Math.random().toString(36).slice(2,8).toUpperCase()}
        </div>
        <button className="btn btn-ghost" style={{ marginTop: 20 }} onClick={() => { setSent(false); setData({ name:'',email:'',company:'',phone:'',service:'compliance',message:'',consent:false }); }}>
          Enviar otro mensaje
        </button>
      </div>
    );
  }

  return (
    <form className="form" onSubmit={submit} noValidate>
      <h3 className="serif">Diagnóstico gratuito · 30 min</h3>
      <div className="form-sub">// Respondo en menos de 24 hrs hábiles</div>

      <div className="field-row">
        <div className="field">
          <label>Nombre completo *</label>
          <input type="text" value={data.name} onChange={upd('name')} />
          {errors.name && <small style={{ color: 'var(--accent)', fontSize: 11 }}>{errors.name}</small>}
        </div>
        <div className="field">
          <label>Empresa</label>
          <input type="text" value={data.company} onChange={upd('company')} placeholder="(opcional)" />
        </div>
      </div>

      <div className="field-row">
        <div className="field">
          <label>Email *</label>
          <input type="email" value={data.email} onChange={upd('email')} />
          {errors.email && <small style={{ color: 'var(--accent)', fontSize: 11 }}>{errors.email}</small>}
        </div>
        <div className="field">
          <label>Teléfono / WhatsApp</label>
          <input type="tel" value={data.phone} onChange={upd('phone')} placeholder="+56 9" />
        </div>
      </div>

      <div className="field">
        <label>¿Qué necesitas resolver?</label>
        <select value={data.service} onChange={upd('service')}>
          <option value="compliance">Adecuación Ley 21.719 / Compliance Digital</option>
          <option value="dpo">DPO externo (Delegado de Protección de Datos)</option>
          <option value="infra">Infraestructura TI / OT (redes, IoT, SCADA)</option>
          <option value="contracts">Contratos tecnológicos / encargo de tratamiento</option>
          <option value="peritaje">Peritaje informático</option>
          <option value="other">Otro / consulta general</option>
        </select>
      </div>

      <div className="field">
        <label>Cuéntame brevemente *</label>
        <textarea value={data.message} onChange={upd('message')} placeholder="Contexto del proyecto, tamaño de la empresa, plazo estimado..."></textarea>
        {errors.message && <small style={{ color: 'var(--accent)', fontSize: 11 }}>{errors.message}</small>}
      </div>

      <label className="consent">
        <input type="checkbox" checked={data.consent} onChange={upd('consent')} />
        <span>
          He leído y acepto la <a href="#" onClick={(e)=>{e.preventDefault(); window.openModal && window.openModal('privacy');}} style={{ textDecoration: 'underline' }}>Política de Privacidad</a> conforme a la Ley 21.719.
        </span>
      </label>
      {errors.consent && <small style={{ color: 'var(--accent)', fontSize: 11, display: 'block', marginBottom: 8 }}>{errors.consent}</small>}

      <button type="submit" className="btn btn-primary" data-cursor="active" disabled={sending}>
        {sending ? <span>Enviando…</span> : <span>Enviar consulta →</span>}
      </button>
    </form>
  );
}

function Contact() {
  return (
    <section id="contacto" className="section container" data-screen-label="06 Contacto">
      <div className="section-tag">Contacto · 05</div>
      <h2 className="section-title serif">
        ¿Tu próximo proyecto necesita una mirada técnica<br/><em>con criterio legal?</em>
      </h2>
      <p className="section-sub">
        Atiendo presencialmente en Antofagasta y remoto a todo Chile. La primera sesión de diagnóstico
        (30 minutos) es sin costo. Modalidad de trabajo según diagnóstico.
      </p>

      <div className="contact-grid">
        <div>
          <div className="contact-info">
            <div className="contact-row">
              <span className="lbl">Dirección</span>
              <span className="val">Calle Prat 548, Of. 501<small>Antofagasta · Chile</small></span>
            </div>
            <div className="contact-row">
              <span className="lbl">Email</span>
              <span className="val">miguel@yalta.cl<small>respuesta &lt; 24 hrs hábiles</small></span>
            </div>
            <div className="contact-row">
              <span className="lbl">Teléfono</span>
              <span className="val">+56 9 8827 0039<small>WhatsApp · L-V 09:00-19:00</small></span>
            </div>
            <div className="contact-row">
              <span className="lbl">LinkedIn</span>
              <span className="val">/in/miguelyalta<small>Perfil profesional</small></span>
            </div>
            <div className="contact-row">
              <span className="lbl">Cobertura</span>
              <span className="val">Antofagasta · Santiago · Remoto<small>Chile · LatAm</small></span>
            </div>
          </div>
          <div className="map-card">
            <iframe
              src="https://www.google.com/maps?q=Calle+Prat+548,+Antofagasta,+Chile&output=embed"
              title="Calle Prat 548, Antofagasta"
              loading="lazy"
              referrerPolicy="no-referrer-when-downgrade"
              allowFullScreen=""
              className="map-iframe"
            ></iframe>
            <div className="pin-meta">// 23°39′03″S 70°23′59″W · Calle Prat 548, Of. 501 · Antofagasta</div>
            <a href="https://www.google.com/maps/dir/?api=1&destination=Calle+Prat+548,+Antofagasta,+Chile"
               target="_blank" rel="noopener" className="map-link" data-cursor="active">
              Cómo llegar →
            </a>
          </div>
        </div>
        <ContactForm />
      </div>
    </section>
  );
}

/* ========== FOOTER ========== */
function Footer({ openModal }) {
  return (
    <footer className="footer" data-screen-label="07 Footer">
      <div className="container">
        <div className="footer-grid">
          <div>
            <Logo size={24} />
            <p style={{ marginTop: 20, fontSize: 13, color: 'rgba(242,237,226,.6)', maxWidth: '36ch' }}>
              Ingeniero en Informática · Habilitado de Derecho conforme Art. 2° Inc. 1° Ley 18.120.
              Antofagasta, Chile.
            </p>
          </div>
          <div>
            <h4>Navegación</h4>
            <ul>
              <li><a href="#perfil">Perfil</a></li>
              <li><a href="#servicios">Servicios</a></li>
              <li><a href="#ley">Ley 21.719</a></li>
              <li><a href="#repositorio">Portal cliente</a></li>
              <li><a href="#contacto">Contacto</a></li>
            </ul>
          </div>
          <div>
            <h4>Legal</h4>
            <ul>
              <li><a href="#" onClick={(e)=>{e.preventDefault(); openModal('privacy');}}>Política de Privacidad</a></li>
              <li><a href="#" onClick={(e)=>{e.preventDefault(); openModal('terms');}}>Términos y Condiciones</a></li>
              <li><a href="#" onClick={(e)=>{e.preventDefault(); openModal('ley');}}>Guía Ley 21.719</a></li>
              <li><a href="#">Protección Ley 17.336</a></li>
            </ul>
          </div>
          <div>
            <h4>Contacto</h4>
            <ul>
              <li>miguel@yalta.cl</li>
              <li>+56 9 8827 0039</li>
              <li>Prat 548 · Of. 501</li>
              <li>Antofagasta</li>
            </ul>
          </div>
        </div>
        <div className="footer-bar">
          <span className="fb-copy">© 2026 Miguel Ángel Yalta · yalta.cl</span>
          <VisitorBadge inline />
          <span className="fb-legal">Sitio protegido · Ley 17.336 · Ley 21.719</span>
        </div>
      </div>
    </footer>
  );
}

/* ========== MODAL ========== */
function Modal({ open, title, mono, onClose, children }) {
  useEffect(() => {
    if (!open) return;
    const onKey = (e) => e.key === 'Escape' && onClose();
    window.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => { window.removeEventListener('keydown', onKey); document.body.style.overflow = ''; };
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal-card" onClick={(e)=>e.stopPropagation()}>
        <div className="modal-head">
          <h3 className="serif">{title}</h3>
          <button className="modal-close" onClick={onClose}>Cerrar ✕</button>
        </div>
        <div className="modal-body">
          {mono && <div className="mono-note">{mono}</div>}
          {children}
        </div>
      </div>
    </div>
  );
}

/* ========== CUSTOM CURSOR ========== */
function CustomCursor({ variant, showCoords }) {
  const ringRef = useRef(null);
  const dotRef = useRef(null);
  const hRef = useRef(null);
  const vRef = useRef(null);
  const readoutRef = useRef(null);
  const stateRef = useRef({ x: 0, y: 0, tx: 0, ty: 0, active: false, text: false });

  useEffect(() => {
    let rafId;
    const onMove = (e) => {
      stateRef.current.tx = e.clientX;
      stateRef.current.ty = e.clientY;
      const t = e.target;
      const interactive = t.closest('a, button, input, textarea, select, [data-cursor="active"], .repo-folder, .repo-file, .service');
      const text = t.matches('input, textarea');
      stateRef.current.active = !!interactive && !text;
      stateRef.current.text = text;
    };
    const onLeave = () => { if (ringRef.current) ringRef.current.style.opacity = 0; if (dotRef.current) dotRef.current.style.opacity = 0; };
    const onEnter = () => { if (ringRef.current) ringRef.current.style.opacity = 1; if (dotRef.current) dotRef.current.style.opacity = 1; };

    const tick = () => {
      const s = stateRef.current;
      s.x += (s.tx - s.x) * 0.18;
      s.y += (s.ty - s.y) * 0.18;
      if (dotRef.current) {
        dotRef.current.style.transform = `translate(${s.tx}px, ${s.ty}px) translate(-50%, -50%)`;
      }
      if (ringRef.current) {
        ringRef.current.style.transform = `translate(${s.x}px, ${s.y}px) translate(-50%, -50%)`;
        ringRef.current.className = 'cursor-ring' + (s.active ? ' cursor-active' : '') + (s.text ? ' cursor-text' : '');
      }
      if (variant === 'crosshair') {
        if (hRef.current) hRef.current.style.transform = `translateY(${s.ty}px)`;
        if (vRef.current) vRef.current.style.transform = `translateX(${s.tx}px)`;
      }
      if (readoutRef.current && showCoords) {
        readoutRef.current.style.transform = `translate(${s.tx + 18}px, ${s.ty + 18}px)`;
        const xs = String(Math.round(s.tx)).padStart(4, '0');
        const ys = String(Math.round(s.ty)).padStart(4, '0');
        readoutRef.current.textContent = `x:${xs} · y:${ys}`;
      }
      rafId = requestAnimationFrame(tick);
    };
    rafId = requestAnimationFrame(tick);
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseleave', onLeave);
    window.addEventListener('mouseenter', onEnter);
    return () => {
      cancelAnimationFrame(rafId);
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseleave', onLeave);
      window.removeEventListener('mouseenter', onEnter);
    };
  }, [variant, showCoords]);

  if (variant === 'off') return null;

  return (
    <div style={{ display: 'contents' }}>
      {variant === 'crosshair' && (
        <Fragment>
          <div className="cursor-crosshair-h" ref={hRef}></div>
          <div className="cursor-crosshair-v" ref={vRef}></div>
        </Fragment>
      )}
      <div className="cursor-ring" ref={ringRef}></div>
      <div className="cursor-dot" ref={dotRef}></div>
      {showCoords && <div className="cursor-readout" ref={readoutRef}>x:0000 · y:0000</div>}
    </div>
  );
}

/* ========== SCROLL TO TOP ========== */
function ScrollTop() {
  const [show, setShow] = useState(false);
  const [progress, setProgress] = useState(0);
  useEffect(() => {
    const onScroll = () => {
      const doc = document.documentElement;
      const total = doc.scrollHeight - window.innerHeight;
      const scrolled = window.scrollY;
      const pct = total > 0 ? scrolled / total : 0;
      setProgress(pct);
      // show after scrolling 60% of one viewport
      setShow(scrolled > window.innerHeight * 0.6);
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  const circumference = 2 * Math.PI * 20;
  const offset = circumference * (1 - progress);

  return (
    <button
      className={'to-top' + (show ? ' show' : '')}
      onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
      data-cursor="active"
      aria-label="Volver arriba"
    >
      <svg className="to-top-ring" width="48" height="48" viewBox="0 0 48 48">
        <circle cx="24" cy="24" r="20" fill="none" stroke="rgba(242,237,226,.18)" strokeWidth="2" />
        <circle cx="24" cy="24" r="20" fill="none" stroke="var(--accent)" strokeWidth="2"
                strokeDasharray={circumference}
                strokeDashoffset={offset}
                strokeLinecap="round"
                transform="rotate(-90 24 24)" />
      </svg>
      <span className="to-top-arrow">↑</span>
      <span className="to-top-label">Volver arriba</span>
    </button>
  );
}

/* ========== WHATSAPP ========== */
function WhatsApp() {
  const msg = encodeURIComponent('Hola Miguel, vi tu sitio yalta.cl y me gustaría agendar un diagnóstico.');
  return (
    <a href={`https://wa.me/56988270039?text=${msg}`} target="_blank" rel="noopener" className="wa-float" data-cursor="active" aria-label="Contactar por WhatsApp">
      <span className="wa-pulse"></span>
      <span className="wa-ico">
        <svg width="28" height="28" viewBox="0 0 24 24" fill="#fff">
          <path d="M12.04 2C6.58 2 2.13 6.45 2.13 11.91c0 1.75.46 3.45 1.32 4.95L2.05 22l5.25-1.38a9.86 9.86 0 0 0 4.74 1.21h.01c5.46 0 9.91-4.45 9.91-9.91S17.5 2 12.04 2zm0 18.15h-.01a8.2 8.2 0 0 1-4.18-1.15l-.3-.18-3.11.82.83-3.04-.2-.31a8.2 8.2 0 1 1 6.97 3.86zm4.5-6.13c-.25-.12-1.46-.72-1.68-.8-.23-.08-.39-.12-.55.12-.16.25-.64.8-.78.97-.14.16-.29.18-.54.06-.25-.12-1.04-.38-1.98-1.22-.73-.65-1.23-1.46-1.37-1.71-.14-.25-.02-.38.11-.5.11-.11.25-.29.37-.43.12-.14.16-.25.25-.41.08-.16.04-.31-.02-.43-.06-.12-.55-1.34-.76-1.83-.2-.48-.4-.42-.55-.42h-.47c-.16 0-.43.06-.65.31-.23.25-.86.84-.86 2.05 0 1.21.88 2.38 1.01 2.55.12.16 1.74 2.66 4.22 3.73.59.25 1.05.4 1.41.52.59.19 1.13.16 1.56.1.48-.07 1.46-.6 1.66-1.18.21-.58.21-1.07.14-1.18-.06-.11-.22-.18-.47-.3z"/>
        </svg>
      </span>
      <span className="wa-tooltip">WhatsApp directo</span>
    </a>
  );
}

/* ========== IP TRACKER ========== */
function VisitorBadge({ inline = false }) {
  const [data, setData] = useState({ current: null, last: null, count: 0 });
  const [expanded, setExpanded] = useState(false);

  useEffect(() => {
    let cancelled = false;
    const STORAGE_KEY = 'yalta_visitor_log';
    const stored = (() => {
      try { return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); }
      catch { return {}; }
    })();

    fetch('https://api.ipify.org?format=json')
      .then(r => r.ok ? r.json() : Promise.reject())
      .then(j => {
        if (cancelled) return;
        const now = new Date().toISOString();
        const last = stored.current && stored.current.ip !== j.ip ? stored.current : (stored.last || null);
        const count = (stored.count || 0) + 1;
        const current = { ip: j.ip, ts: now };
        const next = { current, last, count };
        try { localStorage.setItem(STORAGE_KEY, JSON.stringify(next)); } catch {}
        setData(next);
      })
      .catch(() => {
        if (cancelled) return;
        setData({ current: { ip: '———.———.———.———', ts: new Date().toISOString() }, last: stored.last || stored.current || null, count: stored.count || 0 });
      });

    return () => { cancelled = true; };
  }, []);

  const fmt = (iso) => {
    if (!iso) return '—';
    const d = new Date(iso);
    return d.toLocaleString('es-CL', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' });
  };

  return (
    <div className={'visitor-badge ' + (inline ? 'inline ' : '') + (expanded ? 'expanded' : '')}
         onClick={() => setExpanded(e => !e)}
         data-cursor="active"
         role="button"
         title="Bitácora de visitas">
      <div className="vb-dot"></div>
      <div className="vb-line">
        <span className="vb-label">IP actual</span>
        <span className="vb-val mono">{data.current ? data.current.ip : 'detectando…'}</span>
      </div>
      {expanded && (
        <div className="vb-detail">
          <div className="vb-row">
            <span className="vb-label">Última visita previa</span>
            <span className="vb-val mono">{data.last ? data.last.ip : 'primera visita'}</span>
          </div>
          <div className="vb-row">
            <span className="vb-label">Fecha previa</span>
            <span className="vb-val mono">{data.last ? fmt(data.last.ts) : '—'}</span>
          </div>
          <div className="vb-row">
            <span className="vb-label">Visitas registradas</span>
            <span className="vb-val mono">{String(data.count).padStart(4,'0')}</span>
          </div>
          <div className="vb-note">
            Bitácora local en este navegador. Cumple Art. 14 Ley 21.719 · registro de accesos.
          </div>
        </div>
      )}
    </div>
  );
}

/* ========== ANTI-COPY ========== */
function useAntiCopy(enabled) {
  useEffect(() => {
    if (!enabled) return;
    const isField = (el) => el && (el.matches('input, textarea, [contenteditable="true"]'));
    const notify = (msg = 'Contenido protegido · Ley 17.336') => {
      const t = document.createElement('div');
      t.className = 'copy-toast';
      t.textContent = msg;
      document.body.appendChild(t);
      setTimeout(() => t.classList.add('show'), 10);
      setTimeout(() => { t.classList.remove('show'); setTimeout(() => t.remove(), 300); }, 1800);
    };
    const onCopy = (e) => {
      if (isField(e.target)) return;
      e.preventDefault();
      try { e.clipboardData && e.clipboardData.setData('text/plain', '© yalta.cl · contenido protegido por Ley 17.336.'); } catch {}
      notify('Copia bloqueada · contenido protegido');
    };
    const onContext = (e) => {
      if (isField(e.target)) return;
      // allow context menu inside mobile menu (so links work normally)
      if (e.target.closest('.mobile-menu')) return;
      e.preventDefault();
      notify('Menú contextual deshabilitado');
    };
    const onDrag = (e) => { if (!isField(e.target)) e.preventDefault(); };
    const onSelect = (e) => {
      if (isField(e.target)) return;
      if (e.target.closest && e.target.closest('.mobile-menu')) return;
      e.preventDefault();
    };
    const onKey = (e) => {
      if (isField(e.target)) return;
      const k = e.key.toLowerCase();
      if ((e.ctrlKey || e.metaKey) && ['c','x','s','u','p','a'].includes(k)) {
        e.preventDefault();
        notify('Acción bloqueada · Ctrl+' + k.toUpperCase());
      }
      if (k === 'printscreen') notify('Captura detectada');
    };
    document.addEventListener('copy', onCopy);
    document.addEventListener('cut', onCopy);
    document.addEventListener('contextmenu', onContext);
    document.addEventListener('dragstart', onDrag);
    document.addEventListener('selectstart', onSelect);
    document.addEventListener('keydown', onKey);
    document.body.classList.add('no-copy');
    return () => {
      document.removeEventListener('copy', onCopy);
      document.removeEventListener('cut', onCopy);
      document.removeEventListener('contextmenu', onContext);
      document.removeEventListener('dragstart', onDrag);
      document.removeEventListener('selectstart', onSelect);
      document.removeEventListener('keydown', onKey);
      document.body.classList.remove('no-copy');
    };
  }, [enabled]);
}

/* ========== NAV ========== */
function Nav({ logo, openModal }) {
  const [open, setOpen] = useState(false);
  useEffect(() => {
    const close = () => setOpen(false);
    window.addEventListener('hashchange', close);
    return () => window.removeEventListener('hashchange', close);
  }, []);
  useEffect(() => {
    document.body.style.overflow = open ? 'hidden' : '';
    document.body.classList.toggle('menu-open', open);
    return () => {
      document.body.style.overflow = '';
      document.body.classList.remove('menu-open');
    };
  }, [open]);
  const links = [
    ['#perfil', 'Perfil'],
    ['#servicios', 'Servicios'],
    ['#ley', 'Ley 21.719'],
    ['#repositorio', 'Portal'],
    ['#contacto', 'Contacto'],
  ];
  return (
    <nav className="nav">
      <div className="container nav-inner">
        <Logo variant={logo} />
        <div className="nav-links">
          {links.map(([h, l]) => <a key={h} href={h}>{l}</a>)}
        </div>
        <a href="#contacto" className="nav-cta nav-cta-desktop">Diagnóstico →</a>
        <button
          className={'hamburger ' + (open ? 'open' : '')}
          onClick={() => setOpen(o => !o)}
          aria-label={open ? 'Cerrar menú' : 'Abrir menú'}
          aria-expanded={open}
          data-cursor="active"
        >
          <span></span><span></span><span></span>
        </button>
      </div>

      <div className={'mobile-menu ' + (open ? 'open' : '')} aria-hidden={!open}>
        <div className="mobile-menu-meta">// MENÚ</div>
        <div className="mobile-menu-title">
          Tecnología crítica,<br/><em>cumplimiento legal.</em>
        </div>
        <ol className="mobile-menu-list">
          {links.map(([h, l], i) => (
            <li key={h} style={{ '--i': i }}>
              <a href={h} onClick={() => setOpen(false)}>
                <span className="mm-num">0{i+1}</span>
                <span className="mm-label">{l}</span>
                <span className="mm-arrow">→</span>
              </a>
            </li>
          ))}
        </ol>
        <div className="mobile-menu-footer">
          <a href="#contacto" className="btn btn-primary" onClick={() => setOpen(false)}>
            Agenda diagnóstico gratuito <span>→</span>
          </a>
          <div className="mobile-menu-contact">
            <a className="mm-contact-cell" href="mailto:miguel@yalta.cl" onClick={() => setOpen(false)}>
              <span className="mm-cell-label">Email</span>
              <span className="mm-cell-val">miguel@yalta.cl</span>
            </a>
            <a className="mm-contact-cell" href="tel:+56988270039" onClick={() => setOpen(false)}>
              <span className="mm-cell-label">Teléfono</span>
              <span className="mm-cell-val">+56 9 8827 0039</span>
            </a>
            <a className="mm-contact-cell full"
               href="https://wa.me/56988270039"
               target="_blank" rel="noopener"
               onClick={() => setOpen(false)}>
              <span className="mm-cell-icon">
                <svg width="20" height="20" viewBox="0 0 24 24" fill="#25D366">
                  <path d="M12.04 2C6.58 2 2.13 6.45 2.13 11.91c0 1.75.46 3.45 1.32 4.95L2.05 22l5.25-1.38a9.86 9.86 0 0 0 4.74 1.21h.01c5.46 0 9.91-4.45 9.91-9.91S17.5 2 12.04 2z"/>
                </svg>
              </span>
              <div>
                <span className="mm-cell-label">WhatsApp directo</span>
                <span className="mm-cell-val">+56 9 8827 0039</span>
              </div>
            </a>
            <span className="mm-contact-cell full" style={{ pointerEvents: 'none' }}>
              <span className="mm-cell-label">Oficina</span>
              <span className="mm-cell-val serif">Calle Prat 548, Of. 501 · Antofagasta</span>
            </span>
          </div>
          <div className="mobile-menu-meta-bottom">
            yalta.cl · est. 2007 · habilitado de derecho
          </div>
        </div>
      </div>
    </nav>
  );
}

/* ========== APP ========== */
function App() {
  const [t, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const [modal, setModal] = useState(null);

  useAntiCopy(t.antiCopy !== false);

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', t.theme === 'paper' ? '' : t.theme);
  }, [t.theme]);

  useEffect(() => {
    document.documentElement.style.setProperty('--accent', t.accentColor);
  }, [t.accentColor]);

  const openModal = (k) => setModal(k);
  useEffect(() => { window.openModal = openModal; }, []);

  return (
    <div className="shell">
      <Nav logo={t.logo} openModal={openModal} />
      <Hero />
      <Figures />
      <About />
      <Services />
      <LeyAlert onMore={() => openModal('ley')} />
      <Repository />
      <Contact />
      <Footer openModal={openModal} />

      <WhatsApp />
      <ScrollTop />
      <CustomCursor variant={t.cursor} showCoords={t.showCoords} />

      <Modal open={modal === 'privacy'} title="Política de Privacidad" mono="Versión 1.0 · Actualizada 27 may 2026 · Conforme Ley 21.719" onClose={() => setModal(null)}>
        <PrivacyContent />
      </Modal>
      <Modal open={modal === 'terms'} title="Términos y Condiciones" mono="Versión 1.0 · Actualizada 27 may 2026" onClose={() => setModal(null)}>
        <TermsContent />
      </Modal>
      <Modal open={modal === 'ley'} title="Guía Ley 21.719" mono="Entra en vigencia 1 dic 2026 · Agencia de Protección de Datos Personales" onClose={() => setModal(null)}>
        <LeyContent />
      </Modal>

      <TweaksUI t={t} setTweak={setTweak} />
    </div>
  );
}

/* ========== TWEAKS ========== */
function TweaksUI({ t, setTweak }) {
  const { TweaksPanel, TweakSection, TweakRadio, TweakColor, TweakToggle } = window;
  return (
    <TweaksPanel title="Tweaks · YALTA">
      <TweakSection label="Apariencia">
        <TweakRadio label="Paleta" value={t.theme} onChange={(v)=>setTweak('theme', v)}
          options={[{ value: 'paper', label: 'Papel' }, { value: 'sand', label: 'Arena' }, { value: 'dark', label: 'Oscuro' }]} />
        <TweakColor label="Acento" value={t.accentColor} onChange={(v)=>setTweak('accentColor', v)}
          options={['#8A3324', '#1F3A5F', '#2F6E3E', '#B45309', '#7A2E1B']} />
      </TweakSection>
      <TweakSection label="Logo">
        <TweakRadio label="Variante" value={t.logo} onChange={(v)=>setTweak('logo', v)}
          options={[{ value: 'serif', label: 'Serif' }, { value: 'sans', label: 'Sans' }, { value: 'mono', label: 'Mono' }]} />
      </TweakSection>
      <TweakSection label="Cursor">
        <TweakRadio label="Estilo" value={t.cursor} onChange={(v)=>setTweak('cursor', v)}
          options={[{ value: 'ring', label: 'Anillo' }, { value: 'crosshair', label: 'Cruceta' }, { value: 'off', label: 'Apagado' }]} />
        <TweakToggle label="Coordenadas en vivo" value={t.showCoords} onChange={(v)=>setTweak('showCoords', v)} />
      </TweakSection>
      <TweakSection label="Seguridad">
        <TweakToggle label="Bloquear copia / clic derecho" value={t.antiCopy !== false} onChange={(v)=>setTweak('antiCopy', v)} />
      </TweakSection>
    </TweaksPanel>
  );
}

/* ========== LEGAL CONTENT ========== */
function PrivacyContent() {
  return (
    <Fragment>
      <p><strong>Resumen ejecutivo.</strong> Miguel Yalta (yalta.cl) recopila únicamente los datos personales necesarios para responder consultas profesionales, gestionar la relación contractual y cumplir obligaciones legales. Los datos se almacenan en Chile, no se comercializan, y usted conserva todos los derechos ARCO+ que le otorga la Ley 21.719.</p>

      <h4>1. Responsable del Tratamiento</h4>
      <p>Miguel Ángel Yalta · Calle Prat 548, Oficina 501, Antofagasta, Chile · miguel@yalta.cl · +56 9 8827 0039 · Habilitado de Derecho, Art. 2° Inc. 1° Ley 18.120 (vigente).</p>

      <h4>2. Datos que recopilamos</h4>
      <ul>
        <li>Identificación y contacto: nombre, RUT/RUN, email, teléfono, razón social y cargo cuando aplica.</li>
        <li>Datos técnicos: IP, dispositivo, navegador, páginas consultadas (analítica anonimizada).</li>
        <li>Datos contractuales de clientes activos: información facturable, documentos del proyecto, comunicaciones.</li>
        <li>No se recopilan datos sensibles salvo que el servicio contratado lo requiera, con consentimiento expreso y DPIA previa.</li>
      </ul>

      <h4>3. Finalidades</h4>
      <p>Atención de consultas, ejecución de servicios contratados, cumplimiento legal (Ley 21.719, 19.628, 21.663, SII), facturación, comunicaciones de proyecto y seguridad de la información. No se realiza perfilamiento automatizado ni decisiones automatizadas con efectos jurídicos.</p>

      <h4>4. Base legal</h4>
      <p>Consentimiento expreso, ejecución contractual, cumplimiento de obligación legal, o interés legítimo del Responsable, conforme Art. 12 Ley 21.719.</p>

      <h4>5. Conservación</h4>
      <ul>
        <li>Consultas no contratadas: 12 meses.</li>
        <li>Clientes activos: durante toda la vigencia del servicio.</li>
        <li>Datos contables/tributarios: 6 años (normativa SII).</li>
        <li>Cookies analíticas: hasta 13 meses.</li>
      </ul>

      <h4>6. Derechos ARCO+ (Ley 21.719)</h4>
      <p>Acceso, Rectificación, Cancelación/Supresión, Oposición, Portabilidad y Bloqueo. Solicite a <strong>miguel@yalta.cl</strong> con asunto "Derechos ARCO+ — Ley 21.719" adjuntando cédula. Respuesta en plazo máximo de 15 días hábiles.</p>

      <h4>7. Transferencias</h4>
      <p>No se comercializan datos. Sólo se comparten con encargados contractualmente vinculados (cloud, email, facturación), autoridades públicas frente a requerimientos legales, y asesores profesionales con deber de secreto. Datos preferentemente alojados en Chile.</p>

      <h4>8. Cookies</h4>
      <p>Sólo cookies técnicas necesarias y analítica anonimizada (Plausible/Umami). No se usan cookies publicitarias, retargeting ni terceros con fines de marketing.</p>

      <h4>9. Seguridad</h4>
      <p>Cifrado TLS 1.3 en tránsito, control de acceso por roles, 2FA, respaldos cifrados, registro de auditoría y monitoreo de integridad. En caso de brecha, notificación a la Agencia y a los titulares en plazo máximo de 72 horas (Art. 14 quinquies Ley 21.719).</p>

      <h4>10. Menores</h4>
      <p>Servicios dirigidos a mayores de edad y personas jurídicas. No se recopilan datos de menores de 14 años (Art. 16 Ley 21.719).</p>

      <h4>11. Modificaciones</h4>
      <p>Cambios sustanciales se comunicarán con al menos 30 días de anticipación.</p>

      <h4>12. Reclamos</h4>
      <p>Puede presentar reclamo ante la Agencia de Protección de Datos Personales si considera que el tratamiento no cumple con la Ley 21.719.</p>
    </Fragment>
  );
}

function TermsContent() {
  return (
    <Fragment>
      <p><strong>Aceptación.</strong> Al contratar servicios profesionales, utilizar este sitio web, o intercambiar comunicaciones formales conmigo, usted declara haber leído, comprendido y aceptado íntegramente los presentes Términos y Condiciones.</p>

      <h4>1. Identificación del prestador</h4>
      <p>Miguel Ángel Yalta · Ingeniero en Informática (INACAP, 2013, Folio SRCeI 500673365289) · Habilitado de Derecho (Art. 2° Inc. 1° Ley 18.120, vigente) · Prat 548 Of. 501, Antofagasta · miguel@yalta.cl · +56 9 8827 0039.</p>

      <h4>2. Servicios prestados</h4>
      <ul>
        <li>Consultoría TI/OT: diseño e integración de infraestructura crítica, redes industriales, IoT/M2M.</li>
        <li>Compliance Digital: Ley 21.719, Ley 19.628, Ley 21.663, Privacy by Design.</li>
        <li>DPO externo conforme Art. 47 Ley 21.719.</li>
        <li>Peritaje informático judicial o extrajudicial.</li>
        <li>Asesoría legal informática: contratos tecnológicos, PI de software, due diligence técnico-legal.</li>
        <li>Capacitación corporativa.</li>
      </ul>

      <h4>3. Modalidades</h4>
      <p>Modalidad de trabajo definida según diagnóstico.</p>

      <h4>4. Honorarios</h4>
      <p>CLP + IVA cuando corresponda. Pago a 30 días corridos. Retraso &gt;30 días autoriza suspensión previa notificación de 7 días.</p>

      <h4>5. Obligaciones del cliente</h4>
      <p>Información veraz y oportuna, contraparte técnica designada, accesos razonables, pago oportuno. Cuando se traten datos personales de terceros, el cliente actuará como Responsable y Miguel Yalta como Encargado, suscribiendo contrato de encargo conforme Art. 15 ter Ley 21.719.</p>

      <h4>6. Obligaciones del prestador</h4>
      <p>Diligencia profesional, confidencialidad estricta, notificación de riesgos, cumplimiento de Ley 21.719 cuando actúe como Encargado, notificación de brechas en plazo máximo de 48 horas al cliente.</p>

      <h4>7. Propiedad Intelectual (Ley 17.336)</h4>
      <p>Contenido del sitio yalta.cl es propiedad exclusiva de Miguel Ángel Yalta. Reproducción no autorizada está prohibida. Documentación y diseños de proyectos: cedidos al cliente para uso interno ilimitado. Código fuente: regulado caso a caso (por defecto, licencia perpetua de uso interno). Metodologías, plantillas y know-how permanecen en propiedad del prestador.</p>

      <h4>8. Confidencialidad</h4>
      <p>Obligación recíproca por 5 años después de terminada la relación contractual.</p>

      <h4>9. Limitación de responsabilidad</h4>
      <p>No se responde por fuerza mayor, uso indebido del cliente, decisiones operacionales basadas en informes, ni pérdidas indirectas. La responsabilidad total queda limitada al monto efectivamente facturado y pagado en los 12 meses anteriores al evento, salvo dolo o culpa grave.</p>

      <h4>10. Protección de datos</h4>
      <p>Regida por la Política de Privacidad de yalta.cl y la Ley 21.719.</p>

      <h4>11. Terminación</h4>
      <p>Cualquier parte puede terminar con 30 días de aviso escrito. Incumplimiento grave permite terminación inmediata. Cliente puede solicitar portabilidad de datos (Art. 12 bis Ley 21.719).</p>

      <h4>12. Ley aplicable</h4>
      <p>Leyes de la República de Chile. Controversias: conversación directa (30 días) → mediación voluntaria → Tribunales Ordinarios de Antofagasta.</p>
    </Fragment>
  );
}

function LeyContent() {
  return (
    <Fragment>
      <p>La <strong>Ley N° 21.719</strong> regula la protección y tratamiento de datos personales en Chile y crea la Agencia de Protección de Datos Personales. Publicada el 13 de diciembre de 2024 y vigente plenamente desde el <strong>1 de diciembre de 2026</strong>. Reemplaza la Ley 19.628 (1999) y alinea Chile con el estándar GDPR.</p>

      <h4>A quién aplica</h4>
      <p>Toda persona natural o jurídica, pública o privada, que trate datos personales en Chile —incluyendo empresas extranjeras con efecto extraterritorial sobre datos de personas en Chile.</p>

      <h4>La Agencia</h4>
      <ul>
        <li>Potestad normativa: dicta reglamentos y estándares técnicos.</li>
        <li>Potestad fiscalizadora: investiga de oficio o por denuncia.</li>
        <li>Potestad sancionatoria: aplica multas y ordena suspensión de tratamientos.</li>
        <li>Registro Nacional de Sanciones de carácter público.</li>
      </ul>

      <h4>Derechos del titular (ARCO+)</h4>
      <ul>
        <li><strong>Acceso</strong> — qué datos suyos se tratan, origen, finalidad, destinatarios.</li>
        <li><strong>Rectificación</strong> — corregir datos inexactos.</li>
        <li><strong>Cancelación / Supresión</strong> — eliminar cuando no exista base legal.</li>
        <li><strong>Oposición</strong> — por motivos legítimos.</li>
        <li><strong>Portabilidad</strong> — recibir datos en formato estructurado.</li>
        <li><strong>Bloqueo</strong> — suspensión temporal mientras se resuelve solicitud.</li>
      </ul>
      <p style={{ fontFamily: 'JetBrains Mono', fontSize: 11, color: 'var(--accent)', textTransform: 'uppercase', letterSpacing: '.1em' }}>// Plazo de respuesta del Responsable: 15 días hábiles.</p>

      <h4>Obligaciones para empresas</h4>
      <ul>
        <li>Inventario de tratamientos documentado.</li>
        <li>Delegado de Protección de Datos (DPO) en organizaciones que traten datos masivos, sensibles o de menores.</li>
        <li>Evaluación de Impacto (DPIA) para tratamientos de alto riesgo.</li>
        <li>Privacy by Design y Default.</li>
        <li>Contratos de encargo con terceros.</li>
        <li>Modelo de prevención con accountability.</li>
      </ul>

      <h4>Sanciones</h4>
      <ul>
        <li>Leves: hasta 5.000 UTM (~$350M CLP).</li>
        <li>Graves: hasta 10.000 UTM (~$700M CLP).</li>
        <li>Gravísimas: hasta 20.000 UTM (~$1.400M CLP).</li>
        <li>Reincidencia: al triple o 4% de ingresos anuales.</li>
      </ul>

      <h4>Notificación de brechas</h4>
      <p>72 horas a la Agencia desde la detección · sin demora indebida a titulares afectados cuando el riesgo sea alto.</p>

      <h4>Impacto especial en minería y logística</h4>
      <p>Geolocalización continua (AVL/GPS), biometría de control de acceso, datos de salud ocupacional, productividad en faena y datos de contratistas suelen calificar como tratamientos de alto riesgo que requieren DPIA obligatoria.</p>

      <h4>Hoja de ruta 90 días</h4>
      <ul>
        <li><strong>Días 1–30 · Diagnóstico:</strong> inventario, mapeo de proveedores, gap analysis.</li>
        <li><strong>Días 31–60 · Gobernanza:</strong> designación DPO, políticas, DPIAs, contratos de encargo.</li>
        <li><strong>Días 61–90 · Operación:</strong> controles técnicos, simulaciones ARCO+ y brecha, capacitación.</li>
      </ul>
    </Fragment>
  );
}

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