Claude Directory
UI experiments built with Claude. Watch the demos, copy the prompts, browse the code.
UI experiments built with Claude. Watch the demos, copy the prompts, browse the code.
Built with Claude from a single prompt.
# PROJECT OVERVIEW
BUILD A SINGLE-PAGE, FULL-VIEWPORT CINEMATIC PRELOADER SCREEN. IT IS ONE FIXED FULL-SCREEN OVERLAY (Z-INDEX 9999) ON A NEAR-BLACK NAVY BACKGROUND. A 1394 BY 938 DESIGN CANVAS IS UNIFORMLY SCALED TO FIT THE VIEWPORT (OBJECT-FIT CONTAIN BEHAVIOR). INSIDE THE CANVAS: TWO SOFT RADIAL BLOOMS, 30 TWINKLING PARTICLE DOTS, A GLOWING 3D SPHERE IMAGE WITH COLOR-DODGE BLEND, A FLOWING DASHED ORBIT LINE DRAWN AS AN SVG PATH WITH A VERTICAL FADE MASK, A LARGE CONCENTRIC CIRCLES SVG BEHIND THE SPHERE, THREE DECORATIVE LINE ORNAMENTS (LINE-C-1, LINE-C-2, LINE-C-3) ALL CENTERED ON THE CANVAS WITH NO HORIZONTAL OFFSET, A SMALL 80X80 LOGO (FULL-LOGO.SVG) REVEALED BY TWO ANIMATED TRIANGLE MASKS PRODUCING A CONTINUOUS WAVE-CUT EFFECT, THE WORDMARK MONETA KEY BELOW THE LOGO, A CURVED CANVAS-BASED NUMBER ARC 0–100 NEAR THE BOTTOM, AND FOUR BOUNCING DOTS BELOW THE ARC. OUTSIDE THE SCALED CANVAS, TWO SVG ORNAMENTS LEFT.SVG AND RIGHT.SVG ARE PINNED FLUSH TO THE ACTUAL VIEWPORT BOTTOM-LEFT AND BOTTOM-RIGHT CORNERS. THERE IS NO EXIT TRANSITION TRIGGERED BY REACHING 100; THE LOADER KEEPS IDLING FOREVER.
# TECH STACK
REACT 18 + TYPESCRIPT + VITE + TAILWIND V3. FRAMER-MOTION FOR ANIMATEPRESENCE AND MOTION COMPONENTS. PLAIN CANVAS 2D API FOR THE CURVED NUMBER ARC. REQUESTANIMATIONFRAME FOR THE CHUNKED PROGRESS DRIVER. SINGLE INDEX ROUTE RENDERS A WRAPPER DIV WITH MIN-H-SCREEN AND INLINE STYLE BACKGROUNDCOLOR "#080B14" CONTAINING THE PRELOADER COMPONENT.
# CONSTANTS
```
const BG = "#080B14";
const DESIGN_WIDTH = 1394;
const DESIGN_HEIGHT = 938;
```
# ASSETS (ALL HOSTED AT https://qclay.design/lovable/moneta/)
- SPHERE-3.PNG — GLOWING ORB
- CIRCELS.SVG — CONCENTRIC CIRCLES
- LINE-C-1.SVG — DECORATIVE LINE ORNAMENT
- LINE-C-2.SVG — DECORATIVE LINE ORNAMENT
- LINE-C-3.SVG — DECORATIVE LINE ORNAMENT
- FULL-LOGO.SVG — MONETA MARK USED INSIDE AN SVG IMAGE ELEMENT WITH A MASK
- LEFT.SVG — BOTTOM-LEFT VIEWPORT ORNAMENT
- RIGHT.SVG — BOTTOM-RIGHT VIEWPORT ORNAMENT
# ROOT CONTAINER (MOTION.DIV, KEY "PRELOADER")
- INITIAL { OPACITY: 1 }
- EXIT { OPACITY: 0, SCALE: 1.05, FILTER: "BLUR(8PX)" }
- TRANSITION { DURATION: 0.8, EASE: [0.4, 0, 0.2, 1] }
- STYLE: POSITION FIXED, INSET 0, ZINDEX 9999, BACKGROUND "#080B14", OVERFLOW HIDDEN, FONTFAMILY "'INTER TIGHT', SANS-SERIF"
- CLASSNAME "FLEX FLEX-COL ITEMS-CENTER JUSTIFY-CENTER"
THE EXIT TRANSITION IS DEFINED BUT NEVER TRIGGERED AUTOMATICALLY — THE COMPONENT STAYS MOUNTED FOREVER.
# RESPONSIVE SCALE WRAPPER
A CHILD DIV, ABSOLUTELY POSITIONED AT TOP 50% LEFT 50%, WIDTH DESIGN_WIDTH (1394), HEIGHT DESIGN_HEIGHT (938), TRANSFORM `translate(-50%, -50%) scale(${scale})`, TRANSFORMORIGIN "CENTER CENTER". THE SCALE VALUE IS COMPUTED IN A USEEFFECT:
```
const update = () => setScale(Math.min(window.innerWidth / DESIGN_WIDTH, window.innerHeight / DESIGN_HEIGHT));
update();
window.addEventListener("resize", update);
```
THIS MAKES THE ENTIRE 1394X938 DESIGN FIT THE VIEWPORT WHILE PRESERVING ASPECT RATIO.
# LAYER 1 — INNER RADIAL BLOOM (SMALL, BLUE-VIOLET)
ABSOLUTE, TOP 50% LEFT 50%, TRANSFORM TRANSLATE(-50%, -50%), WIDTH 600, HEIGHT 600, BORDERRADIUS 50%,
BACKGROUND: RADIAL-GRADIENT(CIRCLE, RGBA(100,120,255,0.12) 0%, RGBA(80,60,180,0.06) 40%, TRANSPARENT 70%)
POINTEREVENTS NONE. STATIC — NO ANIMATION.
# LAYER 2 — OUTER RADIAL BLOOM (LARGE, DEEP BLUE)
ABSOLUTE, TOP 50% LEFT 50%, TRANSFORM TRANSLATE(-50%, -50%), WIDTH 900, HEIGHT 900, BORDERRADIUS 50%,
BACKGROUND: RADIAL-GRADIENT(CIRCLE, RGBA(60,80,200,0.06) 0%, TRANSPARENT 65%)
POINTEREVENTS NONE. STATIC.
# LAYER 3 — PARTICLE FIELD (30 TWINKLING DOTS)
A WRAPPER DIV ABSOLUTE INSET 0 ZINDEX 0 POINTEREVENTS NONE. INSIDE, EXACTLY 30 MOTION.DIV PARTICLES. THEY ARE GENERATED ONCE WITH USEMEMO:
```
const particles = useMemo(
() => Array.from({ length: 30 }, () => ({
top: Math.random() * 100,
left: Math.random() * 100,
opacity: 0.1 + Math.random() * 0.2,
duration: 3 + Math.random() * 4,
delay: Math.random() * 4,
})),
[]
);
```
EACH PARTICLE:
STYLE: POSITION ABSOLUTE, TOP `${p.top}%`, LEFT `${p.left}%`, WIDTH 1.5, HEIGHT 1.5, BORDERRADIUS 50%, BACKGROUND `rgba(255,255,255,${p.opacity})`
ANIMATE { OPACITY: [0.05, 0.25, 0.05] }
TRANSITION { DURATION: P.DURATION, DELAY: P.DELAY, REPEAT: INFINITY, EASE: "EASEINOUT" }
# LAYER 4 — SPHERE (SPHERE-3.PNG)
MOTION.IMG SRC "https://qclay.design/lovable/moneta/sphere-3.png"
INITIAL { SCALE: 0.85, OPACITY: 0, FILTER: "BLUR(12PX)" }
ANIMATE { SCALE: [1, 1.025, 1], OPACITY: 0.7, FILTER: "BLUR(0PX)" }
TRANSITION {
SCALE: { DURATION: 4, REPEAT: INFINITY, EASE: "EASEINOUT", DELAY: 1.4 },
OPACITY: { DURATION: 1.4, DELAY: 2, EASE: "EASEOUT" },
FILTER: { DURATION: 1.4, DELAY: 2, EASE: "EASEOUT" },
}
STYLE: POSITION ABSOLUTE, TOP 50%, LEFT 50%, WIDTH 433, HEIGHT 394, MARGINLEFT -216.5, MARGINTOP -197, OBJECTFIT CONTAIN, ZINDEX 1, POINTEREVENTS NONE, MIXBLENDMODE "COLOR-DODGE"
THE SPHERE FADES IN BLURRED AND SCALED DOWN, THEN SETTLES TO OPACITY 0.7 WITH A CONTINUOUS GENTLE 4-SECOND BREATHING PULSE BETWEEN SCALE 1 AND 1.025.
# LAYER 5 — DASHED ORBIT LINE (CUSTOM SVG PATH WITH FRONT-FADE MASK)
WRAPPER DIV ABSOLUTE, TOP 50%, LEFT 50%, WIDTH 840, HEIGHT 420, MARGINLEFT -420, MARGINTOP -210, ZINDEX 2, POINTEREVENTS NONE.
INSIDE: AN SVG WITH VIEWBOX "0 0 1044 356", PRESERVEASPECTRATIO "NONE", STYLE POSITION ABSOLUTE, INSET 0, WIDTH 100%, HEIGHT 100%, OVERFLOW VISIBLE.
DEFS:
- LINEARGRADIENT ID "LINEDRAWGRADIENT" X1 0% Y1 0% X2 100% Y2 0% WITH THREE STOPS:
- 0% RGBA(255,255,255,0)
- 50% RGBA(220,225,255,0.95)
- 100% RGBA(255,255,255,0)
- LINEARGRADIENT ID "LINEFRONTFADEGRADIENT" X1 0 Y1 0 X2 0 Y2 1 GRADIENTUNITS OBJECTBOUNDINGBOX WITH STOPS:
- 0% #000
- 40% #000
- 58% #FFF
- 100% #FFF
- MASK ID "LINEFRONTFADEMASK" MASKUNITS USERSPACEONUSE X -200 Y -200 WIDTH 1444 HEIGHT 800, CONTAINING A SINGLE RECT X -200 Y -200 WIDTH 1444 HEIGHT 800 FILL "URL(#LINEFRONTFADEGRADIENT)"
INSIDE A G WITH MASK "URL(#LINEFRONTFADEMASK)", A SINGLE MOTION.PATH:
KEY `linepath-${runId}`
D "M1042.76 35.8838C1058.87 95.0224 838.678 206.483 550.956 284.839C263.235 363.194 16.9353 378.772 0.830078 319.634C-15.2752 260.495 204.913 149.034 492.634 70.6789C780.355 -7.67647 1026.66 -23.2548 1042.76 35.8838Z"
FILL "NONE"
STROKE "URL(#LINEDRAWGRADIENT)"
STROKEWIDTH 1
STROKELINECAP "ROUND"
PATHLENGTH 1
INITIAL { STROKEDASHOFFSET: 0 }
ANIMATE { STROKEDASHOFFSET: [0, -1.45] }
TRANSITION { DURATION: 5, DELAY: 1.6, REPEAT: INFINITY, REPEATDELAY: 0, EASE: "LINEAR" }
STYLE { STROKEDASHARRAY: "0.45 1", FILTER: "DROP-SHADOW(0 0 4PX RGBA(200,210,255,0.6))" }
THE MASK'S VERTICAL GRADIENT (BLACK ON TOP, WHITE ON BOTTOM, SOFT TRANSITION AROUND 40-58%) MEANS THE FRONT (LOWER) HALF OF THE OVAL IS HIDDEN BY THE MASK WHILE THE BACK (UPPER) HALF IS FULLY DRAWN — CREATING THE ILLUSION THAT THE DASHED LINE PASSES BEHIND THE SPHERE ON ONE SIDE. BECAUSE PATHLENGTH=1 AND THE DASHARRAY IS "0.45 1", THE DASHES FLOW CONTINUOUSLY AROUND THE OVAL.
# LAYER 6 — CIRCELS.SVG (CONCENTRIC CIRCLES, BEHIND SPHERE)
IMG (NO ANIMATION) SRC "https://qclay.design/lovable/moneta/circels.svg"
STYLE: POSITION ABSOLUTE, TOP 50%, LEFT 50%, TRANSFORM TRANSLATE(-50%, -50%), WIDTH 766, HEIGHT 766, ZINDEX -2, POINTEREVENTS NONE.
# LAYER 7 — LINE-C-1 (CENTERED)
OUTER DIV: POSITION ABSOLUTE, TOP 50%, LEFT 50%, TRANSFORM TRANSLATE(-50%, -50%), ZINDEX -1, POINTEREVENTS NONE.
INSIDE, MOTION.IMG SRC "https://qclay.design/lovable/moneta/line-c-1.svg"
INITIAL { OPACITY: 0, Y: 30 }
ANIMATE { OPACITY: 1, Y: 0 }
TRANSITION { DURATION: 0.9, DELAY: 0.3, EASE: "EASEOUT" }
STYLE { DISPLAY: "BLOCK" }
# LAYER 8 — LINE-C-2 (CENTERED, IDENTICAL WRAPPER AS LINE-C-1)
OUTER DIV: POSITION ABSOLUTE, TOP 50%, LEFT 50%, TRANSFORM TRANSLATE(-50%, -50%), ZINDEX -1, POINTEREVENTS NONE.
MOTION.IMG SRC "https://qclay.design/lovable/moneta/line-c-2.svg"
INITIAL { OPACITY: 0, Y: 30 }
ANIMATE { OPACITY: 1, Y: 0 }
TRANSITION { DURATION: 0.9, DELAY: 0.5, EASE: "EASEOUT" }
# LAYER 9 — LINE-C-3 (TOP-CENTERED)
OUTER DIV: POSITION ABSOLUTE, TOP 0, LEFT 50%, TRANSFORM TRANSLATEX(-50%), ZINDEX -1, POINTEREVENTS NONE.
MOTION.IMG SRC "https://qclay.design/lovable/moneta/line-c-3.svg"
INITIAL { OPACITY: 0, Y: -30 }
ANIMATE { OPACITY: 1, Y: 0 }
TRANSITION { DURATION: 0.9, DELAY: 0.4, EASE: "EASEOUT" }
ALL THREE LINE-C ORNAMENTS RELY ON THE SVG ASSET'S INTRINSIC DIMENSIONS AND NATURAL ALIGNMENT. LINE-C-1 AND LINE-C-2 ARE CENTERED ON THE CANVAS; LINE-C-3 IS ANCHORED TO THE TOP EDGE, HORIZONTALLY CENTERED. NONE ARE OFF-CENTER VIA POSITIONING — THE SVG ARTWORK ITSELF SUPPLIES ANY ASYMMETRY.
# LAYER 10 — LOGO + WORDMARK BLOCK
OUTER DIV: POSITION ABSOLUTE, TOP 50%, LEFT 50%, TRANSFORM TRANSLATE(-50%, -60%), ZINDEX 3, DISPLAY FLEX, FLEXDIRECTION COLUMN, ALIGNITEMS CENTER, GAP 16.
## LOGO HALO (RADIAL BEHIND THE 80X80 LOGO)
A RELATIVE WRAPPER DIV WIDTH 80, HEIGHT 80. INSIDE IT, MOTION.DIV:
INITIAL { OPACITY: 0, SCALE: 0.5 }
ANIMATE { OPACITY: 1, SCALE: 1 }
TRANSITION { DURATION: 0.8, DELAY: 0.3 }
STYLE: POSITION ABSOLUTE, INSET -20, BORDERRADIUS 50%, BACKGROUND "RADIAL-GRADIENT(CIRCLE, RGBA(255,255,255,0.18) 0%, TRANSPARENT 65%)", ZINDEX -1, POINTEREVENTS NONE.
## LOGO ITSELF — MOTION.SVG WITH WAVE-CUT MASK
VIEWBOX "0 0 48 48", PRESERVEASPECTRATIO "XMIDYMID MEET"
INITIAL { OPACITY: 0, Y: -12 }
ANIMATE { OPACITY: 1, Y: 0 }
TRANSITION { DURATION: 0.6, DELAY: 0, EASE: "EASEOUT" }
STYLE: POSITION ABSOLUTE, INSET 0, WIDTH 100%, HEIGHT 100%, OVERFLOW VISIBLE.
TWO TRIANGLE PARAMETER OBJECTS (KEPT IN STATE, FULLY EDITABLE):
```
const [tri1, setTri1] = useState({ width: 22.8, height: 24.4, offsetY: 0.2 });
const [tri2, setTri2] = useState({ width: 26.3, height: 25.51, offsetY: 23.5 });
```
EACH TRIANGLE PATH IS BUILT BY A HELPER:
```
const triPath = (t) => {
const x1 = 24 - t.width / 2;
const x2 = 24 + t.width / 2;
const yTop = t.offsetY;
const yTip = t.offsetY + t.height;
return `M${x1} ${yTop}L24 ${yTip}L${x2} ${yTop}L${x1} ${yTop}Z`;
};
```
THESE ARE DOWNWARD-POINTING TRIANGLES CENTERED AT X=24, WITH TIP AT THE BOTTOM.
DEFS > MASK ID "LOGOCUTMASK" MASKUNITS USERSPACEONUSE X 0 Y 0 WIDTH 48 HEIGHT 48 CONTAINS:
1. A WHITE RECT X 0 Y 0 WIDTH 48 HEIGHT 48 (ENTIRE LOGO VISIBLE BY DEFAULT).
2. MOTION.PATH FOR TRI1 (KEY USES TRI1 DIMENSIONS), D=TRIPATH(TRI1), FILL "BLACK":
INITIAL { Y: -TRI1.HEIGHT, OPACITY: 0 }
ANIMATE {
Y: [-TRI1.HEIGHT, -TRI1.HEIGHT, 0, 0, 60, 60, -TRI1.HEIGHT],
OPACITY: [0, 1, 1, 1, 1, 0, 0],
}
TRANSITION {
DURATION: 3,
TIMES: [0, 0.02, 0.183, 0.617, 0.767, 0.787, 1],
EASE: ["LINEAR", "EASEINOUT", "LINEAR", "EASEIN", "LINEAR", "LINEAR"],
REPEAT: INFINITY,
REPEATDELAY: 0,
}
3. MOTION.PATH FOR TRI2 (KEY USES TRI2 DIMENSIONS), D=TRIPATH(TRI2), FILL "BLACK":
INITIAL { Y: -TRI2.HEIGHT, OPACITY: 0 }
ANIMATE {
Y: [-TRI2.HEIGHT, -TRI2.HEIGHT, -TRI2.HEIGHT, 0, 0, 60, 60, -TRI2.HEIGHT],
OPACITY: [0, 0, 1, 1, 1, 1, 0, 0],
}
TRANSITION {
DURATION: 3,
TIMES: [0, 0.183, 0.203, 0.367, 0.617, 0.767, 0.787, 1],
EASE: ["LINEAR", "LINEAR", "EASEINOUT", "LINEAR", "EASEIN", "LINEAR", "LINEAR"],
REPEAT: INFINITY,
REPEATDELAY: 0,
}
AFTER DEFS, AN SVG IMAGE ELEMENT:
THE MASK LOGIC: WHITE = VISIBLE, BLACK TRIANGLES = CUT OUT. TRI1 SITS HIDDEN ABOVE THE LOGO, THEN SNAPS TO Y=0 (COVERING THE UPPER PORTION), HOLDS, THEN SLIDES DOWN TO Y=60 (OUT THE BOTTOM), THEN JUMPS BACK TO START. TRI2 FOLLOWS A SLIGHTLY DELAYED AND OFFSET CHOREOGRAPHY. TOGETHER THEY PRODUCE A CONTINUOUS WAVE-CUT SWEEP THROUGH THE LOGO, REPEATING EVERY 3 SECONDS FOREVER. THE LOGO ALWAYS RENDERS FULL IMAGE MASKED; THE SLICES ROLLING THROUGH CUT VISIBLE CHUNKS OUT AND LET THEM REBUILD.
## WORDMARK "MONETA KEY"
MOTION.DIV BELOW THE LOGO:
INITIAL { OPACITY: 0, Y: 8, FILTER: "BLUR(4PX)" }
ANIMATE { OPACITY: 1, Y: 0, FILTER: "BLUR(0PX)" }
TRANSITION { DURATION: 0.6, DELAY: 0.8, EASE: "EASEOUT" }
STYLE: FONTFAMILY "'INTER TIGHT', SANS-SERIF", FONTSIZE 13, FONTWEIGHT 400, LETTERSPACING "5PX", COLOR "RGBA(255,255,255,0.75)", TEXTALIGN "CENTER"
TEXT CONTENT: MONETA KEY
# LAYER 11 — NUMBER ARC (PRELOADERNUMBERARC COMPONENT)
RENDERED WITH KEY={RUNID} AND PROP PROGRESS={PROGRESS}.
COMPONENT IMPLEMENTATION (PRELOADERNUMBERARC.TSX):
CONSTANTS:
- CANVAS_WIDTH = 550
- CANVAS_HEIGHT = 70
- ARC_RADIUS = 310
- CENTER_X = 275 (CANVAS_WIDTH / 2)
- CENTER_Y = 330 (WELL BELOW THE VISIBLE CANVAS)
- CENTER_ANGLE = -Math.PI / 2 (STRAIGHT UP)
- ANGLE_STEP = Math.PI / 16
- FONT_SIZE = 17
- FONT = `300 17px "Inter Tight", sans-serif`
- VISIBLE_DISTANCE = 5
WRAPPER DIV:
POSITION ABSOLUTE, LEFT 50%, BOTTOM 123, TRANSFORM TRANSLATEX(-50%), WIDTH 550, HEIGHT 70, ZINDEX 4, POINTEREVENTS NONE, OVERFLOW HIDDEN, ARIA-HIDDEN "TRUE".
INSIDE: A SINGLE CANVAS WITH STYLE DISPLAY BLOCK, WIDTH 100%, HEIGHT 100%, AND BOTH WEBKITMASKIMAGE AND MASKIMAGE SET TO:
"RADIAL-GRADIENT(ELLIPSE 55% 100% AT 50% 50%, BLACK 0%, RGBA(0,0,0,0.85) 35%, RGBA(0,0,0,0.4) 65%, TRANSPARENT 100%)"
THIS MAKES THE NUMBERS FADE TO INVISIBLE TOWARD THE CANVAS EDGES.
DPR HANDLING: IN THE DRAW FUNCTION, MULTIPLY WIDTH AND HEIGHT BY WINDOW.DEVICEPIXELRATIO FOR CRISP RENDERING, WHILE KEEPING STYLE WIDTH 550 / HEIGHT 70 FIXED.
DRAWING EACH FRAME, GIVEN A SMOOTHED VALUE:
```
ctx.setTransform(1,0,0,1,0,0); ctx.scale(ratio, ratio); ctx.clearRect(0,0,550,70);
ctx.save(); ctx.beginPath(); ctx.rect(0,0,550,70); ctx.clip();
ctx.font = FONT; ctx.textAlign = "center"; ctx.textBaseline = "middle";
for (let number = 0; number <= 100; number += 1) {
const distance = number - value;
const absDistance = Math.abs(distance);
if (absDistance > 5) continue;
const angle = -Math.PI/2 + distance * (Math.PI/16);
const x = 275 + Math.cos(angle) * 310;
const y = 330 + Math.sin(angle) * 310;
if (x < -80 || x > 630 || y < -20 || y > 90) continue;
const fade = Math.pow(1 - absDistance / 5, 2.2);
const opacity = Math.max(0, 0.95 * fade);
const focal = Math.max(0, 1 - absDistance / 1.2);
const scale = 1 + focal * 0.35;
ctx.save();
ctx.translate(x, y);
ctx.scale(scale, scale);
if (focal > 0.05) {
ctx.shadowColor = `rgba(180, 200, 255, ${focal * 0.9})`;
ctx.shadowBlur = 18 * focal;
}
ctx.fillStyle = `rgba(255,255,255,${opacity})`;
ctx.fillText(String(number), 0, 0);
ctx.restore();
}
ctx.restore();
```
PER-FRAME SMOOTHING TOWARD TARGET PROGRESS (LERP FACTOR 0.045):
```
const tick = () => {
const current = animatedProgressRef.current;
const target = targetProgressRef.current;
const delta = target - current;
if (Math.abs(delta) < 0.001) {
animatedProgressRef.current = target;
draw(target);
frameRef.current = null;
return;
}
animatedProgressRef.current = current + delta * 0.045;
draw(animatedProgressRef.current);
frameRef.current = requestAnimationFrame(tick);
};
```
THIS PRODUCES A SMOOTH INERTIAL SLIDE OF NUMBERS ACROSS THE CURVE EVEN WHEN THE UNDERLYING PROGRESS JUMPS IN CHUNKS. THE FOCAL NUMBER (CLOSEST TO THE TOP OF THE ARC) SCALES UP TO 1.35X AND GETS A SOFT COOL-BLUE GLOW. NUMBERS FURTHER FROM FOCAL FADE SMOOTHLY VIA THE POWER CURVE.
# LAYER 12 — BOUNCING DOTS (MEXICAN WAVE UNDER THE ARC)
```
const dotColors = [
"rgba(255,255,255,0.70)",
"rgba(255,255,255,0.55)",
"rgba(255,255,255,0.55)",
"rgba(255,255,255,0.70)",
];
```
WRAPPER DIV: POSITION ABSOLUTE, BOTTOM 107, LEFT 50%, TRANSFORM TRANSLATEX(-50%), ZINDEX 4, DISPLAY FLEX, ALIGNITEMS CENTER, GAP 7.
EACH OF THE 4 DOTS IS A MOTION.DIV:
ANIMATE { Y: [-7, 0, -7] }
TRANSITION { DURATION: 1.2, REPEAT: INFINITY, EASE: "EASEINOUT", DELAY: I * 0.18 }
STYLE: WIDTH 7, HEIGHT 7, BORDERRADIUS 50%, BACKGROUND DOTCOLORS[I].
THIS CREATES A CONTINUOUS LEFT-TO-RIGHT WAVE BOUNCE.
# LAYER 13 — EDGE-PINNED ORNAMENTS (OUTSIDE THE SCALED WRAPPER, HUGGING VIEWPORT)
MOTION.IMG SRC "https://qclay.design/lovable/moneta/left.svg"
INITIAL { OPACITY: 0, Y: 20 }
ANIMATE { OPACITY: 1, Y: 0 }
TRANSITION { DURATION: 0.9, DELAY: 0.6, EASE: "EASEOUT" }
STYLE: POSITION ABSOLUTE, BOTTOM 0, LEFT 0, ZINDEX 4, POINTEREVENTS NONE, DISPLAY BLOCK.
MOTION.IMG SRC "https://qclay.design/lovable/moneta/right.svg"
INITIAL { OPACITY: 0, Y: 20 }
ANIMATE { OPACITY: 1, Y: 0 }
TRANSITION { DURATION: 0.9, DELAY: 0.6, EASE: "EASEOUT" }
STYLE: POSITION ABSOLUTE, BOTTOM 0, RIGHT 0, ZINDEX 4, POINTEREVENTS NONE, DISPLAY BLOCK.
THESE ARE SIBLINGS OF THE SCALED DESIGN WRAPPER INSIDE THE ROOT MOTION.DIV, SO THEY ALWAYS STAY FLUSH TO THE ACTUAL VIEWPORT EDGES REGARDLESS OF HOW THE 1394X938 DESIGN CANVAS IS SCALED.
# PROGRESS DRIVER (CRITICAL — NON-LINEAR REALISTIC LOADING)
IMPLEMENTED IN USEEFFECT KEYED ON RUNID. IT BUILDS A SEQUENCE OF VARIABLE CHUNKS SUMMING TO 100, EACH WITH RANDOM PRE-DELAY AND RANDOM TRAVERSAL DURATION:
```
useEffect(() => {
setProgress(0);
let cancelled = false;
let current = 0;
const segments = [];
let acc = 0;
while (acc < 100) {
const r = Math.random();
let chunk;
if (r < 0.15) chunk = 1 + Math.random() * 3; // tiny stall-ish
else if (r < 0.85) chunk = 4 + Math.random() * 12; // normal
else chunk = 14 + Math.random() * 18; // burst
acc = Math.min(100, acc + chunk);
const delay = 40 + Math.random() * 220;
const duration = 120 + Math.random() * 380;
segments.push({ to: acc, delay, duration });
}
const animateSegment = (i) => {
if (cancelled || i >= segments.length) return;
const seg = segments[i];
setTimeout(() => {
if (cancelled) return;
const from = current;
const start = performance.now();
const step = (t) => {
if (cancelled) return;
const k = Math.min(1, (t - start) / seg.duration);
const eased = 1 - Math.pow(1 - k, 2); // easeOut quadratic
const value = from + (seg.to - from) * eased;
current = value;
setProgress(value);
if (k < 1) requestAnimationFrame(step);
else { current = seg.to; setProgress(seg.to); animateSegment(i + 1); }
};
requestAnimationFrame(step);
}, seg.delay);
};
animateSegment(0);
return () => { cancelled = true; };
}, [runId]);
```
RESULT: BURSTS OF FAST PROGRESS, BRIEF STALLS, SLOW CRAWLS — NATURAL AND UNPREDICTABLE. TOTAL LOADING TIME TYPICALLY 4–8 SECONDS. WHEN PROGRESS REACHES 100, NOTHING FADES OUT; THE LOADER SIMPLY RESTS AT 100 WITH ALL LOOPS CONTINUING FOREVER.
# ORBIT DOT HELPER (DEFINED BUT CURRENTLY UNUSED IN RENDER)
A SUBCOMPONENT ORBITDOT EXISTS IN THE FILE. IT ANIMATES A SMALL WHITE DOT WITH A SOFT GLOW AND A 20-PIXEL TRAILING GRADIENT, ROTATING AROUND AN ELLIPSE OF ARBITRARY RX, RY, ROTATION, AND DURATION VIA REQUESTANIMATIONFRAME. IT IS EXPORTED AS A HELPER BUT NOT CURRENTLY RENDERED IN THE MAIN COMPOSITION. KEEP ITS IMPLEMENTATION INTACT FOR FUTURE USE:
```
const OrbitDot = ({ rx, ry, rotateDeg, duration, size, opacity, trailOpacity, startOffset = 0 }) => {
const [angle, setAngle] = useState(startOffset Math.PI 2);
useEffect(() => {
let raf = 0;
const start = performance.now();
const tick = (t) => {
const elapsed = (t - start) / 1000;
const a = startOffset Math.PI 2 + (elapsed / duration) Math.PI 2;
setAngle(a);
raf = requestAnimationFrame(tick);
};
raf = requestAnimationFrame(tick);
return () => cancelAnimationFrame(raf);
}, [duration, startOffset]);
const x = Math.cos(angle) * rx;
const y = Math.sin(angle) * ry;
const rad = (rotateDeg * Math.PI) / 180;
const rotX = x Math.cos(rad) - y Math.sin(rad);
const rotY = x Math.sin(rad) + y Math.cos(rad);
return (
);
};
```
# STATE INVENTORY
```
const [progress, setProgress] = useState(0);
const [runId, setRunId] = useState(0);
const [mounted] = useState(true);
const [scale, setScale] = useState(1);
const [tri1, setTri1] = useState({ width: 22.8, height: 24.4, offsetY: 0.2 });
const [tri2, setTri2] = useState({ width: 26.3, height: 25.51, offsetY: 23.5 });
```
THE RUNID IS WIRED INTO THE LINE AND ARC KEYS SO ANY FUTURE REPLAY WOULD RESET THEIR ANIMATIONS CLEANLY, BUT NO REPLAY UI IS RENDERED.
# WHAT IS NOT IN THE SCREEN
NO REPLAY BUTTON, NO SKIP BUTTON, NO CLOSE BUTTON. NO TOP HAIRLINE PROGRESS BAR. NO STATUS TEXT LINE. NO TAGLINE. NO PHRASE CYCLING. NO EXIT FADE TRIGGERED ON 100. THE ARC AND DOTS AND BLOOM AND ORBIT ALL KEEP RUNNING INDEFINITELY.
# PAGE WRAPPER (SRC/PAGES/INDEX.TSX)
```
import Preloader from "@/components/Preloader";
const Index = () => (
);
export default Index;
```
# FILE STRUCTURE
- SRC/PAGES/INDEX.TSX — PAGE WRAPPER AS ABOVE.
- SRC/COMPONENTS/PRELOADER.TSX — THE ENTIRE COMPOSITION DESCRIBED ABOVE, INCLUDING THE ORBITDOT HELPER SUBCOMPONENT.
- SRC/COMPONENTS/PRELOADERNUMBERARC.TSX — THE CANVAS-BASED CURVED 0–100 NUMBER SCROLLER DESCRIBED IN LAYER 11.
# TYPOGRAPHY
SINGLE FONT FAMILY THROUGHOUT: INTER TIGHT (LOADED VIA GOOGLE FONTS IN INDEX.HTML OR IMPORTED GLOBALLY). THE ARC USES 300 WEIGHT 17PX. THE "MONETA KEY" WORDMARK USES 400 WEIGHT 13PX WITH 5PX LETTER-SPACING AND COLOR RGBA(255,255,255,0.75). EVERYTHING ELSE IS WHITE AT VARYING OPACITIES.
# COLOR PALETTE
- BACKGROUND: #080B14.
- ALL FOREGROUND CONTENT: WHITE AT OPACITIES RANGING FROM ~0.05 (FAINTEST PARTICLE) TO ~0.95 (FOCAL ARC NUMBER).
- GLOWS: COOL BLUE-WHITE RGBA(180, 200, 255, ALPHA) FOR THE FOCAL ARC NUMBER; RGBA(200,210,255,0.6) DROP-SHADOW ON THE ORBIT LINE; RGBA(255,255,255,…) SOFT HALOS.
- BLOOMS: RGBA(100,120,255,0.12) INNER AND RGBA(60,80,200,0.06) OUTER. NO WARM COLORS ANYWHERE.
# OVERALL BEHAVIOR
ON MOUNT: SPHERE FADES IN BLURRED, BLOOMS APPEAR, PARTICLES BEGIN TWINKLING, LINE ORNAMENTS SLIDE INTO PLACE, THE DASHED ORBIT BEGINS FLOWING, THE 80X80 LOGO FADES DOWN WITH ITS WAVE-CUT MASK ALREADY CYCLING, THE WORDMARK MONETA KEY BLURS IN BELOW IT, THE NUMBER ARC STARTS AT 0 AND CLIMBS IN IRREGULAR CHUNKS TOWARD 100, THE FOUR DOTS BEGIN THEIR CONTINUOUS MEXICAN WAVE BELOW THE ARC, AND LEFT/RIGHT SVGS FADE UP FROM THE VIEWPORT CORNERS. THE COMPOSITION IS DARK, GLOWING, RESTRAINED, AND ONCE IT REACHES 100 IT SIMPLY RESTS THERE WITH ALL IDLE LOOPS STILL RUNNING.