mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-23 03:27:43 +09:00
The install-time tint only recolored favicon.svg, but the page also shipped a fixed raster favicon.ico + .png — and favicon-hash scanners hash /favicon.ico, which was identical across every install. So the "car-paint" tint didn't change what those tools cluster on. - index.html links only the SVG now (drop the raster <link>s). - Remove the unused favicon-16x16/32x32.png. - install.sh: after tinting favicon.svg, copy it over favicon.ico too, so a blind /favicon.ico fetch also returns the per-install color instead of a fixed icon. (SVG bytes under an .ico name — browsers use the linked SVG; this only affects what a scanner hashes at that URL.) Still obscurity/defense-in-depth, not a real gate — but now it does what it says. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
50 lines
2.6 KiB
HTML
50 lines
2.6 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<!-- Single SVG favicon so the per-install tint (install.sh randomize_favicon)
|
|
is the only mark served; no fixed raster icon to fingerprint-cluster on. -->
|
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
<meta name="description" content="Control Panel" />
|
|
<title>Control Panel</title>
|
|
<!-- Fonts are SELF-HOSTED (see src/styles/base/_fonts.scss → /fonts/*.woff2).
|
|
No Google Fonts / third-party CDN: a self-hosted control panel must not
|
|
leak every user's IP + usage to Google. Falls back to system-ui until
|
|
the woff2 files are present (run frontend/scripts/fetch-fonts.mjs). -->
|
|
<script>
|
|
// Prevent flash of unstyled content (FOUC) by setting theme + accent before React loads
|
|
(function() {
|
|
var d = document.documentElement;
|
|
d.setAttribute('data-theme', localStorage.getItem('theme') || 'dark');
|
|
var accent = localStorage.getItem('accent_color');
|
|
if (accent) {
|
|
var m = accent.match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
|
|
if (m) {
|
|
var r = parseInt(m[1],16), g = parseInt(m[2],16), b = parseInt(m[3],16);
|
|
var hx = function(v){ return Math.max(0,Math.min(255,v)).toString(16).padStart(2,'0'); };
|
|
var dk = function(v){ return Math.round(v*0.88); };
|
|
var br = function(v){ return Math.round(v + (255-v)*0.30); }; // toward white
|
|
var dm = function(v){ return Math.round(v*0.70); };
|
|
d.style.setProperty('--accent-primary', accent);
|
|
d.style.setProperty('--accent', accent);
|
|
d.style.setProperty('--accent-hover', '#'+hx(dk(r))+hx(dk(g))+hx(dk(b)));
|
|
d.style.setProperty('--accent-bright', '#'+hx(br(r))+hx(br(g))+hx(br(b)));
|
|
d.style.setProperty('--accent-dim', '#'+hx(dm(r))+hx(dm(g))+hx(dm(b)));
|
|
d.style.setProperty('--accent-bg', 'rgba('+r+','+g+','+b+',0.13)');
|
|
d.style.setProperty('--accent-bg-soft', 'rgba('+r+','+g+','+b+',0.07)');
|
|
d.style.setProperty('--accent-glow', 'rgba('+r+','+g+','+b+',0.35)');
|
|
d.style.setProperty('--accent-shadow', 'rgba('+r+','+g+','+b+',0.3)');
|
|
}
|
|
}
|
|
})();
|
|
</script>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="root"></div>
|
|
<script type="module" src="/src/main.jsx"></script>
|
|
</body>
|
|
|
|
</html> |