Ka1zen / index.html
LEFBE's picture
Make New-in label dynamic via GitHub API
d6de8f5 verified
Raw
History Blame Contribute Delete
25.8 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ka1zen β€” Local AI for Apple Silicon</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #08080d;
--surface: rgba(255,255,255,.04);
--surface-hover: rgba(255,255,255,.07);
--border: rgba(255,255,255,.08);
--border-hover: rgba(249,115,22,.4);
--accent: #f97316;
--accent2: #fb923c;
--text: #f1f1f5;
--muted: #6b6b85;
--muted2: #9494b0;
--green: #34d399;
}
html { scroll-behavior: smooth; }
body {
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter", "Segoe UI", sans-serif;
line-height: 1.65;
-webkit-font-smoothing: antialiased;
overflow-x: hidden;
}
/* ─────────────────── Noise + glow background ─────────────────── */
body::before {
content: '';
position: fixed; inset: 0; z-index: -2;
background:
radial-gradient(ellipse 120% 60% at 50% -10%, rgba(249,115,22,.12) 0%, transparent 60%),
radial-gradient(ellipse 60% 40% at 80% 60%, rgba(139,92,246,.06) 0%, transparent 50%);
pointer-events: none;
}
/* ─────────────────── Utility ─────────────────── */
.container { max-width: 960px; margin: 0 auto; padding: 0 24px; }
a { color: inherit; text-decoration: none; }
/* ─────────────────── Nav ─────────────────── */
nav {
position: sticky; top: 0; z-index: 100;
backdrop-filter: blur(20px) saturate(180%);
-webkit-backdrop-filter: blur(20px) saturate(180%);
background: rgba(8,8,13,.7);
border-bottom: 1px solid var(--border);
}
.nav-inner {
max-width: 960px; margin: 0 auto; padding: 0 24px;
height: 56px;
display: flex; align-items: center; justify-content: space-between;
}
.nav-logo {
display: flex; align-items: center; gap: 10px;
font-weight: 700; font-size: 1rem;
}
.nav-logo img { width: 28px; height: 28px; border-radius: 7px; }
.nav-links { display: flex; align-items: center; gap: 4px; }
.nav-links a {
padding: 6px 12px; border-radius: 8px;
font-size: .85rem; color: var(--muted2);
transition: background .15s, color .15s;
}
.nav-links a:hover { background: var(--surface-hover); color: var(--text); }
.nav-dl {
background: var(--accent);
color: #fff !important;
font-weight: 600;
padding: 6px 14px !important;
border-radius: 8px !important;
box-shadow: 0 2px 12px rgba(249,115,22,.35);
transition: box-shadow .15s, transform .15s !important;
}
.nav-dl:hover { box-shadow: 0 4px 20px rgba(249,115,22,.55) !important; transform: translateY(-1px); }
/* ─────────────────── Hero ─────────────────── */
.hero {
text-align: center;
padding: 100px 24px 80px;
}
.hero-icon-wrap {
display: inline-block;
padding: 3px;
border-radius: 26px;
background: linear-gradient(135deg, var(--accent), #a855f7);
box-shadow: 0 0 60px rgba(249,115,22,.25), 0 0 120px rgba(249,115,22,.1);
margin-bottom: 32px;
}
.hero-icon-wrap img {
display: block;
width: 100px; height: 100px;
border-radius: 23px;
}
.hero-eyebrow {
display: inline-flex; align-items: center; gap: 8px;
padding: 5px 14px;
border-radius: 999px;
border: 1px solid rgba(249,115,22,.3);
background: rgba(249,115,22,.08);
font-size: .78rem; font-weight: 600;
color: var(--accent2);
letter-spacing: .06em; text-transform: uppercase;
margin-bottom: 24px;
}
.eyebrow-dot {
width: 6px; height: 6px; border-radius: 50%;
background: var(--accent);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: .4; }
}
.hero h1 {
font-size: clamp(2.8rem, 8vw, 5rem);
font-weight: 800;
letter-spacing: -0.04em;
line-height: 1.05;
background: linear-gradient(135deg, #fff 30%, rgba(255,255,255,.5));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 20px;
}
.hero-sub {
font-size: clamp(1rem, 2.5vw, 1.2rem);
color: var(--muted2);
max-width: 500px;
margin: 0 auto 36px;
line-height: 1.7;
}
.hero-pills {
display: flex; flex-wrap: wrap; justify-content: center; gap: 8px;
margin-bottom: 40px;
}
.pill {
display: flex; align-items: center; gap: 6px;
padding: 5px 13px;
border-radius: 999px;
background: var(--surface);
border: 1px solid var(--border);
font-size: .78rem; color: var(--muted2);
backdrop-filter: blur(8px);
}
.pill.hot { border-color: rgba(249,115,22,.35); color: var(--accent2); background: rgba(249,115,22,.07); }
.hero-cta { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }
.btn {
display: inline-flex; align-items: center; gap: 9px;
padding: 13px 26px; border-radius: 12px;
font-size: .95rem; font-weight: 600;
transition: transform .15s, box-shadow .15s, background .15s;
cursor: pointer;
}
.btn:hover { transform: translateY(-2px); }
.btn-primary {
background: linear-gradient(135deg, #f97316, #ea580c);
color: #fff;
box-shadow: 0 4px 24px rgba(249,115,22,.4);
}
.btn-primary:hover { box-shadow: 0 8px 32px rgba(249,115,22,.55); }
.btn-glass {
background: var(--surface);
border: 1px solid var(--border);
color: var(--text);
backdrop-filter: blur(8px);
}
.btn-glass:hover { background: var(--surface-hover); border-color: rgba(255,255,255,.15); }
/* ─────────────────── Stats bar ─────────────────── */
.stats {
margin: 64px auto;
max-width: 700px;
padding: 0 24px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1px;
background: var(--border);
border: 1px solid var(--border);
border-radius: 16px;
overflow: hidden;
}
.stat {
background: var(--bg);
padding: 28px 20px;
text-align: center;
}
.stat .val {
font-size: 2rem; font-weight: 800; letter-spacing: -0.03em;
background: linear-gradient(135deg, #fff, var(--accent2));
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.stat .lbl { font-size: .8rem; color: var(--muted); margin-top: 4px; }
/* ─────────────────── Screenshots ─────────────────── */
.section { padding: 80px 0; }
.section-label {
text-align: center;
font-size: .75rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
color: var(--accent); margin-bottom: 12px;
}
.section-title {
text-align: center;
font-size: clamp(1.6rem, 4vw, 2.2rem); font-weight: 800;
letter-spacing: -0.03em; margin-bottom: 48px;
}
.screenshot-main img {
width: 100%; border-radius: 16px;
border: 1px solid var(--border);
box-shadow: 0 24px 80px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.04);
margin-bottom: 16px;
}
.screenshot-grid-4 {
display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px;
}
.screenshot-grid-4 img {
width: 100%; border-radius: 10px;
border: 1px solid var(--border);
box-shadow: 0 8px 32px rgba(0,0,0,.4);
transition: transform .2s, box-shadow .2s;
}
.screenshot-grid-4 img:hover {
transform: scale(1.02);
box-shadow: 0 16px 48px rgba(0,0,0,.55);
}
/* ─────────────────── Features ─────────────────── */
.feature-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 14px;
}
.feature-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 16px;
padding: 24px;
backdrop-filter: blur(8px);
transition: border-color .2s, background .2s, transform .2s;
position: relative; overflow: hidden;
}
.feature-card::before {
content: '';
position: absolute; inset: 0;
background: radial-gradient(ellipse 80% 60% at 50% 0%, rgba(249,115,22,.05), transparent 70%);
opacity: 0; transition: opacity .2s;
}
.feature-card:hover::before { opacity: 1; }
.feature-card:hover { border-color: var(--border-hover); transform: translateY(-2px); }
.feature-icon {
width: 40px; height: 40px;
border-radius: 10px;
background: rgba(249,115,22,.1);
border: 1px solid rgba(249,115,22,.2);
display: flex; align-items: center; justify-content: center;
font-size: 1.2rem; margin-bottom: 14px;
}
.feature-card h3 { font-size: .95rem; font-weight: 700; margin-bottom: 6px; }
.feature-card p { font-size: .845rem; color: var(--muted2); line-height: 1.6; }
/* ─────────────────── Grounded gen highlight ─────────────────── */
.highlight-box {
background: linear-gradient(135deg, rgba(249,115,22,.07), rgba(139,92,246,.05));
border: 1px solid rgba(249,115,22,.2);
border-radius: 20px;
padding: 48px;
position: relative; overflow: hidden;
}
.highlight-box::after {
content: '';
position: absolute; top: -60px; right: -60px;
width: 200px; height: 200px;
border-radius: 50%;
background: radial-gradient(circle, rgba(249,115,22,.12), transparent 70%);
pointer-events: none;
}
.highlight-box h2 {
font-size: clamp(1.4rem, 3vw, 1.9rem); font-weight: 800;
letter-spacing: -0.03em; margin-bottom: 8px;
}
.highlight-box .sub { color: var(--muted2); margin-bottom: 36px; font-size: .95rem; }
.steps { display: flex; flex-direction: column; gap: 4px; margin-bottom: 36px; }
.step {
display: flex; align-items: flex-start; gap: 18px;
padding: 16px;
border-radius: 12px;
transition: background .15s;
}
.step:hover { background: rgba(255,255,255,.03); }
.step-num {
flex-shrink: 0;
width: 32px; height: 32px; border-radius: 50%;
background: rgba(249,115,22,.15);
border: 1.5px solid rgba(249,115,22,.4);
display: flex; align-items: center; justify-content: center;
font-size: .8rem; font-weight: 700; color: var(--accent);
}
.step h3 { font-size: .9rem; font-weight: 700; margin-bottom: 3px; }
.step p { font-size: .845rem; color: var(--muted2); }
.code-block {
background: rgba(0,0,0,.4);
border: 1px solid var(--border);
border-left: 3px solid var(--accent);
border-radius: 12px;
padding: 20px 24px;
}
.code-block .cb-label {
font-size: .72rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
color: var(--accent); margin-bottom: 12px;
}
.code-block p {
font-family: "SF Mono", "Menlo", "Fira Code", monospace;
font-size: .82rem; color: var(--muted2); line-height: 1.9;
}
.code-block p + p { margin-top: 8px; border-top: 1px solid var(--border); padding-top: 8px; }
/* ─────────────────── Requirements ─────────────────── */
.req-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
gap: 10px;
}
.req-item {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 16px 18px;
display: flex; align-items: center; gap: 12px;
}
.req-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--green); flex-shrink: 0; }
.req-item .req-text { font-size: .875rem; }
.req-item .req-text strong { display: block; color: var(--text); }
.req-item .req-text span { color: var(--muted2); font-size: .8rem; }
/* ─────────────────── Privacy strip ─────────────────── */
.privacy-strip {
background: rgba(52,211,153,.05);
border: 1px solid rgba(52,211,153,.15);
border-radius: 16px;
padding: 24px 32px;
display: flex; align-items: center; justify-content: center;
gap: 16px; flex-wrap: wrap;
text-align: center;
margin-top: 64px;
}
.privacy-strip .lock { font-size: 1.4rem; }
.privacy-strip p { font-size: .9rem; color: var(--muted2); max-width: 480px; }
.privacy-strip strong { color: var(--green); }
/* ─────────────────── Footer ─────────────────── */
footer {
margin-top: 80px;
border-top: 1px solid var(--border);
padding: 48px 24px 36px;
text-align: center;
}
.footer-links {
display: flex; flex-wrap: wrap; justify-content: center; gap: 6px;
margin-bottom: 20px;
}
.footer-links a {
padding: 6px 14px; border-radius: 8px;
font-size: .85rem; color: var(--muted2);
transition: background .15s, color .15s;
}
.footer-links a:hover { background: var(--surface-hover); color: var(--text); }
footer p { font-size: .82rem; color: var(--muted); }
footer a { color: var(--accent); }
/* ─────────────────── Responsive ─────────────────── */
@media (max-width: 640px) {
.stats { grid-template-columns: 1fr; gap: 1px; }
.screenshot-grid-4 { grid-template-columns: 1fr; }
.highlight-box { padding: 28px 20px; }
.nav-links a:not(.nav-dl) { display: none; }
}
</style>
</head>
<body>
<!-- ── Nav ── -->
<nav>
<div class="nav-inner">
<div class="nav-logo">
<img src="icon.png" alt="Ka1zen">
Ka1zen
</div>
<div class="nav-links">
<a href="https://github.com/Flor1an-B/Ka1zen/blob/main/USER_GUIDE.md" target="_blank" rel="noopener">Docs</a>
<a href="https://github.com/Flor1an-B/Ka1zen/blob/main/CHANGELOG.md" target="_blank" rel="noopener">Changelog</a>
<a href="https://github.com/Flor1an-B/Ka1zen" target="_blank" rel="noopener">GitHub</a>
<a class="nav-dl" href="https://github.com/Flor1an-B/Ka1zen/releases/latest" target="_blank" rel="noopener">⬇ Download</a>
</div>
</div>
</nav>
<!-- ── Hero ── -->
<section class="hero">
<div class="hero-icon-wrap">
<img src="icon.png" alt="Ka1zen icon">
</div>
<div style="margin-bottom:16px;">
<span class="hero-eyebrow">
<span class="eyebrow-dot"></span>
<span id="hero-version">Latest release</span>
</span>
</div>
<h1>Local AI for<br>Apple Silicon</h1>
<p class="hero-sub">Chat with open LLMs entirely offline on your Mac. Private by design, powered by Apple MLX. No account, no cloud, no telemetry.</p>
<div class="hero-pills">
<span class="pill">macOS 15+</span>
<span class="pill">Apple Silicon M1+</span>
<span class="pill">100% Offline</span>
<span class="pill hot" id="version-pill">✨ Free forever</span>
</div>
<div class="hero-cta">
<a class="btn btn-primary" href="https://github.com/Flor1an-B/Ka1zen/releases/latest" target="_blank" rel="noopener">
⬇ Download Ka1zen
</a>
<a class="btn btn-glass" href="https://github.com/Flor1an-B/Ka1zen" target="_blank" rel="noopener">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.3 3.44 9.8 8.2 11.37.6.1.82-.26.82-.57v-2c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.09-.75.08-.73.08-.73 1.2.08 1.84 1.24 1.84 1.24 1.07 1.83 2.8 1.3 3.49 1 .1-.78.42-1.3.76-1.6-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.13-.3-.54-1.52.12-3.18 0 0 1.01-.32 3.3 1.23a11.5 11.5 0 0 1 3-.4c1.02 0 2.04.14 3 .4 2.28-1.55 3.29-1.23 3.29-1.23.66 1.66.25 2.88.12 3.18.77.84 1.24 1.91 1.24 3.22 0 4.61-2.81 5.63-5.48 5.92.43.37.81 1.1.81 2.22v3.29c0 .32.22.68.83.57C20.56 21.8 24 17.3 24 12c0-6.63-5.37-12-12-12z"/></svg>
GitHub
</a>
<a class="btn btn-glass" href="https://github.com/Flor1an-B/Ka1zen/blob/main/USER_GUIDE.md" target="_blank" rel="noopener">
πŸ“– User Guide
</a>
</div>
</section>
<!-- ── Stats ── -->
<div class="container">
<div class="stats">
<div class="stat"><div class="val">0 €</div><div class="lbl">No subscription</div></div>
<div class="stat"><div class="val">0 kb</div><div class="lbl">Data sent to cloud</div></div>
<div class="stat"><div class="val">200+</div><div class="lbl">Models supported</div></div>
</div>
</div>
<!-- ── Screenshots ── -->
<section class="section">
<div class="container">
<div class="section-label">Interface</div>
<div class="section-title">Everything in one app</div>
<div class="screenshot-main">
<img src="screenshots/01-hero-chat.png" alt="Ka1zen chat interface">
</div>
<div class="screenshot-grid-4">
<img src="screenshots/03-onboarding-prereqs.png" alt="Onboarding prerequisites">
<img src="screenshots/04-model-manager.png" alt="Model Manager">
<img src="screenshots/06-general-settings.png" alt="General settings">
<img src="screenshots/05-model-settings.png" alt="Model settings">
</div>
</div>
</section>
<!-- ── Features ── -->
<section class="section" style="padding-top:0;">
<div class="container">
<div class="section-label">Features</div>
<div class="section-title">Nothing leaves your Mac</div>
<div class="feature-grid">
<div class="feature-card">
<div class="feature-icon">πŸ’¬</div>
<h3>Local Chat</h3>
<p>Qwen, Gemma, DeepSeek, Mistral, Llama and anything on mlx-community. Real-time streaming.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🎨</div>
<h3>Image Generation</h3>
<p>FLUX.2-klein-9B via mflux, locally. Say "draw a…" and Ka1zen generates. No API key needed.</p>
</div>
<div class="feature-card">
<div class="feature-icon">πŸ”</div>
<h3>Grounded Images</h3>
<p>Ask Ka1zen to search the web AND generate an image. It fetches real facts, then draws from them.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🧠</div>
<h3>Thinking Mode</h3>
<p>Watch the model reason step by step. Works with Qwen3, DeepSeek-R1, Gemma 4, Nemotron.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🌐</div>
<h3>Web Search</h3>
<p>DuckDuckGo + direct page fetch. URL auto-detection. Clickable [1]-style source citations.</p>
</div>
<div class="feature-card">
<div class="feature-icon">πŸ–Ό</div>
<h3>Vision</h3>
<p>Drop images into the chat. Supports Gemma 4, Pixtral, Mistral Small VLM, Qwen2-VL, LLaVA.</p>
</div>
<div class="feature-card">
<div class="feature-icon">πŸ“š</div>
<h3>RAG</h3>
<p>Index PDFs, text, and code locally with Apple NLEmbedding. Fully local SQLite storage.</p>
</div>
<div class="feature-card">
<div class="feature-icon">πŸ”Œ</div>
<h3>API Relay</h3>
<p>OpenAI-compatible proxy for Continue, Cursor, Zed, LM Studio β€” use local models anywhere.</p>
</div>
<div class="feature-card">
<div class="feature-icon">πŸ”Ž</div>
<h3>Token Inspector</h3>
<p>Per-token logprob visualisation β€” spot hallucinations with green / yellow / red colouring.</p>
</div>
</div>
</div>
</section>
<!-- ── Grounded image gen ── -->
<section class="section" style="padding-top:0;">
<div class="container">
<div class="highlight-box">
<div class="section-label" style="text-align:left; margin-bottom:10px;" id="new-in-label">New in latest</div>
<h2>Search the web. Generate an image. One prompt.</h2>
<p class="sub">Ka1zen fetches real facts first, then turns them into a FLUX-optimized prompt and generates locally.</p>
<div class="steps">
<div class="step">
<div class="step-num">1</div>
<div>
<h3>Web Search</h3>
<p>Ka1zen queries DuckDuckGo to gather real, up-to-date facts β€” visible as a live Agent Step with source citations.</p>
</div>
</div>
<div class="step">
<div class="step-num">2</div>
<div>
<h3>Prompt Synthesis</h3>
<p>The active LLM converts search snippets into a detailed FLUX-optimized English prompt, incorporating colors, shapes, era, and context.</p>
</div>
</div>
<div class="step">
<div class="step-num">3</div>
<div>
<h3>Local FLUX Generation</h3>
<p>The image is produced on-device with FLUX.2-klein-9B. No image ever leaves your Mac.</p>
</div>
</div>
</div>
<div class="code-block">
<div class="cb-label">Example prompts</div>
<p>Search for a 1967 Ford Mustang and create a photorealistic image of this car parked in front of an American diner at sunset.</p>
<p>Look up the Renaissance fresco technique and make a detailed illustration of an artist at work on a church ceiling.</p>
<p>Find info about Japanese ramen shops in Tokyo and generate a cinematic photo of a steaming bowl of tonkotsu ramen.</p>
<p>Search the web for James Webb Space Telescope imagery and draw a stylized poster celebrating its deep-field observations.</p>
</div>
</div>
</div>
</section>
<!-- ── Requirements ── -->
<section class="section" style="padding-top:0;">
<div class="container">
<div class="section-label">Requirements</div>
<div class="section-title">What you need</div>
<div class="req-grid">
<div class="req-item"><div class="req-dot"></div><div class="req-text"><strong>macOS 15 Sequoia</strong><span>or later</span></div></div>
<div class="req-item"><div class="req-dot"></div><div class="req-text"><strong>Apple Silicon</strong><span>M1, M2, M3, M4 or newer</span></div></div>
<div class="req-item"><div class="req-dot"></div><div class="req-text"><strong>16 GB RAM</strong><span>32 GB recommended</span></div></div>
<div class="req-item"><div class="req-dot"></div><div class="req-text"><strong>Python 3.14</strong><span>from python.org only</span></div></div>
<div class="req-item"><div class="req-dot"></div><div class="req-text"><strong>mlx-lm</strong><span>via included install.sh</span></div></div>
<div class="req-item"><div class="req-dot"></div><div class="req-text"><strong>mflux</strong><span>optional β€” image generation</span></div></div>
</div>
<div class="privacy-strip">
<span class="lock">πŸ”’</span>
<p><strong>100% private.</strong> No account required. No analytics, no crash reports, no "anonymous usage statistics". Your conversations, documents and embeddings never leave your Mac.</p>
</div>
</div>
</section>
<!-- ── Footer ── -->
<footer>
<div class="footer-links">
<a href="https://github.com/Flor1an-B/Ka1zen/releases/latest" target="_blank" rel="noopener">⬇ Download</a>
<a href="https://github.com/Flor1an-B/Ka1zen" target="_blank" rel="noopener">GitHub</a>
<a href="https://github.com/Flor1an-B/Ka1zen/blob/main/USER_GUIDE.md" target="_blank" rel="noopener">User Guide</a>
<a href="https://github.com/Flor1an-B/Ka1zen/blob/main/MODEL_GUIDE.md" target="_blank" rel="noopener">Model Guide</a>
<a href="https://github.com/Flor1an-B/Ka1zen/blob/main/CHANGELOG.md" target="_blank" rel="noopener">Changelog</a>
</div>
<p>Developed by <a href="https://github.com/Flor1an-B" target="_blank" rel="noopener">Florian Bertaux</a> Β· Β© 2026 Β· <a href="https://github.com/Flor1an-B/Ka1zen/blob/main/LICENSE" target="_blank" rel="noopener">PolyForm Noncommercial License</a></p>
</footer>
<script>
fetch("https://api.github.com/repos/Flor1an-B/Ka1zen/releases/latest")
.then(r => r.json())
.then(data => {
const tag = data.tag_name || "";
const ver = tag.replace(/^v/, "");
if (!ver) return;
const heroEl = document.getElementById("hero-version");
const pillEl = document.getElementById("version-pill");
if (heroEl) heroEl.textContent = tag + " β€” Latest release";
const newInEl = document.getElementById("new-in-label");
if (newInEl) newInEl.textContent = "New in " + ver;
if (pillEl) pillEl.textContent = "v" + ver;
// Update all download links to point to this release's assets
const dlUrl = data.assets && data.assets[0]
? data.assets[0].browser_download_url
: data.html_url;
document.querySelectorAll("a[href*='releases/latest']").forEach(a => {
a.href = dlUrl;
});
})
.catch(() => {});
</script>
</body>
</html>