summaryrefslogblamecommitdiff
path: root/frontend/src/components/LandingPage.tsx
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>
  )
}