diff --git a/hdyc-svelte/src/app.css b/hdyc-svelte/src/app.css
index 5fb1295..46a0407 100644
--- a/hdyc-svelte/src/app.css
+++ b/hdyc-svelte/src/app.css
@@ -62,14 +62,6 @@
src: url('/fonts/jetbrains-mono/JetBrainsMono-SemiBold.woff2') format('woff2');
}
-body {
- visibility: visible;
-}
-
-:root[data-fonts='loading'] body {
- visibility: hidden;
-}
-
:root {
/* ─── Colors (Dark Theme) ─────────────────────────────── */
--bg: #0c0f14;
@@ -467,11 +459,7 @@ a:focus-visible {
.palette-dots {
display: flex;
gap: 0.25rem;
- max-width: 38px;
- overflow-x: hidden;
- overflow-y: visible;
flex: 0 0 auto;
- transition: max-width 0.2s ease, gap 0.2s ease;
}
.palette-dot {
width: 30px;
@@ -482,11 +470,10 @@ a:focus-visible {
background-size: 160%;
background-position: center;
cursor: pointer;
- transition: transform 0.2s, border-color 0.2s, box-shadow 0.2s, opacity 0.2s;
+ transition: transform 0.2s, border-color 0.2s, box-shadow 0.2s;
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05);
overflow: hidden;
flex-shrink: 0;
- order: 0;
transform-origin: center;
}
.palette-dot:hover {
@@ -500,27 +487,6 @@ a:focus-visible {
.palette-dot:focus-visible {
outline: none;
}
-.floating-palette-controls:not(:hover):not(:focus-within) .palette-dots {
- gap: 0;
-}
-.floating-palette-controls:not(:hover):not(:focus-within) .palette-dot:not(.active) {
- opacity: 0;
- pointer-events: none;
-}
-.floating-palette-controls:not(:hover):not(:focus-within) .palette-dot.active {
- order: -1;
-}
-.floating-palette-controls:hover .palette-dots,
-.floating-palette-controls:focus-within .palette-dots {
- max-width: min(280px, calc(100vw - 2rem));
- gap: 0.25rem;
-}
-.floating-palette-controls:hover .palette-dot:not(.active),
-.floating-palette-controls:focus-within .palette-dot:not(.active) {
- opacity: 1;
- pointer-events: auto;
-}
-
@media (max-width: 520px) {
.floating-palette-controls {
gap: 0.2rem;
diff --git a/hdyc-svelte/src/app.html b/hdyc-svelte/src/app.html
index 1837ea7..e88d3f9 100644
--- a/hdyc-svelte/src/app.html
+++ b/hdyc-svelte/src/app.html
@@ -1,5 +1,5 @@
-
+
@@ -62,9 +62,6 @@
%sveltekit.head%
diff --git a/hdyc-svelte/src/hooks.server.ts b/hdyc-svelte/src/hooks.server.ts
index 1c4a2cb..1bd509c 100644
--- a/hdyc-svelte/src/hooks.server.ts
+++ b/hdyc-svelte/src/hooks.server.ts
@@ -14,7 +14,25 @@ const MIME_TYPES: Record = {
};
const HTML_CACHE_CONTROL = 'public, max-age=0, must-revalidate';
+const IMMUTABLE_ASSET_CACHE_CONTROL = 'public, max-age=31536000, immutable';
const ASSET_404_CACHE_CONTROL = 'no-store';
+const LONG_CACHE_EXTENSIONS = new Set([
+ '.js',
+ '.mjs',
+ '.css',
+ '.json',
+ '.svg',
+ '.png',
+ '.jpg',
+ '.jpeg',
+ '.webp',
+ '.avif',
+ '.ico',
+ '.woff2',
+ '.woff',
+ '.ttf',
+ '.otf'
+]);
export const handle: Handle = async ({ event, resolve }) => {
const response = await resolve(event);
@@ -36,11 +54,18 @@ export const handle: Handle = async ({ event, resolve }) => {
// keep pointing to already-rotated files long after a deployment.
if (response.status >= 400) {
response.headers.set('cache-control', ASSET_404_CACHE_CONTROL);
+ } else if (pathname.startsWith('/_app/immutable/')) {
+ response.headers.set('cache-control', IMMUTABLE_ASSET_CACHE_CONTROL);
}
return response;
}
+ const extension = path.extname(pathname).toLowerCase();
+ if (LONG_CACHE_EXTENSIONS.has(extension) && !contentType.includes('text/html')) {
+ response.headers.set('cache-control', IMMUTABLE_ASSET_CACHE_CONTROL);
+ }
+
// HTML documents should revalidate so they can reference the latest client
// bundle hashes after each deployment.
if (contentType.includes('text/html')) {
diff --git a/hdyc-svelte/src/lib/components/Sidebar.svelte b/hdyc-svelte/src/lib/components/Sidebar.svelte
index 360be04..8cdb80b 100644
--- a/hdyc-svelte/src/lib/components/Sidebar.svelte
+++ b/hdyc-svelte/src/lib/components/Sidebar.svelte
@@ -412,14 +412,16 @@
.sidebar {
position: fixed;
top: 0;
- left: -300px;
+ left: 0;
z-index: 100;
height: 100vh;
- transition: left 0.3s ease;
+ transform: translateX(-100%);
+ transition: transform 0.3s ease;
+ will-change: transform;
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.2);
}
.sidebar.open {
- left: 0;
+ transform: translateX(0);
}
.close-btn {
display: block;
diff --git a/hdyc-svelte/src/routes/+layout.svelte b/hdyc-svelte/src/routes/+layout.svelte
index 8ebb7c4..2f07863 100644
--- a/hdyc-svelte/src/routes/+layout.svelte
+++ b/hdyc-svelte/src/routes/+layout.svelte
@@ -252,6 +252,13 @@
},
},
];
+ const matomoContainerSrc = 'https://matomo.howdoyouconvert.com/js/container_B3r877Kn.js';
+
+ type WindowWithAnalytics = Window & {
+ _mtm?: Array>;
+ requestIdleCallback?: (callback: () => void, options?: { timeout: number }) => number;
+ cancelIdleCallback?: (handle: number) => void;
+ };
let sidebarOpen = false;
let headerSearchOpen = false;
@@ -303,6 +310,22 @@
}
};
+ const loadMatomoContainer = () => {
+ if (!browser) return;
+ if (document.querySelector(`script[src="${matomoContainerSrc}"]`)) return;
+
+ const appWindow = window as WindowWithAnalytics;
+ const queue = appWindow._mtm ?? [];
+ appWindow._mtm = queue;
+ queue.push({ 'mtm.startTime': Date.now(), event: 'mtm.Start' });
+
+ const script = document.createElement('script');
+ script.async = true;
+ script.src = matomoContainerSrc;
+ script.setAttribute('data-cfasync', 'false');
+ document.head.appendChild(script);
+ };
+
afterNavigate(() => {
sidebarOpen = false;
headerSearchOpen = false;
@@ -310,6 +333,9 @@
onMount(() => {
if (!browser) return;
+ const appWindow = window as WindowWithAnalytics;
+ let idleCallbackId: number | null = null;
+ let fallbackTimeoutId: number | null = null;
const savedTheme = window.localStorage.getItem('theme') as ThemeMode | null;
const savedPalette = window.localStorage.getItem('palette');
@@ -356,6 +382,11 @@
sidebarOpen = false;
}
updateHeaderBreakpoint();
+ if (typeof appWindow.requestIdleCallback === 'function') {
+ idleCallbackId = appWindow.requestIdleCallback(loadMatomoContainer, { timeout: 3000 });
+ } else {
+ fallbackTimeoutId = window.setTimeout(loadMatomoContainer, 1200);
+ }
const cleanup = () => {
if ('removeEventListener' in mediaQuery) {
@@ -373,6 +404,12 @@
} else {
headerBreakpoint.removeListener(handleHeaderBreakpoint);
}
+ if (idleCallbackId !== null && typeof appWindow.cancelIdleCallback === 'function') {
+ appWindow.cancelIdleCallback(idleCallbackId);
+ }
+ if (fallbackTimeoutId !== null) {
+ window.clearTimeout(fallbackTimeoutId);
+ }
window.removeEventListener('keydown', handleEscape);
};
@@ -400,16 +437,6 @@
-
-
-
Skip to main content