// sections.jsx — header, hero, pain, services, pricing, process, about, FAQ, limits, stats, voices, footer
const { useEffect, useState, useRef } = React;
// ───────────────────────────────────────────────── ICONS
const Icon = ({ name, size = 22, stroke = 1.6 }) => {
const c = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: stroke, strokeLinecap: "round", strokeLinejoin: "round" };
switch (name) {
case "clock":return ;
case "wallet":return ;
case "spark":return ;
case "doc":return ;
case "arrow":return ;
case "check":return ;
case "x":return ;
case "plus":return ;
case "minus":return ;
case "bolt":return ;
case "code":return ;
case "msg":return ;
case "stack":return ;
default:return null;
}
};
// accent color util
const ACC = { purple: "var(--p-purple)", orange: "var(--p-orange)", cyan: "var(--p-cyan)", lime: "var(--p-lime)", pink: "var(--p-pink)" };
// ───────────────────────────────────────────────── HEADER
function Header() {
return (
);
}
// ───────────────────────────────────────────────── HERO
function Hero() {
return (
NOW ACCEPTING / 相談受付中
業務の「ちょっと面倒」を、オリジナルツールで解決する。
中小企業ならではのどろくさい現場でオペレーションを統括してきた経験で、個人事業主・中小企業のための「ちょうど良い業務ツール」を、リーズナブルに、すばやく作ります。
OPERATIONS LEAD
·
50+ TOOLS SHIPPED
·
BASED IN JAPAN
);
}
// Decorative "tool stack" floating cards
function HeroArt() {
return (
{/* Center card */}
shipping.tool
> 142 / 142 件 ✓
> 所要 1.4s
{/* Top right card */}
STREAK
27days
{Array.from({ length: 14 }).map((_, i) =>
)}
{/* Bottom right card */}
PDF.COMPRESS
12.4MB
→
1.1MB
RATIO 1/11
{/* Bottom left chip */}
{/* Floating dots */}
);
}
// ───────────────────────────────────────────────── PAIN
function Pain() {
return (
こんな状況、もう何年も続いていませんか?
1つ1つは小さな不便。でも積み重ねは、年間で数百時間、数十万円規模の損失です。
そのまま放置している自覚すらない、というのが一番怖い。
{PAINS.map((p, i) =>
{e.currentTarget.style.transform = "translateY(-4px)";e.currentTarget.style.borderColor = "var(--line-2)";}}
onMouseLeave={(e) => {e.currentTarget.style.transform = "";e.currentTarget.style.borderColor = "var(--line)";}}>
{p.title}
{p.body}
)}
);
}
// ───────────────────────────────────────────────── SERVICES
function Services() {
return (
「現場に入って一緒に作る」のが、いちばん速い。
仕様書を投げ合うのではなく、業務の隣にいて、動くものを渡しながら磨きます。
以下の4つの動きで、業務の「ちょっと面倒」を畳んでいきます。
{SERVICES.map((s, i) =>
{s.en.toUpperCase()}
{s.n}
{s.title.split("、").map((part, k, arr) =>
{part}{k < arr.length - 1 ? "、" : ""}
)}
{s.body}
)}
);
}
// ───────────────────────────────────────────────── PRICING (hearing-based, no specific number)
function Pricing() {
return (
なぜ、開発会社の1/3〜1/5 で済むのか。
プロではなくセミプロ。
でも、現場の運用担当として年商4億円の業務を回しながら、
自分で使うために 50 以上のツールを作ってきました。
豪華な営業工程・分厚い仕様書・大人数の開発体制は省く。
「動いて、使えて、改修できる」最小構成を、私が直接書く。
だから、価格は抑えられて、判断は速い。
PROCESS
HEARING → ESTIMATE
ヒアリング後に、個別お見積もり。
業務によって工数は大きく変わるため、定額の料金表は出していません。
30〜60分のヒアリングで、対応範囲・概算費用・期間をその場で提示します。
相談自体は完全無料。気になる方は気軽に投げてください。
{[
"対応可否を最初に判断するので、無駄な見積もりが発生しない",
"「これくらいの規模感ですね」を、その場でラフに共有",
"本格依頼の前に、判断材料が全部そろう"].
map((t, i) =>
-
{t}
)}
);
}
// ───────────────────────────────────────────────── PROCESS
function Process() {
return (
相談から納品まで、最短当日。
仕様が固まっていなくて大丈夫。むしろ、固まる前のほうが速く進みます。
以下の5ステップで進めていきます。
);
}
// ───────────────────────────────────────────────── ABOUT
function About() {
return (
中本 達也 / TATSUYA NAKAMOTO
泥臭い現場も、グローバルな仕事も。その両方を、行き来してきました。
中本 達也(なかもと たつや)。
年商4億円の企業でオペレーション統括を担当。業務フロー構築・改善、生産性向上を専門としています。
中小企業や個人事業主向けの事業構築支援も並行して行ってきました。
泥臭い手作業の現場から、ハイレベルなグローバルビジネスまで、多様な現場を経験。
現場に入り込んでスクラムを組み、一気に突き進めるのが得意です。
{["業務フロー設計", "オペレーション統括", "小規模Webツール", "業務自動化", "事業構築支援", "現場ヒアリング"].map((t) =>
{t}
)}
);
}
// ───────────────────────────────────────────────── FAQ
function FAQ() {
const [open, setOpen] = useState(0);
return (
よくある質問
よく聞かれる内容をまとめました。
ここに載っていないことも、フォームから気軽にどうぞ。
{FAQS.map((f, i) => {
const isOpen = open === i;
return (
);
})}
);
}
// ───────────────────────────────────────────────── CANNOT (limits)
function Cannot() {
return (
対応できないこと
「迷うのは時間のムダ」なので、
先に対応外を明示しておきます。
);
}
// ───────────────────────────────────────────────── STATS + VOICES
function CountUp({ to, suffix }) {
const [n, setN] = useState(0);
const ref = useRef(null);
useEffect(() => {
const el = ref.current;if (!el) return;
const io = new IntersectionObserver((ents) => {
ents.forEach((e) => {
if (e.isIntersecting) {
const dur = 1500;const start = performance.now();
const tick = (t) => {
const k = Math.min(1, (t - start) / dur);
const eased = 1 - Math.pow(1 - k, 3);
setN(Math.round(to * eased));
if (k < 1) requestAnimationFrame(tick);
};
requestAnimationFrame(tick);
io.unobserve(el);
}
});
}, { threshold: 0.4 });
io.observe(el);
return () => io.disconnect();
}, [to]);
return {n}{suffix};
}
function Stats() {
return (
);
}
// ───────────────────────────────────────────────── FOOTER
function Footer() {
return (
);
}
Object.assign(window, { Header, Hero, Pain, Services, Pricing, Process, About, FAQ, Cannot, Stats, Footer, Icon, ACC });