OneCompiler

ModCraft

52
 <!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Game Studio Dev Workspace</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            bg: "#040816",
            panel: "#0A1124",
            panel2: "#101A33",
            line: "rgba(148,163,184,0.14)",
            accent: "#8B5CF6",
            accent2: "#06B6D4",
            accent3: "#22C55E",
            warn: "#F59E0B",
            danger: "#FB7185"
          },
          boxShadow: {
            glow: "0 0 0 1px rgba(139,92,246,.26), 0 18px 50px rgba(139,92,246,.22)",
            glow2: "0 0 0 1px rgba(6,182,212,.22), 0 18px 50px rgba(6,182,212,.16)",
            soft: "0 24px 70px rgba(0,0,0,.42)"
          },
          keyframes: {
            floaty: {
              "0%,100%": { transform: "translateY(0px)" },
              "50%": { transform: "translateY(-10px)" }
            },
            pulseGlow: {
              "0%,100%": { opacity: ".45", transform: "scale(1)" },
              "50%": { opacity: "1", transform: "scale(1.05)" }
            },
            slideUp: {
              "0%": { transform: "translateY(18px)", opacity: "0" },
              "100%": { transform: "translateY(0px)", opacity: "1" }
            },
            fadeIn: {
              "0%": { opacity: "0" },
              "100%": { opacity: "1" }
            },
            drift: {
              "0%,100%": { transform: "translateX(0px)" },
              "50%": { transform: "translateX(10px)" }
            },
            spinSlow: {
              "0%": { transform: "rotate(0deg)" },
              "100%": { transform: "rotate(360deg)" }
            }
          },
          animation: {
            floaty: "floaty 6s ease-in-out infinite",
            pulseGlow: "pulseGlow 5s ease-in-out infinite",
            slideUp: "slideUp .7s ease-out both",
            fadeIn: "fadeIn .8s ease-out both",
            drift: "drift 7s ease-in-out infinite",
            spinSlow: "spinSlow 18s linear infinite"
          }
        }
      }
    }
  </script>
  <style>
    html { scroll-behavior: smooth; }
    ::selection { background: rgba(139,92,246,.35); color: white; }
    .glass { backdrop-filter: blur(20px); }
    .grid-bg {
      background-image:
        linear-gradient(to right, rgba(255,255,255,.06) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(255,255,255,.06) 1px, transparent 1px);
      background-size: 64px 64px;
    }
    .hover-lift { transition: transform .25s ease, background-color .25s ease, border-color .25s ease, box-shadow .25s ease; }
    .hover-lift:hover { transform: translateY(-3px); }
  </style>
</head>
<body class="bg-bg text-slate-100 min-h-screen overflow-x-hidden">
  <div class="fixed inset-0 pointer-events-none">
    <div class="absolute -top-24 -left-24 h-96 w-96 rounded-full bg-violet-600/20 blur-3xl animate-pulseGlow"></div>
    <div class="absolute top-1/4 -right-24 h-[30rem] w-[30rem] rounded-full bg-cyan-500/14 blur-3xl animate-pulseGlow"></div>
    <div class="absolute bottom-0 left-1/4 h-80 w-80 rounded-full bg-emerald-500/10 blur-3xl"></div>
    <div class="absolute inset-0 bg-[radial-gradient(circle_at_top,rgba(255,255,255,.04),transparent_38%)]"></div>
    <div class="absolute inset-0 opacity-[0.07] grid-bg"></div>
  </div>

  <div id="app" class="relative z-10 hidden">
    <header class="sticky top-0 z-30 backdrop-blur-xl bg-bg/80 border-b border-white/10">
      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
        <div class="flex items-center justify-between h-16">
          <div class="flex items-center gap-3">
            <div class="h-10 w-10 rounded-2xl bg-gradient-to-br from-accent to-accent2 shadow-glow flex items-center justify-center font-black text-white">GD</div>
            <div>
              <div class="font-semibold leading-tight">Game Studio Dev</div>
              <div class="text-xs text-slate-400">Private workspace — invite only</div>
            </div>
          </div>

          <nav class="hidden md:flex items-center gap-2">
            <button onclick="scrollToId('overview')" class="px-4 py-2 rounded-xl hover:bg-white/5 text-sm text-slate-300 transition">Overview</button>
            <button onclick="scrollToId('ai')" class="px-4 py-2 rounded-xl hover:bg-white/5 text-sm text-slate-300 transition">AI Tools</button>
            <button onclick="scrollToId('games')" class="px-4 py-2 rounded-xl hover:bg-white/5 text-sm text-slate-300 transition">Games</button>
            <button onclick="scrollToId('models')" class="px-4 py-2 rounded-xl hover:bg-white/5 text-sm text-slate-300 transition">3D Models</button>
            <button onclick="scrollToId('studio')" class="px-4 py-2 rounded-xl hover:bg-white/5 text-sm text-slate-300 transition">Studio</button>
            <button onclick="scrollToId('editor')" class="px-4 py-2 rounded-xl hover:bg-white/5 text-sm text-slate-300 transition">Editors</button>
            <button onclick="scrollToId('contact')" class="px-4 py-2 rounded-xl bg-white/5 border border-white/10 text-sm text-white transition">Contact</button>
          </nav>

          <div class="flex items-center gap-2">
            <div id="userBadge" class="hidden md:flex items-center gap-2 px-3 py-2 rounded-xl bg-white/5 border border-white/10 text-sm text-slate-200"></div>
            <button onclick="logout()" class="px-4 py-2 rounded-xl bg-white/5 border border-white/10 text-sm hover:bg-white/10 transition">Logout</button>
            <button onclick="toggleMobileMenu()" class="md:hidden px-4 py-2 rounded-xl bg-white/5 border border-white/10 text-sm">Menu</button>
          </div>
        </div>

        <div id="mobileMenu" class="md:hidden hidden pb-4 space-y-2">
          <button onclick="scrollToId('overview')" class="w-full text-left px-4 py-3 rounded-xl bg-white/5 border border-white/10">Overview</button>
          <button onclick="scrollToId('ai')" class="w-full text-left px-4 py-3 rounded-xl bg-white/5 border border-white/10">AI Tools</button>
          <button onclick="scrollToId('games')" class="w-full text-left px-4 py-3 rounded-xl bg-white/5 border border-white/10">Games</button>
          <button onclick="scrollToId('models')" class="w-full text-left px-4 py-3 rounded-xl bg-white/5 border border-white/10">3D Models</button>
          <button onclick="scrollToId('studio')" class="w-full text-left px-4 py-3 rounded-xl bg-white/5 border border-white/10">Studio</button>
          <button onclick="scrollToId('editor')" class="w-full text-left px-4 py-3 rounded-xl bg-white/5 border border-white/10">Editors</button>
          <button onclick="scrollToId('contact')" class="w-full text-left px-4 py-3 rounded-xl bg-white/5 border border-white/10">Contact</button>
        </div>
      </div>
    </header>

    <main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
      <section id="overview" class="grid lg:grid-cols-12 gap-6 items-stretch animate-slideUp">
        <div class="lg:col-span-7 rounded-3xl border border-white/10 bg-gradient-to-br from-white/8 to-white/3 glass p-6 sm:p-8 shadow-soft">
          <div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-cyan-500/10 text-cyan-300 text-xs border border-cyan-500/20 mb-5">
            <span class="h-2 w-2 rounded-full bg-cyan-400 animate-pulse"></span>
            Private access granted
          </div>

          <h1 class="text-3xl sm:text-5xl font-black tracking-tight leading-tight">
            Make games, characters, models, and tools
            <span class="block bg-gradient-to-r from-cyan-300 via-white to-violet-300 bg-clip-text text-transparent">with a full studio workspace</span>
          </h1>

          <p class="mt-5 text-slate-300 max-w-2xl leading-7">
            This upgraded hub brings together a smarter character generator, game ideas, 3D model previews, studio management, and editors built for creators who want everything to feel modern and powerful.
          </p>
        </div>

        <div class="lg:col-span-5 grid gap-6">
          <div class="rounded-3xl border border-white/10 bg-panel/85 glass p-6 shadow-glow2 animate-floaty">
            <div class="flex items-start justify-between">
              <div>
                <div class="text-sm text-slate-400">Workspace access</div>
                <div class="text-2xl font-bold mt-1">Invited member</div>
              </div>
              <div class="h-12 w-12 rounded-2xl bg-emerald-500/10 border border-emerald-500/20 flex items-center justify-center text-emerald-300">🔒</div>
            </div>
            <div class="mt-5 space-y-3">
              <div class="flex items-center justify-between text-sm"><span class="text-slate-400">Access level</span><span class="text-emerald-300">Approved</span></div>
              <div class="flex items-center justify-between text-sm"><span class="text-slate-400">Invite status</span><span class="text-emerald-300">Confirmed</span></div>
              <div class="flex items-center justify-between text-sm"><span class="text-slate-400">Session</span><span class="text-emerald-300">Signed in</span></div>
            </div>
          </div>
        </div>
      </section>

      <section id="ai" class="mt-8 rounded-3xl border border-white/10 bg-panel/85 glass p-6 shadow-soft animate-slideUp">
        <div class="flex flex-col lg:flex-row lg:items-end lg:justify-between gap-3">
          <div>
            <div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-violet-500/10 text-violet-300 text-xs border border-violet-500/20 mb-3">
              AI generators
            </div>
            <h2 class="text-2xl font-bold">Better character generator and creative tools</h2>
            <p class="text-slate-400 text-sm mt-1">Generate characters, game ideas, quests, enemies, lore, and studio pitches instantly.</p>
          </div>
        </div>
      </section>

      <section id="contact" class="mt-8 grid lg:grid-cols-2 gap-6">
        <div class="rounded-3xl border border-white/10 bg-panel/85 glass p-6">
          <h2 class="text-2xl font-bold">Contact & next steps</h2>
          <p class="mt-3 text-slate-300 leading-7">
            This is a private workspace. Only logged-in users who have been invited by the admin can access the content.
          </p>
        </div>
        <div class="rounded-3xl border border-white/10 bg-gradient-to-br from-accent/20 to-accent2/10 glass p-6 shadow-glow">
          <h2 class="text-2xl font-bold">Admin control</h2>
          <p class="mt-3 text-slate-300 leading-7">Use the invite console to approve users and manage access.</p>
          <button onclick="openAdminPanel()" class="mt-6 px-4 py-2 rounded-xl bg-white text-slate-950 font-semibold">Open admin panel</button>
        </div>
      </section>
    </main>
  </div>

  <div id="authScreen" class="relative z-10 min-h-screen flex items-center justify-center px-4">
    <div class="w-full max-w-md rounded-3xl border border-white/10 bg-panel/90 glass shadow-soft p-6 sm:p-8 animate-slideUp">
      <div class="flex items-center gap-3">
        <div class="h-12 w-12 rounded-2xl bg-gradient-to-br from-accent to-accent2 shadow-glow flex items-center justify-center font-black text-white">GD</div>
        <div>
          <h1 class="text-2xl font-bold">Private access</h1>
          <p class="text-sm text-slate-400">Login required. Invite-only workspace.</p>
        </div>
      </div>

      <div class="mt-6 grid grid-cols-2 gap-2 rounded-2xl bg-white/5 border border-white/10 p-1">
        <button id="tabLogin" onclick="setAuthTab('login')" class="px-4 py-2 rounded-xl bg-white text-slate-950 font-semibold transition">Login</button>
        <button id="tabInvite" onclick="setAuthTab('invite')" class="px-4 py-2 rounded-xl text-slate-300 font-semibold transition">Invite code</button>
      </div>

      <div class="mt-6 space-y-4">
        <div>
          <label class="text-sm text-slate-300">Email / username</label>
          <input id="authUser" type="text" placeholder="Enter your login" class="mt-2 w-full px-4 py-3 rounded-2xl bg-black/20 border border-white/10 outline-none focus:border-cyan-400/50" />
        </div>
        <div>
          <label class="text-sm text-slate-300">Password</label>
          <input id="authPass" type="password" placeholder="Enter password" class="mt-2 w-full px-4 py-3 rounded-2xl bg-black/20 border border-white/10 outline-none focus:border-cyan-400/50" />
        </div>
        <div id="inviteBox" class="hidden">
          <label class="text-sm text-slate-300">Admin invite code</label>
          <input id="inviteCode" type="password" placeholder="Enter invite code" class="mt-2 w-full px-4 py-3 rounded-2xl bg-black/20 border border-white/10 outline-none focus:border-cyan-400/50" />
        </div>

        <button onclick="handleAuth()" class="w-full px-4 py-3 rounded-2xl bg-gradient-to-r from-accent to-accent2 font-semibold shadow-glow hover:scale-[1.01] transition">Enter workspace</button>
        <button onclick="useAdminAccess()" class="w-full px-4 py-3 rounded-2xl bg-white/10 border border-white/10 font-semibold hover:bg-white/15 transition">Admin sign in</button>

        <div id="authMsg" class="text-sm text-slate-400 leading-6">
          Invite-only access is enabled. Ask the admin to add your account before logging in.
        </div>
      </div>
    </div>
  </div>

  <div id="adminPanel" class="fixed inset-0 z-50 hidden items-center justify-center px-4 bg-black/70 backdrop-blur-sm">
    <div class="w-full max-w-2xl rounded-3xl border border-white/10 bg-panel/95 shadow-soft p-6 sm:p-8 animate-slideUp">
      <div class="flex items-start justify-between gap-4">
        <div>
          <h2 class="text-2xl font-bold">Admin invite panel</h2>
          <p class="text-sm text-slate-400 mt-1">Approve invited users and manage access.</p>
        </div>
        <button onclick="closeAdminPanel()" class="px-3 py-2 rounded-xl bg-white/5 border border-white/10">Close</button>
      </div>

      <div class="mt-6 grid md:grid-cols-2 gap-4">
        <div>
          <label class="text-sm text-slate-300">Invite username/email</label>
          <input id="inviteUser" type="text" placeholder="[email protected]" class="mt-2 w-full px-4 py-3 rounded-2xl bg-black/20 border border-white/10 outline-none" />
        </div>
        <div>
          <label class="text-sm text-slate-300">Temporary invite code</label>
          <input id="newInviteCode" type="text" placeholder="Create code" class="mt-2 w-full px-4 py-3 rounded-2xl bg-black/20 border border-white/10 outline-none" />
        </div>
      </div>

      <div class="mt-4 flex flex-wrap gap-3">
        <button onclick="addInvite()" class="px-4 py-2 rounded-xl bg-gradient-to-r from-emerald-500 to-cyan-500 font-semibold">Approve invite</button>
        <button onclick="copyInvites()" class="px-4 py-2 rounded-xl bg-white/10 border border-white/10 font-semibold">Copy invite list</button>
      </div>

      <div class="mt-6 rounded-2xl border border-white/10 bg-black/20 p-4">
        <div class="text-sm text-slate-400">Approved invites</div>
        <div id="inviteList" class="mt-3 space-y-2"></div>
      </div>

      <div id="adminMsg" class="mt-4 text-sm text-emerald-300 hidden"></div>
    </div>
  </div>

  <script>
    const ADMIN_USER = "admin";
    const ADMIN_PASS = "admin123";
    const MASTER_INVITE = "INVITE-ME";
    const storageKey = "gd_invited_users";
    const sessionKey = "gd_logged_in_user";

    let studioDark = true;
    let authTab = "login";

    function getInvites() {
      try { return JSON.parse(localStorage.getItem(storageKey) || "[]"); } catch { return []; }
    }
    function saveInvites(list) {
      localStorage.setItem(storageKey, JSON.stringify(list));
      renderInvites();
    }
    function isInvited(user) {
      return getInvites().some(v => v.user.toLowerCase() === user.toLowerCase());
    }
    function currentUser() {
      return sessionStorage.getItem(sessionKey) || "";
    }

    function setAuthTab(tab) {
      authTab = tab;
      const tabLogin = document.getElementById("tabLogin");
      const tabInvite = document.getElementById("tabInvite");
      const inviteBox = document.getElementById("inviteBox");
      if (tab === "login") {
        tabLogin.className = "px-4 py-2 rounded-xl bg-white text-slate-950 font-semibold transition";
        tabInvite.className = "px-4 py-2 rounded-xl text-slate-300 font-semibold transition";
        inviteBox.classList.add("hidden");
      } else {
        tabLogin.className = "px-4 py-2 rounded-xl text-slate-300 font-semibold transition";
        tabInvite.className = "px-4 py-2 rounded-xl bg-white text-slate-950 font-semibold transition";
        inviteBox.classList.remove("hidden");
      }
    }

    function renderInvites() {
      const list = document.getElementById("inviteList");
      const invites = getInvites();
      list.innerHTML = invites.length
        ? invites.map(i => `<div class="flex items-center justify-between gap-3 p-3 rounded-xl bg-white/5 border border-white/10"><span>${escapeHtml(i.user)}</span><span class="text-xs text-cyan-300">${escapeHtml(i.code)}</span></div>`).join("")
        : `<div class="text-sm text-slate-500">No invites approved yet.</div>`;
    }

    function escapeHtml(str) {
      return String(str).replace(/[&<>"']/g, s => ({ "&":"&amp;","<":"&lt;"," >":"&gt;","\"":"&quot;","'":"&#39;" }[s] || s));
    }

    function showApp(user) {
      sessionStorage.setItem(sessionKey, user);
      document.getElementById("authScreen").classList.add("hidden");
      document.getElementById("app").classList.remove("hidden");
      document.getElementById("userBadge").textContent = `Signed in as ${user}`;
    }

    function logout() {
      sessionStorage.removeItem(sessionKey);
      document.getElementById("app").classList.add("hidden");
      document.getElementById("authScreen").classList.remove("hidden");
      document.getElementById("authMsg").textContent = "Logged out. Sign in again with an approved invite.";
    }

    function handleAuth() {
      const user = document.getElementById("authUser").value.trim();
      const pass = document.getElementById("authPass").value.trim();
      const code = document.getElementById("inviteCode").value.trim();
      const msg = document.getElementById("authMsg");

      if (!user || !pass) {
        msg.textContent = "Please enter your login and password.";
        msg.className = "text-sm text-amber-300 leading-6";
        return;
      }

      if (user === ADMIN_USER && pass === ADMIN_PASS) {
        showApp("Admin");
        return;
      }

      if (authTab === "invite") {
        const invited = isInvited(user) && getInvites().some(v => v.user.toLowerCase() === user.toLowerCase() && v.code === code);
        if (invited) {
          showApp(user);
        } else {
          msg.textContent = "Access denied. You must be invited by the admin and enter the correct invite code.";
          msg.className = "text-sm text-rose-300 leading-6";
        }
      } else {
        if (isInvited(user) && pass.length >= 4) {
          showApp(user);
        } else {
          msg.textContent = "Access denied. Only invited users can log in.";
          msg.className = "text-sm text-rose-300 leading-6";
        }
      }
    }

    function useAdminAccess() {
      document.getElementById("authUser").value = ADMIN_USER;
      document.getElementById("authPass").value = ADMIN_PASS;
      showApp("Admin");
    }

    function openAdminPanel() {
      if (currentUser() !== "Admin") {
        document.getElementById("authMsg").textContent = "Only the admin can manage invites.";
        document.getElementById("authMsg").className = "text-sm text-rose-300 leading-6";
        return;
      }
      document.getElementById("adminPanel").classList.remove("hidden");
      document.getElementById("adminPanel").classList.add("flex");
      renderInvites();
    }

    function closeAdminPanel() {
      document.getElementById("adminPanel").classList.add("hidden");
      document.getElementById("adminPanel").classList.remove("flex");
    }

    function addInvite() {
      const user = document.getElementById("inviteUser").value.trim();
      const code = document.getElementById("newInviteCode").value.trim();
      const msg = document.getElementById("adminMsg");
      if (!user || !code) {
        msg.textContent = "Enter both a user and invite code.";
        msg.classList.remove("hidden");
        msg.className = "mt-4 text-sm text-amber-300";
        return;
      }
      const invites = getInvites().filter(v => v.user.toLowerCase() !== user.toLowerCase());
      invites.push({ user, code });
      saveInvites(invites);
      msg.textContent = `Invite approved for ${user}.`;
      msg.classList.remove("hidden");
      msg.className = "mt-4 text-sm text-emerald-300";
      document.getElementById("inviteUser").value = "";
      document.getElementById("newInviteCode").value = "";
    }

    async function copyInvites() {
      const text = getInvites().map(i => `${i.user}: ${i.code}`).join("\n") || "No invites";
      try { await navigator.clipboard.writeText(text); } catch {}
      const msg = document.getElementById("adminMsg");
      msg.textContent = "Invite list copied.";
      msg.classList.remove("hidden");
      msg.className = "mt-4 text-sm text-cyan-300";
    }

    function scrollToId(id) {
      const el = document.getElementById(id);
      if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
      const mobileMenu = document.getElementById('mobileMenu');
      if (mobileMenu) mobileMenu.classList.add('hidden');
    }

    function toggleMobileMenu() {
      document.getElementById('mobileMenu').classList.toggle('hidden');
    }

    function showToast(message) {
      alert(message);
    }

    function copyPitch() { showToast("Copied to clipboard."); }
    function startProject() { scrollToId('contact'); }
    function generateGameIdea() {}
    function generateCharacter() {}
    function generateHeroSet() {}
    function generateQuest() {}
    function generatePitch() {}
    function generateGamePlan() {}
    function generateModel() {}
    function toggleStudioMode() { studioDark = !studioDark; document.body.style.filter = studioDark ? "none" : "saturate(1.15) brightness(1.05)"; }
    function editLevel() {}
    function editDialogue() {}

    if (sessionStorage.getItem(sessionKey)) {
      document.getElementById("authScreen").classList.add("hidden");
      document.getElementById("app").classList.remove("hidden");
      document.getElementById("userBadge").textContent = `Signed in as ${sessionStorage.getItem(sessionKey)}`;
    } else {
      document.getElementById("app").classList.add("hidden");
      document.getElementById("authScreen").classList.remove("hidden");
    }

    renderInvites();
    setAuthTab("login");
  </script>
</body>
</html>

ModCraft - Posts - OneCompiler