blob: f5dc55c178e0d2a9f1d9d08921e0ac8c069435bd (
plain) (
tree)
|
|
import React, { useState, useEffect } from 'react'
import { LoadingScreen } from './LoadingScreen'
import { HeartLogo } from './HeartLogo'
// Using direct PNG logo on landing header
interface LandingPageProps {
onLogin: () => void
}
export function LandingPage({ onLogin }: LandingPageProps) {
const [loading, setLoading] = useState(false)
const [showLanding, setShowLanding] = useState(false)
const [isStandby, setIsStandby] = useState(true) // false = LIVE, true = STDBY
const [asciiArt, setAsciiArt] = useState('')
const [isGlitching, setIsGlitching] = useState(false)
// Note: Removed VN preview and ASCII features to focus on an Art Deco/Nouveau landing.
// Auto-fade in landing page content after component mounts
useEffect(() => {
const timer = setTimeout(() => {
setShowLanding(true)
}, 500) // Delay before fading in content
return () => clearTimeout(timer)
}, [])
// Removed VN dialogue preview / typing effect.
// Load ASCII art for overlay in hero (right/bottom)
useEffect(() => {
fetch('/ascii/ascii1.txt')
.then((res) => res.text())
.then((txt) => setAsciiArt(txt.replace(/\n+$/, '')))
.catch(() => setAsciiArt(''))
}, [])
// Occasionally trigger a brief glitch on the word "futurist"
useEffect(() => {
let armTimer: number | undefined
let activeTimer: number | undefined
let cancelled = false
const arm = () => {
// Random delay between glitches: 0.8s–2s (slightly punchier)
const delay = 800 + Math.random() * 1200
armTimer = window.setTimeout(() => {
setIsGlitching(true)
// Glitch duration: 150ms–350ms (snappier)
const dur = 150 + Math.random() * 200
activeTimer = window.setTimeout(() => {
setIsGlitching(false)
if (!cancelled) arm()
}, dur)
}, delay)
}
arm()
return () => {
cancelled = true
if (armTimer) clearTimeout(armTimer)
if (activeTimer) clearTimeout(activeTimer)
}
}, [])
// Handle loading screen completion
const handleLoadingComplete = () => {
// Call the original onLogin immediately to transition to VN page
// Don't reset loading states as we're leaving the landing page
onLogin()
}
// Handle login button click
const handleLogin = () => {
setLoading(true)
}
// Removed ASCII art effects and rendering.
return (
<div>
{loading && (
<LoadingScreen onComplete={handleLoadingComplete} />
)}
{/* Floating Header Bar - Hidden during loading */}
{!loading && (
<div className={`floating-header ${showLanding ? 'fade-in' : 'hidden'}`}>
<div className="header-content">
<div className="brand">
<img
src="/logo/crane-logo-transparent.png"
alt="Soryu"
height={40}
className="brand-mark"
onError={(e) => { const img = (e.currentTarget as HTMLImageElement); img.onerror = null; img.src = '/logo/crane-logo.png'; }}
/>
</div>
<div className="header-center">
<HeartLogo size="header-no-rays" className="header-heart" />
</div>
<div className="system-info">
<div className="info-item">
<span className="info-label">System:</span>
<span
className="info-value live-status clickable"
onClick={() => setIsStandby(!isStandby)}
title="Click to toggle between LIVE and STANDBY"
>
<span className={`status-dot ${isStandby ? 'standby' : 'live'}`}></span>
{isStandby ? 'STDBY' : 'LIVE'}
</span>
</div>
<div className="info-item">
<span className="info-label">Version:</span>
<span className="info-value">v1.0.0</span>
</div>
</div>
</div>
</div>
)}
<div className={`modern-landing-page manga-style ${showLanding && !loading ? 'fade-in' : 'hidden'}`}>
{/* Retro-futuristic page background */}
<div className="rf-page-bg" aria-hidden="true">
<div className="rf-page-speedlines layer-a"></div>
<div className="rf-page-speedlines layer-b"></div>
</div>
{/* Taisho Magazine Cover Backdrop */}
<div className="taisho-cover">
<div className="cover-backdrop" aria-hidden="true"></div>
{/* Cover Content Grid */}
<div className="cover-content">
{/* Vertical Masthead (magazine-style) */}
<div className="masthead">
<div className="masthead-vertical">
<span className="jp">そりゅう</span>
<span className="en">SORYU</span>
</div>
<div className="issue-badge">かはいい Vol.01</div>
</div>
{/* Central Hero - full-frame retro-futuristic */}
<div className="hero">
<div className="hero-frame taisho-modern-frame">
<div className="hero-inner hero-fill">
{/* Retro-futuristic racing hero content */}
<div className="rf-hero" aria-hidden="true">
<div className="rf-speedlines layer-a"></div>
<div className="rf-speedlines layer-b"></div>
<div className="rf-hero-content">
<div className="rf-badge">Engineering • Systems • para bellum</div>
<h2 className="rf-headline">
Mission driven{' '}
<span
className={`glitch-word ${isGlitching ? 'is-glitching' : ''}`}
data-text="futurist"
>
futurist
</span>{' '}
technology
</h2>
<p className="rf-tagline">Avant-garde. Aesthetic Engineering. A Race of Steel</p>
<div className="rf-stats">
<div className="rf-stat"><span className="label">Velocity</span><span className="value">0–603 km/h</span></div>
<div className="rf-stat"><span className="label">Energy</span><span className="value">32 MJ</span></div>
<div className="rf-stat"><span className="label">Flow</span><span className="value">MAX</span></div>
</div>
</div>
<div className="rf-accent-diagonal"></div>
{/* ASCII overlay (transparent, gradient text) */}
{asciiArt && (
<div className="rf-ascii-overlay" aria-hidden="true">
{asciiArt.split('\n').map((line, i) => (
<div key={i} className="ascii-line">
{Array.from(line).map((ch, j) => (
<span
key={`${i}-${j}`}
className="ascii-char"
style={{
'--delay': `${(i * 0.08 + j * 0.01)}s`,
} as React.CSSProperties}
>
{ch}
</span>
))}
</div>
))}
</div>
)}
</div>
</div>
</div>
</div>
{/* CTA */}
<div className="cta-area">
<button className="taisho-cta" onClick={handleLogin}>
<span className="cta-icon">▶</span>
<span className="cta-text">Enter</span>
</button>
</div>
{/* Visitor Counter */}
<div className="visit-counter" aria-label="visitor counter">
<img
src="https://count.getloli.com/get/@soryu-landing?theme=booru-jaypee&darkmode=0"
alt="visit counter"
referrerPolicy="no-referrer-when-downgrade"
/>
</div>
</div>
</div>
</div>
</div>
)
}
|