Re-skins every Booth surface in the SVOS design system (design-systems palettes/svos @ ed2f8d8). Visual and interaction layer only: no route, no copy, no ordering and no information-architecture change. - _svos_tokens.css: SVOS semantic tokens vendored by copy, with the four [data-theme] scopes re-scoped onto prefers-color-scheme and prefers-contrast (dark, light, dark-hc, light-hc). Included into base.html's <style>; cached at startup like every other template. - base.html: the accreted Australis sheet is rewritten against semantic tokens only. It also fixes four undefined variables (--line, --bg, --fg, --muted) that the keep/blur/reveal controls had been reading. The three SVOS devices each have exactly one job: reticle = selection (grid cursor, :target, picked option), hazard = irreversible (Wipe now, armed bulk delete), glow = live power (service dot, live bench). - The flag list renders as wrapped chips, so a large flag set no longer pushes the grid below the fold. The list order is unchanged. - IBM Plex Sans + JetBrains Mono load via Google Fonts with display=swap and system fallbacks (approved by booth-dev). - view.html, doc.html: inline styles moved onto tokens. - embed.js: fragment palette as custom properties scoped to .bk-ask; `.bk-ask-opt:has(input:checked)` still appears exactly once. - Favicon (base.html + app.FAVICON_HREF, kept in sync): graphite tile with reticle corners. Verified: 642 passed, the same count as the pre-change baseline. Visual order matches document order on 32 renders (4 booths x 4 widths x 2 schemes). A positive control, one tile given `order:-1`, is detected by the same check.
51 lines
2.1 KiB
HTML
51 lines
2.1 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}{{ file }} · {{ name }} · The Booth{% endblock %}
|
|
{% block content %}
|
|
<div class="docview">
|
|
<div class="vbar">
|
|
<a class="vbtn vx" href="/b/{{ name_url }}/" title="back to gallery (Esc)">✕</a>
|
|
<span class="vname">{{ file }}</span>
|
|
<span class="vspacer"></span>
|
|
<a class="vbtn" href="{{ file_url }}?dl=1" title="download {{ file }}">⬇</a>
|
|
</div>
|
|
{# Same record, same reason as the image viewer: the sidecar that says what
|
|
this doc IS travels with it to full-page view. #}
|
|
{% if caption %}<div class="doccap">{{ caption }}</div>{% endif %}
|
|
{% if marks %}
|
|
<div class="docmarks">
|
|
{% for m in marks if m.shape == 'note' %}<pre class="vnote">{{ m.text }}</pre>{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
{% if is_html %}
|
|
<article class="markdown-body">{{ body|safe }}</article>
|
|
{% else %}
|
|
<pre class="textview">{{ body }}</pre>
|
|
{% endif %}
|
|
</div>
|
|
<style>
|
|
/* .markdown-body and .textview live in base.html (shared with the inline
|
|
gallery view). Only the full-page layout wrapper is page-specific. */
|
|
.docview{max-width:52rem;margin:0 auto;padding:0 clamp(12px,3vw,20px) 64px}
|
|
.docview .vbar{margin:0 calc(-1 * clamp(12px,3vw,20px)) 20px;border-radius:0}
|
|
.docview .textview{overflow-x:auto}
|
|
.doccap{margin:0 0 20px;padding:8px 14px;font-size:var(--size-body);line-height:var(--leading-body);
|
|
color:var(--text-body);border-left:3px solid var(--border-strong);white-space:pre-wrap}
|
|
.docmarks{display:flex;flex-direction:column;gap:8px;margin:0 0 20px}
|
|
</style>
|
|
<script>
|
|
(function () {
|
|
/* Escape leaves the page, so it must not fire from inside a field someone
|
|
is typing in — the same guard the image viewer carries, stated in both
|
|
places because the handler is on `document` in both. */
|
|
function isEditable(el) {
|
|
return !!(el && (el.isContentEditable ||
|
|
/^(input|textarea|select)$/i.test(el.tagName || '')));
|
|
}
|
|
document.addEventListener('keydown', function (e) {
|
|
if (isEditable(e.target)) return;
|
|
if (e.key === 'Escape') window.location.href = {{ ('/b/' ~ name_url ~ '/')|tojson }};
|
|
});
|
|
})();
|
|
</script>
|
|
{% endblock %}
|