/* ===== Fraud Contest LP — Components ===== */ const { useState, useEffect, useRef } = React; /* ---------- Icons (tiny SVG, no external) ---------- */ const IconVideo = ({size=36}) => ( ); const IconPhoto = ({size=36}) => ( ); const IconCrown = ({size=22}) => ( ); const IconArrow = () => ; const IconShare = () => ( ); const IconMail = () => ( ); const IconUpload = () => ( ); const IconEdit = ({size=40}) => ( ); const IconBulb = ({size=18}) => ( ); /* ---------- 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 {v.toLocaleString()}{suffix}; } /* =================================================================== */ /* NAV */ /* =================================================================== */ function Nav(){ const [open,setOpen] = useState(false); const links = [ ["#about","概要"], ["#categories","募集部門"], ["#schedule","スケジュール"], ["#prizes","賞品"], ["#workshop","ワークショップ"], ["#gallery","過去作品"], ["#form","応募フォーム"], ]; return ( ); } /* =================================================================== */ /* 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 (
TC {tc} / 23.976fps
REC · CONTEST.03

それ、 闇バイト じゃないか?

友達を救うのは、君だ。
第3回 メッセージ動画&静止画コンテスト 2026 / 07.01 — 10.31

君が作った1つのクリエイティブが、誰かを救う。
闇バイトの手口とその危険性を伝える、メッセージ動画・静止画を募集します。

応募する コンテストを知る
STOP! 闇バイト被害 スマホだけでできる 簡単なバイト ホワイト案件、身分証だけでOK あなたの作品が、誰かを救う MESSAGE VIDEO & PHOTO CONTEST 2026 STOP! 闇バイト被害 スマホだけでできる 簡単なバイト ホワイト案件、身分証だけでOK あなたの一本が、誰かを救う MESSAGE VIDEO & PHOTO CONTEST 2026
); } /* =================================================================== */ /* 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 (
APPLICATION OPEN DEADLINE · 2026.10.31 23:59 JST

応募締切まで

{String(d).padStart(3,'0')}
Days
{String(h).padStart(2,'0')}
Hours
{String(m).padStart(2,'0')}
Minutes
{String(s).padStart(2,'0')}
Seconds
); } /* =================================================================== */ /* OVERVIEW */ /* =================================================================== */ function Overview(){ return (
About the Contest · 01

君のクリエイティブで、闇バイトから誰かを救え。

大分県警察が主催するメッセージコンテストは、今年で3回目。 SNSや動画投稿サイトを通じて、闇バイトの手口とその危険性を身近な仲間や家族に伝える—— そんなメッセージ動画・静止画を県内から広く募集します。

入賞作品は大分県警察のSNS、YouTube、県内の広報啓発イベントで活用され、 あなたの一本が、本当に誰かの被害を止めるかもしれません。

#STOP闇バイト被害 #友達を救うのは君だ #大分県警察
入賞作品は広告で使用 募集は2部門(動画・静止画) 対象年齢 16〜29歳 応募条件 個人・団体OK
); } /* =================================================================== */ /* CATEGORIES */ /* =================================================================== */ function Categories(){ return (
Categories · 02

2つの部門で募集中

伝えたいメッセージに合わせて、動画または静止画のどちらかで応募できます。両部門への応募も可能です。

A
CATEGORY A · MOVIE

動画部門

YouTubeやSNS等での広報啓発に活用できる、15秒のショート動画を募集。 ドラマ仕立て、アニメーション、インタビュー形式などなど形式は自由です。

尺 15秒 MP4 / MOV 〜100MB
B
CATEGORY B · PHOTO

静止画部門

SNS等で拡散しやすい、1枚の静止画・ポスター・イラスト・グラフィックを募集。 シンプルで伝わる一枚で、誰かの気づきを生んでください。

JPEG / PDF A3 〜10MB
テーマは自由

闇バイトの危険性が伝われば、切り口はあなた次第。 例:甘い勧誘の手口 / “ホワイト案件”の罠 / 抜け出せない恐怖

); } /* =================================================================== */ /* 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 (
Schedule · 03

応募スケジュール

{steps.map((s,i)=>{ const past = now > new Date(s.end).getTime(); return (
{past ? '✓' : String(i+1).padStart(2,'0')}
{s.date}

{s.h}

{s.p}{s.link && <>
{s.link.label}}

); })}
); } /* =================================================================== */ /* PRIZES */ /* =================================================================== */ function Prizes(){ return (
Prizes · 04

賞品内容
Amazonギフトカード

各部門ごとに受賞者を選出。入賞作品は大分県警察のSNS等で広報啓発に活用させていただきます。

Grand Prix · 各部門 1作品

グランプリ

万円分

最も優秀で、広く伝わるメッセージ性の高い作品に贈られます。

A Silver · 各部門 1作品

準グランプリ

万円分

独創性・訴求力に優れた作品に贈られます。

B Jury Award · 各部門 1作品

審査員特別賞

万円分

審査員が特に注目した作品に贈られます。

P Participation

参加賞

円分

ご応募いただいた方への参加賞です。数量に限りがございますので、あらかじめご了承ください。

); } /* =================================================================== */ /* STEPS */ /* =================================================================== */ function Steps(){ const steps = [ {n:"01", h:"メッセージを考える", p:"テーマは自由。闇バイトの危険性が伝わる切り口を、自由な発想で見つけよう。"}, {n:"02", h:"作品をつくる", p:"動画 or 静止画、得意な表現で。スマホだけでもOK。"}, {n:"03", h:"フォームに入力", p:"応募者情報と作品情報、ファイルをアップロード。"}, {n:"04", h:"応募完了", p:"受付確認メールが届いたら完了。結果発表を待とう。"}, ]; return (
How to Apply · 05

応募の4ステップ

{steps.map((s,i)=>(
{s.n}

{s.h}

{s.p}

{i→}
))}
); } /* =================================================================== */ /* 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 (
Workshop · 06

1Day ワークショップ開催!

全国・県内の広告業界で活躍するクリエイターを講師として迎え、スマホでの動画・静止画制作ワークショップを開催します。

{info.map((x)=>(
{x.k}
{x.v}
))}
{closed ? ( <> ワークショップに申し込む

ワークショップの申込期限(2026年7月17日 14:59)は終了しました。

{!over && (

参加希望の場合は直接事務局までお問い合わせください。

)} ) : ( <> ワークショップに申し込む

別ウィンドウでGoogleフォームが開きます

)}
); } /* =================================================================== */ /* 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 (