2026-06-17 17:06:30 -06:00
|
|
|
<!doctype html>
|
|
|
|
|
<html lang="en" data-color-scheme>
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="utf-8" />
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
|
|
|
<link rel="icon" href="%sveltekit.assets%/favicon.ico" />
|
|
|
|
|
<meta name="color-scheme" content="light dark" />
|
2026-06-21 20:03:32 -06:00
|
|
|
%sveltekit.head%
|
2026-06-17 17:06:30 -06:00
|
|
|
<!--
|
|
|
|
|
Anti-FOUC theme init — runs synchronously before first paint.
|
|
|
|
|
Ported from static/js/core/theme-init.js. Keeps the legacy
|
|
|
|
|
`oxicloud_theme` localStorage key and `data-color-scheme` attribute
|
|
|
|
|
so existing users keep their preference across the migration.
|
2026-06-21 20:03:32 -06:00
|
|
|
|
|
|
|
|
Placed AFTER %sveltekit.head% so it follows the CSP <meta> SvelteKit
|
|
|
|
|
injects there, hence it IS governed by that policy. svelte.config.js
|
|
|
|
|
parses this file, finds this <script> by id="theme-init", and adds its
|
|
|
|
|
SHA-256 to script-src automatically — so it's allowed inline (zero extra
|
|
|
|
|
request, no 'unsafe-inline') and the hash stays in sync if you edit it.
|
2026-06-17 17:06:30 -06:00
|
|
|
-->
|
2026-06-21 20:03:32 -06:00
|
|
|
<script id="theme-init">
|
2026-06-17 17:06:30 -06:00
|
|
|
(function () {
|
|
|
|
|
try {
|
|
|
|
|
var s = localStorage.getItem('oxicloud_theme');
|
|
|
|
|
var h = document.documentElement;
|
|
|
|
|
if (s === 'light' || s === 'dark') h.setAttribute('data-color-scheme', s);
|
|
|
|
|
else h.removeAttribute('data-color-scheme');
|
|
|
|
|
} catch (e) {
|
|
|
|
|
/* localStorage unavailable — fall back to OS preference */
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
</script>
|
2026-06-19 16:36:54 +00:00
|
|
|
<!--
|
|
|
|
|
Instant boot splash. Paints on HTML parse (before the app bundle and its
|
|
|
|
|
CSS load), covering the otherwise-blank gap during JS download/parse for a
|
|
|
|
|
faster perceived first paint. The root layout removes `#app-splash` as soon
|
|
|
|
|
as it mounts. `light-dark()` + the early `color-scheme` rules match the
|
|
|
|
|
resolved theme so there's no colour flash when the app CSS arrives.
|
|
|
|
|
-->
|
|
|
|
|
<style>
|
|
|
|
|
html[data-color-scheme='dark'] {
|
|
|
|
|
color-scheme: dark;
|
|
|
|
|
}
|
|
|
|
|
html[data-color-scheme='light'] {
|
|
|
|
|
color-scheme: light;
|
|
|
|
|
}
|
|
|
|
|
#app-splash {
|
|
|
|
|
position: fixed;
|
|
|
|
|
inset: 0;
|
|
|
|
|
z-index: 9999;
|
|
|
|
|
display: grid;
|
|
|
|
|
place-items: center;
|
|
|
|
|
background: light-dark(#f5f7fa, #0f172a);
|
|
|
|
|
}
|
|
|
|
|
#app-splash__spinner {
|
|
|
|
|
width: 38px;
|
|
|
|
|
height: 38px;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
border: 3px solid light-dark(#e2e8f0, #334155);
|
|
|
|
|
border-top-color: #ff5e3a;
|
|
|
|
|
animation: app-splash-spin 0.7s linear infinite;
|
|
|
|
|
}
|
|
|
|
|
@keyframes app-splash-spin {
|
|
|
|
|
to {
|
|
|
|
|
transform: rotate(360deg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
|
|
|
#app-splash__spinner {
|
|
|
|
|
animation: none;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|
2026-06-17 17:06:30 -06:00
|
|
|
</head>
|
|
|
|
|
<body data-sveltekit-preload-data="hover">
|
2026-06-19 16:36:54 +00:00
|
|
|
<div id="app-splash" role="status" aria-label="Loading">
|
|
|
|
|
<div id="app-splash__spinner"></div>
|
|
|
|
|
</div>
|
2026-06-17 17:06:30 -06:00
|
|
|
<div style="display: contents">%sveltekit.body%</div>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|