/* Оконный Гид — shared primitives (window-scoped for multi-file Babel).
   Decoupled modal/lightbox bus: any section fires window event 'okg:open'
   with detail {type:'callback'|'measure'|'messenger'} or 'okg:lightbox'
   with detail {list, index}. The App in index.html renders the overlays. */

const { useState, useEffect, useRef } = React;

const openModal = (type, note) => window.dispatchEvent(new CustomEvent('okg:open', { detail: { type, note } }));
const openLightbox = (list, index) => window.dispatchEvent(new CustomEvent('okg:lightbox', { detail: { list, index } }));

/* ---------- Line icons (1.8px stroke, currentColor) ---------- */
const OKG_ICONS = {
  phone: 'M6.5 3.5c.4 0 .8.3.9.7l.9 2.6c.1.4 0 .8-.3 1.1L6.6 9.4a12 12 0 0 0 5 5l1.5-1.4c.3-.3.7-.4 1.1-.3l2.6.9c.4.1.7.5.7.9V18a2 2 0 0 1-2 2A14 14 0 0 1 4 6a2 2 0 0 1 2-2z',
  thermo: 'M12 4a2 2 0 0 0-2 2v7a4 4 0 1 0 4 0V6a2 2 0 0 0-2-2zm0 9.5a2 2 0 1 1 0 4 2 2 0 0 1 0-4z',
  sound: 'M4 9v6h4l5 4V5L8 9zM16.5 8.5a5 5 0 0 1 0 7M19 6a8.5 8.5 0 0 1 0 12',
  shield: 'M12 3l7 3v5c0 4.4-3 8.3-7 9.5C8 19.3 5 15.4 5 11V6zM9.5 11.5l1.8 1.8 3.4-3.6',
  leaf: 'M5 19c0-7 5-12 14-12 0 9-5 14-12 14-1 0-2-.2-2-2zm2 0c3-3 5-6 7-9',
  palette: 'M12 3a9 9 0 1 0 0 18c1.7 0 2-1.3 1.2-2.2-.8-.9-.3-2.3 1-2.3H17a4 4 0 0 0 4-4c0-4.5-4-7.5-9-7.5zM7.5 12a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z',
  ruler: 'M4 14L14 4l6 6L10 20zM8 8l2 2M11 5l2 2M5 11l2 2',
  gost: 'M12 3l2.4 4.9 5.4.8-3.9 3.8.9 5.4-4.8-2.5-4.8 2.5.9-5.4L3.2 8.7l5.4-.8z',
  truck: 'M3 6h11v9H3zM14 9h4l3 3v3h-7zM7.5 17.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm11 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z',
  clock: 'M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16zm0 4v4l3 2',
  check: 'M5 12.5l4.5 4.5L19 7.5',
  star: 'M12 4l2.4 4.9 5.4.8-3.9 3.8.9 5.4-4.8-2.5-4.8 2.5.9-5.4L3.2 9.7l5.4-.8z',
  home: 'M4 11l8-6 8 6M6 10v9h12v-9M10 19v-5h4v5',
  pin: 'M12 21s7-6 7-11a7 7 0 1 0-14 0c0 5 7 11 7 11zm0-8.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z',
  mail: 'M3 6h18v12H3zM3 7l9 6 9-6',
  chevR: 'M9 6l6 6-6 6',
  chevL: 'M15 6l-6 6 6 6',
  close: 'M6 6l12 12M18 6L6 18',
  menu: 'M4 7h16M4 12h16M4 17h16',
  arrowR: 'M5 12h14M13 6l6 6-6 6',
  frame: 'M5 4h14v16H5zM12 4v16M5 12h14',
  hammer: 'M14 6l4 4-7 7-3 1 1-3zM13 7l-7 7M4 18l2 2',
  doc: 'M7 3h7l4 4v14H7zM14 3v4h4',
  phoneOut: 'M6.5 3.5c.4 0 .8.3.9.7l.9 2.6c.1.4 0 .8-.3 1.1L6.6 9.4a12 12 0 0 0 5 5l1.5-1.4c.3-.3.7-.4 1.1-.3l2.6.9c.4.1.7.5.7.9V18a2 2 0 0 1-2 2A14 14 0 0 1 4 6a2 2 0 0 1 2-2z',
  max: 'M4 19V6l8 8 8-8v13M8 19v-6M16 19v-6',
  wa: 'M12 3a9 9 0 0 0-7.7 13.6L3 21l4.5-1.2A9 9 0 1 0 12 3zM8.5 8c.2 0 .5 0 .7.5l.7 1.6c.1.3 0 .5-.1.7l-.5.6c-.2.2-.3.4-.1.7a6 6 0 0 0 2.8 2.5c.3.1.5 0 .7-.2l.5-.6c.2-.2.4-.2.6-.1l1.6.8c.3.1.4.3.4.6 0 1-.8 1.8-1.7 1.8A8 8 0 0 1 6.7 9.7C6.7 8.8 7.5 8 8.5 8z',
  tg: 'M21 5L3 12l5 2 2 5 3-3 4 3z',
};
function Icon({ name, size = 22, stroke = 1.8, style, fill = 'none' }) {
  const d = OKG_ICONS[name];
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill} stroke="currentColor"
      strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" style={{ flex: 'none', ...style }} aria-hidden="true">
      {d ? d.split('M').filter(Boolean).map((seg, i) => <path key={i} d={'M' + seg} />) : null}
    </svg>
  );
}

// Логотип «Окна в коттедж». Две версии ассета: светлая (для тёмного фона)
// и графитовая (для светлого). height задаёт высоту знака в px.
function Logo({ tone = 'dark', height = 22 }) {
  const h = height * 2.1; // знак вертикальный (лого-квадрат), поэтому крупнее кегля
  return (
    <img
      src={tone === 'light' ? 'photos/logo-light.webp' : 'photos/logo-dark.webp'}
      alt="Окна в коттедж"
      style={{ height: h, width: 'auto', display: 'block' }}
    />
  );
}

function Button({ variant = 'primary', size = 'md', icon, iconRight, onClick, href, children, style, fullWidth, type = 'button' }) {
  const [h, setH] = useState(false);
  const pad = { sm: '9px 16px', md: '13px 24px', lg: '16px 30px' }[size];
  const fs = { sm: 14, md: 15, lg: 16 }[size];
  const pal = {
    primary: { background: h ? 'var(--action-primary-hover)' : 'var(--action-primary)', color: '#fff', border: '1px solid transparent' },
    light: { background: h ? '#f1ece5' : '#fff', color: 'var(--mk-graphite-900)', border: '1px solid #fff' },
    outline: { background: 'transparent', color: 'var(--text-strong)', border: '1px solid ' + (h ? 'var(--text-strong)' : 'var(--border-strong)') },
    outlineLight: { background: h ? 'rgba(255,255,255,.12)' : 'transparent', color: '#fff', border: '1px solid rgba(255,255,255,.5)' },
    ghost: { background: h ? 'var(--surface-fill)' : 'transparent', color: 'var(--text-strong)', border: '1px solid transparent' },
  }[variant];
  const Tag = href ? 'a' : 'button';
  return (
    <Tag href={href} type={href ? undefined : type} onClick={onClick} onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 9, width: fullWidth ? '100%' : 'auto',
        padding: pad, fontSize: fs, fontWeight: 600, lineHeight: 1.1, borderRadius: 'var(--r-md)', cursor: 'pointer',
        transform: h ? 'translateY(-1px)' : 'none', transition: 'all var(--dur) var(--ease)', textAlign: 'center', ...pal, ...style }}>
      {icon && <Icon name={icon} size={fs + 3} />}{children}{iconRight && <Icon name={iconRight} size={fs + 1} />}
    </Tag>
  );
}

/* Маска телефона: +7 (XXX) XXX-XX-XX — не более 11 цифр. */
function formatPhone(raw) {
  let d = (raw || '').replace(/\D/g, '');
  if (!d) return '';
  if (d[0] === '8') d = '7' + d.slice(1);
  if (d[0] !== '7') d = '7' + d;
  d = d.slice(0, 11);
  const p = d.slice(1);
  let out = '+7';
  if (p.length) out += ' (' + p.slice(0, 3);
  if (p.length >= 3) out += ')';
  if (p.length > 3) out += ' ' + p.slice(3, 6);
  if (p.length > 6) out += '-' + p.slice(6, 8);
  if (p.length > 8) out += '-' + p.slice(8, 10);
  return out;
}

function Field({ label, type = 'text', name, placeholder, required, tone = 'light', value, onChange }) {
  const [f, setF] = useState(false);
  const isTel = type === 'tel';
  const [tel, setTel] = useState('');
  const onDark = tone === 'dark';
  const telProps = isTel ? {
    value: value != null ? value : tel,
    inputMode: 'tel',
    autoComplete: 'tel',
    maxLength: 18,
    pattern: '\\+7 \\([0-9]{3}\\) [0-9]{3}-[0-9]{2}-[0-9]{2}',
    title: 'Формат: +7 (999) 123-45-67',
    onChange: (e) => {
      const v = formatPhone(e.target.value);
      setTel(v);
      if (onChange) { e.target.value = v; onChange(e); }
    },
  } : { value, onChange };
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      {label && <span style={{ fontSize: 13, fontWeight: 600, color: onDark ? 'rgba(255,255,255,.72)' : 'var(--text-strong)' }}>{label}{required && <span style={{ color: 'var(--okg-terra-500)' }}> *</span>}</span>}
      <input type={type} name={name} placeholder={placeholder} required={required}
        onFocus={() => setF(true)} onBlur={() => setF(false)} {...telProps}
        style={{ height: 50, padding: '0 16px', fontFamily: 'var(--font-sans)', fontSize: 16,
          color: onDark ? '#fff' : 'var(--text-body)',
          background: onDark ? 'rgba(255,255,255,.07)' : '#fff',
          border: '1px solid ' + (f ? 'var(--okg-terra-500)' : (onDark ? 'rgba(255,255,255,.22)' : 'var(--border-strong)')),
          borderRadius: 'var(--r-sm)', outline: 'none',
          boxShadow: f ? 'var(--shadow-focus)' : 'none', transition: 'border-color var(--dur), box-shadow var(--dur)' }} />
    </label>
  );
}

function Consent({ tone = 'light' }) {
  const onDark = tone === 'dark';
  const box = { marginTop: 3, width: 16, height: 16, accentColor: 'var(--okg-terra-600)', flex: 'none' };
  const txt = { fontSize: 12.5, lineHeight: 1.45, color: onDark ? 'rgba(255,255,255,.6)' : 'var(--text-muted)' };
  const lnk = { textDecoration: 'underline', color: 'inherit' };
  const row = { display: 'flex', gap: 9, alignItems: 'flex-start', cursor: 'pointer' };
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
      <label style={row}>
        <input type="checkbox" required style={box} />
        <span style={txt}>Согласен на обработку <a href="soglasie-pdn.html" target="_blank" rel="noopener" style={lnk}>персональных данных</a> и принимаю <a href="politika-konfidencialnosti.html" target="_blank" rel="noopener" style={lnk}>политику конфиденциальности</a>.</span>
      </label>
      <label style={row}>
        <input type="checkbox" required style={box} />
        <span style={txt}>Согласен на использование <a href="politika-cookie.html" target="_blank" rel="noopener" style={lnk}>файлов cookie</a>.</span>
      </label>
    </div>
  );
}

function Eyebrow({ children, tone, light }) {
  const color = light ? 'var(--okg-terra-on-dark)' : (tone === 'terra' ? 'var(--okg-terra-600)' : 'var(--text-muted)');
  return <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8, fontSize: 13, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', color }}>
    <span style={{ width: 22, height: 2, background: light ? 'var(--okg-terra-on-dark)' : 'var(--okg-terra-500)', borderRadius: 2 }} />{children}
  </span>;
}

/* Появление блоков сделано на CSS-анимации (класс .okg-rev).
   Базовое состояние — ВИДИМОЕ, поэтому контент никогда не может
   «зависнуть» невидимым — ни без JS, ни без IntersectionObserver. */
function SectionHead({ eyebrow, title, sub, center, light, style }) {
  return (
    <div className="okg-rev" style={{ display: 'flex', flexDirection: 'column', gap: 14, marginBottom: 'clamp(32px,5vw,52px)', alignItems: center ? 'center' : 'flex-start', textAlign: center ? 'center' : 'left', maxWidth: center ? 760 : 880, marginInline: center ? 'auto' : 0, ...style }}>
      {eyebrow && <Eyebrow tone="terra" light={light}>{eyebrow}</Eyebrow>}
      <h2 style={{ margin: 0, fontSize: 'clamp(28px,4vw,42px)', fontWeight: 800, letterSpacing: '-0.02em', lineHeight: 1.08, color: light ? '#fff' : 'var(--text-strong)', textWrap: 'balance' }}>{title}</h2>
      {sub && <p style={{ margin: 0, fontSize: 'clamp(15px,1.6vw,18px)', lineHeight: 1.6, color: light ? 'rgba(255,255,255,.74)' : 'var(--text-muted)', textWrap: 'pretty' }}>{sub}</p>}
    </div>
  );
}

/* Reveal — тот же принцип: видим по умолчанию, CSS добавляет плавность. */
function Reveal({ children, delay = 0, style, as = 'div' }) {
  const Tag = as;
  return <Tag className="okg-rev" style={{ animationDelay: delay ? delay + 's' : undefined, ...style }}>{children}</Tag>;
}

/* Spotlight: track cursor position as CSS vars on the hovered card */
function spotMove(e) {
  const el = e.currentTarget, r = el.getBoundingClientRect();
  el.style.setProperty('--mx', (e.clientX - r.left) + 'px');
  el.style.setProperty('--my', (e.clientY - r.top) + 'px');
}

// Лид-форма → e-mail через FormSubmit.co (без бэкенда).
// ВАЖНО: работает только на размещённом сайте (не с file://). При самой
// первой отправке FormSubmit пришлёт на почту письмо-подтверждение — надо
// один раз перейти по ссылке в нём, дальше все заявки будут приходить сразу.
const OKG_LEAD_EMAIL = 'oknavkotedj@mail.ru';
const OKG_THANKS_URL = 'spasibo.html';
async function okgSendLead(formEl, extra) {
  const fd = new FormData(formEl);
  if (extra) Object.keys(extra).forEach((k) => fd.append(k, extra[k]));
  fd.append('_subject', 'Новая заявка с сайта — Окна в коттедж');
  fd.append('_template', 'table');
  fd.append('_captcha', 'false');
  let ok = false;
  try {
    await fetch('https://formsubmit.co/ajax/' + OKG_LEAD_EMAIL, {
      method: 'POST',
      headers: { Accept: 'application/json' },
      body: fd,
    });
    ok = true;
  } catch (e) { ok = false; }
  // Переход на страницу «Спасибо». Работает при размещении на хостинге;
  // если файла рядом нет (превью, автономная сборка), остаётся встроенный
  // экран благодарности внутри формы — заявка в любом случае не теряется.
  try {
    if (location.protocol === 'http:' || location.protocol === 'https:') {
      setTimeout(() => { location.href = OKG_THANKS_URL; }, 350);
    }
  } catch (e) {}
  return ok;
}


function CookieBanner() {
  const KEY = 'okg-cookie-consent';
  const [show, setShow] = useState(() => { try { return !['accepted', 'necessary'].includes(localStorage.getItem(KEY)); } catch (e) { return true; } });
  useEffect(() => { const open = () => setShow(true); window.addEventListener('okg:cookie', open); return () => window.removeEventListener('okg:cookie', open); }, []);
  if (!show) return null;
  const decide = (v) => {
    let prev = null;
    try { prev = localStorage.getItem(KEY); localStorage.setItem(KEY, v); } catch (e) {}
    setShow(false);
    if (v === 'accepted') { window.okgLoadMetrika && window.okgLoadMetrika(); return; }
    document.cookie.split(';').map(c => c.split('=')[0].trim()).filter(n => /^_ym/.test(n)).forEach(n => {
      [location.hostname, '.' + location.hostname.replace(/^www\./, '')].forEach(d => { document.cookie = n + '=; Max-Age=0; path=/; domain=' + d; });
      document.cookie = n + '=; Max-Age=0; path=/';
    });
    if (prev === 'accepted' || window.__okgYm) location.reload();
  };
  return (
    <div role="dialog" aria-label="Использование файлов cookie" style={{ position: 'fixed', left: 16, right: 16, bottom: 'calc(var(--okg-cookie-offset, 16px) + env(safe-area-inset-bottom))', zIndex: 1000, margin: '0 auto', maxWidth: 680, background: '#fff', color: 'var(--text)', borderRadius: 16, boxShadow: '0 12px 40px rgba(0,0,0,.18)', border: '1px solid rgba(0,0,0,.08)', padding: '18px 20px', display: 'flex', flexWrap: 'wrap', gap: 14, alignItems: 'center' }}>
      <p style={{ margin: 0, flex: '1 1 300px', fontSize: 14, lineHeight: 1.5, color: 'var(--text-muted)', textWrap: 'pretty' }}>
        Мы используем необходимые cookie для работы сайта. С вашего согласия также подключим Яндекс.Метрику (ООО «ЯНДЕКС») — она собирает обезличенную статистику посещений и звонков. Подробнее — в <a href="politika-cookie.html" target="_blank" rel="noopener" style={{ color: 'var(--okg-terra-700)', textDecoration: 'underline' }}>политике cookie</a>.
      </p>
      <div style={{ display: 'flex', gap: 8, flex: '1 0 auto', flexWrap: 'wrap', justifyContent: 'flex-end', whiteSpace: 'nowrap' }}>
        <Button variant="primary" size="sm" onClick={() => decide('accepted')}>Принять</Button>
        <Button variant="outline" size="sm" onClick={() => decide('necessary')}>Только необходимые</Button>
      </div>
    </div>
  );
}

Object.assign(window, { CookieBanner, Icon, Logo, Button, Field, Consent, Eyebrow, SectionHead, Reveal, openModal, openLightbox, spotMove, okgSendLead });
