@import '@fontsource-variable/inter';
@import '@fontsource-variable/fraunces';
@import 'tailwindcss';
@import 'tw-animate-css';
@import './theme/tokens.css';
@import './theme/accents.css';
@import './theme/radius.css';
@import './theme/bridge.css';
@import './theme/cover-effects.css';
@custom-variant dark (&:is(.dark *));
.pattern-preview {
position: relative;
overflow: hidden;
}
.pattern-preview[class*='pattern-']::before {
position: absolute;
z-index: 1;
}
.pattern-dots {
background-image: radial-gradient(circle, var(--dot-color) 1px, transparent 1px);
background-size: 24px 24px;
}
.pattern-cross {
background-image: radial-gradient(circle, var(--dot-color) 1px, transparent 1px), radial-gradient(circle, var(--dot-color) 1px, transparent 1px);
background-size: 24px 24px;
background-position:
0 0,
12px 12px;
}
.pattern-aurora {
background-image:
radial-gradient(ellipse 60% 45% at 0% 50%, color-mix(in oklch, var(--primary) 15%, transparent), transparent 100%),
radial-gradient(ellipse 50% 40% at 100% 50%, color-mix(in oklch, var(--primary) 10%, transparent), transparent 100%),
radial-gradient(ellipse 40% 35% at 50% 0%, color-mix(in oklch, var(--primary) 8%, transparent), transparent 100%);
}
.pattern-horizon {
background-image: linear-gradient(180deg, transparent 0%, color-mix(in oklch, var(--primary) 8%, transparent) 50%, transparent 100%);
}
.pattern-topo {
background-image:
repeating-radial-gradient(
circle at 0% 0%,
transparent 0,
transparent 40px,
color-mix(in oklch, var(--dot-color) 50%, transparent) 40px,
color-mix(in oklch, var(--dot-color) 50%, transparent) 41px,
transparent 41px,
transparent 80px
),
repeating-radial-gradient(
circle at 100% 100%,
transparent 0,
transparent 40px,
color-mix(in oklch, var(--dot-color) 50%, transparent) 40px,
color-mix(in oklch, var(--dot-color) 50%, transparent) 41px,
transparent 41px,
transparent 80px
);
}
.pattern-mesh {
background-image:
radial-gradient(at 0% 0%, color-mix(in oklch, var(--primary) 20%, transparent) 0px, transparent 50%),
radial-gradient(at 100% 0%, color-mix(in oklch, var(--primary) 15%, transparent) 0px, transparent 50%),
radial-gradient(at 100% 100%, color-mix(in oklch, var(--primary) 20%, transparent) 0px, transparent 50%),
radial-gradient(at 0% 100%, color-mix(in oklch, var(--primary) 15%, transparent) 0px, transparent 50%),
radial-gradient(at 50% 50%, color-mix(in oklch, var(--primary) 10%, transparent) 0px, transparent 50%);
}
.pattern-glow {
background-image: radial-gradient(ellipse 80% 50% at 50% -10%, color-mix(in oklch, var(--primary) 20%, transparent) 0%, transparent 100%);
}
.pattern-brushed {
background-image: repeating-linear-gradient(
45deg,
transparent,
transparent 1px,
color-mix(in oklch, var(--primary) 6%, transparent) 1px,
color-mix(in oklch, var(--primary) 6%, transparent) 2px
);
}
.pattern-prism::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
linear-gradient(135deg, rgba(255, 0, 0, 0.03) 0%, transparent 50%), linear-gradient(225deg, rgba(0, 0, 255, 0.03) 0%, transparent 50%),
linear-gradient(45deg, rgba(0, 255, 0, 0.03) 0%, transparent 50%);
filter: contrast(150%) brightness(110%);
}
.pattern-spectrum::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
linear-gradient(135deg, oklch(0.7 0.15 var(--tint-h) / 0.08) 0%, transparent 50%),
linear-gradient(225deg, oklch(0.7 0.15 calc(var(--tint-h) + 120) / 0.08) 0%, transparent 50%),
linear-gradient(45deg, oklch(0.7 0.15 calc(var(--tint-h) + 240) / 0.08) 0%, transparent 50%);
filter: contrast(160%) brightness(110%);
}
.pattern-spectrum-x::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
linear-gradient(135deg, oklch(0.7 0.15 var(--tint-h) / 0.08) 0%, transparent 50%),
linear-gradient(225deg, oklch(0.7 0.15 calc(var(--tint-h) + 90) / 0.08) 0%, transparent 50%),
linear-gradient(315deg, oklch(0.7 0.15 calc(var(--tint-h) + 180) / 0.08) 0%, transparent 50%),
linear-gradient(45deg, oklch(0.7 0.15 calc(var(--tint-h) + 270) / 0.08) 0%, transparent 50%);
filter: contrast(160%) brightness(110%);
}
.pattern-spectrum-plus::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
linear-gradient(to bottom, oklch(0.7 0.15 var(--tint-h) / 0.08) 0%, transparent 50%),
linear-gradient(to left, oklch(0.7 0.15 calc(var(--tint-h) + 90) / 0.08) 0%, transparent 50%),
linear-gradient(to top, oklch(0.7 0.15 calc(var(--tint-h) + 180) / 0.08) 0%, transparent 50%),
linear-gradient(to right, oklch(0.7 0.15 calc(var(--tint-h) + 270) / 0.08) 0%, transparent 50%);
filter: contrast(160%) brightness(110%);
}
.pattern-eclipse::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
radial-gradient(at 0% 0%, oklch(0.7 0.15 var(--tint-h) / 0.12) 0%, transparent 65%),
radial-gradient(at 100% 100%, oklch(0.7 0.15 calc(var(--tint-h) + 180) / 0.12) 0%, transparent 65%);
filter: contrast(150%) brightness(110%);
}
.pattern-millimeter::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
linear-gradient(to right, color-mix(in oklch, var(--primary) 5%, transparent) 1px, transparent 1px),
linear-gradient(to bottom, color-mix(in oklch, var(--primary) 5%, transparent) 1px, transparent 1px);
background-size: 2px 2px;
}
.pattern-elevation::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
linear-gradient(to bottom, color-mix(in oklch, var(--primary) 5%, transparent), transparent 40%),
linear-gradient(to top, color-mix(in oklch, var(--primary) 3%, transparent), transparent 30%);
}
.pattern-terminal::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
opacity: 0.05;
background-image: repeating-linear-gradient(90deg, var(--primary), var(--primary) 1px, transparent 1px, transparent 40px);
}
.pattern-scanlines::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background: linear-gradient(to bottom, transparent 50%, color-mix(in oklch, var(--primary) 5%, transparent) 50%);
background-size: 100% 4px;
}
.pattern-vinyl::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image: repeating-radial-gradient(
circle at 50% -25%,
transparent,
transparent 3px,
color-mix(in oklch, var(--primary) 8%, transparent) 3.75px,
transparent 4.5px
);
}
.pattern-carbon::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
linear-gradient(45deg, color-mix(in oklch, var(--primary) 5%, transparent) 25%, transparent 25%),
linear-gradient(-45deg, color-mix(in oklch, var(--primary) 5%, transparent) 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, color-mix(in oklch, var(--primary) 5%, transparent) 75%),
linear-gradient(-45deg, transparent 75%, color-mix(in oklch, var(--primary) 5%, transparent) 75%);
background-size: 8px 8px;
}
.pattern-perforated::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image: radial-gradient(circle at center, color-mix(in oklch, var(--primary) 8%, transparent) 1.5px, transparent 2px);
background-size: 12px 12px;
}
.pattern-blueprint::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
linear-gradient(to right, color-mix(in oklch, var(--primary) 4%, transparent) 1px, transparent 1px),
linear-gradient(to bottom, color-mix(in oklch, var(--primary) 4%, transparent) 1px, transparent 1px);
background-size: 4px 4px;
}
.pattern-wireframe::before {
content: '';
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
opacity: 0.1;
background-color: var(--primary);
-webkit-mask-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 50l50-50 50 50-50 50z' fill='none' stroke='black' stroke-width='0.5'/%3E%3Cpath d='M50 0v100M0 50h100' stroke='black' stroke-width='0.5'/%3E%3Ccircle cx='50' cy='50' r='2' fill='black'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 50l50-50 50 50-50 50z' fill='none' stroke='black' stroke-width='0.5'/%3E%3Cpath d='M50 0v100M0 50h100' stroke='black' stroke-width='0.5'/%3E%3Ccircle cx='50' cy='50' r='2' fill='black'/%3E%3C/svg%3E");
mask-size: 150px 150px;
}
.glow-wrapper {
background-image: radial-gradient(50% 50% at center -25px, color-mix(in oklch, var(--primary) 35%, transparent) 0%, transparent 100%);
background-blend-mode: hard-light, color-dodge;
background-position: top;
background-repeat: no-repeat;
background-size: auto 12rem;
}
@layer base {
* {
@apply border-border outline-ring/50;
scrollbar-color: var(--scrollbar-thumb) transparent;
}
html,
body,
#app,
.app-shell,
.app-shell-inset,
.app-shell-scroll {
max-width: 100%;
overflow-x: clip;
overscroll-behavior-x: none;
}
@supports not (overflow: clip) {
html,
body,
#app,
.app-shell,
.app-shell-inset,
.app-shell-scroll {
overflow-x: hidden;
}
}
body {
@apply bg-background text-foreground font-sans antialiased;
}
@supports (-webkit-touch-callout: none) {
@media (pointer: coarse) {
/* iOS Safari auto-zooms focused inputs below 16px. Keep editable controls at 16px on touch devices. */
input:not([type='checkbox']):not([type='radio']):not([type='range']):not([type='color']):not([type='file']):not([type='button']):not(
[type='submit']
):not([type='reset']):not([data-ios-zoom-exempt]),
textarea:not([data-ios-zoom-exempt]),
select:not([data-ios-zoom-exempt]) {
font-size: 16px;
}
}
}
@media (pointer: coarse) {
.app-shell-inset,
.app-shell-scroll {
touch-action: pan-y;
}
/* Prevent double-tap zoom on tappable controls while preserving normal taps. */
a,
button,
[role='button'] {
touch-action: manipulation;
}
}
/* Webkit scrollbar styles */
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--scrollbar-thumb);
border: 2px solid transparent;
background-clip: padding-box;
border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--scrollbar-thumb-hover);
border: 2px solid transparent;
background-clip: padding-box;
}
}
@layer components {
.viewer-btn {
@apply flex items-center justify-center w-8 h-8 rounded text-foreground/60 hover:text-foreground hover:bg-muted transition-colors shrink-0 disabled:opacity-30 disabled:cursor-not-allowed;
}
.viewer-sep {
@apply w-px h-5 mx-1 bg-border shrink-0;
}
/* ── Settings typography scale ──────────────────────────────
Change these once to update every settings panel at once.
────────────────────────────────────────────────────────────── */
.settings-title {
@apply font-serif font-semibold text-foreground text-2xl tracking-tight;
}
.settings-subtitle {
@apply text-sm text-muted-foreground mt-1;
}
.settings-group-label {
@apply text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-3;
}
.settings-label {
@apply text-sm font-medium text-foreground;
}
.settings-hint {
@apply text-xs text-muted-foreground mt-0.5;
}
.settings-value {
@apply text-sm font-medium tabular-nums text-foreground;
}
/* ── Settings form controls ─────────────────────────────────
Use .input-field on and .select-field on