Initial PlayBull release with Trilogy Hub integration.

Includes homelab deploy tooling, image position/zoom manifest persistence, and full trading/casino stack.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-02 08:31:36 +02:00
commit 94b6cc3be9
60 changed files with 9206 additions and 0 deletions

880
public/index.html Normal file
View File

@@ -0,0 +1,880 @@
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Trilogy Hub — Three Hustlers. One Vision.</title>
<meta name="description" content="Trilogy Hub — the personal brand home of three business partners: Magic Tree Co., NovaTerra Immobilien, and PG Trading Management." />
<!-- Favicon (custom SVG: three interlocking triangles) -->
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%230a0a0a'/%3E%3Cg fill='none' stroke='%23c9a84c' stroke-width='1.6' stroke-linejoin='round'%3E%3Cpath d='M16 6 L23 18 L9 18 Z'/%3E%3Cpath d='M10 14 L17 26 L3 26 Z' opacity='0.55'/%3E%3Cpath d='M22 14 L29 26 L15 26 Z' opacity='0.55'/%3E%3C/g%3E%3C/svg%3E" />
<!-- Fonts: Cabinet Grotesk (display) + Satoshi (body) via Fontshare -->
<link rel="preconnect" href="https://api.fontshare.com" crossorigin />
<link href="https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,700,800,900&f[]=satoshi@400,500,700,900&display=swap" rel="stylesheet" />
<!-- Tailwind CSS v4 (CDN browser build) -->
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<!-- GSAP + ScrollTrigger -->
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>
<!-- Splitting.js -->
<link rel="stylesheet" href="https://unpkg.com/splitting/dist/splitting.css" />
<script src="https://unpkg.com/splitting/dist/splitting.min.js"></script>
<!-- Lenis smooth scroll -->
<script src="https://unpkg.com/lenis@1.1.13/dist/lenis.min.js"></script>
<!-- Motion.js (Framer Motion vanilla) -->
<script src="https://cdn.jsdelivr.net/npm/motion@11.11.13/dist/motion.js"></script>
<!-- Lucide icons -->
<script src="https://unpkg.com/lucide@latest"></script>
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>
<style type="text/tailwindcss">
@theme {
--color-ink-900: #0a0a0a;
--color-ink-800: #111111;
--color-ink-700: #1a1a1a;
--color-ink-600: #242424;
--color-gold: #c9a84c;
--color-gold-soft: #d8bd6e;
--color-cream: #f4f1e9;
--color-success: #46c98b;
--color-error: #e0625e;
--font-display: "Cabinet Grotesk", ui-sans-serif, system-ui, sans-serif;
--font-body: "Satoshi", ui-sans-serif, system-ui, sans-serif;
}
</style>
<style>
:root {
--bg: #0a0a0a;
--bg-2: #111111;
--bg-3: #1a1a1a;
--surface: #161616;
--border: rgba(201, 168, 76, 0.18);
--border-soft: rgba(255, 255, 255, 0.08);
--text: #f4f1e9;
--text-dim: #a8a39a;
--text-faint: #6e6a62;
--gold: #c9a84c;
--gold-soft: #d8bd6e;
--success: #46c98b;
--error: #e0625e;
--ease: cubic-bezier(0.16, 1, 0.3, 1);
}
html:not(.dark) {
--bg: #f6f4ee;
--bg-2: #efece3;
--bg-3: #e7e3d8;
--surface: #ffffff;
--border: rgba(154, 124, 38, 0.28);
--border-soft: rgba(10, 10, 10, 0.1);
--text: #1a1712;
--text-dim: #4f4a40;
--text-faint: #7d7668;
--gold: #9a7c26;
--gold-soft: #b89537;
}
* { -webkit-font-smoothing: antialiased; }
html { scroll-behavior: auto; }
body {
background-color: var(--bg);
color: var(--text);
font-family: var(--font-body);
overflow-x: hidden;
transition: background-color 0.5s var(--ease), color 0.5s var(--ease);
}
.font-display { font-family: var(--font-display); }
::selection { background: var(--gold); color: #0a0a0a; }
/* Scrollbar */
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--bg-3); border-radius: 8px; border: 2px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: var(--gold); }
.text-dim { color: var(--text-dim); }
.text-faint { color: var(--text-faint); }
.text-gold { color: var(--gold); }
.bg-surface { background-color: var(--surface); }
.bg-ink2 { background-color: var(--bg-2); }
.bg-ink3 { background-color: var(--bg-3); }
.border-soft { border-color: var(--border-soft); }
.border-gold { border-color: var(--border); }
/* Section container */
.wrap { width: 100%; max-width: 1200px; margin-inline: auto; padding-inline: clamp(1.25rem, 4vw, 3rem); }
/* Pages */
.page { display: none; }
.page.active { display: block; }
/* Eyebrow label */
.eyebrow {
font-size: 0.75rem; letter-spacing: 0.22em; text-transform: uppercase;
color: var(--gold); font-weight: 700;
}
/* Buttons */
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
min-height: 44px; padding: 0.75rem 1.4rem; border-radius: 0.7rem;
font-weight: 700; font-size: 0.95rem; cursor: pointer;
transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease), background-color 0.3s var(--ease), color 0.3s var(--ease);
border: 1px solid transparent; text-decoration: none; line-height: 1;
}
.btn-primary { background: var(--gold); color: #0a0a0a; }
.btn-primary:hover { transform: scale(1.03); box-shadow: 0 10px 34px -8px rgba(201,168,76,0.55); }
.btn-ghost { background: transparent; color: var(--text); border-color: var(--border); }
.btn-ghost:hover { transform: scale(1.03); border-color: var(--gold); box-shadow: 0 10px 30px -12px rgba(201,168,76,0.4); }
.btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
/* Cards */
.card {
background: var(--surface); border: 1px solid var(--border-soft);
border-radius: 1.1rem; transition: transform 0.45s var(--ease), box-shadow 0.45s var(--ease), border-color 0.45s var(--ease);
}
.card-gold { border-color: var(--border); }
.card-hover:hover {
transform: translateY(-6px);
box-shadow: 0 24px 60px -24px rgba(0,0,0,0.7), 0 0 0 1px var(--border);
}
html:not(.dark) .card-hover:hover { box-shadow: 0 24px 50px -24px rgba(0,0,0,0.25), 0 0 0 1px var(--border); }
/* Photo upload slot */
.photo-slot {
position: relative; display: flex; align-items: center; justify-content: center;
flex-direction: column; gap: 0.6rem; cursor: pointer; overflow: hidden;
background: var(--bg-3); border: 1.5px dashed var(--gold);
border-radius: 1rem; color: var(--text-dim); text-align: center; padding: 1.5rem;
transition: border-color 0.4s var(--ease), background-color 0.4s var(--ease);
min-height: 180px;
}
.photo-slot:hover { border-color: var(--gold-soft); background: var(--bg-2); }
.photo-slot:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.photo-slot .slot-icon { color: var(--gold); transition: transform 0.4s var(--ease); }
.photo-slot:hover .slot-icon { transform: translateY(-3px) scale(1.08); }
.photo-slot .slot-label { font-size: 0.8rem; font-weight: 600; letter-spacing: 0.02em; }
.photo-slot img.preview {
position: absolute; max-width: none; pointer-events: none;
opacity: 0; transition: opacity 0.6s var(--ease), filter 0.6s var(--ease);
border-radius: inherit; z-index: 2;
}
.photo-slot.has-image img.preview { opacity: 1; }
/* Subtle brightness lift on hover for uploaded images */
.photo-slot.has-image:hover img.preview { filter: saturate(1.08) brightness(1.04); }
/* Diagonal glossy shine that sweeps across images on hover */
.photo-slot.has-image::before {
content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
background: linear-gradient(115deg, transparent 30%, rgba(255,255,255,0.18) 48%, transparent 60%);
transform: translateX(-130%); transition: transform 0.85s var(--ease); border-radius: inherit;
}
.photo-slot.has-image:hover::before { transform: translateX(130%); }
/* Gentle gold ring glow when hovering an image */
.photo-slot.has-image:hover { box-shadow: 0 22px 55px -28px rgba(0,0,0,0.85), 0 0 0 1px var(--border); }
.photo-slot.has-image {
border-style: solid;
border-color: var(--border);
padding: 0;
}
.photo-slot .slot-default { display: flex; flex-direction: column; align-items: center; gap: 0.6rem; transition: opacity 0.4s var(--ease); z-index: 1; position: relative; }
.photo-slot .slot-hover-name {
position: absolute; inset: auto 0 0 0; padding: 0.6rem 0.9rem; z-index: 2;
background: linear-gradient(to top, rgba(0,0,0,0.82), transparent);
color: #fff; font-size: 0.78rem; font-weight: 600; opacity: 0;
transform: translateY(8px); transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
text-align: left;
}
.photo-slot.has-image:hover .slot-hover-name { opacity: 1; transform: translateY(0); }
/* Image position editor */
.img-editor-backdrop {
position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center;
background: rgba(0,0,0,0.82); backdrop-filter: blur(10px); padding: 1.25rem;
}
.img-editor-modal { width: 100%; max-width: 420px; padding: 1.5rem; max-height: 92vh; overflow-y: auto; }
.img-editor-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.5rem; }
.img-editor-preview-outer { display: flex; justify-content: center; }
.img-editor-preview {
position: relative; overflow: hidden; background: var(--bg-3);
border: 2px solid var(--border); touch-action: none; cursor: grab;
}
.img-editor-preview:active { cursor: grabbing; }
.img-editor-preview img { position: absolute; max-width: none; pointer-events: none; user-select: none; }
.img-editor-range { width: 100%; accent-color: var(--gold); height: 6px; cursor: pointer; }
/* Nav */
.nav-link {
position: relative; font-weight: 500; color: var(--text-dim); font-size: 0.95rem;
padding: 0.4rem 0; transition: color 0.3s var(--ease); cursor: pointer; background: none; border: none;
}
.nav-link:hover, .nav-link.active { color: var(--text); }
.nav-link::after {
content: ""; position: absolute; left: 0; bottom: -2px; height: 2px; width: 0;
background: var(--gold); transition: width 0.4s var(--ease);
}
.nav-link:hover::after, .nav-link.active::after { width: 100%; }
/* Glass header */
.glass {
background: color-mix(in srgb, var(--bg) 72%, transparent);
backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
border-bottom: 1px solid var(--border-soft);
}
/* Animated reveal base (GSAP will animate). Fallback visible if no JS. */
.reveal { opacity: 0; transform: translateY(30px); }
.js-ready .reveal { will-change: opacity, transform; }
/* Splitting char stagger handled via GSAP, keep visible baseline */
.split-heading .char { display: inline-block; }
/* Hero gradient overlays */
.overlay-green { background: linear-gradient(135deg, rgba(8,30,18,0.92), rgba(10,10,10,0.7)); }
.overlay-navy { background: linear-gradient(135deg, rgba(10,18,38,0.92), rgba(10,10,10,0.7)); }
.overlay-dark { background: linear-gradient(135deg, rgba(10,10,10,0.9), rgba(10,10,10,0.55)); }
/* Price badge */
.badge {
display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.35rem 0.7rem;
border-radius: 0.5rem; font-weight: 800; font-size: 0.85rem;
background: rgba(201,168,76,0.12); color: var(--gold); border: 1px solid var(--border);
}
.chip {
display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.3rem 0.65rem;
border-radius: 999px; font-size: 0.78rem; font-weight: 600;
background: var(--bg-3); color: var(--text-dim); border: 1px solid var(--border-soft);
}
/* LIVE pulsing dot */
.live-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--success); position: relative; }
.live-dot::after {
content: ""; position: absolute; inset: 0; border-radius: 999px; background: var(--success);
animation: ping 1.6s var(--ease) infinite;
}
@keyframes ping { 0% { transform: scale(1); opacity: 0.7; } 80%,100% { transform: scale(2.6); opacity: 0; } }
/* Price flash */
.flash-up { animation: flashUp 0.8s var(--ease); }
.flash-down { animation: flashDown 0.8s var(--ease); }
@keyframes flashUp { 0% { background: rgba(70,201,139,0.28); } 100% { background: transparent; } }
@keyframes flashDown { 0% { background: rgba(224,98,94,0.28); } 100% { background: transparent; } }
.text-success { color: var(--success); }
.text-error { color: var(--error); }
/* Modal */
.modal-backdrop {
position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center;
background: rgba(0,0,0,0.78); backdrop-filter: blur(8px); padding: 1.25rem;
}
.input {
width: 100%; padding: 0.85rem 1rem; border-radius: 0.7rem; background: var(--bg-3);
border: 1px solid var(--border-soft); color: var(--text); font-size: 0.95rem; min-height: 44px;
transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.input:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px rgba(201,168,76,0.18); }
/* Masonry-ish reviews */
.masonry { columns: 1; column-gap: 1.25rem; }
@media (min-width: 640px) { .masonry { columns: 2; } }
@media (min-width: 1024px) { .masonry { columns: 3; } }
.masonry > * { break-inside: avoid; margin-bottom: 1.25rem; }
.divider { height: 1px; background: var(--border-soft); }
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
.reveal { opacity: 1 !important; transform: none !important; }
}
.star { color: var(--gold); letter-spacing: 0.05em; }
/* ===================== ENHANCED EFFECTS ===================== */
/* Scroll progress bar (top of viewport) */
.scroll-progress {
position: fixed; top: 0; left: 0; height: 2.5px; width: 0%;
z-index: 60; transform-origin: left center;
background: linear-gradient(90deg, var(--gold), var(--gold-soft), var(--gold));
box-shadow: 0 0 12px rgba(201,168,76,0.6); will-change: width;
}
/* 3D tilt for cards — JS sets --rx/--ry, CSS handles the smoothing */
.card-hover {
transform-style: preserve-3d;
transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateY(0) translateZ(0);
transition: transform 0.5s var(--ease), box-shadow 0.45s var(--ease), border-color 0.45s var(--ease);
}
.card-hover.is-tilting { transition: box-shadow 0.45s var(--ease), border-color 0.45s var(--ease); }
.card-hover:hover {
transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateY(-6px) translateZ(0);
}
/* Glossy sweep on primary buttons */
.btn-primary { position: relative; overflow: hidden; isolation: isolate; }
.btn-primary::after {
content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
background: linear-gradient(115deg, transparent 35%, rgba(255,255,255,0.45) 50%, transparent 65%);
transform: translateX(-130%); transition: transform 0.7s var(--ease);
}
.btn-primary:hover::after { transform: translateX(130%); }
/* Floating ambient gradient orbs for hero sections */
.orbs { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: -1; }
.orb {
position: absolute; border-radius: 999px; filter: blur(60px); opacity: 0.5;
will-change: transform; mix-blend-mode: screen;
}
html:not(.dark) .orb { mix-blend-mode: multiply; opacity: 0.35; }
.orb-1 { width: 460px; height: 460px; top: -120px; left: -80px;
background: radial-gradient(circle, rgba(201,168,76,0.55), transparent 70%);
animation: orbFloat 18s ease-in-out infinite; }
.orb-2 { width: 380px; height: 380px; bottom: -140px; right: -60px;
background: radial-gradient(circle, rgba(47,158,143,0.4), transparent 70%);
animation: orbFloat 22s ease-in-out infinite reverse; }
@keyframes orbFloat {
0%, 100% { transform: translate(0, 0) scale(1); }
50% { transform: translate(40px, -30px) scale(1.12); }
}
/* Animated gold shimmer on the gold accent words */
.shimmer-gold {
background: linear-gradient(100deg, var(--gold) 0%, var(--gold-soft) 25%, #fff3cf 50%, var(--gold-soft) 75%, var(--gold) 100%);
background-size: 200% auto;
-webkit-background-clip: text; background-clip: text;
-webkit-text-fill-color: transparent; color: transparent;
animation: shimmerMove 6s linear infinite;
}
@keyframes shimmerMove { to { background-position: 200% center; } }
/* Image reveal with clip-path wipe (added by JS via .img-reveal) */
.img-reveal { clip-path: inset(0 0 100% 0); transition: clip-path 1s var(--ease); }
.img-reveal.is-in { clip-path: inset(0 0 0% 0); }
/* Nav underline gets a soft glow on active */
.nav-link.active::after { box-shadow: 0 0 10px rgba(201,168,76,0.7); }
/* Live ticker price cells subtle scale pop handled in JS via flash classes already */
/* ---- Mobile tuning: keep it smooth & tasteful on phones ---- */
@media (max-width: 767px) {
/* Big blurs are expensive on mobile GPUs — lighten them up */
.orb { filter: blur(42px); opacity: 0.4; }
.orb-1 { width: 280px; height: 280px; top: -80px; left: -60px; }
.orb-2 { width: 240px; height: 240px; bottom: -90px; right: -40px; }
.glass { backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
/* No hover on touch, so neutralise tilt vars for crisp rendering */
.card-hover { transform: none; }
.card-hover:hover { transform: translateY(-4px); }
/* Card tap feedback for touch devices */
.card-hover:active { transform: scale(0.985); transition: transform 0.15s var(--ease); }
.btn:active { transform: scale(0.96); }
.scroll-progress { height: 2px; }
/* Make sure the diagonal image shine isn't stuck mid-frame on touch */
.photo-slot.has-image::before { display: none; }
}
@media (prefers-reduced-motion: reduce) {
.orb { animation: none; }
.shimmer-gold { animation: none; }
.img-reveal { clip-path: none !important; }
.card-hover { transform: none !important; }
.scroll-progress { display: none; }
}
</style>
</head>
<body>
<!-- Scroll progress indicator -->
<div class="scroll-progress" id="scrollProgress" aria-hidden="true"></div>
<!-- ================= HEADER / NAV ================= -->
<header class="glass fixed top-0 inset-x-0 z-50">
<nav class="wrap flex items-center justify-between h-[68px]" aria-label="Primary">
<a href="#home" class="flex items-center gap-2.5 group" aria-label="Trilogy Hub home">
<svg width="34" height="34" viewBox="0 0 32 32" aria-hidden="true">
<g fill="none" stroke="var(--gold)" stroke-width="1.7" stroke-linejoin="round">
<path d="M16 5 L24 19 L8 19 Z" />
<path d="M9 13 L17 27 L1 27 Z" opacity="0.55" />
<path d="M23 13 L31 27 L15 27 Z" opacity="0.55" />
</g>
</svg>
<span class="font-display font-extrabold text-lg tracking-tight">Trilogy<span class="text-gold">Hub</span></span>
</a>
<div class="hidden md:flex items-center gap-7">
<button class="nav-link" data-route="home">Home</button>
<button class="nav-link" data-route="magic-mike">Magic Tree Co.</button>
<button class="nav-link" data-route="nico">NovaTerra</button>
<button class="nav-link" data-route="paris">PG Trading</button>
<button class="nav-link" data-route="casino" data-members hidden>Casino</button>
</div>
<div class="flex items-center gap-2">
<button id="themeToggle" class="btn btn-ghost !p-2.5 !min-h-0 w-11 h-11" aria-label="Toggle light and dark mode" title="Toggle theme">
<i data-lucide="moon" class="block dark:hidden w-5 h-5"></i>
<i data-lucide="sun" class="hidden dark:block w-5 h-5"></i>
</button>
<button id="menuToggle" class="btn btn-ghost !p-2.5 !min-h-0 w-11 h-11 md:hidden" aria-label="Open menu" aria-expanded="false">
<i data-lucide="menu" class="w-5 h-5"></i>
</button>
</div>
</nav>
<!-- Mobile menu -->
<div id="mobileMenu" class="md:hidden hidden border-t border-soft bg-ink2">
<div class="wrap py-4 flex flex-col gap-1">
<button class="nav-link text-left py-3" data-route="home">Home</button>
<button class="nav-link text-left py-3" data-route="magic-mike">Magic Tree Co.</button>
<button class="nav-link text-left py-3" data-route="nico">NovaTerra Immobilien</button>
<button class="nav-link text-left py-3" data-route="paris">PG Trading Management</button>
<button class="nav-link text-left py-3" data-route="casino" data-members hidden>🎰 Casino & Games</button>
</div>
</div>
</header>
<main id="app" class="pt-[68px]">
<!-- ============================================================= -->
<!-- ============================ HOME ============================ -->
<!-- ============================================================= -->
<section id="page-home" class="page" aria-label="Home">
<!-- Hero -->
<div class="relative overflow-hidden">
<div class="orbs" aria-hidden="true" data-parallax="0.08"><span class="orb orb-1"></span><span class="orb orb-2"></span></div>
<div class="absolute inset-0 -z-10 opacity-[0.05]" style="background-image: radial-gradient(circle at 1px 1px, var(--gold) 1px, transparent 0); background-size: 28px 28px;"></div>
<div class="wrap pt-20 pb-16 md:pt-28 md:pb-24 text-center">
<p class="eyebrow reveal mb-5">Trees · Properties · Markets</p>
<h1 class="split-heading font-display font-black leading-[0.95] tracking-tight text-[clamp(2.6rem,8vw,6rem)]" data-splitting>
Three Hustlers.<br /><span class="text-gold shimmer-gold">One Vision.</span>
</h1>
<p class="reveal text-dim max-w-2xl mx-auto mt-7 text-lg md:text-xl">
Trees. Properties. Markets. We don't just talk — we build.
</p>
<div class="reveal flex flex-wrap items-center justify-center gap-3 mt-9">
<button class="btn btn-primary" data-route="magic-mike">Explore the Hub <i data-lucide="arrow-right" class="w-4 h-4"></i></button>
<button class="btn btn-ghost" data-route="paris">Trading Dashboard</button>
</div>
<!-- Three partner cards with photo slots -->
<div class="grid sm:grid-cols-3 gap-5 mt-16 text-left">
<article class="reveal card card-gold card-hover p-3" >
<div class="photo-slot !min-h-[260px]" data-slot="Magic Mike" tabindex="0" role="button" aria-label="Upload photo of Magic Mike">
<div class="slot-default"><i data-lucide="image-plus" class="slot-icon w-7 h-7"></i><span class="slot-label">Magic Mike</span></div>
<img class="preview" alt="Magic Mike" />
<span class="slot-hover-name">Magic Mike</span>
</div>
<div class="p-4">
<h3 class="font-display font-bold text-lg">Magic Mike</h3>
<p class="text-dim text-sm mt-1">Founder · Magic Tree Co.</p>
</div>
</article>
<article class="reveal card card-gold card-hover p-3">
<div class="photo-slot !min-h-[260px]" data-slot="Nico Gonzales" tabindex="0" role="button" aria-label="Upload photo of Nico Gonzales">
<div class="slot-default"><i data-lucide="image-plus" class="slot-icon w-7 h-7"></i><span class="slot-label">Nico Gonzales</span></div>
<img class="preview" alt="Nico Gonzales" />
<span class="slot-hover-name">Nico Gonzales</span>
</div>
<div class="p-4">
<h3 class="font-display font-bold text-lg">Nico Gonzales</h3>
<p class="text-dim text-sm mt-1">Broker · NovaTerra Immobilien</p>
</div>
</article>
<article class="reveal card card-gold card-hover p-3">
<div class="photo-slot !min-h-[260px]" data-slot="Paris" tabindex="0" role="button" aria-label="Upload photo of Paris">
<div class="slot-default"><i data-lucide="image-plus" class="slot-icon w-7 h-7"></i><span class="slot-label">Paris</span></div>
<img class="preview" alt="Paris" />
<span class="slot-hover-name">Paris</span>
</div>
<div class="p-4">
<h3 class="font-display font-bold text-lg">Paris</h3>
<p class="text-dim text-sm mt-1">Strategist · PG Trading Management</p>
</div>
</article>
</div>
</div>
</div>
<!-- Our Story -->
<div class="bg-ink2 border-y border-soft">
<div class="wrap py-20 md:py-28 grid md:grid-cols-2 gap-12 items-center">
<div class="reveal">
<p class="eyebrow mb-4">Our Story</p>
<h2 class="font-display font-extrabold text-[clamp(1.9rem,4vw,3rem)] leading-tight mb-6">It started with a handshake and a vision.</h2>
<p class="text-dim text-lg leading-relaxed mb-4">
Mike plants the seeds — literally. Nico turns land into legacy. Paris reads the market like a map.
Together, we invest in each other's ventures and grow as one unit.
</p>
<p class="text-dim text-lg leading-relaxed">
PG Trading Management finances stakes in Nico's real estate portfolio. Magic Tree supplies rare ornamental
trees to Nico's high-end property projects. <span class="text-gold font-semibold shimmer-gold">Three businesses. One ecosystem.</span>
</p>
</div>
<div class="photo-slot !min-h-[360px]" data-slot="Team Photo" tabindex="0" role="button" aria-label="Upload team photo">
<div class="slot-default"><i data-lucide="users" class="slot-icon w-8 h-8"></i><span class="slot-label">Team Photo</span></div>
<img class="preview" alt="Team photo" />
<span class="slot-hover-name">Team Photo</span>
</div>
</div>
</div>
<!-- Team Cards -->
<div class="wrap py-20 md:py-28">
<div class="text-center mb-14 reveal">
<p class="eyebrow mb-4">The Trilogy</p>
<h2 class="font-display font-extrabold text-[clamp(1.9rem,4vw,3rem)]">Three founders, three crafts.</h2>
</div>
<div class="grid md:grid-cols-3 gap-6">
<article class="reveal card card-gold card-hover p-7 flex flex-col">
<i data-lucide="trees" class="w-9 h-9 text-gold mb-5"></i>
<h3 class="font-display font-bold text-2xl">Magic Mike</h3>
<p class="text-gold text-sm font-semibold mt-1 mb-3">Magic Tree Co.</p>
<p class="text-dim leading-relaxed flex-1">Rare and ornamental trees for luxury gardens — from Japanese Maples to 300-year-old olive trees.</p>
<button class="btn btn-ghost mt-6 self-start" data-route="magic-mike">Visit Page <i data-lucide="arrow-up-right" class="w-4 h-4"></i></button>
</article>
<article class="reveal card card-gold card-hover p-7 flex flex-col">
<i data-lucide="building-2" class="w-9 h-9 text-gold mb-5"></i>
<h3 class="font-display font-bold text-2xl">Nico Gonzales</h3>
<p class="text-gold text-sm font-semibold mt-1 mb-3">NovaTerra Immobilien</p>
<p class="text-dim leading-relaxed flex-1">Premium real estate across Baden-Württemberg — buying, selling, and developing property into legacy.</p>
<button class="btn btn-ghost mt-6 self-start" data-route="nico">Visit Page <i data-lucide="arrow-up-right" class="w-4 h-4"></i></button>
</article>
<article class="reveal card card-gold card-hover p-7 flex flex-col">
<i data-lucide="line-chart" class="w-9 h-9 text-gold mb-5"></i>
<h3 class="font-display font-bold text-2xl">Paris</h3>
<p class="text-gold text-sm font-semibold mt-1 mb-3">PG Trading Management</p>
<p class="text-dim leading-relaxed flex-1">Real markets, no risk, full thrill. A paper-trading dashboard powered by live-simulated prices.</p>
<button class="btn btn-ghost mt-6 self-start" data-route="paris">Visit Page <i data-lucide="arrow-up-right" class="w-4 h-4"></i></button>
</article>
</div>
</div>
</section>
<!-- ============================================================= -->
<!-- ========================= MAGIC MIKE ========================= -->
<!-- ============================================================= -->
<section id="page-magic-mike" class="page" aria-label="Magic Mike — Magic Tree Co.">
<!-- Hero -->
<div class="relative min-h-[72vh] flex items-center overflow-hidden">
<div class="photo-slot absolute inset-0 !rounded-none !border-0 !min-h-0" data-slot="Hero Background" tabindex="0" role="button" aria-label="Upload hero background">
<div class="slot-default"><i data-lucide="image" class="slot-icon w-8 h-8"></i><span class="slot-label">Hero Background</span></div>
<img class="preview" alt="Magic Tree Co. hero" data-parallax-img="0.16" />
</div>
<div class="absolute inset-0 overlay-green pointer-events-none"></div>
<div class="wrap relative py-24 text-center md:text-left">
<p class="eyebrow mb-4">Magic Tree Co.</p>
<h1 class="split-heading font-display font-black text-[clamp(2.4rem,7vw,5.2rem)] leading-[0.95] max-w-3xl" data-splitting>Every Garden Tells a Story</h1>
<p class="reveal text-dim text-lg mt-6 max-w-xl">Premium ornamental trees, delivered with craftsmanship and a guarantee.</p>
</div>
</div>
<!-- About -->
<div class="wrap py-20 md:py-28 grid md:grid-cols-2 gap-12 items-center">
<div class="photo-slot !min-h-[380px]" data-slot="Mike's Portrait" tabindex="0" role="button" aria-label="Upload Mike's portrait">
<div class="slot-default"><i data-lucide="user" class="slot-icon w-8 h-8"></i><span class="slot-label">Mike's Portrait</span></div>
<img class="preview" alt="Mike portrait" />
<span class="slot-hover-name">Mike's Portrait</span>
</div>
<div class="reveal">
<p class="eyebrow mb-4">About Mike</p>
<h2 class="font-display font-extrabold text-[clamp(1.8rem,4vw,2.8rem)] mb-6 leading-tight">Where nature meets craftsmanship.</h2>
<p class="text-dim text-lg leading-relaxed">
Mike has been cultivating rare and ornamental trees for over a decade. From Japanese Maples to Giant
Sequoias, every tree he sells carries a story and a guarantee. Magic Tree Co. is more than a nursery —
it's where nature meets craftsmanship.
</p>
</div>
</div>
<!-- Products -->
<div class="bg-ink2 border-y border-soft">
<div class="wrap py-20 md:py-28">
<div class="mb-12 reveal">
<p class="eyebrow mb-4">The Collection</p>
<h2 class="font-display font-extrabold text-[clamp(1.8rem,4vw,2.8rem)]">Featured Trees</h2>
</div>
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-6" id="mikeProducts"></div>
</div>
</div>
<!-- Reviews -->
<div class="wrap py-20 md:py-28">
<div class="mb-12 reveal">
<p class="eyebrow mb-4">Word of Mouth</p>
<h2 class="font-display font-extrabold text-[clamp(1.8rem,4vw,2.8rem)]">Customer Reviews</h2>
</div>
<div class="masonry" id="mikeReviews"></div>
</div>
<!-- Happy Customers Gallery -->
<div class="bg-ink2 border-y border-soft">
<div class="wrap py-20 md:py-28">
<div class="mb-12 reveal">
<p class="eyebrow mb-4">Happy Customers</p>
<h2 class="font-display font-extrabold text-[clamp(1.8rem,4vw,2.8rem)]">Their Gardens, Transformed</h2>
</div>
<div class="grid grid-cols-2 md:grid-cols-3 gap-5" id="mikeGallery"></div>
</div>
</div>
</section>
<!-- ============================================================= -->
<!-- ============================ NICO ============================ -->
<!-- ============================================================= -->
<section id="page-nico" class="page" aria-label="Nico Gonzales — NovaTerra Immobilien">
<!-- Hero -->
<div class="relative min-h-[72vh] flex items-center overflow-hidden">
<div class="photo-slot absolute inset-0 !rounded-none !border-0 !min-h-0" data-slot="Hero Background" tabindex="0" role="button" aria-label="Upload hero background">
<div class="slot-default"><i data-lucide="image" class="slot-icon w-8 h-8"></i><span class="slot-label">Hero Background</span></div>
<img class="preview" alt="NovaTerra hero" data-parallax-img="0.16" />
</div>
<div class="absolute inset-0 overlay-navy pointer-events-none"></div>
<div class="wrap relative py-24 text-center md:text-left">
<p class="eyebrow mb-4">NovaTerra Immobilien · New Ground. New Possibilities.</p>
<h1 class="split-heading font-display font-black text-[clamp(2.4rem,7vw,5.2rem)] leading-[0.95] max-w-3xl" data-splitting>Your Property. Your Legacy.</h1>
<p class="reveal text-dim text-lg mt-6 max-w-xl">Premium real estate, brokered with discretion and results.</p>
</div>
</div>
<!-- About -->
<div class="wrap py-20 md:py-28 grid md:grid-cols-2 gap-12 items-center">
<div class="reveal">
<p class="eyebrow mb-4">About Nico</p>
<h2 class="font-display font-extrabold text-[clamp(1.8rem,4vw,2.8rem)] mb-6 leading-tight">Closing premium deals across the region.</h2>
<p class="text-dim text-lg leading-relaxed">
Nico Gonzales has been closing premium real estate deals across Baden-Württemberg for years. With a network
spanning developers, investors, and private buyers, NovaTerra Immobilien is your partner for buying, selling,
and developing property — backed by the investment muscle of PG Trading Management.
</p>
</div>
<div class="photo-slot !min-h-[380px]" data-slot="Nico's Headshot" tabindex="0" role="button" aria-label="Upload Nico's headshot">
<div class="slot-default"><i data-lucide="user" class="slot-icon w-8 h-8"></i><span class="slot-label">Nico's Headshot</span></div>
<img class="preview" alt="Nico headshot" />
<span class="slot-hover-name">Nico's Headshot</span>
</div>
</div>
<!-- Listings -->
<div class="bg-ink2 border-y border-soft">
<div class="wrap py-20 md:py-28">
<div class="mb-12 reveal">
<p class="eyebrow mb-4">Portfolio</p>
<h2 class="font-display font-extrabold text-[clamp(1.8rem,4vw,2.8rem)]">Featured Listings</h2>
</div>
<div class="grid sm:grid-cols-2 gap-6" id="nicoListings"></div>
</div>
</div>
<!-- Testimonials -->
<div class="wrap py-20 md:py-28">
<div class="mb-12 reveal">
<p class="eyebrow mb-4">Trusted By</p>
<h2 class="font-display font-extrabold text-[clamp(1.8rem,4vw,2.8rem)]">Client Testimonials</h2>
</div>
<div class="grid sm:grid-cols-2 gap-6" id="nicoTestimonials"></div>
</div>
<!-- Gallery -->
<div class="bg-ink2 border-y border-soft">
<div class="wrap py-20 md:py-28">
<div class="mb-12 reveal">
<p class="eyebrow mb-4">Moments</p>
<h2 class="font-display font-extrabold text-[clamp(1.8rem,4vw,2.8rem)]">Deals & Handshakes</h2>
</div>
<div class="grid grid-cols-2 md:grid-cols-3 gap-5" id="nicoGallery"></div>
</div>
</div>
</section>
<!-- ============================================================= -->
<!-- =========================== PARIS =========================== -->
<!-- ============================================================= -->
<section id="page-paris" class="page" aria-label="Paris — PG Trading Management">
<!-- Login gate -->
<div id="parisLogin" class="wrap py-24 md:py-32">
<div class="max-w-md mx-auto text-center mb-10 reveal">
<i data-lucide="line-chart" class="w-12 h-12 text-gold mx-auto mb-5"></i>
<p class="eyebrow mb-3">PG Trading Management</p>
<h1 class="font-display font-black text-[clamp(2rem,6vw,3.4rem)] leading-tight">Your Portfolio. Your Game.</h1>
<p class="text-dim mt-4 text-lg">Real markets. No risk. Full thrill.</p>
</div>
<form id="loginForm" class="card card-gold max-w-md mx-auto p-8" novalidate>
<h2 class="font-display font-bold text-xl mb-1">Member Login</h2>
<p class="text-faint text-sm mb-6">Demo access — user: <span class="text-gold">paris</span> / pass: <span class="text-gold">trading123</span></p>
<label class="block text-sm font-semibold mb-2" for="username">Username</label>
<input class="input mb-4" type="text" id="username" name="username" autocomplete="username" placeholder="paris" />
<label class="block text-sm font-semibold mb-2" for="password">Password</label>
<input class="input mb-2" type="password" id="password" name="password" autocomplete="current-password" placeholder="••••••••" />
<p id="loginError" class="text-error text-sm h-5 mb-2" role="alert"></p>
<button type="submit" class="btn btn-primary w-full">Log In <i data-lucide="lock-open" class="w-4 h-4"></i></button>
</form>
</div>
<!-- Dashboard -->
<div id="parisDashboard" class="hidden">
<!-- Dashboard navbar -->
<div class="bg-ink2 border-b border-soft">
<div class="wrap flex flex-wrap items-center justify-between gap-4 py-4">
<div class="flex items-center gap-3">
<i data-lucide="line-chart" class="w-6 h-6 text-gold"></i>
<span class="font-display font-bold">PG Trading <span class="text-gold">Management</span></span>
<span class="chip ml-2"><span class="live-dot"></span> LIVE</span>
<span class="chip text-gold">Play Money</span>
</div>
<div class="flex items-center gap-4">
<div class="text-right">
<p class="text-faint text-xs">Portfolio</p>
<p class="font-display font-bold text-gold" data-counter="7334899.31" data-prefix="€" data-decimals="2">€7,334,899.31</p>
</div>
<span class="chip">Logged in as Paris</span>
<button id="logoutBtn" class="btn btn-ghost !min-h-0 !py-2.5">Logout <i data-lucide="log-out" class="w-4 h-4"></i></button>
</div>
</div>
</div>
<div class="wrap py-12">
<!-- KPI cards -->
<div class="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-10">
<div class="card p-5">
<p class="text-faint text-xs uppercase tracking-wider mb-2">Portfolio Value</p>
<p class="font-display font-extrabold text-2xl" data-counter="7334899.31" data-prefix="€" data-decimals="2">€7,334,899.31</p>
</div>
<div class="card p-5">
<p class="text-faint text-xs uppercase tracking-wider mb-2">Today's P&L</p>
<p class="font-display font-extrabold text-2xl text-success"><span data-counter="48213.55" data-prefix="+€" data-decimals="2">+€48,213.55</span> <span class="text-sm">(+0.66%)</span></p>
</div>
<div class="card p-5">
<p class="text-faint text-xs uppercase tracking-wider mb-2">Open Positions</p>
<p class="font-display font-extrabold text-2xl" data-counter="10" data-decimals="0">10</p>
</div>
<div class="card p-5">
<p class="text-faint text-xs uppercase tracking-wider mb-2">Buying Power</p>
<p class="font-display font-extrabold text-2xl" data-counter="57539.31" data-prefix="€" data-decimals="2">€57,539.31</p>
</div>
</div>
<div class="grid lg:grid-cols-3 gap-8">
<!-- Watchlist -->
<div class="lg:col-span-2">
<h2 class="font-display font-bold text-xl mb-4 flex items-center gap-2"><i data-lucide="list" class="w-5 h-5 text-gold"></i> Watchlist</h2>
<div class="card overflow-hidden">
<div class="overflow-x-auto">
<table class="w-full text-sm" id="watchlistTable">
<thead>
<tr class="text-faint text-left border-b border-soft">
<th class="py-3 px-4 font-semibold">Ticker</th>
<th class="py-3 px-4 font-semibold">Company</th>
<th class="py-3 px-4 font-semibold text-right">Shares</th>
<th class="py-3 px-4 font-semibold text-right">Avg Buy</th>
<th class="py-3 px-4 font-semibold text-right">Price</th>
<th class="py-3 px-4 font-semibold text-right">P&L</th>
<th class="py-3 px-4 font-semibold text-right">P&L%</th>
</tr>
</thead>
<tbody id="watchlistBody"></tbody>
</table>
</div>
</div>
<!-- Trade log -->
<h2 class="font-display font-bold text-xl mt-10 mb-4 flex items-center gap-2"><i data-lucide="history" class="w-5 h-5 text-gold"></i> Trade Log</h2>
<div class="card divide-y" id="tradeLog" style="--tw-divide-opacity:1"></div>
</div>
<!-- Pie chart -->
<div>
<h2 class="font-display font-bold text-xl mb-4 flex items-center gap-2"><i data-lucide="pie-chart" class="w-5 h-5 text-gold"></i> Allocation</h2>
<div class="card p-6">
<canvas id="allocationChart" height="260"></canvas>
<div id="chartLegend" class="mt-5 space-y-2 text-sm"></div>
</div>
</div>
</div>
</div>
<!-- Disclaimer -->
<div class="bg-ink2 border-t border-soft">
<div class="wrap py-4 text-center text-faint text-sm flex items-center justify-center gap-2">
<i data-lucide="alert-triangle" class="w-4 h-4 text-gold shrink-0"></i>
<span>PG Trading Management is a simulation platform for entertainment purposes only. No real money is involved. Not financial advice.</span>
</div>
</div>
</div>
</section>
<!-- ============================================================= -->
<!-- ========================== CASINO =========================== -->
<!-- ============================================================= -->
<section id="page-casino" class="page" aria-label="PlayBull Casino & Games">
<!-- Login gate (shown when not authenticated) -->
<div id="casinoGate" class="wrap py-24 md:py-32 hidden">
<div class="max-w-md mx-auto text-center reveal">
<i data-lucide="dices" class="w-12 h-12 text-gold mx-auto mb-5"></i>
<p class="eyebrow mb-3">Members Only</p>
<h1 class="font-display font-black text-[clamp(2rem,6vw,3.4rem)] leading-tight">Casino &amp; Games</h1>
<p class="text-dim mt-4 text-lg">Chicken Road, 10×10 Deck, Crash &amp; mehr — mit deinem PlayBull-Konto.</p>
<button class="btn btn-primary mt-8" id="casinoLoginBtn">Einloggen / Registrieren <i data-lucide="log-in" class="w-4 h-4"></i></button>
</div>
</div>
<!-- Embedded full PlayBull arcade (shares the same login + balance) -->
<div id="casinoFrameWrap" class="hidden">
<div class="bg-ink2 border-b border-soft">
<div class="wrap flex flex-wrap items-center justify-between gap-3 py-4">
<div class="flex items-center gap-3">
<i data-lucide="dices" class="w-6 h-6 text-gold"></i>
<span class="font-display font-bold">PlayBull <span class="text-gold">Arcade</span></span>
<span class="chip"><span class="live-dot"></span> LIVE</span>
<span class="chip text-gold">Play Money</span>
</div>
<a href="/play.html" target="_blank" rel="noopener" class="btn btn-ghost !min-h-0 !py-2.5">Vollbild öffnen <i data-lucide="external-link" class="w-4 h-4"></i></a>
</div>
</div>
<iframe id="casinoFrame" title="PlayBull Arcade" style="width:100%;height:calc(100vh - 68px - 64px);border:0;display:block;background:var(--bg)"></iframe>
</div>
</section>
</main>
<!-- ================= FOOTER ================= -->
<footer class="bg-ink2 border-t border-soft">
<div class="wrap py-12 flex flex-col md:flex-row items-center justify-between gap-6">
<div class="flex items-center gap-2.5">
<svg width="28" height="28" viewBox="0 0 32 32" aria-hidden="true">
<g fill="none" stroke="var(--gold)" stroke-width="1.7" stroke-linejoin="round">
<path d="M16 5 L24 19 L8 19 Z" /><path d="M9 13 L17 27 L1 27 Z" opacity="0.55" /><path d="M23 13 L31 27 L15 27 Z" opacity="0.55" />
</g>
</svg>
<span class="font-display font-extrabold">Trilogy<span class="text-gold">Hub</span></span>
</div>
<nav class="flex flex-wrap items-center justify-center gap-6" aria-label="Footer">
<button class="nav-link" data-route="magic-mike">Magic Tree Co.</button>
<button class="nav-link" data-route="nico">NovaTerra Immobilien</button>
<button class="nav-link" data-route="paris">PG Trading Management</button>
<button class="nav-link" data-route="casino" data-members hidden>Casino &amp; Games</button>
</nav>
</div>
<div class="wrap pb-8 text-faint text-sm text-center md:text-left">
Trilogy Hub © 2025 — Built by three, grown together.
</div>
</footer>
<!-- ================= SCRIPTS ================= -->
<script src="/socket.io/socket.io.js"></script>
<script src="image-editor.js"></script>
<script src="app.js"></script>
<script src="playbull.js"></script>
</body>
</html>