Alex Dunmow 6c03f6da6c feat(brutalist): Wave A override contract — 49 builtin overrides, 7 templates, seed
WO-TF-012. Neo-brutalist creative-studio theme brought up to the Wave A
OVERRIDE-CONTRACT (frozen against cms a0f07e2ae).

- Override all 49 mandatory builtin keys in templates/overrides/brutalist/
  (chrome, marketing, primitives, commerce, blog family, auth surface, 404),
  each carrying the brutalist chrome (chunky borders, hard offset shadows,
  hover snap, mono uppercase meta, candy accents) via a raw-CSS "bru-*" kit
  shipped in manifest.yaml. Load-bearing wiring (HTMX auth endpoints, signup
  form, contact-form submit + honeypot, facade scripts, lightbox) preserved
  verbatim.
- 7 page templates: default, full-width, landing, article, blog-index,
  contact, auth (fixed a bug where templates omitted the `dark` class so dark
  presets never activated).
- Blocks rework: removed 6 blocks that duplicated builtins (masthead,
  concrete_hero, meta_strip, caption_image, pull_quote, colophon) — now
  overrides; kept project_ledger; added persona blocks sticker_wall,
  changelog, spec_sheet (4 total).
- 4 dual-mode presets (all mode "both", 19 tokens light + dark): Concrete &
  Cadmium, Hazard, Riso, Acid.
- Bundled 8 latin-subset OFL woff2 (Space Grotesk, Archivo Black, Inter, IBM
  Plex Mono) in assets/fonts/ + LICENSES.md; fonts.json populated; all
  font-family via var(--font-*). RECOMMENDED_FONTS/ICONS updated;
  required_icon_packs declared.
- Email-safe themed wrapper (tables, inline styles) cleaned up.
- master_pages.json reworked to builtin navbar/hero/cta/footer.
- Demo seed (seed/seed.json + workflows.json, demo:true): home, about, blog
  (3 posts), contact (form + contact_submissions data table + row_inserted →
  email-admins workflow), login — studio voice.

Known codeless limitation: page-suggestions renders themed 404 chrome but the
similar-pages list (server-side DB query, no template provider) can't be
reproduced; auth-form captcha widget is server-generated and can't be emitted
(seed leaves captchaEnabled=false). Verified: make exit 0; check-safety
exit 0. Visual quality UNVERIFIED until Wave B.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:56:49 +08:00

62 lines
5.3 KiB
Plaintext

{# brutalist auth-form override — bordered login/register card. HTMX endpoints + input names + tab panels are load-bearing (public_auth.go); kept exact. Fields: default_tab, show_social, captchaEnabled; context.isPublicLoggedIn, context.publicUsername, context.site.google_oauth_client_id/facebook_app_id. NOTE: the proof-of-work captcha widget is server-generated and cannot be emitted from a codeless template — do NOT enable captchaEnabled on an override-rendered auth-form (see WO limitation). #}
{% if context.isPublicLoggedIn %}
<div class="bru-slab bru-shadow p-6 text-center" style="max-width:28rem;margin:0 auto">
<p class="bru-meta">Logged in as <strong class="text-foreground">{{ context.publicUsername }}</strong></p>
<a href="/account" class="bru-btn bru-btn-ghost mt-4">My Account</a>
</div>
{% else %}
{% set defaultTab = default_tab|default:"login" %}
<style>
.bru-auth-tab{color:hsl(var(--muted-foreground));border-bottom:3px solid transparent;margin-bottom:-3px;background:transparent}
.bru-auth-tab[data-active="1"]{color:hsl(var(--foreground));border-bottom-color:hsl(var(--accent))}
</style>
<div class="auth-form" style="max-width:28rem;margin:0 auto">
<div id="auth-message"></div>
<div class="flex mb-6" style="border-bottom:3px solid hsl(var(--border))">
<button type="button" data-auth-tab="login" class="bru-auth-tab flex-1 py-2.5 bru-meta" data-active="{% if defaultTab == "register" %}0{% else %}1{% endif %}">Login</button>
<button type="button" data-auth-tab="register" class="bru-auth-tab flex-1 py-2.5 bru-meta" data-active="{% if defaultTab == "register" %}1{% else %}0{% endif %}">Register</button>
</div>
<div id="login-panel"{% if defaultTab == "register" %} class="hidden"{% endif %}>
<form hx-post="/api/auth/login" hx-target="#auth-message" hx-swap="innerHTML" class="space-y-4">
<div><label class="bru-label">Email</label><input type="email" name="email" required class="bru-field"></div>
<div><label class="bru-label">Password</label><input type="password" name="password" required class="bru-field"></div>
{% if captchaEnabled %}<p class="bru-meta text-destructive">Captcha is enabled but cannot render in this theme. Disable it on the auth-form block.</p>{% endif %}
<button type="submit" class="bru-btn bru-btn-solid w-full" hx-disabled-elt="this">Login</button>
<p class="text-center bru-meta"><a href="/forgot-password" class="text-accent underline underline-offset-4">Forgot password?</a></p>
</form>
{% if show_social != false and (context.site.google_oauth_client_id or context.site.facebook_app_id) %}
<div class="mt-5"><div class="relative my-4"><hr class="bru-rule-thin"><span class="bru-meta" style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background:hsl(var(--background));padding:0 .6rem">or</span></div>
{% if context.site.google_oauth_client_id %}<a href="/api/auth/google/start" class="bru-btn bru-btn-ghost w-full mb-2">Continue with Google</a>{% endif %}
{% if context.site.facebook_app_id %}<a href="/api/auth/facebook/start" class="bru-btn bru-btn-ghost w-full">Continue with Facebook</a>{% endif %}</div>
{% endif %}
</div>
<div id="register-panel"{% if defaultTab != "register" %} class="hidden"{% endif %}>
<form hx-post="/api/auth/register" hx-target="#auth-message" hx-swap="innerHTML" class="space-y-4">
<div><label class="bru-label">Username</label><input type="text" name="username" required pattern="[a-zA-Z0-9_-]{3,30}" class="bru-field"></div>
<div><label class="bru-label">Email</label><input type="email" name="email" required class="bru-field"></div>
<div><label class="bru-label">Password</label><input type="password" name="password" required minlength="8" class="bru-field"></div>
{% if captchaEnabled %}<p class="bru-meta text-destructive">Captcha is enabled but cannot render in this theme. Disable it on the auth-form block.</p>{% endif %}
<button type="submit" class="bru-btn bru-btn-solid w-full" hx-disabled-elt="this">Create Account</button>
</form>
{% if show_social != false and (context.site.google_oauth_client_id or context.site.facebook_app_id) %}
<div class="mt-5"><div class="relative my-4"><hr class="bru-rule-thin"><span class="bru-meta" style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background:hsl(var(--background));padding:0 .6rem">or</span></div>
{% if context.site.google_oauth_client_id %}<a href="/api/auth/google/start" class="bru-btn bru-btn-ghost w-full mb-2">Continue with Google</a>{% endif %}
{% if context.site.facebook_app_id %}<a href="/api/auth/facebook/start" class="bru-btn bru-btn-ghost w-full">Continue with Facebook</a>{% endif %}</div>
{% endif %}
</div>
</div>
<script>
(function(){
var tabs=document.querySelectorAll('[data-auth-tab]');
if(!tabs.length)return;
function activate(name){
var lp=document.getElementById('login-panel'),rp=document.getElementById('register-panel');
if(lp)lp.classList.toggle('hidden',name!=='login');
if(rp)rp.classList.toggle('hidden',name!=='register');
tabs.forEach(function(t){t.setAttribute('data-active',t.getAttribute('data-auth-tab')===name?'1':'0');});
}
tabs.forEach(function(t){t.addEventListener('click',function(){activate(t.getAttribute('data-auth-tab'));});});
})();
</script>
{% endif %}