<!DOCTYPE html>

<html lang="vi">

<head>

  <meta charset="UTF-8">

  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>DeutschLernen Hub - Antigravity Edition</title>

  <script src="https://cdn.tailwindcss.com"></script>

  <script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></script>

  <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossorigin></script>

  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

  <script src="https://unpkg.com/lucide@latest"></script>

  <style>

    body { background-color: #0b0f19; color: #f3f4f6; overflow-x: hidden; }

    #antigravity-canvas { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 0; pointer-events: none; }

    .card-inner { transition: transform 0.6s; transform-style: preserve-3d; }

    .card-flipped { transform: rotateY(180deg); }

    .card-front, .card-back { backface-visibility: hidden; }

    .card-back { transform: rotateY(180deg); }

    .app-container { position: relative; z-index: 10; }

  </style>

</head>

<body>

  <canvas id="antigravity-canvas"></canvas>

  <div id="root" class="app-container"></div>


  <script type="text/babel">

    const { useState, useEffect } = React;


    function initAntigravityPhysics() {

      const canvas = document.getElementById('antigravity-canvas');

      if (!canvas) return;

      const ctx = canvas.getContext('2d');

      let width = canvas.width = window.innerWidth;

      let height = canvas.height = window.innerHeight;


      const words = ['Hallo', 'Tschüss', 'Liebe', 'Danke', 'Lernen', 'der', 'die', 'das', 'Brot', 'Wasser', 'Zeit', 'Sonne', 'Welt', 'Freund'];

      const particles = [];

      const mouse = { x: -1000, y: -1000, radius: 150 };


      window.addEventListener('mousemove', (e) => { mouse.x = e.clientX; mouse.y = e.clientY; });

      window.addEventListener('resize', () => { width = canvas.width = window.innerWidth; height = canvas.height = window.innerHeight; });


      for (let i = 0; i < 35; i++) {

        particles.push({

          x: Math.random() * width,

          y: height + Math.random() * 200,

          text: words[Math.floor(Math.random() * words.length)],

          vx: (Math.random() - 0.5) * 0.8,

          vy: -(Math.random() * 1.5 + 0.5),

          size: Math.floor(Math.random() * 14) + 14,

          alpha: Math.random() * 0.5 + 0.2

        });

      }


      function animate() {

        ctx.clearRect(0, 0, width, height);

        particles.forEach(p => {

          p.x += p.vx;

          p.y += p.vy;


          const dx = mouse.x - p.x;

          const dy = mouse.y - p.y;

          const dist = Math.sqrt(dx * dx + dy * dy);

          if (dist < mouse.radius) {

            const angle = Math.atan2(dy, dx);

            const force = (mouse.radius - dist) / mouse.radius;

            p.x -= Math.cos(angle) * force * 5;

            p.y -= Math.sin(angle) * force * 5;

          }


          if (p.y < -50) { p.y = height + 50; p.x = Math.random() * width; }

          if (p.x < -50) p.x = width + 50;

          if (p.x > width + 50) p.x = -50;


          ctx.font = `${p.size}px sans-serif`;

          ctx.fillStyle = `rgba(56, 189, 248, ${p.alpha})`;

          ctx.shadowBlur = 8;

          ctx.shadowColor = 'rgba(56, 189, 248, 0.4)';

          ctx.fillText(p.text, p.x, p.y);

        });

        requestAnimationFrame(animate);

      }

      animate();

    }


    function App() {

      const [tab, setTab] = useState('flashcard');

      const [xp, setXp] = useState(120);

      const [streak, setStreak] = useState(5);

      const [cardIndex, setCardIndex] = useState(0);

      const [isFlipped, setIsFlipped] = useState(false);

      const [quizIndex, setQuizIndex] = useState(0);

      const [score, setScore] = useState(0);


      const vocabList = [

        { de: 'Hallo', vi: 'Xin chào', type: 'Chào hỏi', ex: 'Hallo, wie geht es dir?' },

        { de: 'Guten Morgen', vi: 'Chào buổi sáng', type: 'Chào hỏi', ex: 'Guten Morgen, Frau Müller!' },

        { de: 'Danke schön', vi: 'Cảm ơn nhiều', type: 'Giao tiếp', ex: 'Vielen Dank für Ihre Hilfe.' },

        { de: 'Das Brot', vi: 'Bánh mì', type: 'Thức ăn', ex: 'Ich esse Brot zum Frühstück.' },

        { de: 'Die Zeit', vi: 'Thời gian', type: 'Danh từ', ex: 'Ich habe keine Zeit.' }

      ];


      const quizList = [

        { q: "Mạo từ của 'Brot' (Bánh mì) là gì?", options: ["Der", "Die", "Das"], correct: 2 },

        { q: "'Guten Tag' có nghĩa là gì?", options: ["Chào buổi sáng", "Chào buổi chiều/ngày", "Chúc ngủ ngon"], correct: 1 },

        { q: "Động từ 'Sein' ở ngôi 'Ich' chia là gì?", options: ["bist", "ist", "bin"], correct: 2 }

      ];


      useEffect(() => {

        initAntigravityPhysics();

        if (window.lucide) window.lucide.createIcons();

      }, []);


      const playAudio = (text) => {

        if ('speechSynthesis' in window) {

          const utterance = new SpeechSynthesisUtterance(text);

          utterance.lang = 'de-DE';

          window.speechSynthesis.speak(utterance);

        }

      };


      return (

        <div class="min-h-screen flex flex-col items-center p-4">

          <header class="w-full max-w-4xl flex justify-between items-center py-4 border-b border-gray-800 mb-6">

            <h1 class="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-amber-400 via-rose-500 to-cyan-400">

              DeutschLernen Hub ✨

            </h1>

            <div class="flex gap-4">

              <span class="bg-amber-500/10 text-amber-400 px-3 py-1 rounded-full text-sm font-semibold border border-amber-500/20">🔥 {streak} Ngày</span>

              <span class="bg-cyan-500/10 text-cyan-400 px-3 py-1 rounded-full text-sm font-semibold border border-cyan-500/20">⚡ {xp} XP</span>

            </div>

          </header>


          <nav class="flex gap-2 mb-8 bg-gray-900/80 p-1.5 rounded-xl border border-gray-800 backdrop-blur">

            {['flashcard', 'quiz', 'grammar'].map(t => (

              <button 

                key={t}

                onClick={() => setTab(t)}

                class={`px-5 py-2 rounded-lg text-sm font-medium capitalize transition-all ${

                  tab === t ? 'bg-gradient-to-r from-amber-500 to-rose-500 text-white shadow-lg' : 'text-gray-400 hover:text-white'

                }`}

              >

                {t === 'flashcard' ? 'Thẻ từ vựng' : t === 'quiz' ? 'Trắc nghiệm' : 'Ngữ pháp'}

              </button>

            ))}

          </nav>


          <main class="w-full max-w-md">

            {tab === 'flashcard' && (

              <div class="flex flex-col items-center">

                <div onClick={() => setIsFlipped(!isFlipped)} class="w-full h-64 cursor-pointer perspective-1000 relative">

                  <div class={`w-full h-full card-inner rounded-2xl bg-gray-900/90 border border-gray-800 p-6 flex flex-col justify-between shadow-2xl backdrop-blur ${isFlipped ? 'card-flipped' : ''}`}>

                    <div class="card-front absolute inset-0 p-6 flex flex-col justify-between items-center text-center">

                      <span class="text-xs text-amber-400 bg-amber-500/10 px-2.5 py-1 rounded-full">{vocabList[cardIndex].type}</span>

                      <div>

                        <h2 class="text-4xl font-bold text-white mb-2">{vocabList[cardIndex].de}</h2>

                        <p class="text-gray-400 text-sm italic">{vocabList[cardIndex].ex}</p>

                      </div>

                      <button onClick={(e) => { e.stopPropagation(); playAudio(vocabList[cardIndex].de); }} class="p-3 bg-amber-500/20 text-amber-400 rounded-full hover:bg-amber-500/30">

                        🔊 Nghe phát âm

                      </button>

                    </div>

                    <div class="card-back absolute inset-0 p-6 flex flex-col justify-center items-center text-center bg-gray-900 rounded-2xl">

                      <h3 class="text-3xl font-bold text-cyan-400 mb-2">{vocabList[cardIndex].vi}</h3>

                      <p class="text-gray-400 text-sm">Bấm để lật lại mặt trước</p>

                    </div>

                  </div>

                </div>


                <div class="flex gap-4 mt-6 w-full">

                  <button onClick={() => { setIsFlipped(false); setCardIndex((prev) => (prev > 0 ? prev - 1 : vocabList.length - 1)); }} class="flex-1 py-3 bg-gray-800 hover:bg-gray-700 rounded-xl font-medium">Trước</button>

                  <button onClick={() => { setIsFlipped(false); setCardIndex((prev) => (prev + 1) % vocabList.length); }} class="flex-1 py-3 bg-gradient-to-r from-amber-500 to-rose-500 text-white rounded-xl font-medium">Tiếp theo</button>

                </div>

              </div>

            )}


            {tab === 'quiz' && (

              <div class="bg-gray-900/90 p-6 rounded-2xl border border-gray-800 backdrop-blur">

                <h3 class="text-lg font-bold mb-4 text-cyan-400">Câu {quizIndex + 1}/{quizList.length}</h3>

                <p class="text-xl mb-6">{quizList[quizIndex].q}</p>

                <div class="flex flex-col gap-3">

                  {quizList[quizIndex].options.map((opt, idx) => (

                    <button 

                      key={idx}

                      onClick={() => {

                        if (idx === quizList[quizIndex].correct) { setXp(prev => prev + 10); setScore(prev => prev + 1); }

                        if (quizIndex < quizList.length - 1) setQuizIndex(prev => prev + 1);

                        else alert(`Hoàn thành! Bạn đạt ${score + (idx === quizList[quizIndex].correct ? 1 : 0)}/${quizList.length} điểm.`);

                      }}

                      class="w-full py-3 px-4 bg-gray-800/80 hover:bg-amber-500/20 hover:border-amber-500/50 border border-gray-700 rounded-xl text-left transition"

                    >

                      {opt}

                    </button>

                  ))}

                </div>

              </div>

            )}


            {tab === 'grammar' && (

              <div class="bg-gray-900/90 p-6 rounded-2xl border border-gray-800 backdrop-blur space-y-4">

                <h3 class="text-xl font-bold text-amber-400 mb-2">Mạo từ trong tiếng Đức (Artikel)</h3>

                <div class="p-3 bg-gray-800/50 rounded-lg border-l-4 border-cyan-400">

                  <p class="font-bold text-cyan-400">DER (Giống đực)</p>

                  <p class="text-sm text-gray-300">Dùng cho nam giới, các ngày trong tuần, tháng, mùa.</p>

                </div>

                <div class="p-3 bg-gray-800/50 rounded-lg border-l-4 border-rose-400">

                  <p class="font-bold text-rose-400">DIE (Giống cái)</p>

                  <p class="text-sm text-gray-300">Dùng cho nữ giới, đa số danh từ kết thúc bằng -ung, -heit, -keit.</p>

                </div>

                <div class="p-3 bg-gray-800/50 rounded-lg border-l-4 border-amber-400">

                  <p class="font-bold text-amber-400">DAS (Giống trung)</p>

                  <p class="text-sm text-gray-300">Dùng cho danh từ kết thúc bằng -chen, -lein, từ mượn.</p>

                </div>

              </div>

            )}

          </main>

        </div>

      );

    }


    ReactDOM.createRoot(document.getElementById('root')).render(<App />);

  </script>

</body>

</html>