Commit e53700c2 authored by Mahmoud Aglan's avatar Mahmoud Aglan

Polish website builder UI/UX — theme-aware CSS, section animations, visual controls

- CSS: all hardcoded colors replaced with CSS variables
- CSS: data-animation system (fade-up/down/left/right, zoom, flip, bounce)
- CSS: card style overrides via data-card, navbar variants via classes
- CSS: reduced-motion support, RTL logical properties throughout
- JS: IntersectionObserver for data-animation sections
- JS: gallery lightbox, FAQ accordion, floating navbar scroll
- Theme editor: mini-mockup template previews, better color preview strip
- Theme editor: visual density indicators, shape/card mini previews
- Theme editor: spinner on save, auto-dismiss success toast
- Section manager: RTL-safe toggle switch, icon on visual controls header
- Section manager: better save button with icon + spinner
- Section manager: auto-dismiss success toast with Alpine transition
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 7f1a8034
@import 'tailwindcss'; @import 'tailwindcss';
/* ═══════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════
CLEAN & PROFESSIONAL — Public Academy Website Template El Captain — Public Academy Website
Light, minimal, structured. Ready out of the box. All colors via CSS variables — supports all 8 templates
═══════════════════════════════════════════════════════════════ */ ═══════════════════════════════════════════════════════════════ */
@theme { @theme {
...@@ -10,10 +10,9 @@ ...@@ -10,10 +10,9 @@
--color-website-secondary: var(--site-secondary, #2d5a87); --color-website-secondary: var(--site-secondary, #2d5a87);
--color-website-accent: var(--site-accent, #2563eb); --color-website-accent: var(--site-accent, #2563eb);
--color-website-text: var(--site-text, #1f2937); --color-website-text: var(--site-text, #1f2937);
--color-website-muted: #6b7280; --color-website-muted: var(--site-muted, #6b7280);
--color-website-surface: #ffffff; --color-website-surface: var(--site-surface, #f9fafb);
--color-website-surface-raised: #f9fafb; --color-website-border: var(--site-border, #e5e7eb);
--color-website-border: #e5e7eb;
} }
@layer base { @layer base {
...@@ -21,6 +20,9 @@ ...@@ -21,6 +20,9 @@
background: var(--site-bg, #ffffff); background: var(--site-bg, #ffffff);
color: var(--site-text, #1f2937); color: var(--site-text, #1f2937);
font-family: var(--site-body-font, 'Cairo'), 'Noto Sans Arabic', system-ui, sans-serif; font-family: var(--site-body-font, 'Cairo'), 'Noto Sans Arabic', system-ui, sans-serif;
font-size: var(--site-text-base, 16px);
line-height: var(--site-line-height, 1.6);
letter-spacing: var(--site-letter-spacing, 0);
direction: rtl; direction: rtl;
min-height: 100vh; min-height: 100vh;
overflow-x: hidden; overflow-x: hidden;
...@@ -41,16 +43,29 @@ ...@@ -41,16 +43,29 @@
inset-inline: 0; inset-inline: 0;
z-index: 100; z-index: 100;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
background: var(--site-primary, #1e3a5f); background: var(--site-primary);
}
.site-nav--transparent {
background: transparent;
}
.site-nav--floating {
top: 1rem;
inset-inline: 1rem;
border-radius: var(--site-radius-lg, 20px);
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(12px);
} }
.site-nav--scrolled { .site-nav--scrolled {
background: var(--site-primary, #1e3a5f); background: var(--site-primary);
box-shadow: 0 2px 20px rgba(0,0,0,0.1); box-shadow: 0 2px 20px rgba(0, 0, 0, 0.15);
} }
.site-nav--solid { .site-nav--floating.site-nav--scrolled {
background: var(--site-primary, #1e3a5f); background: var(--site-primary);
backdrop-filter: none;
} }
/* ─── Hero ─── */ /* ─── Hero ─── */
...@@ -61,7 +76,7 @@ ...@@ -61,7 +76,7 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
overflow: hidden; overflow: hidden;
background: linear-gradient(135deg, var(--site-primary, #1e3a5f) 0%, var(--site-secondary, #2d5a87) 100%); background: linear-gradient(135deg, var(--site-primary) 0%, var(--site-secondary) 100%);
} }
.hero-section::after { .hero-section::after {
...@@ -71,21 +86,17 @@ ...@@ -71,21 +86,17 @@
left: 0; left: 0;
right: 0; right: 0;
height: 80px; height: 80px;
background: linear-gradient(to top, var(--site-bg, #ffffff), transparent); background: linear-gradient(to top, var(--site-bg), transparent);
z-index: 2; z-index: 2;
} }
.hero-clip {
clip-path: none;
}
.hero-overlay { .hero-overlay {
position: absolute; position: absolute;
inset: 0; inset: 0;
background: linear-gradient( background: linear-gradient(
135deg, 135deg,
rgba(0,0,0, var(--overlay-opacity, 0.4)) 0%, rgba(0, 0, 0, var(--overlay-opacity, 0.4)) 0%,
rgba(0,0,0, calc(var(--overlay-opacity, 0.4) + 0.1)) 100% rgba(0, 0, 0, calc(var(--overlay-opacity, 0.4) + 0.1)) 100%
); );
z-index: 1; z-index: 1;
} }
...@@ -98,18 +109,19 @@ ...@@ -98,18 +109,19 @@
} }
.hero-title { .hero-title {
font-size: clamp(2.5rem, 6vw, 4.5rem); font-size: clamp(2.5rem, 6vw, var(--site-h1, 4.5rem));
font-weight: 800; font-weight: var(--site-heading-weight, 800);
line-height: 1.15; line-height: 1.15;
color: #ffffff; color: #ffffff;
letter-spacing: -0.01em; letter-spacing: -0.01em;
font-family: var(--site-heading-font, 'Cairo'), sans-serif;
} }
.hero-accent-line { .hero-accent-line {
width: 0; width: 0;
height: 4px; height: 4px;
margin: 1.5rem auto; margin: 1.5rem auto;
background: var(--site-accent, #2563eb); background: var(--site-accent);
border-radius: 2px; border-radius: 2px;
animation: accent-expand 1s 0.5s cubic-bezier(0.4, 0, 0.2, 1) forwards; animation: accent-expand 1s 0.5s cubic-bezier(0.4, 0, 0.2, 1) forwards;
} }
...@@ -121,28 +133,25 @@ ...@@ -121,28 +133,25 @@
/* ─── Section Shared ─── */ /* ─── Section Shared ─── */
.site-section { .site-section {
position: relative; position: relative;
padding: 5rem 0; padding: var(--section-py, 5rem) 0;
overflow: hidden; overflow: hidden;
background: var(--site-bg, #ffffff); background: var(--site-bg);
} }
.site-section--alt { .site-section--alt {
background: #f8fafc; background: var(--site-surface);
} }
.site-section--dark { .site-section--dark {
background: var(--site-primary, #1e3a5f); background: var(--site-primary);
color: #ffffff; color: #ffffff;
} }
.site-section--pattern {
background-image: none;
}
.section-title { .section-title {
font-size: clamp(1.75rem, 3.5vw, 2.5rem); font-size: clamp(1.75rem, 3.5vw, var(--site-h2, 2.5rem));
font-weight: 700; font-weight: var(--site-heading-weight, 700);
color: var(--site-text, #1f2937); font-family: var(--site-heading-font, 'Cairo'), sans-serif;
color: var(--site-text);
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
position: relative; position: relative;
display: inline-block; display: inline-block;
...@@ -159,25 +168,31 @@ ...@@ -159,25 +168,31 @@
inset-inline-start: 0; inset-inline-start: 0;
width: 50px; width: 50px;
height: 3px; height: 3px;
background: var(--site-accent, #2563eb); background: var(--site-accent);
border-radius: 2px; border-radius: 2px;
} }
.section-subtitle {
color: var(--site-muted);
font-size: 1.1rem;
margin-top: 1rem;
}
/* ─── Cards ─── */ /* ─── Cards ─── */
.site-card { .site-card {
position: relative; position: relative;
border-radius: 1rem; border-radius: var(--site-radius-lg, 1rem);
overflow: hidden; overflow: hidden;
background: #ffffff; background: var(--site-surface);
border: 1px solid #e5e7eb; border: 1px solid var(--site-border);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 1px 3px rgba(0,0,0,0.05); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
} }
.site-card:hover { .site-card:hover {
transform: translateY(-2px); transform: translateY(-4px);
border-color: var(--site-accent, #2563eb); border-color: var(--site-accent);
box-shadow: 0 10px 30px rgba(0,0,0,0.08); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
} }
.site-card__image { .site-card__image {
...@@ -188,39 +203,85 @@ ...@@ -188,39 +203,85 @@
} }
.site-card:hover .site-card__image { .site-card:hover .site-card__image {
transform: scale(1.03); transform: scale(1.05);
}
.site-card__body {
padding: var(--card-gap, 1.5rem);
}
.site-card__title {
font-family: var(--site-heading-font, 'Cairo'), sans-serif;
font-weight: var(--site-heading-weight, 700);
font-size: var(--site-h3, 1.25rem);
color: var(--site-text);
} }
.site-card__overlay { .site-card__overlay {
position: absolute; position: absolute;
inset: 0; inset: 0;
background: linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 60%); background: linear-gradient(to top, rgba(0, 0, 0, 0.7) 0%, transparent 60%);
opacity: 0.8; opacity: 0.8;
transition: opacity 0.3s; transition: opacity 0.3s;
} }
/* Card style overrides via data-card attribute */
[data-card="flat"] .site-card {
box-shadow: none;
border: none;
background: transparent;
}
[data-card="raised"] .site-card {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
border: none;
}
[data-card="bordered"] .site-card {
box-shadow: none;
border: 1px solid var(--site-border);
}
[data-card="glass"] .site-card {
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
border: 1px solid rgba(255, 255, 255, 0.15);
backdrop-filter: blur(12px);
background: rgba(255, 255, 255, 0.05);
}
/* ─── Stats ─── */ /* ─── Stats ─── */
.stats-band { .stats-band {
position: relative; position: relative;
background: var(--site-primary, #1e3a5f); background: var(--site-primary);
overflow: hidden; overflow: hidden;
} }
.stat-number { .stat-number {
font-size: clamp(2.5rem, 5vw, 3.5rem); font-size: clamp(2.5rem, 5vw, 3.5rem);
font-weight: 800; font-weight: 800;
color: var(--site-accent, #2563eb); font-family: var(--site-heading-font, 'Cairo'), sans-serif;
color: var(--site-accent);
line-height: 1; line-height: 1;
} }
.stat-label {
color: rgba(255, 255, 255, 0.8);
margin-top: 0.5rem;
}
/* ─── Testimonials ─── */ /* ─── Testimonials ─── */
.testimonial-card { .testimonial-card {
background: #ffffff; background: var(--site-surface);
border-radius: 1rem; border-radius: var(--site-radius-lg, 1rem);
padding: 2rem; padding: 2rem;
border: 1px solid #e5e7eb; border: 1px solid var(--site-border);
position: relative; position: relative;
box-shadow: 0 1px 3px rgba(0,0,0,0.05); transition: all 0.3s ease;
}
.testimonial-card:hover {
border-color: var(--site-accent);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
} }
.testimonial-card::before { .testimonial-card::before {
...@@ -230,79 +291,89 @@ ...@@ -230,79 +291,89 @@
inset-inline-start: 1.25rem; inset-inline-start: 1.25rem;
font-size: 4rem; font-size: 4rem;
line-height: 1; line-height: 1;
color: var(--site-accent, #2563eb); color: var(--site-accent);
opacity: 0.15; opacity: 0.15;
font-family: serif; font-family: serif;
} }
/* ─── FAQ ─── */ /* ─── FAQ ─── */
.faq-item { .faq-item {
border: 1px solid #e5e7eb; border: 1px solid var(--site-border);
border-radius: 0.75rem; border-radius: var(--site-radius, 0.75rem);
overflow: hidden; overflow: hidden;
transition: border-color 0.3s; transition: border-color 0.3s, box-shadow 0.3s;
background: #ffffff; background: var(--site-surface);
} }
.faq-item:hover, .faq-item:hover,
.faq-item[data-open="true"] { .faq-item[data-open="true"] {
border-color: var(--site-accent, #2563eb); border-color: var(--site-accent);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
} }
/* ─── CTA Section ─── */ /* ─── CTA Section ─── */
.cta-section { .cta-section {
position: relative; position: relative;
background: linear-gradient(135deg, var(--site-primary, #1e3a5f), var(--site-secondary, #2d5a87)); background: linear-gradient(135deg, var(--site-primary), var(--site-secondary));
overflow: hidden; overflow: hidden;
} }
.cta-section::before {
content: none;
}
/* ─── Buttons ─── */ /* ─── Buttons ─── */
.site-btn { .site-btn {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 0.5rem; gap: 0.5rem;
padding: 0.875rem 2rem; padding: 0.875rem 2rem;
border-radius: 0.75rem; border-radius: var(--site-radius, 0.75rem);
font-weight: 600; font-weight: 600;
font-size: 1rem; font-size: 1rem;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
position: relative;
overflow: hidden;
} }
.site-btn--primary { .site-btn--primary {
background: var(--site-accent, #2563eb); background: var(--site-accent);
color: white; color: white;
box-shadow: 0 2px 8px rgba(37, 99, 235, 0.25); box-shadow: 0 4px 14px color-mix(in srgb, var(--site-accent) 30%, transparent);
} }
.site-btn--primary:hover { .site-btn--primary:hover {
transform: translateY(-1px); transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(37, 99, 235, 0.35); box-shadow: 0 8px 25px color-mix(in srgb, var(--site-accent) 40%, transparent);
filter: brightness(1.1);
} }
.site-btn--outline { .site-btn--outline {
background: transparent; background: transparent;
color: white; color: white;
border: 2px solid rgba(255,255,255,0.4); border: 2px solid rgba(255, 255, 255, 0.4);
} }
.site-btn--outline:hover { .site-btn--outline:hover {
border-color: white; border-color: white;
background: rgba(255,255,255,0.1); background: rgba(255, 255, 255, 0.1);
transform: translateY(-2px);
} }
/* ─── Footer ─── */ /* ─── Footer ─── */
.site-footer { .site-footer {
background: var(--site-primary, #1e3a5f); background: var(--site-primary);
color: #ffffff; color: #ffffff;
border-top: none; border-top: none;
} }
.site-footer a {
color: rgba(255, 255, 255, 0.7);
transition: color 0.3s;
}
.site-footer a:hover {
color: var(--site-accent);
}
/* ─── WhatsApp Float ─── */ /* ─── WhatsApp Float ─── */
.whatsapp-float { .whatsapp-float {
position: fixed; position: fixed;
...@@ -316,21 +387,60 @@ ...@@ -316,21 +387,60 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 4px 12px rgba(37, 211, 102, 0.3); box-shadow: 0 4px 14px rgba(37, 211, 102, 0.4);
transition: transform 0.3s; transition: transform 0.3s, box-shadow 0.3s;
animation: whatsapp-pulse 2s infinite; animation: whatsapp-pulse 2s infinite;
} }
.whatsapp-float:hover { .whatsapp-float:hover {
transform: scale(1.1); transform: scale(1.12);
box-shadow: 0 6px 20px rgba(37, 211, 102, 0.5);
} }
@keyframes whatsapp-pulse { @keyframes whatsapp-pulse {
0%, 100% { box-shadow: 0 4px 12px rgba(37, 211, 102, 0.3); } 0%, 100% { box-shadow: 0 4px 14px rgba(37, 211, 102, 0.4); }
50% { box-shadow: 0 4px 20px rgba(37, 211, 102, 0.5), 0 0 0 6px rgba(37, 211, 102, 0.08); } 50% { box-shadow: 0 4px 24px rgba(37, 211, 102, 0.6), 0 0 0 8px rgba(37, 211, 102, 0.08); }
}
/* ─── Section Animations (data-animation system) ─── */
[data-animation] {
opacity: 0;
transition-property: opacity, transform;
transition-duration: var(--anim-duration, 0.8s);
transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
} }
/* ─── Animations ─── */ [data-animation="fade-up"] { transform: translateY(40px); }
[data-animation="fade-down"] { transform: translateY(-40px); }
[data-animation="fade-left"] { transform: translateX(40px); }
[data-animation="fade-right"] { transform: translateX(-40px); }
[data-animation="zoom-in"] { transform: scale(0.9); }
[data-animation="flip"] { transform: perspective(600px) rotateX(15deg); transform-origin: center bottom; }
[data-animation="bounce"] { transform: translateY(40px); }
[data-animation].animated {
opacity: 1;
transform: none;
}
[data-animation="bounce"].animated {
animation: bounce-in var(--anim-duration, 0.8s) cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
@keyframes bounce-in {
0% { opacity: 0; transform: translateY(40px); }
60% { opacity: 1; transform: translateY(-8px); }
100% { opacity: 1; transform: translateY(0); }
}
[data-animations="false"] [data-animation] {
opacity: 1;
transform: none;
transition: none;
animation: none;
}
/* Legacy .reveal support */
.reveal { .reveal {
opacity: 0; opacity: 0;
transform: translateY(20px); transform: translateY(20px);
...@@ -349,9 +459,9 @@ ...@@ -349,9 +459,9 @@
/* ─── Map Container ─── */ /* ─── Map Container ─── */
.map-container { .map-container {
border-radius: 1rem; border-radius: var(--site-radius-lg, 1rem);
overflow: hidden; overflow: hidden;
border: 1px solid #e5e7eb; border: 1px solid var(--site-border);
height: 350px; height: 350px;
} }
...@@ -359,27 +469,33 @@ ...@@ -359,27 +469,33 @@
.gallery-grid { .gallery-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1rem; gap: var(--card-gap, 1rem);
} }
.gallery-item { .gallery-item {
position: relative; position: relative;
border-radius: 0.75rem; border-radius: var(--site-radius, 0.75rem);
overflow: hidden; overflow: hidden;
aspect-ratio: 3/2; aspect-ratio: 3/2;
cursor: pointer; cursor: pointer;
border: 1px solid #e5e7eb; border: 1px solid var(--site-border);
transition: all 0.3s ease;
}
.gallery-item:hover {
border-color: var(--site-accent);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
} }
.gallery-item img { .gallery-item img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1); transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
} }
.gallery-item:hover img { .gallery-item:hover img {
transform: scale(1.05); transform: scale(1.08);
} }
/* ─── Partners Logo Bar ─── */ /* ─── Partners Logo Bar ─── */
...@@ -389,6 +505,10 @@ ...@@ -389,6 +505,10 @@
animation: scroll-logos 30s linear infinite; animation: scroll-logos 30s linear infinite;
} }
.partners-track:hover {
animation-play-state: paused;
}
@keyframes scroll-logos { @keyframes scroll-logos {
0% { transform: translateX(0); } 0% { transform: translateX(0); }
100% { transform: translateX(-50%); } 100% { transform: translateX(-50%); }
...@@ -398,47 +518,52 @@ ...@@ -398,47 +518,52 @@
.site-input { .site-input {
width: 100%; width: 100%;
padding: 0.875rem 1rem; padding: 0.875rem 1rem;
background: #ffffff; background: var(--site-surface);
border: 1px solid #d1d5db; border: 1px solid var(--site-border);
border-radius: 0.75rem; border-radius: var(--site-radius, 0.75rem);
color: #1f2937; color: var(--site-text);
font-size: 1rem; font-size: 1rem;
transition: border-color 0.3s; transition: border-color 0.3s, box-shadow 0.3s;
} }
.site-input:focus { .site-input:focus {
outline: none; outline: none;
border-color: var(--site-accent, #2563eb); border-color: var(--site-accent);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); box-shadow: 0 0 0 3px color-mix(in srgb, var(--site-accent) 15%, transparent);
} }
.site-input::placeholder { .site-input::placeholder {
color: #9ca3af; color: var(--site-muted);
} }
.site-section--dark .site-input { .site-section--dark .site-input {
background: rgba(255,255,255,0.1); background: rgba(255, 255, 255, 0.08);
border-color: rgba(255,255,255,0.2); border-color: rgba(255, 255, 255, 0.15);
color: #ffffff; color: #ffffff;
} }
.site-section--dark .site-input::placeholder { .site-section--dark .site-input::placeholder {
color: rgba(255,255,255,0.5); color: rgba(255, 255, 255, 0.4);
} }
/* ─── Empty/Skeleton States ─── */ .site-section--dark .site-input:focus {
border-color: var(--site-accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--site-accent) 20%, transparent);
}
/* ─── Skeleton / Empty States ─── */
.skeleton-card { .skeleton-card {
background: #f3f4f6; background: var(--site-surface);
border: 1px solid #e5e7eb; border: 1px solid var(--site-border);
border-radius: 1rem; border-radius: var(--site-radius-lg, 1rem);
overflow: hidden; overflow: hidden;
} }
.skeleton-block { .skeleton-block {
background: linear-gradient(90deg, #f3f4f6 25%, #e5e7eb 50%, #f3f4f6 75%); background: linear-gradient(90deg, var(--site-surface) 25%, var(--site-border) 50%, var(--site-surface) 75%);
background-size: 200% 100%; background-size: 200% 100%;
animation: skeleton-shimmer 1.5s infinite; animation: skeleton-shimmer 1.5s infinite;
border-radius: 0.5rem; border-radius: var(--site-radius, 0.5rem);
} }
@keyframes skeleton-shimmer { @keyframes skeleton-shimmer {
...@@ -449,19 +574,25 @@ ...@@ -449,19 +574,25 @@
.empty-state { .empty-state {
text-align: center; text-align: center;
padding: 3rem 1rem; padding: 3rem 1rem;
color: #9ca3af; color: var(--site-muted);
} }
.empty-state svg { .empty-state svg {
margin: 0 auto 1rem; margin: 0 auto 1rem;
opacity: 0.4; opacity: 0.4;
} }
/* ─── Image Shape via data-attribute ─── */
.site-img--square { border-radius: 0; }
.site-img--rounded { border-radius: var(--site-radius-lg, 1rem); }
.site-img--circle { border-radius: 50%; }
.site-img--blob { border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%; }
} }
/* ─── Responsive ─── */ /* ─── Responsive ─── */
@media (max-width: 768px) { @media (max-width: 768px) {
.hero-section { .hero-section {
min-height: 65vh; min-height: 70vh;
} }
.site-section { .site-section {
...@@ -471,10 +602,37 @@ ...@@ -471,10 +602,37 @@
.gallery-grid { .gallery-grid {
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
} }
.site-nav--floating {
top: 0.5rem;
inset-inline: 0.5rem;
}
[data-animation] {
--anim-duration: 0.5s;
}
} }
@media (max-width: 480px) { @media (max-width: 480px) {
.gallery-grid { .gallery-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.hero-title {
font-size: clamp(1.8rem, 8vw, 2.5rem);
}
}
/* ─── Reduced Motion ─── */
@media (prefers-reduced-motion: reduce) {
[data-animation],
.reveal,
.hero-accent-line,
.site-card,
.whatsapp-float {
animation: none !important;
transition: none !important;
opacity: 1 !important;
transform: none !important;
}
} }
/** /**
* Bold & Athletic — Public Website Interactivity * El Captain — Public Website Interactivity
* Scroll animations, counter animations, navbar transitions * Section animations, counters, navbar transitions, gallery lightbox
*/ */
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
initNavbar(); initNavbar();
initSectionAnimations();
initRevealAnimations(); initRevealAnimations();
initCounterAnimations(); initCounterAnimations();
initSmoothScroll(); initSmoothScroll();
initGalleryLightbox();
initFAQAccordion();
}); });
// ─── Navbar scroll transition ───
function initNavbar() { function initNavbar() {
const nav = document.querySelector('.site-nav'); const nav = document.querySelector('.site-nav');
if (!nav) return; if (!nav) return;
const onScroll = () => { const onScroll = () => {
if (window.scrollY > 50) { if (window.scrollY > 60) {
nav.classList.add('site-nav--scrolled'); nav.classList.add('site-nav--scrolled');
} else { } else {
nav.classList.remove('site-nav--scrolled'); nav.classList.remove('site-nav--scrolled');
...@@ -27,7 +29,31 @@ function initNavbar() { ...@@ -27,7 +29,31 @@ function initNavbar() {
onScroll(); onScroll();
} }
// ─── Reveal on scroll (Intersection Observer) ─── function initSectionAnimations() {
const body = document.body;
if (body.dataset.animations === 'false') return;
const sections = document.querySelectorAll('[data-animation]');
if (!sections.length) return;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('animated');
observer.unobserve(entry.target);
}
});
},
{ threshold: 0.1, rootMargin: '0px 0px -60px 0px' }
);
sections.forEach((el, i) => {
el.style.transitionDelay = `${i * 0.08}s`;
observer.observe(el);
});
}
function initRevealAnimations() { function initRevealAnimations() {
const elements = document.querySelectorAll('.reveal'); const elements = document.querySelectorAll('.reveal');
if (!elements.length) return; if (!elements.length) return;
...@@ -47,7 +73,6 @@ function initRevealAnimations() { ...@@ -47,7 +73,6 @@ function initRevealAnimations() {
elements.forEach((el) => observer.observe(el)); elements.forEach((el) => observer.observe(el));
} }
// ─── Counter animation (count up on scroll) ───
function initCounterAnimations() { function initCounterAnimations() {
const counters = document.querySelectorAll('[data-counter]'); const counters = document.querySelectorAll('[data-counter]');
if (!counters.length) return; if (!counters.length) return;
...@@ -76,7 +101,7 @@ function animateCounter(el) { ...@@ -76,7 +101,7 @@ function animateCounter(el) {
function update(now) { function update(now) {
const elapsed = now - start; const elapsed = now - start;
const progress = Math.min(elapsed / duration, 1); const progress = Math.min(elapsed / duration, 1);
const eased = 1 - Math.pow(1 - progress, 4); // ease-out quart const eased = 1 - Math.pow(1 - progress, 4);
const current = Math.floor(eased * target); const current = Math.floor(eased * target);
el.textContent = current.toLocaleString('ar-EG') + suffix; el.textContent = current.toLocaleString('ar-EG') + suffix;
...@@ -89,11 +114,11 @@ function animateCounter(el) { ...@@ -89,11 +114,11 @@ function animateCounter(el) {
requestAnimationFrame(update); requestAnimationFrame(update);
} }
// ─── Smooth scroll for anchor links ───
function initSmoothScroll() { function initSmoothScroll() {
document.querySelectorAll('a[href^="#"]').forEach((link) => { document.querySelectorAll('a[href^="#"]').forEach((link) => {
link.addEventListener('click', (e) => { link.addEventListener('click', (e) => {
const targetId = link.getAttribute('href').slice(1); const targetId = link.getAttribute('href').slice(1);
if (!targetId) return;
const target = document.getElementById(targetId); const target = document.getElementById(targetId);
if (target) { if (target) {
e.preventDefault(); e.preventDefault();
...@@ -102,3 +127,74 @@ function initSmoothScroll() { ...@@ -102,3 +127,74 @@ function initSmoothScroll() {
}); });
}); });
} }
function initGalleryLightbox() {
const items = document.querySelectorAll('.gallery-item[data-src]');
if (!items.length) return;
let lightbox = null;
items.forEach((item) => {
item.addEventListener('click', () => {
const src = item.dataset.src;
if (!src) return;
if (!lightbox) {
lightbox = document.createElement('div');
lightbox.className = 'fixed inset-0 z-[200] bg-black/90 flex items-center justify-center p-4 cursor-pointer opacity-0 transition-opacity duration-300';
lightbox.innerHTML = '<img class="max-w-full max-h-[90vh] rounded-lg object-contain transform scale-95 transition-transform duration-300" />';
lightbox.addEventListener('click', () => {
lightbox.classList.remove('opacity-100');
lightbox.querySelector('img').classList.remove('scale-100');
lightbox.querySelector('img').classList.add('scale-95');
setTimeout(() => lightbox.remove(), 300);
lightbox = null;
});
document.body.appendChild(lightbox);
}
lightbox.querySelector('img').src = src;
requestAnimationFrame(() => {
lightbox.classList.add('opacity-100');
lightbox.querySelector('img').classList.remove('scale-95');
lightbox.querySelector('img').classList.add('scale-100');
});
});
});
}
function initFAQAccordion() {
const items = document.querySelectorAll('.faq-item');
if (!items.length) return;
items.forEach((item) => {
const trigger = item.querySelector('[data-faq-trigger]');
const content = item.querySelector('[data-faq-content]');
const icon = item.querySelector('[data-faq-icon]');
if (!trigger || !content) return;
trigger.addEventListener('click', () => {
const isOpen = item.dataset.open === 'true';
items.forEach((other) => {
if (other !== item) {
other.dataset.open = 'false';
const otherContent = other.querySelector('[data-faq-content]');
const otherIcon = other.querySelector('[data-faq-icon]');
if (otherContent) otherContent.style.maxHeight = '0';
if (otherIcon) otherIcon.style.transform = '';
}
});
if (isOpen) {
item.dataset.open = 'false';
content.style.maxHeight = '0';
if (icon) icon.style.transform = '';
} else {
item.dataset.open = 'true';
content.style.maxHeight = content.scrollHeight + 'px';
if (icon) icon.style.transform = 'rotate(180deg)';
}
});
});
}
...@@ -26,7 +26,15 @@ ...@@ -26,7 +26,15 @@
</div> </div>
@if(session('success')) @if(session('success'))
<div class="mb-4 p-3 rounded-lg bg-green-50 border border-green-200 text-green-700 text-sm"> <div x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 3000)"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 -translate-y-2"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 -translate-y-2"
class="mb-4 p-3 rounded-lg bg-green-50 border border-green-200 text-green-700 text-sm flex items-center gap-2">
<svg class="w-4 h-4 shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg>
{{ session('success') }} {{ session('success') }}
</div> </div>
@endif @endif
...@@ -55,8 +63,8 @@ ...@@ -55,8 +63,8 @@
{{-- Toggle --}} {{-- Toggle --}}
<button wire:click.stop="toggleSection({{ $section['id'] }})" <button wire:click.stop="toggleSection({{ $section['id'] }})"
class="shrink-0 w-9 h-5 rounded-full transition-colors {{ $section['is_enabled'] ? 'bg-green-500' : 'bg-gray-300 dark:bg-gray-600' }}"> class="relative shrink-0 w-9 h-5 rounded-full transition-colors {{ $section['is_enabled'] ? 'bg-green-500' : 'bg-gray-300 dark:bg-gray-600' }}">
<span class="block w-4 h-4 rounded-full bg-white shadow transform transition-transform {{ $section['is_enabled'] ? '-translate-x-4' : '-translate-x-0.5' }}"></span> <span class="absolute top-0.5 block w-4 h-4 rounded-full bg-white shadow transition-all {{ $section['is_enabled'] ? 'inset-inline-start-4' : 'inset-inline-start-0.5' }}"></span>
</button> </button>
</div> </div>
@endforeach @endforeach
...@@ -170,7 +178,10 @@ class="shrink-0 w-9 h-5 rounded-full transition-colors {{ $section['is_enabled'] ...@@ -170,7 +178,10 @@ class="shrink-0 w-9 h-5 rounded-full transition-colors {{ $section['is_enabled']
{{-- Visual Controls --}} {{-- Visual Controls --}}
<div class="border-t border-gray-200 dark:border-gray-700 pt-5 mt-5"> <div class="border-t border-gray-200 dark:border-gray-700 pt-5 mt-5">
<h4 class="text-sm font-semibold text-gray-700 dark:text-gray-300 mb-4">الإعدادات المرئية</h4> <h4 class="flex items-center gap-2 text-sm font-semibold text-gray-700 dark:text-gray-300 mb-4">
<svg class="w-4 h-4 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"/></svg>
الإعدادات المرئية
</h4>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4"> <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
{{-- Background Type --}} {{-- Background Type --}}
...@@ -265,13 +276,19 @@ class="shrink-0 w-9 h-5 rounded-full transition-colors {{ $section['is_enabled'] ...@@ -265,13 +276,19 @@ class="shrink-0 w-9 h-5 rounded-full transition-colors {{ $section['is_enabled']
</div> </div>
{{-- Actions --}} {{-- Actions --}}
<div class="flex items-center gap-3 pt-4 border-t border-gray-200 dark:border-gray-700"> <div class="flex items-center gap-3 pt-5 mt-5 border-t border-gray-200 dark:border-gray-700">
<button type="submit" class="px-6 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 font-medium text-sm transition-colors" <button type="submit" class="inline-flex items-center gap-2 px-6 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 font-medium text-sm transition-all shadow-sm hover:shadow-md"
wire:loading.attr="disabled" wire:target="saveSection"> wire:loading.attr="disabled" wire:loading.class="opacity-70 cursor-wait" wire:target="saveSection">
<span wire:loading.remove wire:target="saveSection">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
</span>
<span wire:loading wire:target="saveSection">
<svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg>
</span>
<span wire:loading.remove wire:target="saveSection">حفظ التغييرات</span> <span wire:loading.remove wire:target="saveSection">حفظ التغييرات</span>
<span wire:loading wire:target="saveSection">جارٍ الحفظ...</span> <span wire:loading wire:target="saveSection">جارٍ الحفظ...</span>
</button> </button>
<button type="button" wire:click="cancelEdit" class="px-4 py-2.5 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 text-sm transition-colors"> <button type="button" wire:click="cancelEdit" class="px-4 py-2.5 text-gray-600 dark:text-gray-400 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 text-sm transition-colors">
إلغاء إلغاء
</button> </button>
</div> </div>
......
...@@ -10,7 +10,15 @@ ...@@ -10,7 +10,15 @@
</div> </div>
@if(session('success')) @if(session('success'))
<div class="mb-4 p-3 rounded-lg bg-green-50 border border-green-200 text-green-700 text-sm"> <div x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 3000)"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 -translate-y-2"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 -translate-y-2"
class="mb-4 p-3 rounded-lg bg-green-50 border border-green-200 text-green-700 text-sm flex items-center gap-2">
<svg class="w-4 h-4 shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg>
{{ session('success') }} {{ session('success') }}
</div> </div>
@endif @endif
...@@ -24,16 +32,24 @@ ...@@ -24,16 +32,24 @@
<div class="grid grid-cols-2 md:grid-cols-4 gap-3"> <div class="grid grid-cols-2 md:grid-cols-4 gap-3">
@foreach($templatePresets as $key => $preset) @foreach($templatePresets as $key => $preset)
<button type="button" wire:click="applyTemplate('{{ $key }}')" <button type="button" wire:click="applyTemplate('{{ $key }}')"
class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template === $key ? 'border-blue-500 ring-2 ring-blue-200' : 'border-gray-200 dark:border-gray-600 hover:border-gray-300' }}"> class="relative group rounded-xl border-2 transition-all text-start overflow-hidden {{ $template === $key ? 'border-blue-500 ring-2 ring-blue-200 dark:ring-blue-800' : 'border-gray-200 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500' }}">
<div class="flex gap-1 mb-2"> {{-- Mini Mockup --}}
<span class="w-4 h-4 rounded-full" style="background-color: {{ $preset['primary'] }}"></span> <div class="h-16 p-2 relative" style="background-color: {{ $preset['bg'] }}">
<span class="w-4 h-4 rounded-full" style="background-color: {{ $preset['accent'] }}"></span> <div class="h-2 w-full rounded-sm mb-1.5" style="background-color: {{ $preset['primary'] }}"></div>
<span class="w-4 h-4 rounded-full" style="background-color: {{ $preset['bg'] }}"></span> <div class="flex gap-1">
<div class="h-6 flex-1 rounded-sm" style="background-color: {{ $preset['surface'] }}; border: 1px solid {{ $preset['border'] }}"></div>
<div class="h-6 w-4 rounded-sm" style="background-color: {{ $preset['accent'] }}"></div>
</div>
</div>
<div class="p-2.5 border-t border-gray-100 dark:border-gray-700">
<div class="flex items-center gap-1.5">
<span class="w-3 h-3 rounded-full shrink-0" style="background-color: {{ $preset['accent'] }}"></span>
<span class="text-xs font-medium text-gray-700 dark:text-gray-300 truncate">{{ $preset['label'] }}</span>
</div>
</div> </div>
<span class="text-xs font-medium text-gray-700 dark:text-gray-300">{{ $preset['label'] }}</span>
@if($template === $key) @if($template === $key)
<span class="absolute top-1.5 end-1.5 w-4 h-4 bg-blue-500 rounded-full flex items-center justify-center"> <span class="absolute top-1.5 end-1.5 w-5 h-5 bg-blue-500 rounded-full flex items-center justify-center shadow-sm">
<svg class="w-2.5 h-2.5 text-white" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/></svg> <svg class="w-3 h-3 text-white" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/></svg>
</span> </span>
@endif @endif
</button> </button>
...@@ -71,12 +87,23 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template = ...@@ -71,12 +87,23 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template =
</div> </div>
{{-- Color Preview --}} {{-- Color Preview --}}
<div class="mt-4 p-4 rounded-lg border" style="background-color: {{ $background_color }}; border-color: {{ $border_color }}"> <div class="mt-4 rounded-xl overflow-hidden border" style="border-color: {{ $border_color }}">
<div class="flex items-center gap-3 flex-wrap"> <div class="p-4" style="background-color: {{ $background_color }}">
<span class="px-3 py-1.5 rounded text-sm font-medium" style="background-color: {{ $primary_color }}; color: {{ $text_color }}">رئيسي</span> <div class="flex items-center gap-3 flex-wrap">
<span class="px-3 py-1.5 rounded text-sm font-medium" style="background-color: {{ $secondary_color }}; color: {{ $text_color }}">ثانوي</span> <span class="px-3 py-1.5 rounded-lg text-sm font-medium" style="background-color: {{ $primary_color }}; color: {{ $background_color }}">رئيسي</span>
<span class="px-3 py-1.5 rounded text-sm font-medium" style="background-color: {{ $accent_color }}; color: {{ $text_color }}">مميز</span> <span class="px-3 py-1.5 rounded-lg text-sm font-medium" style="background-color: {{ $secondary_color }}; color: {{ $background_color }}">ثانوي</span>
<span class="px-3 py-1.5 rounded text-sm font-medium" style="background-color: {{ $surface_color }}; color: {{ $muted_text_color }}; border: 1px solid {{ $border_color }}">سطح</span> <span class="px-3 py-1.5 rounded-lg text-sm font-medium" style="background-color: {{ $accent_color }}; color: #fff">مميز</span>
<span class="px-3 py-1.5 rounded-lg text-sm font-medium" style="background-color: {{ $surface_color }}; color: {{ $muted_text_color }}; border: 1px solid {{ $border_color }}">سطح</span>
</div>
<div class="mt-3 flex items-center gap-4">
<span class="text-lg font-bold" style="color: {{ $text_color }}">عنوان تجريبي</span>
<span class="text-sm" style="color: {{ $muted_text_color }}">نص خافت ثانوي</span>
</div>
</div>
<div class="h-1 flex">
<div class="flex-1" style="background-color: {{ $primary_color }}"></div>
<div class="flex-1" style="background-color: {{ $secondary_color }}"></div>
<div class="flex-1" style="background-color: {{ $accent_color }}"></div>
</div> </div>
</div> </div>
</div> </div>
...@@ -148,15 +175,20 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template = ...@@ -148,15 +175,20 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template =
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">كثافة المحتوى</label> <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">كثافة المحتوى</label>
<div class="grid grid-cols-3 gap-3"> <div class="grid grid-cols-3 gap-3">
@foreach([ @foreach([
['compact', 'مضغوط', 'عناصر متقاربة'], ['compact', 'مضغوط', 'عناصر متقاربة', 'gap-0.5'],
['comfortable', 'مريح', 'التوازن الافتراضي'], ['comfortable', 'مريح', 'التوازن الافتراضي', 'gap-1.5'],
['spacious', 'واسع', 'مساحات كبيرة'], ['spacious', 'واسع', 'مساحات كبيرة', 'gap-3'],
] as [$val, $label, $desc]) ] as [$val, $label, $desc, $gapClass])
<label class="relative cursor-pointer"> <label class="relative cursor-pointer">
<input type="radio" wire:model="density" value="{{ $val }}" class="sr-only peer"> <input type="radio" wire:model="density" value="{{ $val }}" class="sr-only peer">
<div class="p-3 rounded-lg border-2 peer-checked:border-blue-500 border-gray-200 dark:border-gray-600 text-center transition-colors"> <div class="p-4 rounded-lg border-2 peer-checked:border-blue-500 peer-checked:bg-blue-50 dark:peer-checked:bg-blue-900/20 border-gray-200 dark:border-gray-600 text-center transition-all hover:border-gray-300">
<span class="text-sm font-medium block">{{ $label }}</span> <div class="flex flex-col items-center {{ $gapClass }} mb-2">
<span class="text-xs text-gray-400">{{ $desc }}</span> <div class="w-8 h-1.5 rounded-full bg-gray-300 dark:bg-gray-500"></div>
<div class="w-6 h-1.5 rounded-full bg-gray-200 dark:bg-gray-600"></div>
<div class="w-8 h-1.5 rounded-full bg-gray-300 dark:bg-gray-500"></div>
</div>
<span class="text-sm font-medium block text-gray-700 dark:text-gray-300">{{ $label }}</span>
<span class="text-xs text-gray-400 dark:text-gray-500">{{ $desc }}</span>
</div> </div>
</label> </label>
@endforeach @endforeach
...@@ -173,15 +205,15 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template = ...@@ -173,15 +205,15 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template =
<div class="grid grid-cols-4 gap-2"> <div class="grid grid-cols-4 gap-2">
@foreach([ @foreach([
['sharp', 'حاد', 'rounded-none'], ['sharp', 'حاد', 'rounded-none'],
['subtle', 'خفيف', 'rounded'], ['subtle', 'خفيف', 'rounded-sm'],
['rounded', 'دائري', 'rounded-xl'], ['rounded', 'دائري', 'rounded-xl'],
['pill', 'كبسولة', 'rounded-full'], ['pill', 'كبسولة', 'rounded-full'],
] as [$val, $label, $class]) ] as [$val, $label, $class])
<label class="cursor-pointer"> <label class="cursor-pointer">
<input type="radio" wire:model="border_radius_preset" value="{{ $val }}" class="sr-only peer"> <input type="radio" wire:model="border_radius_preset" value="{{ $val }}" class="sr-only peer">
<div class="p-2 border-2 peer-checked:border-blue-500 border-gray-200 dark:border-gray-600 text-center transition-colors {{ $class }}"> <div class="p-3 rounded-lg border-2 peer-checked:border-blue-500 peer-checked:bg-blue-50 dark:peer-checked:bg-blue-900/20 border-gray-200 dark:border-gray-600 text-center transition-all hover:border-gray-300">
<div class="w-8 h-6 mx-auto bg-gray-300 dark:bg-gray-500 {{ $class }}"></div> <div class="w-10 h-7 mx-auto bg-gradient-to-br from-blue-200 to-blue-300 dark:from-blue-700 dark:to-blue-800 {{ $class }} mb-1.5"></div>
<span class="text-xs mt-1 block">{{ $label }}</span> <span class="text-xs font-medium block text-gray-600 dark:text-gray-400">{{ $label }}</span>
</div> </div>
</label> </label>
@endforeach @endforeach
...@@ -192,15 +224,16 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template = ...@@ -192,15 +224,16 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template =
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">نمط البطاقات</label> <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">نمط البطاقات</label>
<div class="grid grid-cols-4 gap-2"> <div class="grid grid-cols-4 gap-2">
@foreach([ @foreach([
['flat', 'مسطح'], ['flat', 'مسطح', 'bg-gray-50 dark:bg-gray-700'],
['raised', 'مرتفع'], ['raised', 'مرتفع', 'bg-white dark:bg-gray-700 shadow-md'],
['bordered', 'محدد'], ['bordered', 'محدد', 'bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-500'],
['glass', 'زجاجي'], ['glass', 'زجاجي', 'bg-white/50 dark:bg-gray-700/50 backdrop-blur-sm border border-white/30'],
] as [$val, $label]) ] as [$val, $label, $cardClass])
<label class="cursor-pointer"> <label class="cursor-pointer">
<input type="radio" wire:model="card_style" value="{{ $val }}" class="sr-only peer"> <input type="radio" wire:model="card_style" value="{{ $val }}" class="sr-only peer">
<div class="p-2 rounded-lg border-2 peer-checked:border-blue-500 border-gray-200 dark:border-gray-600 text-center transition-colors"> <div class="p-3 rounded-lg border-2 peer-checked:border-blue-500 peer-checked:bg-blue-50 dark:peer-checked:bg-blue-900/20 border-gray-200 dark:border-gray-600 text-center transition-all hover:border-gray-300">
<span class="text-xs">{{ $label }}</span> <div class="w-10 h-7 mx-auto rounded {{ $cardClass }} mb-1.5"></div>
<span class="text-xs font-medium block text-gray-600 dark:text-gray-400">{{ $label }}</span>
</div> </div>
</label> </label>
@endforeach @endforeach
...@@ -257,14 +290,17 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template = ...@@ -257,14 +290,17 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template =
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">شريط التنقل</h3> <h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">شريط التنقل</h3>
<div class="grid grid-cols-3 gap-3"> <div class="grid grid-cols-3 gap-3">
@foreach([ @foreach([
['transparent', 'شفاف'], ['transparent', 'شفاف', 'bg-transparent border border-dashed border-gray-300 dark:border-gray-500'],
['solid', 'معتم'], ['solid', 'معتم', 'bg-gray-800 dark:bg-gray-900'],
['floating', 'عائم'], ['floating', 'عائم', 'bg-gray-800/70 dark:bg-gray-900/70 rounded-lg mx-1 backdrop-blur-sm'],
] as [$val, $label]) ] as [$val, $label, $navClass])
<label class="relative cursor-pointer"> <label class="relative cursor-pointer">
<input type="radio" wire:model="navbar_style" value="{{ $val }}" class="sr-only peer"> <input type="radio" wire:model="navbar_style" value="{{ $val }}" class="sr-only peer">
<div class="p-3 rounded-lg border-2 peer-checked:border-blue-500 border-gray-200 dark:border-gray-600 text-center transition-colors"> <div class="p-4 rounded-lg border-2 peer-checked:border-blue-500 peer-checked:bg-blue-50 dark:peer-checked:bg-blue-900/20 border-gray-200 dark:border-gray-600 text-center transition-all hover:border-gray-300">
<span class="text-sm">{{ $label }}</span> <div class="w-full h-12 bg-gradient-to-b from-gray-200 to-gray-100 dark:from-gray-700 dark:to-gray-800 rounded relative mb-2 overflow-hidden">
<div class="absolute top-0 inset-x-0 h-3 {{ $navClass }}"></div>
</div>
<span class="text-xs font-medium text-gray-600 dark:text-gray-400">{{ $label }}</span>
</div> </div>
</label> </label>
@endforeach @endforeach
...@@ -333,15 +369,22 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template = ...@@ -333,15 +369,22 @@ class="relative p-3 rounded-xl border-2 transition-all text-start {{ $template =
</div> </div>
{{-- Save Button --}} {{-- Save Button --}}
<div class="flex items-center gap-3 sticky bottom-4 bg-white dark:bg-gray-800 p-4 rounded-xl border border-gray-200 dark:border-gray-700 shadow-lg"> <div class="flex items-center justify-between sticky bottom-4 bg-white dark:bg-gray-800 p-4 rounded-xl border border-gray-200 dark:border-gray-700 shadow-xl">
<button type="submit" class="px-8 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 font-medium transition-colors" <div class="flex items-center gap-3">
wire:loading.attr="disabled" wire:target="save"> <button type="submit" class="inline-flex items-center gap-2 px-8 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 font-medium transition-all shadow-sm hover:shadow-md"
<span wire:loading.remove wire:target="save">حفظ الإعدادات</span> wire:loading.attr="disabled" wire:loading.class="opacity-70 cursor-wait" wire:target="save">
<span wire:loading wire:target="save">جارٍ الحفظ...</span> <span wire:loading wire:target="save">
</button> <svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg>
<a href="{{ route('website.preview') }}" target="_blank" class="px-4 py-3 text-sm font-medium text-gray-700 dark:text-gray-300 rounded-lg border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"> </span>
معاينة الموقع ↗ <span wire:loading.remove wire:target="save">حفظ الإعدادات</span>
</a> <span wire:loading wire:target="save">جارٍ الحفظ...</span>
</button>
<a href="{{ route('website.preview') }}" target="_blank" class="inline-flex items-center gap-1.5 px-4 py-3 text-sm font-medium text-gray-700 dark:text-gray-300 rounded-lg border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>
معاينة
</a>
</div>
<span class="text-xs text-gray-400 dark:text-gray-500 hidden sm:block">التغييرات تظهر مباشرة بعد الحفظ</span>
</div> </div>
</form> </form>
</div> </div>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment