Re-persona noir from photography to the locked detective/true-crime
direction: case-file panels, typewriter type, redaction bars, evidence
board, film grain. High-key gallery (light) / darkroom black + amber
safelight (dark).
- 49 mandatory builtin overrides (chrome, marketing, primitives,
commerce, blog family, auth, page-suggestions), re-skinned from the
frozen builtin defaults with every field/provider/tag/JS preserved;
legacy button/card field reads reconciled to the new contract.
- 7 page templates (default, full-width, landing, article, blog-index,
contact, auth) + themed email wrapper.
- 4 persona blocks (case_file, evidence_board, redacted_quote,
case_dossier); old photography blocks deleted (now overrides).
- 5 dual-mode presets (19 tokens, light+dark tuned).
- Bundled OFL fonts (Source Serif 4, IBM Plex Mono) + licenses;
RECOMMENDED_FONTS/ICONS updated; required_icon_packs=lucide.
- Master pages + seed demo ("The Cold File": home/about/blog x3/contact
with case_tips data table + row_inserted email-admins workflow/login).
- noir CSS vocabulary via manifest css.input_css_append; MID motion
(scroll-reveal + gallery lightbox, reduced-motion honored, no canvas).
Verified: make build exit 0; check-safety 32 checks 19 ok 13 skip -> OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
53 lines
5.6 KiB
Plaintext
53 lines
5.6 KiB
Plaintext
{# noir override — gallery; preserves layout, gap, columns, lightbox, images[].src/.alt/.caption, data-bn-gallery, data-lightbox, data-bn-gallery-item, data-caption, {% img %} calls, and the full lightbox IIFE verbatim. Only grid tiles restyled (square hairline frames, grayscale). #}
|
|
{% with layout=layout|default:"grid" gap=gap|default:"md" cols=columns|default:3 %}<div data-block-override="noir:gallery" class="bn-gallery my-8{% if class %} {{ class }}{% endif %}" data-bn-gallery data-lightbox="{% if lightbox %}true{% else %}false{% endif %}"><div class="{% if layout == "carousel" %}flex snap-x snap-mandatory overflow-x-auto pb-2 {% if gap == "sm" %}gap-2{% elif gap == "lg" %}gap-6{% else %}gap-4{% endif %}{% elif layout == "masonry" %}columns-2 {% if cols == 4 %}md:columns-4{% elif cols == 2 %}md:columns-2{% else %}md:columns-3{% endif %} {% if gap == "sm" %}gap-2{% elif gap == "lg" %}gap-6{% else %}gap-4{% endif %}{% else %}grid grid-cols-2 {% if cols == 4 %}md:grid-cols-4{% elif cols == 2 %}md:grid-cols-2{% else %}md:grid-cols-3{% endif %} {% if gap == "sm" %}gap-2{% elif gap == "lg" %}gap-6{% else %}gap-4{% endif %}{% endif %}">{% for image in images %}<a href="{{ image.src|mediaURL }}" data-bn-gallery-item data-caption="{{ image.caption|default:"" }}" class="noir-hairline group relative block overflow-hidden bg-muted grayscale transition hover:grayscale-0 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 {% if layout == "carousel" %}w-64 shrink-0 snap-start sm:w-80{% elif layout == "masonry" %}mb-4 w-full break-inside-avoid{% endif %}">{% if layout == "grid" %}{% img image.src alt=image.alt|default:"" class="aspect-square w-full object-cover" %}{% else %}{% img image.src alt=image.alt|default:"" class="h-auto w-full" %}{% endif %}{% if image.caption %}<span class="sr-only">{{ image.caption }}</span>{% endif %}</a>{% endfor %}</div></div>{% if lightbox %}<script>
|
|
(function(){
|
|
if(window.__bnLightbox)return;window.__bnLightbox=true;
|
|
var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
var ov,imgEl,capEl,items=[],idx=0,lastFocus=null;
|
|
function build(){
|
|
ov=document.createElement('div');
|
|
ov.setAttribute('role','dialog');ov.setAttribute('aria-modal','true');ov.setAttribute('aria-label','Image viewer');ov.tabIndex=-1;
|
|
ov.style.cssText='position:fixed;inset:0;z-index:9999;display:none;align-items:center;justify-content:center;background:rgba(0,0,0,0.9);padding:2rem;';
|
|
var btn='position:absolute;width:2.75rem;height:2.75rem;display:inline-flex;align-items:center;justify-content:center;border-radius:9999px;border:none;background:hsl(var(--background));color:hsl(var(--foreground));cursor:pointer;';
|
|
ov.innerHTML=
|
|
'<button type="button" data-lb-close aria-label="Close" style="'+btn+'top:1rem;right:1rem;"><svg style="width:1.25rem;height:1.25rem" aria-hidden="true"><use href="/icons/lucide.svg#x"/></svg></button>'+
|
|
'<button type="button" data-lb-prev aria-label="Previous image" style="'+btn+'left:1rem;top:50%;transform:translateY(-50%);"><svg style="width:1.25rem;height:1.25rem" aria-hidden="true"><use href="/icons/lucide.svg#chevron-left"/></svg></button>'+
|
|
'<figure style="margin:0;max-width:92vw;max-height:92vh;display:flex;flex-direction:column;align-items:center;gap:0.75rem;"><img data-lb-img alt="" style="max-width:92vw;max-height:82vh;object-fit:contain;border-radius:0.5rem;'+(reduce?'':'transition:opacity .2s ease;')+'"><figcaption data-lb-cap style="color:hsl(var(--background));opacity:.85;font-size:.875rem;text-align:center;max-width:60ch;"></figcaption></figure>'+
|
|
'<button type="button" data-lb-next aria-label="Next image" style="'+btn+'right:1rem;top:50%;transform:translateY(-50%);"><svg style="width:1.25rem;height:1.25rem" aria-hidden="true"><use href="/icons/lucide.svg#chevron-right"/></svg></button>';
|
|
document.body.appendChild(ov);
|
|
imgEl=ov.querySelector('[data-lb-img]');capEl=ov.querySelector('[data-lb-cap]');
|
|
ov.addEventListener('click',function(e){if(e.target===ov||e.target.closest('[data-lb-close]'))close();});
|
|
ov.querySelector('[data-lb-prev]').addEventListener('click',function(e){e.stopPropagation();show(idx-1);});
|
|
ov.querySelector('[data-lb-next]').addEventListener('click',function(e){e.stopPropagation();show(idx+1);});
|
|
}
|
|
function show(i){
|
|
if(!items.length)return;
|
|
idx=(i+items.length)%items.length;
|
|
var a=items[idx];var im=a.querySelector('img');
|
|
imgEl.src=(im&&(im.currentSrc||im.src))||a.getAttribute('href');
|
|
imgEl.alt=im?im.alt:'';
|
|
var cap=a.getAttribute('data-caption')||'';capEl.textContent=cap;capEl.style.display=cap?'block':'none';
|
|
}
|
|
function open(g,link){
|
|
if(!ov)build();
|
|
items=Array.prototype.slice.call(g.querySelectorAll('[data-bn-gallery-item]'));
|
|
lastFocus=document.activeElement;ov.style.display='flex';
|
|
var multi=items.length>1;
|
|
ov.querySelector('[data-lb-prev]').style.display=multi?'inline-flex':'none';
|
|
ov.querySelector('[data-lb-next]').style.display=multi?'inline-flex':'none';
|
|
show(items.indexOf(link));ov.focus();
|
|
}
|
|
function close(){if(ov)ov.style.display='none';if(lastFocus&&lastFocus.focus)lastFocus.focus();}
|
|
document.addEventListener('click',function(e){
|
|
var link=e.target.closest('[data-bn-gallery][data-lightbox="true"] [data-bn-gallery-item]');
|
|
if(!link)return;e.preventDefault();open(link.closest('[data-bn-gallery]'),link);
|
|
});
|
|
document.addEventListener('keydown',function(e){
|
|
if(!ov||ov.style.display==='none')return;
|
|
if(e.key==='Escape'){e.preventDefault();close();}
|
|
else if(e.key==='ArrowLeft')show(idx-1);
|
|
else if(e.key==='ArrowRight')show(idx+1);
|
|
});
|
|
})();
|
|
</script>{% endif %}{% endwith %}
|