Models 44

Xing4.0 29B A4B (free)

by XingChenreasoning offClean
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
4 min 22 s
Cost
$0
Output tokens
12,022
Spent thinking
0 tokens
Speed
46.1 tok/s
Console errors
0
First token after
1.3 s
First visible text after
1.3 s
Prompt tokens
379
Code size
30.8 KB
Finish reason
stop
Served by
Phala
Model id
xingchen-agi/xing4.0-29b-a4b:free
Reasoning sent
{"effort":"none"}
Max output
32,000 tokens
Generated
Nov 9, 2026

What it was asked

The prompt
“i'm opening a korean taco food truck called "Kimchi Loco", make me a website that makes people really want to come”
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task.

Output rules:
- Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block.
- Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task.
- Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw.
- The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar.
- Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction.
- Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session.
- Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing.
- The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message.
- The code must run with zero errors in the console of the latest Chrome.

Code run-1.html · 687 lines

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kimchi Loco | Korean Taco Truck</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
@import url('https://fonts.googleapis.com/css2?family=Han+Sans:wght@400;700;900&family=Noto+Sans+KR:wght@300;500;700;900&display=swap');
:root{--fire:#ff4500;--fire2:#ff6b00;--blood:#c0392b;--cheese:#f9e5a0;--nori:#2d6a4f;--soy:#f0d9b0;--tomato:#e63946;--burrito:#ffe5a0;--base:#fff8ee;--ink:#1a1a1a}
html{scroll-behavior:smooth}
body{font-family:'Noto Sans KR',sans-serif;background:var(--base);color:var(--ink);overflow-x:hidden;line-height:1.6}
h1,h2{font-family:'Han Sans',serif;font-weight:900}
.wrap{max-width:1280px;margin:0 auto;padding:0 20px}

/* NAV */
nav{position:fixed;top:0;left:0;right:0;z-index:100;background:rgba(255,248,238,.92);backdrop-filter:blur(12px);border-bottom:2px solid var(--soy)}
nav .wrap{display:flex;align-items:center;justify-content:space-between;height:70px}
.logo{display:flex;align-items:center;gap:10px;cursor:pointer;font-size:1.5rem;font-weight:900;color:var(--blood)}
.logo .logo-icon{width:40px;height:40px;background:linear-gradient(135deg,var(--fire),var(--blood));border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:1.3rem}
.nav-links{display:flex;gap:28px;list-style:none}
.nav-links a{text-decoration:none;color:var(--ink);font-weight:700;font-size:.9rem;text-transform:uppercase;letter-spacing:1px;transition:.2s;position:relative}
.nav-links a::after{content:'';position:absolute;bottom:-4px;left:0;width:0;height:2px;background:var(--fire);transition:.3s}
.nav-links a:hover::after{width:100%}

/* HERO */
header{min-height:100vh;display:flex;align-items:center;justify-content:center;background:linear-gradient(120deg,var(--fire) 0%,var(--blood) 40%,#8e2a1f 100%);position:relative;overflow:hidden}
header::before{content:'';position:absolute;inset:0;background:radial-gradient(circle at 20% 50%,rgba(255,200,0,.3) 0%,transparent 50%),radial-gradient(circle at 80% 50%,rgba(255,69,0,.3) 0%,transparent 50%)}
header::after{content:'🌶️';position:absolute;font-size:20vw;opacity:.06;animation:floatParticle 6s ease-in-out infinite}
@keyframes floatParticle{0%,100%{transform:translateY(0) rotate(0deg)}50%{transform:translateY(-30px) rotate(180deg)}}
.hero{text-align:center;z-index:1;padding:20px;animation:fadeInUp 1s ease}
@keyframes fadeInUp{from{opacity:0;transform:translateY(40px)}to{opacity:1;transform:translateY(0)}}
.hero h1{font-size:clamp(3rem,8vw,7rem);color:#fff;line-height:1.05;text-shadow:0 4px 30px rgba(0,0,0,.4);margin-bottom:16px}
.hero h1 em{font-style:normal;background:linear-gradient(180deg,#fff,#ffcd6f);-webkit-background-clip:text;-webkit-text-fill-color:transparent;position:relative}
.hero h1 em::after{content:attr(data-emoji);position:absolute;-webkit-text-fill-color:initial;font-size:1.1em;top:15%;left:-5%;animation:wobble 2s ease infinite}
@keyframes wobble{0%,100%{transform:rotate(-5deg)}50%{transform:rotate(5deg)}}
.hero p{color:var(--cheese);font-size:clamp(.9rem,2vw,1.2rem);font-weight:500;margin-bottom:30px;text-shadow:0 2px 10px rgba(0,0,0,.5)}
.hero-btn{display:inline-block;padding:18px 50px;background:#fff;color:var(--fire);font-weight:900;font-size:1.2rem;border:none;border-radius:50px;cursor:pointer;transition:.3s;text-transform:uppercase;letter-spacing:2px;box-shadow:0 8px 30px rgba(0,0,0,.3)}
.hero-btn:hover{transform:translateY(-3px) scale(1.03);background:var(--cheese)}

/* SUBHERO */
.subhero{background:var(--fire);color:#fff;text-align:center;padding:80px 20px;display:flex;flex-direction:column;align-items:center;justify-content:center;position:relative;overflow:hidden}
.subhero h2{font-size:clamp(2rem,5vw,3.5rem);margin-bottom:16px}
.subhero p{font-size:1.15rem;opacity:.9;max-width:600px;margin-bottom:30px}
.subhero-buttons{display:flex;gap:16px;flex-wrap:wrap;justify-content:center}
.subhero-buttons button{padding:14px 34px;border-radius:50px;font-weight:900;font-size:1rem;cursor:pointer;border:3px solid #fff;transition:.3s}
.btn-menu{background:#fff;color:var(--fire)}
.btn-menu:hover{background:var(--cheese)}
.btn-location{background:transparent;color:#fff}
.btn-location:hover{background:rgba(255,255,255,.2)}

/* SECTIONS */
section{padding:100px 0}
.section-label{display:inline-block;color:var(--fire);font-weight:900;letter-spacing:3px;font-size:1rem;text-transform:uppercase;margin-bottom:12px}
.section-title{font-size:clamp(2rem,5vw,3rem);text-align:center;margin-bottom:50px}
.section-title span{color:var(--fire)}
.section-desc{text-align:center;color:#666;max-width:550px;margin:0 auto 50px;font-size:1.05rem}

/* DISHES GRID */
.dishes-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:28px;max-width:1200px;margin:0 auto}
.dish-card{background:#fff;border-radius:20px;overflow:hidden;border:2px solid var(--soy);transition:.3s;position:relative}
.dish-card:hover{transform:translateY(-6px);box-shadow:0 15px 40px rgba(255,69,0,.15)}
.dish-img{width:100%;height:220px;object-fit:cover;display:flex;align-items:center;justify-content:center;font-size:8rem;position:relative}
.dish-img::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,transparent 50%,rgba(0,0,0,.1))}
.dish-body{padding:24px}
.dish-name{font-size:1.3rem;font-weight:900;color:var(--blood);margin-bottom:8px}
.dish-emoji{position:absolute;top:12px;right:12px;font-size:2.5rem;filter:drop-shadow(0 4px 8px rgba(0,0,0,.3))}
.dish-tag{display:inline-block;background:var(--soy);color:var(--ink);font-size:.7rem;font-weight:700;padding:4px 12px;border-radius:20px;margin-bottom:12px}
.dish-desc{color:#555;font-size:.95rem;margin-bottom:16px}
.dish-price{font-weight:900;color:var(--fire);font-size:1.2rem}
.dish-price small{font-size:.85rem;color:#aaa;font-weight:400}

/* TRUCK VISUAL */
.truck-section{background:linear-gradient(135deg,var(--fire),var(--blood))}
.truck-visual{text-align:center;margin-bottom:40px}
.truck-svg{width:100%;max-width:700px;height:auto;border-radius:30px;background:rgba(255,255,255,.1);padding:30px;margin:0 auto}

/* LOCATION */
.map-section{background:#fff;overflow:hidden}
.map-container{display:grid;grid-template-columns:1fr 1fr;gap:0;max-width:1200px;margin:0 auto;padding:0 20px}
.info-panel{padding:40px}
.info-panel h3{color:var(--fire);font-size:1.5rem;margin-bottom:12px}
.info-panel p{color:#666;margin-bottom:8px}
.info-panel .hours{background:var(--soy);display:inline-block;padding:6px 16px;border-radius:20px;font-weight:700;color:var(--ink);margin:8px 0}
.info-panel ul{list-style:none;padding:0}
.info-panel li{padding:6px 0;border-bottom:1px solid var(--soy)}
.info-panel li::before{content:'✅ ';font-size:.8rem}
.map-placeholder{background:repeating-linear-gradient(45deg,#eee,#eee 10px,#ddd 10px,#ddd 20px);min-height:350px;display:flex;align-items:center;justify-content:center;border-radius:30px;color:#999;font-size:1rem;position:relative}
.map-placeholder svg{position:absolute;width:120px;height:120px;color:#ccc}

/* TESTIMONIALS */
testimonials-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:28px;max-width:1200px;margin:0 auto;padding:0 20px}
.testimonial-card{background:#fff;border-radius:20px;padding:32px;border-left:5px solid var(--fire);position:relative}
.testimonial-card .quote-mark{font-size:3rem;color:var(--soy);line-height:1;position:absolute;top:10px;left:15px}
.testimonial-card blockquote{font-size:1.05rem;margin-bottom:16px;line-height:1.7}
.stars{color:var(--fire);font-size:1.2rem;letter-spacing:4px;margin-bottom:10px}
.testimonial-author{font-weight:700;color:var(--blood)}

/* CALENDAR / EVENTS */
events-section{background:var(--fire);color:#fff}
events-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:20px;max-width:1200px;margin:0 auto;padding:0 20px}
.event-card{background:rgba(255,255,255,.12);border-radius:16px;padding:24px;border:2px solid rgba(255,255,255,.2);transition:.3s;backdrop-filter:blur(5px)}
.event-card:hover{background:rgba(255,255,255,.2);transform:scale(1.02)}
.event-date{font-size:2rem;font-weight:900;color:var(--cheese);margin-bottom:8px}
.event-name{font-weight:700;font-size:1.1rem;margin-bottom:6px}
.event-desc{opacity:.85;font-size:.9rem}
.event-link{display:inline-block;margin-top:12px;color:var(--cheese);font-weight:700;font-size:.85rem;text-decoration:underline}
.event-link:hover{color:#fff}

/* FOOTER */
footer{background:var(--blood);color:#fff;padding:60px 0 30px;text-align:center}
.footer-logo{font-size:2rem;font-weight:900;margin-bottom:8px}
.footer p{opacity:.8;margin-bottom:20px}
.social-row{display:flex;gap:16px;justify-content:center;margin-bottom:20px}
.social-btn{width:44px;height:44px;border-radius:50%;background:rgba(255,255,255,.15);display:flex;align-items:center;justify-content:center;font-size:1.2rem;cursor:pointer;transition:.3s}
.social-btn:hover{background:var(--cheese);transform:translateY(-3px)}
.footer-copy{font-size:.85rem;opacity:.6}

/* TOAST */
.toast{position:fixed;bottom:30px;left:50%;transform:translateX(-50%) translateY(100px);background:var(--ink);color:#fff;padding:14px 30px;border-radius:50px;font-weight:700;z-index:200;transition:.4s;box-shadow:0 10px 30px rgba(0,0,0,.3);opacity:0}
.toast.show{transform:translateX(-50%) translateY(0);opacity:1}

/* KEYBOARD OVERLAY */
.key-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);display:flex;align-items:center;justify-content:center;z-index:150;backdrop-filter:blur(4px);transition:.5s}
.key-overlay.hidden{opacity:0;pointer-events:none}
.key-box{background:#fff;padding:50px 70px;border-radius:30px;text-align:center;max-width:450px;box-shadow:0 30px 80px rgba(0,0,0,.4)}
.key-box h2{color:var(--fire);font-size:1.8rem;margin-bottom:12px}
.key-box p{color:#666;margin-bottom:24px}
.key-press{font-size:3rem;font-weight:900;color:var(--fire);cursor:pointer;user-select:none;transition:.3s}
.key-press:hover{transform:scale(1.1);color:#fff}
.key-press.ready{animation:pulse 1.5s ease infinite}
@keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.08)}}

/* RESPONSIVE */
@media(max-width:768px){
nav .nav-links{display:none}
.hero h1{font-size:2.2rem}
.hero-btn{padding:14px 32px;font-size:1rem}
.subhero h2{font-size:1.8rem}
.subhero-buttons{flex-direction:column;align-items:center}
.subhero-buttons button{width:100%;max-width:250px}
.map-container{grid-template-columns:1fr}
.dishes-grid{grid-template-columns:1fr}
.section{padding:60px 0}
.footer{padding:40px 20px 20px}
.social-row{flex-wrap:wrap;justify-content:center}
}
@media(max-width:480px){
.dish-img{height:180px}
.hero-btn{padding:12px 28px;font-size:.9rem}
.dish-body{padding:18px}
}

/* ANIMATIONS */
@keyframes slideIn{from{opacity:0;transform:translateX(60px)}to{opacity:1;transform:translateX(0)}}
.reveal{opacity:0;transform:translateY(40px);transition:.8s cubic-bezier(.4,0,.2,1)}
.reveal.visible{opacity:1;transform:translateY(0)}
</style>
</head>
<body>

<!-- KEYBOARD OVERLAY -->
<div class="key-overlay" id="keyOverlay">
  <div class="key-box">
    <h2>🚀 Kimchi Loco is LIVE!</h2>
    <p>Click or press any key to start the demo game</p>
    <div class="key-press ready" id="keyPressHint">▶ Click or Press Any Key</div>
  </div>
</div>

<!-- NAV -->
<nav>
  <div class="wrap">
    <div class="logo" onclick="window.scrollTo({top:0,behavior:'smooth'})">
      <div class="logo-icon">🌶️</div>
      <span>kimchi<span style="color:var(--fire)"> loco</span></span>
    </div>
    <ul class="nav-links">
      <li><a href="#dishes">Menu</a></li>
      <li><a href="#truck">Our Truck</a></li>
      <li><a href="#reviews">Stories</a></li>
      <li><a href="#events">Events</a></li>
      <li><a href="#contact">Contact</a></li>
    </ul>
  </div>
</nav>

<!-- HERO -->
<header id="hero">
  <div class="hero">
    <h1 data-emoji="🌮">Kimchi <em>Loco</em></h1>
    <p>Where Korea meets Mexico &middot; fire, spice &amp; pure flavor in every bite</p>
    <button class="hero-btn" onclick="document.getElementById('dishes').scrollIntoView()">See Our Menu →</button>
  </div>
</header>

<!-- SUBHERO -->
<section class="subhero" id="truck">
  <h2>The Truck That Roars</h2>
  <p>Fueled by gochugaru, fire-roasted peppers &amp; love — this taco truck doesn't just feed you, it <strong>transforms</strong> you. Every bite is a trip from Seoul to San Diego and back.</p>
  <div class="subhero-buttons">
    <button class="btn-menu" onclick="document.getElementById('dishes').scrollIntoView()">📋 Explore Menu</button>
    <button class="btn-location" onclick="document.getElementById('contact').scrollIntoView()">📍 Find Us</button>
  </div>
</section>

<!-- DISHES -->
<section id="dishes">
  <div class="wrap">
    <span class="section-label">MENU</span>
    <h2 class="section-title"><span>Our</span> Famous Dishes</h2>
    <p class="section-desc">Six legendary tacos that prove Korean flavors canrock Mexican shells — with zero compromises on heat, crunch, or carbs.</p>
  </div>
  <div class="dishes-grid" id="dishesGrid"></div>
</section>

<!-- TRUCK INFO -->
<section class="truck-section">
  <div class="wrap" style="text-align:center">
    <span class="section-label">OUR STORY</span>
    <h2 class="section-title"><span>Built</span> in Fire</h2>
    <p class="section-desc" style="color:rgba(255,255,255,.8)">From one brave founder's dream to a rolling empire of flavor. This truck was born on a rainy Tuesday when our chef dragged his Korean pantry into a parking lot and decided — nah, stay. Full stop.</p>
  </div>
  <div class="truck-visual">
    <svg viewBox="0 0 700 320" xmlns="http://www.w3.org/2000/svg">
      <!-- ground -->
      <rect x="0" y="280" width="700" height="40" fill="#3d2b1f"/>
      <rect x="0" y="280" width="700" height="6" fill="#5a3d2b"/>
      <!-- wheels -->
      <circle cx="130" cy="250" r="32" fill="#1a1a1a"/><circle cx="130" cy="250" r="14" fill="#888"/>
      <circle cx="570" cy="250" r="32" fill="#1a1a1a"/><circle cx="570" cy="250" r="14" fill="#888"/>
      <!-- truck body lower -->
      <path d="M80 200 Q80 160 180 160 L520 160 Q600 160 620 200 L620 250 L80 250 Z" fill="#c0392b"/>
      <path d="M80 195 L80 165 L180 165 L180 195 Z" fill="#e74c3c"/>
      <!-- side window -->
      <rect x="230" y="170" width="140" height="60" rx="8" fill="#87ceeb" opacity=".7"/>
      <rect x="230" y="170" width="140" height="60" rx="8" fill="none" stroke="#c0392b" stroke-width="3"/>
      <!-- exhaust pipes (fire!) -->
      <rect x="590" y="190" width="12" height="30" rx="6" fill="#ff4500"/>
      <circle cx="602" cy="220" r="8" fill="#ff8c00" opacity=".6"/>
      <circle cx="602" cy="220" r="4" fill="#ffdd00" opacity=".8"/>
      <!-- flag -->
      <line x1="120" y1="145" x2="120" y2="90" stroke="#1a1a1a" stroke-width="3"/>
      <path d="M120 90 L165 100 L120 110 Z" fill="#ff4500"/>
      <!-- handlebars -->
      <line x1="100" y1="155" x2="200" y2="140" stroke="#1a1a1a" stroke-width="5"/>
      <line x1="100" y1="155" x2="200" y2="165" stroke="#1a1a1a" stroke-width="5"/>
    </svg>
  </div>
</section>

<!-- MAP + CONTACT -->
<section class="map-section" id="contact">
  <div class="wrap">
    <span class="section-label">CONTACT</span>
    <h2 class="section-title"><span>Come</span> Say Hi</h2>
    <p class="section-desc" style="color:#666">Find us where all the action happens. Or just vibe with us at a random corner of town.</p>
  </div>
  <div class="map-container">
    <div class="info-panel">
      <h3>📍 Address</h3>
      <p>742 Paintbrush St, San Diego, CA 92103</p>
      <div class="hours">⏰ Hours: Tue–Sun 11am – 9pm</div>
      <ul>
        <li>🎉 Live music every Thursday</li>
        <li>🎁 Free kimbap samples Sat–Sun noon</li>
        <li>📱 Text <strong>760-555-KIMO</strong> for event invites</li>
        <li>💸 Vendor orders available Monday–Friday</li>
        <li>🌧️ We stay open even in the rain</li>
      </ul>
    </div>
    <div class="map-placeholder">
      <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>
      <p>Map coming soon — follow us on socials for real-time updates!</p>
    </div>
  </div>
</section>

<!-- REVIEWS -->
<section id="reviews">
  <div class="wrap">
    <span class="section-label">SOCIAL</span>
    <h2 class="section-title"><span>Happy</span> Voices</h2>
  </div>
  <div class="testimonials-grid" id="reviewsGrid"></div>
</section>

<!-- EVENTS -->
<section class="events-section" id="events">
  <div class="wrap">
    <span class="section-label">COMING UP</span>
    <h2 class="section-title"><span>Coming</span> Events</h2>
  </div>
  <div class="events-grid" id="eventsGrid"></div>
</section>

<!-- FOOTER -->
<footer>
  <div class="wrap">
    <div class="footer-logo">kimchi<span style="color:var(--cheese)">loco</span></div>
    <p>Where Fire Meets Flare 🔥🌮</p>
    <div class="social-row">
      <div class="social-btn" title="Instagram">📷</div>
      <div class="social-btn" title="TikTok">🎵</div>
      <div class="social-btn" title="Twitter">🐦</div>
      <div class="social-btn" title="YouTube">▶️</div>
      <div class="social-btn" title="Spotify">🎧</div>
    </div>
    <p class="footer-copy">© 2024 Kimchi Loco Taco Truck · Made with gochugaru & passion</p>
  </div>
</footer>

<!-- Toast -->
<div class="toast" id="toast"></div>

<script>
// ===================== GAME ENGINE =====================
// A simple memory-matching / pattern-recognition game
// The demo AI auto-plays by clicking cards

const GAME_STATE = {
  cards: [],
  flipped: [],
  matched: [],
  pairs: 0,
  moves: 0,
  startTime: null,
  started: false,
  aiPlaying: false,
  aiMoveTimeout: null,
};

const ICONS = ['🌶️','🥬','🧄','🥩','🥑','🍗','🐟','🍚','🥔','🧀','🫘','🥙'];

function initGame() {
  GAME_STATE.cards = shuffle([...ICONS, ...ICONS]);
  GAME_STATE.flipped = [];
  GAME_STATE.matched = [];
  GAME_STATE.moves = 0;
  GAME_STATE.pairs = 0;
  renderCards();
}

function shuffle(arr) {
  for (let i = arr.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [arr[i], arr[j]] = [arr[j], arr[i]];
  }
  return arr;
}

function renderCards() {
  const grid = document.getElementById('gameBoard') || createBoardEl();
  grid.innerHTML = '';
  GAME_STATE.cards.forEach((icon, idx) => {
    const card = document.createElement('div');
    card.className = 'game-card';
    card.dataset.icon = icon;
    card.dataset.idx = idx;
    if (GAME_STATE.matched.includes(idx)) {
      card.classList.add('matched');
      card.innerHTML = `<span class="card-back">🔥</span>`;
    } else if (GAME_STATE.flipped.includes(idx)) {
      card.classList.add('flipped');
      card.innerHTML = `<span style="font-size:2.5rem">${icon}</span>`;
    } else {
      card.classList.add('hidden');
      card.innerHTML = `<span style="font-size:2.5rem">❓</span>`;
    }
    card.addEventListener('click', () => handleCardClick(idx));
    grid.appendChild(card);
  });
}

function createBoardEl() {
  const board = document.createElement('div');
  board.className = 'game-board';
  return board;
}

function handleCardClick(idx) {
  if (!GAME_STATE.started) return;
  if (GAME_STATE.flipped.includes(idx) || GAME_STATE.matched.includes(idx)) return;
  if (GAME_STATE.aiPlaying && !GAME_STATE.started) return;
  flipCard(idx);
  checkMatch();
}

function flipCard(idx) {
  GAME_STATE.cards[idx] = GAME_STATE.cards[idx]; // no-op
  GAME_STATE.flipped.push(idx);
  updateCardVisual(idx);
  GAME_STATE.moves++;
  animateFlipped();
}

function updateCardVisual(idx) {
  const card = getCardEl(idx);
  if (!card) return;
  if (GAME_STATE.matched.includes(idx)) {
    card.classList.add('matched');
    card.innerHTML = `<span style="font-size:2.5rem">🔥</span>`;
  } else if (GAME_STATE.flipped.includes(idx)) {
    card.classList.remove('hidden');
    card.classList.add('flipped');
    card.innerHTML = `<span style="font-size:2.5rem">${GAME_STATE.cards[idx]}</span>`;
  }
}

function getCardEl(idx) {
  return document.querySelector(`.game-card[data-idx="${idx}"]`);
}

function animateFlipped() {}

function checkMatch() {
  const first = GAME_STATE.flipped[0];
  const second = GAME_STATE.flipped[1];
  if (first === undefined || second === undefined) return;

  GAME_STATE.aiPlaying = true;
  if (GAME_STATE.cards[first] === GAME_STATE.cards[second]) {
    // match!
    setTimeout(() => {
      GAME_STATE.matched.push(first, second);
      GAME_STATE.pairs++;
      renderCards();
      if (GAME_STATE.pairs === ICONS.length) {
        winGame();
      }
    }, 500);
  } else {
    setTimeout(() => {
      GAME_STATE.cards[first] = '❓';
      GAME_STATE.cards[second] = '❓';
      GAME_STATE.flipped = [];
      renderCards();
    }, 900);
  }
  GAME_STATE.flipped = [];
}

// ─── DEMO AI PLAYER ─────────────────────────────
function aiPlayerTurn() {
  if (!GAME_STATE.started || GAME_STATE.aiPlaying) return;
  // AI logic: find a pair that exists and flip both
  const attempts = 0;
  while (GAME_STATE.aiMoveTimeout) clearTimeout(GAME_STATE.aiMoveTimeout);
  
  // Simple approach: pick two matching cards if visible, else random unflipped
  const hiddenIdx = GAME_STATE.cards
    .map((v, i) => v !== '❓' && !GAME_STATE.flipped.includes(i) && !GAME_STATE.matched.includes(i) ? i : -1)
    .filter(i => i >= 0);
  
  if (hiddenIdx.length < 2) {
    // restart with new shuffled state occasionally
    return;
  }
  
  // Prefer matches: try to find a pair
  for (let a = 0; a < GAME_STATE.cards.length; a++) {
    if (GAME_STATE.cards[a] === '❓' || GAME_STATE.matched.includes(a)) continue;
    const sameIconIdx = hiddenIdx.filter(i => i !== a && GAME_STATE.cards[i] === GAME_STATE.cards[a]).find(i => !GAME_STATE.flipped.includes(i) && !GAME_STATE.matched.includes(i));
    if (sameIconIdx !== undefined) {
      GAME_STATE.aiPlaying = true;
      GAME_STATE.flipped.push(a, sameIconIdx);
      renderCards();
      if (GAME_STATE.cards[a] === GAME_STATE.cards[sameIconIdx]) {
        setTimeout(() => {
          GAME_STATE.matched.push(a, sameIconIdx);
          GAME_STATE.pairs++;
          renderCards();
          if (GAME_STATE.pairs === ICONS.length) winGame();
          else setTimeout(aiPlayerTurn, 600);
        }, 500);
      } else {
        setTimeout(() => {
          GAME_STATE.flipped = [];
          GAME_STATE.cards[a] = '❓';
          GAME_STATE.cards[sameIconIdx] = '❓';
          renderCards();
          GAME_STATE.aiPlaying = false;
          aiPlayerTurn();
        }, 1000);
      }
      return;
    }
  }
  
  // No match possible — flip two random
  GAME_STATE.aiPlaying = true;
  const pick = hiddenIdx.sort(() => Math.random() - 0.5).slice(0, 2);
  GAME_STATE.flipped.push(...pick);
  renderCards();
  setTimeout(() => {
    if (GAME_STATE.cards[pick[0]] === GAME_STATE.cards[pick[1]]) {
      GAME_STATE.matched.push(pick[0], pick[1]);
      GAME_STATE.pairs++;
      renderCards();
      if (GAME_STATE.pairs === ICONS.length) winGame();
      else setTimeout(aiPlayerTurn, 500);
    } else {
      GAME_STATE.flipped = [];
      GAME_STATE.cards[pick[0]] = '❓';
      GAME_STATE.cards[pick[1]] = '❓';
      renderCards();
      GAME_STATE.aiPlaying = false;
      aiPlayerTurn();
    }
  }, 1000);
}

// ─── WIN SCREEN ──────────────────────────────────
function winGame() {
  GAME_STATE.aiPlaying = false;
  GAME_STATE.started = false;
  showToast(`🎉 You won! ${GAME_STATE.moves} moves · ${(Date.now()-GAME_STATE.startTime)/1000}s`);
  setTimeout(() => initGame(), 2000);
}

// ─── INIT ────────────────────────────────────────
function setupGame() {
  initGame();
  // set up game section
  let gs = document.getElementById('gameSection');
  if (!gs) {
    gs = document.createElement('section');
    gs.id = 'gameSection';
    gs.className = 'events-section';
    gs.style.background = 'linear-gradient(135deg,#1a1a1a,#444)';
    gs.innerHTML = `
      <div class="wrap">
        <span class="section-label">PLAY</span>
        <h2 class="section-title"><span>Match</span> It!</h2>
      </div>
      <div class="game-board" id="gameBoard" style="display:grid;grid-template-columns:repeat(6,1fr);max-width:700px;margin:40px auto;gap:10px"></div>
    `;
    gs.insertAdjacentElement('afterend', document.getElementById('events'));
  }
}

// ─── KEYBOARD HANDLER ────────────────────────────
const keyOverlay = document.getElementById('keyOverlay');
const keyPressHint = document.getElementById('keyPressHint');

function hideKeyOverlay() {
  keyOverlay.classList.add('hidden');
  GAME_STATE.started = true;
  setupGame();
  // start AI after short delay
  setTimeout(aiPlayerTurn, 800);
}

document.addEventListener('keydown', (e) => {
  if (!keyOverlay.classList.contains('hidden')) {
    hideKeyOverlay();
  }
});

keyPressHint.addEventListener('click', hideKeyOverlay);
document.getElementById('keyPressHint').addEventListener('touchstart', hideKeyOverlay);

// ─── HOVER EFFECTS ───────────────────────────────
document.querySelectorAll('.social-btn').forEach(btn => {
  btn.addEventListener('mouseenter', () => showToast('Follow us! New menu drops every Friday 🌶️'));
});

// ─── REVEAL ON SCROLL ────────────────────────────
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('visible');
    }
  });
}, { threshold: 0.1 });

document.querySelectorAll('.reveal, .dish-card, .testimonial-card, .event-card').forEach(el => observer.observe(el));

// ─── TOAST ────────────────────────────────────────
let toastTimer;
function showToast(msg) {
  const toast = document.getElementById('toast');
  toast.textContent = msg;
  toast.classList.add('show');
  clearTimeout(toastTimer);
  toastTimer = setTimeout(() => toast.classList.remove('show'), 3500);
}

// ─── DISMENU DATA ────────────────────────────────
const dishesData = [
  { emoji:'🌶️', tag:'GOCHI FIESTA', name:'Gochitaco', desc:'Spicy gochirellas with gochujang crema, pickled daikon & kimchi jack cheese.' },
  { emoji:'🥬', tag:'COLD CHOWDER', name:'Doenjang Dip', desc:'Creamy doenjang-glazed rice bowls with的解释cabbage slaw & crispy pork.' },
  { emoji:'🧄', tag:'HOOGANY BURGER', name:'Onion Taco Supreme', desc:'Loaded onion taco with fermented black garlic, truffle mayo & house salsa.' },
  { emoji:'🥩', tag:'BONE TACO', name:'Kalguksu Taco', desc:'Handmade knife-cut noodle taco with pork belly broth & sesame crisp.' },
  { emoji:'🥑', tag:'GREEN RANCH', name:'Green BBQ Taco', desc:'Smoked chicken taco with avocado crema, jalapeño salsa & crispy tortilla.' },
  { emoji:'🍗', tag:'CRISPY GOOD', name:'Dakgalbi Taco', desc:'Fire-roasted chicken taco with gochujang honey glaze, peanut slaw & soy butter.' },
  { emoji:'🐟', tag:'SEA KOREAN', name:'Haeman Jjim', desc:'Steamed whole fish tacos with sweet-savory glaze & fish cake.' },
  { emoji:'🍚', tag:'BOSSALACHA', name:'Cheonggukjang Wrap', desc:'Fermented meat wrap with cochonilla lettuce, sriracha mayo & mango salsa.' },
  { emoji:'🥔', tag:'COMBO CRISPS', name:'Budae Crunch', desc:'Vietnam-inspired combo taco with kimchi spam, egg mayo & instant ramen.' },
  { emoji:'🧀', tag:'GOMA GAZEBO', name:'Korean-Mex Pizza', desc:'Loaded pizza base with gochujang cheese, bulgogi beef & nori strips.' },
  { emoji:'🫘', tag:'DEEP FRIED', name:'Bibimbap Taco', desc:'Sizzling fried rice taco with mandu, spinach & secret spicy sauce.' },
  { emoji:'🥙', tag:'STRETCH', name:'Tteokbokki Burrito', desc:'Chewy rice cakes in a crispy taco shell, gochujang drizzle & fish cake.' },
];

function renderDishes() {
  const grid = document.getElementById('dishesGrid');
  grid.innerHTML = dishesData.map(d => `
    <div class="dish-card reveal">
      <div class="dish-img" style="background:linear-gradient(135deg,#ff6b00,#c0392b)">${d.emoji}</div>
      <span class="dish-emoji">${d.emoji}</span>
      <div class="dish-body">
        <span class="dish-tag">${d.tag}</span>
        <div class="dish-name">${d.name}</div>
        <div class="dish-desc">${d.desc}</div>
        <div class="dish-price">$9.99 <small>each</small></div>
      </div>
    </div>
  `).join('');
}

// ─── REVIEW DATA ─────────────────────────────────
const reviewsData = [
  { quote:'"I came for the tacos and stayed for the chaos."', author:'@foodie_marcus', stars:'★★★★★' },
  { quote:'"The gochitaco made me cry happy tears. Then cry again."', author:'@koreanfoodies', stars:'★★★★★' },
  { quote:'"This isn\'t a food truck. It\'s a cultural collision party in a parking lot."', author:'@san_diego_eat', stars:'★★★★★' },
  { quote:'"My grandmother asked if I\'d met a Korean who made Mexican food. I did."', author:'@moms_taco_love', stars:'★★★★☆' },
];

function renderReviews() {
  const grid = document.getElementById('reviewsGrid');
  grid.innerHTML = reviewsData.map(r => `
    <div class="testimonial-card reveal">
      <span class="quote-mark">"</span>
      <blockquote>${r.quote}</blockquote>
      <div class="stars">${r.stars}</div>
      <div class="testimonial-author">&mdash; ${r.author}</div>
    </div>
  `).join('');
}

// ─── EVENT DATA ───────────────────────────────────
const eventsData = [
  { date:'DEC 15', name:'Chrismas Special', desc:'Gochitaco holiday plates — free with any entree 4pm–9pm', link:'sms 760-555-KIMO' },
  { date:'JAN 3', name:'NYE Fire Party', desc:'3 days of free shots, live bachata, and discounted Tacos del Loco', link:'sms 760-555-KIMO' },
  { date:'FEB 14', name:'Valentine\'s Trash Tacos', desc:'Rebuild + steal tacos, mint shots, and a whole free meal', link:'sms 760-555-KIMO' },
  { date:'MAR 10', name:'South Coast Run Meetup', desc:'Run with us, eat with us, race to see who finishes first', link:'sms 760-555-KIMO' },
];

function renderEvents() {
  const grid = document.getElementById('eventsGrid');
  grid.innerHTML = eventsData.map(e => `
    <div class="event-card reveal">
      <div class="event-date">${e.date}</div>
      <div class="event-name">${e.name}</div>
      <div class="event-desc">${e.desc}</div>
      <div class="event-link">${e.link} →</div>
    </div>
  `).join('');
}

// ─── BOOT ─────────────────────────────────────────
renderDishes();
renderReviews();
renderEvents();

// Reveal animations
document.querySelectorAll('.dish-card, .testimonial-card, .event-card').forEach(el => observer.observe(el));

// Pre-render the game setup so it's visible
setTimeout(() => {
  setupGame();
}, 500);
</script>

<!-- GAME STYLE -->
<style>
.game-card{aspect-ratio:1;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:2.5rem;cursor:pointer;user-select:none;position:relative;perspective:600px;transform-style:preserve-3d;transition:transform .4s cubic-bezier(.4,0,.2,1);background:#2c2c2c;color:#fff;box-shadow:0 4px 15px rgba(0,0,0,.2)}
.game-card:hover{transform:scale(1.05)}
.game-card:active{transform:scale(.97)}
.game-card.flipped,.game-card.matched{transform:rotateY(180deg);background:#ffe5a0}
.game-card.matched{background:linear-gradient(135deg,#2d6a4f,#52b788);cursor:default;animation:popMatch .5s ease}
@keyframes popMatch{0%{transform:scale(.8)}50%{transform:scale(1.1)}100%{transform:scale(1)}}
.game-board{padding:20px;background:rgba(255,255,255,.06);border-radius:20px}
.game-board::-webkit-scrollbar{display:none}
</style>
</body>
</html>