Files
SaaS-PDF/frontend/src/styles/global.css
Your Name a539ad43af feat: add PWA support with service worker and update prompt
- 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.
2026-04-06 08:12:32 +02:00

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