diff --git a/apps/showcase/output/contract-checklist.md b/apps/showcase/output/contract-checklist.md index bedbf31..c56ae39 100644 --- a/apps/showcase/output/contract-checklist.md +++ b/apps/showcase/output/contract-checklist.md @@ -4,6 +4,8 @@ - Unknown vl-* attrs: **0** - Deprecated vl-* attrs: **0** - Broken #anchors: **0** +- Home anchor motion violations: **0** +- Home scene frame motion violations: **0** ## Per-page status @@ -11,244 +13,342 @@ - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/color/ambient-shadows.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/color/color-palette.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/color/color-system.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/color/design-tokens.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/color/token-spotlight.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/color/tonal-stacking.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/color/tonal-tiers.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/components/api-design-catalog.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/components/buttons.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/components/component-lab.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/components/component-wizard.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/components/design-playground.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/components/forms.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/components/icons.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/core/about.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/core/landing.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/demo/impossible.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/integrations/gsap-anime.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/library/gallery.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/library/index.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/3d-explorer.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/3d-rotation.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/api-motion-catalog.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/interactions.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/kinetic-cards.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/kinetic-motion.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/motion-compiler-demo.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/motion-extended.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/motion-playground.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/motion-principles.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/scale-shift.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/scroll-driven-demos.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/motion/zero-js-motion.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/scenes/scene-creator.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/scenes/scene-features.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/scenes/scene-hero.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/scenes/scene-story.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/scenes/scroll-reveal.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/tools/accessibility.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/tools/architecture.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/tools/brand-voice.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/tools/contrast-tool.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/tools/converter.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/tools/index.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/tools/system-modules.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/typography/typography-composition.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/typography/typography-spec.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none ### OK - `pages/typography/typography.html` - Unknown vl-* attrs: none - Deprecated vl-* attrs: none - Broken #anchors: none +- Home anchor motion: none +- Home scene frame motion: none diff --git a/apps/showcase/public/css/01-tokens.css b/apps/showcase/public/css/01-tokens.css index bedae58..33577ae 100644 --- a/apps/showcase/public/css/01-tokens.css +++ b/apps/showcase/public/css/01-tokens.css @@ -256,6 +256,61 @@ --vl-ease-elastic: cubic-bezier(0.68, -0.55, 0.265, 1.55); --vl-ease-smooth-out: cubic-bezier(0, 0.55, 0.45, 1); + /* --- 2026 Platform easing (Material 3 Expressive / Google I/O 2026) --- */ + --vl-ease-spring-expressive: cubic-bezier(0.175, 0.885, 0.32, 1.275); + --vl-ease-spring-snappy: cubic-bezier(0.34, 1.8, 0.64, 1); + --vl-ease-decelerate: cubic-bezier(0.0, 0.0, 0.2, 1); + --vl-ease-accelerate: cubic-bezier(0.4, 0.0, 1.0, 1.0); + --vl-ease-emphasized: cubic-bezier(0.2, 0.0, 0, 1.0); + --vl-duration-express: 200ms; + --vl-duration-emphasized: 500ms; + + /* --- Wide-gamut accent (display-p3 for P3-capable displays) --- */ + --vl-color-p3-primary: color(display-p3 0.498 0.525 0.407); + --vl-color-p3-accent: color(display-p3 0.361 0.376 0.298); + --vl-color-p3-vivid: color(display-p3 0.55 0.62 0.38); + + /* --- Liquid glass (Apple 2026 — enhanced backdrop layer) --- */ + --vl-liquid-glass-bg: color-mix(in oklch, var(--vl-bg-surface) 58%, transparent); + --vl-liquid-glass-blur: 28px; + --vl-liquid-glass-saturate: 1.6; + --vl-liquid-glass-border: color-mix(in oklch, white 38%, transparent); + --vl-liquid-glass-shadow: + 0 8px 32px color-mix(in oklch, var(--vl-color-primary) 12%, transparent), + inset 0 1px 0 color-mix(in oklch, white 28%, transparent); + + /* --- AI state tokens (streaming / generation patterns) --- */ + --vl-ai-shimmer-start: color-mix(in oklch, var(--vl-bg-surface) 96%, transparent); + --vl-ai-shimmer-mid: color-mix(in oklch, var(--vl-color-primary) 9%, var(--vl-bg-surface)); + --vl-ai-shimmer-end: color-mix(in oklch, var(--vl-bg-surface) 96%, transparent); + --vl-ai-stream-color: color-mix(in oklch, var(--vl-color-primary) 55%, transparent); + --vl-ai-glow: 0 0 0 1px color-mix(in oklch, var(--vl-color-primary) 22%, transparent), + 0 0 20px color-mix(in oklch, var(--vl-color-primary) 14%, transparent); + --vl-ai-duration: 1.8s; + + /* --- CSS Carousel (::scroll-marker / ::scroll-button — Chrome 135+) --- */ + --vl-carousel-marker-size: 0.5rem; + --vl-carousel-marker-gap: 0.375rem; + --vl-carousel-marker-color: var(--vl-border-strong); + --vl-carousel-marker-active: var(--vl-color-primary); + --vl-carousel-btn-size: 2.5rem; + --vl-carousel-item-width: min(80vw, 20rem); + --vl-carousel-gap: var(--vl-space-md); + + /* --- CSS Anchor Positioning (Chrome 125+ / Safari 18.2+) --- */ + --vl-anchor-gap: 0.375rem; + --vl-tooltip-max-width: 16rem; + --vl-float-min-width: 10rem; + + /* --- Edge-to-edge (safe-area-max-inset — Chrome 135+) --- */ + --vl-safe-top: env(safe-area-inset-top, 0px); + --vl-safe-bottom: env(safe-area-inset-bottom, 0px); + --vl-safe-left: env(safe-area-inset-left, 0px); + --vl-safe-right: env(safe-area-inset-right, 0px); + + /* --- Dynamic range (HDR) --- */ + --vl-dynamic-range: standard; + color-scheme: light; } diff --git a/apps/showcase/public/css/02-layout.css b/apps/showcase/public/css/02-layout.css index c5bbcbe..1e44053 100644 --- a/apps/showcase/public/css/02-layout.css +++ b/apps/showcase/public/css/02-layout.css @@ -457,4 +457,93 @@ align-self: start; z-index: var(--vl-z-base); } + + /* ========================================================================= + READING FLOW (Chrome 137+ — CSS reading-flow) + Ensures keyboard tab order follows the visual reading order in flex/grid + layouts, not the DOM source order. Critical for accessibility in + visually-reordered layouts. + @see https://developer.chrome.com/blog/reading-flow + ========================================================================= */ + @supports (reading-flow: normal) { + .vl-grid[vl-reading="rows"], + [vl-reading="rows"] { + reading-flow: grid-rows; + } + + .vl-grid[vl-reading="columns"], + [vl-reading="columns"] { + reading-flow: grid-columns; + } + + .vl-stack[vl-reading="visual"], + .vl-flex[vl-reading="visual"], + [vl-reading="visual"] { + reading-flow: flex-visual; + } + + .vl-stack[vl-reading="flow"], + .vl-flex[vl-reading="flow"], + [vl-reading="flow"] { + reading-flow: flex-flow; + } + + /* Source-order override (useful for decorative reordering) */ + [vl-reading="source"] { + reading-flow: source-order; + } + } + + /* ========================================================================= + EDGE-TO-EDGE (safe-area-max-inset — Chrome 135+) + Performant edge-to-edge layouts that never move during scroll. + ========================================================================= */ + + /** + * Full-bleed section that respects both safe-area dynamic insets AND the + * maximum possible safe-area for performant, non-reflowing layouts. + */ + .vl-edge-to-edge { + padding-inline: max(var(--vl-container-gutter), var(--vl-safe-left, env(safe-area-inset-left, 0px))); + padding-inline-end: max(var(--vl-container-gutter), var(--vl-safe-right, env(safe-area-inset-right, 0px))); + } + + .vl-edge-to-edge--block { + padding-block-start: max(var(--vl-space-md), var(--vl-safe-top, env(safe-area-inset-top, 0px))); + padding-block-end: max(var(--vl-space-md), var(--vl-safe-bottom, env(safe-area-inset-bottom, 0px))); + } + + /* ========================================================================= + LIQUID GLASS SURFACE (Apple 2026 design direction) + A backdrop-filter surface with depth and luminance. Pairs with vl-scene. + ========================================================================= */ + .vl-glass--liquid { + background: var(--vl-liquid-glass-bg); + backdrop-filter: + blur(var(--vl-liquid-glass-blur)) + saturate(var(--vl-liquid-glass-saturate)); + -webkit-backdrop-filter: + blur(var(--vl-liquid-glass-blur)) + saturate(var(--vl-liquid-glass-saturate)); + border: 1px solid var(--vl-liquid-glass-border); + box-shadow: var(--vl-liquid-glass-shadow); + } + + /* ========================================================================= + HDR CONTENT CONTROL (Chrome 135+ — dynamic-range-limit) + Prevent overbright HDR content from dominating the composition. + ========================================================================= */ + @supports (dynamic-range-limit: standard) { + [vl-hdr="constrained"] { + dynamic-range-limit: constrained-high; + } + + [vl-hdr="standard"] { + dynamic-range-limit: standard; + } + + [vl-hdr="auto"] { + dynamic-range-limit: no-limit; + } + } } diff --git a/apps/showcase/public/css/03b-motion-extended.css b/apps/showcase/public/css/03b-motion-extended.css index db74251..d620bf9 100644 --- a/apps/showcase/public/css/03b-motion-extended.css +++ b/apps/showcase/public/css/03b-motion-extended.css @@ -2337,4 +2337,238 @@ animation-timeline: view(); animation-range: entry 10% entry 60%; } + + /* ========================================================================= + 2026 PLATFORM MOTION — Google I/O 2026 · Apple · Material 3 Expressive + New presets leveraging CSS shape(), spring-expressive easing, + liquid glass entrance, and AI streaming states. + ========================================================================= */ + + /* --- Material 3 Expressive spring (vl-effect="spring-express") --- + Asymmetric overshoot + settle. The "express" spring is snappier than + the existing spring-up, designed for UI confirmations and taps. + ------------------------------------------------------------------- */ + @keyframes vl-spring-express { + 0% { opacity: 0; transform: scale(0.82) translateY(1rem); } + 45% { opacity: 1; transform: scale(1.04) translateY(-0.18rem); } + 65% { transform: scale(0.98) translateY(0.05rem); } + 82% { transform: scale(1.01); } + 100% { opacity: 1; transform: scale(1) translateY(0); } + } + + [vl-effect="spring-express"] { + animation: vl-spring-express var(--vl-duration-express, 200ms) var(--vl-ease-spring-expressive, cubic-bezier(0.175, 0.885, 0.32, 1.275)) both; + + @media (prefers-reduced-motion: reduce) { + animation: none; + opacity: 1; + transform: none; + } + } + + /* --- Liquid glass entrance (Apple 2026 — vl-effect="liquid-in") --- + Saturate + blur dissolve with a slight scale. Pairs with .vl-glass--liquid. + ------------------------------------------------------------------- */ + @keyframes vl-liquid-in { + 0% { + opacity: 0; + filter: blur(14px) saturate(0.4); + transform: scale(0.94); + } + + 55% { + filter: blur(3px) saturate(0.9); + } + + 100% { + opacity: 1; + filter: blur(0) saturate(1); + transform: scale(1); + } + } + + [vl-effect="liquid-in"] { + animation: vl-liquid-in var(--vl-duration-slow, 500ms) var(--vl-ease-emphasized, cubic-bezier(0.2, 0, 0, 1)) both; + + @media (prefers-reduced-motion: reduce) { + animation: none; + opacity: 1; + filter: none; + transform: none; + } + } + + /* --- CSS shape() clip reveal (Chrome 135+ — vl-effect="shape-reveal") --- + Organic left-to-right clip wipe using the responsive shape() function. + Falls back silently; content remains visible without the clip animation. + ------------------------------------------------------------------- */ + @supports (clip-path: shape(from 0% 0%, line to 100% 0%, line to 100% 100%, line to 0% 100%)) { + @keyframes vl-shape-reveal { + from { + clip-path: shape(from 0% 0%, line to 0% 0%, line to 0% 100%, line to 0% 100%); + opacity: 0.7; + } + + to { + clip-path: shape(from 0% 0%, line to 100% 0%, line to 100% 100%, line to 0% 100%); + opacity: 1; + } + } + + @keyframes vl-shape-reveal-organic { + from { + clip-path: shape( + from 0% 0%, + line to 0% 0%, + curve to 0% 60% via 2% 30%, 1% 45%, + line to 0% 100%, + line to 0% 100% + ); + } + + 50% { + clip-path: shape( + from 0% 0%, + line to 60% 0%, + curve to 55% 55% via 65% 10%, 62% 35%, + curve to 60% 100% via 58% 75%, 62% 90%, + line to 0% 100% + ); + } + + to { + clip-path: shape( + from 0% 0%, + line to 100% 0%, + line to 100% 100%, + line to 0% 100% + ); + } + } + + [vl-effect="shape-reveal"] { + animation: vl-shape-reveal var(--vl-motion-duration, 300ms) var(--vl-ease-cinematic) both; + + @media (prefers-reduced-motion: reduce) { + animation: none; + opacity: 1; + clip-path: none; + } + } + + [vl-effect="shape-reveal"][vl-variant="organic"] { + animation-name: vl-shape-reveal-organic; + animation-duration: var(--vl-duration-slow, 500ms); + } + } + + /* --- AI shimmer / streaming state (vl-effect="ai-shimmer") --- + CSS-only shimmer for skeleton loading and AI content generation states. + ------------------------------------------------------------------- */ + @keyframes vl-ai-shimmer { + 0% { background-position: -200% center; } + 100% { background-position: 200% center; } + } + + @keyframes vl-ai-pulse-glow { + 0%, 100% { box-shadow: var(--vl-ai-glow, 0 0 0 1px currentColor); opacity: 0.85; } + 50% { box-shadow: 0 0 0 3px color-mix(in oklch, var(--vl-color-primary) 28%, transparent); opacity: 1; } + } + + [vl-effect="ai-shimmer"] { + background: linear-gradient( + 90deg, + var(--vl-ai-shimmer-start, color-mix(in oklch, var(--vl-bg-surface) 96%, transparent)), + var(--vl-ai-shimmer-mid, color-mix(in oklch, var(--vl-color-primary) 9%, var(--vl-bg-surface))), + var(--vl-ai-shimmer-end, color-mix(in oklch, var(--vl-bg-surface) 96%, transparent)) + ); + background-size: 200% 100%; + animation: vl-ai-shimmer var(--vl-ai-duration, 1.8s) linear infinite; + border-radius: inherit; + + @media (prefers-reduced-motion: reduce) { + animation: none; + background: var(--vl-bg-surface); + } + } + + [vl-effect="ai-glow"] { + animation: vl-ai-pulse-glow var(--vl-ai-duration, 1.8s) var(--vl-ease-in-out-smooth) infinite; + + @media (prefers-reduced-motion: reduce) { + animation: none; + } + } + + /* Skeleton block: zero-markup content placeholder */ + .vl-skeleton { + --vl-skeleton-radius: var(--vl-radius-sm); + display: block; + border-radius: var(--vl-skeleton-radius); + min-height: 1em; + } + + .vl-skeleton[vl-effect="ai-shimmer"] { + min-height: var(--vl-skeleton-height, 1em); + width: var(--vl-skeleton-width, 100%); + } + + .vl-skeleton--text { + --vl-skeleton-height: 1rem; + --vl-skeleton-radius: var(--vl-radius-sm); + } + + .vl-skeleton--heading { + --vl-skeleton-height: 1.75rem; + --vl-skeleton-radius: var(--vl-radius-sm); + } + + .vl-skeleton--avatar { + --vl-skeleton-height: 2.5rem; + --vl-skeleton-width: 2.5rem; + --vl-skeleton-radius: var(--vl-radius-full); + aspect-ratio: 1; + } + + /* --- offset-path: shape() motion path (Chrome 137+) --- + Animate an element along a responsive free-form path. + ------------------------------------------------------------------- */ + @supports (offset-path: shape(from 0% 0%, line to 100% 100%)) { + [vl-effect="path-arc"] { + offset-path: shape(from 50% 100%, curve to 100% 0% via 100% 100%, 100% 0%); + animation: vl-path-travel var(--vl-duration-slow, 500ms) var(--vl-ease-cinematic) both; + + @media (prefers-reduced-motion: reduce) { + animation: none; + offset-path: none; + } + } + + @keyframes vl-path-travel { + from { offset-distance: 0%; opacity: 0; } + to { offset-distance: 100%; opacity: 1; } + } + } + + /* --- CSS if() conditional style hook (Chrome 137+) --- + Token-level conditional utility — component examples use this for + smart variant switching without extra class proliferation. + ------------------------------------------------------------------- */ + @supports (color: if(style(--vl-variant: ghost): transparent; else: red)) { + .vl-cta { + /* Ghost variant switches background + border via if() */ + background-color: if( + style(--vl-variant: ghost): transparent; + else: var(--vl-color-primary) + ); + border-color: if( + style(--vl-variant: ghost): currentColor; + else: transparent + ); + color: if( + style(--vl-variant: ghost): var(--vl-color-primary); + else: var(--vl-text-inverse) + ); + } + } } diff --git a/apps/showcase/public/css/04f-carousel.css b/apps/showcase/public/css/04f-carousel.css new file mode 100644 index 0000000..bcd1eaa --- /dev/null +++ b/apps/showcase/public/css/04f-carousel.css @@ -0,0 +1,214 @@ +@layer velora.components { + /* + * CSS-Native Carousel — vl-carousel + * Zero JavaScript. Powered by scroll-snap + CSS Scroll Markers API (Chrome 135+) + * and ::scroll-button() pseudo-elements (Chrome 135+). + * + * Public API: + * .vl-carousel Scroll carousel container + * .vl-carousel--center Center-snap variant + * .vl-carousel--peek Peek at adjacent slides + * .vl-carousel > * Any direct children become slides + * vl-scroll-buttons Attribute — adds ::scroll-button() nav + * --vl-carousel-item-width Per-slide width (default: min(80vw, 20rem)) + * --vl-carousel-gap Gap between slides + * --vl-carousel-marker-size Scroll marker dot size + * --vl-carousel-marker-color Inactive marker color + * --vl-carousel-marker-active Active marker color + * + * Markup pattern: + * + * + * Browser support: + * Scroll-snap: all modern browsers (Chrome 124+, Safari 18+, Firefox 128+) + * ::scroll-marker: Chrome 135+ (progressive enhancement, @supports-guarded) + * ::scroll-button(): Chrome 135+ (progressive enhancement, @supports-guarded) + */ + + /* ------------------------------------------------------------------------- + Base carousel — scroll-snap, hidden scrollbar, touch-friendly + ------------------------------------------------------------------------- */ + .vl-carousel { + --vl-carousel-item-width: min(80vw, 20rem); + --vl-carousel-gap: var(--vl-space-md); + + display: flex; + gap: var(--vl-carousel-gap); + overflow-x: auto; + overflow-y: hidden; + scroll-snap-type: x mandatory; + scroll-behavior: smooth; + overscroll-behavior-x: contain; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + padding-block: var(--vl-space-xs); /* preserve box-shadow on children */ + } + + .vl-carousel::-webkit-scrollbar { + display: none; + } + + /* Slides — snap to start by default */ + .vl-carousel > * { + flex: 0 0 var(--vl-carousel-item-width); + scroll-snap-align: start; + min-width: 0; + } + + /* Center-snap variant */ + .vl-carousel--center > * { + scroll-snap-align: center; + } + + /* Peek variant — show edge of next slide */ + .vl-carousel--peek { + --vl-carousel-item-width: min(75vw, 18rem); + padding-inline-end: calc(var(--vl-carousel-gap) * 2); + } + + /* Full-width slides */ + .vl-carousel--full > * { + flex: 0 0 100%; + scroll-snap-align: start; + } + + /* ------------------------------------------------------------------------- + CSS Scroll Markers (Chrome 135+) + Renders a navigation dot group after the carousel with zero JS. + @see https://developer.chrome.com/blog/css-scroll-markers + ------------------------------------------------------------------------- */ + @supports selector(.x::scroll-marker) { + .vl-carousel { + scroll-marker-group: after; + } + + /* Each slide contributes a dot to the marker group */ + .vl-carousel > *::scroll-marker { + content: ""; + display: block; + width: var(--vl-carousel-marker-size, 0.5rem); + height: var(--vl-carousel-marker-size, 0.5rem); + border-radius: var(--vl-radius-full); + background: var(--vl-carousel-marker-color, var(--vl-border-strong)); + transition: + background var(--vl-duration-fast) var(--vl-ease-out-soft), + transform var(--vl-duration-fast) var(--vl-ease-spring), + opacity var(--vl-duration-fast) var(--vl-ease-out-soft); + } + + /* Active (current) dot */ + .vl-carousel > *::scroll-marker:target-current { + background: var(--vl-carousel-marker-active, var(--vl-color-primary)); + transform: scale(1.5); + } + + /* Marker group container */ + .vl-carousel::scroll-marker-group { + display: flex; + justify-content: center; + align-items: center; + gap: var(--vl-carousel-marker-gap, 0.375rem); + padding-block: var(--vl-space-md) var(--vl-space-xs); + /* Inherit layout width so it aligns with the carousel */ + width: 100%; + } + + /* Elongated active marker variant */ + .vl-carousel--pill > *::scroll-marker:target-current { + width: 1.5rem; + border-radius: var(--vl-radius-full); + transform: none; + } + } + + /* ------------------------------------------------------------------------- + CSS Scroll Buttons (Chrome 135+) + Prev / next controls rendered as ::pseudo-elements — no HTML needed. + Apply the [vl-scroll-buttons] attribute to opt in. + ------------------------------------------------------------------------- */ + @supports selector(.x::scroll-button(inline-start)) { + .vl-carousel[vl-scroll-buttons] { + position: relative; + } + + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-start), + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-end) { + /* Layout */ + position: absolute; + top: 50%; + transform: translateY(-50%); + width: var(--vl-carousel-btn-size, 2.5rem); + height: var(--vl-carousel-btn-size, 2.5rem); + + /* Appearance */ + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--vl-radius-full); + background: var(--vl-bg-surface); + border: 1px solid var(--vl-border-subtle); + color: var(--vl-text-primary); + font-size: var(--vl-font-size-md); + cursor: pointer; + box-shadow: var(--vl-shadow-md); + z-index: var(--vl-z-base); + + transition: + opacity var(--vl-duration-fast) var(--vl-ease-out-soft), + background var(--vl-duration-fast) var(--vl-ease-out-soft), + box-shadow var(--vl-duration-fast) var(--vl-ease-out-soft), + transform var(--vl-duration-fast) var(--vl-ease-spring); + } + + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-start) { + content: "‹"; + inset-inline-start: calc(var(--vl-carousel-btn-size, 2.5rem) * -0.5); + } + + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-end) { + content: "›"; + inset-inline-end: calc(var(--vl-carousel-btn-size, 2.5rem) * -0.5); + } + + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-start):hover, + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-end):hover { + background: var(--vl-bg-surface-elevated); + box-shadow: var(--vl-shadow-lg); + transform: translateY(calc(-50% - 1px)); + } + + /* Disabled state when no more content to scroll */ + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-start):disabled, + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-end):disabled { + opacity: 0.25; + cursor: not-allowed; + transform: translateY(-50%); + } + + /* Focus-visible ring */ + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-start):focus-visible, + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-end):focus-visible { + outline: var(--vl-focus-ring-width) solid var(--vl-focus-ring-color); + outline-offset: var(--vl-focus-ring-offset); + } + } + + /* ------------------------------------------------------------------------- + Accessibility + ------------------------------------------------------------------------- */ + @media (prefers-reduced-motion: reduce) { + .vl-carousel { + scroll-behavior: auto; + } + + @supports selector(.x::scroll-marker) { + .vl-carousel > *::scroll-marker { + transition: none; + } + } + } +} diff --git a/apps/showcase/public/css/04g-anchor.css b/apps/showcase/public/css/04g-anchor.css new file mode 100644 index 0000000..9ca229f --- /dev/null +++ b/apps/showcase/public/css/04g-anchor.css @@ -0,0 +1,266 @@ +@layer velora.components { + /* + * CSS Anchor Positioning — vl-anchor-group / vl-tooltip / vl-float + * Zero JavaScript floating UI using the CSS Anchor Positioning API. + * + * Browser support: + * Chrome 125+, Safari 18.2+. Firefox: pending (graceful degradation via + * @supports guard — elements remain visible, just not anchor-positioned). + * + * Architecture: container-based pattern + * The [vl-anchor-group] wrapper establishes a relative context as a fallback. + * Inside it, the first [vl-anchor-trigger] element is the anchor source. + * Positioned elements ([vl-tooltip], [vl-float]) are auto-positioned via CSS. + * + * Public API: + * [vl-anchor-group] Container that scopes the anchor relationship + * [vl-anchor-trigger] The element that acts as the anchor point + * [vl-tooltip] Small inline label above the anchor + * [vl-tooltip][vl-position="*"] Override position: top|bottom|left|right + * [vl-float] Dropdown/panel below the anchor + * [vl-float][vl-position="*"] Override position: top|bottom|left|right + * popover + popovertarget Add popover API for toggle behavior (no JS) + * + * Markup — tooltip (hover + focus, using popover="hint"): + *
+ * + *
Tooltip text
+ *
+ * + * Markup — floating dropdown: + *
+ * + * + *
+ * + * Markup — without Popover API (always visible, CSS-positioned): + *
+ * + *
Always visible label
+ *
+ */ + + /* ------------------------------------------------------------------------- + Fallback: relative container (all browsers) + Tooltip/float positioned absolutely within the group when anchor API + is not available. + ------------------------------------------------------------------------- */ + [vl-anchor-group] { + position: relative; + display: inline-block; + } + + /* Fallback positioning for tooltip (top-center above trigger) */ + [vl-tooltip]:not(:popover-open) { + position: absolute; + inset-block-end: calc(100% + var(--vl-anchor-gap, 0.375rem)); + inset-inline-start: 50%; + transform: translateX(-50%); + z-index: var(--vl-z-dropdown); + } + + /* Fallback positioning for float (bottom-start below trigger) */ + [vl-float]:not(:popover-open) { + position: absolute; + inset-block-start: calc(100% + var(--vl-anchor-gap, 0.375rem)); + inset-inline-start: 0; + z-index: var(--vl-z-dropdown); + } + + /* ------------------------------------------------------------------------- + Tooltip styles (all browsers) + ------------------------------------------------------------------------- */ + [vl-tooltip] { + /* Reset popover UA styles */ + border: 1px solid var(--vl-border-subtle); + background: var(--vl-bg-inset); + color: var(--vl-text-primary); + font-family: var(--vl-font-family); + font-size: var(--vl-font-size-xs); + font-weight: var(--vl-font-weight-medium); + line-height: var(--vl-leading-normal); + padding: var(--vl-space-xs) var(--vl-space-sm); + border-radius: var(--vl-radius-sm); + max-width: var(--vl-tooltip-max-width, 16rem); + white-space: normal; + box-shadow: var(--vl-shadow-md); + pointer-events: none; + } + + /* ------------------------------------------------------------------------- + Float / dropdown panel styles (all browsers) + ------------------------------------------------------------------------- */ + [vl-float] { + /* Reset popover UA styles */ + border: 1px solid var(--vl-border-subtle); + background: var(--vl-bg-surface); + color: var(--vl-text-primary); + font-family: var(--vl-font-family); + font-size: var(--vl-font-size-sm); + border-radius: var(--vl-radius-md); + padding: var(--vl-space-xs); + min-width: var(--vl-float-min-width, 10rem); + box-shadow: var(--vl-shadow-lg); + overflow: clip; + } + + /* ------------------------------------------------------------------------- + @starting-style transitions — smooth open/close (Chrome 117+, Safari 17.5+) + Pairs naturally with popover="hint" and popover="" toggle behavior. + ------------------------------------------------------------------------- */ + @supports (transition-behavior: allow-discrete) { + [vl-tooltip], + [vl-float] { + transition: + opacity var(--vl-duration-fast) var(--vl-ease-out-soft), + transform var(--vl-duration-fast) var(--vl-ease-spring), + display var(--vl-duration-fast) allow-discrete, + overlay var(--vl-duration-fast) allow-discrete; + opacity: 1; + } + + [vl-tooltip]:not(:popover-open), + [vl-float]:not(:popover-open) { + opacity: 0; + } + + @starting-style { + [vl-tooltip]:popover-open { + opacity: 0; + transform: translateX(-50%) translateY(0.25rem) scale(0.95); + } + + [vl-float]:popover-open { + opacity: 0; + transform: translateY(-0.375rem) scale(0.97); + } + } + } + + /* ------------------------------------------------------------------------- + CSS Anchor Positioning (Chrome 125+ / Safari 18.2+) + When available, the fallback position: absolute is replaced by true + anchor positioning with auto-flip and inset-area. + ------------------------------------------------------------------------- */ + @supports (anchor-name: --x) { + /* The trigger element becomes the anchor */ + [vl-anchor-trigger] { + anchor-name: --vl-anchor-local; + } + + /* Tooltip — top-center of anchor, auto-flips to bottom if needed */ + [vl-tooltip] { + position: absolute; + position: fixed; /* top-layer: works inside popover */ + position-anchor: --vl-anchor-local; + inset-area: top span-all; + margin-block-end: var(--vl-anchor-gap, 0.375rem); + justify-self: anchor-center; + /* Auto-flip: try bottom if no room above */ + position-try-options: flip-block; + position-try-order: most-height; + inset: auto; + + /* Reset fallback transform for anchor-positioned context */ + transform: none; + } + + /* Tooltip position overrides */ + [vl-tooltip][vl-position="bottom"] { + inset-area: bottom span-all; + margin-block: var(--vl-anchor-gap, 0.375rem) 0; + } + + [vl-tooltip][vl-position="left"] { + inset-area: left span-all; + margin-inline-end: var(--vl-anchor-gap, 0.375rem); + position-try-options: flip-inline; + } + + [vl-tooltip][vl-position="right"] { + inset-area: right span-all; + margin-inline-start: var(--vl-anchor-gap, 0.375rem); + position-try-options: flip-inline; + } + + /* @starting-style for anchor-positioned tooltip */ + @supports (transition-behavior: allow-discrete) { + @starting-style { + [vl-tooltip]:popover-open { + opacity: 0; + transform: scale(0.94); + } + } + } + + /* Float — bottom-start of anchor, auto-flips to top if needed */ + [vl-float] { + position: absolute; + position: fixed; /* top-layer: works inside popover */ + position-anchor: --vl-anchor-local; + inset-area: bottom span-all; + margin-block-start: var(--vl-anchor-gap, 0.375rem); + /* Minimum width tracks the anchor width */ + min-width: anchor-size(width); + /* Auto-flip to top when clipped */ + position-try-options: flip-block; + position-try-order: most-height; + inset: auto; + + transform: none; + } + + /* Float position overrides */ + [vl-float][vl-position="top"] { + inset-area: top span-all; + margin-block-end: var(--vl-anchor-gap, 0.375rem); + } + + @supports (transition-behavior: allow-discrete) { + @starting-style { + [vl-float]:popover-open { + opacity: 0; + transform: scale(0.97); + } + } + } + + /* Position visibility: hide when anchor scrolls out of view */ + [vl-tooltip], + [vl-float] { + position-visibility: anchors-visible; + } + + /* Multi-anchor support: use vl-anchor-name CSS property override + Example: style="--vl-anchor-name: --my-custom-anchor" on trigger + float */ + [vl-anchor-trigger][style*="--vl-anchor-name"] { + anchor-name: var(--vl-anchor-name); + } + + [vl-tooltip][style*="--vl-anchor-name"], + [vl-float][style*="--vl-anchor-name"] { + position-anchor: var(--vl-anchor-name); + } + } + + /* ------------------------------------------------------------------------- + Focus ring — keyboard accessibility + ------------------------------------------------------------------------- */ + [vl-anchor-trigger]:focus-visible { + outline: var(--vl-focus-ring-width) solid var(--vl-focus-ring-color); + outline-offset: var(--vl-focus-ring-offset); + } + + /* ------------------------------------------------------------------------- + Reduced motion — disable transform transitions, keep opacity fade + ------------------------------------------------------------------------- */ + @media (prefers-reduced-motion: reduce) { + [vl-tooltip], + [vl-float] { + transition: opacity var(--vl-duration-instant) linear, + display var(--vl-duration-instant) allow-discrete; + } + } +} diff --git a/apps/showcase/public/css/05-transitions.css b/apps/showcase/public/css/05-transitions.css index 6c3fb05..ffa96b7 100644 --- a/apps/showcase/public/css/05-transitions.css +++ b/apps/showcase/public/css/05-transitions.css @@ -428,6 +428,87 @@ animation-name: vl-vt-iris-new; } + /* ------------------------------------------------------------------------- + VIEW TRANSITION LEVEL 2 — match-element (Chrome 137+) + Generates a stable, unique view-transition-name from the element's identity. + Ideal for SPA list → detail morphing without manual name management. + + Usage: +
  • ← each item gets a unique stable VT name +
    + + The browser handles uniqueness; no need for inline style or IDs. + @see https://developer.chrome.com/blog/chrome-137-beta#view-transition-name-match-element + ------------------------------------------------------------------------- */ + @supports (view-transition-name: match-element) { + [vl-vt-match] { + view-transition-name: match-element; + } + + /* Sub-elements that should morph independently within a matched item */ + [vl-vt-match-inner] { + view-transition-name: match-element; + } + } + + /* ------------------------------------------------------------------------- + MORPH — Preset (vl-page-transition="morph") + Shape-clip morph transition that looks great for card → detail pages. + Uses clip-path with CSS shape() (Chrome 135+), gracefully degrades to + the default velora preset on older browsers. + ------------------------------------------------------------------------- */ + @keyframes vl-vt-morph-old { + from { + opacity: 1; + clip-path: inset(0 0 0 0 round var(--vl-radius-lg)); + transform: scale(1); + } + + to { + opacity: 0; + clip-path: inset(4% 3% 4% 3% round var(--vl-radius-xl)); + transform: scale(0.94); + filter: blur(6px); + } + } + + @keyframes vl-vt-morph-new { + from { + opacity: 0; + clip-path: inset(5% 4% 5% 4% round var(--vl-radius-2xl)); + transform: scale(1.06); + filter: blur(8px); + } + + to { + opacity: 1; + clip-path: inset(0 0 0 0 round 0px); + transform: scale(1); + filter: blur(0); + } + } + + :root[vl-page-transition="morph"]::view-transition-old(root) { + animation-name: vl-vt-morph-old; + animation-duration: var(--vl-vt-root-duration, 0.6s); + animation-timing-function: var(--vl-ease-emphasized, cubic-bezier(0.2, 0, 0, 1)); + } + + :root[vl-page-transition="morph"]::view-transition-new(root) { + animation-name: vl-vt-morph-new; + animation-duration: var(--vl-vt-root-duration, 0.65s); + animation-timing-function: var(--vl-ease-emphasized, cubic-bezier(0.2, 0, 0, 1)); + } + + /* morph: shared card uses matching clip-path animation */ + :root[vl-page-transition="morph"]::view-transition-old(shared-card) { + animation-name: vl-vt-morph-old; + } + + :root[vl-page-transition="morph"]::view-transition-new(shared-card) { + animation-name: vl-vt-morph-new; + } + /* ------------------------------------------------------------------------- Acessibilidade ------------------------------------------------------------------------- */ diff --git a/apps/showcase/public/css/showcase-tw-demos.css b/apps/showcase/public/css/showcase-tw-demos.css index c5cf59f..b78a211 100644 --- a/apps/showcase/public/css/showcase-tw-demos.css +++ b/apps/showcase/public/css/showcase-tw-demos.css @@ -1 +1 @@ -.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{left:0;right:0}.inset-x-12{left:3rem;right:3rem}.inset-y-0{top:0;bottom:0}.-bottom-4{bottom:-1rem}.-bottom-6{bottom:-1.5rem}.-left-12{left:-3rem}.-left-8{left:-2rem}.-right-4{right:-1rem}.-right-6{right:-1.5rem}.-top-12{top:-3rem}.-top-8{top:-2rem}.bottom-0{bottom:0}.bottom-4{bottom:1rem}.bottom-6{bottom:1.5rem}.bottom-8{bottom:2rem}.left-0{left:0}.left-1\/2{left:50%}.left-4{left:1rem}.left-6{left:1.5rem}.left-8{left:2rem}.left-\[400px\]{left:400px}.right-0{right:0}.right-4{right:1rem}.right-6{right:1.5rem}.right-8{right:2rem}.top-0{top:0}.top-1\/2{top:50%}.top-16{top:4rem}.top-4{top:1rem}.top-6{top:1.5rem}.top-8{top:2rem}.top-\[320px\]{top:320px}.isolate{isolation:isolate}.-z-10{z-index:-10}.z-10{z-index:10}.z-40{z-index:40}.z-50{z-index:50}.z-\[100\]{z-index:100}.col-span-12{grid-column:span 12/span 12}.mx-8{margin-left:2rem;margin-right:2rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-0{margin-bottom:0}.mb-1{margin-bottom:.25rem}.mb-10{margin-bottom:2.5rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-20{margin-bottom:5rem}.mb-24{margin-bottom:6rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-40{margin-bottom:10rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-64{margin-left:16rem}.mr-3{margin-right:.75rem}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-24{margin-top:6rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-40{margin-top:10rem}.mt-8{margin-top:2rem}.mt-auto{margin-top:auto}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.aspect-\[1\.6\/1\]{aspect-ratio:1.6/1}.aspect-video{aspect-ratio:16/9}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-20{height:5rem}.h-24{height:6rem}.h-3{height:.75rem}.h-32{height:8rem}.h-4{height:1rem}.h-40{height:10rem}.h-48{height:12rem}.h-52{height:13rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-8{height:2rem}.h-80{height:20rem}.h-9{height:2.25rem}.h-96{height:24rem}.h-\[600px\]{height:600px}.h-\[800px\]{height:800px}.h-\[calc\(100vh-4rem\)\]{height:calc(100vh - 4rem)}.h-\[calc\(100vh-64px\)\]{height:calc(100vh - 64px)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.min-h-\[180px\]{min-height:180px}.min-h-screen{min-height:100vh}.w-0\.5{width:.125rem}.w-1\/2{width:50%}.w-1\/3{width:33.333333%}.w-10{width:2.5rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\/3{width:66.666667%}.w-20{width:5rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\/4{width:75%}.w-32{width:8rem}.w-4\/6{width:66.666667%}.w-5\/6{width:83.333333%}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-\[800px\]{width:800px}.w-\[90vw\]{width:90vw}.w-full{width:100%}.w-px{width:1px}.min-w-\[100px\]{min-width:100px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-\[90\%\]{max-width:90%}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.flex-grow{flex-grow:1}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-full{--tw-translate-y:-100%}.-translate-y-full,.translate-y-4{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-4{--tw-translate-y:1rem}.scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05}.scale-105,.scale-110{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.scale-90{--tw-scale-x:.9;--tw-scale-y:.9}.scale-90,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-pointer{cursor:pointer}.resize{resize:both}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.gap-0{gap:0}.gap-1{gap:.25rem}.gap-12{gap:3rem}.gap-2{gap:.5rem}.gap-24{gap:6rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.gap-x-12{-moz-column-gap:3rem;column-gap:3rem}.gap-y-24{row-gap:6rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-16>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(4rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(4rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-24>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(6rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(6rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-outline-variant\/10>:not([hidden])~:not([hidden]){border-color:rgba(67,74,65,.1)}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.rounded{border-radius:.125rem}.rounded-2xl{border-radius:1rem}.rounded-\[0\.125rem\]{border-radius:.125rem}.rounded-full{border-radius:.75rem}.rounded-lg{border-radius:.25rem}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.5rem}.rounded-t-2xl{border-top-left-radius:1rem;border-top-right-radius:1rem}.rounded-t-xl{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-2{border-width:2px}.border-x{border-left-width:1px;border-right-width:1px}.border-b{border-bottom-width:1px}.border-l-4{border-left-width:4px}.border-r{border-right-width:1px}.border-r-2{border-right-width:2px}.border-t{border-top-width:1px}.border-none{border-style:none}.border-\[\#6b7a63\]{--tw-border-opacity:1;border-color:rgb(107 122 99/var(--tw-border-opacity,1))}.border-\[\#bbcbb1\]{--tw-border-opacity:1;border-color:rgb(187 203 177/var(--tw-border-opacity,1))}.border-outline-variant{--tw-border-opacity:1;border-color:rgb(67 74 65/var(--tw-border-opacity,1))}.border-outline-variant\/10{border-color:rgba(67,74,65,.1)}.border-outline-variant\/15{border-color:rgba(67,74,65,.15)}.border-outline-variant\/20{border-color:rgba(67,74,65,.2)}.border-outline-variant\/25{border-color:rgba(67,74,65,.25)}.border-outline-variant\/30{border-color:rgba(67,74,65,.3)}.border-outline-variant\/40{border-color:rgba(67,74,65,.4)}.border-outline-variant\/5{border-color:rgba(67,74,65,.05)}.border-primary{--tw-border-opacity:1;border-color:rgb(187 203 177/var(--tw-border-opacity,1))}.border-primary\/10{border-color:hsla(97,20%,75%,.1)}.border-primary\/20{border-color:hsla(97,20%,75%,.2)}.border-primary\/30{border-color:hsla(97,20%,75%,.3)}.border-primary\/40{border-color:hsla(97,20%,75%,.4)}.border-transparent{border-color:transparent}.border-white\/20{border-color:hsla(0,0%,100%,.2)}.border-white\/5{border-color:hsla(0,0%,100%,.05)}.bg-\[\#0d0f0c\]{--tw-bg-opacity:1;background-color:rgb(13 15 12/var(--tw-bg-opacity,1))}.bg-\[\#0d0f0c\]\/80{background-color:rgba(13,15,12,.8)}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-error-dim{--tw-bg-opacity:1;background-color:rgb(186 87 63/var(--tw-bg-opacity,1))}.bg-on-surface\/10{background-color:hsla(93,19%,88%,.1)}.bg-on-surface\/20{background-color:hsla(93,19%,88%,.2)}.bg-on-surface\/30{background-color:hsla(93,19%,88%,.3)}.bg-on-surface\/80{background-color:hsla(93,19%,88%,.8)}.bg-outline-variant{--tw-bg-opacity:1;background-color:rgb(67 74 65/var(--tw-bg-opacity,1))}.bg-outline-variant\/20{background-color:rgba(67,74,65,.2)}.bg-outline-variant\/30{background-color:rgba(67,74,65,.3)}.bg-primary{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.bg-primary-container{--tw-bg-opacity:1;background-color:rgb(61 75 54/var(--tw-bg-opacity,1))}.bg-primary-container\/20{background-color:rgba(61,75,54,.2)}.bg-primary-container\/30{background-color:rgba(61,75,54,.3)}.bg-primary\/10{background-color:hsla(97,20%,75%,.1)}.bg-primary\/15{background-color:hsla(97,20%,75%,.15)}.bg-primary\/20{background-color:hsla(97,20%,75%,.2)}.bg-primary\/40{background-color:hsla(97,20%,75%,.4)}.bg-secondary-container{--tw-bg-opacity:1;background-color:rgb(58 60 57/var(--tw-bg-opacity,1))}.bg-secondary\/15{background-color:hsla(75,2%,61%,.15)}.bg-secondary\/20{background-color:hsla(75,2%,61%,.2)}.bg-surface{--tw-bg-opacity:1;background-color:rgb(13 15 12/var(--tw-bg-opacity,1))}.bg-surface-container{--tw-bg-opacity:1;background-color:rgb(23 27 22/var(--tw-bg-opacity,1))}.bg-surface-container-high{--tw-bg-opacity:1;background-color:rgb(28 33 27/var(--tw-bg-opacity,1))}.bg-surface-container-highest{--tw-bg-opacity:1;background-color:rgb(33 39 32/var(--tw-bg-opacity,1))}.bg-surface-container-low{--tw-bg-opacity:1;background-color:rgb(17 20 16/var(--tw-bg-opacity,1))}.bg-surface-container-low\/50{background-color:rgba(17,20,16,.5)}.bg-surface-container-lowest{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.bg-\[linear-gradient\(to_right\2c \#1c211b_1px\2c transparent_1px\)\2c linear-gradient\(to_bottom\2c \#1c211b_1px\2c transparent_1px\)\]{background-image:linear-gradient(90deg,#1c211b 1px,transparent 0),linear-gradient(180deg,#1c211b 1px,transparent 0)}.bg-\[radial-gradient\(circle_at_center\2c _var\(--tw-gradient-from\)_0\%\2c _transparent_70\%\)\]{background-image:radial-gradient(circle at center,var(--tw-gradient-from) 0,transparent 70%)}.bg-\[radial-gradient\(ellipse_at_center\2c _transparent_0\%\2c _\#0d0f0c_85\%\)\]{background-image:radial-gradient(ellipse at center,transparent 0,#0d0f0c 85%)}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.bg-gradient-to-tr{background-image:linear-gradient(to top right,var(--tw-gradient-stops))}.from-primary{--tw-gradient-from:#bbcbb1 var(--tw-gradient-from-position);--tw-gradient-to:hsla(97,20%,75%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-primary\/10{--tw-gradient-from:hsla(97,20%,75%,.1) var(--tw-gradient-from-position);--tw-gradient-to:hsla(97,20%,75%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-surface{--tw-gradient-from:#0d0f0c var(--tw-gradient-from-position);--tw-gradient-to:rgba(13,15,12,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-surface-container-high\/50{--tw-gradient-from:rgba(28,33,27,.5) var(--tw-gradient-from-position);--tw-gradient-to:rgba(28,33,27,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-transparent{--tw-gradient-from:transparent var(--tw-gradient-from-position);--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-primary\/30{--tw-gradient-to:hsla(97,20%,75%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),hsla(97,20%,75%,.3) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-primary\/40{--tw-gradient-to:hsla(97,20%,75%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),hsla(97,20%,75%,.4) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),transparent var(--tw-gradient-via-position),var(--tw-gradient-to)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.bg-\[size\:40px_40px\]{background-size:40px 40px}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-10{padding:2.5rem}.p-12{padding:3rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-12{padding-bottom:3rem}.pb-24{padding-bottom:6rem}.pb-32{padding-bottom:8rem}.pb-4{padding-bottom:1rem}.pl-16{padding-left:4rem}.pl-4{padding-left:1rem}.pl-8{padding-left:2rem}.pr-6{padding-right:1.5rem}.pr-8{padding-right:2rem}.pt-0{padding-top:0}.pt-10{padding-top:2.5rem}.pt-2{padding-top:.5rem}.pt-24{padding-top:6rem}.pt-28{padding-top:7rem}.pt-32{padding-top:8rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-\[\'Manrope\'\]{font-family:Manrope}.font-body{font-family:Manrope,system-ui,sans-serif}.font-headline{font-family:Space Grotesk,system-ui,sans-serif}.font-label{font-family:Manrope,system-ui,sans-serif}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-6xl{font-size:3.75rem;line-height:1}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[18px\]{font-size:18px}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.normal-case{text-transform:none}.leading-\[0\.9\]{line-height:.9}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-\[-0\.04em\]{letter-spacing:-.04em}.tracking-\[0\.15em\]{letter-spacing:.15em}.tracking-\[0\.1em\]{letter-spacing:.1em}.tracking-\[0\.25em\]{letter-spacing:.25em}.tracking-\[0\.2em\]{letter-spacing:.2em}.tracking-\[0\.4em\]{letter-spacing:.4em}.tracking-tight{letter-spacing:-.025em}.tracking-tighter{letter-spacing:-.05em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-\[\#6b7a63\]{--tw-text-opacity:1;color:rgb(107 122 99/var(--tw-text-opacity,1))}.text-\[\#727d6d\]{--tw-text-opacity:1;color:rgb(114 125 109/var(--tw-text-opacity,1))}.text-\[\#bbcbb1\]{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.text-error{--tw-text-opacity:1;color:rgb(237 127 100/var(--tw-text-opacity,1))}.text-on-primary{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.text-on-primary-container{--tw-text-opacity:1;color:rgb(197 213 186/var(--tw-text-opacity,1))}.text-on-secondary-container{--tw-text-opacity:1;color:rgb(191 192 187/var(--tw-text-opacity,1))}.text-on-surface{--tw-text-opacity:1;color:rgb(225 231 220/var(--tw-text-opacity,1))}.text-on-surface-variant{--tw-text-opacity:1;color:rgb(167 173 162/var(--tw-text-opacity,1))}.text-on-surface-variant\/40{color:hsla(93,6%,66%,.4)}.text-on-surface-variant\/50{color:hsla(93,6%,66%,.5)}.text-on-surface\/40{color:hsla(93,19%,88%,.4)}.text-on-surface\/60{color:hsla(93,19%,88%,.6)}.text-outline{--tw-text-opacity:1;color:rgb(113 119 110/var(--tw-text-opacity,1))}.text-primary{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.text-primary-dim{--tw-text-opacity:1;color:rgb(174 190 164/var(--tw-text-opacity,1))}.text-primary\/20{color:hsla(97,20%,75%,.2)}.text-primary\/40{color:hsla(97,20%,75%,.4)}.text-primary\/50{color:hsla(97,20%,75%,.5)}.text-primary\/60{color:hsla(97,20%,75%,.6)}.text-primary\/70{color:hsla(97,20%,75%,.7)}.text-primary\/80{color:hsla(97,20%,75%,.8)}.text-secondary{--tw-text-opacity:1;color:rgb(157 158 154/var(--tw-text-opacity,1))}.text-tertiary{--tw-text-opacity:1;color:rgb(241 255 212/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.decoration-primary\/50{text-decoration-color:hsla(97,20%,75%,.5)}.underline-offset-4{text-underline-offset:4px}.accent-primary{accent-color:#bbcbb1}.opacity-0{opacity:0}.opacity-10{opacity:.1}.opacity-20{opacity:.2}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.opacity-90{opacity:.9}.opacity-95{opacity:.95}.opacity-\[0\.03\]{opacity:.03}.mix-blend-overlay{mix-blend-mode:overlay}.mix-blend-luminosity{mix-blend-mode:luminosity}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-\[0_-20px_50px_rgba\(0\2c 0\2c 0\2c 0\.5\)\]{--tw-shadow:0 -20px 50px rgba(0,0,0,.5);--tw-shadow-colored:0 -20px 50px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_-30px_60px_rgba\(0\2c 0\2c 0\2c 0\.6\)\]{--tw-shadow:0 -30px 60px rgba(0,0,0,.6);--tw-shadow-colored:0 -30px 60px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_15px_rgba\(187\2c 203\2c 177\2c 0\.8\)\]{--tw-shadow:0 0 15px hsla(97,20%,75%,.8);--tw-shadow-colored:0 0 15px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_30px_rgba\(187\2c 203\2c 177\2c 0\.3\)\]{--tw-shadow:0 0 30px hsla(97,20%,75%,.3);--tw-shadow-colored:0 0 30px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_50px_rgba\(187\2c 203\2c 177\2c 0\.4\)\]{--tw-shadow:0 0 50px hsla(97,20%,75%,.4);--tw-shadow-colored:0 0 50px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[20px_0_40px_rgba\(0\2c 0\2c 0\2c 0\.4\)\]{--tw-shadow:20px 0 40px rgba(0,0,0,.4);--tw-shadow-colored:20px 0 40px var(--tw-shadow-color)}.shadow-\[20px_0_40px_rgba\(0\2c 0\2c 0\2c 0\.4\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-md,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-primary\/10{--tw-shadow-color:hsla(97,20%,75%,.1);--tw-shadow:var(--tw-shadow-colored)}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-2{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-4{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-primary\/20{--tw-ring-color:hsla(97,20%,75%,.2)}.blur{--tw-blur:blur(8px)}.blur,.grayscale{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.grayscale{--tw-grayscale:grayscale(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-xl{--tw-backdrop-blur:blur(24px)}.backdrop-blur-xl,.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-1000{transition-duration:1s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-700{transition-duration:.7s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.selection\:bg-primary ::-moz-selection{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.selection\:bg-primary ::selection{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.selection\:text-on-primary ::-moz-selection{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.selection\:text-on-primary ::selection{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.selection\:bg-primary::-moz-selection{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.selection\:bg-primary::selection{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.selection\:text-on-primary::-moz-selection{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.selection\:text-on-primary::selection{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.placeholder\:text-on-surface-variant\/40::-moz-placeholder{color:hsla(93,6%,66%,.4)}.placeholder\:text-on-surface-variant\/40::placeholder{color:hsla(93,6%,66%,.4)}.hover\:-translate-y-1:hover{--tw-translate-y:-0.25rem}.hover\:-translate-y-1:hover,.hover\:translate-y-\[-10px\]:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:translate-y-\[-10px\]:hover{--tw-translate-y:-10px}.hover\:translate-y-\[-20px\]:hover{--tw-translate-y:-20px}.hover\:translate-y-\[-20px\]:hover,.hover\:translate-y-\[-2px\]:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:translate-y-\[-2px\]:hover{--tw-translate-y:-2px}.hover\:translate-y-\[-30px\]:hover{--tw-translate-y:-30px}.hover\:scale-95:hover,.hover\:translate-y-\[-30px\]:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-95:hover{--tw-scale-x:.95;--tw-scale-y:.95}.hover\:bg-\[\#1a1d18\]:hover{--tw-bg-opacity:1;background-color:rgb(26 29 24/var(--tw-bg-opacity,1))}.hover\:bg-primary:hover{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.hover\:bg-primary-container:hover{--tw-bg-opacity:1;background-color:rgb(61 75 54/var(--tw-bg-opacity,1))}.hover\:bg-surface-bright:hover{--tw-bg-opacity:1;background-color:rgb(39 46 37/var(--tw-bg-opacity,1))}.hover\:bg-surface-container-high:hover{--tw-bg-opacity:1;background-color:rgb(28 33 27/var(--tw-bg-opacity,1))}.hover\:bg-surface-container-highest:hover{--tw-bg-opacity:1;background-color:rgb(33 39 32/var(--tw-bg-opacity,1))}.hover\:bg-white\/5:hover{background-color:hsla(0,0%,100%,.05)}.hover\:text-\[\#bbcbb1\]:hover{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.hover\:text-on-primary:hover{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.hover\:text-on-surface:hover{--tw-text-opacity:1;color:rgb(225 231 220/var(--tw-text-opacity,1))}.hover\:text-primary:hover{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.hover\:opacity-90:hover{opacity:.9}.hover\:shadow-\[0_0_20px_rgba\(187\2c 203\2c 177\2c 0\.3\)\]:hover{--tw-shadow:0 0 20px hsla(97,20%,75%,.3);--tw-shadow-colored:0 0 20px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:brightness-110:hover{--tw-brightness:brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:border-primary\/60:focus{border-color:hsla(97,20%,75%,.6)}.focus\:ring-0:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-0:focus,.focus\:ring-1:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-primary\/40:focus{--tw-ring-color:hsla(97,20%,75%,.4)}.active\:scale-95:active{--tw-scale-x:.95;--tw-scale-y:.95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:focus-within .group-focus-within\:text-primary{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.group:hover .group-hover\:-translate-y-1{--tw-translate-y:-0.25rem}.group:hover .group-hover\:-translate-y-1,.group:hover .group-hover\:translate-x-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:translate-x-1{--tw-translate-x:0.25rem}.group:hover .group-hover\:translate-y-0{--tw-translate-y:0px}.group:hover .group-hover\:rotate-180,.group:hover .group-hover\:translate-y-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:rotate-180{--tw-rotate:180deg}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:border-primary\/20{border-color:hsla(97,20%,75%,.2)}.group:hover .group-hover\:text-primary{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.group:hover .group-hover\:text-primary\/40{color:hsla(97,20%,75%,.4)}.group:hover .group-hover\:opacity-100{opacity:1}.group:hover .group-hover\:opacity-20{opacity:.2}.group:hover .group-hover\:brightness-110{--tw-brightness:brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.dark\:bg-\[\#0d0f0c\]:is(.dark *){--tw-bg-opacity:1;background-color:rgb(13 15 12/var(--tw-bg-opacity,1))}@media (min-width:768px){.md\:col-span-2{grid-column:span 2/span 2}.md\:col-span-5{grid-column:span 5/span 5}.md\:col-span-7{grid-column:span 7/span 7}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-end{align-items:flex-end}}@media (min-width:1024px){.lg\:col-span-5{grid-column:span 5/span 5}.lg\:col-span-7{grid-column:span 7/span 7}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:px-12{padding-left:3rem;padding-right:3rem}}@media (min-width:1280px){.xl\:text-7xl{font-size:4.5rem;line-height:1}} \ No newline at end of file +.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{left:0;right:0}.inset-x-12{left:3rem;right:3rem}.inset-y-0{top:0;bottom:0}.-bottom-4{bottom:-1rem}.-bottom-6{bottom:-1.5rem}.-left-12{left:-3rem}.-left-8{left:-2rem}.-right-4{right:-1rem}.-right-6{right:-1.5rem}.-top-12{top:-3rem}.-top-8{top:-2rem}.bottom-0{bottom:0}.bottom-4{bottom:1rem}.bottom-6{bottom:1.5rem}.bottom-8{bottom:2rem}.left-0{left:0}.left-1\/2{left:50%}.left-4{left:1rem}.left-6{left:1.5rem}.left-8{left:2rem}.left-\[400px\]{left:400px}.right-0{right:0}.right-4{right:1rem}.right-6{right:1.5rem}.right-8{right:2rem}.top-0{top:0}.top-1\/2{top:50%}.top-16{top:4rem}.top-4{top:1rem}.top-6{top:1.5rem}.top-8{top:2rem}.top-\[320px\]{top:320px}.isolate{isolation:isolate}.-z-10{z-index:-10}.z-10{z-index:10}.z-40{z-index:40}.z-50{z-index:50}.z-\[100\]{z-index:100}.col-span-12{grid-column:span 12/span 12}.mx-8{margin-left:2rem;margin-right:2rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-0{margin-bottom:0}.mb-1{margin-bottom:.25rem}.mb-10{margin-bottom:2.5rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-20{margin-bottom:5rem}.mb-24{margin-bottom:6rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-40{margin-bottom:10rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-64{margin-left:16rem}.mr-3{margin-right:.75rem}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-24{margin-top:6rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-40{margin-top:10rem}.mt-8{margin-top:2rem}.mt-auto{margin-top:auto}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.aspect-\[1\.6\/1\]{aspect-ratio:1.6/1}.aspect-video{aspect-ratio:16/9}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-20{height:5rem}.h-24{height:6rem}.h-3{height:.75rem}.h-32{height:8rem}.h-4{height:1rem}.h-40{height:10rem}.h-48{height:12rem}.h-52{height:13rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-8{height:2rem}.h-80{height:20rem}.h-9{height:2.25rem}.h-96{height:24rem}.h-\[600px\]{height:600px}.h-\[800px\]{height:800px}.h-\[calc\(100vh-4rem\)\]{height:calc(100vh - 4rem)}.h-\[calc\(100vh-64px\)\]{height:calc(100vh - 64px)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.min-h-\[180px\]{min-height:180px}.min-h-screen{min-height:100vh}.w-0\.5{width:.125rem}.w-1\/2{width:50%}.w-1\/3{width:33.333333%}.w-10{width:2.5rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\/3{width:66.666667%}.w-20{width:5rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\/4{width:75%}.w-32{width:8rem}.w-4\/6{width:66.666667%}.w-5\/6{width:83.333333%}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-\[800px\]{width:800px}.w-\[90vw\]{width:90vw}.w-full{width:100%}.w-px{width:1px}.min-w-\[100px\]{min-width:100px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-\[90\%\]{max-width:90%}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.flex-grow{flex-grow:1}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-full{--tw-translate-y:-100%}.-translate-y-full,.translate-y-4{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-4{--tw-translate-y:1rem}.scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05}.scale-105,.scale-110{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.scale-90{--tw-scale-x:.9;--tw-scale-y:.9}.scale-90,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-pointer{cursor:pointer}.resize{resize:both}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.gap-0{gap:0}.gap-1{gap:.25rem}.gap-12{gap:3rem}.gap-2{gap:.5rem}.gap-24{gap:6rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.gap-x-12{-moz-column-gap:3rem;column-gap:3rem}.gap-y-24{row-gap:6rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-16>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(4rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(4rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-24>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(6rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(6rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-outline-variant\/10>:not([hidden])~:not([hidden]){border-color:rgba(67,74,65,.1)}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.rounded{border-radius:.125rem}.rounded-2xl{border-radius:1rem}.rounded-\[0\.125rem\]{border-radius:.125rem}.rounded-full{border-radius:.75rem}.rounded-lg{border-radius:.25rem}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.5rem}.rounded-t-2xl{border-top-left-radius:1rem;border-top-right-radius:1rem}.rounded-t-xl{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-2{border-width:2px}.border-x{border-left-width:1px;border-right-width:1px}.border-b{border-bottom-width:1px}.border-l-4{border-left-width:4px}.border-r{border-right-width:1px}.border-r-2{border-right-width:2px}.border-t{border-top-width:1px}.border-none{border-style:none}.border-\[\#6b7a63\]{--tw-border-opacity:1;border-color:rgb(107 122 99/var(--tw-border-opacity,1))}.border-\[\#bbcbb1\]{--tw-border-opacity:1;border-color:rgb(187 203 177/var(--tw-border-opacity,1))}.border-outline-variant{--tw-border-opacity:1;border-color:rgb(67 74 65/var(--tw-border-opacity,1))}.border-outline-variant\/10{border-color:rgba(67,74,65,.1)}.border-outline-variant\/15{border-color:rgba(67,74,65,.15)}.border-outline-variant\/20{border-color:rgba(67,74,65,.2)}.border-outline-variant\/25{border-color:rgba(67,74,65,.25)}.border-outline-variant\/30{border-color:rgba(67,74,65,.3)}.border-outline-variant\/40{border-color:rgba(67,74,65,.4)}.border-outline-variant\/5{border-color:rgba(67,74,65,.05)}.border-primary{--tw-border-opacity:1;border-color:rgb(187 203 177/var(--tw-border-opacity,1))}.border-primary\/10{border-color:hsla(97,20%,75%,.1)}.border-primary\/20{border-color:hsla(97,20%,75%,.2)}.border-primary\/30{border-color:hsla(97,20%,75%,.3)}.border-primary\/40{border-color:hsla(97,20%,75%,.4)}.border-transparent{border-color:transparent}.border-white\/20{border-color:hsla(0,0%,100%,.2)}.border-white\/5{border-color:hsla(0,0%,100%,.05)}.bg-\[\#0d0f0c\]{--tw-bg-opacity:1;background-color:rgb(13 15 12/var(--tw-bg-opacity,1))}.bg-\[\#0d0f0c\]\/80{background-color:rgba(13,15,12,.8)}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-error-dim{--tw-bg-opacity:1;background-color:rgb(186 87 63/var(--tw-bg-opacity,1))}.bg-on-surface\/10{background-color:hsla(93,19%,88%,.1)}.bg-on-surface\/20{background-color:hsla(93,19%,88%,.2)}.bg-on-surface\/30{background-color:hsla(93,19%,88%,.3)}.bg-on-surface\/80{background-color:hsla(93,19%,88%,.8)}.bg-outline-variant{--tw-bg-opacity:1;background-color:rgb(67 74 65/var(--tw-bg-opacity,1))}.bg-outline-variant\/20{background-color:rgba(67,74,65,.2)}.bg-outline-variant\/30{background-color:rgba(67,74,65,.3)}.bg-primary{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.bg-primary-container{--tw-bg-opacity:1;background-color:rgb(61 75 54/var(--tw-bg-opacity,1))}.bg-primary-container\/20{background-color:rgba(61,75,54,.2)}.bg-primary-container\/30{background-color:rgba(61,75,54,.3)}.bg-primary\/10{background-color:hsla(97,20%,75%,.1)}.bg-primary\/15{background-color:hsla(97,20%,75%,.15)}.bg-primary\/20{background-color:hsla(97,20%,75%,.2)}.bg-primary\/40{background-color:hsla(97,20%,75%,.4)}.bg-secondary-container{--tw-bg-opacity:1;background-color:rgb(58 60 57/var(--tw-bg-opacity,1))}.bg-secondary\/15{background-color:hsla(75,2%,61%,.15)}.bg-secondary\/20{background-color:hsla(75,2%,61%,.2)}.bg-surface{--tw-bg-opacity:1;background-color:rgb(13 15 12/var(--tw-bg-opacity,1))}.bg-surface-container{--tw-bg-opacity:1;background-color:rgb(23 27 22/var(--tw-bg-opacity,1))}.bg-surface-container-high{--tw-bg-opacity:1;background-color:rgb(28 33 27/var(--tw-bg-opacity,1))}.bg-surface-container-highest{--tw-bg-opacity:1;background-color:rgb(33 39 32/var(--tw-bg-opacity,1))}.bg-surface-container-low{--tw-bg-opacity:1;background-color:rgb(17 20 16/var(--tw-bg-opacity,1))}.bg-surface-container-low\/50{background-color:rgba(17,20,16,.5)}.bg-surface-container-lowest{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.bg-\[linear-gradient\(to_right\2c \#1c211b_1px\2c transparent_1px\)\2c linear-gradient\(to_bottom\2c \#1c211b_1px\2c transparent_1px\)\]{background-image:linear-gradient(90deg,#1c211b 1px,transparent 0),linear-gradient(180deg,#1c211b 1px,transparent 0)}.bg-\[radial-gradient\(circle_at_center\2c _var\(--tw-gradient-from\)_0\%\2c _transparent_70\%\)\]{background-image:radial-gradient(circle at center,var(--tw-gradient-from) 0,transparent 70%)}.bg-\[radial-gradient\(ellipse_at_center\2c _transparent_0\%\2c _\#0d0f0c_85\%\)\]{background-image:radial-gradient(ellipse at center,transparent 0,#0d0f0c 85%)}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.bg-gradient-to-tr{background-image:linear-gradient(to top right,var(--tw-gradient-stops))}.from-primary{--tw-gradient-from:#bbcbb1 var(--tw-gradient-from-position);--tw-gradient-to:hsla(97,20%,75%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-primary\/10{--tw-gradient-from:hsla(97,20%,75%,.1) var(--tw-gradient-from-position);--tw-gradient-to:hsla(97,20%,75%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-surface{--tw-gradient-from:#0d0f0c var(--tw-gradient-from-position);--tw-gradient-to:rgba(13,15,12,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-surface-container-high\/50{--tw-gradient-from:rgba(28,33,27,.5) var(--tw-gradient-from-position);--tw-gradient-to:rgba(28,33,27,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-transparent{--tw-gradient-from:transparent var(--tw-gradient-from-position);--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-primary\/30{--tw-gradient-to:hsla(97,20%,75%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),hsla(97,20%,75%,.3) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-primary\/40{--tw-gradient-to:hsla(97,20%,75%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),hsla(97,20%,75%,.4) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),transparent var(--tw-gradient-via-position),var(--tw-gradient-to)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.bg-\[size\:40px_40px\]{background-size:40px 40px}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-10{padding:2.5rem}.p-12{padding:3rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-12{padding-bottom:3rem}.pb-24{padding-bottom:6rem}.pb-32{padding-bottom:8rem}.pb-4{padding-bottom:1rem}.pl-16{padding-left:4rem}.pl-4{padding-left:1rem}.pl-8{padding-left:2rem}.pr-6{padding-right:1.5rem}.pr-8{padding-right:2rem}.pt-0{padding-top:0}.pt-10{padding-top:2.5rem}.pt-2{padding-top:.5rem}.pt-24{padding-top:6rem}.pt-28{padding-top:7rem}.pt-32{padding-top:8rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-\[\'Manrope\'\]{font-family:Manrope}.font-body{font-family:Manrope,system-ui,sans-serif}.font-headline{font-family:Space Grotesk,system-ui,sans-serif}.font-label{font-family:Manrope,system-ui,sans-serif}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem}.text-5xl,.text-6xl{line-height:1}.text-6xl{font-size:3.75rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[18px\]{font-size:18px}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.normal-case{text-transform:none}.leading-\[0\.9\]{line-height:.9}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-\[-0\.04em\]{letter-spacing:-.04em}.tracking-\[0\.15em\]{letter-spacing:.15em}.tracking-\[0\.1em\]{letter-spacing:.1em}.tracking-\[0\.25em\]{letter-spacing:.25em}.tracking-\[0\.2em\]{letter-spacing:.2em}.tracking-\[0\.4em\]{letter-spacing:.4em}.tracking-tight{letter-spacing:-.025em}.tracking-tighter{letter-spacing:-.05em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-\[\#6b7a63\]{--tw-text-opacity:1;color:rgb(107 122 99/var(--tw-text-opacity,1))}.text-\[\#727d6d\]{--tw-text-opacity:1;color:rgb(114 125 109/var(--tw-text-opacity,1))}.text-\[\#bbcbb1\]{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.text-error{--tw-text-opacity:1;color:rgb(237 127 100/var(--tw-text-opacity,1))}.text-on-primary{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.text-on-primary-container{--tw-text-opacity:1;color:rgb(197 213 186/var(--tw-text-opacity,1))}.text-on-secondary-container{--tw-text-opacity:1;color:rgb(191 192 187/var(--tw-text-opacity,1))}.text-on-surface{--tw-text-opacity:1;color:rgb(225 231 220/var(--tw-text-opacity,1))}.text-on-surface-variant{--tw-text-opacity:1;color:rgb(167 173 162/var(--tw-text-opacity,1))}.text-on-surface-variant\/40{color:hsla(93,6%,66%,.4)}.text-on-surface-variant\/50{color:hsla(93,6%,66%,.5)}.text-on-surface\/40{color:hsla(93,19%,88%,.4)}.text-on-surface\/60{color:hsla(93,19%,88%,.6)}.text-outline{--tw-text-opacity:1;color:rgb(113 119 110/var(--tw-text-opacity,1))}.text-primary{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.text-primary-dim{--tw-text-opacity:1;color:rgb(174 190 164/var(--tw-text-opacity,1))}.text-primary\/20{color:hsla(97,20%,75%,.2)}.text-primary\/40{color:hsla(97,20%,75%,.4)}.text-primary\/50{color:hsla(97,20%,75%,.5)}.text-primary\/60{color:hsla(97,20%,75%,.6)}.text-primary\/70{color:hsla(97,20%,75%,.7)}.text-primary\/80{color:hsla(97,20%,75%,.8)}.text-secondary{--tw-text-opacity:1;color:rgb(157 158 154/var(--tw-text-opacity,1))}.text-tertiary{--tw-text-opacity:1;color:rgb(241 255 212/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.decoration-primary\/50{text-decoration-color:hsla(97,20%,75%,.5)}.underline-offset-4{text-underline-offset:4px}.accent-primary{accent-color:#bbcbb1}.opacity-0{opacity:0}.opacity-10{opacity:.1}.opacity-20{opacity:.2}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.opacity-90{opacity:.9}.opacity-95{opacity:.95}.opacity-\[0\.03\]{opacity:.03}.mix-blend-overlay{mix-blend-mode:overlay}.mix-blend-luminosity{mix-blend-mode:luminosity}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-\[0_-20px_50px_rgba\(0\2c 0\2c 0\2c 0\.5\)\]{--tw-shadow:0 -20px 50px rgba(0,0,0,.5);--tw-shadow-colored:0 -20px 50px var(--tw-shadow-color)}.shadow-\[0_-20px_50px_rgba\(0\2c 0\2c 0\2c 0\.5\)\],.shadow-\[0_-30px_60px_rgba\(0\2c 0\2c 0\2c 0\.6\)\]{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_-30px_60px_rgba\(0\2c 0\2c 0\2c 0\.6\)\]{--tw-shadow:0 -30px 60px rgba(0,0,0,.6);--tw-shadow-colored:0 -30px 60px var(--tw-shadow-color)}.shadow-\[0_0_15px_rgba\(187\2c 203\2c 177\2c 0\.8\)\]{--tw-shadow:0 0 15px hsla(97,20%,75%,.8);--tw-shadow-colored:0 0 15px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_30px_rgba\(187\2c 203\2c 177\2c 0\.3\)\]{--tw-shadow:0 0 30px hsla(97,20%,75%,.3);--tw-shadow-colored:0 0 30px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_50px_rgba\(187\2c 203\2c 177\2c 0\.4\)\]{--tw-shadow:0 0 50px hsla(97,20%,75%,.4);--tw-shadow-colored:0 0 50px var(--tw-shadow-color)}.shadow-\[0_0_50px_rgba\(187\2c 203\2c 177\2c 0\.4\)\],.shadow-\[20px_0_40px_rgba\(0\2c 0\2c 0\2c 0\.4\)\]{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[20px_0_40px_rgba\(0\2c 0\2c 0\2c 0\.4\)\]{--tw-shadow:20px 0 40px rgba(0,0,0,.4);--tw-shadow-colored:20px 0 40px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-sm,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.shadow-primary\/10{--tw-shadow-color:hsla(97,20%,75%,.1);--tw-shadow:var(--tw-shadow-colored)}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-2{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-4{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-primary\/20{--tw-ring-color:hsla(97,20%,75%,.2)}.blur{--tw-blur:blur(8px)}.blur,.grayscale{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.grayscale{--tw-grayscale:grayscale(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-xl{--tw-backdrop-blur:blur(24px)}.backdrop-blur-xl,.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-1000{transition-duration:1s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-700{transition-duration:.7s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.selection\:bg-primary ::-moz-selection{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.selection\:bg-primary ::selection{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.selection\:text-on-primary ::-moz-selection{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.selection\:text-on-primary ::selection{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.selection\:bg-primary::-moz-selection{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.selection\:bg-primary::selection{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.selection\:text-on-primary::-moz-selection{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.selection\:text-on-primary::selection{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.placeholder\:text-on-surface-variant\/40::-moz-placeholder{color:hsla(93,6%,66%,.4)}.placeholder\:text-on-surface-variant\/40::placeholder{color:hsla(93,6%,66%,.4)}.hover\:-translate-y-1:hover{--tw-translate-y:-0.25rem}.hover\:-translate-y-1:hover,.hover\:translate-y-\[-10px\]:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:translate-y-\[-10px\]:hover{--tw-translate-y:-10px}.hover\:translate-y-\[-20px\]:hover{--tw-translate-y:-20px}.hover\:translate-y-\[-20px\]:hover,.hover\:translate-y-\[-2px\]:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:translate-y-\[-2px\]:hover{--tw-translate-y:-2px}.hover\:translate-y-\[-30px\]:hover{--tw-translate-y:-30px}.hover\:scale-95:hover,.hover\:translate-y-\[-30px\]:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-95:hover{--tw-scale-x:.95;--tw-scale-y:.95}.hover\:bg-\[\#1a1d18\]:hover{--tw-bg-opacity:1;background-color:rgb(26 29 24/var(--tw-bg-opacity,1))}.hover\:bg-primary:hover{--tw-bg-opacity:1;background-color:rgb(187 203 177/var(--tw-bg-opacity,1))}.hover\:bg-primary-container:hover{--tw-bg-opacity:1;background-color:rgb(61 75 54/var(--tw-bg-opacity,1))}.hover\:bg-surface-bright:hover{--tw-bg-opacity:1;background-color:rgb(39 46 37/var(--tw-bg-opacity,1))}.hover\:bg-surface-container-high:hover{--tw-bg-opacity:1;background-color:rgb(28 33 27/var(--tw-bg-opacity,1))}.hover\:bg-surface-container-highest:hover{--tw-bg-opacity:1;background-color:rgb(33 39 32/var(--tw-bg-opacity,1))}.hover\:bg-white\/5:hover{background-color:hsla(0,0%,100%,.05)}.hover\:text-\[\#bbcbb1\]:hover{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.hover\:text-on-primary:hover{--tw-text-opacity:1;color:rgb(54 68 48/var(--tw-text-opacity,1))}.hover\:text-on-surface:hover{--tw-text-opacity:1;color:rgb(225 231 220/var(--tw-text-opacity,1))}.hover\:text-primary:hover{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.hover\:opacity-90:hover{opacity:.9}.hover\:shadow-\[0_0_20px_rgba\(187\2c 203\2c 177\2c 0\.3\)\]:hover{--tw-shadow:0 0 20px hsla(97,20%,75%,.3);--tw-shadow-colored:0 0 20px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:brightness-110:hover{--tw-brightness:brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:border-primary\/60:focus{border-color:hsla(97,20%,75%,.6)}.focus\:ring-0:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-0:focus,.focus\:ring-1:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-primary\/40:focus{--tw-ring-color:hsla(97,20%,75%,.4)}.active\:scale-95:active{--tw-scale-x:.95;--tw-scale-y:.95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:focus-within .group-focus-within\:text-primary{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.group:hover .group-hover\:-translate-y-1{--tw-translate-y:-0.25rem}.group:hover .group-hover\:-translate-y-1,.group:hover .group-hover\:translate-x-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:translate-x-1{--tw-translate-x:0.25rem}.group:hover .group-hover\:translate-y-0{--tw-translate-y:0px}.group:hover .group-hover\:rotate-180,.group:hover .group-hover\:translate-y-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:rotate-180{--tw-rotate:180deg}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:border-primary\/20{border-color:hsla(97,20%,75%,.2)}.group:hover .group-hover\:text-primary{--tw-text-opacity:1;color:rgb(187 203 177/var(--tw-text-opacity,1))}.group:hover .group-hover\:text-primary\/40{color:hsla(97,20%,75%,.4)}.group:hover .group-hover\:opacity-100{opacity:1}.group:hover .group-hover\:opacity-20{opacity:.2}.group:hover .group-hover\:brightness-110{--tw-brightness:brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.dark\:bg-\[\#0d0f0c\]:is(.dark *){--tw-bg-opacity:1;background-color:rgb(13 15 12/var(--tw-bg-opacity,1))}@media (min-width:768px){.md\:col-span-2{grid-column:span 2/span 2}.md\:col-span-5{grid-column:span 5/span 5}.md\:col-span-7{grid-column:span 7/span 7}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-end{align-items:flex-end}}@media (min-width:1024px){.lg\:col-span-5{grid-column:span 5/span 5}.lg\:col-span-7{grid-column:span 7/span 7}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:px-12{padding-left:3rem;padding-right:3rem}}@media (min-width:1280px){.xl\:text-7xl{font-size:4.5rem;line-height:1}} \ No newline at end of file diff --git a/apps/showcase/public/css/velora.css b/apps/showcase/public/css/velora.css index e66f73a..339d111 100644 --- a/apps/showcase/public/css/velora.css +++ b/apps/showcase/public/css/velora.css @@ -16,6 +16,8 @@ @import "./04c-structures.css"; @import "./04d-premium.css"; @import "./04e-showcase-elevation-patterns.css"; +@import "./04f-carousel.css"; +@import "./04g-anchor.css"; @import "./05-transitions.css"; @import "./06-utilities.css"; @import "./07-overrides.css"; diff --git a/packages/css/src/01-tokens.css b/packages/css/src/01-tokens.css index bedae58..33577ae 100644 --- a/packages/css/src/01-tokens.css +++ b/packages/css/src/01-tokens.css @@ -256,6 +256,61 @@ --vl-ease-elastic: cubic-bezier(0.68, -0.55, 0.265, 1.55); --vl-ease-smooth-out: cubic-bezier(0, 0.55, 0.45, 1); + /* --- 2026 Platform easing (Material 3 Expressive / Google I/O 2026) --- */ + --vl-ease-spring-expressive: cubic-bezier(0.175, 0.885, 0.32, 1.275); + --vl-ease-spring-snappy: cubic-bezier(0.34, 1.8, 0.64, 1); + --vl-ease-decelerate: cubic-bezier(0.0, 0.0, 0.2, 1); + --vl-ease-accelerate: cubic-bezier(0.4, 0.0, 1.0, 1.0); + --vl-ease-emphasized: cubic-bezier(0.2, 0.0, 0, 1.0); + --vl-duration-express: 200ms; + --vl-duration-emphasized: 500ms; + + /* --- Wide-gamut accent (display-p3 for P3-capable displays) --- */ + --vl-color-p3-primary: color(display-p3 0.498 0.525 0.407); + --vl-color-p3-accent: color(display-p3 0.361 0.376 0.298); + --vl-color-p3-vivid: color(display-p3 0.55 0.62 0.38); + + /* --- Liquid glass (Apple 2026 — enhanced backdrop layer) --- */ + --vl-liquid-glass-bg: color-mix(in oklch, var(--vl-bg-surface) 58%, transparent); + --vl-liquid-glass-blur: 28px; + --vl-liquid-glass-saturate: 1.6; + --vl-liquid-glass-border: color-mix(in oklch, white 38%, transparent); + --vl-liquid-glass-shadow: + 0 8px 32px color-mix(in oklch, var(--vl-color-primary) 12%, transparent), + inset 0 1px 0 color-mix(in oklch, white 28%, transparent); + + /* --- AI state tokens (streaming / generation patterns) --- */ + --vl-ai-shimmer-start: color-mix(in oklch, var(--vl-bg-surface) 96%, transparent); + --vl-ai-shimmer-mid: color-mix(in oklch, var(--vl-color-primary) 9%, var(--vl-bg-surface)); + --vl-ai-shimmer-end: color-mix(in oklch, var(--vl-bg-surface) 96%, transparent); + --vl-ai-stream-color: color-mix(in oklch, var(--vl-color-primary) 55%, transparent); + --vl-ai-glow: 0 0 0 1px color-mix(in oklch, var(--vl-color-primary) 22%, transparent), + 0 0 20px color-mix(in oklch, var(--vl-color-primary) 14%, transparent); + --vl-ai-duration: 1.8s; + + /* --- CSS Carousel (::scroll-marker / ::scroll-button — Chrome 135+) --- */ + --vl-carousel-marker-size: 0.5rem; + --vl-carousel-marker-gap: 0.375rem; + --vl-carousel-marker-color: var(--vl-border-strong); + --vl-carousel-marker-active: var(--vl-color-primary); + --vl-carousel-btn-size: 2.5rem; + --vl-carousel-item-width: min(80vw, 20rem); + --vl-carousel-gap: var(--vl-space-md); + + /* --- CSS Anchor Positioning (Chrome 125+ / Safari 18.2+) --- */ + --vl-anchor-gap: 0.375rem; + --vl-tooltip-max-width: 16rem; + --vl-float-min-width: 10rem; + + /* --- Edge-to-edge (safe-area-max-inset — Chrome 135+) --- */ + --vl-safe-top: env(safe-area-inset-top, 0px); + --vl-safe-bottom: env(safe-area-inset-bottom, 0px); + --vl-safe-left: env(safe-area-inset-left, 0px); + --vl-safe-right: env(safe-area-inset-right, 0px); + + /* --- Dynamic range (HDR) --- */ + --vl-dynamic-range: standard; + color-scheme: light; } diff --git a/packages/css/src/02-layout.css b/packages/css/src/02-layout.css index c5bbcbe..1e44053 100644 --- a/packages/css/src/02-layout.css +++ b/packages/css/src/02-layout.css @@ -457,4 +457,93 @@ align-self: start; z-index: var(--vl-z-base); } + + /* ========================================================================= + READING FLOW (Chrome 137+ — CSS reading-flow) + Ensures keyboard tab order follows the visual reading order in flex/grid + layouts, not the DOM source order. Critical for accessibility in + visually-reordered layouts. + @see https://developer.chrome.com/blog/reading-flow + ========================================================================= */ + @supports (reading-flow: normal) { + .vl-grid[vl-reading="rows"], + [vl-reading="rows"] { + reading-flow: grid-rows; + } + + .vl-grid[vl-reading="columns"], + [vl-reading="columns"] { + reading-flow: grid-columns; + } + + .vl-stack[vl-reading="visual"], + .vl-flex[vl-reading="visual"], + [vl-reading="visual"] { + reading-flow: flex-visual; + } + + .vl-stack[vl-reading="flow"], + .vl-flex[vl-reading="flow"], + [vl-reading="flow"] { + reading-flow: flex-flow; + } + + /* Source-order override (useful for decorative reordering) */ + [vl-reading="source"] { + reading-flow: source-order; + } + } + + /* ========================================================================= + EDGE-TO-EDGE (safe-area-max-inset — Chrome 135+) + Performant edge-to-edge layouts that never move during scroll. + ========================================================================= */ + + /** + * Full-bleed section that respects both safe-area dynamic insets AND the + * maximum possible safe-area for performant, non-reflowing layouts. + */ + .vl-edge-to-edge { + padding-inline: max(var(--vl-container-gutter), var(--vl-safe-left, env(safe-area-inset-left, 0px))); + padding-inline-end: max(var(--vl-container-gutter), var(--vl-safe-right, env(safe-area-inset-right, 0px))); + } + + .vl-edge-to-edge--block { + padding-block-start: max(var(--vl-space-md), var(--vl-safe-top, env(safe-area-inset-top, 0px))); + padding-block-end: max(var(--vl-space-md), var(--vl-safe-bottom, env(safe-area-inset-bottom, 0px))); + } + + /* ========================================================================= + LIQUID GLASS SURFACE (Apple 2026 design direction) + A backdrop-filter surface with depth and luminance. Pairs with vl-scene. + ========================================================================= */ + .vl-glass--liquid { + background: var(--vl-liquid-glass-bg); + backdrop-filter: + blur(var(--vl-liquid-glass-blur)) + saturate(var(--vl-liquid-glass-saturate)); + -webkit-backdrop-filter: + blur(var(--vl-liquid-glass-blur)) + saturate(var(--vl-liquid-glass-saturate)); + border: 1px solid var(--vl-liquid-glass-border); + box-shadow: var(--vl-liquid-glass-shadow); + } + + /* ========================================================================= + HDR CONTENT CONTROL (Chrome 135+ — dynamic-range-limit) + Prevent overbright HDR content from dominating the composition. + ========================================================================= */ + @supports (dynamic-range-limit: standard) { + [vl-hdr="constrained"] { + dynamic-range-limit: constrained-high; + } + + [vl-hdr="standard"] { + dynamic-range-limit: standard; + } + + [vl-hdr="auto"] { + dynamic-range-limit: no-limit; + } + } } diff --git a/packages/css/src/03b-motion-extended.css b/packages/css/src/03b-motion-extended.css index db74251..d620bf9 100644 --- a/packages/css/src/03b-motion-extended.css +++ b/packages/css/src/03b-motion-extended.css @@ -2337,4 +2337,238 @@ animation-timeline: view(); animation-range: entry 10% entry 60%; } + + /* ========================================================================= + 2026 PLATFORM MOTION — Google I/O 2026 · Apple · Material 3 Expressive + New presets leveraging CSS shape(), spring-expressive easing, + liquid glass entrance, and AI streaming states. + ========================================================================= */ + + /* --- Material 3 Expressive spring (vl-effect="spring-express") --- + Asymmetric overshoot + settle. The "express" spring is snappier than + the existing spring-up, designed for UI confirmations and taps. + ------------------------------------------------------------------- */ + @keyframes vl-spring-express { + 0% { opacity: 0; transform: scale(0.82) translateY(1rem); } + 45% { opacity: 1; transform: scale(1.04) translateY(-0.18rem); } + 65% { transform: scale(0.98) translateY(0.05rem); } + 82% { transform: scale(1.01); } + 100% { opacity: 1; transform: scale(1) translateY(0); } + } + + [vl-effect="spring-express"] { + animation: vl-spring-express var(--vl-duration-express, 200ms) var(--vl-ease-spring-expressive, cubic-bezier(0.175, 0.885, 0.32, 1.275)) both; + + @media (prefers-reduced-motion: reduce) { + animation: none; + opacity: 1; + transform: none; + } + } + + /* --- Liquid glass entrance (Apple 2026 — vl-effect="liquid-in") --- + Saturate + blur dissolve with a slight scale. Pairs with .vl-glass--liquid. + ------------------------------------------------------------------- */ + @keyframes vl-liquid-in { + 0% { + opacity: 0; + filter: blur(14px) saturate(0.4); + transform: scale(0.94); + } + + 55% { + filter: blur(3px) saturate(0.9); + } + + 100% { + opacity: 1; + filter: blur(0) saturate(1); + transform: scale(1); + } + } + + [vl-effect="liquid-in"] { + animation: vl-liquid-in var(--vl-duration-slow, 500ms) var(--vl-ease-emphasized, cubic-bezier(0.2, 0, 0, 1)) both; + + @media (prefers-reduced-motion: reduce) { + animation: none; + opacity: 1; + filter: none; + transform: none; + } + } + + /* --- CSS shape() clip reveal (Chrome 135+ — vl-effect="shape-reveal") --- + Organic left-to-right clip wipe using the responsive shape() function. + Falls back silently; content remains visible without the clip animation. + ------------------------------------------------------------------- */ + @supports (clip-path: shape(from 0% 0%, line to 100% 0%, line to 100% 100%, line to 0% 100%)) { + @keyframes vl-shape-reveal { + from { + clip-path: shape(from 0% 0%, line to 0% 0%, line to 0% 100%, line to 0% 100%); + opacity: 0.7; + } + + to { + clip-path: shape(from 0% 0%, line to 100% 0%, line to 100% 100%, line to 0% 100%); + opacity: 1; + } + } + + @keyframes vl-shape-reveal-organic { + from { + clip-path: shape( + from 0% 0%, + line to 0% 0%, + curve to 0% 60% via 2% 30%, 1% 45%, + line to 0% 100%, + line to 0% 100% + ); + } + + 50% { + clip-path: shape( + from 0% 0%, + line to 60% 0%, + curve to 55% 55% via 65% 10%, 62% 35%, + curve to 60% 100% via 58% 75%, 62% 90%, + line to 0% 100% + ); + } + + to { + clip-path: shape( + from 0% 0%, + line to 100% 0%, + line to 100% 100%, + line to 0% 100% + ); + } + } + + [vl-effect="shape-reveal"] { + animation: vl-shape-reveal var(--vl-motion-duration, 300ms) var(--vl-ease-cinematic) both; + + @media (prefers-reduced-motion: reduce) { + animation: none; + opacity: 1; + clip-path: none; + } + } + + [vl-effect="shape-reveal"][vl-variant="organic"] { + animation-name: vl-shape-reveal-organic; + animation-duration: var(--vl-duration-slow, 500ms); + } + } + + /* --- AI shimmer / streaming state (vl-effect="ai-shimmer") --- + CSS-only shimmer for skeleton loading and AI content generation states. + ------------------------------------------------------------------- */ + @keyframes vl-ai-shimmer { + 0% { background-position: -200% center; } + 100% { background-position: 200% center; } + } + + @keyframes vl-ai-pulse-glow { + 0%, 100% { box-shadow: var(--vl-ai-glow, 0 0 0 1px currentColor); opacity: 0.85; } + 50% { box-shadow: 0 0 0 3px color-mix(in oklch, var(--vl-color-primary) 28%, transparent); opacity: 1; } + } + + [vl-effect="ai-shimmer"] { + background: linear-gradient( + 90deg, + var(--vl-ai-shimmer-start, color-mix(in oklch, var(--vl-bg-surface) 96%, transparent)), + var(--vl-ai-shimmer-mid, color-mix(in oklch, var(--vl-color-primary) 9%, var(--vl-bg-surface))), + var(--vl-ai-shimmer-end, color-mix(in oklch, var(--vl-bg-surface) 96%, transparent)) + ); + background-size: 200% 100%; + animation: vl-ai-shimmer var(--vl-ai-duration, 1.8s) linear infinite; + border-radius: inherit; + + @media (prefers-reduced-motion: reduce) { + animation: none; + background: var(--vl-bg-surface); + } + } + + [vl-effect="ai-glow"] { + animation: vl-ai-pulse-glow var(--vl-ai-duration, 1.8s) var(--vl-ease-in-out-smooth) infinite; + + @media (prefers-reduced-motion: reduce) { + animation: none; + } + } + + /* Skeleton block: zero-markup content placeholder */ + .vl-skeleton { + --vl-skeleton-radius: var(--vl-radius-sm); + display: block; + border-radius: var(--vl-skeleton-radius); + min-height: 1em; + } + + .vl-skeleton[vl-effect="ai-shimmer"] { + min-height: var(--vl-skeleton-height, 1em); + width: var(--vl-skeleton-width, 100%); + } + + .vl-skeleton--text { + --vl-skeleton-height: 1rem; + --vl-skeleton-radius: var(--vl-radius-sm); + } + + .vl-skeleton--heading { + --vl-skeleton-height: 1.75rem; + --vl-skeleton-radius: var(--vl-radius-sm); + } + + .vl-skeleton--avatar { + --vl-skeleton-height: 2.5rem; + --vl-skeleton-width: 2.5rem; + --vl-skeleton-radius: var(--vl-radius-full); + aspect-ratio: 1; + } + + /* --- offset-path: shape() motion path (Chrome 137+) --- + Animate an element along a responsive free-form path. + ------------------------------------------------------------------- */ + @supports (offset-path: shape(from 0% 0%, line to 100% 100%)) { + [vl-effect="path-arc"] { + offset-path: shape(from 50% 100%, curve to 100% 0% via 100% 100%, 100% 0%); + animation: vl-path-travel var(--vl-duration-slow, 500ms) var(--vl-ease-cinematic) both; + + @media (prefers-reduced-motion: reduce) { + animation: none; + offset-path: none; + } + } + + @keyframes vl-path-travel { + from { offset-distance: 0%; opacity: 0; } + to { offset-distance: 100%; opacity: 1; } + } + } + + /* --- CSS if() conditional style hook (Chrome 137+) --- + Token-level conditional utility — component examples use this for + smart variant switching without extra class proliferation. + ------------------------------------------------------------------- */ + @supports (color: if(style(--vl-variant: ghost): transparent; else: red)) { + .vl-cta { + /* Ghost variant switches background + border via if() */ + background-color: if( + style(--vl-variant: ghost): transparent; + else: var(--vl-color-primary) + ); + border-color: if( + style(--vl-variant: ghost): currentColor; + else: transparent + ); + color: if( + style(--vl-variant: ghost): var(--vl-color-primary); + else: var(--vl-text-inverse) + ); + } + } } diff --git a/packages/css/src/04f-carousel.css b/packages/css/src/04f-carousel.css new file mode 100644 index 0000000..bcd1eaa --- /dev/null +++ b/packages/css/src/04f-carousel.css @@ -0,0 +1,214 @@ +@layer velora.components { + /* + * CSS-Native Carousel — vl-carousel + * Zero JavaScript. Powered by scroll-snap + CSS Scroll Markers API (Chrome 135+) + * and ::scroll-button() pseudo-elements (Chrome 135+). + * + * Public API: + * .vl-carousel Scroll carousel container + * .vl-carousel--center Center-snap variant + * .vl-carousel--peek Peek at adjacent slides + * .vl-carousel > * Any direct children become slides + * vl-scroll-buttons Attribute — adds ::scroll-button() nav + * --vl-carousel-item-width Per-slide width (default: min(80vw, 20rem)) + * --vl-carousel-gap Gap between slides + * --vl-carousel-marker-size Scroll marker dot size + * --vl-carousel-marker-color Inactive marker color + * --vl-carousel-marker-active Active marker color + * + * Markup pattern: + * + * + * Browser support: + * Scroll-snap: all modern browsers (Chrome 124+, Safari 18+, Firefox 128+) + * ::scroll-marker: Chrome 135+ (progressive enhancement, @supports-guarded) + * ::scroll-button(): Chrome 135+ (progressive enhancement, @supports-guarded) + */ + + /* ------------------------------------------------------------------------- + Base carousel — scroll-snap, hidden scrollbar, touch-friendly + ------------------------------------------------------------------------- */ + .vl-carousel { + --vl-carousel-item-width: min(80vw, 20rem); + --vl-carousel-gap: var(--vl-space-md); + + display: flex; + gap: var(--vl-carousel-gap); + overflow-x: auto; + overflow-y: hidden; + scroll-snap-type: x mandatory; + scroll-behavior: smooth; + overscroll-behavior-x: contain; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + padding-block: var(--vl-space-xs); /* preserve box-shadow on children */ + } + + .vl-carousel::-webkit-scrollbar { + display: none; + } + + /* Slides — snap to start by default */ + .vl-carousel > * { + flex: 0 0 var(--vl-carousel-item-width); + scroll-snap-align: start; + min-width: 0; + } + + /* Center-snap variant */ + .vl-carousel--center > * { + scroll-snap-align: center; + } + + /* Peek variant — show edge of next slide */ + .vl-carousel--peek { + --vl-carousel-item-width: min(75vw, 18rem); + padding-inline-end: calc(var(--vl-carousel-gap) * 2); + } + + /* Full-width slides */ + .vl-carousel--full > * { + flex: 0 0 100%; + scroll-snap-align: start; + } + + /* ------------------------------------------------------------------------- + CSS Scroll Markers (Chrome 135+) + Renders a navigation dot group after the carousel with zero JS. + @see https://developer.chrome.com/blog/css-scroll-markers + ------------------------------------------------------------------------- */ + @supports selector(.x::scroll-marker) { + .vl-carousel { + scroll-marker-group: after; + } + + /* Each slide contributes a dot to the marker group */ + .vl-carousel > *::scroll-marker { + content: ""; + display: block; + width: var(--vl-carousel-marker-size, 0.5rem); + height: var(--vl-carousel-marker-size, 0.5rem); + border-radius: var(--vl-radius-full); + background: var(--vl-carousel-marker-color, var(--vl-border-strong)); + transition: + background var(--vl-duration-fast) var(--vl-ease-out-soft), + transform var(--vl-duration-fast) var(--vl-ease-spring), + opacity var(--vl-duration-fast) var(--vl-ease-out-soft); + } + + /* Active (current) dot */ + .vl-carousel > *::scroll-marker:target-current { + background: var(--vl-carousel-marker-active, var(--vl-color-primary)); + transform: scale(1.5); + } + + /* Marker group container */ + .vl-carousel::scroll-marker-group { + display: flex; + justify-content: center; + align-items: center; + gap: var(--vl-carousel-marker-gap, 0.375rem); + padding-block: var(--vl-space-md) var(--vl-space-xs); + /* Inherit layout width so it aligns with the carousel */ + width: 100%; + } + + /* Elongated active marker variant */ + .vl-carousel--pill > *::scroll-marker:target-current { + width: 1.5rem; + border-radius: var(--vl-radius-full); + transform: none; + } + } + + /* ------------------------------------------------------------------------- + CSS Scroll Buttons (Chrome 135+) + Prev / next controls rendered as ::pseudo-elements — no HTML needed. + Apply the [vl-scroll-buttons] attribute to opt in. + ------------------------------------------------------------------------- */ + @supports selector(.x::scroll-button(inline-start)) { + .vl-carousel[vl-scroll-buttons] { + position: relative; + } + + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-start), + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-end) { + /* Layout */ + position: absolute; + top: 50%; + transform: translateY(-50%); + width: var(--vl-carousel-btn-size, 2.5rem); + height: var(--vl-carousel-btn-size, 2.5rem); + + /* Appearance */ + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--vl-radius-full); + background: var(--vl-bg-surface); + border: 1px solid var(--vl-border-subtle); + color: var(--vl-text-primary); + font-size: var(--vl-font-size-md); + cursor: pointer; + box-shadow: var(--vl-shadow-md); + z-index: var(--vl-z-base); + + transition: + opacity var(--vl-duration-fast) var(--vl-ease-out-soft), + background var(--vl-duration-fast) var(--vl-ease-out-soft), + box-shadow var(--vl-duration-fast) var(--vl-ease-out-soft), + transform var(--vl-duration-fast) var(--vl-ease-spring); + } + + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-start) { + content: "‹"; + inset-inline-start: calc(var(--vl-carousel-btn-size, 2.5rem) * -0.5); + } + + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-end) { + content: "›"; + inset-inline-end: calc(var(--vl-carousel-btn-size, 2.5rem) * -0.5); + } + + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-start):hover, + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-end):hover { + background: var(--vl-bg-surface-elevated); + box-shadow: var(--vl-shadow-lg); + transform: translateY(calc(-50% - 1px)); + } + + /* Disabled state when no more content to scroll */ + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-start):disabled, + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-end):disabled { + opacity: 0.25; + cursor: not-allowed; + transform: translateY(-50%); + } + + /* Focus-visible ring */ + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-start):focus-visible, + .vl-carousel[vl-scroll-buttons]::scroll-button(inline-end):focus-visible { + outline: var(--vl-focus-ring-width) solid var(--vl-focus-ring-color); + outline-offset: var(--vl-focus-ring-offset); + } + } + + /* ------------------------------------------------------------------------- + Accessibility + ------------------------------------------------------------------------- */ + @media (prefers-reduced-motion: reduce) { + .vl-carousel { + scroll-behavior: auto; + } + + @supports selector(.x::scroll-marker) { + .vl-carousel > *::scroll-marker { + transition: none; + } + } + } +} diff --git a/packages/css/src/04g-anchor.css b/packages/css/src/04g-anchor.css new file mode 100644 index 0000000..9ca229f --- /dev/null +++ b/packages/css/src/04g-anchor.css @@ -0,0 +1,266 @@ +@layer velora.components { + /* + * CSS Anchor Positioning — vl-anchor-group / vl-tooltip / vl-float + * Zero JavaScript floating UI using the CSS Anchor Positioning API. + * + * Browser support: + * Chrome 125+, Safari 18.2+. Firefox: pending (graceful degradation via + * @supports guard — elements remain visible, just not anchor-positioned). + * + * Architecture: container-based pattern + * The [vl-anchor-group] wrapper establishes a relative context as a fallback. + * Inside it, the first [vl-anchor-trigger] element is the anchor source. + * Positioned elements ([vl-tooltip], [vl-float]) are auto-positioned via CSS. + * + * Public API: + * [vl-anchor-group] Container that scopes the anchor relationship + * [vl-anchor-trigger] The element that acts as the anchor point + * [vl-tooltip] Small inline label above the anchor + * [vl-tooltip][vl-position="*"] Override position: top|bottom|left|right + * [vl-float] Dropdown/panel below the anchor + * [vl-float][vl-position="*"] Override position: top|bottom|left|right + * popover + popovertarget Add popover API for toggle behavior (no JS) + * + * Markup — tooltip (hover + focus, using popover="hint"): + *
    + * + *
    Tooltip text
    + *
    + * + * Markup — floating dropdown: + *
    + * + * + *
    + * + * Markup — without Popover API (always visible, CSS-positioned): + *
    + * + *
    Always visible label
    + *
    + */ + + /* ------------------------------------------------------------------------- + Fallback: relative container (all browsers) + Tooltip/float positioned absolutely within the group when anchor API + is not available. + ------------------------------------------------------------------------- */ + [vl-anchor-group] { + position: relative; + display: inline-block; + } + + /* Fallback positioning for tooltip (top-center above trigger) */ + [vl-tooltip]:not(:popover-open) { + position: absolute; + inset-block-end: calc(100% + var(--vl-anchor-gap, 0.375rem)); + inset-inline-start: 50%; + transform: translateX(-50%); + z-index: var(--vl-z-dropdown); + } + + /* Fallback positioning for float (bottom-start below trigger) */ + [vl-float]:not(:popover-open) { + position: absolute; + inset-block-start: calc(100% + var(--vl-anchor-gap, 0.375rem)); + inset-inline-start: 0; + z-index: var(--vl-z-dropdown); + } + + /* ------------------------------------------------------------------------- + Tooltip styles (all browsers) + ------------------------------------------------------------------------- */ + [vl-tooltip] { + /* Reset popover UA styles */ + border: 1px solid var(--vl-border-subtle); + background: var(--vl-bg-inset); + color: var(--vl-text-primary); + font-family: var(--vl-font-family); + font-size: var(--vl-font-size-xs); + font-weight: var(--vl-font-weight-medium); + line-height: var(--vl-leading-normal); + padding: var(--vl-space-xs) var(--vl-space-sm); + border-radius: var(--vl-radius-sm); + max-width: var(--vl-tooltip-max-width, 16rem); + white-space: normal; + box-shadow: var(--vl-shadow-md); + pointer-events: none; + } + + /* ------------------------------------------------------------------------- + Float / dropdown panel styles (all browsers) + ------------------------------------------------------------------------- */ + [vl-float] { + /* Reset popover UA styles */ + border: 1px solid var(--vl-border-subtle); + background: var(--vl-bg-surface); + color: var(--vl-text-primary); + font-family: var(--vl-font-family); + font-size: var(--vl-font-size-sm); + border-radius: var(--vl-radius-md); + padding: var(--vl-space-xs); + min-width: var(--vl-float-min-width, 10rem); + box-shadow: var(--vl-shadow-lg); + overflow: clip; + } + + /* ------------------------------------------------------------------------- + @starting-style transitions — smooth open/close (Chrome 117+, Safari 17.5+) + Pairs naturally with popover="hint" and popover="" toggle behavior. + ------------------------------------------------------------------------- */ + @supports (transition-behavior: allow-discrete) { + [vl-tooltip], + [vl-float] { + transition: + opacity var(--vl-duration-fast) var(--vl-ease-out-soft), + transform var(--vl-duration-fast) var(--vl-ease-spring), + display var(--vl-duration-fast) allow-discrete, + overlay var(--vl-duration-fast) allow-discrete; + opacity: 1; + } + + [vl-tooltip]:not(:popover-open), + [vl-float]:not(:popover-open) { + opacity: 0; + } + + @starting-style { + [vl-tooltip]:popover-open { + opacity: 0; + transform: translateX(-50%) translateY(0.25rem) scale(0.95); + } + + [vl-float]:popover-open { + opacity: 0; + transform: translateY(-0.375rem) scale(0.97); + } + } + } + + /* ------------------------------------------------------------------------- + CSS Anchor Positioning (Chrome 125+ / Safari 18.2+) + When available, the fallback position: absolute is replaced by true + anchor positioning with auto-flip and inset-area. + ------------------------------------------------------------------------- */ + @supports (anchor-name: --x) { + /* The trigger element becomes the anchor */ + [vl-anchor-trigger] { + anchor-name: --vl-anchor-local; + } + + /* Tooltip — top-center of anchor, auto-flips to bottom if needed */ + [vl-tooltip] { + position: absolute; + position: fixed; /* top-layer: works inside popover */ + position-anchor: --vl-anchor-local; + inset-area: top span-all; + margin-block-end: var(--vl-anchor-gap, 0.375rem); + justify-self: anchor-center; + /* Auto-flip: try bottom if no room above */ + position-try-options: flip-block; + position-try-order: most-height; + inset: auto; + + /* Reset fallback transform for anchor-positioned context */ + transform: none; + } + + /* Tooltip position overrides */ + [vl-tooltip][vl-position="bottom"] { + inset-area: bottom span-all; + margin-block: var(--vl-anchor-gap, 0.375rem) 0; + } + + [vl-tooltip][vl-position="left"] { + inset-area: left span-all; + margin-inline-end: var(--vl-anchor-gap, 0.375rem); + position-try-options: flip-inline; + } + + [vl-tooltip][vl-position="right"] { + inset-area: right span-all; + margin-inline-start: var(--vl-anchor-gap, 0.375rem); + position-try-options: flip-inline; + } + + /* @starting-style for anchor-positioned tooltip */ + @supports (transition-behavior: allow-discrete) { + @starting-style { + [vl-tooltip]:popover-open { + opacity: 0; + transform: scale(0.94); + } + } + } + + /* Float — bottom-start of anchor, auto-flips to top if needed */ + [vl-float] { + position: absolute; + position: fixed; /* top-layer: works inside popover */ + position-anchor: --vl-anchor-local; + inset-area: bottom span-all; + margin-block-start: var(--vl-anchor-gap, 0.375rem); + /* Minimum width tracks the anchor width */ + min-width: anchor-size(width); + /* Auto-flip to top when clipped */ + position-try-options: flip-block; + position-try-order: most-height; + inset: auto; + + transform: none; + } + + /* Float position overrides */ + [vl-float][vl-position="top"] { + inset-area: top span-all; + margin-block-end: var(--vl-anchor-gap, 0.375rem); + } + + @supports (transition-behavior: allow-discrete) { + @starting-style { + [vl-float]:popover-open { + opacity: 0; + transform: scale(0.97); + } + } + } + + /* Position visibility: hide when anchor scrolls out of view */ + [vl-tooltip], + [vl-float] { + position-visibility: anchors-visible; + } + + /* Multi-anchor support: use vl-anchor-name CSS property override + Example: style="--vl-anchor-name: --my-custom-anchor" on trigger + float */ + [vl-anchor-trigger][style*="--vl-anchor-name"] { + anchor-name: var(--vl-anchor-name); + } + + [vl-tooltip][style*="--vl-anchor-name"], + [vl-float][style*="--vl-anchor-name"] { + position-anchor: var(--vl-anchor-name); + } + } + + /* ------------------------------------------------------------------------- + Focus ring — keyboard accessibility + ------------------------------------------------------------------------- */ + [vl-anchor-trigger]:focus-visible { + outline: var(--vl-focus-ring-width) solid var(--vl-focus-ring-color); + outline-offset: var(--vl-focus-ring-offset); + } + + /* ------------------------------------------------------------------------- + Reduced motion — disable transform transitions, keep opacity fade + ------------------------------------------------------------------------- */ + @media (prefers-reduced-motion: reduce) { + [vl-tooltip], + [vl-float] { + transition: opacity var(--vl-duration-instant) linear, + display var(--vl-duration-instant) allow-discrete; + } + } +} diff --git a/packages/css/src/05-transitions.css b/packages/css/src/05-transitions.css index 6c3fb05..ffa96b7 100644 --- a/packages/css/src/05-transitions.css +++ b/packages/css/src/05-transitions.css @@ -428,6 +428,87 @@ animation-name: vl-vt-iris-new; } + /* ------------------------------------------------------------------------- + VIEW TRANSITION LEVEL 2 — match-element (Chrome 137+) + Generates a stable, unique view-transition-name from the element's identity. + Ideal for SPA list → detail morphing without manual name management. + + Usage: +
  • ← each item gets a unique stable VT name +
    + + The browser handles uniqueness; no need for inline style or IDs. + @see https://developer.chrome.com/blog/chrome-137-beta#view-transition-name-match-element + ------------------------------------------------------------------------- */ + @supports (view-transition-name: match-element) { + [vl-vt-match] { + view-transition-name: match-element; + } + + /* Sub-elements that should morph independently within a matched item */ + [vl-vt-match-inner] { + view-transition-name: match-element; + } + } + + /* ------------------------------------------------------------------------- + MORPH — Preset (vl-page-transition="morph") + Shape-clip morph transition that looks great for card → detail pages. + Uses clip-path with CSS shape() (Chrome 135+), gracefully degrades to + the default velora preset on older browsers. + ------------------------------------------------------------------------- */ + @keyframes vl-vt-morph-old { + from { + opacity: 1; + clip-path: inset(0 0 0 0 round var(--vl-radius-lg)); + transform: scale(1); + } + + to { + opacity: 0; + clip-path: inset(4% 3% 4% 3% round var(--vl-radius-xl)); + transform: scale(0.94); + filter: blur(6px); + } + } + + @keyframes vl-vt-morph-new { + from { + opacity: 0; + clip-path: inset(5% 4% 5% 4% round var(--vl-radius-2xl)); + transform: scale(1.06); + filter: blur(8px); + } + + to { + opacity: 1; + clip-path: inset(0 0 0 0 round 0px); + transform: scale(1); + filter: blur(0); + } + } + + :root[vl-page-transition="morph"]::view-transition-old(root) { + animation-name: vl-vt-morph-old; + animation-duration: var(--vl-vt-root-duration, 0.6s); + animation-timing-function: var(--vl-ease-emphasized, cubic-bezier(0.2, 0, 0, 1)); + } + + :root[vl-page-transition="morph"]::view-transition-new(root) { + animation-name: vl-vt-morph-new; + animation-duration: var(--vl-vt-root-duration, 0.65s); + animation-timing-function: var(--vl-ease-emphasized, cubic-bezier(0.2, 0, 0, 1)); + } + + /* morph: shared card uses matching clip-path animation */ + :root[vl-page-transition="morph"]::view-transition-old(shared-card) { + animation-name: vl-vt-morph-old; + } + + :root[vl-page-transition="morph"]::view-transition-new(shared-card) { + animation-name: vl-vt-morph-new; + } + /* ------------------------------------------------------------------------- Acessibilidade ------------------------------------------------------------------------- */ diff --git a/packages/css/src/velora.css b/packages/css/src/velora.css index e66f73a..339d111 100644 --- a/packages/css/src/velora.css +++ b/packages/css/src/velora.css @@ -16,6 +16,8 @@ @import "./04c-structures.css"; @import "./04d-premium.css"; @import "./04e-showcase-elevation-patterns.css"; +@import "./04f-carousel.css"; +@import "./04g-anchor.css"; @import "./05-transitions.css"; @import "./06-utilities.css"; @import "./07-overrides.css"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a09df2..de1db23 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,6 +30,8 @@ importers: specifier: ^8.0.7 version: 8.0.8(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.8.3) + packages/compiler: {} + packages/css: {} packages: