diff --git a/app/layout.tsx b/app/layout.tsx
index 771a359..16a4cfa 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -39,6 +39,7 @@ import { FloatingInstallBanner } from "@/components/pwa/FloatingInstallBanner";
import { DisclaimerModal } from "@/components/DisclaimerModal";
import { CommandPalette } from "@/components/command/CommandPalette";
import { ThemeSync } from "@/components/layout/ThemeSync";
+import { BrandSplash } from '@/components/brand/BrandSplash';
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "https://pdfly-source.github.io";
const BASE_PATH = process.env.NEXT_PUBLIC_BASE_PATH ?? "";
@@ -127,6 +128,7 @@ export default function RootLayout({
return (
+
diff --git a/components/brand/BrandSplash.tsx b/components/brand/BrandSplash.tsx
new file mode 100644
index 0000000..be091a1
--- /dev/null
+++ b/components/brand/BrandSplash.tsx
@@ -0,0 +1,156 @@
+'use client';
+
+import React, { useState, useEffect } from 'react';
+
+export interface BrandSplashProps {
+ autoDismissMs?: number;
+ onComplete?: () => void;
+}
+
+const CSS = `
+.bs-root{position:fixed;inset:0;z-index:9999;overflow:hidden;isolation:isolate;transition:opacity .4s ease}
+.bs-root.is-fading{opacity:0}
+.bs-root>*{position:absolute}
+.bs-ph{width:240px;height:500px;border:6px solid #15151a;border-radius:36px;position:relative;overflow:hidden;cursor:pointer;isolation:isolate;box-shadow:0 18px 40px rgba(0,0,0,.18)}
+.bs-ph>*{position:absolute}
+.bs-ctr{inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding-bottom:44px}
+.bs-ctr img{display:block;mix-blend-mode:multiply}
+.bs-cc{left:50%;top:190px}
+.bs-go .bs-mk{animation:zoom 1s cubic-bezier(.2,.9,.3,1.1) .2s both}
+.bs-go .bs-tx{animation:rise .8s ease .9s both}
+.bs-pb{left:60px;right:60px;bottom:54px;height:5px;border-radius:5px;background:rgba(0,0,0,.07);overflow:hidden}
+.bs-pb:after,.bs-steps i:after{content:"";display:block;height:100%;width:0;border-radius:5px;background:var(--pg,var(--s))}
+.bs-go .bs-pb:after{animation:fill 2.4s cubic-bezier(.4,0,.2,1) .6s both}
+/* 1 AppMintly */
+.bs-a1{background:radial-gradient(circle at 12% 8%,rgba(31,157,85,.2),transparent 46%),radial-gradient(circle at 92% 96%,rgba(37,99,235,.22),transparent 52%),#f8fbff}
+.bs-rg{width:200px;height:200px;margin:-100px 0 0 -100px;border-radius:50%;border:1.5px solid rgba(37,99,235,.4);opacity:0}
+.bs-go .bs-rg{animation:ring 1.6s ease-out .3s both}
+.bs-dots{left:0;right:0;bottom:52px;display:flex;justify-content:center;gap:9px}
+.bs-dots i{width:9px;height:9px;border-radius:50%;opacity:.25;animation:pulse 1.1s ease-in-out infinite}
+/* 2 NexDrop */
+.bs-a2{background:linear-gradient(135deg,#ebfafd,#fff 50%,#fff0e8)}
+.bs-sk{left:0;height:5px;border-radius:5px;opacity:0}
+.bs-go .bs-sk{animation:streak 1.3s cubic-bezier(.2,.7,.2,1) both}
+.bs-go.bs-a2 .bs-mk{animation:slide .8s cubic-bezier(.2,.8,.2,1) .25s both}
+.bs-go.bs-a2 .bs-tx{animation:wipe .8s cubic-bezier(.6,0,.2,1) .9s both}
+/* 3 Niramay */
+.bs-a3{background:radial-gradient(circle at 50% 38%,#fffef8,#f6eed8 85%)}
+.bs-gl{width:300px;height:300px;margin:-150px 0 0 -150px;border-radius:50%;background:radial-gradient(circle,rgba(212,170,70,.28),transparent 68%);opacity:0}
+.bs-go .bs-gl{animation:glow 2s ease .1s both}
+.bs-gd{width:4px;height:4px;border-radius:50%;background:#c9a24a;opacity:0}
+.bs-gd{animation:float 3.6s ease-in-out infinite}
+.bs-go.bs-a3 .bs-mk{animation:soft 1.5s cubic-bezier(.2,.7,.2,1) .3s both}
+.bs-go.bs-a3 .bs-tx{animation:rise 1.1s ease 1.2s both}
+.gl2{left:50%;bottom:58px;height:1px;width:0;margin-left:-60px;background:linear-gradient(90deg,transparent,#c9a24a,transparent)}
+.bs-go .gl2{animation:lw 1.4s ease 1.6s both}
+/* 4 PDFMiniFly */
+.bs-a4{background:linear-gradient(180deg,#fff,#fff0ec)}
+.bs-rgl{width:270px;height:270px;margin:-135px 0 0 -135px;border-radius:50%;background:radial-gradient(circle,rgba(255,70,40,.24),transparent 68%);opacity:0}
+.bs-go .bs-rgl{animation:glow 1.2s ease .3s both}
+.bs-go.bs-a4 .bs-mk{animation:drop .95s cubic-bezier(.3,.8,.3,1) .2s both}
+.bs-go.bs-a4 .bs-tx{animation:wipe .9s cubic-bezier(.6,0,.2,1) .95s both}
+/* 5 BillCraft */
+.bs-a5{background:radial-gradient(circle at 50% 40%,#fff,#ece4ff 88%)}
+.bs-rp{width:120px;height:120px;margin:-60px 0 0 -60px;border-radius:50%;border:2px solid #17c3a0;opacity:0}
+.bs-go .bs-rp{animation:rip 1.8s ease-out 1s both}
+.bs-go.bs-a5 .bs-mk{animation:fall .9s cubic-bezier(.3,.7,.3,1) .2s both}
+.bs-steps{left:60px;right:60px;bottom:52px;display:flex;gap:6px}
+.bs-steps i{flex:1;height:4px;border-radius:4px;background:rgba(91,33,182,.14);overflow:hidden}
+.bs-go .bs-steps i:after{animation:fill .6s ease both;animation-delay:var(--d)}
+/* 6 Cineflow */
+.bs-a6{background:linear-gradient(160deg,#f5f7ff,#ede8ff)}
+.bs-a6 .bs-ctr{perspective:700px}
+.bs-fs{left:0;right:0;height:26px;background:#141a4a}
+.bs-fs:before{content:"";position:absolute;left:0;right:0;top:9px;height:8px;background:repeating-linear-gradient(90deg,#eef0ff 0 10px,transparent 10px 20px);animation:scroll 1.2s linear infinite}
+.bs-f1{top:66px;transform-origin:left}
+.bs-f2{bottom:66px;transform-origin:right}
+.bs-f2:before{animation-direction:reverse}
+.bs-go .bs-fs{animation:sx 1s cubic-bezier(.2,.8,.2,1) both}
+.bs-go.bs-a6 .bs-mk{animation:flip 1.1s cubic-bezier(.2,.8,.2,1) .35s both}
+/* 7 Studyria */
+.bs-a7{background:repeating-linear-gradient(180deg,transparent 0 31px,rgba(20,20,30,.055) 31px 32px),#fbfaf7}
+.bs-ml{left:34px;top:0;bottom:0;width:1px;background:rgba(190,25,25,.3);transform-origin:top}
+.bs-go .bs-ml{animation:gy .9s ease .1s both}
+.bs-go.bs-a7 .bs-mk{animation:settle 1s cubic-bezier(.2,.8,.2,1) .25s both}
+.bs-go.bs-a7 .bs-tx{animation:wipe 1s cubic-bezier(.6,0,.2,1) .95s both}
+.bs-sk{display:none}
+@keyframes rise{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
+@keyframes zoom{from{opacity:0;transform:scale(.72);filter:blur(10px)}to{opacity:1;transform:none;filter:blur(0)}}
+@keyframes ring{from{opacity:.9;transform:scale(.45)}to{opacity:0;transform:scale(1.6)}}
+@keyframes wipe{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0)}}
+@keyframes fill{to{width:100%}}
+@keyframes pulse{50%{opacity:1;transform:scale(1.35)}}
+@keyframes streak{0%{transform:translateX(-130px);opacity:0}25%{opacity:.9}100%{transform:translateX(310px);opacity:0}}
+@keyframes slide{from{opacity:0;transform:translateX(-70px) skewX(-8deg);filter:blur(6px)}to{opacity:1;transform:none;filter:blur(0)}}
+@keyframes glow{from{opacity:0;transform:scale(.6)}to{opacity:1;transform:none}}
+@keyframes float{0%{opacity:0;transform:translateY(24px)}40%{opacity:.9}100%{opacity:0;transform:translateY(-56px)}}
+@keyframes soft{from{opacity:0;transform:scale(.92)}to{opacity:1;transform:none}}
+@keyframes lw{to{width:120px}}
+@keyframes drop{0%{opacity:0;transform:translateY(130px) rotate(-8deg) scale(.8)}60%{opacity:1;transform:translateY(-10px) rotate(2deg) scale(1.03)}100%{opacity:1;transform:none}}
+@keyframes rip{from{opacity:.8;transform:scale(.8)}to{opacity:0;transform:scale(3)}}
+@keyframes fall{0%{opacity:0;transform:translateY(-100px) scale(.9)}55%{opacity:1;transform:translateY(8px)}78%{transform:translateY(-3px)}100%{opacity:1;transform:none}}
+@keyframes scroll{to{background-position-x:20px}}
+@keyframes sx{from{transform:scaleX(0)}to{transform:scaleX(1)}}
+@keyframes flip{from{opacity:0;transform:rotateY(-80deg) scale(.8)}to{opacity:1;transform:none}}
+@keyframes gy{from{transform:scaleY(0)}to{transform:scaleY(1)}}
+@keyframes settle{from{opacity:0;transform:translateY(-36px) scale(.94)}to{opacity:1;transform:none}}
+@media (prefers-reduced-motion: reduce){.bs-go .bs-fs,.bs-go .bs-mk,.bs-go .bs-tx,.bs-fs:before,.bs-go .bs-sk,.bs-go .bs-rp,.bs-go .bs-gl,.bs-go .bs-gd,.bs-go .bs-rgl,.bs-go .bs-ml,.bs-go .bs-rg,.bs-go .bs-dots i,.bs-go .bs-steps i,.bs-go .bs-pb:after{animation-duration:.01ms!important;animation-iteration-count:1!important}}
+`;
+
+/**
+ * Brand splash - generated from the owner-approved artwork sheet so the app and
+ * the reference render identically: same ground, same marks, same sequence.
+ * Shows once per tab; the overlay fades before it unmounts.
+ */
+export const BrandSplash: React.FC = ({ autoDismissMs = 2800, onComplete }) => {
+ const [visible, setVisible] = useState(false);
+ const [fading, setFading] = useState(false);
+
+ useEffect(() => {
+ let seen = true;
+ try {
+ seen = !!sessionStorage.getItem('brand_splash_niramay_shown');
+ } catch {
+ seen = true;
+ }
+ if (seen) return;
+ const t = setTimeout(() => setVisible(true), 0);
+ return () => clearTimeout(t);
+ }, []);
+
+ useEffect(() => {
+ if (!visible) return;
+ const a = setTimeout(() => setFading(true), autoDismissMs);
+ const b = setTimeout(() => {
+ setVisible(false);
+ try {
+ sessionStorage.setItem('brand_splash_niramay_shown', 'true');
+ } catch {
+ /* storage unavailable - splash reappears next load */
+ }
+ onComplete?.();
+ }, autoDismissMs + 420);
+ return () => {
+ clearTimeout(a);
+ clearTimeout(b);
+ };
+ }, [visible, autoDismissMs, onComplete]);
+
+ if (!visible) return null;
+
+ return (
+ <>
+
+
+
+
+ {/* eslint-disable-next-line @next/next/no-img-element */}
+

+ {/* eslint-disable-next-line @next/next/no-img-element */}
+

+
+
+
+ >
+ );
+};
diff --git a/package.json b/package.json
index d1b35d9..9c1ad9f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "niramay",
- "version": "2.1.1",
+ "version": "2.2.0",
"private": true,
"scripts": {
"dev": "next dev",
diff --git a/public/brand/splash/mark.jpg b/public/brand/splash/mark.jpg
new file mode 100644
index 0000000..d5c0458
Binary files /dev/null and b/public/brand/splash/mark.jpg differ
diff --git a/public/brand/splash/wordmark.jpg b/public/brand/splash/wordmark.jpg
new file mode 100644
index 0000000..72cd246
Binary files /dev/null and b/public/brand/splash/wordmark.jpg differ