/* ===== Fraud Contest LP — Components ===== */
const { useState, useEffect, useRef } = React;

/* ---------- Icons (tiny SVG, no external) ---------- */
const IconVideo = ({size=36}) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <path d="M2 6a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2z"/>
    <path d="m22 8-6 4 6 4V8Z"/>
  </svg>
);
const IconPhoto = ({size=36}) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <rect x="3" y="5" width="18" height="14" rx="2"/>
    <circle cx="12" cy="12" r="3.5"/>
    <path d="M8 5 9.5 3h5L16 5"/>
  </svg>
);
const IconCrown = ({size=22}) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor"><path d="M2 7l5 4 5-7 5 7 5-4-2 12H4L2 7zm3 13h14v2H5z"/></svg>
);
const IconArrow = () => <span className="arrow">→</span>;
const IconShare = () => (
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/>
    <path d="m8.6 13.5 6.8 4M15.4 6.5l-6.8 4"/>
  </svg>
);
const IconMail = () => (
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <rect x="2" y="5" width="20" height="14" rx="2"/><path d="m2 7 10 7 10-7"/>
  </svg>
);
const IconUpload = () => (
  <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
    <path d="M17 8l-5-5-5 5"/><path d="M12 3v12"/>
  </svg>
);
const IconEdit = ({size=40}) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
    <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
  </svg>
);
const IconBulb = ({size=18}) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <path d="M9 18h6"/><path d="M10 21h4"/>
    <path d="M12 3a6 6 0 0 0-3.5 10.9c.5.4.8 1 .9 1.6l.1.5h5l.1-.5c.1-.6.4-1.2.9-1.6A6 6 0 0 0 12 3z"/>
  </svg>
);

/* ---------- Reveal hook ---------- */
function useReveal(){
  useEffect(()=>{
    const els = document.querySelectorAll('.reveal');
    const io = new IntersectionObserver((entries)=>{
      entries.forEach(e=>{
        if(e.isIntersecting){ e.target.classList.add('in'); io.unobserve(e.target); }
      });
    },{threshold:0.12});
    els.forEach(el=>io.observe(el));
    return ()=>io.disconnect();
  },[]);
}

/* ---------- Countdown hook ---------- */
function useCountdown(target){
  const [t,setT] = useState(()=>diff(target));
  useEffect(()=>{
    const id = setInterval(()=>setT(diff(target)),1000);
    return ()=>clearInterval(id);
  },[target]);
  return t;
}
function diff(target){
  const ms = Math.max(0, target - Date.now());
  const d = Math.floor(ms/86400000);
  const h = Math.floor(ms/3600000)%24;
  const m = Math.floor(ms/60000)%60;
  const s = Math.floor(ms/1000)%60;
  return {d,h,m,s,done:ms===0};
}

/* ---------- Count-up when in view ---------- */
function CountUp({to, dur=1600, suffix="", className=""}){
  const [v,setV] = useState(0);
  const ref = useRef(null);
  useEffect(()=>{
    const el = ref.current; if(!el) return;
    const io = new IntersectionObserver((es)=>{
      es.forEach(e=>{
        if(e.isIntersecting){
          const start = performance.now();
          const tick = (now)=>{
            const p = Math.min(1,(now-start)/dur);
            const eased = 1 - Math.pow(1-p, 3);
            setV(Math.floor(eased*to));
            if(p<1) requestAnimationFrame(tick);
            else setV(to);
          };
          requestAnimationFrame(tick);
          io.unobserve(el);
        }
      });
    },{threshold:0.4});
    io.observe(el);
    return ()=>io.disconnect();
  },[to,dur]);
  return <span ref={ref} className={className}>{v.toLocaleString()}{suffix}</span>;
}

/* =================================================================== */
/* NAV                                                                   */
/* =================================================================== */
function Nav(){
  const [open,setOpen] = useState(false);
  const links = [
    ["#about","概要"],
    ["#categories","募集部門"],
    ["#schedule","スケジュール"],
    ["#prizes","賞品"],
    ["#workshop","ワークショップ"],
    ["#gallery","過去作品"],
    ["#form","応募フォーム"],
  ];
  return (
    <nav className="nav">
      <div className="nav-inner">
        <a href="#top" className="nav-brand" onClick={()=>setOpen(false)}>
          <img className="brand-logo" src="assets/oita-police-logo.png" alt="大分県警察 OITA PREFECTURAL POLICE"/>
          <span className="main">「友達を救うのは君だ‼︎」<br/>メッセージ動画&静止画 コンテスト</span>
        </a>
        <div className="nav-links">
          {links.map(([href,label])=>(<a key={href} href={href}>{label}</a>))}
        </div>
        <a href="#form" className="nav-cta">応募する →</a>
        <button
          className="nav-toggle"
          aria-label="メニュー"
          aria-expanded={open}
          onClick={()=>setOpen(!open)}
        >
          <span/><span/><span/>
        </button>
      </div>
      <div className={`nav-mobile ${open?"open":""}`}>
        {links.map(([href,label])=>(<a key={href} href={href} onClick={()=>setOpen(false)}>{label}</a>))}
        <a href="#form" className="nav-cta-mobile" onClick={()=>setOpen(false)}>応募する →</a>
      </div>
    </nav>
  );
}

/* =================================================================== */
/* HERO                                                                 */
/* =================================================================== */
function Hero(){
  const [tc,setTc] = useState("00:00:00:00");
  useEffect(()=>{
    const start = performance.now();
    const id = setInterval(()=>{
      const ms = performance.now() - start;
      const f = Math.floor((ms/1000*30))%30;
      const s = Math.floor(ms/1000)%60;
      const m = Math.floor(ms/60000)%60;
      const h = Math.floor(ms/3600000)%24;
      setTc(`${String(h).padStart(2,'0')}:${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}:${String(f).padStart(2,'0')}`);
    },100);
    return ()=>clearInterval(id);
  },[]);

  return (
    <header id="top" className="hero">
      <div className="hero-bg" />
      <div className="hero-vignette" />

      <div className="hero-tc">TC {tc} / 23.976fps</div>
      <div className="hero-rec"><span className="dot"/>REC<span className="rec-meta"> · CONTEST.03</span></div>

      <div className="hero-inner">
        <h1 className="hero-title">
          <span className="line sore">それ、</span>
          <span className="line"><span className="sagi">闇バイト</span></span>
          <span className="line ja">じゃないか<span style={{color:'var(--danger)'}}>?</span></span>
        </h1>

        <div className="hero-sub"><span>友達を救うのは、君だ。</span></div>

        <div className="hero-eyebrow">
          <span className="ev-title"><b>第3回</b> メッセージ動画&amp;静止画コンテスト</span>
          <span className="ev-date">2026 / 07.01 — 10.31</span>
        </div>

        <p className="hero-kicker">
          君が作った<b className="hi">1つのクリエイティブ</b>が、誰かを救う。<br/>
          闇バイトの手口とその危険性を伝える、メッセージ動画・静止画を募集します。
        </p>

        <div className="hero-actions">
          <a href="#form" className="btn btn-primary">応募する <IconArrow/></a>
          <a href="#about" className="btn btn-ghost">コンテストを知る <IconArrow/></a>
        </div>
      </div>

      <div className="hero-marquee">
        <div className="marquee-track">
          <span>STOP! 闇バイト被害</span><span className="sep">◆</span>
          <span>スマホだけでできる <b>簡単なバイト</b></span><span className="sep">◆</span>
          <span>ホワイト案件、身分証だけでOK</span><span className="sep">◆</span>
          <span>あなたの作品が、誰かを救う</span><span className="sep">◆</span>
          <span>MESSAGE VIDEO &amp; PHOTO CONTEST 2026</span><span className="sep">◆</span>
          <span>STOP! 闇バイト被害</span><span className="sep">◆</span>
          <span>スマホだけでできる <b>簡単なバイト</b></span><span className="sep">◆</span>
          <span>ホワイト案件、身分証だけでOK</span><span className="sep">◆</span>
          <span>あなたの一本が、誰かを救う</span><span className="sep">◆</span>
          <span>MESSAGE VIDEO &amp; PHOTO CONTEST 2026</span><span className="sep">◆</span>
        </div>
      </div>
    </header>
  );
}

/* =================================================================== */
/* COUNTDOWN bar                                                        */
/* =================================================================== */
function Countdown(){
  // Target: 2026-10-31 23:59:59 JST
  const target = new Date("2026-10-31T23:59:59+09:00").getTime();
  const {d,h,m,s} = useCountdown(target);
  return (
    <section className="countdown reveal">
      <div className="container">
        <div className="countdown-top">
          <span className="chip live"><span className="dot"/>APPLICATION OPEN</span>
          <span className="deadline">DEADLINE · 2026.10.31 23:59 JST</span>
        </div>
        <div className="cd-head">
          <h2>応募締切まで</h2>
        </div>
        <div className="cd-grid">
          <div className="cd-cell"><div className="cd-num">{String(d).padStart(3,'0')}</div><div className="cd-label">Days</div></div>
          <div className="cd-cell"><div className="cd-num">{String(h).padStart(2,'0')}</div><div className="cd-label">Hours</div></div>
          <div className="cd-cell"><div className="cd-num">{String(m).padStart(2,'0')}</div><div className="cd-label">Minutes</div></div>
          <div className="cd-cell"><div className="cd-num">{String(s).padStart(2,'0')}</div><div className="cd-label">Seconds</div></div>
        </div>
      </div>
    </section>
  );
}

/* =================================================================== */
/* OVERVIEW                                                             */
/* =================================================================== */
function Overview(){
  return (
    <section id="about" className="section overview">
      <div className="container">
        <div className="overview-grid">
          <div className="reveal">
            <div className="section-label">About the Contest · 01</div>
            <h2 className="section-title">君の<span className="accent">クリエイティブ</span>で、<span style={{color:'var(--caution)'}}>闇バイト</span>から誰かを救え。</h2>
            <p className="overview-p">
              大分県警察が主催するメッセージコンテストは、今年で<b>3回目</b>。
              SNSや動画投稿サイトを通じて、闇バイトの手口とその危険性を身近な仲間や家族に伝える——
              そんな<b>メッセージ動画・静止画</b>を県内から広く募集します。
            </p>
            <p className="overview-p">
              入賞作品は大分県警察のSNS、YouTube、県内の広報啓発イベントで活用され、
              あなたの一本が、本当に誰かの被害を止めるかもしれません。
            </p>
            <div style={{display:'flex',gap:12,flexWrap:'wrap',marginTop:20}}>
              <span className="chip">#STOP闇バイト被害</span>
              <span className="chip">#友達を救うのは君だ</span>
              <span className="chip">#大分県警察</span>
            </div>
          </div>

          <div className="stats-col reveal delay-1">
            <div className="about-cards">
              <img src="uploads/about/advertise.webp" alt="入賞作品は広告で使用" loading="lazy"/>
              <img src="uploads/about/2section.webp" alt="募集は2部門（動画・静止画）" loading="lazy"/>
              <img src="uploads/about/limited_old.webp" alt="対象年齢 16〜29歳" loading="lazy"/>
              <img src="uploads/about/application_condition.webp" alt="応募条件 個人・団体OK" loading="lazy"/>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* =================================================================== */
/* CATEGORIES                                                           */
/* =================================================================== */
function Categories(){
  return (
    <section id="categories" className="section">
      <div className="container">
        <div className="reveal" style={{marginBottom:48}}>
          <div className="section-label">Categories · 02</div>
          <h2 className="section-title">2つの<span className="accent">部門</span>で募集中</h2>
          <p className="section-lede">
            伝えたいメッセージに合わせて、動画または静止画のどちらかで応募できます。両部門への応募も可能です。
          </p>
        </div>

        <div className="cats">
          <article className="cat video reveal">
            <div className="num-big">A</div>
            <div>
              <div className="cat-label">CATEGORY A · MOVIE</div>
              <div className="cat-icon"><IconVideo/></div>
              <h3>動画部門</h3>
              <p>
                YouTubeやSNS等での広報啓発に活用できる、15秒のショート動画を募集。
                ドラマ仕立て、アニメーション、インタビュー形式などなど形式は自由です。
              </p>
            </div>
            <div className="meta">
              <span className="chip">尺 15秒</span>
              <span className="chip">MP4 / MOV</span>
              <span className="chip">〜100MB</span>
            </div>
          </article>

          <article className="cat photo reveal delay-1">
            <div className="num-big">B</div>
            <div>
              <div className="cat-label">CATEGORY B · PHOTO</div>
              <div className="cat-icon"><IconPhoto/></div>
              <h3>静止画部門</h3>
              <p>
                SNS等で拡散しやすい、1枚の静止画・ポスター・イラスト・グラフィックを募集。
                シンプルで伝わる一枚で、誰かの気づきを生んでください。
              </p>
            </div>
            <div className="meta">
              <span className="chip">JPEG / PDF</span>
              <span className="chip">A3</span>
              <span className="chip">〜10MB</span>
            </div>
          </article>
        </div>

        <div className="cat-hint reveal">
          <span className="cat-hint-head"><IconBulb size={20}/> テーマは自由</span>
          <p>
            闇バイトの危険性が伝われば、切り口はあなた次第。
            <span className="cat-hint-ex">例：甘い勧誘の手口 ／ “ホワイト案件”の罠 ／ 抜け出せない恐怖</span>
          </p>
        </div>
      </div>
    </section>
  );
}

/* =================================================================== */
/* SCHEDULE                                                             */
/* =================================================================== */
function Schedule(){
  // 通常は現在日時で判定。?preview=2026-08-01 のように指定すると基準日を差し替えてプレビュー可能。
  const preview = new URLSearchParams(window.location.search).get('preview');
  const now = preview ? new Date(preview).getTime() : Date.now();
  const steps = [
    {date:"2026.07.01", h:"応募受付スタート", p:"特設サイトより応募開始", end:"2026-07-01T23:59:59+09:00", link:{href:"#form", label:"応募はこちら →"}},
    {date:"2026.07.18", h:"1Dayワークショップ", p:"スマホで動画・静止画制作を学べる1日講座（申込締切 7/17 14:59）", end:"2026-07-18T23:59:59+09:00", link:{href:"#workshop", label:"申し込みはこちら →"}},
    {date:"2026.10.31", h:"応募締切", p:"23:59 まで / 必着", end:"2026-10-31T23:59:59+09:00"},
    {date:"2026.11頃", h:"審査期間", p:"大分県警察・特別審査員による選考", end:"2026-11-30T23:59:59+09:00"},
    {date:"2026.12頃", h:"結果発表・表彰式", p:"特設サイト・大分県警察SNSにて発表", end:"2026-12-15T23:59:59+09:00"},
  ];
  return (
    <section id="schedule" className="section schedule">
      <div className="container">
        <div className="reveal" style={{marginBottom:32}}>
          <div className="section-label">Schedule · 03</div>
          <h2 className="section-title">応募スケジュール</h2>
        </div>
        <div className="timeline">
          {steps.map((s,i)=>{
            const past = now > new Date(s.end).getTime();
            return (
              <div key={i} className={`tl-step reveal delay-${i} ${past?'past':''}`}>
                <div className="tl-dot">{past ? '✓' : String(i+1).padStart(2,'0')}</div>
                <div className="tl-date">{s.date}</div>
                <h4>{s.h}</h4>
                <p>{s.p}{s.link && <><br/><a href={s.link.href} className="tl-link">{s.link.label}</a></>}</p>
              </div>
            );
          })}
        </div>
      </div>
    </section>
  );
}

/* =================================================================== */
/* PRIZES                                                               */
/* =================================================================== */
function Prizes(){
  return (
    <section id="prizes" className="section prizes">
      <div className="container">
        <div className="reveal" style={{marginBottom:32}}>
          <div className="section-label">Prizes · 04</div>
          <h2 className="section-title">賞品内容<br/><span className="accent">Amazonギフトカード</span></h2>
          <p className="section-lede">各部門ごとに受賞者を選出。入賞作品は大分県警察のSNS等で広報啓発に活用させていただきます。</p>
        </div>

        <div className="prize-grid">
          <div className="prize top reveal">
            <span className="pk">★</span>
            <span className="crown"><IconCrown size={30}/></span>
            <span className="rank">Grand Prix · 各部門 1作品</span>
            <h4>グランプリ</h4>
            <div className="amount"><CountUp to={10}/><span className="jp">万円分</span></div>
            <p className="desc">最も優秀で、広く伝わるメッセージ性の高い作品に贈られます。</p>
          </div>
          <div className="prize reveal delay-1">
            <span className="pk">A</span>
            <span className="crown crown-w"><IconCrown size={24}/></span>
            <span className="rank">Silver · 各部門 1作品</span>
            <h4>準グランプリ</h4>
            <div className="amount"><CountUp to={5}/><span className="jp">万円分</span></div>
            <p className="desc">独創性・訴求力に優れた作品に贈られます。</p>
          </div>
          <div className="prize reveal delay-2">
            <span className="pk">B</span>
            <span className="crown crown-w"><IconCrown size={24}/></span>
            <span className="rank">Jury Award · 各部門 1作品</span>
            <h4>審査員特別賞</h4>
            <div className="amount"><CountUp to={5}/><span className="jp">万円分</span></div>
            <p className="desc">審査員が特に注目した作品に贈られます。</p>
          </div>
          <div className="prize reveal delay-3">
            <span className="pk">P</span>
            <span className="rank">Participation</span>
            <h4>参加賞</h4>
            <div className="amount"><CountUp to={1500}/><span className="jp">円分</span></div>
            <p className="desc">ご応募いただいた方への参加賞です。数量に限りがございますので、あらかじめご了承ください。</p>
          </div>
        </div>
      </div>
    </section>
  );
}

/* =================================================================== */
/* STEPS                                                                */
/* =================================================================== */
function Steps(){
  const steps = [
    {n:"01", h:"メッセージを考える", p:"テーマは自由。闇バイトの危険性が伝わる切り口を、自由な発想で見つけよう。"},
    {n:"02", h:"作品をつくる", p:"動画 or 静止画、得意な表現で。スマホだけでもOK。"},
    {n:"03", h:"フォームに入力", p:"応募者情報と作品情報、ファイルをアップロード。"},
    {n:"04", h:"応募完了", p:"受付確認メールが届いたら完了。結果発表を待とう。"},
  ];
  return (
    <section className="section steps">
      <div className="container">
        <div className="reveal" style={{marginBottom:32}}>
          <div className="section-label">How to Apply · 05</div>
          <h2 className="section-title">応募の<span className="accent">4ステップ</span></h2>
        </div>
        <div className="step-grid">
          {steps.map((s,i)=>(
            <div key={i} className={`step reveal delay-${i}`}>
              <div className="no">{s.n}</div>
              <h4>{s.h}</h4>
              <p>{s.p}</p>
              {i<steps.length-1 && <span className="arrow-right">→</span>}
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* =================================================================== */
/* WORKSHOP                                                             */
/* =================================================================== */
const WORKSHOP_FORM_URL = "https://docs.google.com/forms/d/e/1FAIpQLSc7F6g0Ge-jD3rE7UXVDmAjG5RcitbgAGCpfIGq3rbasqJNdg/viewform";

function Workshop(){
  // 締切判定。?preview=YYYY-MM-DD で基準日を差し替えてプレビュー可能（Scheduleと共通）。
  const preview = new URLSearchParams(window.location.search).get('preview');
  const now = preview ? new Date(preview).getTime() : Date.now();
  // 7/17 14:59までは申込ボタン有効。7/17 15:00以降は締切表示に切替。
  const closed = now > new Date("2026-07-17T14:59:59+09:00").getTime();
  // 締切後〜7/18 11:59までは直接事務局への問い合わせ案内を表示。7/18 12:00以降は締切文のみ。
  const over = now > new Date("2026-07-18T11:59:59+09:00").getTime();
  const info = [
    {k:"対象", v:"大分県内在住の16〜29歳の方（個人・団体問わず）"},
    {k:"日程", v:"2026年7月18日（土） 13:30スタート（受付13:00）"},
    {k:"場所", v:"Garraway0（大分市府内町1丁目1-12）"},
    {k:"申込締切", v:"2026年7月17日（金）14:59まで", hot:true},
  ];
  return (
    <section id="workshop" className="section workshop">
      <div className="container">
        <div className="reveal" style={{marginBottom:32}}>
          <div className="section-label">Workshop · 06</div>
          <h2 className="section-title">1Day <span className="accent">ワークショップ</span>開催！</h2>
          <p className="section-lede">
            全国・県内の広告業界で活躍するクリエイターを講師として迎え、スマホでの動画・静止画制作ワークショップを開催します。
          </p>
        </div>

        <div className="ws-card reveal">
          <dl className="ws-info">
            {info.map((x)=>(
              <div className="ws-row" key={x.k}>
                <dt>{x.k}</dt>
                <dd className={x.hot?"hot":""}>{x.v}</dd>
              </div>
            ))}
          </dl>
          <div className="ws-cta">
            {closed ? (
              <>
                <span className="btn btn-primary ws-btn is-disabled" aria-disabled="true">
                  ワークショップに申し込む <IconArrow/>
                </span>
                <p className="ws-note ws-note-closed">ワークショップの申込期限（2026年7月17日 14:59）は終了しました。</p>
                {!over && (
                  <p className="ws-note ws-note-contact">参加希望の場合は直接事務局までお問い合わせください。</p>
                )}
              </>
            ) : (
              <>
                <a href={WORKSHOP_FORM_URL} target="_blank" rel="noopener noreferrer" className="btn btn-primary ws-btn">
                  ワークショップに申し込む <IconArrow/>
                </a>
                <p className="ws-note">別ウィンドウでGoogleフォームが開きます</p>
              </>
            )}
          </div>
        </div>
      </div>
    </section>
  );
}

/* =================================================================== */
/* GALLERY (past winners placeholders)                                  */
/* =================================================================== */
function Gallery(){
  /* ===== 受賞作品の登録 =====================================================
     動画(YouTube): { y, t, cat:"VIDEO", youtube:"<11桁のYouTube動画ID>", poster?:"画像パス(任意)" }
       例) https://www.youtube.com/watch?v=AbCdEfGhIjk  → youtube:"AbCdEfGhIjk"
       poster 省略時は YouTube のサムネイルを自動取得します。
     静止画       : { y, t, cat:"PHOTO", image:"画像パス(例 uploads/winners/2025-photo.jpg)" }
     ※ youtube / image が未設定の項目は、従来どおりプレースホルダー表示になります。
  ========================================================================= */
  const items = [
    // 動画部門
    {y:"2025", t:"グランプリ",   cat:"VIDEO", youtube:"stLL-3GHibU"},
    {y:"2025", t:"準グランプリ", cat:"VIDEO", youtube:"o1rEu9fNtoo"},
    {y:"2025", t:"審査員特別賞", cat:"VIDEO", youtube:"6xZxO4TCRNc"},
    // 静止画部門
    {y:"2025", t:"グランプリ",   cat:"PHOTO", image:"uploads/winners/2025-grandprix.jpg"},
    {y:"2025", t:"準グランプリ", cat:"PHOTO", image:"uploads/winners/2025-second.jpg"},
    {y:"2025", t:"審査員特別賞", cat:"PHOTO", image:"uploads/winners/2025-jury.jpg"},
  ];

  const [active, setActive] = useState(null);
  const isVideo = (it)=> it.cat === "VIDEO";
  const ready   = (it)=> isVideo(it) ? !!it.youtube : !!it.image;
  const thumb   = (it)=> isVideo(it)
    ? (it.poster || (it.youtube ? `https://i.ytimg.com/vi/${it.youtube}/maxresdefault.jpg` : ""))
    : (it.image || "");

  useEffect(()=>{
    if(active===null) return;
    const onKey = (e)=>{ if(e.key==="Escape") setActive(null); };
    window.addEventListener("keydown", onKey);
    return ()=>window.removeEventListener("keydown", onKey);
  },[active]);

  return (
    <section id="gallery" className="section">
      <div className="container">
        <div className="reveal" style={{marginBottom:32}}>
          <div className="section-label">Past Winners · 07</div>
          <h2 className="section-title">過去の<span className="accent">受賞作品</span></h2>
          <p className="section-lede">第1回・第2回の受賞作品を一部ご紹介。どれも見る人の心に残る力作です。</p>
        </div>
        <div className="gallery-grid">
          {items.map((it,i)=>{
            const src = thumb(it);
            const can = ready(it);
            return (
              <div key={i}
                   className={`gi ${isVideo(it)?"vid":""} ${can?"":"pending"} reveal delay-${i%4}`}
                   onClick={()=> can && setActive(i)}
                   role={can?"button":undefined}
                   tabIndex={can?0:undefined}
                   onKeyDown={(e)=>{ if(can && (e.key==="Enter"||e.key===" ")){ e.preventDefault(); setActive(i); } }}>
                {src
                  ? <img className="gi-img" src={src} alt={`${it.y} ${it.t}`} loading="lazy"
                         onError={(isVideo(it) && !it.poster)
                           ? (e)=>{ const t=e.currentTarget; if(t.dataset.fb) return; t.dataset.fb="1"; t.src=`https://i.ytimg.com/vi/${it.youtube}/mqdefault.jpg`; }
                           : undefined}/>
                  : <div className="ph">[{it.cat}]</div>}
                <div className="gi-grad" aria-hidden="true"/>
                <div className="rec-strip">{it.cat}</div>
                <div className="label">
                  <span>{it.t}</span>
                  <span className="year">{it.y}</span>
                </div>
              </div>
            );
          })}
        </div>
        <p style={{color:'var(--ink-3)',fontSize:12,marginTop:16,textAlign:'center',letterSpacing:'.1em'}}>
          ※ 一部の作品はイメージです。実際の作品は大分県警察公式SNS・YouTubeにてご覧いただけます。
        </p>
      </div>

      {active!==null && (
        <div className="lightbox" onClick={()=>setActive(null)}>
          <button className="lightbox-close" aria-label="閉じる" onClick={()=>setActive(null)}>×</button>
          <div className="lightbox-body" onClick={(e)=>e.stopPropagation()}>
            {isVideo(items[active])
              ? <div className="lb-video">
                  <iframe
                    src={`https://www.youtube-nocookie.com/embed/${items[active].youtube}?autoplay=1&rel=0&playsinline=1`}
                    title={`${items[active].y} ${items[active].t}`}
                    frameBorder="0"
                    allow="autoplay; encrypted-media; picture-in-picture; fullscreen"
                    allowFullScreen
                  />
                </div>
              : <img className="lb-img" src={items[active].image} alt={`${items[active].y} ${items[active].t}`}/>}
            <div className="lightbox-cap"><span>{items[active].t}</span><span className="year">{items[active].y}</span></div>
          </div>
        </div>
      )}
    </section>
  );
}

/* =================================================================== */
/* FORM (Googleフォームへ誘導)                                          */
/* ------------------------------------------------------------------- */
/* 応募は外部のGoogleフォームで受け付けます。                            */
/* ↓ を実際の公開URL（https://forms.gle/... 等）に差し替えてください。     */
/* 旧：サイト内ステップ式フォームは backup/Form.component.jsx に保管。     */
/* =================================================================== */
const GOOGLE_FORM_URL = "https://docs.google.com/forms/d/e/1FAIpQLSc--pevu5QsHyZT47L2KMZInmIbPftB6dkz93R1pEP_4NQT7g/viewform?usp=dialog";

function Form(){
  return (
    <section id="form" className="section form-section">
      <div className="form-wrap container">
        <div className="reveal" style={{textAlign:'center',marginBottom:32}}>
          <div className="section-label" style={{justifyContent:'center'}}>Application · 08</div>
          <h2 className="section-title"><span className="accent">応募</span>はこちら</h2>
          <p className="section-lede" style={{margin:'0 auto'}}>
            ご応募（エントリー）は、専用の応募フォームで受け付けています。下のボタンからお進みのうえ、必要事項をご入力ください。
          </p>
        </div>

        <div className="apply-cta reveal">
          <div className="apply-cta-ico"><IconEdit size={40}/></div>
          <h3 className="apply-cta-title">コンテストにエントリーする</h3>
          <p className="apply-cta-lede">
            出場の意思表明として、応募者情報をご登録ください。所要時間は約3分です。
          </p>
          <a
            href={GOOGLE_FORM_URL}
            target="_blank"
            rel="noopener noreferrer"
            className="btn btn-primary apply-cta-btn"
          >
            応募フォームへ進む <IconArrow/>
          </a>
          <p className="apply-note">別ウィンドウでGoogleフォームが開きます</p>
        </div>
      </div>
    </section>
  );
}

/* =================================================================== */
/* TERMS                                                                */
/* =================================================================== */
function Terms({onOpenPrivacy}){
  const items = [
    "応募資格は16~29歳までです。個人/団体は問いません。",
    "18歳未満の方は、保護者の同意・確認の上でご応募ください。",
    "参加賞は応募いただいた個人または団体につき各部門1つまでです。",
    "複数応募の場合でも重複表彰はいたしません。",
    "入賞作品は YouTube や SNS 等での広報啓発に活用いたします。",
    "作品は応募者自身のオリジナル作品に限ります。第三者の権利を侵害するものは無効とします。",
    "応募作品は未発表の作品に限ります。AI画像生成サービス等を利用した作品は応募できません。",
    "作品内に第三者の肖像・音楽・著作物等を含む場合は、事前に権利者の同意・許諾を得てください。",
    "応募多数の場合は抽選とさせていただく場合があります。",
    "応募いただいた作品（データ・書類等）は返却いたしません。応募前にコピーの保管をお願いします。",
    "本キャンペーンは大分県警察による提供です。",
    "本キャンペーンについてのお問い合わせは、事務局までお願いします。",
  ];
  return (
    <section id="terms" className="section terms">
      <div className="container">
        <div className="reveal" style={{marginBottom:32}}>
          <div className="section-label">Terms &amp; Notes · 09</div>
          <h2 className="section-title">応募規約・注意事項</h2>
        </div>
        <div className="terms-grid">
          {items.map((t,i)=>(
            <div key={i} className="terms-item reveal delay-1">
              <span className="i">!</span>
              <span>{t}</span>
            </div>
          ))}
        </div>
        <p className="terms-privacy-note reveal">
          個人情報の取扱いについては、
          <button type="button" className="terms-privacy-link" onClick={onOpenPrivacy}>プライバシーポリシー</button>
          をご確認ください。
        </p>
      </div>
    </section>
  );
}

/* =================================================================== */
/* CONTACT / SHARE                                                      */
/* =================================================================== */
function Contact(){
  return (
    <section className="section">
      <div className="container">
        <div className="reveal" style={{marginBottom:32}}>
          <div className="section-label">Share / Contact · 10</div>
          <h2 className="section-title">広げよう、<span className="accent">このメッセージ</span></h2>
        </div>
        <div className="contact-grid">
          <div className="contact-card reveal">
            <h4>SNSでシェア</h4>
            <p>このコンテストを友達に教えて、一緒に応募しよう。</p>
            <div className="share-row">
              <a href="#" className="share-btn"><IconShare/>Facebook</a>
              <a href="#" className="share-btn"><IconShare/>LINE</a>
              <a href="#" className="share-btn"><IconShare/>Instagram</a>
              <a href="#" className="share-btn"><IconShare/>リンクをコピー</a>
            </div>
          </div>
          <div className="contact-card reveal delay-1">
            <h4>お問い合わせ</h4>
            <p>メッセージ動画&amp;静止画コンテスト 事務局</p>
            <div className="email">oita_ad@jupiter.jcom.co.jp</div>
            <div style={{marginTop:14,display:'flex',gap:10,flexWrap:'wrap'}}>
              <a href="#" className="share-btn"><IconMail/>メールで問い合わせ</a>
              <span className="chip">平日 9:00 — 17:00</span>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* =================================================================== */
/* PRIVACY POLICY (modal content)                                       */
/* =================================================================== */
const MAIL = "oita_ad@jupiter.jcom.co.jp";
const PRIVACY_CONTENT = [
  {type:"h", text:"応募についての注意点（必読）"},
  {type:"note", text:"応募作品が未発表作品であることに限ります。"},
  {type:"note", text:"AI画像生成サービス等を利用した作品は応募不可となります。"},
  {type:"note", text:"18歳未満の方の応募の際には保護者へ確認の上応募してください。"},
  {type:"note", text:"応募作品は応募者本人または応募団体が撮影・制作したオリジナル作品に限ります。"},
  {type:"note", text:"応募作品の著作権は大分県警察に帰属します。"},
  {type:"note", text:"応募作品を若者を犯罪に加担させないための注意喚起やイベント・広告宣伝などに使用する場合があります。"},
  {type:"note", text:"応募作品を改変・編集する場合があります。"},
  {type:"note", text:"応募作品内で応募者本人または団体メンバー以外の人物などが映っている場合は、事前に必ず本人の同意を得た上で応募してください。"},
  {type:"note", text:"応募作品内で応募者以外の方が権利を有するデザイン、音楽を使用する場合には、必ず事前に権利者の同意を得た上で応募してください。"},
  {type:"p", text:"取得した個人情報は、応募者の同意なく第三者に提供しません。ただし、法令に基づく場合（例：裁判所や警察からの要請）や、コンテスト運営に必要な委託先（例：配送業者、システム管理会社）に提供する場合を除きます。委託先には、個人情報保護法に基づく適切な管理を義務付け、監督を行います。"},
  {type:"sub", text:"安全管理措置"},
  {type:"p", text:"個人情報の漏洩、滅失、毀損を防止するため、情報セキュリティポリシーに基づく厳格な管理を行います（詳細は情報セキュリティポリシーを参照）。"},
  {type:"p", text:"不要となった個人情報は、適切な方法で速やかに削除または廃棄します。"},
  {type:"sub", text:"個人情報の開示・訂正・削除"},
  {type:"p", text:`応募者は、自身の個人情報の開示、訂正、削除、利用停止を求める権利を有します。ご依頼はお問い合わせ先（ ${MAIL} ）にて受け付けます。`},
  {type:"p", text:"開示等の手続きには、本人確認が必要です。ご不明点やご懸念がある場合は、上記お問い合わせ先までご連絡ください。"},
  {type:"p", text:`詳細は応募規定をご確認ください。ご不明点はお問い合わせ先（ ${MAIL} ）までご連絡ください。`},

  {type:"h", text:"情報セキュリティポリシー"},
  {type:"p", text:"主催者は、応募者の個人情報や応募作品を安全に管理するため、情報セキュリティに関する法律（個人情報保護法、情報セキュリティ基本方針等）および以下のポリシーに基づき、適切な対策を講じます。"},
  {type:"sub", text:"セキュリティ対策"},
  {type:"p", text:"技術的対策：ウェブサイトはSSL/TLS暗号化を採用し、通信の安全性を確保します。サーバーはファイアウォールや侵入検知システムで保護します。"},
  {type:"p", text:"物理的対策：データセンターやサーバールームは、アクセス制限や監視システムにより不正侵入を防止します。"},
  {type:"p", text:"組織的対策：従業員および委託先に対し、情報セキュリティ教育を定期的に実施し、機密保持契約を締結します。"},
  {type:"p", text:"必須項目と任意項目を明確に区別し、応募者の同意に基づき取得します。"},
  {type:"sub", text:"第三者提供の制限"},
  {type:"p", text:"個人情報は、応募者の同意なく第三者に提供しません。ただし、以下の場合は除きます。"},
  {type:"p", text:"・法令に基づく場合（例：裁判所、警察からの要請）／委託先（例：システム管理会社、配送業者）への提供（機密保持契約を締結）／公的機関としての業務遂行に必要な場合。"},
  {type:"sub", text:"安全管理措置"},
  {type:"p", text:"個人情報の漏洩、滅失、毀損を防止するため、情報セキュリティポリシーに定める対策を講じます。個人情報の取り扱いを委託する場合は、委託先の選定基準を定め、定期的な監査を実施します。"},
  {type:"sub", text:"開示・訂正・削除等の請求"},
  {type:"p", text:"応募者は、個人情報保護法に基づき、自身の個人情報の開示、訂正、追加、削除、利用停止、第三者提供の停止を求めることができます。"},
  {type:"p", text:"応募作品に第三者の著作物（音楽、画像、映像、引用等）を含む場合、応募者は事前に権利者の許諾を得るか、著作権法で認められた範囲で使用してください。第三者の肖像を含む場合、肖像権者の同意を得てください。"},
  {type:"p", text:"権利侵害が判明した場合、応募は無効となり、応募者が一切の責任（損害賠償含む）を負います。"},
  {type:"sub", text:"著作権侵害への対応"},
  {type:"p", text:"主催者は、応募作品に関する著作権侵害の申し立てを受けた場合、事実関係を調査し、必要に応じて作品の公開停止や応募資格の取り消しを行います。"},
  {type:"p", text:`申し立ては、お問い合わせ先（ ${MAIL} ）にて受け付けます。`},
  {type:"sub", text:"作品の返却"},
  {type:"p", text:"応募作品（データ、書類等）は返却しません。必要な場合は、応募前にコピーを保管してください。"},
  {type:"p", text:`ご不明点は、応募規定またはお問い合わせ先（ ${MAIL} ）にてご確認ください。`},
];

function PrivacyModal({open, onClose}){
  useEffect(()=>{
    if(!open) return;
    const onKey = (e)=>{ if(e.key==="Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return ()=>{ document.removeEventListener("keydown", onKey); document.body.style.overflow = prev; };
  },[open,onClose]);

  if(!open) return null;
  return (
    <div className="modal-overlay" onClick={onClose} role="dialog" aria-modal="true" aria-label="プライバシーポリシー">
      <div className="modal-panel" onClick={(e)=>e.stopPropagation()}>
        <div className="modal-head">
          <h3>プライバシーポリシー</h3>
          <button className="modal-close" onClick={onClose} aria-label="閉じる">×</button>
        </div>
        <div className="modal-body">
          {PRIVACY_CONTENT.map((b,i)=>{
            if(b.type==="h")    return <h4 key={i} className="modal-h">{b.text}</h4>;
            if(b.type==="sub")  return <h5 key={i} className="modal-sub">{b.text}</h5>;
            if(b.type==="note") return <p  key={i} className="modal-note">{b.text}</p>;
            return <p key={i} className="modal-p">{b.text}</p>;
          })}
        </div>
      </div>
    </div>
  );
}

/* =================================================================== */
/* FOOTER                                                               */
/* =================================================================== */
function Footer({onOpenPrivacy}){
  return (
    <footer className="footer">
      <div className="container">
        <div className="footer-grid">
          <div>
            <div className="nav-brand" style={{marginBottom:14}}>
              <img className="brand-logo" src="assets/oita-police-logo.png" alt="大分県警察 OITA PREFECTURAL POLICE"/>
            </div>
            <p style={{margin:0,maxWidth:'42ch'}}>
              第3回 メッセージ動画&amp;静止画コンテスト 特設サイト<br/>
              主催 : 大分県警察 / 運営 : コンテスト事務局
            </p>
          </div>
          <div>
            <h5>CONTEST</h5>
            <ul>
              <li><a href="#about">概要</a></li>
              <li><a href="#categories">募集部門</a></li>
              <li><a href="#prizes">賞品</a></li>
              <li><a href="#gallery">過去作品</a></li>
            </ul>
          </div>
          <div>
            <h5>APPLY</h5>
            <ul>
              <li><a href="#form">応募フォーム</a></li>
              <li><a href="#terms">応募規約</a></li>
              <li><a href="#" onClick={(e)=>{e.preventDefault(); onOpenPrivacy();}}>プライバシーポリシー</a></li>
            </ul>
          </div>
        </div>
        <div className="footer-legal">
          <span>© 2026 Oita Prefectural Police. All rights reserved.</span>
          <div className="legal-amazon">
            <span>Amazon、Amazon.co.jp およびそれらのロゴは Amazon.com, Inc.またはその関連会社の商標です。</span>
            <span>お問い合わせは、Amazon ではお受けしておりません。友達を救うのは君だ!!メッセージ動画＆静止画コンテスト事務局までお願いします。</span>
          </div>
        </div>
      </div>
    </footer>
  );
}

/* =================================================================== */
/* TWEAKS PANEL                                                         */
/* =================================================================== */
function TweakPanel({visible, palette, setPalette}){
  return (
    <div className={`tweak-panel ${visible?"visible":""}`}>
      <h5>PALETTE</h5>
      <div className="tweak-row">
        {[
          {k:"red",l:"レッド基調"},
          {k:"yellow",l:"イエロー基調"},
          {k:"mono",l:"モノクロ+差し色"},
        ].map(o=>(
          <button
            key={o.k}
            className={`tweak-btn ${palette===o.k?"active":""}`}
            onClick={()=>setPalette(o.k)}
          >{o.l}</button>
        ))}
      </div>
    </div>
  );
}

/* =================================================================== */
/* APP                                                                  */
/* =================================================================== */
function App(){
  useReveal();

  // Tweak state
  const DEFAULTS = window.__EDIT_DEFAULTS__ || {palette:"red"};
  const [palette,setPalette] = useState(DEFAULTS.palette || "red");
  const [tweaksVisible,setTweaksVisible] = useState(false);
  const [privacyOpen,setPrivacyOpen] = useState(false);

  useEffect(()=>{ document.body.setAttribute('data-palette',palette); },[palette]);

  // Tweak host integration
  useEffect(()=>{
    const onMsg = (e)=>{
      if(!e.data || !e.data.type) return;
      if(e.data.type==="__activate_edit_mode") setTweaksVisible(true);
      if(e.data.type==="__deactivate_edit_mode") setTweaksVisible(false);
    };
    window.addEventListener('message',onMsg);
    window.parent.postMessage({type:"__edit_mode_available"},"*");
    return ()=>window.removeEventListener('message',onMsg);
  },[]);

  const changePalette = (p)=>{
    setPalette(p);
    window.parent.postMessage({type:"__edit_mode_set_keys",edits:{palette:p}},"*");
  };

  return (
    <>
      <Nav/>
      <Hero/>
      <Countdown/>
      <Overview/>
      <Categories/>
      <Schedule/>
      <Prizes/>
      <Steps/>
      <Workshop/>
      <Gallery/>
      <Form/>
      <Terms onOpenPrivacy={()=>setPrivacyOpen(true)}/>
      <Contact/>
      <Footer onOpenPrivacy={()=>setPrivacyOpen(true)}/>
      <TweakPanel visible={tweaksVisible} palette={palette} setPalette={changePalette}/>
      <PrivacyModal open={privacyOpen} onClose={()=>setPrivacyOpen(false)}/>
    </>
  );
}

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