Spaces:
Sleeping
Sleeping
| @import "tailwindcss"; | |
| /* ------------------------------------------------------------------ */ | |
| /* MedASR Bench — "Clinical Instrument" token system */ | |
| /* ------------------------------------------------------------------ */ | |
| :root { | |
| color-scheme: light; | |
| /* Palette — light "precision instrument": cool paper-white surfaces, ink | |
| text, deep violet accent (user-picked hue; deepened for light-mode | |
| contrast: oklch(0.50 0.17 290) = 6.1:1 on --bg). Built in OKLCH; all | |
| small-text pairings clear WCAG 4.5:1. Saturated hues are reserved for | |
| meaning (accent/warn/crit). NO green — repeatedly rejected by the user. */ | |
| --bg: #f9f9fb; | |
| --surface: #ffffff; | |
| --surface-2: #eeeef2; | |
| --line: rgba(36, 36, 60, 0.13); | |
| --text: #24242f; | |
| --muted: #62626f; | |
| --accent: #654abb; /* deep violet — sparingly */ | |
| --warn: #a15e00; /* contamination / caution only */ | |
| --crit: #c53637; /* critical / error only */ | |
| /* Derived tints — single-source: everything mixes from the tokens above */ | |
| --accent-dim: color-mix(in srgb, var(--accent) 12%, transparent); | |
| --warn-dim: color-mix(in srgb, var(--warn) 12%, transparent); | |
| --crit-dim: color-mix(in srgb, var(--crit) 10%, transparent); | |
| --grid-ink: rgba(36, 36, 80, 0.045); | |
| --grid-ink-major: rgba(36, 36, 80, 0.065); | |
| } | |
| @theme inline { | |
| /* Colors → Tailwind utilities (bg-bg, text-muted, border-line, …) */ | |
| --color-bg: var(--bg); | |
| --color-surface: var(--surface); | |
| --color-surface-2: var(--surface-2); | |
| --color-line: var(--line); | |
| --color-text: var(--text); | |
| --color-muted: var(--muted); | |
| --color-accent: var(--accent); | |
| --color-warn: var(--warn); | |
| --color-crit: var(--crit); | |
| --color-accent-dim: var(--accent-dim); | |
| --color-warn-dim: var(--warn-dim); | |
| --color-crit-dim: var(--crit-dim); | |
| /* Fonts → font-display / font-body / font-mono utilities. | |
| The var() chain resolves to next/font variables set on <html>. */ | |
| --font-display: var(--font-display), "Instrument Serif", Georgia, serif; | |
| --font-body: var(--font-body), "Be Vietnam Pro", system-ui, sans-serif; | |
| --font-sans: var(--font-body), "Be Vietnam Pro", system-ui, sans-serif; | |
| --font-mono: var(--font-mono), "IBM Plex Mono", ui-monospace, SFMono-Regular, | |
| monospace; | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Base + atmosphere: graph-paper micro-grid + scanline layer */ | |
| /* ------------------------------------------------------------------ */ | |
| html { | |
| background-color: var(--bg); | |
| } | |
| body { | |
| /* solid color lives on <html>; body stays transparent so the fixed | |
| negative-z ambient glow layers (AmbientEffects) shine through the grid */ | |
| background-color: transparent; | |
| color: var(--text); | |
| font-family: var(--font-body), "Be Vietnam Pro", system-ui, sans-serif; | |
| /* graph-paper grid: 140px major rhythm over the 28px minor micro-grid */ | |
| background-image: linear-gradient(var(--grid-ink-major) 1px, transparent 1px), | |
| linear-gradient(90deg, var(--grid-ink-major) 1px, transparent 1px), | |
| linear-gradient(var(--grid-ink) 1px, transparent 1px), | |
| linear-gradient(90deg, var(--grid-ink) 1px, transparent 1px); | |
| background-size: | |
| 140px 140px, | |
| 140px 140px, | |
| 28px 28px, | |
| 28px 28px; | |
| -webkit-font-smoothing: antialiased; | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Grain texture — subtle film noise for tactile depth */ | |
| /* ------------------------------------------------------------------ */ | |
| body::before { | |
| content: ""; | |
| position: fixed; | |
| inset: 0; | |
| z-index: 29; | |
| pointer-events: none; | |
| opacity: 0.02; | |
| background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); | |
| } | |
| /* scanline veil — fixed, non-interactive, layered above grain */ | |
| body::after { | |
| content: ""; | |
| position: fixed; | |
| inset: 0; | |
| z-index: 30; | |
| pointer-events: none; | |
| background: repeating-linear-gradient( | |
| to bottom, | |
| color-mix(in srgb, var(--text) 1.2%, transparent) 0px, | |
| color-mix(in srgb, var(--text) 1.2%, transparent) 1px, | |
| transparent 1px, | |
| transparent 3px | |
| ); | |
| } | |
| ::selection { | |
| background: var(--accent-dim); | |
| color: var(--text); | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Ambient light — fixed phosphor glow washes behind all content */ | |
| /* (rendered by components/ui/AmbientEffects; GPU-cheap transform drift) */ | |
| /* ------------------------------------------------------------------ */ | |
| @keyframes ambient-drift-a { | |
| 0%, | |
| 100% { | |
| transform: translate3d(0, 0, 0) scale(1); | |
| } | |
| 50% { | |
| transform: translate3d(4%, 3%, 0) scale(1.08); | |
| } | |
| } | |
| @keyframes ambient-drift-b { | |
| 0%, | |
| 100% { | |
| transform: translate3d(0, 0, 0) scale(1); | |
| } | |
| 50% { | |
| transform: translate3d(-3%, -4%, 0) scale(1.06); | |
| } | |
| } | |
| .ambient-glow { | |
| position: absolute; | |
| pointer-events: none; | |
| will-change: transform; | |
| } | |
| /* top-center wash — the room's key light */ | |
| .ambient-glow-top { | |
| top: -32vh; | |
| left: -12vw; | |
| right: -12vw; | |
| height: 78vh; | |
| background: radial-gradient( | |
| ellipse 55% 55% at 50% 45%, | |
| color-mix(in srgb, var(--accent) 9%, transparent), | |
| transparent 70% | |
| ); | |
| animation: ambient-drift-a 70s ease-in-out infinite; | |
| } | |
| /* lower-right fill — faint counter-glow */ | |
| .ambient-glow-corner { | |
| right: -22vw; | |
| bottom: -30vh; | |
| width: 72vw; | |
| height: 75vh; | |
| background: radial-gradient( | |
| ellipse 50% 50% at 55% 55%, | |
| color-mix(in srgb, var(--accent) 5.5%, transparent), | |
| transparent 70% | |
| ); | |
| animation: ambient-drift-b 90s ease-in-out infinite; | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Glass morphism — translucent surfaces tuned to the lifted palette */ | |
| /* ------------------------------------------------------------------ */ | |
| /* layered as components so Tailwind utilities (bg-surface/55 …) can | |
| override the surface opacity per-instance */ | |
| @layer components { | |
| /* veil only: translucent surface + blur, no border (compose freely) */ | |
| .glass-veil { | |
| background: color-mix(in srgb, var(--surface) 66%, transparent); | |
| -webkit-backdrop-filter: blur(16px) saturate(1.2); | |
| backdrop-filter: blur(16px) saturate(1.2); | |
| } | |
| /* full glass panel: veil + hairline + machined top-edge relief */ | |
| .glass { | |
| background: color-mix(in srgb, var(--surface) 72%, transparent); | |
| -webkit-backdrop-filter: blur(14px) saturate(1.2); | |
| backdrop-filter: blur(14px) saturate(1.2); | |
| border: 1px solid var(--line); | |
| box-shadow: inset 0 1px 0 color-mix(in srgb, var(--text) 6%, transparent); | |
| } | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Hairline utilities (1px --line rules, the only "shadows" we use) */ | |
| /* ------------------------------------------------------------------ */ | |
| .hairline { | |
| border: 1px solid var(--line); | |
| /* machined top-edge relief — the only "shadow" beyond hairlines */ | |
| box-shadow: inset 0 1px 0 color-mix(in srgb, var(--text) 4%, transparent); | |
| } | |
| .hairline-t { | |
| border-top: 1px solid var(--line); | |
| } | |
| .hairline-b { | |
| border-bottom: 1px solid var(--line); | |
| } | |
| .hairline-l { | |
| border-left: 1px solid var(--line); | |
| } | |
| .hairline-r { | |
| border-right: 1px solid var(--line); | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Spring animations — physics-based motion */ | |
| /* ------------------------------------------------------------------ */ | |
| @keyframes spring-in { | |
| from { | |
| opacity: 0; | |
| transform: scale(0.95) translateY(12px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: scale(1) translateY(0); | |
| } | |
| } | |
| @keyframes spring-up { | |
| from { | |
| opacity: 0; | |
| transform: translateY(20px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| @keyframes soft-appear { | |
| from { | |
| opacity: 0; | |
| transform: translateY(8px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| /* Spring-based entrance animations */ | |
| .spring-in { | |
| animation: spring-in 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both; | |
| } | |
| .spring-up { | |
| animation: spring-up 0.55s cubic-bezier(0.22, 1, 0.36, 1) both; | |
| } | |
| .soft-appear { | |
| animation: soft-appear 0.4s cubic-bezier(0.16, 1, 0.3, 1) both; | |
| } | |
| /* Improved stagger with spring feel */ | |
| .stagger-spring > * { | |
| animation: spring-up 0.5s cubic-bezier(0.22, 1, 0.36, 1) both; | |
| } | |
| .stagger-spring > :nth-child(1) { animation-delay: 0ms; } | |
| .stagger-spring > :nth-child(2) { animation-delay: 60ms; } | |
| .stagger-spring > :nth-child(3) { animation-delay: 120ms; } | |
| .stagger-spring > :nth-child(4) { animation-delay: 180ms; } | |
| .stagger-spring > :nth-child(5) { animation-delay: 240ms; } | |
| .stagger-spring > :nth-child(6) { animation-delay: 300ms; } | |
| .stagger-spring > :nth-child(7) { animation-delay: 360ms; } | |
| .stagger-spring > :nth-child(8) { animation-delay: 420ms; } | |
| /* ------------------------------------------------------------------ */ | |
| /* Spotlight border effect — card illumination on hover */ | |
| /* ------------------------------------------------------------------ */ | |
| .spotlight-card { | |
| position: relative; | |
| isolation: isolate; | |
| transition: border-color 0.3s ease, box-shadow 0.3s ease; | |
| } | |
| .spotlight-card::before { | |
| content: ""; | |
| position: absolute; | |
| inset: 0; | |
| border-radius: inherit; | |
| background: radial-gradient( | |
| 500px circle at var(--mouse-x, 50%) var(--mouse-y, 50%), | |
| color-mix(in srgb, var(--accent) 12%, transparent), | |
| transparent 40% | |
| ); | |
| opacity: 0; | |
| transition: opacity 0.4s ease; | |
| z-index: -1; | |
| pointer-events: none; | |
| } | |
| .spotlight-card:hover { | |
| border-color: color-mix(in srgb, var(--accent) 25%, transparent); | |
| box-shadow: inset 0 1px 0 color-mix(in srgb, var(--accent) 8%, transparent); | |
| } | |
| .spotlight-card:hover::before { | |
| opacity: 1; | |
| } | |
| /* Spotlight row for tables. | |
| IMPORTANT: no ::before/::after on this class — it sits on <tr>, and a | |
| generated box on a table row gets wrapped in an ANONYMOUS CELL, silently | |
| shifting every real cell one column right of the headers. The hover | |
| sweep is painted as the row's own background instead. */ | |
| .spotlight-row { | |
| transition: background-color 0.2s ease; | |
| } | |
| .spotlight-row:hover { | |
| background-color: var(--surface-2); | |
| background-image: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| color-mix(in srgb, var(--accent) 4%, transparent) 50%, | |
| transparent 100% | |
| ); | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Tactile button states */ | |
| /* ------------------------------------------------------------------ */ | |
| .tactile { | |
| transition: transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1), | |
| background-color 0.2s ease, | |
| border-color 0.2s ease; | |
| } | |
| .tactile:active { | |
| transform: scale(0.975) translateY(1px); | |
| } | |
| .tactile:hover:not(:disabled) { | |
| background-color: var(--surface-2); | |
| } | |
| /* Interactive elements with subtle lift */ | |
| .hover-lift { | |
| transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1), | |
| box-shadow 0.2s ease; | |
| } | |
| .hover-lift:hover { | |
| transform: translateY(-2px); | |
| box-shadow: | |
| 0 4px 14px rgba(20, 20, 45, 0.1), | |
| inset 0 1px 0 color-mix(in srgb, var(--text) 4%, transparent); | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Accent glow effects */ | |
| /* ------------------------------------------------------------------ */ | |
| .glow-accent-subtle { | |
| box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 10%, transparent); | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Edge accent bar — vertical phosphor line */ | |
| /* ------------------------------------------------------------------ */ | |
| .edge-accent { | |
| position: relative; | |
| } | |
| .edge-accent::before { | |
| content: ""; | |
| position: absolute; | |
| left: 0; | |
| top: 0; | |
| bottom: 0; | |
| width: 2px; | |
| background: linear-gradient( | |
| to bottom, | |
| transparent, | |
| var(--accent) 20%, | |
| var(--accent) 80%, | |
| transparent | |
| ); | |
| opacity: 0.6; | |
| } | |
| /* Mono numerals everywhere data lives */ | |
| .num { | |
| font-family: var(--font-mono), "IBM Plex Mono", ui-monospace, monospace; | |
| font-variant-numeric: tabular-nums; | |
| } | |
| .tabular { | |
| font-variant-numeric: tabular-nums; | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Keyframes */ | |
| /* ------------------------------------------------------------------ */ | |
| @keyframes rise { | |
| from { | |
| opacity: 0; | |
| transform: translateY(14px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| /* pair with pathLength={1} + stroke-dasharray: 1 on an SVG path */ | |
| @keyframes drawLine { | |
| from { | |
| stroke-dashoffset: 1; | |
| } | |
| to { | |
| stroke-dashoffset: 0; | |
| } | |
| } | |
| /* ambient ECG sweep: a short bright tracer cycling over the dim base path */ | |
| @keyframes sweep { | |
| from { | |
| stroke-dashoffset: 1; | |
| } | |
| to { | |
| stroke-dashoffset: 0; | |
| } | |
| } | |
| @keyframes shimmer { | |
| from { | |
| background-position: -200% 0; | |
| } | |
| to { | |
| background-position: 200% 0; | |
| } | |
| } | |
| @keyframes pulseDot { | |
| 0%, | |
| 100% { | |
| opacity: 1; | |
| transform: scale(1); | |
| } | |
| 50% { | |
| opacity: 0.35; | |
| transform: scale(0.78); | |
| } | |
| } | |
| @keyframes scaleInX { | |
| from { | |
| transform: scaleX(0); | |
| } | |
| to { | |
| transform: scaleX(1); | |
| } | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Motion helpers — one orchestrated load per route */ | |
| /* ------------------------------------------------------------------ */ | |
| /* stagger container: children rise with 55ms steps */ | |
| .stagger > * { | |
| animation: rise 0.6s cubic-bezier(0.22, 1, 0.36, 1) both; | |
| } | |
| .stagger > :nth-child(1) { | |
| animation-delay: 0ms; | |
| } | |
| .stagger > :nth-child(2) { | |
| animation-delay: 55ms; | |
| } | |
| .stagger > :nth-child(3) { | |
| animation-delay: 110ms; | |
| } | |
| .stagger > :nth-child(4) { | |
| animation-delay: 165ms; | |
| } | |
| .stagger > :nth-child(5) { | |
| animation-delay: 220ms; | |
| } | |
| .stagger > :nth-child(6) { | |
| animation-delay: 275ms; | |
| } | |
| .stagger > :nth-child(7) { | |
| animation-delay: 330ms; | |
| } | |
| .stagger > :nth-child(8) { | |
| animation-delay: 385ms; | |
| } | |
| .stagger > :nth-child(9) { | |
| animation-delay: 440ms; | |
| } | |
| .stagger > :nth-child(10) { | |
| animation-delay: 495ms; | |
| } | |
| .stagger > :nth-child(11) { | |
| animation-delay: 550ms; | |
| } | |
| .stagger > :nth-child(12) { | |
| animation-delay: 605ms; | |
| } | |
| /* manual stagger steps for non-sibling layouts */ | |
| .delay-1 { | |
| animation-delay: 55ms; | |
| } | |
| .delay-2 { | |
| animation-delay: 110ms; | |
| } | |
| .delay-3 { | |
| animation-delay: 165ms; | |
| } | |
| .delay-4 { | |
| animation-delay: 220ms; | |
| } | |
| /* skeleton block: surface placeholder swept by the shimmer keyframes */ | |
| .skeleton { | |
| position: relative; | |
| overflow: hidden; | |
| border-radius: 2px; | |
| background-color: var(--surface-2); | |
| background-image: linear-gradient( | |
| 100deg, | |
| transparent 40%, | |
| color-mix(in srgb, var(--text) 7%, transparent) 50%, | |
| transparent 60% | |
| ); | |
| background-size: 200% 100%; | |
| animation: shimmer 1.8s linear infinite; | |
| } | |
| /* shimmering surface for status=running chips */ | |
| .chip-shimmer { | |
| background-image: linear-gradient( | |
| 100deg, | |
| color-mix(in srgb, var(--accent) 7%, transparent) 40%, | |
| color-mix(in srgb, var(--accent) 22%, transparent) 50%, | |
| color-mix(in srgb, var(--accent) 7%, transparent) 60% | |
| ); | |
| background-size: 200% 100%; | |
| animation: shimmer 2.4s linear infinite; | |
| } | |
| .pulse-dot { | |
| animation: pulseDot 1.4s ease-in-out infinite; | |
| } | |
| .draw-line { | |
| stroke-dasharray: 1; | |
| animation: drawLine 1.4s cubic-bezier(0.4, 0, 0.2, 1) 0.15s both; | |
| } | |
| /* pair with pathLength={1}: 6%-long phosphor tracer, ~7s per pass */ | |
| .pulse-sweep { | |
| stroke-dasharray: 0.06 0.94; | |
| animation: sweep 7s linear infinite; | |
| } | |
| /* CI whisker draw-in: the micro-bar sweeps open left → right once */ | |
| .ci-draw { | |
| transform-origin: left center; | |
| animation: scaleInX 0.6s cubic-bezier(0.22, 1, 0.36, 1) both; | |
| } | |
| /* NOTE: scroll-driven entrances (animation-timeline: view()) were tried | |
| and removed — with fill-mode both, content whose timeline binds to the | |
| wrong scroll container (e.g. rows inside overflow-x-auto) can be stuck | |
| at opacity 0 forever. Entrances are load-orchestrated only. */ | |
| /* ------------------------------------------------------------------ */ | |
| /* Scroll-triggered animations (Intersection Observer based) */ | |
| /* ------------------------------------------------------------------ */ | |
| /* Base scroll animation classes */ | |
| .scroll-animate { | |
| opacity: 0; | |
| transform: translateY(24px); | |
| transition: opacity 0.5s cubic-bezier(0.22, 1, 0.36, 1), | |
| transform 0.5s cubic-bezier(0.22, 1, 0.36, 1); | |
| } | |
| .scroll-animate.in-view { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| /* Scroll scale animation */ | |
| .scroll-scale { | |
| opacity: 0; | |
| transform: scale(0.95); | |
| transition: opacity 0.5s cubic-bezier(0.22, 1, 0.36, 1), | |
| transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| } | |
| .scroll-scale.in-view { | |
| opacity: 1; | |
| transform: scale(1); | |
| } | |
| /* Scroll slide animations */ | |
| .scroll-slide-left { | |
| opacity: 0; | |
| transform: translateX(-24px); | |
| transition: opacity 0.4s cubic-bezier(0.22, 1, 0.36, 1), | |
| transform 0.4s cubic-bezier(0.22, 1, 0.36, 1); | |
| } | |
| .scroll-slide-left.in-view { | |
| opacity: 1; | |
| transform: translateX(0); | |
| } | |
| .scroll-slide-right { | |
| opacity: 0; | |
| transform: translateX(24px); | |
| transition: opacity 0.4s cubic-bezier(0.22, 1, 0.36, 1), | |
| transform 0.4s cubic-bezier(0.22, 1, 0.36, 1); | |
| } | |
| .scroll-slide-right.in-view { | |
| opacity: 1; | |
| transform: translateX(0); | |
| } | |
| .scroll-slide-down { | |
| opacity: 0; | |
| transform: translateY(-24px); | |
| transition: opacity 0.4s cubic-bezier(0.22, 1, 0.36, 1), | |
| transform 0.4s cubic-bezier(0.22, 1, 0.36, 1); | |
| } | |
| .scroll-slide-down.in-view { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| /* Scroll fade animation */ | |
| .scroll-fade { | |
| opacity: 0; | |
| transition: opacity 0.4s ease-out; | |
| } | |
| .scroll-fade.in-view { | |
| opacity: 1; | |
| } | |
| /* Stagger children on scroll */ | |
| .scroll-stagger > * { | |
| opacity: 0; | |
| transform: translateY(16px); | |
| transition: opacity 0.4s ease-out, | |
| transform 0.4s cubic-bezier(0.22, 1, 0.36, 1); | |
| } | |
| .scroll-stagger.in-view > *:nth-child(1) { opacity: 1; transform: translateY(0); transition-delay: 0ms; } | |
| .scroll-stagger.in-view > *:nth-child(2) { opacity: 1; transform: translateY(0); transition-delay: 60ms; } | |
| .scroll-stagger.in-view > *:nth-child(3) { opacity: 1; transform: translateY(0); transition-delay: 120ms; } | |
| .scroll-stagger.in-view > *:nth-child(4) { opacity: 1; transform: translateY(0); transition-delay: 180ms; } | |
| .scroll-stagger.in-view > *:nth-child(5) { opacity: 1; transform: translateY(0); transition-delay: 240ms; } | |
| .scroll-stagger.in-view > *:nth-child(6) { opacity: 1; transform: translateY(0); transition-delay: 300ms; } | |
| .scroll-stagger.in-view > *:nth-child(7) { opacity: 1; transform: translateY(0); transition-delay: 360ms; } | |
| .scroll-stagger.in-view > *:nth-child(8) { opacity: 1; transform: translateY(0); transition-delay: 420ms; } | |
| /* ------------------------------------------------------------------ */ | |
| /* Micro-interactions */ | |
| /* ------------------------------------------------------------------ */ | |
| /* ------------------------------------------------------------------ */ | |
| /* Card depth variations */ | |
| /* ------------------------------------------------------------------ */ | |
| .depth-1 { | |
| box-shadow: 0 1px 3px rgba(20, 20, 45, 0.06); | |
| } | |
| .depth-2 { | |
| box-shadow: 0 2px 10px rgba(20, 20, 45, 0.07); | |
| } | |
| .depth-3 { | |
| box-shadow: | |
| 0 8px 28px rgba(20, 20, 45, 0.09), | |
| 0 2px 6px rgba(20, 20, 45, 0.05); | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Full-bleed breakout — a block wider than the page container, */ | |
| /* centered on the viewport (parent must be a centered max-w column) */ | |
| /* ------------------------------------------------------------------ */ | |
| @media (min-width: 80rem) { | |
| .breakout-wide { | |
| --breakout-w: min(100vw - 5rem, 85rem); | |
| width: var(--breakout-w); | |
| margin-left: calc(50% - var(--breakout-w) / 2); | |
| } | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Nav sweep — a phosphor tracer riding the sticky nav's bottom */ | |
| /* hairline; the instrument is always on */ | |
| /* ------------------------------------------------------------------ */ | |
| .nav-sweep { | |
| position: absolute; | |
| inset-inline: 0; | |
| bottom: -1px; | |
| height: 1px; | |
| overflow: hidden; | |
| pointer-events: none; | |
| } | |
| .nav-sweep::before { | |
| content: ""; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| height: 100%; | |
| width: 140px; | |
| background: linear-gradient( | |
| 90deg, | |
| transparent, | |
| color-mix(in srgb, var(--accent) 55%, transparent), | |
| transparent | |
| ); | |
| animation: nav-sweep 9s linear infinite; | |
| } | |
| @keyframes nav-sweep { | |
| from { | |
| transform: translateX(-140px); | |
| } | |
| to { | |
| transform: translateX(100vw); | |
| } | |
| } | |
| /* ------------------------------------------------------------------ */ | |
| /* Reduced motion: everything settles instantly */ | |
| /* ------------------------------------------------------------------ */ | |
| @media (prefers-reduced-motion: reduce) { | |
| *, | |
| *::before, | |
| *::after { | |
| animation-duration: 0.001ms ; | |
| animation-delay: 0ms ; | |
| animation-iteration-count: 1 ; | |
| animation-timeline: auto ; | |
| transition-duration: 0.001ms ; | |
| scroll-behavior: auto ; | |
| } | |
| /* ambient effects are pure ambience — remove them when motion is reduced */ | |
| .pulse-sweep { | |
| visibility: hidden; | |
| } | |
| .nav-sweep { | |
| display: none; | |
| } | |
| /* ambient glow drift stops; the static light wash may remain */ | |
| .ambient-glow { | |
| animation: none; | |
| will-change: auto; | |
| } | |
| /* skeletons settle to a static placeholder */ | |
| .skeleton { | |
| animation: none; | |
| background-image: none; | |
| } | |
| /* grain and scanline remain as they don't animate */ | |
| body::before, | |
| body::after { | |
| display: none; | |
| } | |
| /* spotlight effects collapse to static */ | |
| .spotlight-card::before { | |
| display: none; | |
| } | |
| /* hover lifts settle */ | |
| .hover-lift:hover { | |
| transform: none; | |
| } | |
| /* glows collapse */ | |
| .glow-accent-subtle { | |
| box-shadow: none; | |
| } | |
| /* scroll animations resolve immediately */ | |
| .scroll-animate, | |
| .scroll-scale, | |
| .scroll-slide-left, | |
| .scroll-slide-right, | |
| .scroll-slide-down, | |
| .scroll-fade { | |
| opacity: 1; | |
| transform: none; | |
| } | |
| .scroll-stagger > * { | |
| opacity: 1; | |
| transform: none; | |
| } | |
| } | |