Files
xevion.dev/web/src/app.css

278 lines
6.7 KiB
CSS

@import "tailwindcss";
/* Dark variant definition */
@variant dark (&:where(.dark, .dark *));
@theme {
/* Custom colors */
--color-zinc-850: #1d1d20;
/* Semantic color tokens - Light mode defaults */
--color-bg-primary: #ffffff;
--color-bg-secondary: #f4f4f5;
--color-surface: #ffffff;
--color-surface-secondary: #fafafa;
--color-border: #e4e4e7;
--color-border-subtle: #f4f4f5;
--color-text-primary: #18181b;
--color-text-secondary: #52525b;
--color-text-tertiary: #71717a;
/* Custom font sizes */
--font-size-10xl: 10rem;
/* Drop shadows */
--drop-shadow-extreme: 0 0 50px black;
/* Font families */
--font-inter: "Inter Variable", sans-serif;
--font-hanken: "Hanken Grotesk", sans-serif;
--font-schibsted: "Schibsted Grotesk Variable", sans-serif;
/* Background images */
--background-image-gradient-radial: radial-gradient(
50% 50% at 50% 50%,
var(--tw-gradient-stops)
);
/* Admin colors - Light mode defaults */
--color-admin-bg: #f9fafb;
--color-admin-bg-secondary: #ffffff;
--color-admin-surface: #ffffff;
--color-admin-surface-hover: #f3f4f6;
--color-admin-border: #e5e7eb;
--color-admin-border-hover: #d1d5db;
--color-admin-text: #111827;
--color-admin-text-secondary: #4b5563;
--color-admin-text-muted: #6b7280;
--color-admin-accent: #6366f1;
--color-admin-accent-hover: #818cf8;
}
/* Dark mode overrides */
.dark {
--color-bg-primary: #000000;
--color-bg-secondary: #09090b;
--color-surface: #18181b;
--color-surface-secondary: #27272a;
--color-border: #27272a;
--color-border-subtle: #18181b;
--color-text-primary: #fafafa;
--color-text-secondary: #d4d4d8;
--color-text-tertiary: #a1a1aa;
/* Admin colors - Dark mode overrides */
--color-admin-bg: #0a0a0b;
--color-admin-bg-secondary: #18181b;
--color-admin-surface: #27272a;
--color-admin-surface-hover: #3f3f46;
--color-admin-border: #27272a;
--color-admin-border-hover: #3f3f46;
--color-admin-text: #fafafa;
--color-admin-text-secondary: #a1a1aa;
--color-admin-text-muted: #71717a;
}
html,
body {
@apply font-inter overflow-x-hidden;
color: var(--color-text-primary);
}
body {
@apply h-full;
background-color: var(--color-bg-primary);
}
html:not(.dark) {
.os-scrollbar {
--os-handle-bg: rgba(0, 0, 0, 0.25) !important;
--os-handle-bg-hover: rgba(0, 0, 0, 0.35) !important;
--os-handle-bg-active: rgba(0, 0, 0, 0.45) !important;
}
}
html.dark {
.os-scrollbar {
--os-handle-bg: rgba(255, 255, 255, 0.35) !important;
--os-handle-bg-hover: rgba(255, 255, 255, 0.45) !important;
--os-handle-bg-active: rgba(255, 255, 255, 0.55) !important;
}
}
.os-scrollbar-handle {
border-radius: 4px;
}
/* Give body scrollbars unique view-transition-names so they persist through page transitions */
/* Use child combinator to exclude nested OverlayScrollbarsComponent instances (e.g., /pgp page) */
body > .os-scrollbar-horizontal {
view-transition-name: scrollbar-h;
}
body > .os-scrollbar-vertical {
view-transition-name: scrollbar-v;
}
/* Fade in scrollbars on initial page load */
@keyframes scrollbar-fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.os-scrollbar {
animation: scrollbar-fade-in 300ms ease-out;
}
/* Native scrollbars for other elements (Webkit: Chrome, Safari, Edge) */
html:not(.dark) ::-webkit-scrollbar {
width: 10px;
height: 10px;
}
html:not(.dark) ::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.05);
border-radius: 4px;
}
html:not(.dark) ::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.25);
border-radius: 4px;
}
html:not(.dark) ::-webkit-scrollbar-thumb:hover {
background: rgba(0, 0, 0, 0.35);
}
html:not(.dark) ::-webkit-scrollbar-thumb:active {
background: rgba(0, 0, 0, 0.45);
}
html.dark ::-webkit-scrollbar {
width: 10px;
height: 10px;
}
html.dark ::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.05);
border-radius: 4px;
}
html.dark ::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.35);
border-radius: 4px;
}
html.dark ::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.45);
}
html.dark ::-webkit-scrollbar-thumb:active {
background: rgba(255, 255, 255, 0.55);
}
/* Native scrollbars for other elements (Firefox) - applied to a wrapper class */
.native-scrollbar {
scrollbar-width: thin;
}
html:not(.dark) .native-scrollbar {
scrollbar-color: rgba(0, 0, 0, 0.25) rgba(0, 0, 0, 0.05);
}
html.dark .native-scrollbar {
scrollbar-color: rgba(255, 255, 255, 0.35) rgba(255, 255, 255, 0.05);
}
/* Hide native scrollbar on html/body - OverlayScrollbars handles body scrolling */
/* Must come AFTER general scrollbar styles to win via cascade */
html,
body {
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE/Edge */
}
html::-webkit-scrollbar,
body::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera */
}
/* Utility class for page main wrapper */
.page-main {
@apply relative min-h-screen text-zinc-900 dark:text-zinc-50;
}
/* View Transitions API - theme toggle animation */
/* Disable default cross-fade so JS can animate clip-path instead */
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
/* Persistent elements (background, theme toggle, scrollbars) - excluded from page transitions */
/* Hide old snapshots entirely so only the live element shows (prevents doubling/ghosting) */
::view-transition-old(background),
::view-transition-old(theme-toggle),
::view-transition-old(scrollbar-h),
::view-transition-old(scrollbar-v) {
display: none;
}
::view-transition-new(background),
::view-transition-new(theme-toggle),
::view-transition-new(scrollbar-h),
::view-transition-new(scrollbar-v) {
animation: none;
}
/* Page content transition - Material Design shared axis pattern */
@keyframes vt-slide-to-left {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(-20px);
opacity: 0;
}
}
@keyframes vt-slide-from-right {
from {
transform: translateX(20px);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
::view-transition-old(page-content) {
animation: vt-slide-to-left 250ms cubic-bezier(0.4, 0, 0.2, 1) both;
}
::view-transition-new(page-content) {
animation: vt-slide-from-right 250ms cubic-bezier(0.4, 0, 0.2, 1) both;
}
/* Media mask for project card background images/videos - fades from transparent (left) to solid (right) */
.media-mask-fade-left {
mask-image: linear-gradient(
to right,
transparent 0%,
/* Non-linear stops to help breakup the gradient better */
rgba(0, 0, 0, 0.08) 12%,
rgba(0, 0, 0, 0.2) 22%,
rgba(0, 0, 0, 0.4) 32%,
rgba(0, 0, 0, 0.65) 42%,
rgba(0, 0, 0, 0.85) 52%,
black 65%
);
}