site: rebuild landing page at 2026-04-30T12:26:03Z
@@ -0,0 +1,62 @@
|
||||
// Scarf landing page — minimal client behavior.
|
||||
// No dependencies. Runs after defer-parse.
|
||||
|
||||
(function () {
|
||||
const root = document.documentElement;
|
||||
const STORAGE_KEY = 'scarf-theme';
|
||||
|
||||
function applyTheme(theme) {
|
||||
if (theme === 'light' || theme === 'dark') {
|
||||
root.setAttribute('data-theme', theme);
|
||||
} else {
|
||||
root.removeAttribute('data-theme');
|
||||
}
|
||||
}
|
||||
|
||||
// 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).
|
||||
try {
|
||||
const stored = localStorage.getItem(STORAGE_KEY);
|
||||
if (stored === 'light' || stored === 'dark') applyTheme(stored);
|
||||
} catch (_) { /* localStorage unavailable — fall back to media query */ }
|
||||
|
||||
const toggle = document.querySelector('[data-theme-toggle]');
|
||||
if (toggle) {
|
||||
toggle.addEventListener('click', () => {
|
||||
const current = root.getAttribute('data-theme');
|
||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
let next;
|
||||
if (current === 'light') next = 'dark';
|
||||
else if (current === 'dark') next = null;
|
||||
else next = prefersDark ? 'light' : 'dark';
|
||||
|
||||
applyTheme(next);
|
||||
try {
|
||||
if (next) localStorage.setItem(STORAGE_KEY, next);
|
||||
else localStorage.removeItem(STORAGE_KEY);
|
||||
} catch (_) { /* ignore */ }
|
||||
});
|
||||
}
|
||||
|
||||
// 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;
|
||||
let ticking = false;
|
||||
window.addEventListener('scroll', () => {
|
||||
if (ticking) return;
|
||||
window.requestAnimationFrame(() => {
|
||||
const y = window.scrollY;
|
||||
if (y > 80 && y > lastY) header.style.transform = 'translateY(-100%)';
|
||||
else header.style.transform = '';
|
||||
lastY = y;
|
||||
ticking = false;
|
||||
});
|
||||
ticking = true;
|
||||
}, { passive: true });
|
||||
header.style.transition = 'transform 0.25s ease';
|
||||
}
|
||||
})();
|
||||
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 391 KiB |
|
After Width: | Height: | Size: 632 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 429 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 183 KiB |
|
After Width: | Height: | Size: 514 KiB |
|
After Width: | Height: | Size: 472 KiB |
|
After Width: | Height: | Size: 750 KiB |
|
After Width: | Height: | Size: 473 KiB |
|
After Width: | Height: | Size: 539 KiB |
|
After Width: | Height: | Size: 261 KiB |
|
After Width: | Height: | Size: 600 KiB |
|
After Width: | Height: | Size: 328 KiB |
|
After Width: | Height: | Size: 750 KiB |
|
After Width: | Height: | Size: 473 KiB |
|
After Width: | Height: | Size: 412 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 553 KiB |
|
After Width: | Height: | Size: 276 KiB |
|
After Width: | Height: | Size: 501 KiB |
|
After Width: | Height: | Size: 241 KiB |
|
After Width: | Height: | Size: 790 KiB |
|
After Width: | Height: | Size: 488 KiB |
|
After Width: | Height: | Size: 577 KiB |
|
After Width: | Height: | Size: 354 KiB |
|
After Width: | Height: | Size: 591 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
@@ -2,23 +2,683 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Scarf</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
body { font-family: -apple-system, system-ui, sans-serif; max-width: 40rem; margin: 4rem auto; padding: 0 1rem; color: #222; }
|
||||
a { color: #0969da; }
|
||||
</style>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
|
||||
<title>Scarf — Native Mac & iOS app for your Hermes AI agent</title>
|
||||
<meta name="description" content="Scarf is the native macOS and iOS GUI for the Hermes AI agent — sessions, projects, memory, skills, cron, multi-server SSH. Free and open source.">
|
||||
<link rel="canonical" href="https://awizemann.github.io/scarf/">
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:site_name" content="Scarf">
|
||||
<meta property="og:title" content="Scarf — Native Mac & iOS app for your Hermes AI agent">
|
||||
<meta property="og:description" content="Native macOS and iOS GUI for the Hermes AI agent. Sessions, projects, memory, skills, cron, multi-server SSH. Free and open source.">
|
||||
<meta property="og:url" content="https://awizemann.github.io/scarf/">
|
||||
<meta property="og:image" content="https://awizemann.github.io/scarf/assets/og-image.png">
|
||||
<meta property="og:image:width" content="1200">
|
||||
<meta property="og:image:height" content="630">
|
||||
<meta property="og:image:alt" content="Scarf — native Mac & iOS app for the Hermes AI agent">
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="Scarf — Native Mac & iOS app for your Hermes AI agent">
|
||||
<meta name="twitter:description" content="Native macOS and iOS GUI for the Hermes AI agent. Sessions, projects, memory, skills, cron, multi-server SSH.">
|
||||
<meta name="twitter:image" content="https://awizemann.github.io/scarf/assets/twitter-card.png">
|
||||
|
||||
<!-- Theme + favicons -->
|
||||
<meta name="theme-color" content="#C2563D" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#1A1818" media="(prefers-color-scheme: dark)">
|
||||
<link rel="icon" href="favicon.ico" sizes="any">
|
||||
<link rel="icon" href="assets/icon-192.png" type="image/png" sizes="192x192">
|
||||
<link rel="icon" href="assets/icon-512.png" type="image/png" sizes="512x512">
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png">
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
|
||||
<!-- AI crawler hint -->
|
||||
<link rel="alternate" type="text/plain" title="LLM-friendly summary" href="llms.txt">
|
||||
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Scarf</h1>
|
||||
<p>A native macOS companion app for the Hermes AI agent.</p>
|
||||
<p>
|
||||
Downloads and release notes live on the
|
||||
<a href="https://github.com/awizemann/scarf/releases">GitHub releases page</a>.
|
||||
</p>
|
||||
<p>
|
||||
The Sparkle auto-update feed is at
|
||||
<a href="appcast.xml">appcast.xml</a>.
|
||||
</p>
|
||||
<a class="skip-link" href="#main">Skip to content</a>
|
||||
|
||||
<header class="site-header" role="banner">
|
||||
<a class="brand" href="./" aria-label="Scarf home">
|
||||
<img src="assets/scarf-icon-512.png" width="32" height="32" alt="" decoding="async">
|
||||
<span class="brand-name">Scarf</span>
|
||||
</a>
|
||||
<nav class="site-nav" aria-label="Primary">
|
||||
<a href="#features">Features</a>
|
||||
<a href="#ios">iPhone</a>
|
||||
<a href="templates/">Templates</a>
|
||||
<a href="#download">Download</a>
|
||||
<a href="https://github.com/awizemann/scarf" rel="noopener">GitHub</a>
|
||||
</nav>
|
||||
<button type="button" class="theme-toggle" aria-label="Toggle dark mode" data-theme-toggle>
|
||||
<svg class="theme-icon icon-sun" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"></path></svg>
|
||||
<svg class="theme-icon icon-moon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<main id="main">
|
||||
|
||||
<!-- Hero -->
|
||||
<section class="hero" id="hero" aria-labelledby="hero-title">
|
||||
<div class="hero-copy">
|
||||
<h1 id="hero-title">Native Mac & iOS app<br>for your Hermes AI agent.</h1>
|
||||
<p class="hero-lede">
|
||||
Scarf is a native macOS and iOS GUI for the
|
||||
<a href="https://github.com/hermes-ai/hermes-agent" rel="noopener">Hermes AI agent</a>.
|
||||
See every session, project, skill, memory file, and cron job — locally on your Mac
|
||||
and remotely from your iPhone over SSH.
|
||||
</p>
|
||||
<div class="cta-row">
|
||||
<a class="btn btn-primary" href="https://github.com/awizemann/scarf/releases/latest" rel="noopener">
|
||||
<span>Download for Mac</span>
|
||||
<span class="btn-meta">macOS 14.6+ · Apple Silicon & Intel</span>
|
||||
</a>
|
||||
<a class="btn btn-secondary" href="https://testflight.apple.com/join/qCrRpcTz" rel="noopener">
|
||||
<span>Get on iPhone</span>
|
||||
<span class="btn-meta">TestFlight · iOS 18+</span>
|
||||
</a>
|
||||
</div>
|
||||
<p class="hero-prereq">
|
||||
Requires <a href="https://github.com/hermes-ai/hermes-agent" rel="noopener">Hermes</a> installed at <code>~/.hermes/</code>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<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"
|
||||
alt="Scarf on macOS — chat view streaming a response with a tool-call card"
|
||||
width="1600" height="1000"
|
||||
fetchpriority="high" decoding="async">
|
||||
</picture>
|
||||
<picture class="hero-iphone">
|
||||
<img src="assets/screenshots/ios-chat.png"
|
||||
alt="ScarfGo on iPhone — chat with the Hermes agent over SSH"
|
||||
width="430" height="932"
|
||||
decoding="async">
|
||||
</picture>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Trust strip -->
|
||||
<aside class="trust-strip" aria-label="At a glance">
|
||||
<ul>
|
||||
<li>Native Swift 6</li>
|
||||
<li>No Electron</li>
|
||||
<li>MIT licensed</li>
|
||||
<li>Sparkle auto-updates</li>
|
||||
<li>macOS 14.6+ · iOS 18+</li>
|
||||
</ul>
|
||||
</aside>
|
||||
|
||||
<!-- What Scarf does (AEO load-bearing paragraph) -->
|
||||
<section class="what" id="what" aria-labelledby="what-title">
|
||||
<h2 id="what-title">What Scarf does</h2>
|
||||
<p>
|
||||
Scarf is a native macOS and iOS GUI for the Hermes AI agent. It surfaces every part of a
|
||||
running Hermes installation — chat sessions, project workspaces, memory files, installed
|
||||
skills, MCP servers, cron jobs, messaging gateways, logs, and configuration — through a
|
||||
sidebar-driven app on Mac and a tab-based companion on iPhone. Scarf reads from
|
||||
<code>~/.hermes/state.db</code> directly (read-only), streams agent replies in real time
|
||||
over the Agent Client Protocol, and connects to remote Hermes installations through your
|
||||
existing SSH config. There is no telemetry, no login, and no separate cloud service.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Mac feature blocks -->
|
||||
<section class="features" id="features" aria-labelledby="features-title">
|
||||
<h2 id="features-title" class="section-heading">Built for the way Hermes actually works</h2>
|
||||
|
||||
<article class="feature feature-flip">
|
||||
<div class="feature-text">
|
||||
<h3>Live agent sessions</h3>
|
||||
<p>
|
||||
Real-time streaming chat over the Agent Client Protocol. Tool calls render inline with
|
||||
collapsible argument and output panes. Tool-permission requests surface as interactive
|
||||
dialogs you can approve, deny, or stage. Reasoning and thinking blocks display when the
|
||||
model emits them. Resume any prior session from the sidebar, or jump back into a
|
||||
conversation that disconnected — Scarf reconnects to the same session id.
|
||||
</p>
|
||||
</div>
|
||||
<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"
|
||||
alt="Mac app — chat view with a tool-call card and a streaming response"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="feature">
|
||||
<div class="feature-text">
|
||||
<h3>Project workspaces</h3>
|
||||
<p>
|
||||
Per-project chat with the agent's working directory pinned, custom dashboards rendered
|
||||
from a JSON spec the agent itself can author, project-scoped slash commands defined as
|
||||
Markdown files, and a Scarf-managed <code>AGENTS.md</code> block that gives Hermes
|
||||
project context before every session boots. Templates package these into a single
|
||||
<code>.scarftemplate</code> bundle you can share or install with one click.
|
||||
</p>
|
||||
</div>
|
||||
<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"
|
||||
alt="Mac app — project dashboard with stat boxes and a chart widget"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="feature feature-flip">
|
||||
<div class="feature-text">
|
||||
<h3>Multi-server over SSH</h3>
|
||||
<p>
|
||||
One window per Hermes server. Local <code>~/.hermes/</code> is synthesized
|
||||
automatically; remote servers connect through your existing
|
||||
<code>~/.ssh/config</code>, ssh-agent, ProxyJump, and ControlMaster. File I/O routes
|
||||
through scp/sftp; the SQLite database is served from atomic snapshots; chat tunnels as
|
||||
<code>ssh -T host hermes acp</code> with JSON-RPC end-to-end. There is no companion
|
||||
service in the middle.
|
||||
</p>
|
||||
</div>
|
||||
<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"
|
||||
alt="Mac app — sessions browser filtered to a remote server"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="feature">
|
||||
<div class="feature-text">
|
||||
<h3>Memory, skills, MCP</h3>
|
||||
<p>
|
||||
Edit <code>MEMORY.md</code> and <code>USER.md</code> with live file-watcher refresh and
|
||||
external-provider awareness. Browse the Skills Hub across six registries, install,
|
||||
update, and inspect <code>SKILL.md</code> frontmatter. Configure MCP servers from a
|
||||
curated preset list (GitHub, Linear, Notion, Sentry, Stripe) or fully custom; test the
|
||||
connection in-app and watch the discovered tool list populate.
|
||||
</p>
|
||||
</div>
|
||||
<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"
|
||||
alt="Mac app — MCP servers configuration view"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="feature feature-flip">
|
||||
<div class="feature-text">
|
||||
<h3>Cron & messaging gateways</h3>
|
||||
<p>
|
||||
Create, edit, pause, resume, run-now, and delete cron jobs without touching the CLI —
|
||||
with human-readable schedules ("Every weekday at 9:00 AM") and the underlying
|
||||
expression a tap away. Native GUI for thirteen messaging platforms (Telegram, Discord,
|
||||
Slack, WhatsApp, Signal, iMessage, Email, Matrix, Mattermost, Feishu, Home Assistant,
|
||||
Webhook, CLI) with per-platform credential forms and connectivity dots.
|
||||
</p>
|
||||
</div>
|
||||
<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"
|
||||
alt="Mac app — cron manager with paused and active jobs"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="feature">
|
||||
<div class="feature-text">
|
||||
<h3>Insights & health</h3>
|
||||
<p>
|
||||
Token usage and cost broken down by day, model, and platform; reasoning tokens
|
||||
tracked separately. Activity heatmaps and notable sessions across 7, 30, 90 days, or
|
||||
all time. Component-level health checks, on-demand diagnostics, and a one-click debug
|
||||
report uploader for Hermes support — with a confirmation dialog before anything
|
||||
leaves the machine.
|
||||
</p>
|
||||
</div>
|
||||
<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"
|
||||
alt="Mac app — dashboard with token usage, recent sessions, and health"
|
||||
width="1600" height="1000" loading="lazy" decoding="async">
|
||||
</picture>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<!-- iOS / ScarfGo -->
|
||||
<section class="ios" id="ios" aria-labelledby="ios-title">
|
||||
<div class="ios-copy">
|
||||
<p class="eyebrow">ScarfGo for iPhone</p>
|
||||
<h2 id="ios-title">Your Hermes agent, on your phone.</h2>
|
||||
<p>
|
||||
ScarfGo is the native iOS companion to Scarf. It speaks SSH directly to your Hermes
|
||||
host using <a href="https://github.com/orlandos-nl/Citadel" rel="noopener">Citadel</a> — a
|
||||
pure-Swift SSH stack, no companion service, no developer-controlled relay. Generate an
|
||||
Ed25519 keypair on the device, paste the public half into <code>authorized_keys</code>,
|
||||
and you have full project-aware chat, session resume, memory editing, cron browsing,
|
||||
and skill management on iOS 18+.
|
||||
</p>
|
||||
<ul class="ios-points">
|
||||
<li>Pure-Swift SSH — keys live in the iOS Keychain and never leave the device.</li>
|
||||
<li>Multi-server: connect to as many Hermes hosts as you have SSH access to.</li>
|
||||
<li>Project-scoped chat writes the same Scarf-managed <code>AGENTS.md</code> block as Mac.</li>
|
||||
<li>Same session attribution, so "which project does this conversation belong to?" matches across devices.</li>
|
||||
</ul>
|
||||
<a class="btn btn-primary" href="https://testflight.apple.com/join/qCrRpcTz" rel="noopener">
|
||||
<span>Join the public TestFlight</span>
|
||||
<span class="btn-meta">iOS 18+</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="ios-gallery" role="list" aria-label="ScarfGo screenshots">
|
||||
<div class="phone-frame" role="listitem">
|
||||
<img src="assets/screenshots/ios-servers.png" alt="ScarfGo — server picker with two configured Hermes hosts" loading="lazy" decoding="async" width="430" height="932">
|
||||
</div>
|
||||
<div class="phone-frame" role="listitem">
|
||||
<img src="assets/screenshots/ios-chat.png" alt="ScarfGo — chat with the Hermes agent" loading="lazy" decoding="async" width="430" height="932">
|
||||
</div>
|
||||
<div class="phone-frame" role="listitem">
|
||||
<img src="assets/screenshots/ios-project-dashboard.png" alt="ScarfGo — project dashboard" loading="lazy" decoding="async" width="430" height="932">
|
||||
</div>
|
||||
<div class="phone-frame" role="listitem">
|
||||
<img src="assets/screenshots/ios-skills.png" alt="ScarfGo — skills browser" loading="lazy" decoding="async" width="430" height="932">
|
||||
</div>
|
||||
<div class="phone-frame" role="listitem">
|
||||
<img src="assets/screenshots/ios-system.png" alt="ScarfGo — system tab" loading="lazy" decoding="async" width="430" height="932">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why native -->
|
||||
<section class="why" id="why" aria-labelledby="why-title">
|
||||
<h2 id="why-title" class="section-heading">Why a native app</h2>
|
||||
<div class="why-grid">
|
||||
<article class="why-card">
|
||||
<h3>Native, not Electron</h3>
|
||||
<p>
|
||||
One Mach-O binary. SwiftUI on macOS 14.6+ and iOS 18+. Kilobytes of memory and
|
||||
negligible energy use compared to a bundled Chromium. Drag-and-drop, sharing, the
|
||||
menu bar, Spotlight, and accessibility all behave the way a Mac or iPhone user
|
||||
expects.
|
||||
</p>
|
||||
</article>
|
||||
<article class="why-card">
|
||||
<h3>Read-only safe</h3>
|
||||
<p>
|
||||
Scarf opens <code>~/.hermes/state.db</code> in read-only WAL mode. The app cannot
|
||||
corrupt your Hermes data even if it crashes mid-write — because it never writes.
|
||||
Memory files and cron jobs are the only mutable surfaces, both with explicit
|
||||
confirmations.
|
||||
</p>
|
||||
</article>
|
||||
<article class="why-card">
|
||||
<h3>Open and inspectable</h3>
|
||||
<p>
|
||||
<a href="https://github.com/awizemann/scarf" rel="noopener">MIT licensed</a>, pure
|
||||
Swift, zero external runtime dependencies. Build it yourself with
|
||||
<code>xcodebuild</code> in two minutes. Sparkle auto-updates ship signed,
|
||||
notarized, EdDSA-verified zips — never silent over-the-wire mutations.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Templates teaser -->
|
||||
<section class="templates" id="templates" aria-labelledby="templates-title">
|
||||
<h2 id="templates-title">Project templates</h2>
|
||||
<p>
|
||||
A <code>.scarftemplate</code> bundle packages a project's dashboard, skills, cron jobs,
|
||||
memory blocks, slash commands, and configuration schema into one shareable file.
|
||||
Browse the public catalog and install with a single click.
|
||||
</p>
|
||||
<a class="btn btn-secondary" href="templates/">Browse the template catalog →</a>
|
||||
</section>
|
||||
|
||||
<!-- Download -->
|
||||
<section class="download" id="download" aria-labelledby="download-title">
|
||||
<h2 id="download-title" class="section-heading">Download</h2>
|
||||
<div class="download-grid">
|
||||
<article class="download-card">
|
||||
<h3>Scarf for Mac</h3>
|
||||
<p class="download-meta">macOS 14.6 (Sonoma) or later · Apple Silicon & Intel · Universal binary</p>
|
||||
<ul class="download-points">
|
||||
<li>Notarized, code-signed Developer ID build</li>
|
||||
<li>Sparkle auto-updates with EdDSA signature verification</li>
|
||||
<li>Free and open source under the MIT license</li>
|
||||
</ul>
|
||||
<a class="btn btn-primary" href="https://github.com/awizemann/scarf/releases/latest" rel="noopener">
|
||||
<span>Get the latest release</span>
|
||||
<span class="btn-meta">GitHub Releases · .zip</span>
|
||||
</a>
|
||||
</article>
|
||||
|
||||
<article class="download-card">
|
||||
<h3>ScarfGo for iPhone</h3>
|
||||
<p class="download-meta">iOS 18.0 or later · iPhone · public TestFlight</p>
|
||||
<ul class="download-points">
|
||||
<li>Pure-Swift SSH — no companion service required</li>
|
||||
<li>Multi-server support, identical to Mac</li>
|
||||
<li>Free and open source under the MIT license</li>
|
||||
</ul>
|
||||
<a class="btn btn-primary" href="https://testflight.apple.com/join/qCrRpcTz" rel="noopener">
|
||||
<span>Join the TestFlight</span>
|
||||
<span class="btn-meta">Apple TestFlight</span>
|
||||
</a>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<p class="download-prereq">
|
||||
Both apps require <a href="https://github.com/hermes-ai/hermes-agent" rel="noopener">Hermes</a>
|
||||
installed at <code>~/.hermes/</code> on each host you want to manage. Scarf does not include
|
||||
Hermes itself — see the
|
||||
<a href="https://github.com/hermes-ai/hermes-agent#installation" rel="noopener">Hermes installation
|
||||
guide</a> first.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- FAQ -->
|
||||
<section class="faq" id="faq" aria-labelledby="faq-title">
|
||||
<h2 id="faq-title" class="section-heading">Frequently asked questions</h2>
|
||||
<div class="faq-list">
|
||||
|
||||
<details>
|
||||
<summary>What is Scarf?</summary>
|
||||
<div>
|
||||
<p>Scarf is a native macOS and iOS GUI for the <a href="https://github.com/hermes-ai/hermes-agent" rel="noopener">Hermes AI agent</a>. It surfaces Hermes's sessions, projects, memory, skills, MCP servers, cron jobs, messaging gateways, logs, and configuration through a sidebar-driven Mac app and a tab-based iPhone companion called ScarfGo.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Do I need Hermes installed first?</summary>
|
||||
<div>
|
||||
<p>Yes. Scarf is a client for an existing Hermes installation. It expects to find Hermes's data directory at <code>~/.hermes/</code> on each host you connect to (local or remote). Install Hermes first by following the <a href="https://github.com/hermes-ai/hermes-agent#installation" rel="noopener">Hermes installation guide</a>.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Does Scarf work without internet?</summary>
|
||||
<div>
|
||||
<p>Yes for the local Hermes case — Scarf reads files and the SQLite database directly from <code>~/.hermes/</code> with no network involvement. Internet is only required when Hermes itself reaches out to model providers or MCP servers, when you connect to a remote Hermes host over SSH, or when checking for Sparkle updates.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Is Scarf open source?</summary>
|
||||
<div>
|
||||
<p>Yes. Both Scarf and ScarfGo are <a href="https://github.com/awizemann/scarf/blob/main/LICENSE" rel="noopener">MIT licensed</a> and built from the same open repository at <a href="https://github.com/awizemann/scarf" rel="noopener">github.com/awizemann/scarf</a>. There are no closed-source components and no telemetry.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>What macOS and iOS versions are supported?</summary>
|
||||
<div>
|
||||
<p>Scarf for Mac requires macOS 14.6 Sonoma or later, on Apple Silicon or Intel. ScarfGo for iPhone requires iOS 18.0 or later. Both are universal builds; there is no separate Apple Silicon download.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>How does ScarfGo connect to my Mac?</summary>
|
||||
<div>
|
||||
<p>ScarfGo speaks SSH directly to your Hermes host using a pure-Swift SSH stack (Citadel). On first launch it generates an Ed25519 keypair on the device — the private key lives in the iOS Keychain (with <code>kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly</code>) and is excluded from iCloud sync. Paste the public key into the host's <code>~/.ssh/authorized_keys</code>, and ScarfGo can run <code>hermes acp</code> over the SSH session for chat and read the SQLite database for everything else. There is no companion service or developer-controlled relay.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>What data does Scarf collect?</summary>
|
||||
<div>
|
||||
<p>None. Scarf has no telemetry, no analytics, no crash reporter, and no account system. The only outbound network connections are to GitHub Releases (when you check for updates via Sparkle), to remote Hermes hosts you explicitly add, and to Hermes's own model providers and MCP servers — all initiated by Hermes, not Scarf.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Where are my conversations stored?</summary>
|
||||
<div>
|
||||
<p>In Hermes's own data directory — <code>~/.hermes/state.db</code> for session history and <code>~/.hermes/sessions/session_*.json</code> for full transcripts. Scarf reads these files but never writes to <code>state.db</code>. ScarfGo reads them through SSH-initiated SQLite snapshots and never caches them locally on the device.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>How do updates work?</summary>
|
||||
<div>
|
||||
<p>Scarf for Mac uses <a href="https://sparkle-project.org/" rel="noopener">Sparkle</a> for in-app updates — signed and notarized zips with EdDSA signature verification. The appcast lives at <a href="appcast.xml">awizemann.github.io/scarf/appcast.xml</a>. ScarfGo updates through TestFlight in the usual way until it ships on the App Store.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Can I use Scarf with a remote or headless Hermes server?</summary>
|
||||
<div>
|
||||
<p>Yes — that is one of the main use cases. Add the host through <strong>File → Open Server… → Add Server</strong> on Mac, or tap <strong>Add Server</strong> on the ScarfGo Servers tab. Scarf uses the system SSH config (Mac) or a device-generated key (iOS), so anything reachable through your normal terminal SSH workflow works without extra setup. The remote host needs <code>sqlite3</code> and <code>pgrep</code> on its <code>$PATH</code> and the SSH user needs read access to <code>~/.hermes/</code>.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>What's the difference between Scarf and using Hermes from the terminal?</summary>
|
||||
<div>
|
||||
<p>Scarf is strictly additive — it visualizes data Hermes already produces. The terminal CLI (<code>hermes chat</code>, <code>hermes cron</code>, <code>hermes mcp</code>, etc.) remains the source of truth for everything. Scarf gives you live streaming chat with rich tool-call rendering, multi-server windows, project workspaces with custom dashboards, and a one-pane view of skills, MCP servers, cron jobs, and gateways without memorizing CLI subcommands.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Is there a Windows or Linux version?</summary>
|
||||
<div>
|
||||
<p>No. Scarf is built on SwiftUI and AppKit and ships only for Apple platforms. There are no current plans for Windows or Linux ports — the
|
||||
<a href="https://github.com/hermes-ai/hermes-agent" rel="noopener">Hermes CLI</a> itself works on those platforms, and Scarf can connect to a remote Linux Hermes host from a Mac.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="site-footer" role="contentinfo">
|
||||
<div class="footer-inner">
|
||||
<div class="footer-brand">
|
||||
<img src="assets/scarf-icon-512.png" width="40" height="40" alt="" decoding="async">
|
||||
<p>Scarf is made by <a href="https://github.com/awizemann" rel="noopener">Alan Wizemann</a>. MIT licensed.</p>
|
||||
</div>
|
||||
<nav class="footer-nav" aria-label="Footer">
|
||||
<div>
|
||||
<h4>Project</h4>
|
||||
<ul>
|
||||
<li><a href="https://github.com/awizemann/scarf" rel="noopener">GitHub</a></li>
|
||||
<li><a href="https://github.com/awizemann/scarf/wiki" rel="noopener">Wiki</a></li>
|
||||
<li><a href="https://github.com/awizemann/scarf/releases" rel="noopener">Releases</a></li>
|
||||
<li><a href="https://github.com/awizemann/scarf/blob/main/LICENSE" rel="noopener">License (MIT)</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Community</h4>
|
||||
<ul>
|
||||
<li><a href="templates/">Template catalog</a></li>
|
||||
<li><a href="https://github.com/awizemann/scarf/discussions" rel="noopener">Discussions</a></li>
|
||||
<li><a href="https://github.com/awizemann/scarf/issues" rel="noopener">Report a bug</a></li>
|
||||
<li><a href="https://www.buymeacoffee.com/awizemann" rel="noopener">Buy me a coffee</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Technical</h4>
|
||||
<ul>
|
||||
<li><a href="appcast.xml">Sparkle appcast</a></li>
|
||||
<li><a href="llms.txt">llms.txt</a></li>
|
||||
<li><a href="https://github.com/hermes-ai/hermes-agent" rel="noopener">Hermes agent</a></li>
|
||||
<li><a href="https://testflight.apple.com/join/qCrRpcTz" rel="noopener">TestFlight (iOS)</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Structured data -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@graph": [
|
||||
{
|
||||
"@type": "SoftwareApplication",
|
||||
"name": "Scarf",
|
||||
"alternateName": "Scarf for Mac",
|
||||
"applicationCategory": "DeveloperApplication",
|
||||
"operatingSystem": "macOS 14.6 or later",
|
||||
"description": "Native macOS GUI for the Hermes AI agent. Sessions, projects, memory, skills, MCP servers, cron jobs, messaging gateways, multi-server SSH.",
|
||||
"url": "https://awizemann.github.io/scarf/",
|
||||
"downloadUrl": "https://github.com/awizemann/scarf/releases/latest",
|
||||
"softwareVersion": "2.5.2",
|
||||
"license": "https://opensource.org/licenses/MIT",
|
||||
"image": "https://awizemann.github.io/scarf/assets/og-image.png",
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "0",
|
||||
"priceCurrency": "USD"
|
||||
},
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "Alan Wizemann",
|
||||
"url": "https://github.com/awizemann"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "MobileApplication",
|
||||
"name": "ScarfGo",
|
||||
"applicationCategory": "DeveloperApplication",
|
||||
"operatingSystem": "iOS 18.0 or later",
|
||||
"description": "Native iPhone companion to Scarf. Multi-server Hermes management over SSH, project-aware chat, memory editor, cron browser, skills browser.",
|
||||
"url": "https://awizemann.github.io/scarf/#ios",
|
||||
"downloadUrl": "https://testflight.apple.com/join/qCrRpcTz",
|
||||
"license": "https://opensource.org/licenses/MIT",
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "0",
|
||||
"priceCurrency": "USD"
|
||||
},
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "Alan Wizemann",
|
||||
"url": "https://github.com/awizemann"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "FAQPage",
|
||||
"mainEntity": [
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "What is Scarf?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Scarf is a native macOS and iOS GUI for the Hermes AI agent. It surfaces Hermes's sessions, projects, memory, skills, MCP servers, cron jobs, messaging gateways, logs, and configuration through a sidebar-driven Mac app and a tab-based iPhone companion called ScarfGo."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Do I need Hermes installed first?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Yes. Scarf is a client for an existing Hermes installation. It expects to find Hermes's data directory at ~/.hermes/ on each host you connect to. Install Hermes first by following the Hermes installation guide."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Does Scarf work without internet?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Yes for the local Hermes case — Scarf reads files and the SQLite database directly from ~/.hermes/ with no network involvement. Internet is only required when Hermes itself reaches out to model providers or MCP servers, when connecting to a remote Hermes host over SSH, or when checking for Sparkle updates."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Is Scarf open source?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Yes. Both Scarf and ScarfGo are MIT licensed and built from the same open repository at github.com/awizemann/scarf. There are no closed-source components and no telemetry."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "What macOS and iOS versions are supported?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Scarf for Mac requires macOS 14.6 Sonoma or later, on Apple Silicon or Intel. ScarfGo for iPhone requires iOS 18.0 or later. Both are universal builds."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "How does ScarfGo connect to my Mac?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "ScarfGo speaks SSH directly to your Hermes host using Citadel, a pure-Swift SSH stack. On first launch it generates an Ed25519 keypair on the device — the private key lives in the iOS Keychain and never leaves the phone. Paste the public key into the host's authorized_keys and ScarfGo can run hermes acp over the SSH session for chat and read the SQLite database for everything else. There is no companion service or relay."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "What data does Scarf collect?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "None. Scarf has no telemetry, no analytics, no crash reporter, and no account system. The only outbound network connections are to GitHub Releases (Sparkle update checks), remote Hermes hosts you explicitly add, and Hermes's own model providers and MCP servers — all initiated by Hermes, not Scarf."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Where are my conversations stored?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "In Hermes's own data directory — ~/.hermes/state.db for session history and ~/.hermes/sessions/session_*.json for full transcripts. Scarf reads these files but never writes to state.db. ScarfGo reads them through SSH-initiated SQLite snapshots and never caches them locally on the device."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "How do updates work?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Scarf for Mac uses Sparkle for in-app updates — signed and notarized zips with EdDSA signature verification. The appcast lives at awizemann.github.io/scarf/appcast.xml. ScarfGo updates through TestFlight in the usual way until it ships on the App Store."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Can I use Scarf with a remote or headless Hermes server?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Yes. Add the host through File → Open Server… → Add Server on Mac, or Add Server on ScarfGo. Scarf uses the system SSH config (Mac) or a device-generated key (iOS), so anything reachable through normal terminal SSH works without extra setup. The remote host needs sqlite3 and pgrep on its PATH and the SSH user needs read access to ~/.hermes/."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "What's the difference between Scarf and using Hermes from the terminal?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Scarf is strictly additive — it visualizes data Hermes already produces. The terminal CLI remains the source of truth. Scarf gives you live streaming chat with rich tool-call rendering, multi-server windows, project workspaces with custom dashboards, and a one-pane view of skills, MCP servers, cron jobs, and gateways without memorizing CLI subcommands."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Is there a Windows or Linux version?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "No. Scarf is built on SwiftUI and AppKit and ships only for Apple platforms. The Hermes CLI itself works on those platforms, and Scarf can connect to a remote Linux Hermes host from a Mac."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="app.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# Scarf
|
||||
|
||||
> Scarf is a native macOS and iOS GUI for the Hermes AI agent. It surfaces every part of a running Hermes installation — chat sessions, project workspaces, memory files, installed skills, MCP servers, cron jobs, messaging gateways, logs, and configuration — through a sidebar-driven Mac app and a tab-based iPhone companion called ScarfGo.
|
||||
|
||||
Both apps are free, MIT licensed, and built from a single open repository. Scarf reads from `~/.hermes/state.db` directly (read-only) and streams agent replies in real time over the Agent Client Protocol. It connects to remote Hermes installations using the host's existing SSH config — no companion service, no telemetry, no account.
|
||||
|
||||
## Quick facts
|
||||
|
||||
- **Platforms:** macOS 14.6+ Sonoma (Apple Silicon and Intel), iOS 18+
|
||||
- **License:** MIT
|
||||
- **Repository:** https://github.com/awizemann/scarf
|
||||
- **Author:** Alan Wizemann
|
||||
- **Hermes prerequisite:** https://github.com/hermes-ai/hermes-agent installed at `~/.hermes/`
|
||||
- **Mac download:** https://github.com/awizemann/scarf/releases/latest
|
||||
- **iOS download:** https://testflight.apple.com/join/qCrRpcTz (public TestFlight)
|
||||
- **Auto-updates (Mac):** Sparkle, with EdDSA signature verification
|
||||
- **Telemetry:** none
|
||||
|
||||
## Documentation
|
||||
|
||||
- [README](https://github.com/awizemann/scarf/blob/main/README.md): project overview, full feature list, build instructions
|
||||
- [Wiki](https://github.com/awizemann/scarf/wiki): user guide, architecture, design system reference
|
||||
- [Wiki — ScarfGo](https://github.com/awizemann/scarf/wiki/ScarfGo): iOS companion details
|
||||
- [Wiki — ScarfGo Onboarding](https://github.com/awizemann/scarf/wiki/ScarfGo-Onboarding): SSH key setup walkthrough
|
||||
- [Wiki — Platform Differences](https://github.com/awizemann/scarf/wiki/Platform-Differences): what is and isn't shared between Mac and iOS
|
||||
- [Releases](https://github.com/awizemann/scarf/releases): release notes for every version
|
||||
- [License](https://github.com/awizemann/scarf/blob/main/LICENSE): MIT
|
||||
|
||||
## Feature surfaces
|
||||
|
||||
Mac (sidebar sections):
|
||||
|
||||
- **Monitor:** Dashboard, Insights, Sessions Browser, Activity Feed
|
||||
- **Interact:** Live Chat (ACP streaming + Terminal mode), Memory Viewer/Editor, Skills Browser
|
||||
- **Configure:** Platforms, Personalities, Quick Commands, Credential Pools, Plugins, Webhooks, Profiles
|
||||
- **Manage:** Tools, MCP Servers, Gateway Control, Cron Manager, Health, Log Viewer, Settings
|
||||
- **Project Dashboards:** custom JSON-defined dashboards rendered by Scarf, populated by the agent
|
||||
- **System:** Hermes process control, menu bar status
|
||||
|
||||
iOS (ScarfGo, tabs):
|
||||
|
||||
- Servers (multi-host management with pure-Swift SSH)
|
||||
- Dashboard (stats + recent sessions per server)
|
||||
- Chat (full ACP, project-scoped)
|
||||
- Sessions (resume, attribute to projects)
|
||||
- Memory editor (read/write `MEMORY.md`, `USER.md`)
|
||||
- Cron (list view, human-readable schedules)
|
||||
- Skills browser (categories + prereq banners)
|
||||
- Settings (read-only `config.yaml`)
|
||||
|
||||
## Differentiators
|
||||
|
||||
- Native SwiftUI, not Electron — single Mach-O binary, kilobytes of memory, full system integration
|
||||
- Read-only access to `state.db` — Scarf cannot corrupt Hermes data because it never writes
|
||||
- Multi-server: one window per Hermes host on Mac, multi-server on iOS, all over standard SSH
|
||||
- Project-scoped chat with Scarf-managed `AGENTS.md` block injected before session boot
|
||||
- Portable `.scarftemplate` bundles for sharing project setups (dashboards, skills, cron jobs, slash commands)
|
||||
- Live ACP streaming with rich tool-call rendering, permission dialogs, voice control
|
||||
- 13 messaging platforms managed in one native UI (Telegram, Discord, Slack, WhatsApp, Signal, iMessage, Email, Matrix, Mattermost, Feishu, Home Assistant, Webhook, CLI)
|
||||
- Open and inspectable — pure Swift, MIT, no external runtime dependencies
|
||||
|
||||
## Optional
|
||||
|
||||
- [Templates Catalog](https://awizemann.github.io/scarf/templates/): community-contributed `.scarftemplate` bundles, one-click install
|
||||
- [Sparkle Appcast](https://awizemann.github.io/scarf/appcast.xml): the auto-update feed (RSS/XML)
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "Scarf",
|
||||
"short_name": "Scarf",
|
||||
"description": "Native macOS and iOS GUI for the Hermes AI agent.",
|
||||
"start_url": "./",
|
||||
"scope": "./",
|
||||
"display": "browser",
|
||||
"background_color": "#FAF7F2",
|
||||
"theme_color": "#C2563D",
|
||||
"icons": [
|
||||
{
|
||||
"src": "assets/icon-192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icon-512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512",
|
||||
"purpose": "any"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: https://awizemann.github.io/scarf/sitemap.xml
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://awizemann.github.io/scarf/</loc>
|
||||
<lastmod>2026-04-30</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://awizemann.github.io/scarf/templates/</loc>
|
||||
<lastmod>2026-04-30</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://awizemann.github.io/scarf/templates/awizemann/site-status-checker/</loc>
|
||||
<lastmod>2026-04-30</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.6</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://awizemann.github.io/scarf/templates/awizemann/template-author/</loc>
|
||||
<lastmod>2026-04-30</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.6</priority>
|
||||
</url>
|
||||
</urlset>
|
||||
@@ -0,0 +1,859 @@
|
||||
/* Scarf landing page.
|
||||
* Vanilla CSS, no framework. Tokens map to ScarfDesign (rust palette).
|
||||
*
|
||||
* Layers:
|
||||
* 1. Tokens (CSS custom properties)
|
||||
* 2. Reset + base
|
||||
* 3. Layout primitives
|
||||
* 4. Header / footer
|
||||
* 5. Sections (hero, trust strip, what, features, ios, why, templates, download, faq)
|
||||
* 6. Components (buttons, cards, phone frame)
|
||||
* 7. Responsive
|
||||
*/
|
||||
|
||||
/* ---------- 1. Tokens ---------- */
|
||||
|
||||
:root {
|
||||
/* Colors — light mode (mirrors ScarfBrand.xcassets light variants) */
|
||||
--accent: #C2563D;
|
||||
--accent-hover: #A8482F;
|
||||
--accent-active: #8E3B26;
|
||||
--accent-tint: rgba(194, 86, 61, 0.12);
|
||||
|
||||
--fg: #1A1818;
|
||||
--fg-muted: #5C5552;
|
||||
--fg-faint: #8B8480;
|
||||
|
||||
--bg: #FAF7F2;
|
||||
--bg-card: #FFFFFF;
|
||||
--bg-tertiary: #F2EDE5;
|
||||
|
||||
--border: #E5DED2;
|
||||
--border-strong: #C9BFAE;
|
||||
|
||||
--success: #4F8B5F;
|
||||
--danger: #B5453A;
|
||||
--warning: #C9821C;
|
||||
--info: #4A6F8E;
|
||||
|
||||
/* Spacing — ScarfSpace s1..s10 */
|
||||
--s1: 4px;
|
||||
--s2: 8px;
|
||||
--s3: 12px;
|
||||
--s4: 16px;
|
||||
--s5: 20px;
|
||||
--s6: 24px;
|
||||
--s7: 32px;
|
||||
--s8: 40px;
|
||||
--s9: 56px;
|
||||
--s10: 80px;
|
||||
|
||||
/* Radius — ScarfRadius */
|
||||
--r-sm: 6px;
|
||||
--r-md: 10px;
|
||||
--r-lg: 14px;
|
||||
--r-xl: 20px;
|
||||
--r-xxl: 28px;
|
||||
--r-pill: 999px;
|
||||
|
||||
/* Typography */
|
||||
--sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
--display: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Segoe UI", Roboto, sans-serif;
|
||||
--mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "JetBrains Mono", monospace;
|
||||
|
||||
/* Shadows */
|
||||
--shadow-sm: 0 1px 2px rgba(26, 24, 24, 0.04), 0 2px 6px rgba(26, 24, 24, 0.04);
|
||||
--shadow-md: 0 2px 4px rgba(26, 24, 24, 0.06), 0 8px 20px rgba(26, 24, 24, 0.06);
|
||||
--shadow-lg: 0 4px 8px rgba(26, 24, 24, 0.08), 0 16px 40px rgba(26, 24, 24, 0.10);
|
||||
--shadow-xl: 0 8px 16px rgba(26, 24, 24, 0.10), 0 32px 80px rgba(26, 24, 24, 0.14);
|
||||
|
||||
/* Layout */
|
||||
--max-w: 1180px;
|
||||
--max-w-prose: 720px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--accent: #E89580;
|
||||
--accent-hover: #ECA593;
|
||||
--accent-active: #F0B5A6;
|
||||
--accent-tint: rgba(232, 149, 128, 0.16);
|
||||
|
||||
--fg: #EDEBEB;
|
||||
--fg-muted: #ADA8A4;
|
||||
--fg-faint: #807A75;
|
||||
|
||||
--bg: #141211;
|
||||
--bg-card: #1F1C1A;
|
||||
--bg-tertiary: #2A2622;
|
||||
|
||||
--border: #2F2A26;
|
||||
--border-strong: #4A413A;
|
||||
|
||||
--success: #6FA37E;
|
||||
--danger: #D27468;
|
||||
--warning: #DDA653;
|
||||
--info: #7397B5;
|
||||
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3), 0 2px 6px rgba(0, 0, 0, 0.3);
|
||||
--shadow-md: 0 2px 4px rgba(0, 0, 0, 0.4), 0 8px 20px rgba(0, 0, 0, 0.4);
|
||||
--shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.45), 0 16px 40px rgba(0, 0, 0, 0.5);
|
||||
--shadow-xl: 0 8px 16px rgba(0, 0, 0, 0.5), 0 32px 80px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
/* Manual theme override (set by app.js — wins over media query) */
|
||||
:root[data-theme="light"] {
|
||||
color-scheme: light;
|
||||
--accent: #C2563D;
|
||||
--accent-hover: #A8482F;
|
||||
--accent-active: #8E3B26;
|
||||
--accent-tint: rgba(194, 86, 61, 0.12);
|
||||
--fg: #1A1818;
|
||||
--fg-muted: #5C5552;
|
||||
--fg-faint: #8B8480;
|
||||
--bg: #FAF7F2;
|
||||
--bg-card: #FFFFFF;
|
||||
--bg-tertiary: #F2EDE5;
|
||||
--border: #E5DED2;
|
||||
--border-strong: #C9BFAE;
|
||||
--success: #4F8B5F;
|
||||
--danger: #B5453A;
|
||||
--warning: #C9821C;
|
||||
--info: #4A6F8E;
|
||||
--shadow-sm: 0 1px 2px rgba(26, 24, 24, 0.04), 0 2px 6px rgba(26, 24, 24, 0.04);
|
||||
--shadow-md: 0 2px 4px rgba(26, 24, 24, 0.06), 0 8px 20px rgba(26, 24, 24, 0.06);
|
||||
--shadow-lg: 0 4px 8px rgba(26, 24, 24, 0.08), 0 16px 40px rgba(26, 24, 24, 0.10);
|
||||
--shadow-xl: 0 8px 16px rgba(26, 24, 24, 0.10), 0 32px 80px rgba(26, 24, 24, 0.14);
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
color-scheme: dark;
|
||||
--accent: #E89580;
|
||||
--accent-hover: #ECA593;
|
||||
--accent-active: #F0B5A6;
|
||||
--accent-tint: rgba(232, 149, 128, 0.16);
|
||||
--fg: #EDEBEB;
|
||||
--fg-muted: #ADA8A4;
|
||||
--fg-faint: #807A75;
|
||||
--bg: #141211;
|
||||
--bg-card: #1F1C1A;
|
||||
--bg-tertiary: #2A2622;
|
||||
--border: #2F2A26;
|
||||
--border-strong: #4A413A;
|
||||
--success: #6FA37E;
|
||||
--danger: #D27468;
|
||||
--warning: #DDA653;
|
||||
--info: #7397B5;
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3), 0 2px 6px rgba(0, 0, 0, 0.3);
|
||||
--shadow-md: 0 2px 4px rgba(0, 0, 0, 0.4), 0 8px 20px rgba(0, 0, 0, 0.4);
|
||||
--shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.45), 0 16px 40px rgba(0, 0, 0, 0.5);
|
||||
--shadow-xl: 0 8px 16px rgba(0, 0, 0, 0.5), 0 32px 80px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
/* ---------- 2. Reset + base ---------- */
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
* { margin: 0; }
|
||||
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
text-size-adjust: 100%;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html { scroll-behavior: auto; }
|
||||
*, *::before, *::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--sans);
|
||||
font-size: 17px;
|
||||
line-height: 1.55;
|
||||
color: var(--fg);
|
||||
background: var(--bg);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-feature-settings: "kern", "liga", "calt";
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
img, picture { max-width: 100%; height: auto; display: block; }
|
||||
|
||||
a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
a:hover { color: var(--accent-hover); text-decoration: underline; }
|
||||
a:focus-visible {
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: var(--mono);
|
||||
font-size: 0.92em;
|
||||
background: var(--accent-tint);
|
||||
color: var(--accent);
|
||||
padding: 1px 6px;
|
||||
border-radius: var(--r-sm);
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-family: var(--display);
|
||||
line-height: 1.18;
|
||||
letter-spacing: -0.02em;
|
||||
font-weight: 700;
|
||||
}
|
||||
h1 { font-size: clamp(40px, 6vw, 68px); letter-spacing: -0.03em; }
|
||||
h2 { font-size: clamp(28px, 3.5vw, 40px); letter-spacing: -0.025em; }
|
||||
h3 { font-size: clamp(22px, 2.4vw, 28px); }
|
||||
h4 { font-size: 14px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--fg-muted); }
|
||||
p { color: var(--fg); }
|
||||
|
||||
/* Skip link for keyboard users */
|
||||
.skip-link {
|
||||
position: absolute;
|
||||
left: -10000px;
|
||||
top: auto;
|
||||
}
|
||||
.skip-link:focus {
|
||||
position: fixed;
|
||||
left: var(--s4);
|
||||
top: var(--s4);
|
||||
z-index: 1000;
|
||||
padding: var(--s3) var(--s5);
|
||||
background: var(--bg-card);
|
||||
border: 2px solid var(--accent);
|
||||
border-radius: var(--r-md);
|
||||
}
|
||||
|
||||
/* ---------- 3. Layout primitives ---------- */
|
||||
|
||||
main { display: block; }
|
||||
|
||||
section {
|
||||
padding: var(--s10) var(--s5);
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
section { padding-inline: var(--s7); }
|
||||
}
|
||||
|
||||
.section-heading {
|
||||
text-align: center;
|
||||
margin-bottom: var(--s8);
|
||||
max-width: var(--max-w-prose);
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
/* ---------- 4. Header ---------- */
|
||||
|
||||
.site-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 50;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--s5);
|
||||
padding: var(--s3) var(--s5);
|
||||
background: color-mix(in srgb, var(--bg) 88%, transparent);
|
||||
backdrop-filter: saturate(160%) blur(12px);
|
||||
-webkit-backdrop-filter: saturate(160%) blur(12px);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.site-header { padding: var(--s3) var(--s7); }
|
||||
}
|
||||
|
||||
.brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--s2);
|
||||
font-weight: 600;
|
||||
font-size: 17px;
|
||||
color: var(--fg);
|
||||
letter-spacing: -0.01em;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.brand:hover { color: var(--fg); text-decoration: none; }
|
||||
.brand img { width: 32px; height: 32px; border-radius: var(--r-sm); }
|
||||
.brand-name { display: none; }
|
||||
@media (min-width: 540px) { .brand-name { display: inline; } }
|
||||
|
||||
.site-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--s5);
|
||||
margin-left: auto;
|
||||
font-size: 15px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.site-nav a {
|
||||
color: var(--fg-muted);
|
||||
font-weight: 500;
|
||||
}
|
||||
.site-nav a:hover { color: var(--fg); text-decoration: none; }
|
||||
@media (max-width: 600px) {
|
||||
.site-nav { gap: var(--s4); font-size: 14px; }
|
||||
.site-nav a:nth-child(3) { display: none; } /* hide Templates on tiny widths */
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: var(--r-md);
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-card);
|
||||
color: var(--fg-muted);
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
transition: color 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
.theme-toggle:hover { color: var(--fg); border-color: var(--border-strong); }
|
||||
.theme-toggle .theme-icon { display: none; }
|
||||
:root[data-theme="dark"] .theme-toggle .icon-sun,
|
||||
:root:not([data-theme]) .theme-toggle .icon-sun { display: block; }
|
||||
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }
|
||||
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme]) .theme-toggle .icon-sun { display: none; }
|
||||
:root:not([data-theme]) .theme-toggle .icon-moon { display: block; }
|
||||
}
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root:not([data-theme]) .theme-toggle .icon-moon { display: none; }
|
||||
:root:not([data-theme]) .theme-toggle .icon-sun { display: block; }
|
||||
}
|
||||
|
||||
/* ---------- 5. Hero ---------- */
|
||||
|
||||
.hero {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--s8);
|
||||
align-items: center;
|
||||
max-width: var(--max-w);
|
||||
margin: 0 auto;
|
||||
padding-block: var(--s8) var(--s10);
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.hero { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: var(--s10); }
|
||||
}
|
||||
|
||||
.hero-copy { max-width: 620px; }
|
||||
.hero h1 {
|
||||
font-size: clamp(40px, 5.5vw, 68px);
|
||||
margin-bottom: var(--s5);
|
||||
}
|
||||
.hero-lede {
|
||||
font-size: clamp(18px, 1.6vw, 22px);
|
||||
line-height: 1.5;
|
||||
color: var(--fg-muted);
|
||||
max-width: 56ch;
|
||||
margin-bottom: var(--s7);
|
||||
}
|
||||
.hero-lede a { color: var(--fg); text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 3px; text-decoration-thickness: 2px; }
|
||||
.hero-lede a:hover { color: var(--accent); }
|
||||
|
||||
.hero-prereq {
|
||||
margin-top: var(--s5);
|
||||
font-size: 14px;
|
||||
color: var(--fg-faint);
|
||||
}
|
||||
|
||||
.cta-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--s3);
|
||||
}
|
||||
|
||||
/* Hero visual — Mac window with overlapping iPhone */
|
||||
.hero-visual {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
max-width: 720px;
|
||||
aspect-ratio: 16 / 11;
|
||||
}
|
||||
.hero-mac {
|
||||
position: absolute;
|
||||
inset: 0 8% 12% 0;
|
||||
border-radius: var(--r-lg);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-xl);
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.hero-mac img { width: 100%; height: 100%; object-fit: cover; object-position: top left; }
|
||||
.hero-iphone {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: -4%;
|
||||
width: 22%;
|
||||
aspect-ratio: 9 / 19.5;
|
||||
border-radius: 18px;
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-xl), 0 0 0 6px var(--bg-card);
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border-strong);
|
||||
transform: rotate(2deg);
|
||||
}
|
||||
.hero-iphone img { width: 100%; height: 100%; object-fit: cover; }
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
.hero-visual { max-width: 600px; aspect-ratio: 16 / 11; }
|
||||
.hero-iphone { width: 24%; bottom: -2%; }
|
||||
}
|
||||
@media (max-width: 540px) {
|
||||
.hero-visual { aspect-ratio: 4 / 3.5; }
|
||||
.hero-iphone { width: 28%; right: 2%; }
|
||||
}
|
||||
|
||||
/* ---------- Trust strip ---------- */
|
||||
|
||||
.trust-strip {
|
||||
border-top: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--bg-tertiary);
|
||||
padding-block: var(--s5);
|
||||
}
|
||||
.trust-strip ul {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: var(--s3) var(--s7);
|
||||
list-style: none;
|
||||
padding: 0 var(--s5);
|
||||
max-width: var(--max-w);
|
||||
margin: 0 auto;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--fg-muted);
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
/* ---------- 'What' section ---------- */
|
||||
|
||||
.what {
|
||||
max-width: var(--max-w-prose);
|
||||
margin: 0 auto;
|
||||
text-align: left;
|
||||
}
|
||||
.what h2 {
|
||||
margin-bottom: var(--s5);
|
||||
}
|
||||
.what p {
|
||||
font-size: clamp(17px, 1.5vw, 20px);
|
||||
line-height: 1.6;
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
/* ---------- Features ---------- */
|
||||
|
||||
.features {
|
||||
max-width: var(--max-w);
|
||||
margin: 0 auto;
|
||||
padding-block: var(--s10);
|
||||
}
|
||||
.features .section-heading { margin-bottom: var(--s10); }
|
||||
|
||||
.feature {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--s7);
|
||||
align-items: center;
|
||||
margin-bottom: var(--s10);
|
||||
}
|
||||
.feature:last-child { margin-bottom: 0; }
|
||||
@media (min-width: 900px) {
|
||||
.feature { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s9); }
|
||||
.feature.feature-flip { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
|
||||
.feature.feature-flip .feature-text { order: 2; }
|
||||
.feature.feature-flip .feature-visual { order: 1; }
|
||||
}
|
||||
|
||||
.feature-text h3 { margin-bottom: var(--s4); }
|
||||
.feature-text p { color: var(--fg-muted); font-size: 17px; line-height: 1.6; max-width: 52ch; }
|
||||
.feature-text p code { font-size: 0.88em; }
|
||||
|
||||
.feature-visual {
|
||||
position: relative;
|
||||
border-radius: var(--r-lg);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-lg);
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
aspect-ratio: 16 / 10;
|
||||
}
|
||||
.feature-visual img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: top left;
|
||||
}
|
||||
|
||||
/* ---------- iOS / ScarfGo ---------- */
|
||||
|
||||
.ios {
|
||||
background: var(--bg-tertiary);
|
||||
border-top: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-block: var(--s10);
|
||||
}
|
||||
.ios > * { max-width: var(--max-w); margin-inline: auto; }
|
||||
.ios {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--s8);
|
||||
align-items: center;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.ios {
|
||||
grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
|
||||
gap: var(--s9);
|
||||
}
|
||||
}
|
||||
|
||||
.ios-copy { padding-inline: var(--s5); }
|
||||
.eyebrow {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--accent);
|
||||
background: var(--accent-tint);
|
||||
padding: 4px 10px;
|
||||
border-radius: var(--r-pill);
|
||||
margin-bottom: var(--s4);
|
||||
}
|
||||
.ios-copy h2 { margin-bottom: var(--s5); }
|
||||
.ios-copy > p { color: var(--fg-muted); font-size: 17px; line-height: 1.6; margin-bottom: var(--s5); }
|
||||
.ios-points {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0 0 var(--s7) 0;
|
||||
display: grid;
|
||||
gap: var(--s3);
|
||||
}
|
||||
.ios-points li {
|
||||
position: relative;
|
||||
padding-left: var(--s6);
|
||||
color: var(--fg);
|
||||
font-size: 16px;
|
||||
}
|
||||
.ios-points li::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 10px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.ios-gallery {
|
||||
display: flex;
|
||||
gap: var(--s3);
|
||||
overflow-x: auto;
|
||||
scroll-snap-type: x mandatory;
|
||||
padding: var(--s5) var(--s5) var(--s7);
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.ios-gallery { padding-block: var(--s5); padding-inline: 0 var(--s5); }
|
||||
}
|
||||
|
||||
.phone-frame {
|
||||
flex: 0 0 200px;
|
||||
scroll-snap-align: start;
|
||||
position: relative;
|
||||
background: #1A1818;
|
||||
border-radius: 28px;
|
||||
padding: 8px;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
.phone-frame::before {
|
||||
/* Dynamic Island stand-in */
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 64px;
|
||||
height: 18px;
|
||||
border-radius: 12px;
|
||||
background: #0a0a0a;
|
||||
z-index: 1;
|
||||
}
|
||||
.phone-frame img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 22px;
|
||||
display: block;
|
||||
background: var(--bg-card);
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
.phone-frame { flex-basis: 220px; }
|
||||
}
|
||||
|
||||
/* ---------- Why native ---------- */
|
||||
|
||||
.why {
|
||||
max-width: var(--max-w);
|
||||
margin: 0 auto;
|
||||
padding-block: var(--s10);
|
||||
}
|
||||
.why-grid {
|
||||
display: grid;
|
||||
gap: var(--s5);
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
@media (min-width: 720px) { .why-grid { grid-template-columns: repeat(3, 1fr); } }
|
||||
|
||||
.why-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--r-lg);
|
||||
padding: var(--s7);
|
||||
box-shadow: var(--shadow-sm);
|
||||
transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
.why-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-md);
|
||||
border-color: var(--border-strong);
|
||||
}
|
||||
.why-card h3 {
|
||||
font-size: 22px;
|
||||
margin-bottom: var(--s4);
|
||||
color: var(--accent);
|
||||
}
|
||||
.why-card p { color: var(--fg-muted); font-size: 16px; line-height: 1.55; }
|
||||
|
||||
/* ---------- Templates teaser ---------- */
|
||||
|
||||
.templates {
|
||||
max-width: var(--max-w-prose);
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
padding-block: var(--s9);
|
||||
}
|
||||
.templates h2 { margin-bottom: var(--s4); }
|
||||
.templates p { color: var(--fg-muted); margin-bottom: var(--s6); font-size: 17px; }
|
||||
|
||||
/* ---------- Download ---------- */
|
||||
|
||||
.download {
|
||||
max-width: var(--max-w);
|
||||
margin: 0 auto;
|
||||
padding-block: var(--s10);
|
||||
}
|
||||
.download-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--s5);
|
||||
}
|
||||
@media (min-width: 720px) { .download-grid { grid-template-columns: 1fr 1fr; } }
|
||||
|
||||
.download-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--r-xl);
|
||||
padding: var(--s8);
|
||||
box-shadow: var(--shadow-sm);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.download-card h3 { font-size: 26px; margin-bottom: var(--s2); }
|
||||
.download-meta {
|
||||
font-size: 14px;
|
||||
color: var(--fg-muted);
|
||||
margin-bottom: var(--s5);
|
||||
}
|
||||
.download-points {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0 0 var(--s7);
|
||||
display: grid;
|
||||
gap: var(--s2);
|
||||
font-size: 15px;
|
||||
color: var(--fg-muted);
|
||||
}
|
||||
.download-points li::before {
|
||||
content: "✓ ";
|
||||
color: var(--success);
|
||||
font-weight: 700;
|
||||
}
|
||||
.download-card .btn { margin-top: auto; }
|
||||
|
||||
.download-prereq {
|
||||
margin-top: var(--s7);
|
||||
text-align: center;
|
||||
color: var(--fg-muted);
|
||||
font-size: 15px;
|
||||
max-width: var(--max-w-prose);
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
/* ---------- FAQ ---------- */
|
||||
|
||||
.faq {
|
||||
max-width: 820px;
|
||||
margin: 0 auto;
|
||||
padding-block: var(--s10);
|
||||
}
|
||||
.faq-list {
|
||||
display: grid;
|
||||
gap: var(--s2);
|
||||
}
|
||||
.faq details {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--r-md);
|
||||
padding: var(--s5) var(--s6);
|
||||
transition: border-color 0.15s ease;
|
||||
}
|
||||
.faq details[open] {
|
||||
border-color: var(--border-strong);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
.faq summary {
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
font-size: 17px;
|
||||
color: var(--fg);
|
||||
list-style: none;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: var(--s4);
|
||||
padding: var(--s2) 0;
|
||||
}
|
||||
.faq summary::-webkit-details-marker { display: none; }
|
||||
.faq summary::after {
|
||||
content: "+";
|
||||
font-size: 24px;
|
||||
font-weight: 300;
|
||||
color: var(--fg-faint);
|
||||
transition: transform 0.2s ease, color 0.15s ease;
|
||||
flex-shrink: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
.faq details[open] summary::after { transform: rotate(45deg); color: var(--accent); }
|
||||
.faq summary:hover { color: var(--accent); }
|
||||
.faq details > div {
|
||||
padding-top: var(--s4);
|
||||
color: var(--fg-muted);
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.faq details > div p { color: inherit; }
|
||||
|
||||
/* ---------- 6. Components ---------- */
|
||||
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding: var(--s4) var(--s6);
|
||||
border-radius: var(--r-md);
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
text-decoration: none;
|
||||
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
|
||||
line-height: 1.2;
|
||||
border: 1px solid transparent;
|
||||
min-height: 48px;
|
||||
}
|
||||
.btn:hover { text-decoration: none; transform: translateY(-1px); }
|
||||
.btn:active { transform: translateY(0); }
|
||||
.btn-meta {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
margin-top: 2px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.btn-primary:hover { background: var(--accent-hover); color: #FFFFFF; }
|
||||
.btn-primary:active { background: var(--accent-active); }
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--bg-card);
|
||||
color: var(--fg);
|
||||
border-color: var(--border-strong);
|
||||
}
|
||||
.btn-secondary:hover { color: var(--fg); border-color: var(--accent); background: var(--bg-card); }
|
||||
|
||||
/* ---------- Footer ---------- */
|
||||
|
||||
.site-footer {
|
||||
background: var(--bg-tertiary);
|
||||
border-top: 1px solid var(--border);
|
||||
padding: var(--s9) var(--s5) var(--s8);
|
||||
margin-top: var(--s8);
|
||||
}
|
||||
.footer-inner {
|
||||
max-width: var(--max-w);
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--s8);
|
||||
}
|
||||
@media (min-width: 720px) {
|
||||
.footer-inner { grid-template-columns: 1fr 2fr; gap: var(--s9); }
|
||||
}
|
||||
.footer-brand { display: flex; align-items: flex-start; gap: var(--s4); }
|
||||
.footer-brand img { width: 40px; height: 40px; border-radius: var(--r-sm); flex-shrink: 0; }
|
||||
.footer-brand p { font-size: 15px; color: var(--fg-muted); }
|
||||
.footer-brand a { color: var(--fg); }
|
||||
|
||||
.footer-nav {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: var(--s7);
|
||||
}
|
||||
.footer-nav h4 { margin-bottom: var(--s3); color: var(--fg); font-size: 13px; }
|
||||
.footer-nav ul { list-style: none; padding: 0; display: grid; gap: var(--s2); }
|
||||
.footer-nav a { color: var(--fg-muted); font-size: 14px; }
|
||||
.footer-nav a:hover { color: var(--accent); }
|
||||
|
||||
/* ---------- 7. Responsive tweaks ---------- */
|
||||
|
||||
@media (max-width: 540px) {
|
||||
section { padding-block: var(--s9); }
|
||||
.hero { padding-block: var(--s7) var(--s9); }
|
||||
.features { padding-block: var(--s9); }
|
||||
.feature { gap: var(--s5); margin-bottom: var(--s9); }
|
||||
.ios { padding-block: var(--s9); }
|
||||
.why { padding-block: var(--s9); }
|
||||
.download { padding-block: var(--s9); }
|
||||
.faq { padding-block: var(--s9); }
|
||||
.btn { width: 100%; }
|
||||
.cta-row { flex-direction: column; align-items: stretch; }
|
||||
.download-card { padding: var(--s6); }
|
||||
.why-card { padding: var(--s6); }
|
||||
}
|
||||