136ceff69f
Rebuilds the landing page from the prototype: 1900px scale-to-fit hero with hand-drawn SVG-jitter frames, typewriter input + start button, 5 horizontal collapsible category selectors (with style-picker modal), 7 scattered hero cards over a 16-card masonry gallery, and project intro panel. Each card is filled with a Runware FLUX.2 image, pre-generated and stored as WebP (~2 MB total for 30 cards). Hero card content + image switches by 性向 (男性向 / 女性向); gallery stays shared. Hover overlay on every card shows title + outline in a bottom-up dark gradient, matching the prior homepage's interaction style. Bug fixes uncovered by tracing the form-state → engine pipeline: - 「语音配音:关闭」was previously stuffed into styleGuide (consumed only by FLUX, ignored by TTS). Now serialized as audioEnabled boolean in the sessionStorage payload; play page's fetchBeatAudio early-returns when false, so no /api/beat-audio request fires. - 「绘画风格:自动」used to pass the literal Chinese phrase "由模型根据 prompt 自动判断画风" to FLUX, which painted it as text. Now maps to the 二次元/galgame default prompt. Adds reusable scripts under apps/web/scripts/: - generate-home-images.mjs — Runware FLUX.2 idempotent batch generator - optimize-home-images.mjs — sharp WebP downscale + recompress Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
45 lines
1.7 KiB
TypeScript
45 lines
1.7 KiB
TypeScript
import type { Metadata } from "next";
|
|
import "./globals.css";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "InfiPlot — AI 实时交互剧情游戏",
|
|
description: "InfiPlot 是一款用 AI 实时生成图片、语音与剧情分支的交互式剧情游戏 Demo。",
|
|
};
|
|
|
|
export default function RootLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode;
|
|
}) {
|
|
return (
|
|
<html lang="zh-CN" suppressHydrationWarning>
|
|
<head>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
|
|
<link
|
|
rel="stylesheet"
|
|
href="https://fonts.googleapis.com/css2?family=Patrick+Hand&family=Noto+Sans+SC:wght@300;400;500;600;700&display=swap"
|
|
/>
|
|
</head>
|
|
<body className="min-h-screen overflow-x-hidden">
|
|
{/* Hand-drawn jitter filters used by every .frame element */}
|
|
<svg width="0" height="0" style={{ position: "absolute" }} aria-hidden>
|
|
<filter id="s1">
|
|
<feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="2" seed="7" result="n" />
|
|
<feDisplacementMap in="SourceGraphic" in2="n" scale="1.2" />
|
|
</filter>
|
|
<filter id="s2">
|
|
<feTurbulence type="fractalNoise" baseFrequency="0.016" numOctaves="2" seed="4" result="n" />
|
|
<feDisplacementMap in="SourceGraphic" in2="n" scale="2.6" />
|
|
</filter>
|
|
<filter id="s3">
|
|
<feTurbulence type="fractalNoise" baseFrequency="0.022" numOctaves="3" seed="11" result="n" />
|
|
<feDisplacementMap in="SourceGraphic" in2="n" scale="4.2" />
|
|
</filter>
|
|
</svg>
|
|
{children}
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|