- Updated package.json to include vite-plugin-pwa and workbox-window. - Added icon SVGs for PWA: icon-512.svg and maskable-512.svg. - Created a manifest.json for PWA configuration. - Implemented PwaUpdatePrompt component to notify users of available updates. - Enhanced CookieConsent and SiteAssistant components for better layout and responsiveness. - Updated global CSS for safe-area insets and mobile-first enhancements. - Registered service worker in usePwaRegistration hook for managing updates. - Modified Vite configuration to integrate PWA features and caching strategies.
313 lines
12 KiB
CSS
313 lines
12 KiB
CSS
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
@layer base {
|
|
:root {
|
|
--color-bg: #ffffff;
|
|
--color-surface: #f8fafc;
|
|
--color-text: #0f172a;
|
|
--color-text-secondary: #64748b;
|
|
--color-border: #e2e8f0;
|
|
}
|
|
|
|
.dark {
|
|
--color-bg: #0f172a;
|
|
--color-surface: #1e293b;
|
|
--color-text: #f1f5f9;
|
|
--color-text-secondary: #94a3b8;
|
|
--color-border: #334155;
|
|
}
|
|
|
|
html {
|
|
scroll-behavior: smooth;
|
|
overscroll-behavior-y: contain;
|
|
}
|
|
|
|
body {
|
|
@apply bg-white text-slate-900 antialiased dark:bg-slate-950 dark:text-slate-100;
|
|
font-family: 'Inter', 'Tajawal', system-ui, sans-serif;
|
|
text-rendering: optimizeLegibility;
|
|
}
|
|
|
|
/* RTL Support */
|
|
[dir="rtl"] body {
|
|
font-family: 'Tajawal', 'Inter', system-ui, sans-serif;
|
|
}
|
|
|
|
[dir="rtl"] .ltr-only {
|
|
direction: ltr;
|
|
}
|
|
}
|
|
|
|
@layer components {
|
|
.btn-primary {
|
|
@apply inline-flex items-center justify-center gap-2 rounded-xl bg-primary-600 px-6 py-3 text-sm font-semibold text-white shadow-sm transition-all hover:bg-primary-700 active:scale-[0.98] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 disabled:opacity-50 disabled:cursor-not-allowed dark:bg-primary-500 dark:hover:bg-primary-600;
|
|
}
|
|
|
|
.btn-secondary {
|
|
@apply inline-flex items-center justify-center gap-2 rounded-xl bg-white px-6 py-3 text-sm font-semibold text-slate-900 shadow-sm ring-1 ring-inset ring-slate-300 transition-all hover:bg-slate-50 active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed dark:bg-slate-800 dark:text-slate-100 dark:ring-slate-600 dark:hover:bg-slate-700;
|
|
}
|
|
|
|
.btn-success {
|
|
@apply inline-flex items-center justify-center gap-2 rounded-xl bg-emerald-600 px-6 py-3 text-sm font-semibold text-white shadow-sm transition-all hover:bg-emerald-700 active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed dark:bg-emerald-500 dark:hover:bg-emerald-600;
|
|
}
|
|
|
|
.card {
|
|
@apply rounded-2xl bg-white p-6 shadow-sm ring-1 ring-slate-200 transition-shadow hover:shadow-md dark:bg-slate-800 dark:ring-slate-700;
|
|
}
|
|
|
|
.tool-card {
|
|
@apply card cursor-pointer hover:ring-primary-300 hover:shadow-lg transition-all duration-200 dark:hover:ring-primary-600;
|
|
}
|
|
|
|
.input-field {
|
|
@apply block w-full rounded-xl border-0 py-3 px-4 text-slate-900 shadow-sm ring-1 ring-inset ring-slate-300 placeholder:text-slate-400 focus:ring-2 focus:ring-inset focus:ring-primary-600 sm:text-sm sm:leading-6 dark:bg-slate-800 dark:text-slate-100 dark:ring-slate-600 dark:placeholder:text-slate-500;
|
|
}
|
|
|
|
.section-heading {
|
|
@apply text-2xl font-bold tracking-tight text-slate-900 sm:text-3xl dark:text-slate-100;
|
|
}
|
|
}
|
|
|
|
/* Upload zone styles */
|
|
.upload-zone {
|
|
@apply flex flex-col items-center justify-center rounded-2xl border-2 border-dashed border-slate-300 bg-slate-50 p-4 text-center transition-colors cursor-pointer sm:p-6 lg:p-8 dark:border-slate-600 dark:bg-slate-800/50;
|
|
}
|
|
|
|
.upload-zone:hover,
|
|
.upload-zone.drag-active {
|
|
@apply border-primary-400 bg-primary-50 dark:border-primary-500 dark:bg-primary-900/20;
|
|
}
|
|
|
|
.upload-zone.drag-active {
|
|
@apply ring-2 ring-primary-300 dark:ring-primary-600;
|
|
}
|
|
|
|
/* Progress bar animation */
|
|
@keyframes progress-pulse {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.6; }
|
|
}
|
|
|
|
.progress-bar-animated {
|
|
animation: progress-pulse 1.5s ease-in-out infinite;
|
|
}
|
|
|
|
/* Ad slot container */
|
|
.ad-slot {
|
|
@apply flex items-center justify-center bg-slate-50 rounded-xl border border-slate-200 min-h-[90px] overflow-hidden dark:bg-slate-800 dark:border-slate-700;
|
|
}
|
|
|
|
/* Dropdown animation */
|
|
@keyframes fadeSlideIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(-4px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.animate-in {
|
|
animation: fadeSlideIn 0.15s ease-out;
|
|
}
|
|
|
|
/* ──────────────────────────────────────────────────────────────────────────
|
|
Hero Upload Zone — premium glassmorphism card for the homepage
|
|
────────────────────────────────────────────────────────────────────────── */
|
|
.hero-upload-zone {
|
|
@apply relative flex flex-col items-center justify-center rounded-3xl border border-slate-200/80 bg-white/80 backdrop-blur-sm p-6 text-center transition-all duration-300 ease-in-out cursor-pointer sm:p-10 lg:p-14 shadow-sm dark:border-slate-700/60 dark:bg-slate-800/60 dark:backdrop-blur-sm;
|
|
background-image: radial-gradient(ellipse at top, rgba(219, 234, 254, 0.3) 0%, transparent 70%);
|
|
}
|
|
|
|
.dark .hero-upload-zone {
|
|
background-image: radial-gradient(ellipse at top, rgba(30, 58, 138, 0.15) 0%, transparent 70%);
|
|
}
|
|
|
|
.hero-upload-zone::before {
|
|
content: '';
|
|
@apply absolute inset-0 rounded-3xl transition-opacity duration-300 opacity-0;
|
|
background: linear-gradient(135deg, rgba(59, 130, 246, 0.06) 0%, rgba(168, 85, 247, 0.04) 100%);
|
|
}
|
|
|
|
.hero-upload-zone:hover::before {
|
|
@apply opacity-100;
|
|
}
|
|
|
|
.hero-upload-zone:hover {
|
|
@apply border-primary-300 shadow-lg shadow-primary-100/50 -translate-y-1 dark:border-primary-600/60 dark:shadow-primary-900/30;
|
|
}
|
|
|
|
.hero-upload-zone.drag-active {
|
|
@apply border-primary-500 shadow-2xl shadow-primary-200/60 scale-[1.02] dark:border-primary-400 dark:shadow-primary-900/40;
|
|
background-image: radial-gradient(ellipse at top, rgba(191, 219, 254, 0.5) 0%, rgba(219, 234, 254, 0.2) 100%);
|
|
}
|
|
|
|
/* ──────────────────────────────────────────────────────────────────────────
|
|
Glassmorphism card utility
|
|
────────────────────────────────────────────────────────────────────────── */
|
|
.glass-card {
|
|
@apply bg-white/70 backdrop-blur-md border border-white/50 shadow-sm dark:bg-slate-800/60 dark:border-slate-700/50;
|
|
}
|
|
|
|
/* ──────────────────────────────────────────────────────────────────────────
|
|
Gradient hero mesh background
|
|
────────────────────────────────────────────────────────────────────────── */
|
|
.hero-gradient-bg {
|
|
background:
|
|
radial-gradient(ellipse 80% 60% at 50% -20%, rgba(59, 130, 246, 0.12) 0%, transparent 70%),
|
|
radial-gradient(ellipse 60% 40% at 80% 20%, rgba(168, 85, 247, 0.06) 0%, transparent 60%),
|
|
linear-gradient(180deg, #f8fafc 0%, #ffffff 100%);
|
|
}
|
|
|
|
.dark .hero-gradient-bg {
|
|
background:
|
|
radial-gradient(ellipse 80% 60% at 50% -20%, rgba(30, 58, 138, 0.3) 0%, transparent 70%),
|
|
radial-gradient(ellipse 60% 40% at 80% 20%, rgba(88, 28, 135, 0.15) 0%, transparent 60%),
|
|
linear-gradient(180deg, #0f172a 0%, #0f172a 100%);
|
|
}
|
|
|
|
.marketing-shell {
|
|
background:
|
|
radial-gradient(circle at top left, rgba(59, 130, 246, 0.1), transparent 30%),
|
|
radial-gradient(circle at top right, rgba(14, 165, 233, 0.08), transparent 26%),
|
|
linear-gradient(180deg, rgba(248, 250, 252, 0.88) 0%, rgba(255, 255, 255, 0.92) 26%, #ffffff 100%);
|
|
}
|
|
|
|
.dark .marketing-shell {
|
|
background:
|
|
radial-gradient(circle at top left, rgba(37, 99, 235, 0.18), transparent 32%),
|
|
radial-gradient(circle at top right, rgba(14, 165, 233, 0.12), transparent 28%),
|
|
linear-gradient(180deg, rgba(2, 6, 23, 0.96) 0%, rgba(15, 23, 42, 0.98) 26%, #020617 100%);
|
|
}
|
|
|
|
.marketing-panel {
|
|
@apply rounded-[2rem] border border-slate-200/80 bg-white/90 shadow-sm backdrop-blur-sm dark:border-slate-700/70 dark:bg-slate-900/70;
|
|
}
|
|
|
|
.marketing-card {
|
|
@apply rounded-[1.75rem] border border-slate-200/80 bg-white/90 p-6 shadow-sm transition-all duration-300 dark:border-slate-700/70 dark:bg-slate-900/75;
|
|
}
|
|
|
|
.marketing-card:hover {
|
|
@apply -translate-y-1 shadow-lg shadow-slate-200/70 dark:shadow-slate-950/30;
|
|
}
|
|
|
|
.metric-card {
|
|
@apply rounded-3xl border border-slate-200/80 bg-white/85 p-5 shadow-sm backdrop-blur-sm dark:border-slate-700/70 dark:bg-slate-900/70;
|
|
}
|
|
|
|
.section-kicker {
|
|
@apply text-xs font-bold uppercase tracking-[0.24em] text-primary-600 dark:text-primary-400;
|
|
}
|
|
|
|
/* ──────────────────────────────────────────────────────────────────────────
|
|
Shimmer loading effect
|
|
────────────────────────────────────────────────────────────────────────── */
|
|
@keyframes shimmer-sweep {
|
|
0% { background-position: -200% center; }
|
|
100% { background-position: 200% center; }
|
|
}
|
|
|
|
.shimmer-text {
|
|
background: linear-gradient(90deg, #1e40af 30%, #7c3aed 50%, #1e40af 70%);
|
|
background-size: 200% auto;
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
animation: shimmer-sweep 4s linear infinite;
|
|
}
|
|
|
|
/* ──────────────────────────────────────────────────────────────────────────
|
|
How it Works — connector line between steps
|
|
────────────────────────────────────────────────────────────────────────── */
|
|
.step-connector {
|
|
@apply absolute top-8 left-[calc(50%+2.5rem)] hidden h-px w-[calc(100%-5rem)] sm:block;
|
|
background: linear-gradient(90deg, rgba(59, 130, 246, 0.4) 0%, rgba(59, 130, 246, 0.1) 100%);
|
|
}
|
|
|
|
/* Modal animations */
|
|
@keyframes modalFadeIn {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes modalSlideUp {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(16px) scale(0.96);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0) scale(1);
|
|
}
|
|
}
|
|
|
|
.modal-backdrop {
|
|
animation: modalFadeIn 0.2s ease-out;
|
|
}
|
|
|
|
.modal-content {
|
|
animation: modalSlideUp 0.25s ease-out;
|
|
}
|
|
|
|
.deferred-section {
|
|
content-visibility: auto;
|
|
contain-intrinsic-size: 1px 2000px;
|
|
}
|
|
|
|
/* ──────────────────────────────────────────────────────────────────────────
|
|
Mobile-first enhancements
|
|
────────────────────────────────────────────────────────────────────────── */
|
|
|
|
/* Respect user preference for reduced motion */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
animation-duration: 0.01ms !important;
|
|
animation-iteration-count: 1 !important;
|
|
transition-duration: 0.01ms !important;
|
|
scroll-behavior: auto !important;
|
|
}
|
|
}
|
|
|
|
/* Guard hover-dependent styles for touch devices */
|
|
@media (hover: hover) {
|
|
.tool-card:hover {
|
|
--tw-translate-y: -0.25rem;
|
|
}
|
|
.hero-upload-zone:hover {
|
|
--tw-translate-y: -0.25rem;
|
|
}
|
|
.marketing-card:hover {
|
|
--tw-translate-y: -0.25rem;
|
|
}
|
|
}
|
|
|
|
/* Remove 300ms tap delay and prevent double-tap zoom on interactive elements */
|
|
a,
|
|
button,
|
|
input,
|
|
select,
|
|
textarea,
|
|
[role="button"] {
|
|
touch-action: manipulation;
|
|
}
|
|
|
|
/* Safe-area inset support for notched phones */
|
|
.sticky-header-safe {
|
|
padding-top: env(safe-area-inset-top);
|
|
}
|
|
|
|
.bottom-safe {
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
}
|