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 (
+
+
+
+
+
+
+
+ );
+}