Files
ascii-art-app/templates/index.html
T
rmancinasandClaude Fable 5 5e33a38dbb
Build and Deploy / Build Image (push) Successful in 31s
Build and Deploy / Deploy to Portainer (push) Successful in 6s
feat: redesign UI with themes, animations, procedural ASCII engine
- Split app.py into routes + ascii_engine.py (stdlib-only procedural
  generation: figlet banners, creatures, patterns, scenes, classics)
- API: /api/random?category=..., /api/categories, richer JSON payload
- New frontend: templates/index.html + static/ (vanilla JS/CSS)
- 4 themes (graphite/paper/phosphor/amber), localStorage persist,
  no-flash boot, prefers-color-scheme default
- Scramble-resolve art transition, reduced-motion support
- Responsive: rail collapses to chips <760px, art auto-fits width
- Fix grid blowout on mobile (min-width: 0 on stage children)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 22:18:14 -07:00

105 lines
4.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>asciigen — procedural ascii art</title>
<script>
/* Theme boot: runs before first paint, no flash. */
(function () {
var t;
try { t = localStorage.getItem("asciigen.theme"); } catch (e) {}
if (!t) {
t = (window.matchMedia && window.matchMedia("(prefers-color-scheme: light)").matches)
? "paper" : "graphite";
}
document.documentElement.dataset.theme = t;
})();
</script>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<div class="scan" aria-hidden="true"></div>
<div class="drift" aria-hidden="true">
<span style="--x:6%; --d:34s; --dl:-4s; --s:1.1">{ }</span>
<span style="--x:16%; --d:46s; --dl:-20s; --s:0.8">#</span>
<span style="--x:28%; --d:38s; --dl:-11s; --s:1.4">&gt;_</span>
<span style="--x:41%; --d:52s; --dl:-30s; --s:0.9"></span>
<span style="--x:55%; --d:40s; --dl:-7s; --s:1.2">::</span>
<span style="--x:67%; --d:47s; --dl:-25s; --s:0.7">%</span>
<span style="--x:78%; --d:36s; --dl:-15s; --s:1.3">[]</span>
<span style="--x:90%; --d:50s; --dl:-2s; --s:1.0">\\</span>
</div>
<div class="app">
<header class="topbar">
<div class="brand">
<span class="brand-mark" aria-hidden="true"></span>
<span class="brand-name">asciigen</span>
<span class="brand-tag">/dev/random</span>
</div>
<div class="themes" role="group" aria-label="Theme">
<button class="theme-btn" data-set-theme="graphite" aria-label="Graphite theme (dark)" title="graphite"><span class="sw"></span></button>
<button class="theme-btn" data-set-theme="paper" aria-label="Paper theme (light)" title="paper"><span class="sw"></span></button>
<button class="theme-btn" data-set-theme="phosphor" aria-label="Phosphor theme (green terminal)" title="phosphor"><span class="sw"></span></button>
<button class="theme-btn" data-set-theme="amber" aria-label="Amber theme (CRT)" title="amber"><span class="sw"></span></button>
</div>
</header>
<main class="stage">
<aside class="rail">
<p class="rail-label">channel</p>
<nav class="cats" aria-label="Art category">
{% for cat in categories %}
<button class="cat{% if cat == 'any' %} is-active{% endif %}" data-cat="{{ cat }}">
<span class="cat-cursor" aria-hidden="true"></span>{{ cat }}
</button>
{% endfor %}
</nav>
<div class="hints" aria-hidden="true">
<p><kbd>space</kbd> generate</p>
<p><kbd>c</kbd> copy</p>
<p><kbd>t</kbd> theme</p>
</div>
</aside>
<section class="canvas">
<div class="frame" id="frame">
<span class="corner c-tl" aria-hidden="true"></span>
<span class="corner c-tr" aria-hidden="true"></span>
<span class="corner c-bl" aria-hidden="true"></span>
<span class="corner c-br" aria-hidden="true"></span>
<div class="art-scroll" id="artScroll" role="img" aria-label="Generated ASCII artwork">
<pre id="art">{{ piece.art }}</pre>
</div>
</div>
<div class="status" aria-live="polite">
<span class="st-title" id="stTitle">{{ piece.title }}</span>
<span class="st-sep" aria-hidden="true">·</span>
<span class="st-dims" id="stDims">{{ piece.cols }}×{{ piece.rows }}</span>
<span class="st-msg" id="stMsg">ready</span>
</div>
<div class="actions">
<button class="btn btn-primary" id="genBtn">
<span class="btn-glyph" aria-hidden="true"></span> generate
</button>
<button class="btn" id="copyBtn">
<span class="btn-glyph" aria-hidden="true"></span> <span id="copyLabel">copy</span>
</button>
</div>
</section>
</main>
<footer class="foot">
<span>procedural · stdlib python · zero deps</span>
<span class="foot-api">GET /api/random?category=…</span>
</footer>
</div>
<script>window.__initial = {{ piece | tojson }};</script>
<script src="{{ url_for('static', filename='js/app.js') }}" defer></script>
</body>
</html>