diff --git a/src/app/(site)/layout.tsx b/src/app/(site)/layout.tsx index 26b9c963..4aa4b4ae 100644 --- a/src/app/(site)/layout.tsx +++ b/src/app/(site)/layout.tsx @@ -1,5 +1,6 @@ import dynamic from "next/dynamic"; import type { ReactNode } from "react"; +import { CloudsField } from "@/components/clouds-field"; import MotionPageWrapper from "@/components/motion-page-wrapper"; import { Navigation } from "@/components/navigation"; import { SiteFooter } from "@/components/site-footer"; @@ -29,6 +30,7 @@ export default async function SiteLayout({ return ( <> + {session?.user?.id ? ( <>
diff --git a/src/app/globals.css b/src/app/globals.css index b10c4877..3acbe547 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -342,6 +342,97 @@ summary, transparent 100% ); } +/* Floating cloud puffs drifting across the public background. */ +.clouds { + position: fixed; + inset: 0; + z-index: -1; + pointer-events: none; + overflow: hidden; +} +.cloud { + position: absolute; + width: clamp(140px, 22vw, 260px); + height: clamp(40px, 7vw, 70px); + left: 0; + opacity: 0.7; + transform: scale(var(--cloud-scale, 1)); + filter: blur(0.5px); + will-change: transform; + animation-name: cloud-drift; + animation-timing-function: linear; + animation-iteration-count: infinite; + background: + radial-gradient( + ellipse 62% 55% at 30% 50%, + rgba(255, 255, 255, 0.6) 0%, + transparent 70% + ), + radial-gradient( + ellipse 70% 60% at 55% 45%, + rgba(255, 255, 255, 0.55) 0%, + transparent 72% + ), + radial-gradient( + ellipse 60% 55% at 78% 58%, + rgba(255, 255, 255, 0.45) 0%, + transparent 72% + ); +} +.cloud-1 { + --cloud-scale: 1.15; + top: 7%; + animation-duration: 95s; + animation-delay: -30s; +} +.cloud-2 { + --cloud-scale: 0.75; + top: 15%; + opacity: 0.45; + animation-duration: 130s; + animation-delay: -85s; +} +.cloud-3 { + --cloud-scale: 0.9; + top: 24%; + opacity: 0.5; + animation-duration: 160s; + animation-delay: -60s; +} +.cloud-4 { + --cloud-scale: 0.6; + top: 34%; + opacity: 0.3; + animation-duration: 110s; + animation-delay: -105s; +} +.cloud-5 { + --cloud-scale: 1.35; + top: 45%; + opacity: 0.22; + animation-duration: 190s; + animation-delay: -140s; +} +@keyframes cloud-drift { + 0% { + transform: translateX(clamp(-30vw, -220px, -140px)) + scale(var(--cloud-scale, 1)); + } + 100% { + transform: translateX(calc(100vw + 260px)) scale(var(--cloud-scale, 1)); + } +} +html.dark .cloud { + opacity: 0.28; +} +@media (prefers-reduced-motion: reduce) { + .cloud { + animation: none; + transform: translateX(clamp(-30vw, -220px, -140px)) + scale(var(--cloud-scale, 1)); + } +} + /* Subtle primary glow */ .site-bg::after { content: ""; diff --git a/src/components/clouds-field.tsx b/src/components/clouds-field.tsx new file mode 100644 index 00000000..f10ebe32 --- /dev/null +++ b/src/components/clouds-field.tsx @@ -0,0 +1,15 @@ +/** + * Drifting cloud puffs that float across the public background. + * Pure decoration: fixed, behind the content, no pointer events. + */ +export function CloudsField() { + return ( + + ); +}