Spaces:
Sleeping
Sleeping
| import { useEffect, useRef, useState } from "react"; | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // StudioShowcase β the homepage's living art piece. A self-running reel that | |
| // demonstrates the product's OWN range: kinetic type, documentary lower-thirds, | |
| // Arabic RTL aurora titles, animated data, glassmorphism, 3D space and neural | |
| // agent viz β each with its own palette, font and background. Pure CSS/SVG, so | |
| // it always renders (no headless player, no fonts-required fallbacks break it). | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // shared list, also used by the homepage marquee | |
| export const STYLE_NAMES = [ | |
| "Kinetic Type", "Lower-Thirds", "Glassmorphism", "Aurora", "Neural Nets", "3D Space", | |
| "Atlas Maps", "Data Viz", "Sketchbook", "Logo Intros", "Documentary", "Counters", | |
| "Waveforms", "Comic", "Chalkboard", "Spotlight", "Glitch", "Reveal", | |
| ]; | |
| const GRAIN = | |
| "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E\")"; | |
| export const SHOWCASE_CSS = ` | |
| @keyframes mg-in { from { opacity: 0; transform: scale(.985); } to { opacity: 1; transform: none; } } | |
| @keyframes mg-rise { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: none; } } | |
| @keyframes mg-rise-sm { from { opacity: 0; transform: translateY(13px); } to { opacity: 1; transform: none; } } | |
| @keyframes mg-pop { 0% { opacity: 0; transform: scale(.7); } 62% { opacity: 1; transform: scale(1.06); } 100% { transform: scale(1); } } | |
| @keyframes mg-sweep { from { transform: scaleX(0); } to { transform: scaleX(1); } } | |
| @keyframes mg-sweep-v { from { transform: scaleY(0); } to { transform: scaleY(1); } } | |
| @keyframes mg-float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-14px); } } | |
| @keyframes mg-float2 { 0%,100% { transform: translate(0,0); } 50% { transform: translate(12px,-20px); } } | |
| @keyframes mg-grid { from { background-position: 0 0; } to { background-position: 0 42px; } } | |
| @keyframes mg-aurora { 0% { transform: translate(-9%,0) rotate(-7deg); } 50% { transform: translate(9%,5%) rotate(-2deg); } 100% { transform: translate(-9%,0) rotate(-7deg); } } | |
| @keyframes mg-draw { to { stroke-dashoffset: 0; } } | |
| @keyframes mg-pulse { 0%,100% { opacity: .35; transform: translate(-50%,-50%) scale(1); } 50% { opacity: 1; transform: translate(-50%,-50%) scale(1.35); } } | |
| @keyframes mg-spin3d { from { transform: rotateY(-26deg) rotateX(6deg); } to { transform: rotateY(26deg) rotateX(-6deg); } } | |
| @keyframes mg-blink { 0%,100% { opacity: 1; } 50% { opacity: 0; } } | |
| @keyframes mg-mesh { 0% { transform: translate(0,0) scale(1); } 33% { transform: translate(4%,-3%) scale(1.08); } 66% { transform: translate(-3%,4%) scale(1.05); } 100% { transform: translate(0,0) scale(1); } } | |
| @keyframes mg-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } } | |
| @keyframes mg-word-in { from { opacity: 0; transform: translateY(16px) rotate(-2deg); } to { opacity: 1; transform: none; } } | |
| @keyframes mg-word-out{ to { opacity: 0; transform: translateY(-12px); } } | |
| @keyframes mg-ring { to { stroke-dashoffset: 0; } } | |
| @keyframes mg-scan { from { transform: translateY(-100%); } to { transform: translateY(220%); } } | |
| `; | |
| // ββ Scene 1 Β· Kinetic typography ββββββββββββββββββββββββββββββββββββββββββββ | |
| function KineticScene() { | |
| return ( | |
| <div className="absolute inset-0 overflow-hidden" style={{ background: "radial-gradient(120% 100% at 50% 0%, #1c1450, #0a0a16 72%)" }}> | |
| <div className="absolute inset-x-0 bottom-0 h-1/2" style={{ backgroundImage: "linear-gradient(rgba(150,120,255,.20) 1px, transparent 1px), linear-gradient(90deg, rgba(150,120,255,.20) 1px, transparent 1px)", backgroundSize: "42px 42px", transform: "perspective(420px) rotateX(60deg)", transformOrigin: "bottom", animation: "mg-grid 2.4s linear infinite", maskImage: "linear-gradient(to top, #000, transparent)", WebkitMaskImage: "linear-gradient(to top, #000, transparent)" }} /> | |
| <div className="absolute inset-0 grid place-items-center"> | |
| <div className="text-center"> | |
| {["STORIES", "IN", "MOTION"].map((w, i) => ( | |
| <div key={w} className="font-extrabold leading-[0.92] tracking-tight" style={{ fontSize: "clamp(34px,7vw,82px)", fontFamily: "Inter, sans-serif", animation: `mg-rise .7s ${0.12 * i + 0.1}s both`, backgroundImage: "linear-gradient(100deg,#a78bfa,#f472b6 55%,#fb923c)", WebkitBackgroundClip: "text", backgroundClip: "text", color: "transparent" }}>{w}</div> | |
| ))} | |
| <div className="mx-auto mt-4 h-[3px] w-44 rounded-full" style={{ background: "linear-gradient(90deg,#a78bfa,#fb923c)", transformOrigin: "left", animation: "mg-sweep .8s .55s both" }} /> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| // ββ Scene 2 Β· Documentary lower-third βββββββββββββββββββββββββββββββββββββββ | |
| function DocScene() { | |
| return ( | |
| <div className="absolute inset-0 overflow-hidden" style={{ background: "radial-gradient(130% 90% at 72% 18%, #2c1d11, #080706 76%)" }}> | |
| <div className="absolute inset-0" style={{ boxShadow: "inset 0 0 160px 40px rgba(0,0,0,.7)" }} /> | |
| <div className="absolute right-5 top-5 flex items-center gap-3 text-[11px] font-medium tracking-wider text-white/60" style={{ fontFamily: "'JetBrains Mono', monospace", animation: "mg-rise-sm .5s .1s both" }}> | |
| <span className="flex items-center gap-1.5"><span className="h-2 w-2 rounded-full bg-red-500" style={{ animation: "mg-blink 1s steps(1) infinite" }} />REC</span> | |
| <span>00:00:14:09</span> | |
| </div> | |
| <div className="absolute inset-x-7 bottom-10"> | |
| <div className="flex items-stretch gap-3.5"> | |
| <div className="w-1.5 rounded-full" style={{ background: "linear-gradient(#f4934f,#e7723b)", transformOrigin: "top", animation: "mg-sweep-v .5s .15s both" }} /> | |
| <div> | |
| <div className="font-semibold leading-tight text-white" style={{ fontSize: "clamp(26px,4.4vw,48px)", fontFamily: "Georgia, 'Times New Roman', serif", animation: "mg-rise .6s .25s both" }}>Dr. Lina Haddad</div> | |
| <div className="relative mt-1.5 inline-block px-0.5"> | |
| <span className="relative z-10 text-[12.5px] font-semibold uppercase tracking-[0.18em] text-white" style={{ animation: "mg-rise-sm .6s .45s both" }}>Marine Biologist Β· Red Sea</span> | |
| <span className="absolute inset-y-0 -inset-x-1" style={{ background: "rgba(231,114,59,.92)", transformOrigin: "left", animation: "mg-sweep .55s .62s both" }} /> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| // ββ Scene 3 Β· Arabic Β· Aurora Β· RTL βββββββββββββββββββββββββββββββββββββββββ | |
| function ArabicScene() { | |
| return ( | |
| <div dir="rtl" className="absolute inset-0 overflow-hidden" style={{ background: "linear-gradient(160deg,#04211e,#06100f)" }}> | |
| <div className="absolute -inset-[20%]"> | |
| <div className="absolute left-1/2 top-1/3 h-44 w-[150%] -translate-x-1/2 rounded-full blur-3xl" style={{ background: "linear-gradient(90deg, rgba(54,194,184,0), rgba(54,194,184,.55), rgba(16,185,129,0))", animation: "mg-aurora 9s ease-in-out infinite" }} /> | |
| <div className="absolute left-1/2 top-1/2 h-36 w-[140%] -translate-x-1/2 rounded-full blur-3xl" style={{ background: "linear-gradient(90deg, rgba(45,212,191,0), rgba(94,234,212,.4), rgba(45,212,191,0))", animation: "mg-aurora 11s ease-in-out infinite reverse" }} /> | |
| </div> | |
| <div className="absolute inset-0 grid place-items-center px-8 text-center"> | |
| <div> | |
| <div className="text-[16px] font-semibold tracking-wide text-teal-300/90" style={{ fontFamily: "'El Messiri', sans-serif", animation: "mg-rise-sm .6s .15s both" }}>Ψ₯Ψ¨Ψ―Ψ§ΨΉ Ψ¨Ψ΅Ψ±Ω</div> | |
| <div className="mt-2 font-bold leading-none text-white" style={{ fontSize: "clamp(44px,10vw,104px)", fontFamily: "'Reem Kufi', sans-serif", animation: "mg-rise .7s .25s both" }}>Ψ¨ΩΨ§ ΨΨ―ΩΨ―</div> | |
| <div className="mx-auto mt-6 h-[3px] w-48 rounded-full" style={{ background: "linear-gradient(90deg,#5eead4,#10b981)", transformOrigin: "right", animation: "mg-sweep .8s .55s both" }} /> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| // ββ Scene 4 Β· Animated data / counter βββββββββββββββββββββββββββββββββββββββ | |
| function CounterScene() { | |
| const [n, setN] = useState(0); | |
| useEffect(() => { | |
| let raf = 0; | |
| const t0 = performance.now(); | |
| const tick = (t: number) => { | |
| const p = Math.min(1, (t - t0) / 1500); | |
| const e = 1 - Math.pow(1 - p, 3); | |
| setN(Math.round(e * 340)); | |
| if (p < 1) raf = requestAnimationFrame(tick); | |
| }; | |
| raf = requestAnimationFrame(tick); | |
| return () => cancelAnimationFrame(raf); | |
| }, []); | |
| return ( | |
| <div className="absolute inset-0 overflow-hidden" style={{ background: "radial-gradient(80% 72% at 50% 10%, #2a230c, #070707 72%)" }}> | |
| <div className="absolute left-1/2 top-0 h-full w-[58%] -translate-x-1/2" style={{ background: "linear-gradient(to bottom, rgba(224,179,65,.20), transparent 58%)", filter: "blur(10px)" }} /> | |
| <div className="absolute inset-0 grid place-items-center"> | |
| <div className="text-center"> | |
| <div className="font-extrabold leading-none text-white" style={{ fontSize: "clamp(60px,13vw,132px)", fontFamily: "'JetBrains Mono', monospace", fontVariantNumeric: "tabular-nums", animation: "mg-pop .6s both" }}> | |
| <span style={{ color: "#E0B341" }}>+</span>{n}<span style={{ color: "#E0B341" }}>%</span> | |
| </div> | |
| <div className="mt-2 text-[14px] font-medium uppercase tracking-[0.22em] text-white/70" style={{ animation: "mg-rise-sm .6s .4s both" }}>year-over-year growth</div> | |
| <div className="mx-auto mt-5 flex items-center gap-2.5 text-[12px] text-amber-200/80" style={{ fontFamily: "'JetBrains Mono', monospace", animation: "mg-rise-sm .6s .55s both" }}> | |
| <span>Q4 2026</span><span className="text-white/30">Β·</span><span className="font-bold text-amber-300">record quarter</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| // ββ Scene 5 Β· Glassmorphism βββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function GlassScene() { | |
| return ( | |
| <div className="absolute inset-0 overflow-hidden" style={{ background: "linear-gradient(150deg,#2a1130,#3b1538 50%,#120a1a)" }}> | |
| <div className="absolute h-44 w-44 rounded-full blur-2xl" style={{ left: "8%", top: "16%", background: "radial-gradient(circle,#e879f9,transparent 70%)", animation: "mg-float2 7s ease-in-out infinite" }} /> | |
| <div className="absolute h-52 w-52 rounded-full blur-2xl" style={{ right: "6%", bottom: "10%", background: "radial-gradient(circle,#f0abfc,transparent 70%)", animation: "mg-float 9s ease-in-out infinite" }} /> | |
| <div className="absolute inset-0 grid place-items-center px-8"> | |
| <div className="w-full max-w-[340px] rounded-2xl border border-white/20 p-6 text-center shadow-2xl" style={{ background: "rgba(255,255,255,.08)", backdropFilter: "blur(16px)", WebkitBackdropFilter: "blur(16px)", animation: "mg-pop .7s both, mg-float 8s ease-in-out 1s infinite" }}> | |
| <div className="mx-auto mb-3 grid h-12 w-12 place-items-center rounded-full" style={{ background: "linear-gradient(135deg,#f0abfc,#c026d3)" }}> | |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="#fff"><path d="M8 5v14l11-7z" /></svg> | |
| </div> | |
| <div className="text-[23px] font-bold text-white" style={{ animation: "mg-rise-sm .6s .2s both" }}>Designed to move</div> | |
| <div className="mt-1 text-[13px] text-white/70" style={{ animation: "mg-rise-sm .6s .32s both" }}>premium motion, on demand</div> | |
| <div className="mt-4 flex flex-wrap justify-center gap-1.5"> | |
| {["Reels", "Promos", "Launches"].map((t, i) => ( | |
| <span key={t} className="rounded-full border border-white/20 bg-white/10 px-2.5 py-1 text-[11px] font-medium text-white/90" style={{ animation: `mg-rise-sm .5s ${0.42 + i * 0.08}s both` }}>{t}</span> | |
| ))} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| // ββ Scene 6 Β· 3D space ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function ThreeDScene() { | |
| return ( | |
| <div className="absolute inset-0 grid place-items-center overflow-hidden" style={{ background: "radial-gradient(90% 80% at 50% 30%, #0c1f3a, #050a14 76%)", perspective: "820px" }}> | |
| <div style={{ transformStyle: "preserve-3d", animation: "mg-spin3d 5s ease-in-out infinite alternate" }}> | |
| <div className="relative grid h-40 w-64 place-items-center rounded-2xl border border-white/15 text-white shadow-2xl" style={{ background: "linear-gradient(135deg, rgba(96,165,250,.38), rgba(37,99,235,.14))", backdropFilter: "blur(6px)", WebkitBackdropFilter: "blur(6px)", transform: "translateZ(46px)" }}> | |
| <div className="text-center"> | |
| <div className="text-[46px] font-extrabold leading-none" style={{ fontFamily: "Inter, sans-serif", letterSpacing: "-0.02em" }}>2026</div> | |
| <div className="mt-1 text-[12px] uppercase tracking-[0.28em] text-blue-200/80">the year in motion</div> | |
| </div> | |
| <div className="absolute inset-x-0 top-0 h-1/2 rounded-t-2xl" style={{ background: "linear-gradient(to bottom, rgba(255,255,255,.16), transparent)" }} /> | |
| </div> | |
| <div className="absolute inset-x-6 -bottom-7 h-10 rounded-full blur-md" style={{ background: "radial-gradient(ellipse, rgba(96,165,250,.45), transparent 70%)", transform: "rotateX(72deg)" }} /> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| // ββ Scene 7 Β· Arabic statement (RTL) β a second, distinct bilingual showcase β | |
| function ArabicStatement() { | |
| return ( | |
| <div dir="rtl" className="absolute inset-0 overflow-hidden" style={{ background: "linear-gradient(150deg,#2a1130,#3b1538 50%,#120a1a)" }}> | |
| <div className="absolute h-44 w-44 rounded-full blur-2xl" style={{ right: "10%", top: "16%", background: "radial-gradient(circle,#e879f9,transparent 70%)", animation: "mg-float2 8s ease-in-out infinite" }} /> | |
| <div className="absolute h-52 w-52 rounded-full blur-2xl" style={{ left: "8%", bottom: "12%", background: "radial-gradient(circle,#f0abfc,transparent 70%)", animation: "mg-float 10s ease-in-out infinite" }} /> | |
| <div className="absolute inset-0 grid place-items-center px-10 text-center"> | |
| <div> | |
| <div className="text-[16px] font-semibold tracking-wide" style={{ color: "#f0abfc", fontFamily: "'El Messiri', sans-serif", animation: "mg-rise-sm .6s .15s both" }}>Ψ¨ΩΨΊΨͺΩΨ ΩΨ¨ΩΩ Ψ₯ΨͺΩΨ§Ω</div> | |
| <div className="mt-3 font-bold text-white" style={{ fontSize: "clamp(38px,8vw,86px)", lineHeight: 1.18, fontFamily: "'Reem Kufi', sans-serif", animation: "mg-rise .7s .25s both" }}>ΩΨ΅ΨͺΩ ΨͺΨͺΨΨ±ΩΩ<br />ΩΩ Ψ§ ΨͺΨ³ΨͺΨΩ</div> | |
| <div className="mx-auto mt-6 h-[3px] w-44 rounded-full" style={{ background: "linear-gradient(90deg,#e879f9,#c026d3)", transformOrigin: "right", animation: "mg-sweep .8s .55s both" }} /> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| const SCENES = [ | |
| { key: "kinetic", tag: "Kinetic typography", Comp: KineticScene }, | |
| { key: "doc", tag: "Documentary Β· lower-third", Comp: DocScene }, | |
| { key: "ar", tag: "Ψ§ΩΨΉΨ±Ψ¨ΩΨ© Β· Aurora Β· RTL", Comp: ArabicScene }, | |
| { key: "count", tag: "Animated data", Comp: CounterScene }, | |
| { key: "glass", tag: "Glassmorphism", Comp: GlassScene }, | |
| { key: "3d", tag: "3D space", Comp: ThreeDScene }, | |
| { key: "arstmt", tag: "Ψ§ΩΨΉΨ±Ψ¨ΩΨ© Β· Statement Β· RTL", Comp: ArabicStatement }, | |
| ]; | |
| export function StudioShowcase({ withStyle = true }: { withStyle?: boolean }) { | |
| const [idx, setIdx] = useState(0); | |
| const prev = useRef(0); | |
| useEffect(() => { | |
| const t = setInterval(() => setIdx((i) => { prev.current = i; return (i + 1) % SCENES.length; }), 4000); | |
| return () => clearInterval(t); | |
| }, []); | |
| const Cur = SCENES[idx].Comp; | |
| const Prev = SCENES[prev.current].Comp; | |
| return ( | |
| <div className="relative h-full w-full overflow-hidden bg-[#07070d]"> | |
| {withStyle && <style>{SHOWCASE_CSS}</style>} | |
| {prev.current !== idx && <div key={"p" + prev.current} className="absolute inset-0"><Prev /></div>} | |
| <div key={"a" + idx} className="absolute inset-0" style={{ animation: "mg-in .7s ease both" }}><Cur /></div> | |
| {/* film grain + scanline for cinematic texture */} | |
| <div className="pointer-events-none absolute inset-0 z-10 opacity-[0.07] mix-blend-overlay" style={{ backgroundImage: GRAIN }} /> | |
| <div className="pointer-events-none absolute inset-x-0 top-0 z-10 h-1/3 opacity-30" style={{ background: "linear-gradient(to bottom, rgba(255,255,255,.10), transparent)", animation: "mg-scan 6s linear infinite" }} /> | |
| {/* technique label */} | |
| <div key={"l" + idx} className="absolute left-4 top-4 z-20 inline-flex items-center gap-2 rounded-full border border-white/15 bg-black/35 px-3 py-1.5 text-[11px] font-semibold tracking-wide text-white/90 backdrop-blur-sm" style={{ animation: "mg-rise-sm .6s .15s both" }}> | |
| <span className="h-1.5 w-1.5 rounded-full bg-[#e7723b]" /> {SCENES[idx].tag} | |
| </div> | |
| {/* progress dots */} | |
| <div className="absolute bottom-4 left-1/2 z-20 flex -translate-x-1/2 items-center gap-1.5"> | |
| {SCENES.map((s, i) => ( | |
| <span key={s.key} className="h-1.5 rounded-full transition-all duration-500" style={{ width: i === idx ? 20 : 6, background: i === idx ? "#e7723b" : "rgba(255,255,255,.3)" }} /> | |
| ))} | |
| </div> | |
| </div> | |
| ); | |
| } | |