/* ============================================================
   lp.jsx — ポートフォリオLP「ぽやんち」3案
   ピコ（閲覧者＝みんなの本音）/ ぽやん（ホスト＝パンダのあなた）
   window から: Pixel(ピコ), PixelPanda(ぽやん), PixelSprite を利用
   ============================================================ */

/* ---------- 共有コンテンツ ---------- */
const SITE = {
  name: "405 Just Found",
  roman: "405 JUST FOUND",
  concept: "やりたいことだけ、しよう。",
  welcome: "だいじょうぶ。ここは、そのままでいい場所。",
};

// ピコの立ち/手をふる/寝てる をページを開くたびにランダム表示
const PICO_POSES = ["stand", "wave", "sleep"];
const pickPose = () => PICO_POSES[Math.floor(Math.random() * PICO_POSES.length)];

// ファーストビューでピコがランダムに話す“本音”
const PICO_LINES = [
  "SNS、キラキラしすぎて\n見るのつらい…",
  "でも断捨離するほど、\n自分を持ってない",
  "生活弱者です。",
  "子育てに、正解ってあるの？",
  "やりたいことだけ、したいなあ",
];

const FEATURES = [
  {
    id: "blog", glyph: "doc", accent: "var(--sage-d)", bg: "var(--sage-bg)",
    title: "レリゴーブログ",
    desc: "いいことも、ダメな日も。",
    href: "blog.html",
  },
  {
    id: "video", glyph: "play", accent: "var(--sky-d)", bg: "var(--sky-bg)",
    title: "レリゴー動画",
    desc: "おすすめ動画と、レリゴーな動画。",
    href: "video.html",
  },
  {
    id: "community", glyph: "heart", accent: "var(--blush)", bg: "var(--butter-bg)",
    title: "LIGコミュニティ",
    desc: "同じ気持ちで、集まるだけ。",
    href: "community.html",
  },
  {
    id: "pace", glyph: "info", accent: "var(--peach-d)", bg: "var(--paper-2)",
    title: "レリゴー情報",
    desc: "役に立つかも、立たないかも。",
    href: "info.html",
  },
  {
    id: "project", glyph: "rocket", accent: "var(--peach-d)", bg: "var(--peach-bg)",
    title: "レリゴーProject",
    desc: "やりたいこと、なんでも。",
    href: "project.html",
  },
  {
    id: "friends", glyph: "friends", accent: "var(--sky-d)", bg: "var(--sky-bg)",
    title: "レリゴー仲間",
    desc: "レリゴーで、愉快な仲間。",
    href: "friends.html",
  },
];

/* ============================================================
   ピクセルアイコン（PixelSprite を流用）
   ============================================================ */
const ICON_PAL = (c) => ({ k: c, o: c, l: "var(--paper)" });
const GLYPHS = {
  doc: [
    "okkkkko",
    "ok...ko",
    "ok.l.ko",
    "ok...ko",
    "ok.l.ko",
    "ok...ko",
    "okkkkko",
  ],
  play: [
    "k......",
    "kkk....",
    "kkkkk..",
    "kkkkkkk",
    "kkkkk..",
    "kkk....",
    "k......",
  ],
  heart: [
    ".k.k.k.",
    "kkkkkkk",
    "kkkkkkk",
    "kkkkkkk",
    ".kkkkk.",
    "..kkk..",
    "...k...",
  ],
  moon: [
    "..kkk..",
    ".kk....",
    "kk.....",
    "kk.....",
    "kk.....",
    ".kk....",
    "..kkk..",
  ],
  info: [
    "..kkk..",
    "..kkk..",
    ".......",
    "..kkk..",
    "..kkk..",
    "..kkk..",
    "..kkk..",
  ],
  rocket: [
    "...k...",
    "..kkk..",
    "..klk..",
    "..kkk..",
    ".kkkkk.",
    "k.kkk.k",
    "..k.k..",
  ],
  friends: [
    "k.k.k.k",
    "kkk.kkk",
    "klk.klk",
    "kkk.kkk",
    "kkk.kkk",
    ".k...k.",
    ".......",
  ],
  lock: [
    "..kkk..",
    ".k...k.",
    ".k...k.",
    "kkkkkkk",
    "kk.l.kk",
    "kk.l.kk",
    "kkkkkkk",
  ],
};
function PixIcon({ glyph, color, cell = 6 }) {
  const PixelSprite = window.PixelSprite;
  return <PixelSprite rows={GLYPHS[glyph]} palette={ICON_PAL(color)} cell={cell} />;
}

/* ステータスバー */
/* ステータスバー（共通HUDを使用） */

/* ピコのセリフ（ランダム・タイプライター） */
function PicoTalk() {
  const [line] = React.useState(() => {
    const PICO_LINES_LOCAL = [
      "SNS、キラキラしすぎて\n見るのつらい…",
      "でも断捨離するほど、\n自分を持ってない",
      "ここでいいんだ、って\n思える場所でいたい",
      "がんばってるの、\n見えてないだけだよ",
      "今日も来てくれたんだね。",
    ];
    return PICO_LINES_LOCAL[Math.floor(Math.random() * PICO_LINES_LOCAL.length)];
  });
  const [n, setN] = React.useState(0);
  React.useEffect(() => {
    if (n >= line.length) return;
    const t = setTimeout(() => setN(x => x + 1), 55);
    return () => clearTimeout(t);
  }, [n, line]);
  const shown = line.slice(0, n);
  return (
    <span>
      {shown.split("\n").map((l, i, arr) => (
        <React.Fragment key={i}>{l}{i < arr.length - 1 && <br />}</React.Fragment>
      ))}
      {n < line.length && <span style={{ display: "inline-block", width: 8, height: 14, background: "var(--sage-d)", verticalAlign: -2, marginLeft: 2 }} />}
    </span>
  );
}

/* ============================================================
   フェイスチップ（顔だけクロップ）
   ============================================================ */
function FaceChip({ which, size = 56, square = false, bg }) {
  const cfg = which === "pico"
    ? { Comp: window.Pixel, scale: 0.74 * (size / 56), ty: 2 }
    : { Comp: window.PixelPanda, scale: 0.66 * (size / 56), ty: 0 };
  const C = cfg.Comp;
  return (
    <div className="facechip" style={{ width: size, height: size, background: bg, borderRadius: square ? 0 : "50%" }}>
      <div className="facechip-inner" style={{ transform: `translate(-50%,-50%) scale(${cfg.scale}) translateY(${cfg.ty}px)` }}>
        <C pose="stand" />
      </div>
    </div>
  );
}

/* マスコット全身（スケール指定） */
function Mascot({ which, scale = 1, pose = "stand" }) {
  const C = which === "pico" ? window.Pixel : window.PixelPanda;
  return (
    <div className="m-scale" style={{ transform: `scale(${scale})`, transformOrigin: "center" }}>
      <C pose={pose} />
    </div>
  );
}

/* アート調ロゴ「405 Just Found」 — 数字をピクセルタイルに */
function Logo405({ bgs = ["var(--sage-bg)", "var(--sky-bg)", "var(--butter-bg)"] }) {
  const nums = ["4", "0", "5"];
  return (
    <div className="logo405">
      <div className="l405-tiles">
        {nums.map((n, i) => (
          <div className="hardshadow pixbox l405-tile dot" key={i} style={{ background: bgs[i] }}>{n}</div>
        ))}
      </div>
      <div className="l405-jf dot">JUST FOUND</div>
    </div>
  );
}

/* ============================================================
   PRESS START — シンプルポップアップ（パンダが順に説明）
   ============================================================ */
const INTRO_LINES = [
  { parts: [{t:"ようこそ、ここは"},{t:"ひとり親",em:true},{t:"がゆるく\n集まれる場所だよ。"}], pose: "stand" },
  { parts: [{t:"気になるとこだけ、見ればいいよ。\nカードから気軽にのぞいてみて。\nきっと"},{t:"同じ気持ちの仲間",em:true},{t:"と会えるはず。"}], pose: "stand" },
  { parts: [{t:"コミュニティ",em:true},{t:"では毎日、今日の気持ちを\n置いていける場所があるよ。\n気持ちを置くと、"},{t:"気持ちの証",em:true},{t:"がもらえる。"}], pose: "stand" },
  { parts: [{t:"集めた気持ちの証で、\n庭に花を咲かせたり、\n"},{t:"他の仲間",em:true},{t:"を解放してね。"}], pose: "wave" },
  { parts: [{t:"みんなでひとり親世界を\n"},{t:"ちょっと楽しく",em:true},{t:"できたらいいね！\nよろしくね！"}], pose: "wave" },
];

function IntroOverlay({ onClose }) {
  const PandaC = window.PixelPanda;
  const reduce = typeof window !== "undefined" && window.matchMedia
    && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  const [step, setStep] = React.useState(0);
  const [n, setN] = React.useState(0);

  const cur = INTRO_LINES[step];
  const full = cur ? cur.parts.map(p => p.t).join("") : "";
  const shown = full.slice(0, n);
  const done = n >= full.length;

  const renderRich = () => {
    if (!cur) return [];
    let used = 0; const out = [];
    cur.parts.forEach((p, pi) => {
      const rem = Math.max(0, n - used);
      const txt = p.t.slice(0, rem);
      if (txt) {
        const segs = txt.split("\n");
        segs.forEach((seg, si) => {
          if (p.em) out.push(<span key={pi+"-"+si} style={{color:"var(--sage-d)",fontWeight:700}}>{seg}</span>);
          else out.push(<React.Fragment key={pi+"-"+si}>{seg}</React.Fragment>);
          if (si < segs.length - 1) out.push(<br key={pi+"-br"+si} />);
        });
      }
      used += p.t.length;
    });
    return out;
  };

  React.useEffect(() => { setN(0); }, [step]);

  React.useEffect(() => {
    if (reduce) { setN(full.length); return; }
    if (n >= full.length) return;
    const t = setTimeout(() => setN(x => x + 1), 46);
    return () => clearTimeout(t);
  }, [n, full, reduce]);

  return (
    <div className="intro-pop-veil" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="intro-pop">
        <div className="intro-pop-face pixbox" style={{ background: "var(--cream)" }}>
          <div className="facechip-inner" style={{ transform: `translate(-50%,-50%) scale(0.48)` }}>
            {PandaC && <PandaC pose={cur ? cur.pose : "stand"} />}
          </div>
        </div>
        <div className="intro-pop-bubble">
          <span className="intro-pop-text">{renderRich()}</span>
          {!done && <span className="intro-cursor" />}
        </div>
        <div className="intro-pop-foot">
          <div className="intro-pop-dots">
            {INTRO_LINES.map((_, i) => <i key={i} className={i === step ? "on" : ""} />)}
          </div>
          <div className={"intro-pop-btns" + (done ? "" : " ipop-hidden")}>
            {step > 0
              ? <button className="ipop-back dot" onClick={() => setStep(s => s - 1)}>◀ もどる</button>
              : <span className="ipop-placeholder" />}
            {step < INTRO_LINES.length - 1
              ? <button className="ipop-btn dot" onClick={() => setStep(s => s + 1)}>つぎへ ▶</button>
              : <button className="ipop-btn dot" onClick={onClose}>とじる</button>}
            <button className="ipop-skip dot" onClick={onClose}>スキップ</button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* サイトへのご意見・不具合報告（rg_contacts に保存＝問い合わせと同じ仕組み） */
function FeedbackBox() {
  const fload = (k, d) => { try { return JSON.parse(localStorage.getItem(k)) ?? d; } catch (e) { return d; } };
  const fsave = (k, v) => { try { localStorage.setItem(k, JSON.stringify(v)); } catch (e) {} };
  const SERVER = (typeof window !== "undefined" && window.GardenAPI && window.GardenAPI.enabled);
  const [open, setOpen] = React.useState(false);
  const [text, setText] = React.useState("");
  const [nick, setNick] = React.useState("");
  const [sent, setSent] = React.useState(false);

  const submit = (e) => {
    e.preventDefault();
    if (!text.trim()) return;
    const body = text.trim();
    const nk = nick.trim() || "ななしさん";
    if (SERVER) {
      // サーバーへ送信（カテゴリ feedback ＝管理画面に「サイト不具合」で届く）
      window.GardenAPI.contactSend({ category: "feedback", nick: nk, text: body });
    } else {
      const d = new Date().toLocaleDateString("ja-JP", { month: "numeric", day: "numeric" });
      const all = fload("rg_contacts", []);
      const entry = {
        id: "fb" + Date.now(), category: "feedback",
        title: "サイトへのご意見・不具合報告",
        nick: nk,
        msgs: [{ by: "me", text: body, date: d }], date: d,
      };
      fsave("rg_contacts", [entry, ...all]);
    }
    setText(""); setNick(""); setOpen(false); setSent(true);
  };

  return (
    <div className="fbbox">
      <div className="fbbox-card hardshadow pixbox">
        <div className="fbbox-head">
          <span className="fbbox-ico" aria-hidden="true"></span>
          <div className="fbbox-tx">
            <b>サイトの不具合・ご意見はこちらから</b>
            誤字・表示崩れ・動かないボタン…なんでも教えてくれると助かります。
          </div>
        </div>

        {sent ? (
          <div className="fbbox-thanks dot">
            ✓ おくってくれてありがとう！直すのに役立てます。
            <button className="fbbox-again" onClick={() => setSent(false)}>もう一度おくる</button>
          </div>
        ) : !open ? (
          <button className="fbbox-open" onClick={() => setOpen(true)}>▶ おくる</button>
        ) : (
          <form className="fbbox-form" onSubmit={submit}>
            <input
              className="fbbox-in" type="text" maxLength={20}
              placeholder="ニックネーム（任意）"
              value={nick} onChange={(e) => setNick(e.target.value)}
            />
            <textarea
              className="fbbox-text" rows={3} maxLength={600}
              placeholder="気づいたこと、おかしいと感じたところを自由にどうぞ。"
              value={text} onChange={(e) => setText(e.target.value)}
            ></textarea>
            <div className="fbbox-row">
              <button type="button" className="fbbox-cancel" onClick={() => setOpen(false)}>やめる</button>
              <button type="submit" className="fbbox-send" disabled={!text.trim()}>▶ 送信する</button>
            </div>
          </form>
        )}
      </div>
    </div>
  );
}

/* おしらせ帯 — 中身はサーバー（レリゴー情報）から読む。ここに文章は書かない。
   ▼ 運営メモ（管理画面だけで完結できるようにしてある）
     ・出す/引っ込める → admin.html の 📚情報 で NOTICE_INFO_ID の記事を「公開する / 下書きに」
       （下書きに戻すと、この帯はトップから自動で消える）
     ・文言を変える   → 同じ記事の「タイトル」と「リード」を直すだけ
     ・別のおしらせに使い回す → 下の NOTICE_INFO_ID を、その記事のIDに変える */
/* 帯の左上に出す見出し。記事のカテゴリから自動で決まるので、
   別の記事に切り替えてもここは直さなくてよい（該当なしなら「おしらせ」）。 */
const NOTICE_CATS = {
  jishin: "令和8年熊本地震",
  shien:  "支援制度",
  kodomo: "子供食堂",
  life:   "生活の知恵",
};
const NOTICE_INFO_ID = "jishin-kumamoto";
function QuakeNotice() {
  const [notice, setNotice] = React.useState(null);
  React.useEffect(() => {
    if (!(window.GardenAPI && window.GardenAPI.enabled && window.GardenAPI.infosList)) return;
    window.GardenAPI.infosList().then((list) => {
      if (!Array.isArray(list)) return;
      const hit = list.find((x) => x && x.id === NOTICE_INFO_ID);
      if (hit) setNotice(hit);
    });
  }, []);

  if (!notice) return null;
  // 帯にはリードの1文目だけを出す（長すぎたら切る）。全文は情報ページ側で読める。
  const head = (notice.lead || "").split("。")[0];
  const sub = !head ? "" : (head.length > 30 ? head.slice(0, 30) + "…" : head + "。");
  return (
    <a
      href={"info.html?cat=" + (notice.cat || "shien")}
      className="hardshadow pixbox"
      style={{
        display: "block", margin: "0 0 14px", padding: "13px 15px 14px", textAlign: "left",
        background: "var(--sky-bg)", color: "var(--ink)", textDecoration: "none",
      }}
    >
      <div className="dot" style={{ fontSize: 11.5, letterSpacing: ".14em", color: "var(--sky-d)", marginBottom: 7 }}>● {NOTICE_CATS[notice.cat] || "おしらせ"}</div>
      <div style={{ fontSize: 15.5, lineHeight: 1.5, fontWeight: 700 }}>{notice.title}</div>
      {/* リードは出さない（カテゴリ名＋タイトルで用件は伝わる／帯を低く保ってファーストビューに収めるため） */}
      <div className="dot" style={{ fontSize: 11.5, letterSpacing: ".1em", textAlign: "right", marginTop: 8, color: "var(--sky-d)" }}>ひらく ▶</div>
    </a>
  );
}

/* 改装中バナー — 両端で玄人がぴょこぴょこ／背景にドットのビル */
function ConstructionBanner() {
  const Kuro = window.PixelKuro;
  const buildings = [30, 48, 38, 60, 34, 52, 44, 64, 32, 50, 40, 56];
  return (
    <div className="cobanner hardshadow pixbox">
      <div className="cobanner-city" aria-hidden="true">
        {buildings.map((h, i) => (
          <span className="cobanner-bldg" key={i} style={{ height: h + "px" }}></span>
        ))}
      </div>
      <div className="cobanner-kuro l" aria-hidden="true">
        <span className="cobanner-kuro-in">{Kuro ? <Kuro pose="stand" /> : null}</span>
      </div>
      <div className="cobanner-text">
        <span className="cob-sub dot">NOW UPDATING</span>
        <span className="cob-main">随時コンテンツ<br /><span className="em">改装中！</span></span>
      </div>
      <div className="cobanner-kuro r" aria-hidden="true">
        <span className="cobanner-kuro-in">{Kuro ? <Kuro pose="stand" /> : null}</span>
      </div>
    </div>
  );
}

/* ============================================================
   案C — コンソール / PLAYER SELECT
   ============================================================ */
function VariantC({ dark }) {
  const [picoPose] = React.useState(pickPose);
  /* 「友達100人できるかな」の人数を数える。1つの端末につき1回だけ。
     数えるのは数字だけで、誰が来たかは一切保存していない（405-reactions.php）。
     ⚠️ ページを開いただけでは数えない。スクロール・タップ・キー操作のどれかが
     1回あってから数える＝自動巡回プログラム（ボット）を数えないため。 */
  React.useEffect(() => {
    let already = false;
    try { already = !!localStorage.getItem("rg_visit_counted"); } catch (e) {}
    if (already) return;
    if (!(window.GardenAPI && window.GardenAPI.enabled && window.GardenAPI.reactionTap)) return;

    let done = false;
    const stop = () => {
      window.removeEventListener("scroll", count);
      window.removeEventListener("pointerdown", count);
      window.removeEventListener("keydown", count);
    };
    const count = () => {
      if (done) return;
      done = true;
      stop();
      window.GardenAPI.reactionTap("site:visit:join", 1).then((res) => {
        if (res && typeof res.n === "number") {
          try { localStorage.setItem("rg_visit_counted", "1"); } catch (e) {}
        }
      });
    };
    window.addEventListener("scroll", count, { passive: true });
    window.addEventListener("pointerdown", count, { passive: true });
    window.addEventListener("keydown", count);
    return stop;
  }, []);
  const [introOpen, setIntroOpen] = React.useState(false); // 自動起動なし。PRESS STARTボタンでのみ開く
  const [blogNew, setBlogNew] = React.useState(false);
  const [videoNew, setVideoNew] = React.useState(false);
  const [paceNew, setPaceNew] = React.useState(false);
  const [projNew, setProjNew] = React.useState(false);
  const [commNew, setCommNew] = React.useState(false);
  const [secretNew, setSecretNew] = React.useState(false);
  const [, forceTick] = React.useReducer((x) => x + 1, 0);
  // 戻る/進む(bfcache)やタブ復帰でトップに戻ったとき、新着バッジを再評価する
  React.useEffect(() => {
    const recheck = (e) => { if (!e || e.persisted || document.visibilityState === "visible") forceTick(); };
    window.addEventListener("pageshow", recheck);
    document.addEventListener("visibilitychange", recheck);
    return () => {
      window.removeEventListener("pageshow", recheck);
      document.removeEventListener("visibilitychange", recheck);
    };
  }, []);
  // ブログのサーバー記事数を見て、増えていたら新着バッジ
  React.useEffect(() => {
    if (window.GardenAPI && window.GardenAPI.enabled && window.GardenAPI.blogPosts) {
      window.GardenAPI.blogPosts().then((sv) => {
        if (!sv) return;
        if (window.seedCount) window.seedCount("blog", sv.length);
        if (window.hasNewCount && window.hasNewCount("blog", sv.length)) setBlogNew(true);
      });
    }
  }, []);
  // 動画のサーバー本数を見て、増えていたら新着バッジ（ブログと同じ仕組み）
  React.useEffect(() => {
    if (window.GardenAPI && window.GardenAPI.enabled && window.GardenAPI.videosList) {
      window.GardenAPI.videosList().then((res) => {
        if (!res || !Array.isArray(res.videos)) return;   // 取得失敗は何もしない（0件とは区別する）
        if (window.seedCount) window.seedCount("video", res.videos.length);
        if (window.hasNewCount && window.hasNewCount("video", res.videos.length)) setVideoNew(true);
      });
    }
  }, []);
  // 情報のサーバー件数を見て、増えていたら新着バッジ
  React.useEffect(() => {
    if (window.GardenAPI && window.GardenAPI.enabled && window.GardenAPI.infosList) {
      window.GardenAPI.infosList().then((sv) => {   // ⚠️infosListは配列を直で返す（失敗時はnull）
        if (!Array.isArray(sv)) return;   // 取得失敗は何もしない（0件とは区別する）
        if (window.seedCount) window.seedCount("pace", sv.length);
        if (window.hasNewCount && window.hasNewCount("pace", sv.length)) setPaceNew(true);
      });
    }
  }, []);
  // プロジェクトのサーバー件数を見て、増えていたら新着バッジ
  React.useEffect(() => {
    if (window.GardenAPI && window.GardenAPI.enabled && window.GardenAPI.projectsList) {
      window.GardenAPI.projectsList().then((sv) => {   // ⚠️projectsListは配列を直で返す（失敗時はnull）
        if (!Array.isArray(sv)) return;   // 取得失敗は何もしない（0件とは区別する）
        if (window.seedCount) window.seedCount("project", sv.length);
        if (window.hasNewCount && window.hasNewCount("project", sv.length)) setProjNew(true);
      });
    }
  }, []);
  // コミュニティ：運営からの未読返信があればバッジ
  React.useEffect(() => {
    if (window.GardenAPI && window.GardenAPI.enabled && window.GardenAPI.consultList) {
      window.GardenAPI.consultList().then((res) => {
        if (!res || !Array.isArray(res.threads)) return;
        const load = (k, d) => { try { return JSON.parse(localStorage.getItem(k)) ?? d; } catch (e) { return d; } };
        const hasUnread = res.threads.some((th) => {
          const them = (th.msgs || []).filter((m) => m.by === "them").length;
          return them > load("rg_read_" + th.id, 0);
        });
        if (hasUnread) setCommNew(true);
      });
    }
  }, []);
  // ひみつけっしゃ：運営からの未読返信があればバッジ
  React.useEffect(() => {
    if (window.GardenAPI && window.GardenAPI.enabled && window.GardenAPI.contactList) {
      window.GardenAPI.contactList().then((res) => {
        if (!res || !Array.isArray(res.threads)) return;
        const load = (k, d) => { try { return JSON.parse(localStorage.getItem(k)) ?? d; } catch (e) { return d; } };
        const them = res.threads.reduce((n, th) => n + (th.msgs || []).filter((m) => m.by === "them").length, 0);
        if (them > load("rg_contact_seen", 0)) setSecretNew(true);
      });
    }
  }, []);
  const t = dark
    ? { bg: "#100e09", fg: "#f3efe6", soft: "#a8a294", panel: "#242018", card: "#242018", tileBg: ["#242018", "#242018", "#242018"] }
    : { bg: "var(--cream)", fg: "var(--ink)", soft: "var(--ink-soft)", panel: "var(--paper)", card: null, tileBg: ["var(--sage-bg)", "var(--sky-bg)", "var(--butter-bg)"] };
  return (
    <div className={"screen" + (dark ? " dark" : "")} style={{ background: t.bg }}>
      {introOpen && <IntroOverlay onClose={() => setIntroOpen(false)} />}
      {window.HudBar ? React.createElement(window.HudBar, { tint: t.fg }) : null}
      <div style={{ textAlign: "center", padding: "0 0 8px" }}>
        <span className="dot" style={{ fontSize: 12.5, color: t.soft, letterSpacing: ".22em" }}>{SITE.roman}</span>
        <div className="bookmark-hint dot" style={{ fontSize: 9.5, color: t.soft, opacity: .72, letterSpacing: ".06em", marginTop: 3 }}>
          ★ ホーム画面に追加して、またフラッと来てね
        </div>
      </div>

      {/* CRTスクリーン：ピコが話す（ポーズはランダム） */}
      <div style={{ margin: "0 16px" }}>
        <div className="hardshadow pixframe">
          <div className="pixframe-in">
            <div className="crt" style={{ padding: "12px 14px 12px" }}>
              <div className="crt-glow" />
              <div style={{ position: "relative", zIndex: 1 }}>
                <div style={{ display: "grid", placeItems: "center", height: 130 }}>
                  <Mascot which="pico" scale={0.70} pose={picoPose} />
                </div>
                <div className="dot" style={{ fontSize: 17, lineHeight: 1.7, marginTop: 12, minHeight: "3.4em" }}>
                  <PicoTalk />
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* タイトルロゴ */}
      <div style={{ padding: "10px 20px 4px" }}>
        <Logo405 bgs={t.tileBg} />
      </div>

      {/* SELECT MODE：ゲームカード */}
      <div data-tour-id="select" style={{ padding: "0 16px 0" }}>
        {/* PRESS START — カードの上 */}
        <div style={{ textAlign: "center", paddingBottom: 10 }}>
          <div style={{ fontSize: 16, color: t.soft, marginBottom: 8 }}>{SITE.concept}</div>

          {/* おしらせ帯 — ロゴとサブキャッチ（やりたいことだけ、しよう。）の流れを切らないよう、
              サブキャッチの下・PRESS STARTの上に置く。ここならファーストビューにも収まる。 */}
          <QuakeNotice />

          <div className="pixbtn-wrap">
            <button className="pixbtn sage" onClick={() => setIntroOpen(true)}><span className="play">▶</span> PRESS START</button>
          </div>
          <div className="dot blink" style={{ fontSize: 12.5, color: t.soft, marginTop: 10, letterSpacing: ".1em" }}>
            - サイトのせつめい -
          </div>
        </div>

        <div className="sec-label dot" data-tour-scroll="select" style={{ justifyContent: "center", marginBottom: 16, width: "100%" }}>SELECT MODE</div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
          {FEATURES.map((f, i) => {
            const moodPending = (() => {
              try {
                const rec = JSON.parse(localStorage.getItem("rg_mood_today"));
                const d = new Date();
                const ld = new Date(d.getTime() - d.getTimezoneOffset() * 60000).toISOString().slice(0, 10);
                return !(rec && rec.date === ld);
              } catch (e) { return true; }
            })();
            const isNew = (typeof window.hasContentUpdate === "function" && window.hasContentUpdate(f.id))
              || (f.id === "community" && (moodPending || commNew))
              || (f.id === "blog" && blogNew)
              || (f.id === "video" && videoNew)
              || (f.id === "pace" && paceNew)
              || (f.id === "project" && projNew)
              || (f.id === "friends" && typeof window.hasNewUnlock === "function" && window.hasNewUnlock());
            const card = (
              <div className="hardshadow gcard pixbox profile-card" key={f.id} style={{ background: t.card || f.bg }}>
                <div className="gcard-in">
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
                    <div className="feat-ico" style={{ width: 40, height: 40, justifyContent: "flex-start" }}>
                      <PixIcon glyph={f.glyph} color={f.accent} cell={5} />
                    </div>
                    {isNew
                      ? <span className="gcard-new-badge" aria-label="新着"></span>
                      : <span className="gnum">0{i + 1}</span>}
                  </div>
                  <div className="feat-title" style={{ fontSize: 16 }}>{f.title}</div>
                  <div className="feat-desc" style={{ fontSize: 14, lineHeight: 1.75, textWrap: "balance" }}>{f.desc}</div>
                </div>
              </div>
            );
            return f.href
              ? <a key={f.id} data-tour-id={f.id === "community" ? "community" : f.id === "friends" ? "friends" : undefined} href={f.href} style={{ textDecoration: "none", color: "inherit", display: "block" }}>{card}</a>
              : card;
          })}
        </div>
      </div>

      {/* やりたいこと（テキストのみ残す） */}
      {/* PRESS START はSELECT MODEの上に移動済み */}

      {/* 改装中バナー（カード群とパンダNOWの間） */}
      <ConstructionBanner />

      {/* パンダNOW！（プロフィールの上） */}
      {window.PandaNow ? <window.PandaNow /> : null}

      {/* プロフィール / あいさつ — 横レイアウト（立ち姿 左・テキスト 右）/ クリックで詳細へ */}
      <div style={{ padding: "32px 16px 0" }}>
        <div className="sec-label dot" style={{ justifyContent: "center", marginBottom: 16, width: "100%" }}>PROFILE</div>
        <a href="profile.html" style={{ textDecoration: "none", color: "inherit", display: "block" }}>
          <div className="hardshadow pixbox profile-card" style={{ background: t.panel, padding: "22px 18px" }}>
            <div style={{ display: "flex", gap: 18, alignItems: "center" }}>
              <div style={{ flex: "0 0 auto", width: 108, height: 100, position: "relative" }}>
                <div style={{ position: "absolute", left: "50%", top: "50%", transform: "translate(-50%,-50%) scale(0.58)" }}>
                  <Mascot which="poyan" pose="stand" />
                </div>
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div className="dot" style={{ fontSize: 21.5, marginBottom: 10, color: t.fg }}>パンダ</div>
                <p className="feat-desc" style={{ margin: 0, color: t.fg }}>
                  シングルファザー。<br />だいじょうぶ、ここは、そのままでいい場所です。
                </p>
                <div className="dot" style={{ fontSize: 13.5, color: "var(--sage-d)", marginTop: 12, letterSpacing: ".04em" }}>くわしく見る ▶</div>
              </div>
            </div>
          </div>
        </a>
      </div>

      {/* サイトへのご意見・不具合報告 */}
      <FeedbackBox />

      {/* ひみつけっしゃ バナー（サポーター・企業様向け / ダークで別物） */}
      <div style={{ padding: "30px 16px 0" }}>
        <a href="secret.html" className="secret-banner" style={{ textDecoration: "none", display: "block", position: "relative" }}>
          {secretNew && <span className="sb-new-badge" aria-label="新着"></span>}
          <div className="sb-head">
            <div className="sb-ico">
              <PixIcon glyph="lock" color="var(--sage-d)" cell={5} />
            </div>
            <div className="sb-tx">
              <div className="sb-tag dot">FOR SUPPORTERS &amp; PARTNERS</div>
              <div className="sb-title">ひみつけっしゃ</div>
            </div>
            <span className="sb-arr dot">▶</span>
          </div>
          <div className="sb-desc">サポーター・企業様向け。表には書いてない、ここだけの話。</div>
        </a>
      </div>

      <div className="foot dot" style={{ textAlign: "center", padding: "28px 0 28px", fontSize: 12.5 }}>
        © 2026 405 JUST FOUND — INSERT, NOT COIN
        <span style={{ display: "block", marginTop: 6, fontSize: 10, opacity: 0.45 }}>build {window.SITE_BUILD || "?"}</span>
      </div>
    </div>
  );
}

/* ============================================================
   App
   ============================================================ */
const W = 384;
function App() {
  return (
    <DesignCanvas>
      <DCSection
        id="lp"
        title="ポートフォリオLP「405 Just Found」"
        subtitle="ピコ（閲覧者）が本音をランダムにつぶやく ・ 8bitレトロ × ミニマル ・ スマホ縦長"
      >
        <DCArtboard id="console" label="405 Just Found · PLAYER SELECT" width={W} height={1573}><VariantC /></DCArtboard>
        <DCPostIt id="note" top={120} left={470} width={250} rotate={-2}>
          ファーストビューのピコは、開くたびに「立ち／手をふる／寝てる」をランダム表示。ピコの本音もタイプライターでランダムに流れます。
        </DCPostIt>
      </DCSection>
    </DesignCanvas>
  );
}

Object.assign(window, { VariantC });
if (!window.__LP_STANDALONE) {
  ReactDOM.createRoot(document.getElementById("root")).render(<App />);
}
