kmcom-nuxt-layers 4.0.1 → 5.0.1
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/docs/PEER-DEPENDENCY-MISMATCHES.md +48 -0
- package/docs/VITE-PLUS-MIGRATION.md +246 -0
- package/docs/superpowers/plans/2026-09-03-layout-layer-fluid-rebuild.md +8 -8
- package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-7-design.md +1 -1
- package/docs/superpowers/specs/2026-08-31-swiss-grid-layer-design.md +3 -3
- package/docs/superpowers/specs/2026-09-03-layout-layer-fluid-rebuild-design.md +3 -3
- package/layers/content/app/components/Blog/Article.vue +1 -1
- package/layers/content/app/components/Gallery/Detail.vue +8 -8
- package/layers/content/app/components/Gallery/Grid.vue +8 -8
- package/layers/content/app/components/Gallery/ImageDetail.vue +6 -6
- package/layers/content/app/components/Gallery/Lightbox.vue +3 -3
- package/layers/content/app/components/NuxtContent/Detail.vue +1 -1
- package/layers/content/app/components/NuxtContent/List.vue +1 -1
- package/layers/content/app/components/Portfolio/ColorPalette.vue +5 -5
- package/layers/content/app/components/Portfolio/Detail.vue +1 -1
- package/layers/content/app/components/Portfolio/List.vue +1 -1
- package/layers/content/app/components/Portfolio/Typography.vue +5 -5
- package/layers/content/app/components/content/Figure.vue +1 -1
- package/layers/core/app/assets/css/layout.css +1 -1
- package/layers/core/app/components/DiagnosticsPage.vue +15 -15
- package/layers/core/app/components/Element.test.ts +1 -1
- package/layers/core/app/components/ElementTw.test.ts +1 -1
- package/layers/core/app/components/ErrorBoundary.vue +5 -5
- package/layers/core/app/composables/useElementGrid.test.ts +1 -1
- package/layers/core/app/composables/useElementInteraction.test.ts +1 -1
- package/layers/core/app/composables/useElementLayout.test.ts +1 -1
- package/layers/core/app/composables/useElementSizing.test.ts +1 -1
- package/layers/core/app/composables/useElementSurface.test.ts +1 -1
- package/layers/core/app/composables/useLayoutAttrs.test.ts +1 -1
- package/layers/core/app/error.vue +1 -1
- package/layers/core/app/pages/[...slug].vue +2 -2
- package/layers/core/app/utils/browserInfo.test.ts +1 -1
- package/layers/core/app/utils/featureClasses.test.ts +1 -1
- package/layers/core/app/utils/scrollGuardClamp.test.ts +1 -1
- package/layers/core/app/utils/styleToTailwindClasses.test.ts +1 -1
- package/layers/data/forms/app/utils/contact-schema.test.ts +1 -1
- package/layers/data/forms/app/utils/fieldProps.test.ts +1 -1
- package/layers/data/metadata/providers/comicvine/server/utils/metadata-comicvine/normalise.test.ts +1 -1
- package/layers/data/metadata/providers/google-books/server/utils/metadata-google-books/client.test.ts +1 -1
- package/layers/data/metadata/providers/google-books/server/utils/metadata-google-books/normalise.test.ts +1 -1
- package/layers/data/metadata/providers/openlibrary/server/utils/metadata-openlibrary/client.test.ts +1 -1
- package/layers/data/metadata/providers/openlibrary/server/utils/metadata-openlibrary/normalise.test.ts +1 -1
- package/layers/data/metadata/providers/themoviedb/server/utils/metadata-tmdb/client.test.ts +1 -1
- package/layers/data/metadata/providers/themoviedb/server/utils/metadata-tmdb/normalise.test.ts +1 -1
- package/layers/data/metadata/server/utils/metadata/cache.test.ts +1 -1
- package/layers/data/metadata/server/utils/metadata/provider-registry.test.ts +1 -1
- package/layers/data/metadata/server/utils/metadata/search.test.ts +1 -1
- package/layers/delivery/feeds/app/assets/css/feeds.css +23 -11
- package/layers/delivery/feeds/app/components/Feeds/Index.vue +10 -10
- package/layers/delivery/feeds/app/components/Feeds/RouteCard.vue +1 -1
- package/layers/delivery/feeds/public/feed/style.css +16 -16
- package/layers/delivery/feeds/server/utils/content-adapter.test.ts +1 -1
- package/layers/delivery/feeds/server/utils/feed-author.test.ts +1 -1
- package/layers/delivery/feeds/server/utils/feed-config.test.ts +1 -1
- package/layers/delivery/feeds/server/utils/formats.test.ts +1 -1
- package/layers/delivery/scripts/app/components/BaselineStatus.vue +3 -1
- package/layers/delivery/seo/app/utils/seoConfig.test.ts +1 -1
- package/layers/design-system/theming/app/assets/css/theme.css +0 -1
- package/layers/design-system/theming/app/components/ThemePicker/AccentButton.vue +2 -2
- package/layers/design-system/theming/app/components/ThemePicker/Menu.vue +3 -3
- package/layers/design-system/theming/app/composables/useAccentColor.ts +4 -1
- package/layers/design-system/theming/app/plugins/theme.client.ts +15 -13
- package/layers/design-system/theming/app/utils/themeAdapter.ts +1 -1
- package/layers/design-system/theming/nuxt.config.ts +1 -1
- package/layers/design-system/theming/server/utils/accent-css.test.ts +1 -1
- package/layers/design-system/theming/server/utils/fouc-config.test.ts +1 -1
- package/layers/design-system/typography/app/components/Typography/TextStroke.vue +1 -1
- package/layers/design-system/visual/app/assets/css/visual.css +0 -1
- package/layers/design-system/visual/app/components/Accent/Scene.vue +2 -2
- package/layers/design-system/visual/app/components/Tint/Overlay.vue +1 -1
- package/layers/design-system/visual/app/utils/colorTokens.test.ts +1 -1
- package/layers/design-system/visual/app/utils/gradientStyle.test.ts +1 -1
- package/layers/design-system/visual/app/utils/responsiveSizes.test.ts +1 -1
- package/layers/motion/animations/app/components/Motion/Marquee.vue +1 -1
- package/layers/motion/animations/app/components/Motion/MarqueeText.vue +3 -3
- package/layers/motion/scroll/app/components/Motion/HorizontalScroll.vue +1 -1
- package/layers/motion/scroll/app/components/Motion/PinnedSection.vue +2 -2
- package/layers/motion/scroll/app/components/Motion/ScrollProgress.vue +2 -2
- package/layers/motion/scroll/app/components/Motion/ScrollStats.vue +6 -6
- package/layers/motion/transitions/app/assets/css/transitions.css +12 -12
- package/layers/render/canvas/nuxt.config.ts +1 -1
- package/layers/render/canvas/package.json +2 -1
- package/layers/render/shader/app/assets/css/shader.css +5 -5
- package/layers/render/shader/app/shaders/common/grain.ts +1 -1
- package/layers/render/shader/app/types/tsl.ts +1 -1
- package/layers/render/shader/app/utils/tsl/index.ts +2 -0
- package/layers/structure/grid/app/assets/css/grid.css +2 -0
- package/layers/structure/grid/app/composables/useGridTracks.test.ts +1 -1
- package/layers/structure/grid/app/types/tracks.test.ts +1 -1
- package/layers/structure/grid/app/utils/placement.test.ts +1 -1
- package/layers/structure/layout/app/components/Layout/Grid/Debug.vue +1 -1
- package/layers/structure/layout/app/components/Layout/Page/Header.vue +3 -3
- package/layers/structure/layout/app/components/Layout/Page/index.vue +16 -11
- package/layers/structure/layout/app/utils/gridPlacementStyle.test.ts +1 -1
- package/layers/structure/navigation/app/components/Mast/Nav.vue +1 -1
- package/layers/structure/navigation/app/components/Mast/NavModal.vue +2 -2
- package/layers/structure/navigation/app/utils/site.test.ts +1 -1
- package/layers/structure/routing/app/utils/resolveRoute.test.ts +1 -1
- package/package.json +26 -45
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
:root {
|
|
15
|
-
--feed-bg: var(--ui-bg,
|
|
16
|
-
--feed-bg-elevated: var(--ui-bg-elevated,
|
|
17
|
-
--feed-bg-accented: var(--ui-bg-accented,
|
|
18
|
-
--feed-border: var(--ui-border,
|
|
19
|
-
--feed-text: var(--ui-text,
|
|
20
|
-
--feed-text-muted: var(--ui-text-muted,
|
|
21
|
-
--feed-text-toned: var(--ui-text-toned,
|
|
15
|
+
--feed-bg: var(--ui-bg, oklch(100% 0 0deg));
|
|
16
|
+
--feed-bg-elevated: var(--ui-bg-elevated, oklch(98.42% 0.0034 247.86deg));
|
|
17
|
+
--feed-bg-accented: var(--ui-bg-accented, oklch(96.83% 0.0069 247.9deg));
|
|
18
|
+
--feed-border: var(--ui-border, oklch(92.88% 0.0126 255.51deg));
|
|
19
|
+
--feed-text: var(--ui-text, oklch(20.77% 0.0398 265.75deg));
|
|
20
|
+
--feed-text-muted: var(--ui-text-muted, oklch(55.44% 0.0407 257.42deg));
|
|
21
|
+
--feed-text-toned: var(--ui-text-toned, oklch(44.55% 0.0374 257.28deg));
|
|
22
22
|
--feed-primary: var(--ui-color-primary-500, oklch(62.3% 0.214 259.5deg));
|
|
23
23
|
--feed-primary-text: var(--ui-color-primary-600, oklch(54.6% 0.214 259.5deg));
|
|
24
24
|
--feed-primary-bg: var(--ui-color-primary-50, oklch(97% 0.03 259.5deg));
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
|
|
29
29
|
@media (prefers-color-scheme: dark) {
|
|
30
30
|
:root {
|
|
31
|
-
--feed-bg: var(--ui-bg,
|
|
32
|
-
--feed-bg-elevated: var(--ui-bg-elevated,
|
|
33
|
-
--feed-bg-accented: var(--ui-bg-accented,
|
|
34
|
-
--feed-border: var(--ui-border,
|
|
35
|
-
--feed-text: var(--ui-text,
|
|
36
|
-
--feed-text-muted: var(--ui-text-muted,
|
|
37
|
-
--feed-text-toned: var(--ui-text-toned,
|
|
31
|
+
--feed-bg: var(--ui-bg, oklch(12.88% 0.0406 264.7deg));
|
|
32
|
+
--feed-bg-elevated: var(--ui-bg-elevated, oklch(20.77% 0.0398 265.75deg));
|
|
33
|
+
--feed-bg-accented: var(--ui-bg-accented, oklch(27.95% 0.0368 260.03deg));
|
|
34
|
+
--feed-border: var(--ui-border, oklch(27.95% 0.0368 260.03deg));
|
|
35
|
+
--feed-text: var(--ui-text, oklch(98.42% 0.0034 247.86deg));
|
|
36
|
+
--feed-text-muted: var(--ui-text-muted, oklch(71.07% 0.0351 256.79deg));
|
|
37
|
+
--feed-text-toned: var(--ui-text-toned, oklch(86.9% 0.0198 252.89deg));
|
|
38
38
|
--feed-primary: var(--ui-color-primary-400, oklch(71% 0.18 259.5deg));
|
|
39
39
|
--feed-primary-text: var(--ui-color-primary-400, oklch(71% 0.18 259.5deg));
|
|
40
40
|
--feed-primary-bg: var(--ui-color-primary-950, oklch(22% 0.06 259.5deg));
|
|
@@ -160,7 +160,7 @@ a:hover {
|
|
|
160
160
|
border-radius: var(--feed-radius);
|
|
161
161
|
background-color: var(--feed-primary);
|
|
162
162
|
padding: 0.5rem 1.125rem;
|
|
163
|
-
color:
|
|
163
|
+
color: oklch(100% 0 0deg);
|
|
164
164
|
font-weight: 600;
|
|
165
165
|
font-size: 0.875rem;
|
|
166
166
|
line-height: 1;
|
|
@@ -169,7 +169,7 @@ a:hover {
|
|
|
169
169
|
|
|
170
170
|
.feed-subscribe:hover {
|
|
171
171
|
opacity: 0.85;
|
|
172
|
-
color:
|
|
172
|
+
color: oklch(100% 0 0deg);
|
|
173
173
|
text-decoration: none;
|
|
174
174
|
}
|
|
175
175
|
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
},
|
|
11
11
|
},
|
|
12
12
|
setup(props) {
|
|
13
|
-
|
|
13
|
+
// Render the custom element on server AND client. Returning null on the server
|
|
14
|
+
// produced a comment node there but an element on the client (hydration mismatch);
|
|
15
|
+
// an unregistered custom element is inert until the client script upgrades it.
|
|
14
16
|
return () => h('baseline-status', { featureId: props.featureId })
|
|
15
17
|
},
|
|
16
18
|
})
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
class="size-8 rounded-full ring-1 ring-offset-2 transition-shadow duration-200"
|
|
22
22
|
:class="[
|
|
23
23
|
active
|
|
24
|
-
? 'ring-
|
|
25
|
-
: '
|
|
24
|
+
? 'ring-primary ring-offset-bg shadow-lg ring-2'
|
|
25
|
+
: 'hover:ring-muted ring-offset-bg ring-transparent hover:shadow-md',
|
|
26
26
|
]"
|
|
27
27
|
:style="bgStyle"
|
|
28
28
|
:aria-label="`Set accent color to ${color}`"
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
<li class="flex w-full flex-row items-center justify-between py-1">
|
|
35
35
|
<div>
|
|
36
36
|
<h2 class="text-lg font-semibold">High Contrast</h2>
|
|
37
|
-
<p v-if="contrastOverride === 'system'" class="text-
|
|
37
|
+
<p v-if="contrastOverride === 'system'" class="text-muted text-sm">
|
|
38
38
|
Following system
|
|
39
39
|
</p>
|
|
40
40
|
</div>
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
<li class="flex w-full flex-row items-center justify-between py-1">
|
|
50
50
|
<div>
|
|
51
51
|
<h2 class="text-lg font-semibold">Reduce Motion</h2>
|
|
52
|
-
<p v-if="motionOverride === 'system'" class="text-
|
|
52
|
+
<p v-if="motionOverride === 'system'" class="text-muted text-sm">
|
|
53
53
|
Following system
|
|
54
54
|
</p>
|
|
55
55
|
</div>
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
<li class="flex w-full flex-row items-center justify-between py-1">
|
|
65
65
|
<div>
|
|
66
66
|
<h2 class="text-lg font-semibold">Reduce Transparency</h2>
|
|
67
|
-
<p v-if="transparencyOverride === 'system'" class="text-
|
|
67
|
+
<p v-if="transparencyOverride === 'system'" class="text-muted text-sm">
|
|
68
68
|
Following system
|
|
69
69
|
</p>
|
|
70
70
|
</div>
|
|
@@ -13,7 +13,10 @@ export const useAccentColor = createSharedComposable(() => {
|
|
|
13
13
|
// theme.client.ts reads localStorage after hydration and calls setAccent.
|
|
14
14
|
const accent = useState<AccentColor>('theme-accent', () => defaultAccent)
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
// Page-scoped override. Must be useState (not a module-level ref): pages call
|
|
17
|
+
// setPageAccent() during setup, and a plain ref is not carried in the SSR payload,
|
|
18
|
+
// so the server rendered the default accent while the client had the page's.
|
|
19
|
+
const pageAccent = useState<AccentColor | null>('theme-page-accent', () => null)
|
|
17
20
|
const activeAccent = computed<AccentColor>(() => pageAccent.value ?? accent.value)
|
|
18
21
|
|
|
19
22
|
function setAccent(color: AccentColor) {
|
|
@@ -10,19 +10,21 @@ export default defineNuxtPlugin({
|
|
|
10
10
|
const { setTransparencyOverride, effectiveReducedTransparency } = useThemeTransparency()
|
|
11
11
|
|
|
12
12
|
// Restore persisted preferences. useState defaults were serialized from the
|
|
13
|
-
// server, so hydration matches
|
|
14
|
-
// hydration
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
13
|
+
// server, so hydration matches only if client state is still at those defaults
|
|
14
|
+
// while hydrating. Plugin setup runs BEFORE hydration, so the stored values are
|
|
15
|
+
// applied on `app:mounted` (after hydration) instead of here.
|
|
16
|
+
useNuxtApp().hook('app:mounted', () => {
|
|
17
|
+
const restorers: Array<[key: string, apply: (value: string) => void]> = [
|
|
18
|
+
['theme-colour', (v) => setAccent(v as AccentColor)],
|
|
19
|
+
['theme-contrast', (v) => setContrastOverride(v as PreferenceOverride)],
|
|
20
|
+
['theme-motion', (v) => setMotionOverride(v as PreferenceOverride)],
|
|
21
|
+
['theme-transparency', (v) => setTransparencyOverride(v as PreferenceOverride)],
|
|
22
|
+
]
|
|
23
|
+
for (const [key, apply] of restorers) {
|
|
24
|
+
const stored = localStorage.getItem(key)
|
|
25
|
+
if (stored) apply(stored)
|
|
26
|
+
}
|
|
27
|
+
})
|
|
26
28
|
|
|
27
29
|
watch(
|
|
28
30
|
activeAccent,
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
v-bind="$attrs"
|
|
32
32
|
>
|
|
33
33
|
<!-- Sizer: transparent text for natural sizing + selectable -->
|
|
34
|
-
<span class="text-stroke-sizer text-transparent
|
|
34
|
+
<span class="text-stroke-sizer whitespace-nowrap text-transparent" aria-hidden="true">{{
|
|
35
35
|
text
|
|
36
36
|
}}</span>
|
|
37
37
|
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
</script>
|
|
26
26
|
|
|
27
27
|
<template>
|
|
28
|
-
<component :is="tag" class="relative overflow-clip
|
|
29
|
-
<div class="absolute inset-0
|
|
28
|
+
<component :is="tag" class="relative isolate overflow-clip">
|
|
29
|
+
<div class="pointer-events-none absolute inset-0" aria-hidden="true">
|
|
30
30
|
<AccentBlob
|
|
31
31
|
v-for="(blob, i) in resolvedBlobs"
|
|
32
32
|
:key="i"
|
|
@@ -20,6 +20,6 @@
|
|
|
20
20
|
<template>
|
|
21
21
|
<component :is="tag" class="relative">
|
|
22
22
|
<slot />
|
|
23
|
-
<span class="absolute inset-0
|
|
23
|
+
<span class="pointer-events-none absolute inset-0" :style aria-hidden="true" />
|
|
24
24
|
</component>
|
|
25
25
|
</template>
|
|
@@ -95,8 +95,8 @@
|
|
|
95
95
|
onMounted(async () => {
|
|
96
96
|
await nextTick()
|
|
97
97
|
|
|
98
|
-
baseX.value =
|
|
99
|
-
directionFactors.value =
|
|
98
|
+
baseX.value = Array.from({ length: texts.length }, () => 0)
|
|
99
|
+
directionFactors.value = Array.from({ length: texts.length }, () => 1)
|
|
100
100
|
animLastTime = performance.now()
|
|
101
101
|
|
|
102
102
|
const firstContainer = containerRef.value?.[0]
|
|
@@ -131,7 +131,7 @@
|
|
|
131
131
|
:style="parallaxStyle"
|
|
132
132
|
>
|
|
133
133
|
<div
|
|
134
|
-
:class="`${scrollerClassName} font-styles-logo flex py-2 text-center font-sans text-4xl font-medium tracking-[-0.02em] whitespace-nowrap
|
|
134
|
+
:class="`${scrollerClassName} font-styles-logo text-neutral flex py-2 text-center font-sans text-4xl font-medium tracking-[-0.02em] whitespace-nowrap drop-shadow md:text-[5rem] md:leading-20`"
|
|
135
135
|
:style="{ transform: `translateX(${scrollTransforms[index] ?? '0px'})`, ...scrollerStyle }"
|
|
136
136
|
>
|
|
137
137
|
<span
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
|
|
58
58
|
<template>
|
|
59
59
|
<section ref="sectionRef" class="motion-horizontal-scroll h-screen overflow-hidden">
|
|
60
|
-
<div ref="trackRef" class="h-full
|
|
60
|
+
<div ref="trackRef" class="flex h-full items-center will-change-transform">
|
|
61
61
|
<slot />
|
|
62
62
|
</div>
|
|
63
63
|
</section>
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
</script>
|
|
73
73
|
|
|
74
74
|
<template>
|
|
75
|
-
<section ref="sectionRef" class="motion-pinned-section h-screen
|
|
76
|
-
<div ref="contentRef" class="motion-pinned-content h-full
|
|
75
|
+
<section ref="sectionRef" class="motion-pinned-section relative h-screen">
|
|
76
|
+
<div ref="contentRef" class="motion-pinned-content flex h-full items-center justify-center">
|
|
77
77
|
<slot />
|
|
78
78
|
</div>
|
|
79
79
|
</section>
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
<!-- Linear Progress -->
|
|
50
50
|
<div v-if="type === 'linear'" class="motion-scroll-progress-linear" v-bind="$attrs">
|
|
51
51
|
<div
|
|
52
|
-
class="w-full rounded-full
|
|
52
|
+
class="w-full overflow-hidden rounded-full"
|
|
53
53
|
:style="{ height: `${height}px`, backgroundColor: bgColor }"
|
|
54
54
|
>
|
|
55
55
|
<div
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
}"
|
|
61
61
|
/>
|
|
62
62
|
</div>
|
|
63
|
-
<span v-if="showPercentage" class="text-sm font-medium tabular-nums
|
|
63
|
+
<span v-if="showPercentage" class="mt-2 block text-center text-sm font-medium tabular-nums">
|
|
64
64
|
{{ percentage }}%
|
|
65
65
|
</span>
|
|
66
66
|
</div>
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
|
|
52
52
|
<template>
|
|
53
53
|
<div
|
|
54
|
-
class="bg-black/80 backdrop-blur-sm
|
|
54
|
+
class="rounded-xl bg-black/80 text-white backdrop-blur-sm transition-opacity duration-300"
|
|
55
55
|
:class="[
|
|
56
56
|
...positionClasses,
|
|
57
57
|
isScrolling ? 'opacity-100' : 'opacity-60',
|
|
@@ -61,31 +61,31 @@
|
|
|
61
61
|
<div class="flex items-center" :class="[compact ? 'gap-4 text-xs' : 'gap-6 text-sm']">
|
|
62
62
|
<!-- Scrolling indicator -->
|
|
63
63
|
<div
|
|
64
|
-
class="
|
|
64
|
+
class="h-2 w-2 rounded-full transition-colors duration-100"
|
|
65
65
|
:class="isScrolling ? 'bg-green-500' : 'bg-gray-600'"
|
|
66
66
|
/>
|
|
67
67
|
|
|
68
68
|
<!-- Velocity -->
|
|
69
69
|
<div v-if="show.includes('velocity')" class="text-center">
|
|
70
|
-
<div v-if="!compact" class="
|
|
70
|
+
<div v-if="!compact" class="mb-0.5 text-xs text-gray-500">VEL</div>
|
|
71
71
|
<div class="font-medium tabular-nums">{{ velocity.toFixed(2) }}</div>
|
|
72
72
|
</div>
|
|
73
73
|
|
|
74
74
|
<!-- Progress -->
|
|
75
75
|
<div v-if="show.includes('progress')" class="text-center">
|
|
76
|
-
<div v-if="!compact" class="
|
|
76
|
+
<div v-if="!compact" class="mb-0.5 text-xs text-gray-500">PROG</div>
|
|
77
77
|
<div class="font-medium tabular-nums">{{ (progress * 100).toFixed(0) }}%</div>
|
|
78
78
|
</div>
|
|
79
79
|
|
|
80
80
|
<!-- Direction -->
|
|
81
81
|
<div v-if="show.includes('direction')" class="text-center">
|
|
82
|
-
<div v-if="!compact" class="
|
|
82
|
+
<div v-if="!compact" class="mb-0.5 text-xs text-gray-500">DIR</div>
|
|
83
83
|
<div class="font-medium">{{ directionLabel }}</div>
|
|
84
84
|
</div>
|
|
85
85
|
|
|
86
86
|
<!-- Scroll Y -->
|
|
87
87
|
<div v-if="show.includes('scrollY')" class="text-center">
|
|
88
|
-
<div v-if="!compact" class="
|
|
88
|
+
<div v-if="!compact" class="mb-0.5 text-xs text-gray-500">Y</div>
|
|
89
89
|
<div class="font-medium tabular-nums">{{ Math.round(scrollY) }}px</div>
|
|
90
90
|
</div>
|
|
91
91
|
</div>
|
|
@@ -21,31 +21,31 @@
|
|
|
21
21
|
|
|
22
22
|
/* Animation classes */
|
|
23
23
|
.animate-fade-in {
|
|
24
|
-
animation:
|
|
24
|
+
animation: fade-in 0.3s ease-out forwards;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
.animate-fade-out {
|
|
28
|
-
animation:
|
|
28
|
+
animation: fade-out 0.3s ease-out forwards;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
.animate-slide-in-up {
|
|
32
|
-
animation:
|
|
32
|
+
animation: slide-in-up 0.3s ease-out forwards;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
.animate-slide-in-down {
|
|
36
|
-
animation:
|
|
36
|
+
animation: slide-in-down 0.3s ease-out forwards;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
.animate-slide-in-left {
|
|
40
|
-
animation:
|
|
40
|
+
animation: slide-in-left 0.3s ease-out forwards;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
.animate-slide-in-right {
|
|
44
|
-
animation:
|
|
44
|
+
animation: slide-in-right 0.3s ease-out forwards;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/* Keyframes */
|
|
48
|
-
@keyframes
|
|
48
|
+
@keyframes fade-in {
|
|
49
49
|
from {
|
|
50
50
|
opacity: 0;
|
|
51
51
|
}
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
@keyframes
|
|
58
|
+
@keyframes fade-out {
|
|
59
59
|
from {
|
|
60
60
|
opacity: 1;
|
|
61
61
|
}
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
@keyframes
|
|
68
|
+
@keyframes slide-in-up {
|
|
69
69
|
from {
|
|
70
70
|
transform: translateY(20px);
|
|
71
71
|
opacity: 0;
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
@keyframes
|
|
80
|
+
@keyframes slide-in-down {
|
|
81
81
|
from {
|
|
82
82
|
transform: translateY(-20px);
|
|
83
83
|
opacity: 0;
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
@keyframes
|
|
92
|
+
@keyframes slide-in-left {
|
|
93
93
|
from {
|
|
94
94
|
transform: translateX(-20px);
|
|
95
95
|
opacity: 0;
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
@keyframes
|
|
104
|
+
@keyframes slide-in-right {
|
|
105
105
|
from {
|
|
106
106
|
transform: translateX(20px);
|
|
107
107
|
opacity: 0;
|
|
@@ -12,17 +12,17 @@
|
|
|
12
12
|
z-index: 9999;
|
|
13
13
|
backdrop-filter: blur(8px);
|
|
14
14
|
border-radius: 0.5rem;
|
|
15
|
-
background:
|
|
15
|
+
background: oklch(0% 0 0deg / 0.8);
|
|
16
16
|
padding: 0.75rem 1rem;
|
|
17
17
|
min-width: 200px;
|
|
18
|
-
color:
|
|
18
|
+
color: oklch(100% 0 0deg);
|
|
19
19
|
font-size: 0.75rem;
|
|
20
20
|
font-family: ui-monospace, monospace;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
.shader-debug-title {
|
|
24
24
|
margin-bottom: 0.5rem;
|
|
25
|
-
color:
|
|
25
|
+
color: oklch(70.9% 0.1592 293.54deg);
|
|
26
26
|
font-weight: 600;
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
.shader-debug-label {
|
|
36
|
-
color:
|
|
36
|
+
color: oklch(71.07% 0.0351 256.79deg);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
.shader-debug-value {
|
|
40
|
-
color:
|
|
40
|
+
color: oklch(72.27% 0.192 149.58deg);
|
|
41
41
|
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
:root {
|
|
13
13
|
/* rem term keeps this WCAG 1.4.4 zoom-safe; svi never vw (viewport-bar-collapse safe) */
|
|
14
14
|
--fs: clamp(1rem, 0.95rem + 0.25svi, 1.125rem);
|
|
15
|
+
|
|
15
16
|
/* rounded, not raw, so grid boundaries land on-pixel */
|
|
16
17
|
line-height: round(nearest, var(--fs) * 1.5, 1px);
|
|
17
18
|
}
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
line-height */
|
|
22
23
|
--unit: 1rlh;
|
|
23
24
|
--measure-min: 22rem;
|
|
25
|
+
|
|
24
26
|
/* margin floor > 0, steep svi slope so it shrinks fast on narrow screens */
|
|
25
27
|
--edge-min: clamp(1rlh, 8svi, 3rlh);
|
|
26
28
|
--avail-b: calc(100svh - 2 * var(--edge-min));
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
|
|
73
73
|
<template>
|
|
74
74
|
<Teleport to="body">
|
|
75
|
-
<div v-if="visible" :style class="grid-debug
|
|
75
|
+
<div v-if="visible" :style class="grid-debug fixed inset-0 z-9999" aria-hidden="true">
|
|
76
76
|
<div v-for="i in cols" :key="i" :style="{ backgroundColor: color }" class="h-full" />
|
|
77
77
|
</div>
|
|
78
78
|
</Teleport>
|