mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-08 02:14:37 +00:00
site: rebuild landing page at 2026-04-30T12:33:24Z
This commit is contained in:
@@ -11,16 +11,50 @@
|
||||
} else {
|
||||
root.removeAttribute('data-theme');
|
||||
}
|
||||
applyImageTheme();
|
||||
}
|
||||
|
||||
// Hydrate stored preference (if any) — runs after DOMContentLoaded since the
|
||||
// <script> is deferred. There's a brief moment of media-query default before
|
||||
// hydrate; that's acceptable here (no FOUC because the media query already
|
||||
// gets the right colors).
|
||||
// Resolve the *effective* theme — explicit data-theme wins, otherwise
|
||||
// fall back to the OS preference.
|
||||
function resolveTheme() {
|
||||
const explicit = root.getAttribute('data-theme');
|
||||
if (explicit === 'light' || explicit === 'dark') return explicit;
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
// Swap every <img data-dark-src="..."> between its light and dark variants.
|
||||
// Also rewrites the parent <picture>'s <source srcset> so the picture
|
||||
// algorithm doesn't override us on resize/layout passes.
|
||||
function applyImageTheme() {
|
||||
const theme = resolveTheme();
|
||||
document.querySelectorAll('img[data-dark-src]').forEach((img) => {
|
||||
if (!img.dataset.lightSrc) {
|
||||
img.dataset.lightSrc = img.getAttribute('src');
|
||||
}
|
||||
const target = theme === 'dark' ? img.dataset.darkSrc : img.dataset.lightSrc;
|
||||
if (img.getAttribute('src') !== target) img.setAttribute('src', target);
|
||||
const picture = img.parentElement;
|
||||
if (picture && picture.tagName === 'PICTURE') {
|
||||
picture.querySelectorAll('source').forEach((s) => {
|
||||
if (s.getAttribute('srcset') !== target) s.setAttribute('srcset', target);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Hydrate stored preference (if any) — runs after DOMContentLoaded since
|
||||
// the <script> is deferred. There's a brief moment of media-query default
|
||||
// before hydrate; that's acceptable here (no FOUC because the media query
|
||||
// already gets the right colors and the first images render at light by
|
||||
// default — JS swaps within a frame on dark-mode systems).
|
||||
let stored = null;
|
||||
try {
|
||||
const stored = localStorage.getItem(STORAGE_KEY);
|
||||
stored = localStorage.getItem(STORAGE_KEY);
|
||||
if (stored === 'light' || stored === 'dark') applyTheme(stored);
|
||||
} catch (_) { /* localStorage unavailable — fall back to media query */ }
|
||||
else applyImageTheme(); // initial pass even if no stored preference
|
||||
} catch (_) {
|
||||
applyImageTheme();
|
||||
}
|
||||
|
||||
const toggle = document.querySelector('[data-theme-toggle]');
|
||||
if (toggle) {
|
||||
@@ -40,8 +74,18 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Re-apply on system preference change so users who haven't set an
|
||||
// explicit override still get matching screenshots.
|
||||
if (window.matchMedia) {
|
||||
const mql = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const onChange = () => {
|
||||
if (!root.hasAttribute('data-theme')) applyImageTheme();
|
||||
};
|
||||
if (mql.addEventListener) mql.addEventListener('change', onChange);
|
||||
else if (mql.addListener) mql.addListener(onChange);
|
||||
}
|
||||
|
||||
// Auto-collapse sticky header on scroll-down, restore on scroll-up.
|
||||
// Pure progressive enhancement — no header in the DOM = nothing happens.
|
||||
const header = document.querySelector('.site-header');
|
||||
if (header) {
|
||||
let lastY = window.scrollY;
|
||||
|
||||
+7
-7
@@ -91,7 +91,7 @@
|
||||
<div class="hero-visual" aria-hidden="false">
|
||||
<picture class="hero-mac">
|
||||
<source media="(prefers-color-scheme: dark)" srcset="assets/screenshots/mac-hero-dark.png">
|
||||
<img src="assets/screenshots/mac-hero.png"
|
||||
<img data-dark-src="assets/screenshots/mac-hero-dark.png" src="assets/screenshots/mac-hero.png"
|
||||
alt="Scarf on macOS — chat view streaming a response with a tool-call card"
|
||||
width="1600" height="1000"
|
||||
fetchpriority="high" decoding="async">
|
||||
@@ -148,7 +148,7 @@
|
||||
<div class="feature-visual">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="assets/screenshots/mac-chat-dark.png">
|
||||
<img src="assets/screenshots/mac-chat.png"
|
||||
<img data-dark-src="assets/screenshots/mac-chat-dark.png" src="assets/screenshots/mac-chat.png"
|
||||
alt="Mac app — chat view with a tool-call card and a streaming response"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
@@ -169,7 +169,7 @@
|
||||
<div class="feature-visual">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="assets/screenshots/mac-projects-dark.png">
|
||||
<img src="assets/screenshots/mac-projects.png"
|
||||
<img data-dark-src="assets/screenshots/mac-projects-dark.png" src="assets/screenshots/mac-projects.png"
|
||||
alt="Mac app — project dashboard with stat boxes and a chart widget"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
@@ -191,7 +191,7 @@
|
||||
<div class="feature-visual">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="assets/screenshots/mac-sessions-dark.png">
|
||||
<img src="assets/screenshots/mac-sessions.png"
|
||||
<img data-dark-src="assets/screenshots/mac-sessions-dark.png" src="assets/screenshots/mac-sessions.png"
|
||||
alt="Mac app — sessions browser filtered to a remote server"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
@@ -212,7 +212,7 @@
|
||||
<div class="feature-visual">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="assets/screenshots/mac-mcp-dark.png">
|
||||
<img src="assets/screenshots/mac-mcp.png"
|
||||
<img data-dark-src="assets/screenshots/mac-mcp-dark.png" src="assets/screenshots/mac-mcp.png"
|
||||
alt="Mac app — MCP servers configuration view"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
@@ -233,7 +233,7 @@
|
||||
<div class="feature-visual">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="assets/screenshots/mac-cron-dark.png">
|
||||
<img src="assets/screenshots/mac-cron.png"
|
||||
<img data-dark-src="assets/screenshots/mac-cron-dark.png" src="assets/screenshots/mac-cron.png"
|
||||
alt="Mac app — cron manager with paused and active jobs"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
@@ -254,7 +254,7 @@
|
||||
<div class="feature-visual">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="assets/screenshots/mac-dashboard-dark.png">
|
||||
<img src="assets/screenshots/mac-dashboard.png"
|
||||
<img data-dark-src="assets/screenshots/mac-dashboard-dark.png" src="assets/screenshots/mac-dashboard.png"
|
||||
alt="Mac app — dashboard with token usage, recent sessions, and health"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
|
||||
Reference in New Issue
Block a user