diff --git a/src/components/Map/RadialMenu.css b/src/components/Map/RadialMenu.css
new file mode 100644
index 0000000..76e5da1
--- /dev/null
+++ b/src/components/Map/RadialMenu.css
@@ -0,0 +1,296 @@
+/* Dual FAB Menu - Left (Categories) + Right (Time/Actions) */
+
+/* Backdrop */
+.fab-backdrop {
+ position: fixed;
+ inset: 0;
+ background: rgba(0, 0, 0, 0.15);
+ backdrop-filter: blur(2px);
+ -webkit-backdrop-filter: blur(2px);
+ z-index: 998;
+ animation: fab-fade-in 0.2s ease;
+}
+
+@keyframes fab-fade-in {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+
+/* FAB Containers */
+.fab-left,
+.fab-right {
+ position: fixed;
+ top: 120px;
+ z-index: 999;
+}
+
+.fab-left {
+ left: 24px;
+}
+
+.fab-right {
+ right: 12px;
+}
+
+/* Main FAB Button */
+.fab-btn {
+ width: 48px;
+ height: 48px;
+ border-radius: 50%;
+ border: none;
+ background: linear-gradient(135deg, var(--fab-color, #6366f1) 0%, color-mix(in srgb, var(--fab-color, #6366f1) 80%, #000) 100%);
+ color: #fff;
+ font-size: 18px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
+ -webkit-tap-highlight-color: transparent;
+ position: relative;
+ z-index: 1001;
+}
+
+.fab-btn-right {
+ --fab-color: #6366f1;
+}
+
+.fab-btn-split {
+ border: 2px solid rgba(255,255,255,0.3);
+}
+
+.fab-count {
+ font-size: 16px;
+ font-weight: 800;
+}
+
+.fab-btn:hover {
+ transform: scale(1.06);
+}
+
+.fab-btn:active {
+ transform: scale(0.94);
+}
+
+/* FAB Label */
+.fab-label {
+ position: absolute;
+ top: 54px;
+ left: 50%;
+ transform: translateX(-50%);
+ font-size: 10px;
+ font-weight: 700;
+ color: #e2e8f0;
+ text-shadow: 0 1px 4px rgba(0,0,0,0.8);
+ white-space: nowrap;
+ pointer-events: none;
+}
+
+.fab-label-time {
+ background: rgba(15, 23, 42, 0.85);
+ padding: 2px 6px;
+ border-radius: 4px;
+}
+
+/* Ring containers */
+.fab-ring {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 48px;
+ height: 48px;
+ pointer-events: none;
+}
+
+/* Individual items */
+.fab-item {
+ position: absolute;
+ top: 4px;
+ left: 4px;
+ width: 40px;
+ height: 40px;
+ border-radius: 50%;
+ border: 1.5px solid rgba(255, 255, 255, 0.15);
+ background: rgba(15, 23, 42, 0.92);
+ color: #cbd5e1;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 3px 12px rgba(0, 0, 0, 0.35);
+ opacity: 0;
+ transform: translate(0, 0) scale(0.3);
+ pointer-events: none;
+ transition:
+ transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1),
+ opacity 0.2s ease,
+ background 0.15s ease,
+ border-color 0.15s ease,
+ color 0.15s ease;
+ -webkit-tap-highlight-color: transparent;
+}
+
+.fab-item.is-visible {
+ opacity: 1;
+ transform: translate(var(--x), var(--y)) scale(1);
+ pointer-events: auto;
+ transition-delay: var(--delay);
+}
+
+.fab-item:hover {
+ background: var(--color, #3b82f6);
+ border-color: var(--color, #3b82f6);
+ color: #fff;
+}
+
+.fab-item:active {
+ transform: translate(var(--x), var(--y)) scale(0.9) !important;
+}
+
+.fab-item.is-active {
+ background: var(--color, #3b82f6);
+ border-color: var(--color, #3b82f6);
+ color: #fff;
+ box-shadow: 0 4px 16px color-mix(in srgb, var(--color, #3b82f6) 50%, transparent);
+}
+
+/* Time chips - smaller text */
+.fab-time {
+ font-size: 11px;
+ font-weight: 700;
+ --color: #f59e0b;
+}
+
+/* Subcategory items */
+.fab-sub {
+ width: 36px;
+ height: 36px;
+ font-size: 13px;
+ opacity: 1;
+ transform: translate(var(--x), var(--y)) scale(1);
+ pointer-events: auto;
+ animation: fab-pop-in 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
+ animation-delay: var(--delay);
+ --color: #64748b;
+}
+
+.fab-sub.is-active {
+ --color: #3b82f6;
+}
+
+@keyframes fab-pop-in {
+ from {
+ opacity: 0;
+ transform: translate(calc(var(--x) * 0.3), calc(var(--y) * 0.3)) scale(0.5);
+ }
+ to {
+ opacity: 1;
+ transform: translate(var(--x), var(--y)) scale(1);
+ }
+}
+
+/* Action items */
+.fab-action {
+ width: 42px;
+ height: 42px;
+ font-size: 16px;
+}
+
+/* ========== LIGHT THEME ========== */
+body[data-theme="light"] .fab-backdrop {
+ background: rgba(255, 255, 255, 0.2);
+}
+
+body[data-theme="light"] .fab-btn {
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
+}
+
+body[data-theme="light"] .fab-label {
+ color: #1e293b;
+ text-shadow: 0 1px 4px rgba(255,255,255,0.8);
+}
+
+body[data-theme="light"] .fab-label-time {
+ background: rgba(255, 255, 255, 0.9);
+ color: #1e293b;
+}
+
+body[data-theme="light"] .fab-item {
+ background: rgba(255, 255, 255, 0.95);
+ border-color: rgba(148, 163, 184, 0.4);
+ color: #475569;
+ box-shadow: 0 3px 12px rgba(0, 0, 0, 0.1);
+}
+
+body[data-theme="light"] .fab-item:hover,
+body[data-theme="light"] .fab-item.is-active {
+ color: #fff;
+}
+
+/* ========== MOBILE ========== */
+@media (max-width: 480px) {
+ .fab-left,
+ .fab-right {
+ top: 100px;
+ }
+
+ .fab-left {
+ left: 18px;
+ }
+
+ .fab-right {
+ right: 8px;
+ }
+
+ .fab-btn {
+ width: 44px;
+ height: 44px;
+ font-size: 16px;
+ }
+
+ .fab-item {
+ width: 36px;
+ height: 36px;
+ font-size: 12px;
+ }
+
+ .fab-sub {
+ width: 32px;
+ height: 32px;
+ font-size: 11px;
+ }
+
+ .fab-action {
+ width: 38px;
+ height: 38px;
+ font-size: 14px;
+ }
+
+ .fab-time {
+ font-size: 10px;
+ }
+
+ .fab-label {
+ font-size: 9px;
+ top: 50px;
+ }
+}
+
+/* Safe area */
+@supports (padding-top: env(safe-area-inset-top)) {
+ .fab-left,
+ .fab-right {
+ top: calc(120px + env(safe-area-inset-top));
+ }
+
+ .fab-left {
+ left: calc(24px + env(safe-area-inset-left));
+ }
+
+ .fab-right {
+ right: calc(12px + env(safe-area-inset-right));
+ }
+}
diff --git a/src/components/Map/RadialMenu.jsx b/src/components/Map/RadialMenu.jsx
new file mode 100644
index 0000000..e60a679
--- /dev/null
+++ b/src/components/Map/RadialMenu.jsx
@@ -0,0 +1,229 @@
+import React, { useState, useCallback } from "react";
+import "./RadialMenu.css";
+
+const CATEGORIES = [
+ { id: "News", icon: "fa-solid fa-newspaper", color: "#3b82f6" },
+ { id: "Friends", icon: "fa-solid fa-users", color: "#10b981" },
+ { id: "Events", icon: "fa-solid fa-calendar", color: "#f59e0b" },
+ { id: "Market", icon: "fa-solid fa-store", color: "#8b5cf6" },
+];
+
+const SUBCATEGORIES = {
+ News: [
+ { id: "World", icon: "fa-solid fa-globe" },
+ { id: "Politics", icon: "fa-solid fa-landmark" },
+ { id: "Tech", icon: "fa-solid fa-microchip" },
+ { id: "Finance", icon: "fa-solid fa-chart-line" },
+ { id: "Local", icon: "fa-solid fa-location-dot" },
+ ],
+ Friends: [
+ { id: "Nearby", icon: "fa-solid fa-location-crosshairs" },
+ { id: "Chats", icon: "fa-solid fa-comments" },
+ { id: "Groups", icon: "fa-solid fa-user-group" },
+ ],
+ Events: [
+ { id: "Today", icon: "fa-solid fa-calendar-day" },
+ { id: "Music", icon: "fa-solid fa-music" },
+ { id: "Sports", icon: "fa-solid fa-football" },
+ ],
+ Market: [
+ { id: "Deals", icon: "fa-solid fa-tags" },
+ { id: "Tech", icon: "fa-solid fa-laptop" },
+ { id: "Auto", icon: "fa-solid fa-car" },
+ ],
+};
+
+const TIME_OPTIONS = [
+ { label: "1h", hours: 1 },
+ { label: "6h", hours: 6 },
+ { label: "24h", hours: 24 },
+ { label: "7d", hours: 168 },
+ { label: "2w", hours: 336 },
+];
+
+export default function RadialMenu({
+ onCategoryToggle,
+ onSubcategoryToggle,
+ onTime,
+ onWeather,
+ activeCategories = [],
+ activeSubcategories = [],
+ activeTime,
+ weatherEnabled,
+}) {
+ const [leftOpen, setLeftOpen] = useState(false);
+ const [rightOpen, setRightOpen] = useState(false);
+
+ // Get colors for split FAB
+ const activeColors = CATEGORIES
+ .filter(c => activeCategories.includes(c.id))
+ .map(c => c.color);
+
+ const handleLeftToggle = () => {
+ setLeftOpen(!leftOpen);
+ if (!leftOpen) setRightOpen(false);
+ };
+
+ const handleRightToggle = () => {
+ setRightOpen(!rightOpen);
+ if (!rightOpen) setLeftOpen(false);
+ };
+
+ const handleCategoryClick = (catId) => {
+ onCategoryToggle?.(catId);
+ };
+
+ const handleSubcatClick = (catId, subId) => {
+ onSubcategoryToggle?.(catId, subId);
+ };
+
+ const handleTimeClick = (hours) => {
+ onTime?.(hours);
+ };
+
+ const handleWeatherClick = () => {
+ onWeather?.();
+ };
+
+ // Build gradient for multi-select FAB
+ const fabGradient = activeColors.length === 0
+ ? "linear-gradient(135deg, #6366f1 0%, #4f46e5 100%)"
+ : activeColors.length === 1
+ ? `linear-gradient(135deg, ${activeColors[0]} 0%, ${activeColors[0]}dd 100%)`
+ : `conic-gradient(${activeColors.map((c, i) => `${c} ${i * (360 / activeColors.length)}deg ${(i + 1) * (360 / activeColors.length)}deg`).join(", ")})`;
+
+ return (
+ <>
+ {/* Backdrop */}
+ {(leftOpen || rightOpen) && (
+
{ setLeftOpen(false); setRightOpen(false); }}
+ />
+ )}
+
+ {/* LEFT FAB - Categories */}
+
+ {/* Categories ring - expand DOWN-RIGHT */}
+
+ {CATEGORIES.map((cat, i) => {
+ // Find index of first active category to rotate
+ const firstActiveIdx = CATEGORIES.findIndex(c => activeCategories.includes(c.id));
+ // Rotate so active category is at top-right (angle 20)
+ const rotateOffset = firstActiveIdx >= 0 ? -firstActiveIdx * 42 : 0;
+ const angle = 20 + (i * 42) + rotateOffset; // Rotated based on selection
+ const rad = (angle * Math.PI) / 180;
+ const r = 62;
+ const x = Math.cos(rad) * r;
+ const y = Math.sin(rad) * r;
+ const isActive = activeCategories.includes(cat.id);
+
+ // Subcategories for this category
+ const subcats = SUBCATEGORIES[cat.id] || [];
+ const subRadius = 55;
+
+ return (
+
+ {/* Category button */}
+
+
+ {/* Subcategories - appear around the category when active */}
+ {isActive && leftOpen && subcats.map((sub, si) => {
+ const subAngle = angle - 25 + (si * 38); // More spacing
+ const subRad = (subAngle * Math.PI) / 180;
+ const subX = x + Math.cos(subRad) * subRadius;
+ const subY = y + Math.sin(subRad) * subRadius;
+ const isSubActive = activeSubcategories.includes(`${cat.id}:${sub.id}`);
+
+ return (
+
+ );
+ })}
+
+ );
+ })}
+
+
+ {/* Main FAB - split colors */}
+
+
+
+ {/* RIGHT FAB - Time & Weather */}
+
+
+ {/* Time options */}
+ {TIME_OPTIONS.map((t, i) => {
+ const angle = 110 + (i * 35);
+ const rad = (angle * Math.PI) / 180;
+ const r = 60;
+ const x = Math.cos(rad) * r;
+ const y = Math.sin(rad) * r;
+ return (
+
+ );
+ })}
+
+ {/* Weather toggle */}
+
+
+
+ {/* Main FAB */}
+
+
{TIME_OPTIONS.find(t => t.hours === activeTime)?.label || "2w"}
+
+ >
+ );
+}
diff --git a/src/components/Map/markerManager.js b/src/components/Map/markerManager.js
index 8af6da9..6c68cc7 100644
--- a/src/components/Map/markerManager.js
+++ b/src/components/Map/markerManager.js
@@ -1503,32 +1503,19 @@ export function openCenteredOverlay({ map, post, theme, fullScreen = false }) {
}
});
});
+ // Animate in using CSS classes only (no inline transitions that persist)
requestAnimationFrame(() => {
- try { backdrop.classList.add("sw-enter-active"); } catch {}
- try { modalWrap.classList.add("sw-enter-active"); } catch {}
+ backdrop.classList.add("sw-open");
+ modalWrap.classList.add("sw-open");
+ // After animation completes, remove any inline transition to prevent jumps
+ setTimeout(() => {
+ try {
+ modalWrap.style.transition = "none";
+ backdrop.style.transition = "none";
+ } catch {}
+ }, 350);
});
- // animate in
- backdrop.style.opacity = "0";
- modalWrap.style.opacity = "0";
- modalWrap.style.transform = "scale(0.96)";
- requestAnimationFrame(() => {
- backdrop.style.transition = "opacity 260ms ease";
- modalWrap.style.transition = "opacity 260ms ease, transform 320ms cubic-bezier(.2,.9,.2,1)";
- backdrop.style.opacity = "1";
- modalWrap.style.opacity = "1";
- modalWrap.style.transform = "scale(1)";
- });
-
-
- // ✅ animate in (fade + scale)
- try {
- requestAnimationFrame(() => {
- backdrop.classList.add("sw-open");
- modalWrap.classList.add("sw-open");
- });
- } catch {}
-
// outside click closes (ignore drag/scroll on map)
let backdropDown = null;
const trackDown = (e) => {
diff --git a/src/styles/filters.css b/src/styles/filters.css
index 12a22cb..60f9ae8 100644
--- a/src/styles/filters.css
+++ b/src/styles/filters.css
@@ -1,20 +1,79 @@
-.sw-icon-column { display:flex; flex-direction:column; gap:.55rem; align-items:center; }
-.sw-icon-btn { background:none; border:none; padding:0; cursor:pointer; display:flex; flex-direction:column; align-items:center; gap:.15rem; color:#e5e7eb; }
-.sw-icon-circle {
- width:54px; height:54px; border-radius:50%;
- background: rgba(15, 23, 42, 0.86);
- border: 1.5px solid rgba(148, 163, 184, 0.7);
- display:flex; align-items:center; justify-content:center;
- color:#e5e7eb;
- box-shadow:0 3px 10px rgba(0,0,0,.75);
- transition: transform 0.36s ease, box-shadow 0.36s ease, border-color 0.36s ease, background 0.36s ease;
+/* Filter buttons - Modern glassmorphism style */
+.sw-icon-column {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ align-items: center;
+}
+
+.sw-icon-btn {
+ background: none;
+ border: none;
+ padding: 0;
+ cursor: pointer;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 0.2rem;
+ color: #e5e7eb;
+ -webkit-tap-highlight-color: transparent;
+}
+
+.sw-icon-circle {
+ width: 48px;
+ height: 48px;
+ border-radius: 50%;
+ background: rgba(15, 23, 42, 0.75);
+ backdrop-filter: blur(8px);
+ -webkit-backdrop-filter: blur(8px);
+ border: 1.5px solid rgba(148, 163, 184, 0.4);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #cbd5e1;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.05);
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+}
+
+.sw-icon-circle i {
+ font-size: 18px;
+ color: currentColor;
+ transition: transform 0.2s ease;
+}
+
+.sw-icon-label {
+ font-size: 0.65rem;
+ font-weight: 500;
+ line-height: 1;
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
+ opacity: 0.9;
+}
+
+.sw-icon-btn:hover .sw-icon-circle {
+ transform: scale(1.08);
+ border-color: rgba(148, 163, 184, 0.6);
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
+}
+
+.sw-icon-btn:hover .sw-icon-circle i {
+ transform: scale(1.1);
+}
+
+.sw-icon-btn:active .sw-icon-circle {
+ transform: scale(0.95);
+}
+
+.sw-icon-active .sw-icon-circle {
+ background: linear-gradient(135deg, rgba(59, 130, 246, 0.9), rgba(37, 99, 235, 0.9));
+ border-color: rgba(96, 165, 250, 0.8);
+ color: #fff;
+ box-shadow: 0 4px 20px rgba(59, 130, 246, 0.5), 0 0 0 3px rgba(59, 130, 246, 0.2);
+}
+
+.sw-icon-active .sw-icon-label {
+ color: #93c5fd;
+ font-weight: 600;
}
-.sw-icon-circle i { font-size:22px; color: currentColor; }
-.sw-icon-label { font-size:.7rem; line-height:1; text-shadow:0 1px 2px rgba(0,0,0,.9); }
-.sw-icon-btn:hover .sw-icon-circle { transform: translateY(-1px); box-shadow:0 5px 14px rgba(0,0,0,.85); }
-.sw-icon-btn:active .sw-icon-circle { transform: scale(.96); box-shadow:0 2px 8px rgba(0,0,0,.9); }
-.sw-icon-active .sw-icon-circle { background: rgba(37, 99, 235, 0.82); border-color:#60a5fa; box-shadow:0 0 14px rgba(56,189,248,.95); }
-.sw-icon-active .sw-icon-label { color:#bfdbfe; font-weight:600; }
/* Right-side filter stack alignment */
.map-overlay-right .sw-icon-column { align-items:center; }
diff --git a/src/styles/map.css b/src/styles/map.css
index d9f614e..bfc2687 100644
--- a/src/styles/map.css
+++ b/src/styles/map.css
@@ -183,20 +183,20 @@
/* Left / right: filtres */
.map-overlay-left{
- left:.7rem;
- top:50%;
- transform:translateY(-50%);
- display:flex;
- flex-direction:column;
- gap:.5rem;
+ left: 0.6rem;
+ top: 50%;
+ transform: translateY(-50%);
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
}
.map-overlay-right{
- right:.7rem;
- top:50%;
- transform:translateY(-50%);
- display:flex;
- flex-direction:column;
- gap:.5rem;
+ right: 0.6rem;
+ top: 50%;
+ transform: translateY(-50%);
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
}
diff --git a/src/styles/mapMarkers.css b/src/styles/mapMarkers.css
index ab5dbc5..aebaa9a 100644
--- a/src/styles/mapMarkers.css
+++ b/src/styles/mapMarkers.css
@@ -70,6 +70,12 @@
gap: 8px;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
+ /* Mobile stability fixes */
+ -webkit-tap-highlight-color: transparent;
+ touch-action: pan-y;
+ -webkit-touch-callout: none;
+ transform: translateZ(0);
+ backface-visibility: hidden;
--sw-modal-accent: #38bdf8;
--sw-modal-accent-soft: rgba(56,189,248,0.28);
--sw-modal-accent-glow: rgba(56,189,248,0.5);
@@ -79,6 +85,14 @@
--sw-modal-pill-text: #c7e3ff;
}
+/* Prevent any tap effects on interactive elements inside modal */
+.sw-centered-modal button,
+.sw-centered-modal a,
+.sw-centered-modal [data-action] {
+ -webkit-tap-highlight-color: transparent;
+ touch-action: manipulation;
+}
+
/* Couleur principale par catégorie/template pour grosse carte */
.sw-centered-modal [data-template="news"]{
@@ -536,10 +550,25 @@ body[data-theme="light"] .sw-chat-bubble::before{
color: #e8f5ff;
font-weight: 900;
padding: 6px 12px;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: background 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
+ -webkit-tap-highlight-color: transparent;
+ user-select: none;
+}
+
+.post-card-btn:hover{
+ background: var(--sw-modal-accent-soft, rgba(56,189,248,0.25));
+ border-color: var(--sw-modal-accent, rgba(56,189,248,0.5));
}
.post-card-btn:active{
- transform: scale(0.98);
+ opacity: 0.8;
+}
+
+.post-card-btn:disabled{
+ opacity: 0.5;
+ cursor: not-allowed;
}
/* Center modal content */
@@ -1017,6 +1046,15 @@ body[data-theme="light"] .sw-modal-hero-fallback{
border: 1px solid var(--sw-modal-accent, rgba(90, 190, 255, 0.22));
padding: 6px 10px;
border-radius: 999px;
+ min-width: 52px;
+ text-align: center;
+ white-space: nowrap;
+}
+
+.sw-stat-pill .sw-stat-num{
+ display: inline-block;
+ min-width: 1.2em;
+ transition: opacity 0.15s ease;
}
.sw-modal-cta-row{
@@ -1087,7 +1125,11 @@ body[data-theme="light"] .sw-modal-hero-fallback{
padding: 12px;
pointer-events: auto;
opacity: 0;
- transition: opacity 440ms ease;
+ transition: opacity 300ms ease;
+ /* Mobile stability */
+ -webkit-tap-highlight-color: transparent;
+ touch-action: none;
+ overscroll-behavior: contain;
}
.sw-centered-backdrop.sw-modal-fullscreen{
@@ -1095,10 +1137,14 @@ body[data-theme="light"] .sw-modal-hero-fallback{
}
.sw-centered-modal{
- transform: scale(0.94);
- opacity: 0.0;
- transition: transform 440ms ease, opacity 440ms ease;
+ transform: scale(0.96);
+ opacity: 0;
+ transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1), opacity 200ms ease;
will-change: transform, opacity;
+ /* Prevent any bouncing/jumping */
+ -webkit-tap-highlight-color: transparent;
+ backface-visibility: hidden;
+ perspective: 1000px;
}
.sw-centered-backdrop.sw-open{
@@ -1106,8 +1152,38 @@ body[data-theme="light"] .sw-modal-hero-fallback{
}
.sw-centered-modal.sw-open{
- transform: scale(1);
- opacity: 1.0;
+ transform: scale(1) translateZ(0);
+ opacity: 1;
+ /* Once open, disable ALL transitions to prevent flash/jump */
+ transition: none !important;
+ will-change: auto;
+}
+
+/* Prevent layout shifts during interactions */
+.sw-centered-modal.sw-open .post-card.sw-expanded-shell{
+ contain: layout style paint;
+ transform: translateZ(0);
+ isolation: isolate;
+}
+
+/* Smooth stat updates without layout shift */
+.sw-stat-num{
+ display: inline-block;
+ min-width: 1.5em;
+ text-align: center;
+}
+
+/* Mobile: prevent any visual feedback that causes "jumping" */
+@media (hover: none) and (pointer: coarse) {
+ .sw-centered-modal * {
+ -webkit-tap-highlight-color: transparent !important;
+ }
+
+ .sw-centered-modal button:active,
+ .sw-centered-modal [data-action]:active {
+ transform: none !important;
+ opacity: 0.85;
+ }
}
body[data-theme="blue"] .sw-centered-backdrop{
diff --git a/src/styles/smartSearchBar.css b/src/styles/smartSearchBar.css
index e69984d..598e911 100644
--- a/src/styles/smartSearchBar.css
+++ b/src/styles/smartSearchBar.css
@@ -247,3 +247,53 @@ body[data-theme="light"] {
color: var(--sw-danger, #ff6b6b);
font-size: 12.5px;
}
+
+/* Time filter chips */
+.sw-time-chips {
+ display: flex;
+ gap: 3px;
+}
+
+.sw-time-chip {
+ border: none;
+ outline: none;
+ cursor: pointer;
+ padding: 5px 8px;
+ border-radius: 8px;
+ background: var(--sw-chip-bg, rgba(255,255,255,0.08));
+ color: var(--sw-muted, rgba(255,255,255,0.7));
+ font-size: 11px;
+ font-weight: 700;
+ transition: all 0.15s ease;
+ -webkit-tap-highlight-color: transparent;
+}
+
+.sw-time-chip:hover {
+ background: rgba(59, 130, 246, 0.25);
+ color: var(--sw-text, #fff);
+}
+
+.sw-time-chip.is-active {
+ background: linear-gradient(135deg, #3b82f6, #6366f1);
+ color: #fff;
+ box-shadow: 0 2px 8px rgba(59, 130, 246, 0.4);
+}
+
+.sw-time-chip:active {
+ transform: scale(0.95);
+}
+
+body[data-theme="light"] .sw-time-chip {
+ background: rgba(148, 163, 184, 0.2);
+ color: #475569;
+}
+
+body[data-theme="light"] .sw-time-chip:hover {
+ background: rgba(59, 130, 246, 0.15);
+ color: #1e40af;
+}
+
+body[data-theme="light"] .sw-time-chip.is-active {
+ background: linear-gradient(135deg, #2563eb, #4f46e5);
+ color: #fff;
+}