@morphika/andami 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -36
- package/app/admin/assets/page.tsx +6 -6
- package/app/admin/database/page.tsx +302 -302
- package/app/admin/error.tsx +53 -53
- package/app/admin/layout.tsx +320 -327
- package/app/admin/navigation/page.tsx +255 -255
- package/app/admin/pages/[slug]/page.tsx +6 -6
- package/app/admin/pages/page.tsx +11 -11
- package/app/admin/projects/page.tsx +14 -14
- package/app/admin/setup/page.tsx +1 -1
- package/app/admin/styles/page.tsx +1 -1
- package/components/admin/MetadataEditor.tsx +6 -6
- package/components/admin/nav-builder/NavBuilder.tsx +1 -1
- package/components/admin/nav-builder/NavBuilderGrid.tsx +3 -3
- package/components/admin/nav-builder/NavGridCell.tsx +48 -48
- package/components/admin/nav-builder/NavGridItem.tsx +4 -4
- package/components/admin/nav-builder/NavItemSettings.tsx +331 -331
- package/components/admin/nav-builder/NavItemTypePicker.tsx +102 -102
- package/components/admin/nav-builder/NavLivePreview.tsx +1 -1
- package/components/admin/nav-builder/NavMobileLivePreview.tsx +226 -226
- package/components/admin/nav-builder/NavMobileSettings.tsx +242 -242
- package/components/admin/nav-builder/NavSettingsFields.tsx +514 -514
- package/components/admin/setup-wizard/BrandingStep.tsx +3 -3
- package/components/admin/setup-wizard/DatabaseStep.tsx +2 -2
- package/components/admin/setup-wizard/DoneStep.tsx +1 -1
- package/components/admin/setup-wizard/SetupWizard.tsx +4 -4
- package/components/admin/setup-wizard/StorageStep.tsx +2 -2
- package/components/admin/setup-wizard/WelcomeStep.tsx +2 -2
- package/components/admin/styles/ColorsEditor.tsx +2 -2
- package/components/admin/styles/FontsEditor.tsx +6 -6
- package/components/admin/styles/GridLayoutEditor.tsx +9 -9
- package/components/admin/styles/LinksButtonsEditor.tsx +5 -5
- package/components/admin/styles/TypographyEditor.tsx +6 -6
- package/components/admin/styles/shared.tsx +68 -68
- package/components/blocks/AudioBlockRenderer.tsx +286 -0
- package/components/blocks/BeforeAfterBlockRenderer.tsx +274 -0
- package/components/blocks/MarqueeBlockRenderer.tsx +316 -0
- package/components/blocks/ProjectCarouselBlockRenderer.tsx +1 -1
- package/components/builder/BlockCardIcons.tsx +316 -227
- package/components/builder/BlockTypePicker.tsx +3 -1
- package/components/builder/BubbleIcons.tsx +90 -0
- package/components/builder/BuilderCanvas.tsx +2 -0
- package/components/builder/CanvasMinimap.tsx +2 -2
- package/components/builder/CoverSectionCanvas.tsx +363 -275
- package/components/builder/DeviceFrame.tsx +1 -1
- package/components/builder/DndWrapper.tsx +3 -3
- package/components/builder/InsertionLines.tsx +1 -1
- package/components/builder/SectionCardIcons.tsx +421 -320
- package/components/builder/SectionEditorBar.tsx +1 -1
- package/components/builder/SectionTypePicker.tsx +4 -4
- package/components/builder/SectionV2Canvas.tsx +20 -4
- package/components/builder/SectionV2Column.tsx +74 -68
- package/components/builder/SortableBlock.tsx +93 -73
- package/components/builder/SortableRow.tsx +27 -26
- package/components/builder/VirtualAssetGrid.tsx +2 -2
- package/components/builder/asset-browser/R2BrowserContent.tsx +34 -17
- package/components/builder/asset-browser/helpers.ts +4 -0
- package/components/builder/asset-browser/types.ts +2 -1
- package/components/builder/blockStyles.tsx +192 -173
- package/components/builder/color-picker/AlphaSlider.tsx +141 -141
- package/components/builder/color-picker/ColorInputs.tsx +105 -105
- package/components/builder/color-picker/EyedropperButton.tsx +74 -74
- package/components/builder/color-picker/HueSlider.tsx +124 -124
- package/components/builder/color-picker/SaturationCanvas.tsx +142 -142
- package/components/builder/color-picker/SwatchBar.tsx +93 -93
- package/components/builder/editors/AudioBlockEditor.tsx +242 -0
- package/components/builder/editors/BeforeAfterBlockEditor.tsx +360 -0
- package/components/builder/editors/ButtonBlockEditor.tsx +4 -4
- package/components/builder/editors/EnterAnimationPicker.tsx +2 -2
- package/components/builder/editors/HoverEffectPicker.tsx +2 -2
- package/components/builder/editors/ImageBlockEditor.tsx +2 -2
- package/components/builder/editors/ImageGridBlockEditor.tsx +4 -4
- package/components/builder/editors/MarqueeBlockEditor.tsx +621 -0
- package/components/builder/editors/ProjectCarouselBlockEditor.tsx +443 -443
- package/components/builder/editors/ProjectGridEditor.tsx +9 -9
- package/components/builder/editors/SpacerBlockEditor.tsx +5 -5
- package/components/builder/editors/StaggerSettings.tsx +109 -109
- package/components/builder/editors/TextBlockEditor.tsx +3 -3
- package/components/builder/editors/TextStylePicker.tsx +1 -1
- package/components/builder/editors/VideoBlockEditor.tsx +2 -2
- package/components/builder/editors/index.ts +11 -10
- package/components/builder/editors/shared.tsx +7 -7
- package/components/builder/live-preview/LiveAudioPreview.tsx +120 -0
- package/components/builder/live-preview/LiveBeforeAfterPreview.tsx +176 -0
- package/components/builder/live-preview/LiveImageGridPreview.tsx +10 -2
- package/components/builder/live-preview/LiveImagePreview.tsx +1 -1
- package/components/builder/live-preview/LiveMarqueePreview.tsx +39 -0
- package/components/builder/live-preview/LiveProjectCarouselPreview.tsx +1 -1
- package/components/builder/live-preview/LiveVideoPreview.tsx +1 -1
- package/components/builder/live-preview/ProjectCardWrapper.tsx +291 -291
- package/components/builder/settings-panel/AnimationTab.tsx +138 -138
- package/components/builder/settings-panel/BlockLayoutTab.tsx +7 -7
- package/components/builder/settings-panel/CardEntranceSection.tsx +114 -114
- package/components/builder/settings-panel/ColumnV2Settings.tsx +5 -5
- package/components/builder/settings-panel/CoverSectionLayoutTab.tsx +71 -71
- package/components/builder/settings-panel/CoverSectionSettings.tsx +335 -335
- package/components/builder/settings-panel/PageSettings.tsx +3 -3
- package/components/builder/settings-panel/ParallaxSlideSettings.tsx +2 -2
- package/components/builder/settings-panel/SectionV2AnimationTab.tsx +4 -4
- package/components/builder/settings-panel/SectionV2LayoutTab.tsx +356 -356
- package/components/builder/settings-panel/SectionV2Settings.tsx +14 -14
- package/components/builder/settings-panel/TRBLInputs.tsx +1 -1
- package/lib/animation/enter-types.ts +3 -0
- package/lib/animation/hover-effect-presets.ts +210 -210
- package/lib/animation/hover-effect-types.ts +3 -0
- package/lib/builder/block-registrations.ts +468 -335
- package/lib/builder/constants.ts +111 -111
- package/lib/builder/store-sections.ts +2 -2
- package/lib/builder/types-slices.ts +414 -414
- package/lib/builder/types.ts +6 -1
- package/lib/config/index.ts +27 -27
- package/lib/sanity/types.ts +156 -1
- package/lib/version.ts +1 -1
- package/package.json +1 -1
- package/sanity/schemas/blocks/audioBlock.ts +69 -0
- package/sanity/schemas/blocks/beforeAfterBlock.ts +121 -0
- package/sanity/schemas/blocks/index.ts +12 -9
- package/sanity/schemas/blocks/marqueeBlock.ts +292 -0
- package/sanity/schemas/index.ts +120 -111
- package/styles/admin.css +85 -85
- package/styles/animations.css +237 -237
- package/styles/base.css +114 -114
package/styles/admin.css
CHANGED
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
/* ============================================
|
|
2
|
-
Admin Panel — Clean UI Override
|
|
3
|
-
Uses Inter (sans-serif) for admin, white bg,
|
|
4
|
-
clean hierarchy. Mono reserved for public site.
|
|
5
|
-
============================================ */
|
|
6
|
-
|
|
7
|
-
/* Admin shell: override dark defaults */
|
|
8
|
-
[data-admin] {
|
|
9
|
-
font-family: var(--font-sans);
|
|
10
|
-
background: #ffffff;
|
|
11
|
-
color: #1a1a1a;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
[data-admin] * {
|
|
15
|
-
cursor: auto;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/* Admin typography scale */
|
|
19
|
-
[data-admin] h1 { font-size: 1.5rem; font-weight: 600; letter-spacing: -0.01em; color: #111; }
|
|
20
|
-
[data-admin] h2 { font-size: 1.125rem; font-weight: 600; letter-spacing: -0.01em; color: #222; }
|
|
21
|
-
[data-admin] h3 { font-size: 0.9375rem; font-weight: 500; color: #333; }
|
|
22
|
-
|
|
23
|
-
/* Admin inputs */
|
|
24
|
-
[data-admin] input[type="text"],
|
|
25
|
-
[data-admin] input[type="password"],
|
|
26
|
-
[data-admin] input[type="email"],
|
|
27
|
-
[data-admin] input[type="url"],
|
|
28
|
-
[data-admin] input[type="number"],
|
|
29
|
-
[data-admin] textarea,
|
|
30
|
-
[data-admin] select {
|
|
31
|
-
font-family: var(--font-sans);
|
|
32
|
-
font-size: 0.8125rem;
|
|
33
|
-
border-radius: 0.5rem;
|
|
34
|
-
border: 1px solid #e5e5e5;
|
|
35
|
-
padding: 0.5rem 0.75rem;
|
|
36
|
-
transition: border-color 0.15s;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
[data-admin] input:focus,
|
|
40
|
-
[data-admin] textarea:focus,
|
|
41
|
-
[data-admin] select:focus {
|
|
42
|
-
border-color: #
|
|
43
|
-
outline: none;
|
|
44
|
-
box-shadow: 0 0 0 3px rgba(
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/* Admin buttons base */
|
|
48
|
-
[data-admin] .btn-primary {
|
|
49
|
-
background: #
|
|
50
|
-
color: white;
|
|
51
|
-
font-weight: 500;
|
|
52
|
-
font-size: 0.8125rem;
|
|
53
|
-
padding: 0.5rem 1.25rem;
|
|
54
|
-
border-radius: 0.5rem;
|
|
55
|
-
transition: all 0.15s;
|
|
56
|
-
}
|
|
57
|
-
[data-admin] .btn-primary:hover { background: #
|
|
58
|
-
[data-admin] .btn-primary:disabled { opacity: 0.4; }
|
|
59
|
-
|
|
60
|
-
[data-admin] .btn-secondary {
|
|
61
|
-
background: white;
|
|
62
|
-
color: #555;
|
|
63
|
-
font-weight: 500;
|
|
64
|
-
font-size: 0.8125rem;
|
|
65
|
-
padding: 0.5rem 1.25rem;
|
|
66
|
-
border-radius: 0.5rem;
|
|
67
|
-
border: 1px solid #e5e5e5;
|
|
68
|
-
transition: all 0.15s;
|
|
69
|
-
}
|
|
70
|
-
[data-admin] .btn-secondary:hover { border-color: #ccc; color: #111; }
|
|
71
|
-
|
|
72
|
-
/* Admin card base */
|
|
73
|
-
[data-admin] .admin-card {
|
|
74
|
-
background: white;
|
|
75
|
-
border: 1px solid #f0f0f0;
|
|
76
|
-
border-radius: 0.75rem;
|
|
77
|
-
padding: 1.5rem;
|
|
78
|
-
box-shadow: 0 1px 3px rgba(0,0,0,0.04);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/* Scrollbar for admin */
|
|
82
|
-
[data-admin] ::-webkit-scrollbar { width: 6px; }
|
|
83
|
-
[data-admin] ::-webkit-scrollbar-track { background: transparent; }
|
|
84
|
-
[data-admin] ::-webkit-scrollbar-thumb { background: #ddd; border-radius: 3px; }
|
|
85
|
-
[data-admin] ::-webkit-scrollbar-thumb:hover { background: #bbb; }
|
|
1
|
+
/* ============================================
|
|
2
|
+
Admin Panel — Clean UI Override
|
|
3
|
+
Uses Inter (sans-serif) for admin, white bg,
|
|
4
|
+
clean hierarchy. Mono reserved for public site.
|
|
5
|
+
============================================ */
|
|
6
|
+
|
|
7
|
+
/* Admin shell: override dark defaults */
|
|
8
|
+
[data-admin] {
|
|
9
|
+
font-family: var(--font-sans);
|
|
10
|
+
background: #ffffff;
|
|
11
|
+
color: #1a1a1a;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
[data-admin] * {
|
|
15
|
+
cursor: auto;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* Admin typography scale */
|
|
19
|
+
[data-admin] h1 { font-size: 1.5rem; font-weight: 600; letter-spacing: -0.01em; color: #111; }
|
|
20
|
+
[data-admin] h2 { font-size: 1.125rem; font-weight: 600; letter-spacing: -0.01em; color: #222; }
|
|
21
|
+
[data-admin] h3 { font-size: 0.9375rem; font-weight: 500; color: #333; }
|
|
22
|
+
|
|
23
|
+
/* Admin inputs */
|
|
24
|
+
[data-admin] input[type="text"],
|
|
25
|
+
[data-admin] input[type="password"],
|
|
26
|
+
[data-admin] input[type="email"],
|
|
27
|
+
[data-admin] input[type="url"],
|
|
28
|
+
[data-admin] input[type="number"],
|
|
29
|
+
[data-admin] textarea,
|
|
30
|
+
[data-admin] select {
|
|
31
|
+
font-family: var(--font-sans);
|
|
32
|
+
font-size: 0.8125rem;
|
|
33
|
+
border-radius: 0.5rem;
|
|
34
|
+
border: 1px solid #e5e5e5;
|
|
35
|
+
padding: 0.5rem 0.75rem;
|
|
36
|
+
transition: border-color 0.15s;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
[data-admin] input:focus,
|
|
40
|
+
[data-admin] textarea:focus,
|
|
41
|
+
[data-admin] select:focus {
|
|
42
|
+
border-color: #3580f9;
|
|
43
|
+
outline: none;
|
|
44
|
+
box-shadow: 0 0 0 3px rgba(53, 128, 249, 0.08);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* Admin buttons base */
|
|
48
|
+
[data-admin] .btn-primary {
|
|
49
|
+
background: #3580f9;
|
|
50
|
+
color: white;
|
|
51
|
+
font-weight: 500;
|
|
52
|
+
font-size: 0.8125rem;
|
|
53
|
+
padding: 0.5rem 1.25rem;
|
|
54
|
+
border-radius: 0.5rem;
|
|
55
|
+
transition: all 0.15s;
|
|
56
|
+
}
|
|
57
|
+
[data-admin] .btn-primary:hover { background: #2d6dd4; }
|
|
58
|
+
[data-admin] .btn-primary:disabled { opacity: 0.4; }
|
|
59
|
+
|
|
60
|
+
[data-admin] .btn-secondary {
|
|
61
|
+
background: white;
|
|
62
|
+
color: #555;
|
|
63
|
+
font-weight: 500;
|
|
64
|
+
font-size: 0.8125rem;
|
|
65
|
+
padding: 0.5rem 1.25rem;
|
|
66
|
+
border-radius: 0.5rem;
|
|
67
|
+
border: 1px solid #e5e5e5;
|
|
68
|
+
transition: all 0.15s;
|
|
69
|
+
}
|
|
70
|
+
[data-admin] .btn-secondary:hover { border-color: #ccc; color: #111; }
|
|
71
|
+
|
|
72
|
+
/* Admin card base */
|
|
73
|
+
[data-admin] .admin-card {
|
|
74
|
+
background: white;
|
|
75
|
+
border: 1px solid #f0f0f0;
|
|
76
|
+
border-radius: 0.75rem;
|
|
77
|
+
padding: 1.5rem;
|
|
78
|
+
box-shadow: 0 1px 3px rgba(0,0,0,0.04);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Scrollbar for admin */
|
|
82
|
+
[data-admin] ::-webkit-scrollbar { width: 6px; }
|
|
83
|
+
[data-admin] ::-webkit-scrollbar-track { background: transparent; }
|
|
84
|
+
[data-admin] ::-webkit-scrollbar-thumb { background: #ddd; border-radius: 3px; }
|
|
85
|
+
[data-admin] ::-webkit-scrollbar-thumb:hover { background: #bbb; }
|
package/styles/animations.css
CHANGED
|
@@ -1,237 +1,237 @@
|
|
|
1
|
-
/* ============================================
|
|
2
|
-
Animations — Core keyframes and animation systems
|
|
3
|
-
Imported by globals.css (monolith) or instance CSS
|
|
4
|
-
============================================ */
|
|
5
|
-
|
|
6
|
-
@keyframes marquee {
|
|
7
|
-
from {
|
|
8
|
-
transform: translateX(0);
|
|
9
|
-
}
|
|
10
|
-
to {
|
|
11
|
-
transform: translateX(-50%);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/* V2 Grid snapping guide pulse */
|
|
16
|
-
@keyframes pulse {
|
|
17
|
-
0%, 100% { opacity: 0.4; }
|
|
18
|
-
50% { opacity: 1; }
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/* ============================================
|
|
22
|
-
View Transitions — DISABLED (Session 112)
|
|
23
|
-
Removed to eliminate black flash conflicts with
|
|
24
|
-
"On Enter" element animations. Page exit animations
|
|
25
|
-
(PageExitContext) handle the transition feel instead.
|
|
26
|
-
============================================ */
|
|
27
|
-
|
|
28
|
-
/* ============================================
|
|
29
|
-
Enter Animation Keyframes (Session 120)
|
|
30
|
-
Used by EnterAnimationWrapper via inline styles.
|
|
31
|
-
animation-name, duration, delay, easing, and fill-mode
|
|
32
|
-
are set via inline styles — no CSS rules needed here.
|
|
33
|
-
============================================ */
|
|
34
|
-
|
|
35
|
-
@keyframes enter-fade {
|
|
36
|
-
from { opacity: 0; }
|
|
37
|
-
to { opacity: 1; }
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
@keyframes enter-slide-up {
|
|
41
|
-
from { opacity: 0; transform: translateY(30px); }
|
|
42
|
-
to { opacity: 1; transform: translateY(0); }
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
@keyframes enter-slide-down {
|
|
46
|
-
from { opacity: 0; transform: translateY(-30px); }
|
|
47
|
-
to { opacity: 1; transform: translateY(0); }
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
@keyframes enter-scale {
|
|
51
|
-
from { opacity: 0; transform: scale(0.85); }
|
|
52
|
-
to { opacity: 1; transform: scale(1); }
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
@keyframes enter-reveal {
|
|
56
|
-
from { opacity: 0; clip-path: inset(0 100% 0 0); }
|
|
57
|
-
to { opacity: 1; clip-path: inset(0 0% 0 0); }
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
@keyframes enter-blur {
|
|
61
|
-
from { opacity: 0; filter: blur(10px); }
|
|
62
|
-
to { opacity: 1; filter: blur(0px); }
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
@keyframes enter-blur-in {
|
|
66
|
-
from { opacity: 0; filter: blur(6px); }
|
|
67
|
-
to { opacity: 1; filter: blur(0px); }
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/* Prefers reduced motion — neutralize ALL enter animations */
|
|
71
|
-
@media (prefers-reduced-motion: reduce) {
|
|
72
|
-
[data-enter-animation] {
|
|
73
|
-
animation: none !important;
|
|
74
|
-
opacity: 1 !important;
|
|
75
|
-
transform: none !important;
|
|
76
|
-
filter: none !important;
|
|
77
|
-
clip-path: none !important;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/* Suppress hover transitions while enter animation is still playing.
|
|
82
|
-
Prevents visual conflict between CSS animation (enter) and CSS transition (hover). */
|
|
83
|
-
[data-enter-animation]:not([data-entered]) [data-hover-effect] {
|
|
84
|
-
transition: none !important;
|
|
85
|
-
pointer-events: none;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/* ============================================
|
|
89
|
-
Hover Effect System (Sessions 60, 120)
|
|
90
|
-
============================================
|
|
91
|
-
Most hover styling is applied via inline styles in HoverAnimationWrapper.
|
|
92
|
-
The :hover pseudo-class cannot be set inline, so we use data attributes. */
|
|
93
|
-
|
|
94
|
-
/* Scale Up */
|
|
95
|
-
[data-hover-effect="scale-up"]:hover {
|
|
96
|
-
transform: scale(1.05) !important;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/* Scale Down */
|
|
100
|
-
[data-hover-effect="scale-down"]:hover {
|
|
101
|
-
transform: scale(0.95) !important;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/* Lift — uses inline custom properties for intensity-dependent values */
|
|
105
|
-
[data-hover-effect="lift"] {
|
|
106
|
-
--hover-lift-y: -4px;
|
|
107
|
-
--hover-lift-shadow: 0 8px 20px rgba(0,0,0,0.15);
|
|
108
|
-
}
|
|
109
|
-
[data-hover-effect="lift"]:hover {
|
|
110
|
-
transform: translateY(var(--hover-lift-y)) !important;
|
|
111
|
-
box-shadow: var(--hover-lift-shadow) !important;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/* Tilt 3D — transform is handled by JS mousemove, but we ensure base state */
|
|
115
|
-
[data-hover-effect="tilt-3d"] {
|
|
116
|
-
transform-style: preserve-3d;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/* Color Shift */
|
|
120
|
-
[data-hover-effect="color-shift"] {
|
|
121
|
-
--hover-brightness: 1.1;
|
|
122
|
-
--hover-saturate: 1.2;
|
|
123
|
-
}
|
|
124
|
-
[data-hover-effect="color-shift"]:hover {
|
|
125
|
-
filter: brightness(var(--hover-brightness)) saturate(var(--hover-saturate)) !important;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/* Blur Reveal */
|
|
129
|
-
[data-hover-effect="blur-reveal"] {
|
|
130
|
-
--hover-blur-base: 3px;
|
|
131
|
-
--hover-opacity-base: 0.85;
|
|
132
|
-
}
|
|
133
|
-
[data-hover-effect="blur-reveal"]:hover {
|
|
134
|
-
filter: blur(0px) !important;
|
|
135
|
-
opacity: 1 !important;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/* Border Glow */
|
|
139
|
-
[data-hover-effect="border-glow"] {
|
|
140
|
-
--hover-glow-spread: 4px;
|
|
141
|
-
--hover-glow-color: rgba(
|
|
142
|
-
}
|
|
143
|
-
[data-hover-effect="border-glow"]:hover {
|
|
144
|
-
box-shadow: 0 0 calc(var(--hover-glow-spread) * 2) var(--hover-glow-spread) var(--hover-glow-color) !important;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/* Prefers reduced motion — disable hover animations */
|
|
148
|
-
@media (prefers-reduced-motion: reduce) {
|
|
149
|
-
[data-hover-effect] {
|
|
150
|
-
transition: none !important;
|
|
151
|
-
}
|
|
152
|
-
[data-hover-effect]:hover {
|
|
153
|
-
transform: none !important;
|
|
154
|
-
filter: none !important;
|
|
155
|
-
box-shadow: none !important;
|
|
156
|
-
opacity: 1 !important;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/* ============================================
|
|
161
|
-
Text Animation Presets (Parallax Showcase)
|
|
162
|
-
CSS-only presets for title/subtitle entrance.
|
|
163
|
-
Triggered via IntersectionObserver (enter mode).
|
|
164
|
-
============================================ */
|
|
165
|
-
|
|
166
|
-
/* ============================================
|
|
167
|
-
Nav Entrance Animations
|
|
168
|
-
Applied to the entire nav or individual items
|
|
169
|
-
when stagger is enabled. Triggered on page load.
|
|
170
|
-
============================================ */
|
|
171
|
-
|
|
172
|
-
@keyframes nav-fade-in {
|
|
173
|
-
from { opacity: 0; }
|
|
174
|
-
to { opacity: 1; }
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
@keyframes nav-slide-down {
|
|
178
|
-
from { opacity: 0; transform: translateY(-100%); }
|
|
179
|
-
to { opacity: 1; transform: translateY(0); }
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
@keyframes nav-blur-in {
|
|
183
|
-
from { opacity: 0; filter: blur(12px); }
|
|
184
|
-
to { opacity: 1; filter: blur(0px); }
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/* Nav entrance: initial hidden state */
|
|
188
|
-
[data-nav-entrance] {
|
|
189
|
-
opacity: 0;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/* Nav entrance: play once the attribute is set */
|
|
193
|
-
[data-nav-entrance="fade-in"][data-nav-entered] {
|
|
194
|
-
animation: nav-fade-in var(--nav-entrance-duration, 600ms) var(--nav-entrance-delay, 0ms) ease-out forwards;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
[data-nav-entrance="slide-down"][data-nav-entered] {
|
|
198
|
-
animation: nav-slide-down var(--nav-entrance-duration, 600ms) var(--nav-entrance-delay, 0ms) ease-out forwards;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
[data-nav-entrance="blur-in"][data-nav-entered] {
|
|
202
|
-
animation: nav-blur-in var(--nav-entrance-duration, 700ms) var(--nav-entrance-delay, 0ms) ease-out forwards;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/* Staggered items: each item animates independently */
|
|
206
|
-
[data-nav-item-entrance] {
|
|
207
|
-
opacity: 0;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
[data-nav-item-entrance="fade-in"][data-nav-entered] {
|
|
211
|
-
animation: nav-fade-in var(--nav-item-duration, 400ms) var(--nav-item-delay, 0ms) ease-out forwards;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
[data-nav-item-entrance="slide-down"][data-nav-entered] {
|
|
215
|
-
animation: nav-slide-down var(--nav-item-duration, 400ms) var(--nav-item-delay, 0ms) ease-out forwards;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
[data-nav-item-entrance="blur-in"][data-nav-entered] {
|
|
219
|
-
animation: nav-blur-in var(--nav-item-duration, 400ms) var(--nav-item-delay, 0ms) ease-out forwards;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/* Prefers reduced motion — disable nav animations */
|
|
223
|
-
@media (prefers-reduced-motion: reduce) {
|
|
224
|
-
[data-nav-entrance],
|
|
225
|
-
[data-nav-item-entrance] {
|
|
226
|
-
animation: none !important;
|
|
227
|
-
opacity: 1 !important;
|
|
228
|
-
transform: none !important;
|
|
229
|
-
filter: none !important;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/* Typewriter cursor blink */
|
|
234
|
-
@keyframes typewriter-cursor-blink {
|
|
235
|
-
0%, 100% { opacity: 1; }
|
|
236
|
-
50% { opacity: 0; }
|
|
237
|
-
}
|
|
1
|
+
/* ============================================
|
|
2
|
+
Animations — Core keyframes and animation systems
|
|
3
|
+
Imported by globals.css (monolith) or instance CSS
|
|
4
|
+
============================================ */
|
|
5
|
+
|
|
6
|
+
@keyframes marquee {
|
|
7
|
+
from {
|
|
8
|
+
transform: translateX(0);
|
|
9
|
+
}
|
|
10
|
+
to {
|
|
11
|
+
transform: translateX(-50%);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* V2 Grid snapping guide pulse */
|
|
16
|
+
@keyframes pulse {
|
|
17
|
+
0%, 100% { opacity: 0.4; }
|
|
18
|
+
50% { opacity: 1; }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* ============================================
|
|
22
|
+
View Transitions — DISABLED (Session 112)
|
|
23
|
+
Removed to eliminate black flash conflicts with
|
|
24
|
+
"On Enter" element animations. Page exit animations
|
|
25
|
+
(PageExitContext) handle the transition feel instead.
|
|
26
|
+
============================================ */
|
|
27
|
+
|
|
28
|
+
/* ============================================
|
|
29
|
+
Enter Animation Keyframes (Session 120)
|
|
30
|
+
Used by EnterAnimationWrapper via inline styles.
|
|
31
|
+
animation-name, duration, delay, easing, and fill-mode
|
|
32
|
+
are set via inline styles — no CSS rules needed here.
|
|
33
|
+
============================================ */
|
|
34
|
+
|
|
35
|
+
@keyframes enter-fade {
|
|
36
|
+
from { opacity: 0; }
|
|
37
|
+
to { opacity: 1; }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@keyframes enter-slide-up {
|
|
41
|
+
from { opacity: 0; transform: translateY(30px); }
|
|
42
|
+
to { opacity: 1; transform: translateY(0); }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@keyframes enter-slide-down {
|
|
46
|
+
from { opacity: 0; transform: translateY(-30px); }
|
|
47
|
+
to { opacity: 1; transform: translateY(0); }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@keyframes enter-scale {
|
|
51
|
+
from { opacity: 0; transform: scale(0.85); }
|
|
52
|
+
to { opacity: 1; transform: scale(1); }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@keyframes enter-reveal {
|
|
56
|
+
from { opacity: 0; clip-path: inset(0 100% 0 0); }
|
|
57
|
+
to { opacity: 1; clip-path: inset(0 0% 0 0); }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@keyframes enter-blur {
|
|
61
|
+
from { opacity: 0; filter: blur(10px); }
|
|
62
|
+
to { opacity: 1; filter: blur(0px); }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@keyframes enter-blur-in {
|
|
66
|
+
from { opacity: 0; filter: blur(6px); }
|
|
67
|
+
to { opacity: 1; filter: blur(0px); }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Prefers reduced motion — neutralize ALL enter animations */
|
|
71
|
+
@media (prefers-reduced-motion: reduce) {
|
|
72
|
+
[data-enter-animation] {
|
|
73
|
+
animation: none !important;
|
|
74
|
+
opacity: 1 !important;
|
|
75
|
+
transform: none !important;
|
|
76
|
+
filter: none !important;
|
|
77
|
+
clip-path: none !important;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Suppress hover transitions while enter animation is still playing.
|
|
82
|
+
Prevents visual conflict between CSS animation (enter) and CSS transition (hover). */
|
|
83
|
+
[data-enter-animation]:not([data-entered]) [data-hover-effect] {
|
|
84
|
+
transition: none !important;
|
|
85
|
+
pointer-events: none;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* ============================================
|
|
89
|
+
Hover Effect System (Sessions 60, 120)
|
|
90
|
+
============================================
|
|
91
|
+
Most hover styling is applied via inline styles in HoverAnimationWrapper.
|
|
92
|
+
The :hover pseudo-class cannot be set inline, so we use data attributes. */
|
|
93
|
+
|
|
94
|
+
/* Scale Up */
|
|
95
|
+
[data-hover-effect="scale-up"]:hover {
|
|
96
|
+
transform: scale(1.05) !important;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Scale Down */
|
|
100
|
+
[data-hover-effect="scale-down"]:hover {
|
|
101
|
+
transform: scale(0.95) !important;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Lift — uses inline custom properties for intensity-dependent values */
|
|
105
|
+
[data-hover-effect="lift"] {
|
|
106
|
+
--hover-lift-y: -4px;
|
|
107
|
+
--hover-lift-shadow: 0 8px 20px rgba(0,0,0,0.15);
|
|
108
|
+
}
|
|
109
|
+
[data-hover-effect="lift"]:hover {
|
|
110
|
+
transform: translateY(var(--hover-lift-y)) !important;
|
|
111
|
+
box-shadow: var(--hover-lift-shadow) !important;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Tilt 3D — transform is handled by JS mousemove, but we ensure base state */
|
|
115
|
+
[data-hover-effect="tilt-3d"] {
|
|
116
|
+
transform-style: preserve-3d;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* Color Shift */
|
|
120
|
+
[data-hover-effect="color-shift"] {
|
|
121
|
+
--hover-brightness: 1.1;
|
|
122
|
+
--hover-saturate: 1.2;
|
|
123
|
+
}
|
|
124
|
+
[data-hover-effect="color-shift"]:hover {
|
|
125
|
+
filter: brightness(var(--hover-brightness)) saturate(var(--hover-saturate)) !important;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Blur Reveal */
|
|
129
|
+
[data-hover-effect="blur-reveal"] {
|
|
130
|
+
--hover-blur-base: 3px;
|
|
131
|
+
--hover-opacity-base: 0.85;
|
|
132
|
+
}
|
|
133
|
+
[data-hover-effect="blur-reveal"]:hover {
|
|
134
|
+
filter: blur(0px) !important;
|
|
135
|
+
opacity: 1 !important;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Border Glow */
|
|
139
|
+
[data-hover-effect="border-glow"] {
|
|
140
|
+
--hover-glow-spread: 4px;
|
|
141
|
+
--hover-glow-color: rgba(53, 128, 249,0.4);
|
|
142
|
+
}
|
|
143
|
+
[data-hover-effect="border-glow"]:hover {
|
|
144
|
+
box-shadow: 0 0 calc(var(--hover-glow-spread) * 2) var(--hover-glow-spread) var(--hover-glow-color) !important;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Prefers reduced motion — disable hover animations */
|
|
148
|
+
@media (prefers-reduced-motion: reduce) {
|
|
149
|
+
[data-hover-effect] {
|
|
150
|
+
transition: none !important;
|
|
151
|
+
}
|
|
152
|
+
[data-hover-effect]:hover {
|
|
153
|
+
transform: none !important;
|
|
154
|
+
filter: none !important;
|
|
155
|
+
box-shadow: none !important;
|
|
156
|
+
opacity: 1 !important;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* ============================================
|
|
161
|
+
Text Animation Presets (Parallax Showcase)
|
|
162
|
+
CSS-only presets for title/subtitle entrance.
|
|
163
|
+
Triggered via IntersectionObserver (enter mode).
|
|
164
|
+
============================================ */
|
|
165
|
+
|
|
166
|
+
/* ============================================
|
|
167
|
+
Nav Entrance Animations
|
|
168
|
+
Applied to the entire nav or individual items
|
|
169
|
+
when stagger is enabled. Triggered on page load.
|
|
170
|
+
============================================ */
|
|
171
|
+
|
|
172
|
+
@keyframes nav-fade-in {
|
|
173
|
+
from { opacity: 0; }
|
|
174
|
+
to { opacity: 1; }
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@keyframes nav-slide-down {
|
|
178
|
+
from { opacity: 0; transform: translateY(-100%); }
|
|
179
|
+
to { opacity: 1; transform: translateY(0); }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@keyframes nav-blur-in {
|
|
183
|
+
from { opacity: 0; filter: blur(12px); }
|
|
184
|
+
to { opacity: 1; filter: blur(0px); }
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Nav entrance: initial hidden state */
|
|
188
|
+
[data-nav-entrance] {
|
|
189
|
+
opacity: 0;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* Nav entrance: play once the attribute is set */
|
|
193
|
+
[data-nav-entrance="fade-in"][data-nav-entered] {
|
|
194
|
+
animation: nav-fade-in var(--nav-entrance-duration, 600ms) var(--nav-entrance-delay, 0ms) ease-out forwards;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
[data-nav-entrance="slide-down"][data-nav-entered] {
|
|
198
|
+
animation: nav-slide-down var(--nav-entrance-duration, 600ms) var(--nav-entrance-delay, 0ms) ease-out forwards;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
[data-nav-entrance="blur-in"][data-nav-entered] {
|
|
202
|
+
animation: nav-blur-in var(--nav-entrance-duration, 700ms) var(--nav-entrance-delay, 0ms) ease-out forwards;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* Staggered items: each item animates independently */
|
|
206
|
+
[data-nav-item-entrance] {
|
|
207
|
+
opacity: 0;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
[data-nav-item-entrance="fade-in"][data-nav-entered] {
|
|
211
|
+
animation: nav-fade-in var(--nav-item-duration, 400ms) var(--nav-item-delay, 0ms) ease-out forwards;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
[data-nav-item-entrance="slide-down"][data-nav-entered] {
|
|
215
|
+
animation: nav-slide-down var(--nav-item-duration, 400ms) var(--nav-item-delay, 0ms) ease-out forwards;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
[data-nav-item-entrance="blur-in"][data-nav-entered] {
|
|
219
|
+
animation: nav-blur-in var(--nav-item-duration, 400ms) var(--nav-item-delay, 0ms) ease-out forwards;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/* Prefers reduced motion — disable nav animations */
|
|
223
|
+
@media (prefers-reduced-motion: reduce) {
|
|
224
|
+
[data-nav-entrance],
|
|
225
|
+
[data-nav-item-entrance] {
|
|
226
|
+
animation: none !important;
|
|
227
|
+
opacity: 1 !important;
|
|
228
|
+
transform: none !important;
|
|
229
|
+
filter: none !important;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/* Typewriter cursor blink */
|
|
234
|
+
@keyframes typewriter-cursor-blink {
|
|
235
|
+
0%, 100% { opacity: 1; }
|
|
236
|
+
50% { opacity: 0; }
|
|
237
|
+
}
|