// Shared primitives & styles — LIGHT BRAND THEME

const css = `
  /* ─── Sections ─── */
  section{position:relative}
  .sec{padding:96px 0;border-top:1px solid var(--line)}
  .sec-tight{padding:64px 0}
  @media (max-width:780px){.sec{padding:64px 0}.sec-tight{padding:48px 0}}

  .eyebrow{
    display:inline-flex;align-items:center;gap:8px;
    font-family:var(--font-mono);
    font-size:11px;letter-spacing:.18em;text-transform:uppercase;
    color:var(--accent);font-weight:500;
  }
  .eyebrow::before{
    content:"";width:6px;height:6px;border-radius:50%;background:var(--accent);
    box-shadow:0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent);
  }
  .eyebrow.muted{color:var(--mute)}
  .eyebrow.muted::before{background:var(--mute);box-shadow:0 0 0 4px color-mix(in srgb, var(--mute) 18%, transparent)}

  h1,h2,h3,h4{margin:0;letter-spacing:-0.025em;font-weight:700;color:var(--fg);font-family:var(--font-display)}
  h1{font-size:clamp(44px,7vw,104px);line-height:.96;font-weight:800;letter-spacing:-0.03em}
  h2{font-size:clamp(34px,5vw,64px);line-height:1.02;letter-spacing:-0.025em;font-weight:700}
  h3{font-size:clamp(20px,2vw,28px);line-height:1.15;font-weight:600;letter-spacing:-0.02em;font-family:var(--font-body)}
  p{margin:0;color:var(--fg-2);line-height:1.55}

  .lead{font-size:clamp(17px,1.45vw,21px);color:var(--fg-2);line-height:1.5;max-width:62ch}
  .em-red{color:var(--accent)}
  .em-mute{color:var(--mute)}

  .hr-line{height:1px;background:var(--line);width:100%;border:0;margin:0}

  /* ─── Buttons ─── */
  .btn{
    --bgc:var(--ink);--fgc:#fff;
    display:inline-flex;align-items:center;gap:10px;
    padding:15px 24px;border-radius:999px;border:0;cursor:pointer;
    font-size:15px;font-weight:600;letter-spacing:-0.005em;
    background:var(--bgc);color:var(--fgc);
    transition:transform .2s ease, background .2s ease, box-shadow .2s ease;
    white-space:nowrap;font-family:inherit;
  }
  .btn:hover{transform:translateY(-1px)}
  .btn.primary{--bgc:var(--accent);--fgc:#fff;
    box-shadow:0 8px 24px -6px color-mix(in srgb, var(--accent) 45%, transparent),
               inset 0 1px 0 rgba(255,255,255,.18);
  }
  .btn.primary:hover{--bgc:var(--accent-deep);
    box-shadow:0 12px 30px -8px color-mix(in srgb, var(--accent) 55%, transparent),
               inset 0 1px 0 rgba(255,255,255,.18)}
  .btn.ghost{--bgc:transparent;--fgc:var(--fg);border:1px solid var(--line-2)}
  .btn.ghost:hover{background:rgba(0,0,0,.04)}
  .ink-block .btn.ghost:hover{background:rgba(255,255,255,.06)}
  .btn.dark{--bgc:var(--ink);--fgc:#fff}
  .btn.dark:hover{--bgc:#000}
  .btn .arrow{
    display:inline-grid;place-items:center;width:18px;height:18px;border-radius:50%;
    background:rgba(255,255,255,.15);font-size:11px;transition:transform .2s ease;
  }
  .btn:hover .arrow{transform:translateX(2px)}
  .btn.ghost .arrow{background:rgba(0,0,0,.08)}
  .ink-block .btn.ghost .arrow{background:rgba(255,255,255,.1)}

  /* ─── Cards ─── */
  .card{
    background:var(--surface);
    border:1px solid var(--line);
    border-radius:var(--radius-lg);
    padding:28px;
    position:relative;
    overflow:hidden;
  }
  .card-grid{display:grid;gap:14px}

  /* ─── Pill / tag ─── */
  .pill{
    display:inline-flex;align-items:center;gap:6px;
    padding:6px 11px;border-radius:999px;
    border:1px solid var(--line-2);background:var(--surface);
    font-size:12px;color:var(--fg-2);font-weight:500;
  }
  .pill .dot{width:6px;height:6px;border-radius:50%;background:var(--accent);
    box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent);
    animation:pulse 1.6s ease-in-out infinite alternate;
  }
  @keyframes pulse{from{opacity:.7}to{opacity:1}}

  /* ─── Animations (reveal on scroll) ─── */
  .reveal{opacity:0;transform:translateY(18px);transition:opacity .8s ease, transform .8s ease}
  .reveal.in{opacity:1;transform:none}

  /* ─── Grid utility ─── */
  .row{display:grid;gap:24px}
  @media (min-width:780px){
    .row-2{grid-template-columns:repeat(2,1fr)}
    .row-3{grid-template-columns:repeat(3,1fr)}
    .row-4{grid-template-columns:repeat(4,1fr)}
  }

  .only-md{display:none}
  @media (min-width:880px){.only-md{display:flex}.hide-md{display:none}}

  /* Section with ink (dark) background — no top border (sharp transition) */
  .ink-block{background:var(--bg);color:var(--fg)}
  .ink-block.sec{border-top:0}
`;

(function injectStyles(){
  if (document.getElementById('__pcr_css')) return;
  const s = document.createElement('style');
  s.id = '__pcr_css';
  s.textContent = css;
  document.head.appendChild(s);
})();

// ─── useReveal — with fallback so content always becomes visible
function useReveal(){
  React.useEffect(() => {
    const els = document.querySelectorAll('.reveal');
    // If page is hidden or in a reduced-motion / screenshot context,
    // skip animations entirely — set final state immediately.
    const skipAnim = document.visibilityState !== 'visible'
                  || matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (skipAnim){
      els.forEach(el => {
        el.style.transition = 'none';
        el.style.opacity = '1';
        el.style.transform = 'none';
        el.classList.add('in');
      });
      return;
    }
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting){ e.target.classList.add('in'); io.unobserve(e.target); }
      });
    }, { threshold: 0.05, rootMargin: '0px 0px -40px 0px' });
    els.forEach(el => io.observe(el));
    // Fallback: after 1.4s, force-reveal anything not yet revealed.
    // Apply via inline style (overrides the transition) — survives timeline freezing.
    const tid = setTimeout(() => {
      document.querySelectorAll('.reveal:not(.in)').forEach(el => {
        el.style.transition = 'none';
        el.style.opacity = '1';
        el.style.transform = 'none';
        el.classList.add('in');
      });
    }, 1400);
    return () => { io.disconnect(); clearTimeout(tid); };
  }, []);
}

// ─── useCountUp
function useCountUp(target, { duration = 1400, decimals = 0, enabled = true } = {}){
  // If page is hidden / reduced motion, skip animation
  const skipAnim = typeof document !== 'undefined'
    && (document.visibilityState !== 'visible'
        || matchMedia('(prefers-reduced-motion: reduce)').matches);
  const initialVal = (enabled && !skipAnim) ? 0 : target;
  const [val, setVal] = React.useState(initialVal);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!enabled || skipAnim){ setVal(target); return; }
    let started = false;
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((entries) => {
      if (started) return;
      if (entries[0].isIntersecting){
        started = true;
        const start = performance.now();
        const tick = (t) => {
          const p = Math.min(1, (t - start) / duration);
          const eased = 1 - Math.pow(1 - p, 3);
          setVal(target * eased);
          if (p < 1) requestAnimationFrame(tick);
          else setVal(target);
        };
        requestAnimationFrame(tick);
      }
    }, { threshold: 0.4 });
    io.observe(el);
    // Fallback: jump to target after 2s if still not animated
    const tid = setTimeout(() => { if (!started) setVal(target); }, 2000);
    return () => { io.disconnect(); clearTimeout(tid); };
  }, [target, duration, enabled, skipAnim]);
  const display = decimals ? val.toFixed(decimals) : Math.round(val).toLocaleString('ru-RU');
  return [display, ref];
}

// ─── Arrow icon
function Arrow({ size = 12 }){
  return (
    <span className="arrow" aria-hidden="true">
      <svg width={size} height={size} viewBox="0 0 12 12" fill="none">
        <path d="M2 6h7M6 3l3 3-3 3" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
      </svg>
    </span>
  );
}

// ─── Pin
function PinIcon({ size = 16, color = "currentColor" }){
  return (
    <svg width={size} height={size} viewBox="0 0 20 20" fill="none">
      <path d="M10 18s6-5.2 6-10.2A6 6 0 1 0 4 7.8C4 12.8 10 18 10 18Z" stroke={color} strokeWidth="1.5"/>
      <circle cx="10" cy="8" r="2.2" fill={color}/>
    </svg>
  );
}

// ─── Logo — icon image + HTML text. Text color follows currentColor / parent.
function Logo({ size = 22, theme }){
  // theme: 'light' (white text) | 'dark' (black text) | undefined => auto-detect
  const ref = React.useRef(null);
  const [resolvedTheme, setResolvedTheme] = React.useState(theme || 'dark');
  React.useEffect(() => {
    if (theme) { setResolvedTheme(theme); return; }
    const el = ref.current;
    if (!el) return;
    setResolvedTheme(el.closest('.ink-block') ? 'light' : 'dark');
  }, [theme]);

  const textColor = resolvedTheme === 'light' ? '#FAFAFA' : '#1a1a1a';
  return (
    <a ref={ref} className="logo" href="#top" aria-label="ПроТочкаРоста">
      <img className="logo-mark" src="assets/logo-mark.png" alt="" aria-hidden="true"
        style={{ height: size * 1.45, width: 'auto' }}/>
      <span className="logo-text" style={{ color: textColor, fontSize: size * 0.86 }}>
        <span>Про</span><span style={{ color: '#E31E24' }}>Точка</span><span>Роста</span>
      </span>
      <style>{`
        .logo{display:inline-flex;align-items:center;gap:8px;text-decoration:none}
        .logo-mark{display:block}
        .logo-text{
          font-family:var(--font-display);
          font-weight:800;letter-spacing:-.02em;line-height:1;white-space:nowrap;
        }
      `}</style>
    </a>
  );
}

Object.assign(window, { useReveal, useCountUp, Arrow, PinIcon, Logo });
