Refine explore and settings theming
This commit is contained in:
@@ -33,10 +33,10 @@ export function FolderScopeDropdown() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="relative">
|
<div ref={ref} className="feature-scope-dropdown relative">
|
||||||
<button
|
<button
|
||||||
onClick={() => setOpen((v) => !v)}
|
onClick={() => setOpen((v) => !v)}
|
||||||
className={`flex max-w-56 items-center gap-1.5 rounded-lg border px-3 py-1.5 text-xs transition-colors ${
|
className={`feature-scope-trigger flex max-w-56 items-center gap-1.5 rounded-lg border px-3 py-1.5 text-xs transition-colors ${
|
||||||
open
|
open
|
||||||
? "border-white/15 bg-white/8 text-white light-theme:border-gray-700/50 light-theme:bg-gray-900 light-theme:text-white"
|
? "border-white/15 bg-white/8 text-white light-theme:border-gray-700/50 light-theme:bg-gray-900 light-theme:text-white"
|
||||||
: "border-white/8 bg-transparent text-gray-400 hover:border-white/15 hover:text-gray-200 light-theme:border-gray-700/40 light-theme:text-gray-600 light-theme:hover:border-gray-700 light-theme:hover:bg-gray-900 light-theme:hover:text-white"
|
: "border-white/8 bg-transparent text-gray-400 hover:border-white/15 hover:text-gray-200 light-theme:border-gray-700/40 light-theme:text-gray-600 light-theme:hover:border-gray-700 light-theme:hover:bg-gray-900 light-theme:hover:text-white"
|
||||||
@@ -55,9 +55,9 @@ export function FolderScopeDropdown() {
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
{open ? (
|
{open ? (
|
||||||
<div className="absolute right-0 top-full z-30 mt-1.5 max-h-80 min-w-52 overflow-y-auto rounded-xl border border-white/10 bg-gray-950/98 p-1 shadow-2xl backdrop-blur light-theme:border-gray-700/50">
|
<div className="feature-scope-menu absolute right-0 top-full z-30 mt-1.5 max-h-80 min-w-52 overflow-y-auto rounded-xl border border-white/10 bg-gray-950/98 p-1 shadow-2xl backdrop-blur light-theme:border-gray-700/50">
|
||||||
<button
|
<button
|
||||||
className={`flex w-full items-center justify-between gap-3 rounded-lg px-3 py-2 text-left text-sm transition-colors ${
|
className={`feature-scope-option flex w-full items-center justify-between gap-3 rounded-lg px-3 py-2 text-left text-sm transition-colors ${
|
||||||
selectedFolderId === null ? "bg-white/6 text-white light-theme:bg-gray-900 light-theme:text-white" : "text-gray-400 hover:bg-white/5 hover:text-white light-theme:text-gray-600 light-theme:hover:bg-gray-900 light-theme:hover:text-white"
|
selectedFolderId === null ? "bg-white/6 text-white light-theme:bg-gray-900 light-theme:text-white" : "text-gray-400 hover:bg-white/5 hover:text-white light-theme:text-gray-600 light-theme:hover:bg-gray-900 light-theme:hover:text-white"
|
||||||
}`}
|
}`}
|
||||||
onClick={() => select(null)}
|
onClick={() => select(null)}
|
||||||
@@ -74,7 +74,7 @@ export function FolderScopeDropdown() {
|
|||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={folder.id}
|
key={folder.id}
|
||||||
className={`flex w-full items-center justify-between gap-3 rounded-lg px-3 py-2 text-left text-sm transition-colors ${
|
className={`feature-scope-option flex w-full items-center justify-between gap-3 rounded-lg px-3 py-2 text-left text-sm transition-colors ${
|
||||||
active ? "bg-white/6 text-white light-theme:bg-gray-900 light-theme:text-white" : "text-gray-400 hover:bg-white/5 hover:text-white light-theme:text-gray-600 light-theme:hover:bg-gray-900 light-theme:hover:text-white"
|
active ? "bg-white/6 text-white light-theme:bg-gray-900 light-theme:text-white" : "text-gray-400 hover:bg-white/5 hover:text-white light-theme:text-gray-600 light-theme:hover:bg-gray-900 light-theme:hover:text-white"
|
||||||
}`}
|
}`}
|
||||||
onClick={() => select(folder.id)}
|
onClick={() => select(folder.id)}
|
||||||
|
|||||||
+56
-33
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||||
import { motion } from "framer-motion";
|
import { motion, useReducedMotion } from "framer-motion";
|
||||||
import { convertFileSrc } from "@tauri-apps/api/core";
|
import { convertFileSrc } from "@tauri-apps/api/core";
|
||||||
import { ExploreTagEntry, TagCloudEntry, useGalleryStore } from "../store";
|
import { ExploreTagEntry, TagCloudEntry, useGalleryStore } from "../store";
|
||||||
import { FolderScopeDropdown } from "./FolderScopeDropdown";
|
import { FolderScopeDropdown } from "./FolderScopeDropdown";
|
||||||
@@ -110,29 +110,44 @@ function buildCloud(entries: TagCloudEntry[], containerW: number, containerH: nu
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function CloudCard({ node, onOpen }: { node: PlacedNode; onOpen: (imageIds: number[]) => void }) {
|
function CloudCard({ node, onOpen, animated }: { node: PlacedNode; onOpen: (imageIds: number[]) => void; animated: boolean }) {
|
||||||
const src = node.entry.thumbnail_path ? convertFileSrc(node.entry.thumbnail_path) : null;
|
const src = node.entry.thumbnail_path ? convertFileSrc(node.entry.thumbnail_path) : null;
|
||||||
const { w, h, accent } = node;
|
const { w, h, accent } = node;
|
||||||
|
const driftTransition = {
|
||||||
|
duration: node.driftDuration,
|
||||||
|
ease: "easeInOut" as const,
|
||||||
|
delay: seeded(node.index + 41) * 1.6,
|
||||||
|
repeat: 1,
|
||||||
|
repeatType: "reverse" as const,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.button
|
<motion.button
|
||||||
className="group absolute overflow-hidden rounded-2xl border border-white/8 bg-white/[0.04] text-left shadow-[0_8px_40px_rgba(0,0,0,0.5)] focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30"
|
className="explore-cluster-card group absolute overflow-hidden rounded-2xl border border-white/8 bg-white/[0.04] text-left shadow-[0_8px_28px_rgba(0,0,0,0.38)] focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30"
|
||||||
style={{ width: w, height: h, left: node.x - w / 2, top: node.y - h / 2 }}
|
style={{ width: w, height: h, left: node.x - w / 2, top: node.y - h / 2 }}
|
||||||
initial={{ opacity: 0, scale: 0.75 }}
|
initial={animated ? { opacity: 0, scale: 0.82, rotate: node.rotateSeed } : { opacity: 0, scale: 0.96 }}
|
||||||
animate={{
|
animate={
|
||||||
|
animated
|
||||||
|
? {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
x: [0, node.driftX, 0],
|
x: [0, node.driftX * 0.65, 0],
|
||||||
y: [0, node.driftY, 0],
|
y: [0, node.driftY * 0.65, 0],
|
||||||
rotate: [node.rotateSeed, node.rotateSeed + 1.4, node.rotateSeed],
|
rotate: [node.rotateSeed, node.rotateSeed + 0.8, node.rotateSeed],
|
||||||
}}
|
}
|
||||||
transition={{
|
: { opacity: 1, scale: 1, rotate: node.rotateSeed }
|
||||||
opacity: { duration: 0.3, delay: Math.min(node.index * 0.035, 0.7) },
|
}
|
||||||
scale: { duration: 0.3, delay: Math.min(node.index * 0.035, 0.7) },
|
transition={
|
||||||
x: { duration: node.driftDuration, repeat: Infinity, ease: "easeInOut", delay: seeded(node.index + 41) * 3 },
|
animated
|
||||||
y: { duration: node.driftDuration + 1.6, repeat: Infinity, ease: "easeInOut", delay: seeded(node.index + 51) * 3 },
|
? {
|
||||||
rotate: { duration: node.driftDuration + 0.9, repeat: Infinity, ease: "easeInOut" },
|
opacity: { duration: 0.24, delay: Math.min(node.index * 0.024, 0.45) },
|
||||||
}}
|
scale: { duration: 0.24, delay: Math.min(node.index * 0.024, 0.45) },
|
||||||
|
x: driftTransition,
|
||||||
|
y: { ...driftTransition, duration: node.driftDuration + 1.2, delay: seeded(node.index + 51) * 1.6 },
|
||||||
|
rotate: { ...driftTransition, duration: node.driftDuration + 0.8, delay: seeded(node.index + 61) * 1.2 },
|
||||||
|
}
|
||||||
|
: { opacity: { duration: 0.18, delay: Math.min(node.index * 0.016, 0.28) }, scale: { duration: 0.18, delay: Math.min(node.index * 0.016, 0.28) } }
|
||||||
|
}
|
||||||
whileHover={{ scale: 1.06, rotate: 0, transition: { duration: 0.18 } }}
|
whileHover={{ scale: 1.06, rotate: 0, transition: { duration: 0.18 } }}
|
||||||
onClick={() => onOpen(node.entry.image_ids)}
|
onClick={() => onOpen(node.entry.image_ids)}
|
||||||
title={`Open cluster — ${node.entry.count.toLocaleString()} images`}
|
title={`Open cluster — ${node.entry.count.toLocaleString()} images`}
|
||||||
@@ -143,22 +158,24 @@ function CloudCard({ node, onOpen }: { node: PlacedNode; onOpen: (imageIds: numb
|
|||||||
alt=""
|
alt=""
|
||||||
className="absolute inset-0 h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
|
className="absolute inset-0 h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
|
||||||
draggable={false}
|
draggable={false}
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="absolute inset-0 bg-gradient-to-br from-white/[0.07] to-transparent" />
|
<div className="absolute inset-0 bg-gradient-to-br from-white/[0.07] to-transparent" />
|
||||||
)}
|
)}
|
||||||
<div className="absolute inset-0 bg-gradient-to-t from-black/85 via-black/20 to-transparent" />
|
<div className="explore-cluster-overlay absolute inset-0 bg-gradient-to-t from-black/85 via-black/20 to-transparent" />
|
||||||
{/* Accent glow on hover */}
|
{/* Accent glow on hover */}
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0 opacity-0 transition-opacity duration-300 group-hover:opacity-100"
|
className="absolute inset-0 opacity-0 transition-opacity duration-300 group-hover:opacity-100"
|
||||||
style={{ background: `radial-gradient(ellipse at bottom, ${accent}25, transparent 70%)` }}
|
style={{ background: `radial-gradient(ellipse at bottom, ${accent}25, transparent 70%)` }}
|
||||||
/>
|
/>
|
||||||
<div className="absolute inset-x-0 bottom-0 p-3">
|
<div className="absolute inset-x-0 bottom-0 p-3">
|
||||||
<div className="mb-2 h-px rounded-full" style={{ background: `linear-gradient(to right, ${accent}80, transparent)` }} />
|
<div className="explore-cluster-rule mb-2 h-px rounded-full" style={{ background: `linear-gradient(to right, ${accent}80, transparent)` }} />
|
||||||
<div className="flex items-end justify-between gap-2">
|
<div className="flex items-end justify-between gap-2">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-[9px] uppercase tracking-[0.18em] text-white/35">Cluster</p>
|
<p className="explore-cluster-label text-[9px] uppercase tracking-[0.18em] text-white/35">Cluster</p>
|
||||||
<p className="text-base font-semibold leading-none text-white">{node.entry.count.toLocaleString()}</p>
|
<p className="explore-cluster-count text-base font-semibold leading-none text-white">{node.entry.count.toLocaleString()}</p>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
className="rounded-full border px-2 py-0.5 text-[9px] uppercase tracking-[0.1em] opacity-0 transition-opacity duration-200 group-hover:opacity-100"
|
className="rounded-full border px-2 py-0.5 text-[9px] uppercase tracking-[0.1em] opacity-0 transition-opacity duration-200 group-hover:opacity-100"
|
||||||
@@ -197,7 +214,7 @@ function TagWord({
|
|||||||
animate={{ opacity: 0.4 + ratio * 0.6, scale: 1 }}
|
animate={{ opacity: 0.4 + ratio * 0.6, scale: 1 }}
|
||||||
transition={{ delay: Math.min(index * 0.008, 0.55), duration: 0.22 }}
|
transition={{ delay: Math.min(index * 0.008, 0.55), duration: 0.22 }}
|
||||||
whileHover={{ scale: 1.2, opacity: 1, rotate: 0, transition: { duration: 0.14 } }}
|
whileHover={{ scale: 1.2, opacity: 1, rotate: 0, transition: { duration: 0.14 } }}
|
||||||
className="group inline-flex items-center gap-1 rounded-full px-2 py-1 transition-colors hover:bg-white/[0.07]"
|
className="explore-tag-word group inline-flex items-center gap-1 rounded-full px-2 py-1 transition-colors hover:bg-white/[0.07]"
|
||||||
style={{ fontSize, rotate: tilt }}
|
style={{ fontSize, rotate: tilt }}
|
||||||
onClick={() => onSearch(entry.tag)}
|
onClick={() => onSearch(entry.tag)}
|
||||||
title={`${entry.tag} — ${entry.count.toLocaleString()} images`}
|
title={`${entry.tag} — ${entry.count.toLocaleString()} images`}
|
||||||
@@ -221,7 +238,7 @@ function TagWord({
|
|||||||
function Spinner() {
|
function Spinner() {
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
className="h-5 w-5 rounded-full border-2 border-white/15 border-t-white/50"
|
className="explore-spinner h-5 w-5 rounded-full border-2 border-white/15 border-t-white/50"
|
||||||
animate={{ rotate: 360 }}
|
animate={{ rotate: 360 }}
|
||||||
transition={{ duration: 0.85, repeat: Infinity, ease: "linear" }}
|
transition={{ duration: 0.85, repeat: Infinity, ease: "linear" }}
|
||||||
/>
|
/>
|
||||||
@@ -238,6 +255,7 @@ function ClusterCloud({
|
|||||||
entries: TagCloudEntry[];
|
entries: TagCloudEntry[];
|
||||||
onOpen: (imageIds: number[]) => void;
|
onOpen: (imageIds: number[]) => void;
|
||||||
}) {
|
}) {
|
||||||
|
const reducedMotion = useReducedMotion();
|
||||||
const canvasRef = useRef<HTMLDivElement>(null);
|
const canvasRef = useRef<HTMLDivElement>(null);
|
||||||
const [canvasSize, setCanvasSize] = useState({ w: 0, h: 0 });
|
const [canvasSize, setCanvasSize] = useState({ w: 0, h: 0 });
|
||||||
|
|
||||||
@@ -261,9 +279,14 @@ function ClusterCloud({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={canvasRef} className="relative min-h-0 flex-1 overflow-hidden">
|
<div ref={canvasRef} className="relative min-h-0 flex-1 overflow-hidden">
|
||||||
<div className="pointer-events-none absolute inset-0 opacity-[0.07] [background-image:radial-gradient(circle,rgba(255,255,255,0.6)_1px,transparent_1px)] [background-size:28px_28px]" />
|
<div className="explore-cluster-grid pointer-events-none absolute inset-0 opacity-[0.07] [background-image:radial-gradient(circle,rgba(255,255,255,0.6)_1px,transparent_1px)] [background-size:28px_28px]" />
|
||||||
{nodes.map((node) => (
|
{nodes.map((node) => (
|
||||||
<CloudCard key={`${node.entry.representative_image_id}:${node.index}`} node={node} onOpen={onOpen} />
|
<CloudCard
|
||||||
|
key={`${node.entry.representative_image_id}:${node.index}`}
|
||||||
|
node={node}
|
||||||
|
onOpen={onOpen}
|
||||||
|
animated={!reducedMotion && node.index < 12}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -300,13 +323,13 @@ export function TagCloud() {
|
|||||||
const entryCount = exploreMode === "visual" ? tagCloudEntries.length : exploreTagEntries.length;
|
const entryCount = exploreMode === "visual" ? tagCloudEntries.length : exploreTagEntries.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-0 flex-1 flex-col overflow-hidden bg-[radial-gradient(ellipse_at_top,rgba(59,130,246,0.08),transparent_50%),radial-gradient(ellipse_at_80%_75%,rgba(168,85,247,0.07),transparent_40%),#07080f]">
|
<div className="explore-view flex min-h-0 flex-1 flex-col overflow-hidden bg-[radial-gradient(ellipse_at_top,rgba(59,130,246,0.08),transparent_50%),radial-gradient(ellipse_at_80%_75%,rgba(168,85,247,0.07),transparent_40%),#07080f]">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="shrink-0 border-b border-white/[0.05] px-6 py-4">
|
<div className="explore-header shrink-0 border-b border-white/[0.05] px-6 py-4">
|
||||||
<div className="flex items-center justify-between gap-4">
|
<div className="flex items-center justify-between gap-4">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<h2 className="text-[15px] font-semibold text-white">Explore</h2>
|
<h2 className="explore-title text-[15px] font-semibold text-white">Explore</h2>
|
||||||
<p className="mt-0.5 truncate text-[11px] text-white/30">
|
<p className="explore-subtitle mt-0.5 truncate text-[11px] text-white/30">
|
||||||
{loading
|
{loading
|
||||||
? exploreMode === "visual" ? "Computing visual clusters…" : "Loading tags…"
|
? exploreMode === "visual" ? "Computing visual clusters…" : "Loading tags…"
|
||||||
: hasEntries
|
: hasEntries
|
||||||
@@ -320,9 +343,9 @@ export function TagCloud() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex shrink-0 items-center gap-2">
|
<div className="flex shrink-0 items-center gap-2">
|
||||||
<FolderScopeDropdown />
|
<FolderScopeDropdown />
|
||||||
<div className="flex rounded-lg border border-white/8 bg-white/[0.03] p-0.5">
|
<div className="explore-mode-toggle flex rounded-lg border border-white/8 bg-white/[0.03] p-0.5">
|
||||||
<button
|
<button
|
||||||
className={`rounded-md px-3 py-1.5 text-xs transition-colors ${
|
className={`explore-mode-button rounded-md px-3 py-1.5 text-xs transition-colors ${
|
||||||
exploreMode === "visual" ? "bg-white/10 text-white" : "text-gray-500 hover:text-gray-300"
|
exploreMode === "visual" ? "bg-white/10 text-white" : "text-gray-500 hover:text-gray-300"
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setExploreMode("visual")}
|
onClick={() => setExploreMode("visual")}
|
||||||
@@ -330,7 +353,7 @@ export function TagCloud() {
|
|||||||
Clusters
|
Clusters
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={`rounded-md px-3 py-1.5 text-xs transition-colors ${
|
className={`explore-mode-button rounded-md px-3 py-1.5 text-xs transition-colors ${
|
||||||
exploreMode === "tags" ? "bg-white/10 text-white" : "text-gray-500 hover:text-gray-300"
|
exploreMode === "tags" ? "bg-white/10 text-white" : "text-gray-500 hover:text-gray-300"
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setExploreMode("tags")}
|
onClick={() => setExploreMode("tags")}
|
||||||
@@ -343,13 +366,13 @@ export function TagCloud() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="flex flex-1 items-center justify-center gap-3 text-white/25">
|
<div className="explore-empty flex flex-1 items-center justify-center gap-3 text-white/25">
|
||||||
<Spinner />
|
<Spinner />
|
||||||
<span className="text-sm">{exploreMode === "visual" ? "Computing clusters…" : "Loading tags…"}</span>
|
<span className="text-sm">{exploreMode === "visual" ? "Computing clusters…" : "Loading tags…"}</span>
|
||||||
</div>
|
</div>
|
||||||
) : !hasEntries ? (
|
) : !hasEntries ? (
|
||||||
<div className="flex flex-1 items-center justify-center px-8">
|
<div className="flex flex-1 items-center justify-center px-8">
|
||||||
<p className="max-w-xs text-center text-sm leading-relaxed text-white/25">
|
<p className="explore-empty max-w-xs text-center text-sm leading-relaxed text-white/25">
|
||||||
{exploreMode === "visual"
|
{exploreMode === "visual"
|
||||||
? "No visual clusters yet. Images need embeddings before they can be grouped. Check indexing progress in the sidebar."
|
? "No visual clusters yet. Images need embeddings before they can be grouped. Check indexing progress in the sidebar."
|
||||||
: "No tags yet. Run the AI tagger from Settings, or add tags manually in the image preview."}
|
: "No tags yet. Run the AI tagger from Settings, or add tags manually in the image preview."}
|
||||||
|
|||||||
+230
@@ -61,6 +61,236 @@ html[data-theme="subtle-light"] .media-dark-surface {
|
|||||||
--color-gray-100: #f3f4f6;
|
--color-gray-100: #f3f4f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal {
|
||||||
|
background: #f4f2ea !important;
|
||||||
|
border-color: #d6d1c7 !important;
|
||||||
|
color: #1f2937 !important;
|
||||||
|
box-shadow: 0 24px 80px rgb(0 0 0 / 0.24) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal aside {
|
||||||
|
background: #ece9e1 !important;
|
||||||
|
border-color: #d6d1c7 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal aside > div:first-child {
|
||||||
|
border-color: #d6d1c7 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .settings-nav-active {
|
||||||
|
background: #d8d4ca !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .settings-nav-inactive {
|
||||||
|
background: transparent !important;
|
||||||
|
color: #4b5563 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .settings-nav-inactive:hover {
|
||||||
|
background: #e2ded5 !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .settings-model-card,
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .settings-light-panel {
|
||||||
|
background: #fbfaf6 !important;
|
||||||
|
border-color: #d6d1c7 !important;
|
||||||
|
color: #1f2937 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal button:not([role="switch"]) {
|
||||||
|
background: #fbfaf6 !important;
|
||||||
|
border-color: #cfc8ba !important;
|
||||||
|
color: #374151 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal button:not([role="switch"]):hover {
|
||||||
|
background: #eeeae0 !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal input {
|
||||||
|
background: #ffffff !important;
|
||||||
|
border-color: #cfc8ba !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-white,
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-gray-200,
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-gray-300,
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-gray-400 {
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-gray-500,
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-gray-600 {
|
||||||
|
color: #5f5a52 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-emerald-200,
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-emerald-300 {
|
||||||
|
color: #047857 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-sky-300 {
|
||||||
|
color: #0369a1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-amber-200,
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-amber-300 {
|
||||||
|
color: #b45309 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .text-red-200 {
|
||||||
|
color: #b91c1c !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .bg-white\/10,
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .bg-white\/5,
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .bg-white\/\[0\.025\],
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .bg-white\/\[0\.04\],
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .bg-white\/\[0\.045\],
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .bg-white\/\[0\.055\] {
|
||||||
|
background: #fbfaf6 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .border-white\/10,
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .border-white\/\[0\.05\],
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .border-white\/\[0\.06\],
|
||||||
|
html[data-theme="subtle-light"] .settings-modal .border-white\/\[0\.07\] {
|
||||||
|
border-color: #d6d1c7 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-view {
|
||||||
|
background:
|
||||||
|
radial-gradient(ellipse at top, rgb(59 130 246 / 0.08), transparent 48%),
|
||||||
|
radial-gradient(ellipse at 80% 75%, rgb(16 185 129 / 0.07), transparent 42%),
|
||||||
|
#f4f2ea !important;
|
||||||
|
color: #1f2937 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-header {
|
||||||
|
background: #f4f2ea !important;
|
||||||
|
border-color: #d8d2c7 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-title {
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-subtitle,
|
||||||
|
html[data-theme="subtle-light"] .explore-empty {
|
||||||
|
color: #7a746b !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-mode-toggle {
|
||||||
|
background: #ece8dd !important;
|
||||||
|
border-color: #d0c8ba !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-mode-button {
|
||||||
|
background: transparent !important;
|
||||||
|
color: #4b5563 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-mode-button:hover {
|
||||||
|
background: #e0dbcf !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-mode-button.bg-white\/10 {
|
||||||
|
background: #d8d4ca !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-cluster-grid {
|
||||||
|
background-image: radial-gradient(circle, rgb(31 41 55 / 0.18) 1px, transparent 1px) !important;
|
||||||
|
opacity: 0.16 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-cluster-card {
|
||||||
|
background: #fbfaf6 !important;
|
||||||
|
border-color: #d8d2c7 !important;
|
||||||
|
box-shadow: 0 14px 36px rgb(28 25 23 / 0.18) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-cluster-card:hover {
|
||||||
|
box-shadow: 0 18px 44px rgb(28 25 23 / 0.22) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-cluster-overlay {
|
||||||
|
background: linear-gradient(
|
||||||
|
to top,
|
||||||
|
rgb(251 250 246 / 0.9),
|
||||||
|
rgb(251 250 246 / 0.52) 34%,
|
||||||
|
rgb(251 250 246 / 0.06) 68%,
|
||||||
|
transparent
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-cluster-label {
|
||||||
|
color: #6b6257 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-cluster-count {
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-tag-word:hover {
|
||||||
|
background: #e8e2d6 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-tag-word span:first-child {
|
||||||
|
color: #374151 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .explore-spinner {
|
||||||
|
border-color: rgb(17 24 39 / 0.18) !important;
|
||||||
|
border-top-color: rgb(17 24 39 / 0.55) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .feature-scope-trigger {
|
||||||
|
background: #f8f6ef !important;
|
||||||
|
border-color: #d0c8ba !important;
|
||||||
|
color: #4b5563 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .feature-scope-trigger:hover,
|
||||||
|
html[data-theme="subtle-light"] .feature-scope-dropdown:has(.feature-scope-menu) .feature-scope-trigger {
|
||||||
|
background: #ece8dd !important;
|
||||||
|
border-color: #bfb6a7 !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .feature-scope-menu {
|
||||||
|
background: #fbfaf6 !important;
|
||||||
|
border-color: #d0c8ba !important;
|
||||||
|
color: #1f2937 !important;
|
||||||
|
box-shadow: 0 18px 44px rgb(28 25 23 / 0.2) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .feature-scope-option {
|
||||||
|
color: #4b5563 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .feature-scope-option:hover {
|
||||||
|
background: #ece8dd !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="subtle-light"] .feature-scope-option.bg-white\/6 {
|
||||||
|
background: #d8d4ca !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.explore-cluster-card,
|
||||||
|
.explore-cluster-card img {
|
||||||
|
transition-duration: 0.01ms !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Custom scrollbar */
|
/* Custom scrollbar */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
|
|||||||
Reference in New Issue
Block a user