// sections.jsx — KLPARTNERS landing sections
// All exported to window so app.jsx can compose them.

const { useState, useEffect, useRef } = React;

/* 사업자등록증 기준 사업자 정보 */
const BUSINESS = {
  name: '케이엘파트너스',
  nameEn: 'KLPARTNERS',
  regNo: '653-67-00433',
  ceo: '이형준',
  address: '서울특별시 송파구 올림픽로34길 27-23, 3층 301호(방이동, One57빌딩)',
  phone: '02-2055-9224',
  phoneHref: 'tel:0220559224',
};

/* ──────────────────────────────────────────────────────────── */
/*  Animation utilities                                         */
/* ──────────────────────────────────────────────────────────── */

// Trigger when element enters viewport. Disconnects after first fire.
function useInView(options = {}) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    if (typeof IntersectionObserver === 'undefined') {
      setInView(true);
      return;
    }
    const obs = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        setInView(true);
        obs.disconnect();
      }
    }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px', ...options });
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return [ref, inView];
}

// Reveal — fades + slides element on enter.
// dir: 'up' | 'down' | 'left' | 'right' | 'fade' | 'scale'
function Reveal({ children, dir = 'up', delay = 0, as: As = 'div', className = '', style, ...rest }) {
  const [ref, inView] = useInView();
  const cls = `reveal reveal-${dir}${inView ? ' in' : ''}${className ? ' ' + className : ''}`;
  return (
    <As
      ref={ref}
      className={cls}
      style={{ transitionDelay: `${delay}ms`, ...(style || {}) }}
      {...rest}
    >
      {children}
    </As>
  );
}

// CountUp — animates from 0 to `to` when in view (or immediately if `immediate`).
function CountUp({ to, duration = 1600, format = true, decimals = 0, immediate = false }) {
  const [ref, inView] = useInView({ threshold: 0.15 });
  const active = immediate || inView;
  const [val, setVal] = useState(0);
  useEffect(() => {
    if (!active) return;
    const start = performance.now();
    let raf;
    const tick = (now) => {
      const t = Math.min(1, (now - start) / duration);
      const eased = 1 - Math.pow(1 - t, 3);
      setVal(to * eased);
      if (t < 1) raf = requestAnimationFrame(tick);
      else setVal(to);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [active, to, duration]);
  const rounded = decimals > 0 ? Number(val.toFixed(decimals)) : Math.round(val);
  const text = format ? rounded.toLocaleString('en-US') : String(rounded);
  return <span ref={ref}>{text}</span>;
}

// Typewriter — types out segmented text with optional per-segment className.
// segments: [{ text } | { text, className } | { br: true }]
function Typewriter({ segments, startDelay = 250, speed = 55, caretClassName = 'typewriter-caret' }) {
  const [progress, setProgress] = useState(0);
  const total = segments.reduce((s, seg) => s + (seg.br ? 0 : (seg.text || '').length), 0);
  const done = progress >= total;

  useEffect(() => {
    let t1, t2;
    t1 = setTimeout(() => {
      let i = 0;
      t2 = setInterval(() => {
        i += 1;
        setProgress(i);
        if (i >= total) clearInterval(t2);
      }, speed);
    }, startDelay);
    return () => { clearTimeout(t1); clearInterval(t2); };
  }, []);

  let used = 0;
  const parts = [];
  segments.forEach((seg, idx) => {
    if (seg.br) {
      if (progress >= used) parts.push(<br key={'b'+idx} />);
      return;
    }
    const remaining = Math.max(0, progress - used);
    const shown = seg.text.slice(0, remaining);
    used += seg.text.length;
    if (shown.length === 0) return;
    if (seg.className) {
      parts.push(<span key={idx} className={seg.className}>{shown}</span>);
    } else {
      parts.push(<React.Fragment key={idx}>{shown}</React.Fragment>);
    }
  });
  return (
    <span>
      {parts}
      {!done && <span className={caretClassName}></span>}
    </span>
  );
}

/* ────────────────────────────────────────────────────────────
   Nav
   ──────────────────────────────────────────────────────────── */
function Nav() {
  const [scrolled, setScrolled] = useState(false);
  const [menuOpen, setMenuOpen] = useState(false);
  const links = [
    ['소개',     '#about'],
    ['서비스',   '#services'],
    ['자금종류', '#funds'],
    ['프로세스', '#process'],
    ['실적',     '#stats'],
    ['후기',     '#testimonials'],
    ['FAQ',      '#faq'],
  ];

  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 20);
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  useEffect(() => {
    document.body.classList.toggle('is-menu-open', menuOpen);
    if (!menuOpen) return undefined;
    const onKey = (e) => {
      if (e.key === 'Escape') setMenuOpen(false);
    };
    window.addEventListener('keydown', onKey);
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.classList.remove('is-menu-open');
    };
  }, [menuOpen]);

  const closeMenu = () => setMenuOpen(false);
  const toggleMenu = () => setMenuOpen((open) => !open);

  return (
    <>
      <header className={`site-header${scrolled ? ' is-scrolled' : ''}`}>
        <div className="site-header__inner">
          <a href="#top" className="site-header__brand" onClick={closeMenu}>
            <img src="assets/logo.png" alt="KLPARTNERS" className="brand-logo" />
            <span className="site-header__brand-text">
              <span className="en">KLPARTNERS</span>
              <span className="kr">케이엘파트너스</span>
            </span>
          </a>

          <nav className="site-header__nav" aria-label="주요 메뉴">
            {links.map(([label, href]) => (
              <a key={href} href={href}>{label}</a>
            ))}
          </nav>

          <div className="site-header__actions">
            <a href={BUSINESS.phoneHref} className="site-header__phone">{BUSINESS.phone}</a>
            <a href="#contact" className="btn btn-primary site-header__cta-btn">무료 상담 신청</a>
          </div>

          <button
            type="button"
            className={`site-header__burger${menuOpen ? ' is-active' : ''}`}
            aria-label={menuOpen ? '메뉴 닫기' : '메뉴 열기'}
            aria-expanded={menuOpen}
            aria-controls="site-mobile-menu"
            onClick={toggleMenu}
          >
            <span /><span /><span />
          </button>
        </div>
      </header>

      <div
        id="site-mobile-menu"
        className={`site-mobile-menu${menuOpen ? ' is-open' : ''}`}
        aria-hidden={!menuOpen}
      >
        <button
          type="button"
          className="site-mobile-menu__backdrop"
          aria-label="메뉴 닫기"
          tabIndex={menuOpen ? 0 : -1}
          onClick={closeMenu}
        />
        <div
          className="site-mobile-menu__panel"
          role="dialog"
          aria-modal="true"
          aria-label="모바일 메뉴"
        >
          <div className="site-mobile-menu__head">
           
            <button type="button" className="site-mobile-menu__close" onClick={closeMenu}>
              닫기
            </button>
          </div>

          <nav className="site-mobile-menu__nav">
            {links.map(([label, href]) => (
              <a key={href} href={href} onClick={closeMenu}>{label}</a>
            ))}
          </nav>

          <a href="#contact" className="btn btn-primary site-mobile-menu__cta" onClick={closeMenu}>
            무료 상담 신청
          </a>

          <div className="site-mobile-menu__footer">
            <img src="assets/logo.png" alt="" className="brand-logo" />
            <span className="en">KLPARTNERS</span>
            <span className="kr">케이엘파트너스</span>
          </div>
        </div>
      </div>
    </>
  );
}

/* ────────────────────────────────────────────────────────────
   Hero
   ──────────────────────────────────────────────────────────── */
function Hero({ layout = 'split' }) {
  const cls =
    layout === 'centered' ? 'hero-grid centered' :
    layout === 'stacked'  ? 'hero-grid stacked'  :
                            'hero-grid';

  return (
    <section className="hero" id="top" data-screen-label="01 Hero">
      <div className="hero-bg" aria-hidden="true">
        <img
          src="hero-bg.webp"
          alt=""
          className="hero-bg-img"
          decoding="async"
          fetchPriority="high"
        />
      </div>
      <div className="container">
        <div className={cls}>
          <div className="hero-copy">
            <Reveal dir="fade" delay={0}>
              <div className="hero-eyebrow-wrap">
                <span className="hero-badge">
                  <span className="dot"></span>
                  정책자금 · 세무 · 정부지원금 전문
                </span>
              </div>
            </Reveal>
            <h1 className="h-display hero-h1">
              <Typewriter
                startDelay={400}
                speed={70}
                segments={[
                  { text: '복잡한 자금 절차,' },
                  { br: true },
                  { text: '대표님은 사업에만', className: 'underline' },
                  { br: true },
                  { text: '집중하세요.', className: 'accent' },
                ]}
              />
            </h1>
            <Reveal dir="up" delay={2400} className="hero-action-block">
              <p className="lede hero-lede">
                KLPARTNERS는 중소기업·소상공인 대표님의 자금 조달, 세무, 정부지원사업을
                처음 상담부터 사후관리까지 한 번에 책임지는 경영컨설팅 파트너입니다.
                필요한 건 단 한 번의 전화면 충분합니다.
              </p>
              <div className="hero-cta-row">
                <a href="#contact" className="btn btn-primary hero-btn-primary">
                  1:1 무료 상담 신청 <span className="arrow">→</span>
                </a>
                <a href="#services" className="btn btn-ghost hero-btn-secondary">
                  서비스 자세히 보기
                </a>
              </div>
            </Reveal>
            <div className="hero-meta">
              <div className="hero-meta-item">
                <span className="num">
                  <CountUp to={12} duration={1400} immediate />
                  <span className="num-suffix">년+</span>
                </span>
                <span className="label">컨설팅 경력</span>
              </div>
              <div className="hero-meta-item">
                <span className="num">
                  <CountUp to={2400} duration={2000} immediate />
                  <span className="num-suffix">건</span>
                </span>
                <span className="label">누적 컨설팅</span>
              </div>
              <div className="hero-meta-item">
                <span className="num">
                  <CountUp to={96} duration={1600} immediate />
                  <span className="num-suffix">%</span>
                </span>
                <span className="label">고객 만족도</span>
              </div>
            </div>
          </div>

          <Reveal as="div" dir="right" delay={400} className="hero-art">
            <div className="stock">
              <span className="stock-label">대표 컨설팅 사진 · 800×1000</span>
            </div>
            <div className="hero-art-floating fl-1">
              <span style={{fontFamily:'var(--f-mono)',fontSize:'10.5px',letterSpacing:'0.14em',color:'var(--ink-mute)',textTransform:'uppercase'}}>
                이번 달 승인
              </span>
              <span style={{fontFamily:'var(--f-display)',fontSize:'26px',fontWeight:600,color:'var(--ink)',letterSpacing:'-0.01em'}}>
                ₩ <CountUp to={38} duration={1600} />억 +
              </span>
            </div>
            <div className="hero-art-floating fl-2">
              <div className="ic">★</div>
              <div style={{display:'flex',flexDirection:'column',lineHeight:1.2}}>
                <span style={{fontSize:'12.5px',color:'var(--ink-mute)'}}>고객 후기 평점</span>
                <span style={{fontFamily:'var(--f-display)',fontSize:'18px',fontWeight:600,color:'var(--ink)'}}>4.9 / 5.0</span>
              </div>
            </div>
          </Reveal>
        </div>
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   About / Strengths
   ──────────────────────────────────────────────────────────── */
function About() {
  const strengths = [
    {
      n: '01',
      title: '전담 컨설턴트 1:1 매칭',
      body: '대표님 사업 단계와 업종에 맞는 전담 컨설턴트가 처음부터 끝까지 직접 상담합니다. 매번 담당자가 바뀌는 일이 없습니다.',
    },
    {
      n: '02',
      title: '정책자금 · 세무 · 인증 통합',
      body: '자금만, 세무만 따로 보지 않습니다. 기업 재무상태와 인증 현황까지 통합 분석해 최적의 조합을 설계합니다.',
    },
    {
      n: '03',
      title: '신청 → 승인 → 사후관리',
      body: '서류 작성, 기관 응대, 승인 후 자금 집행과 의무사항 관리까지. 한 번의 계약으로 전 과정이 끝납니다.',
    },
    {
      n: '04',
      title: '정직한 사전 진단',
      body: '되지 않을 일을 되는 것처럼 말하지 않습니다. 무료 진단에서 가능성과 한계를 모두 솔직하게 설명합니다.',
    },
  ];

  return (
    <section className="about section" id="about" data-screen-label="02 About">
      <div className="container">
        <div className="about-grid">
          <Reveal dir="left">
            <span className="eyebrow">ABOUT US</span>
            <h2 className="h-section" style={{marginTop:'14px'}}>
              사업의 길목마다<br/>곁에 있는 파트너.
            </h2>
          </Reveal>
          <Reveal dir="right" delay={120}>
            <p className="lede">
              KLPARTNERS는 정책자금·세무·정부지원금 분야에서 12년간 2,400여 건의 컨설팅을
              수행해 온 전문가 그룹입니다. 자금 조달이 처음인 소상공인부터,
              R&D 지원·기업인증·법인 전환을 동시에 준비하는 성장 기업까지 —
              규모와 단계에 맞는 솔루션을 함께 설계합니다.
            </p>
            <p className="lede" style={{marginTop:'20px'}}>
              저희가 가장 신경 쓰는 것은 "맞는 일"과 "안 맞는 일"을 솔직하게 알려드리는
              것입니다. 무리한 신청으로 시간과 신뢰를 잃지 않도록, 정확한 진단부터 시작합니다.
            </p>

            <div className="strengths">
              {strengths.map((s, i) => (
                <Reveal as="div" key={s.n} dir="up" delay={i * 100} className="strength">
                  <span className="strength-num">{s.n}</span>
                  <h3>{s.title}</h3>
                  <p>{s.body}</p>
                </Reveal>
              ))}
            </div>
          </Reveal>
        </div>
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Services
   ──────────────────────────────────────────────────────────── */
function Services() {
  const services = [
    {
      glyph: '₩',
      title: '정책자금',
      desc: '중소벤처기업진흥공단, 소상공인시장진흥공단, 신용보증재단 등 정부·공공기관의 저리 정책자금을 진단부터 실행까지 함께합니다.',
      features: [
        '중소기업 운전·시설자금',
        '소상공인 일반·특별경영안정자금',
        '신용·기술 보증서 발급',
        '재도전·재창업 자금',
      ],
    },
    {
      glyph: '§',
      title: '세무·회계',
      desc: '기장·신고만 하는 세무가 아니라, 절세 시나리오를 함께 설계하는 세무 파트너십. 대표님의 의사결정에 세무가 걸림돌이 되지 않도록 합니다.',
      features: [
        '월 기장 및 부가세·종합소득세 신고',
        '법인세 신고 및 세무조정',
        '절세 컨설팅 / 세무조사 대응',
        '가지급금·가수금 정리',
      ],
    },
    {
      glyph: '+',
      title: '정부지원금 / R&D',
      desc: '연구개발·고용·디지털 전환 등 정부 지원사업을 대표님의 사업계획과 매칭하고, 사업계획서 설계부터 평가 대응까지 전 과정을 지원합니다.',
      features: [
        'R&D 과제 기획 및 사업계획서',
        '고용 지원금 (청년·장년·신중년)',
        '스마트공장 / 디지털 전환',
        '수출바우처 · 마케팅 지원',
      ],
    },
    {
      glyph: '✓',
      title: '기업인증',
      desc: '벤처기업, 이노비즈, 메인비즈, 기술혁신형·경영혁신형 인증을 통해 정책자금 한도 확대와 세제 혜택을 함께 확보합니다.',
      features: [
        '벤처기업 / 이노비즈 / 메인비즈',
        '기업부설연구소 · 연구개발전담부서',
        'ISO · 가족친화 · 여성기업',
        'NET / NEP 신기술 인증',
      ],
    },
    {
      glyph: '◎',
      title: '재무·회계 컨설팅',
      desc: '재무제표를 단순한 결과지가 아닌, 자금 조달과 세무 전략의 출발점으로 다듬습니다. 결산 전 사전 컨설팅을 권합니다.',
      features: [
        '재무비율 진단 및 개선 설계',
        '결산 전 사전 컨설팅',
        '자금 흐름 / 운전자본 분석',
        '신용평가등급 관리',
      ],
    },
    {
      glyph: '⌂',
      title: '법인설립 · 전환 / 경영진단',
      desc: '개인사업자에서 법인으로의 전환 시점, 지분 구조, 사업계획 수립까지 — 회사의 다음 단계를 함께 설계합니다.',
      features: [
        '법인설립 / 개인 → 법인 전환',
        '지분 구조 및 가지급금 정리',
        '사업계획서 작성',
        '경영 진단 및 성장 전략',
      ],
    },
  ];

  return (
    <section className="services section section--photo" id="services" data-screen-label="03 Services">
      <div className="container">
        <Reveal as="div" dir="up" className="section-head">
          <span className="eyebrow">OUR SERVICES</span>
          <h2 className="h-section">대표님 사업에 필요한,<br/>딱 그만큼의 컨설팅.</h2>
          <p className="lede">
            한 가지만 잘하는 곳이 아니라, 자금·세무·인증·지원금을 하나로 묶어
            서로 맞물리도록 설계합니다. 필요한 서비스만 골라 받으셔도 좋습니다.
          </p>
        </Reveal>

        <div className="services-grid">
          {services.map((s, i) => (
            <Reveal as="article" key={i} dir="up" delay={(i % 3) * 110} className="service-card">
              <div className="ic-wrap">{s.glyph}</div>
              <h3>{s.title}</h3>
              <p className="desc">{s.desc}</p>
              <ul className="features">
                {s.features.map((f, j) => <li key={j}>{f}</li>)}
              </ul>
              <a className="more" href="#contact">상담 받기 <span>→</span></a>
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Funds list
   ──────────────────────────────────────────────────────────── */
function Funds() {
  const funds = [
    { tag: '운전자금', name: '중소기업 정책자금 (중진공)', sub: '신성장기반·혁신성장지원 등', amt: '최대 100억' },
    { tag: '운전자금', name: '소상공인 일반경영안정자금',     sub: '소진공 · 저신용 포함',          amt: '최대 7천만' },
    { tag: '시설자금', name: '시설투자 자금 (중진공)',         sub: '설비·공장·연구장비',           amt: '최대 60억' },
    { tag: '보증서',   name: '기술보증기금 보증서',             sub: '기술평가 기반 보증',          amt: '최대 100억' },
    { tag: '보증서',   name: '신용보증기금 / 지역신보',         sub: '신용평가 기반 보증',          amt: '최대 30억' },
    { tag: 'R&D',     name: '중소기업 기술개발사업',           sub: '창업성장·산학연·전략형',        amt: '최대 6억' },
    { tag: 'R&D',     name: '소부장·뿌리기업 R&D',              sub: '소재·부품·장비 분야',          amt: '최대 12억' },
    { tag: '고용',     name: '청년·장년 고용지원금',            sub: '신규 채용 기업 대상',          amt: '최대 1천 / 1인' },
    { tag: '수출',     name: '수출바우처 / 해외마케팅',          sub: '바우처 지원 패키지',           amt: '최대 1억' },
    { tag: '스마트',   name: '스마트공장 보급 사업',             sub: '기초·고도화 단계별',           amt: '최대 4억' },
    { tag: '재창업',   name: '재도전·재창업 자금',               sub: '폐업 후 재시작 대표',          amt: '최대 5억' },
    { tag: '특별',     name: '재해·위기지역 특별자금',           sub: '재해·고용위기 지정 시',        amt: '최대 10억' },
  ];

  return (
    <section className="funds section section--photo" id="funds" data-screen-label="04 Funds">
      <div className="container">
        <Reveal as="div" dir="up" className="section-head">
          <span className="eyebrow">AVAILABLE FUNDS</span>
          <h2 className="h-section">우리 회사가 받을 수 있는<br/>자금, 한눈에.</h2>
          <p className="lede">
            대표적인 자금만 정리했습니다. 업력·매출·인증·업종에 따라 한도와 금리가
            달라지며, 정확한 가능 금액은 무료 진단에서 확인해 드립니다.
          </p>
        </Reveal>

        <div className="funds-wrap">
          {funds.map((f, i) => (
            <Reveal as="div" key={i} dir={i % 2 === 0 ? 'left' : 'right'} delay={(i % 4) * 60} className="fund-row">
              <span className="tag">{f.tag}</span>
              <div className="name">
                {f.name}
                <span className="sub">{f.sub}</span>
              </div>
              <span className="amt">{f.amt}</span>
            </Reveal>
          ))}
        </div>

        <div style={{marginTop:'32px',display:'flex',gap:'12px',alignItems:'center',flexWrap:'wrap'}}>
          <span style={{fontSize:'13px',color:'var(--ink-mute)',fontFamily:'var(--f-mono)',letterSpacing:'0.06em'}}>
            * 표시 금액은 일반 최대 한도 기준이며, 실제 가능 금액은 진단 후 확인 가능합니다.
          </span>
        </div>
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Process
   ──────────────────────────────────────────────────────────── */
function Process() {
  const steps = [
    { tag: 'STEP 01', title: '1:1 무료 상담', body: '전화 또는 방문 상담으로 사업 현황과 필요한 자금·세무 이슈를 정확히 파악합니다.' },
    { tag: 'STEP 02', title: '진단 · 전략 설계',   body: '재무·인증·업종 데이터를 기반으로 어떤 자금이 가능한지, 어떤 순서로 진행할지를 설계합니다.' },
    { tag: 'STEP 03', title: '신청 · 서류 작성',   body: '사업계획서·재무자료·기관 요구 서류를 컨설턴트가 직접 준비해 신청까지 책임집니다.' },
    { tag: 'STEP 04', title: '승인 · 사후관리',    body: '자금 집행 후 의무사항, 세무 신고, 다음 자금 사이클까지 — 끊김 없이 관리합니다.' },
  ];
  return (
    <section className="process section" id="process" data-screen-label="05 Process">
      <div className="container">
        <Reveal as="div" dir="up" className="section-head" style={{maxWidth:'820px'}}>
          <span className="eyebrow">HOW IT WORKS</span>
          <h2 className="h-section">단순하지만,<br/>꼼꼼한 네 단계.</h2>
          <p className="lede">
            대표님은 사업을, 우리는 절차를. 상담 신청부터 사후관리까지
            한 명의 전담 컨설턴트가 처음과 끝을 함께합니다.
          </p>
        </Reveal>

        <div className="process-grid">
          {steps.map((s, i) => (
            <Reveal as="div" key={i} dir="up" delay={i * 140} className="process-step">
              <div className="num-wrap">{String(i+1).padStart(2,'0')}</div>
              <span className="step-tag">{s.tag}</span>
              <h4>{s.title}</h4>
              <p>{s.body}</p>
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Stats
   ──────────────────────────────────────────────────────────── */
function Stats() {
  const stats = [
    { n: 12,    unit: '년+',  label: 'EXPERIENCE',  note: '컨설팅 업력' },
    { n: 2400,  unit: '건',   label: 'PROJECTS',    note: '누적 컨설팅 수행' },
    { n: 1820,  unit: '억',   label: 'FUNDING',     note: '누적 자금 조달액' },
    { n: 96,    unit: '%',    label: 'SATISFACTION',note: '재이용 의향 응답' },
  ];
  return (
    <section className="stats section" id="stats" data-screen-label="06 Stats">
      <div className="container">
        <Reveal as="div" dir="up" className="section-head" style={{maxWidth:'820px'}}>
          <span className="eyebrow">BY THE NUMBERS</span>
          <h2 className="h-section">숫자로 보는 KLPARTNERS</h2>
          <p className="lede">
            지난 12년 동안 함께한 대표님들과 만들어 온 결과입니다.
            모든 수치는 자체 집계 기준 누적치입니다.
          </p>
        </Reveal>

        <div className="stats-grid">
          {stats.map((s,i) => (
            <Reveal as="div" key={i} dir="up" delay={i * 120} className="stat">
              <span className="label">{s.label}</span>
              <span className="value">
                <CountUp to={s.n} duration={1800} />
                <span className="unit">{s.unit}</span>
              </span>
              <span className="note">{s.note}</span>
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Testimonials
   ──────────────────────────────────────────────────────────── */
function TestimonialStars({ rating = 5 }) {
  return (
    <span className="review-stars" aria-label={`${rating}점`}>
      {[1, 2, 3, 4, 5].map((n) => (
        <span key={n} className={n <= rating ? 'on' : 'off'}>★</span>
      ))}
    </span>
  );
}

function TestimonialCard({ item }) {
  return (
    <figure className="testimonial-card">
      <div className="testimonial-card__top">
        <TestimonialStars rating={item.rating} />
        <time className="testimonial-card__date" dateTime={item.dateIso}>{item.date}</time>
      </div>
      <span className="testimonial-card__badge">상담 완료 고객</span>
      <span className="testimonial-card__tag">{item.tag}</span>
      <blockquote className="testimonial-card__body">{item.body}</blockquote>
      <figcaption className="testimonial-card__meta">
        <span className="testimonial-card__avatar" aria-hidden="true">{item.init}</span>
        <span className="testimonial-card__who">
          <span className="name">{item.name}</span>
          <span className="role">{item.role}</span>
        </span>
      </figcaption>
    </figure>
  );
}

function Testimonials() {
  const items = [
    {
      body: '거래은행에서 안 된다고 했던 시설자금이, 진단 받고 보증기금 쪽으로 다시 짰더니 통과됐어요. 어디가 막혔는지 딱 짚어주셔서 "아 이렇게 가는 거구나" 싶었습니다.',
      name: '김○○ 대표',
      role: '제조업 · 경기 화성 · 매출 38억',
      tag: '시설자금',
      init: '김',
      rating: 5,
      date: '2025.11.08',
      dateIso: '2025-11-08',
    },
    {
      body: '기장만 하던 세무사에서 옮기기 전에 시뮬레이션 먼저 해주셔서 결정했어요. 작년 종소세가 생각보다 많이 줄었고, 결산 전에 미리 연락 오는 게 제일 편합니다.',
      name: '이○○ 대표',
      role: '도소매 · 서울 강서 · 매출 12억',
      tag: '세무·절세',
      init: '이',
      rating: 5,
      date: '2025.10.22',
      dateIso: '2025-10-22',
    },
    {
      body: '벤처인증이랑 R&D를 동시에 알아보다가 여기저기 말이 달라서 혼란스러웠는데, 한 번에 로드맵 잡아주셔서 순서대로 진행했습니다. 담당자분이 끝까지 챙겨주신 느낌이에요.',
      name: '박○○ 대표',
      role: 'IT서비스 · 판교 · 직원 18명',
      tag: 'R&D · 인증',
      init: '박',
      rating: 5,
      date: '2025.09.14',
      dateIso: '2025-09-14',
    },
    {
      body: '창업 8개월 차라 가능할지 몰랐는데, 소상공인 대출이랑 지원금 같이 챙겨주셨어요. 서류 뭐부터 준비할지 체크리스트 주셔서 밤에 혼자 헤매지 않았습니다 ㅎㅎ',
      name: '최○○ 대표',
      role: '카페 · 부산 해운대 · 직원 4명',
      tag: '창업 초기',
      init: '최',
      rating: 5,
      date: '2025.08.03',
      dateIso: '2025-08-03',
    },
    {
      body: '인건비 부담 때문에 고민이었는데, 고용지원금이랑 두루누리 같이 보면서 신청했습니다. "이건 안 됩니다" 하고 솔직히 말해주셔서 오히려 믿음이 갔어요.',
      name: '정○○ 대표',
      role: '요식업 · 대구 수성',
      tag: '정부지원금',
      init: '정',
      rating: 5,
      date: '2025.07.19',
      dateIso: '2025-07-19',
    },
    {
      body: '메인비즈 인증 때문에 막막했는데, 서류 쓰는 톤까지 잡아주셔서 심사 통과했습니다. 직원이 적은 회사라 더 도움 많이 받은 것 같아요.',
      name: '한○○ 대표',
      role: '디자인 · 서울 마포 · 직원 7명',
      tag: '기업인증',
      init: '한',
      rating: 5,
      date: '2025.06.27',
      dateIso: '2025-06-27',
    },
    {
      body: '첫 상담은 전화 20분이었는데, 가능한 자금이랑 안 되는 이유를 나눠서 설명해주셔서 부담이 덜했습니다. 이후 카톡으로도 진행 상황 공유해 주셔서 좋았습니다.',
      name: '윤○○ 대표',
      role: '도매 · 인천 부평',
      tag: '정책자금',
      init: '윤',
      rating: 5,
      date: '2025.05.11',
      dateIso: '2025-05-11',
    },
    {
      body: '법인 전환 시기랑 세무 영향을 같이 봐주셔서 타이밍 맞춰 진행했어요. 회계사 사무실이랑도 연결해 주셔서 따로 설명 안 해도 됐습니다.',
      name: '조○○ 대표',
      role: '건설자재 · 경기 성남 · 매출 21억',
      tag: '법인전환',
      init: '조',
      rating: 5,
      date: '2025.04.02',
      dateIso: '2025-04-02',
    },
    {
      body: '급하게 운전자금 필요했는데, 주말에도 답장 주셔서 월요일에 바로 접수했습니다. 승인까지 5주 정도 걸렸고, 중간에 서류 보완도 빠르게 도와주셨어요.',
      name: '송○○ 대표',
      role: '물류 · 김포 · 차량 6대',
      tag: '운전자금',
      init: '송',
      rating: 5,
      date: '2025.03.16',
      dateIso: '2025-03-16',
    },
  ];

  const sectionRef = useRef(null);
  const viewportRef = useRef(null);
  const [active, setActive] = useState(0);
  const pausedRef = useRef(false);
  const visibleRef = useRef(true);

  useEffect(() => {
    const el = sectionRef.current;
    if (!el || typeof IntersectionObserver === 'undefined') return undefined;
    const obs = new IntersectionObserver(([entry]) => {
      visibleRef.current = entry.isIntersecting;
    }, { threshold: 0.12, rootMargin: '0px 0px -5% 0px' });
    obs.observe(el);
    return () => obs.disconnect();
  }, []);

  const scrollToIndex = (idx) => {
    const viewport = viewportRef.current;
    if (!viewport) return;
    const card = viewport.querySelector('.testimonial-card');
    if (!card) return;
    const gap = 20;
    const step = card.offsetWidth + gap;
    viewport.scrollTo({ left: step * idx, behavior: 'smooth' });
    setActive(idx);
  };

  useEffect(() => {
    const viewport = viewportRef.current;
    if (!viewport) return undefined;

    const tick = () => {
      if (pausedRef.current || !visibleRef.current) return;
      const card = viewport.querySelector('.testimonial-card');
      if (!card) return;
      const gap = 20;
      const step = card.offsetWidth + gap;
      const maxScroll = viewport.scrollWidth - viewport.clientWidth;
      if (viewport.scrollLeft >= maxScroll - 4) {
        viewport.scrollTo({ left: 0, behavior: 'smooth' });
        setActive(0);
      } else {
        viewport.scrollBy({ left: step, behavior: 'smooth' });
        setActive((i) => Math.min(i + 1, items.length - 1));
      }
    };

    const timer = setInterval(tick, 4200);
    return () => clearInterval(timer);
  }, [items.length]);

  useEffect(() => {
    const viewport = viewportRef.current;
    if (!viewport) return undefined;

    const onScroll = () => {
      const card = viewport.querySelector('.testimonial-card');
      if (!card) return;
      const gap = 20;
      const step = card.offsetWidth + gap;
      const idx = Math.round(viewport.scrollLeft / step);
      setActive(Math.max(0, Math.min(idx, items.length - 1)));
    };

    viewport.addEventListener('scroll', onScroll, { passive: true });
    return () => viewport.removeEventListener('scroll', onScroll);
  }, [items.length]);

  return (
    <section ref={sectionRef} className="testimonials section" id="testimonials" data-screen-label="07 Testimonials">
      <div className="container">
        <Reveal as="div" dir="up" className="section-head" style={{maxWidth:'820px'}}>
          <span className="eyebrow">CLIENT STORIES</span>
          <h2 className="h-section">대표님들이 직접 남긴 말</h2>
          <p className="lede">
            실제 상담을 진행하신 대표님들의 후기입니다. (개인정보 보호를 위해 일부 표기는 비공개 처리했습니다.)
          </p>
        </Reveal>

        <Reveal as="div" dir="up" delay={120} className="testimonials-slider">
          <p className="testimonials-slider__hint">← 좌우로 넘겨 더 많은 후기 보기 →</p>
          <div
            className="testimonials-slider__viewport"
            ref={viewportRef}
            onMouseEnter={() => { pausedRef.current = true; }}
            onMouseLeave={() => { pausedRef.current = false; }}
            onTouchStart={() => { pausedRef.current = true; }}
            onTouchEnd={() => { pausedRef.current = false; }}
          >
            <div className="testimonials-slider__track">
              {items.map((t, i) => (
                <TestimonialCard key={i} item={t} />
              ))}
            </div>
          </div>

          <div className="testimonials-slider__dots" role="tablist" aria-label="후기 슬라이드">
            {items.map((_, i) => (
              <button
                key={i}
                type="button"
                role="tab"
                aria-selected={active === i}
                aria-label={`후기 ${i + 1}`}
                className={`testimonials-slider__dot${active === i ? ' is-active' : ''}`}
                onClick={() => scrollToIndex(i)}
              />
            ))}
          </div>
        </Reveal>
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   FAQ
   ──────────────────────────────────────────────────────────── */
function FAQ() {
  const items = [
    {
      q: '상담은 정말로 무료인가요?',
      a: '네, 처음 진단 상담은 무료입니다. 사업 현황과 가능 자금/지원사업을 짚어드린 뒤, 컨설팅이 필요하다고 판단되는 부분만 별도 안내드립니다. 상담 후 진행 여부는 대표님이 자유롭게 결정하시면 됩니다.',
    },
    {
      q: '업력이 짧거나 매출이 작아도 정책자금이 가능한가요?',
      a: '가능합니다. 창업 1년 미만 기업이나 소상공인 대상의 자금이 별도로 운영되며, 매출보다 사업성·신용·기술력을 함께 보는 자금도 많습니다. 진단을 통해 가장 맞는 트랙을 안내해 드립니다.',
    },
    {
      q: '거래 세무사 / 회계사가 따로 있어도 컨설팅을 받을 수 있나요?',
      a: '네. 자금·인증·R&D 컨설팅만 별도로 진행하시는 대표님이 많습니다. 필요한 경우 기존 세무대리인과 협업하며, 세무 컨설팅 자체를 옮기실 의향이 있을 때만 변경을 진행합니다.',
    },
    {
      q: '정책자금이나 지원금 신청에 얼마나 시간이 걸리나요?',
      a: '자금별로 다릅니다. 운전자금은 평균 4~6주, 시설자금/R&D는 평균 8~12주 정도가 소요됩니다. 진단 후 일정과 마일스톤을 미리 공유해 드리므로 사업 일정에 맞춰 준비하실 수 있습니다.',
    },
    {
      q: '컨설팅 비용은 어떻게 책정되나요?',
      a: '서비스에 따라 정액제와 성공보수형이 있으며, 처음부터 명확하게 공개합니다. 진행 도중 추가 비용을 임의로 청구하지 않으며, 계약서에 모든 항목이 사전 명시됩니다.',
    },
    {
      q: '한 번의 컨설팅으로 끝인가요, 계속 관리해 주시나요?',
      a: '자금 집행 이후가 더 중요합니다. 사후 의무사항, 차년도 자금 사이클, 인증 갱신, 세무 연동 부분까지 지속 관리해 드리며, 이를 위해 전담 컨설턴트가 계속 매칭됩니다.',
    },
  ];

  const [open, setOpen] = useState(0);

  return (
    <section className="faq section" id="faq" data-screen-label="08 FAQ">
      <div className="container">
        <Reveal as="div" dir="up" className="section-head" style={{maxWidth:'820px',textAlign:'center',marginLeft:'auto',marginRight:'auto'}}>
          <span className="eyebrow" style={{justifyContent:'center'}}>F.A.Q</span>
          <h2 className="h-section">자주 묻는 질문</h2>
          <p className="lede" style={{marginLeft:'auto',marginRight:'auto'}}>
            상담 전에 가장 많이 받는 질문을 모았습니다. 더 궁금한 점은
            언제든 1:1 상담을 통해 편하게 물어보세요.
          </p>
        </Reveal>

        <div className="faq-list">
          {items.map((it, i) => (
            <Reveal as="div" key={i} dir="up" delay={i * 60} className={`faq-item ${open === i ? 'open' : ''}`}>
              <button className="faq-q" onClick={() => setOpen(open === i ? -1 : i)}>
                <span className="q-mark">Q.</span>
                <span className="q-text">{it.q}</span>
                <span className="toggle">+</span>
              </button>
              <div className="faq-a">
                <p>{it.a}</p>
              </div>
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Contact
   ──────────────────────────────────────────────────────────── */
function Contact() {
  const [submitted, setSubmitted] = useState(false);
  const onSubmit = (e) => {
    e.preventDefault();
    setSubmitted(true);
    setTimeout(() => setSubmitted(false), 4000);
  };

  return (
    <section className="contact section section--photo" id="contact" data-screen-label="09 Contact">
      <div className="container">
        <div className="contact-grid">
          <Reveal as="div" dir="up" className="contact-info">
            <span className="eyebrow">FREE CONSULTATION</span>
            <h2 className="h-section" style={{marginTop:'14px'}}>
              우선,<br/>편하게 말 한 번<br/>건네 보세요.
            </h2>
            <p className="lede" style={{marginTop:'20px'}}>
              간단한 정보만 남겨 주시면, 영업일 기준 24시간 내에
              전담 컨설턴트가 직접 연락드립니다. 무료 진단부터 시작합니다.
            </p>

            <div className="contact-info-list">
              <div className="contact-info-item">
                <span className="k">PHONE</span>
                <span className="v">
                  <a href={BUSINESS.phoneHref}>{BUSINESS.phone}</a>
                  <span className="small">평일 09:00 – 18:00 · 점심시간 12:30 – 13:30</span>
                </span>
              </div>
              <div className="contact-info-item">
                <span className="k">EMAIL</span>
                <span className="v">contact@klpartners.co.kr<span className="small">24시간 접수 · 영업일 기준 회신</span></span>
              </div>
              <div className="contact-info-item">
                <span className="k">KAKAO</span>
                <span className="v">@klpartners<span className="small">친구추가 후 상담 메시지 남겨주세요</span></span>
              </div>
              <div className="contact-info-item" style={{borderBottom:'none'}}>
                <span className="k">OFFICE</span>
                <span className="v">
                  {BUSINESS.address}
                  <span className="small">방이동 One57빌딩 · 방문 상담 시 사전 연락 부탁드립니다</span>
                </span>
              </div>
            </div>
          </Reveal>

          <Reveal as="form" dir="up" delay={100} className="contact-form" onSubmit={onSubmit}>
            <h3 className="form-title">상담 신청</h3>
            <p className="form-sub">업체명, 대표자명, 연락처를 입력해 주시면 전담 컨설턴트가 연락드립니다.</p>

            <div className="form-field">
              <label htmlFor="contact-company">업체명 *</label>
              <input id="contact-company" name="company" type="text" required placeholder="(주)○○○○" />
            </div>

            <div className="form-field">
              <label htmlFor="contact-ceo">대표자명 *</label>
              <input id="contact-ceo" name="ceo" type="text" required placeholder="홍길동" />
            </div>

            <div className="form-field">
              <label htmlFor="contact-phone">연락처 *</label>
              <input id="contact-phone" name="phone" type="tel" required placeholder="010-0000-0000" />
            </div>

            <div className="form-consent-list">
              <label className="form-consent">
                <input type="checkbox" name="privacyAgree" required />
                <span>
                  <strong>개인정보 수집 및 이용</strong>에 동의합니다. (필수)
                  <span className="form-consent-detail">
                    수집 항목: 업체명, 대표자명, 연락처 / 이용 목적: 상담 접수 및 회신 / 보유 기간: 상담 종료 후 1년
                  </span>
                  <a href="#">전문 보기</a>
                </span>
              </label>
              <label className="form-consent">
                <input type="checkbox" name="termsAgree" required />
                <span>
                  <strong>이용 동의</strong>에 동의합니다. (필수)
                  <span className="form-consent-detail">
                    서비스 이용약관 및 상담 안내에 동의합니다.
                  </span>
                  <a href="#">이용약관 보기</a>
                </span>
              </label>
            </div>

            <button className="form-submit" type="submit">
              {submitted ? '✓ 상담 신청이 접수되었습니다 — 24시간 내 연락드릴게요' : '상담 신청하기 →'}
            </button>
          </Reveal>
        </div>
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Footer
   ──────────────────────────────────────────────────────────── */
function Footer() {
  return (
    <footer className="footer" data-screen-label="10 Footer">
      <div className="container">
        <div className="footer-top">
          <div className="footer-brand">
            <div className="footer-logo">
              <img src="assets/logo.png" alt="KLPARTNERS" className="brand-logo" />
              <div>
                <div className="en">{BUSINESS.nameEn}</div>
                <span className="kr">{BUSINESS.name}</span>
              </div>
            </div>
            <p>
              중소기업·소상공인 대표님의 자금 조달과 세무, 정부지원사업을
              한 자리에서 책임지는 경영컨설팅 파트너.
              사업의 모든 길목에서 곁에 있겠습니다.
            </p>
            <div className="footer-contact">
              <span>
                <strong>대표전화</strong>
                <a href={BUSINESS.phoneHref}>{BUSINESS.phone}</a>
              </span>
              <span>
                <strong>이메일</strong>
                <a href="mailto:contact@klpartners.co.kr">contact@klpartners.co.kr</a>
              </span>
              <span>
                <strong>주소</strong>
                <span>{BUSINESS.address}</span>
              </span>
            </div>
          </div>
        </div>

        <div className="footer-business" id="business-info">
          <h3 className="footer-business-title">사업자 정보</h3>
          <dl className="footer-biz-list">
            <div className="footer-biz-row">
              <dt>상호</dt>
              <dd>{BUSINESS.name}</dd>
            </div>
            <div className="footer-biz-row">
              <dt>대표자</dt>
              <dd>{BUSINESS.ceo}</dd>
            </div>
            <div className="footer-biz-row">
              <dt>사업자등록번호</dt>
              <dd>{BUSINESS.regNo}</dd>
            </div>
            <div className="footer-biz-row">
              <dt>사업장 소재지</dt>
              <dd>{BUSINESS.address}</dd>
            </div>
            <div className="footer-biz-row">
              <dt>연락처</dt>
              <dd><a href={BUSINESS.phoneHref}>{BUSINESS.phone}</a></dd>
            </div>
          </dl>
        </div>

        <div className="footer-bottom">
          <div className="footer-bottom-copy">
            <span>© 2026 {BUSINESS.nameEn} · {BUSINESS.name}. All rights reserved.</span>
            <span className="footer-bottom-biz">
              {BUSINESS.name} · 대표 {BUSINESS.ceo} · 사업자등록번호 {BUSINESS.regNo} · {BUSINESS.phone}
            </span>
          </div>
          <div className="legal">
            <a href="#">개인정보처리방침</a>
            <a href="#">이용약관</a>
            <a href="#business-info">사업자정보</a>
          </div>
        </div>
      </div>
    </footer>
  );
}

/* ────────────────────────────────────────────────────────────
   Floating actions (mobile bar + desktop FABs)
   ──────────────────────────────────────────────────────────── */
function IconTop() {
  return (
    <svg width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <path d="M12 5l-7 7h4v7h6v-7h4l-7-7z" fill="currentColor" />
    </svg>
  );
}
function IconPhone() {
  return (
    <svg width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <path d="M6.6 10.8c1.4 2.8 3.8 5.2 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.1 21 3 13.9 3 5c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.3.2 2.5.6 3.6.2.3.1.7-.2 1L6.6 10.8z" fill="currentColor" />
    </svg>
  );
}
function IconChat() {
  return (
    <svg width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H5.2L4 17.2V4h16v12z" fill="currentColor" />
    </svg>
  );
}

function FloatActions() {
  const [showTop, setShowTop] = useState(false);

  useEffect(() => {
    const onScroll = () => setShowTop(window.scrollY > 320);
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  const scrollTop = () => window.scrollTo({ top: 0, behavior: 'smooth' });

  return (
    <>
      {/* 모바일: 하단 고정 50/50 */}
      <div className="float-bar" role="navigation" aria-label="빠른 상담">
        <a href={BUSINESS.phoneHref} className="float-bar__btn float-bar__btn--phone">
          <IconPhone />
          <span>전화 상담</span>
        </a>
        <a href="#contact" className="float-bar__btn float-bar__btn--contact">
          <IconChat />
          <span>문의 신청</span>
        </a>
      </div>

      {/* PC: 우측 하단 아이콘 */}
      <div className="float-fab" role="navigation" aria-label="빠른 메뉴">
        <button
          type="button"
          className={`float-fab__btn float-fab__btn--top${showTop ? ' is-visible' : ''}`}
          aria-label="맨 위로"
          onClick={scrollTop}
        >
          <IconTop />
        </button>
        <a href={BUSINESS.phoneHref} className="float-fab__btn float-fab__btn--phone" aria-label="전화 상담">
          <IconPhone />
        </a>
        <a href="#contact" className="float-fab__btn float-fab__btn--contact" aria-label="문의 신청">
          <IconChat />
        </a>
      </div>
    </>
  );
}

/* ──────────────────────────────────────────────────────────── */
Object.assign(window, {
  Nav, Hero, About, Services, Funds, Process, Stats, Testimonials, FAQ, Contact, Footer, FloatActions,
});
