2025-09-25 15:14:15 -07:00
< div class = "random-result" id = "random-result" >
< style >
2025-09-26 18:15:52 -07:00
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}
.diag-badges{display:inline-flex; gap:4px; margin-left:8px; flex-wrap:wrap; align-items:center;}
.diag-badge{background:var(--panel-alt,#334155); color:#fff; padding:3px 7px; border-radius:12px; font-size:10px; letter-spacing:.5px; line-height:1.3; display:inline-flex; align-items:center; gap:4px;}
.diag-badge.warn{background:#814c14;}
2025-09-25 15:14:15 -07:00
.diag-badge.err{background:#7f1d1d;}
2025-09-26 18:15:52 -07:00
.diag-badge.fallback{background:#4338ca;}
.diag-badge .badge-icon{font-size:12px; display:inline-block;}
2025-09-25 15:14:15 -07:00
.btn-compact{font-size:11px; padding:2px 6px; line-height:1.2;}
2025-09-26 18:15:52 -07:00
.fallback-notice{margin-top:8px; padding:10px 12px; border-radius:6px; font-size:13px; line-height:1.45; border-left:4px solid currentColor; display:flex; gap:8px; align-items:flex-start;}
.fallback-notice.info{background:rgba(79,70,229,0.18); color:#2c2891; border:1px solid rgba(79,70,229,0.45);}
.fallback-notice.warn{background:#fff0d6; color:#6c4505; border:1px solid #d89b32;}
.fallback-notice.danger{background:#fef2f2; color:#7f1d1d; border:1px solid rgba(127,29,29,0.5);}
.fallback-notice:focus-visible{outline:2px solid currentColor; outline-offset:2px;}
.fallback-notice .notice-icon{font-size:16px; line-height:1; margin-top:2px;}
2025-09-25 15:14:15 -07:00
< / style >
< div class = "random-meta" style = "display:flex; gap:12px; align-items:center; flex-wrap:wrap;" >
< span class = "seed" > Seed: < strong > {{ seed }}< / strong > < / span >
{% if theme %}< span class = "theme" > Theme: < strong > {{ theme }}< / strong > < / span > {% endif %}
{% if permalink %}
< button class = "btn btn-compact" type = "button" aria-label = "Copy permalink for this exact build" onclick = "(async()=>{try{await navigator.clipboard.writeText(location.origin + '{{ permalink }}');(window.toast&&toast('Permalink copied'))||console.log('Permalink copied');}catch(e){alert('Copy failed');}})()" > Copy Permalink< / button >
{% endif %}
{% if show_diagnostics and diagnostics %}
2025-09-26 18:15:52 -07:00
< span class = "diag-badges" aria-label = "Diagnostics" role = "status" aria-live = "polite" aria-atomic = "true" >
< span class = "diag-badge" title = "Attempts tried before acceptance" aria-label = "Attempts tried before acceptance" >
< span class = "badge-icon" aria-hidden = "true" > ⟳< / span >
< span aria-hidden = "true" > Att {{ diagnostics.attempts }}< / span >
< / span >
< span class = "diag-badge" title = "Elapsed build time in milliseconds" aria-label = "Elapsed build time in milliseconds" >
< span class = "badge-icon" aria-hidden = "true" > ⏱< / span >
< span aria-hidden = "true" > {{ diagnostics.elapsed_ms }}ms< / span >
< / span >
{% if diagnostics.timeout_hit %}
< span class = "diag-badge warn" title = "Generation loop exceeded timeout limit before success" aria-label = "Generation exceeded timeout limit before success" >
< span class = "badge-icon" aria-hidden = "true" > ⚠< / span >
< span aria-hidden = "true" > Timeout< / span >
< / span >
{% endif %}
{% if diagnostics.retries_exhausted %}
< span class = "diag-badge warn" title = "All allotted attempts were used without an early acceptable candidate" aria-label = "All attempts were used without an early acceptable candidate" >
< span class = "badge-icon" aria-hidden = "true" > ↺< / span >
< span aria-hidden = "true" > Retries< / span >
< / span >
{% endif %}
{% if fallback or diagnostics.fallback %}
< span class = "diag-badge fallback" title = "Original theme produced no candidates; Surprise mode fallback engaged" aria-label = "Fallback engaged after theme produced no candidates" >
< span class = "badge-icon" aria-hidden = "true" > ★< / span >
< span aria-hidden = "true" > Fallback< / span >
< / span >
{% endif %}
2025-09-25 15:14:15 -07:00
< / span >
{% endif %}
2025-09-17 13:23:27 -07:00
< / div >
2025-09-26 18:15:52 -07:00
{% set display_list = display_themes or resolved_themes or [] %}
{% set resolved_list = display_list %}
{% set has_primary = primary_theme or secondary_theme or tertiary_theme %}
{% if resolved_list or has_primary %}
< div class = "resolved-themes" style = "margin-top:6px; font-size:13px; color:var(--text-muted,#94a3b8);" role = "status" aria-live = "polite" >
{% if resolved_list %}
Resolved themes: < strong > {{ resolved_list|join(' + ') }}< / strong >
{% else %}
Resolved themes: < strong > Full pool fallback< / strong >
{% endif %}
< / div >
{% endif %}
{% if auto_fill_applied and auto_filled_themes %}
< div class = "auto-fill-note" style = "margin-top:4px; font-size:12px; color:var(--text-muted,#94a3b8);" role = "status" aria-live = "polite" >
Auto-filled: < strong > {{ auto_filled_themes|join(', ') }}< / strong >
< / div >
{% endif %}
2025-09-29 21:32:08 -07:00
{% if fallback_reason and has_primary %}
2025-09-26 18:15:52 -07:00
{% if synergy_fallback and (not resolved_list) %}
{% set notice_class = 'danger' %}
{% elif synergy_fallback %}
{% set notice_class = 'warn' %}
{% else %}
{% set notice_class = 'info' %}
{% endif %}
{% if notice_class == 'danger' %}
{% set notice_icon = '⛔' %}
{% elif notice_class == 'warn' %}
{% set notice_icon = '⚠️' %}
{% else %}
{% set notice_icon = 'ℹ ️ ' %}
{% endif %}
< div class = "fallback-notice {{ notice_class }}" role = "status" aria-live = "assertive" aria-atomic = "true" tabindex = "0" >
< span class = "notice-icon" aria-hidden = "true" > {{ notice_icon }}< / span >
< span >
< strong > Heads up:< / strong >
< span id = "fallback-reason-text" > {{ fallback_reason }}.< / span >
< span class = "sr-only" > You can tweak secondary or tertiary themes for different mixes, or reroll to explore more options.< / span >
< span aria-hidden = "true" > Try tweaking Secondary or Tertiary themes for different mixes, or reroll to explore more options.< / span >
< / span >
< / div >
{% endif %}
2025-09-25 15:14:15 -07:00
<!-- Hidden current seed so HTMX reroll button can include it via hx - include -->
< input type = "hidden" id = "current-seed" name = "seed" value = "{{ seed }}" / >
< input type = "hidden" id = "current-commander" name = "commander" value = "{{ commander }}" / >
2025-09-26 18:15:52 -07:00
< input type = "hidden" id = "current-primary-theme" name = "primary_theme" value = "{{ primary_theme or '' }}" / >
< input type = "hidden" id = "current-secondary-theme" name = "secondary_theme" value = "{{ secondary_theme or '' }}" / >
< input type = "hidden" id = "current-tertiary-theme" name = "tertiary_theme" value = "{{ tertiary_theme or '' }}" / >
< input type = "hidden" id = "current-resolved-themes" name = "resolved_themes" value = "{{ resolved_list|join('||') }}" / >
< input type = "hidden" id = "current-auto-fill-enabled" name = "auto_fill_enabled" value = "{{ 'true' if auto_fill_enabled else 'false' }}" / >
< input type = "hidden" id = "current-auto-fill-secondary-enabled" name = "auto_fill_secondary_enabled" value = "{{ 'true' if auto_fill_secondary_enabled else 'false' }}" / >
< input type = "hidden" id = "current-auto-fill-tertiary-enabled" name = "auto_fill_tertiary_enabled" value = "{{ 'true' if auto_fill_tertiary_enabled else 'false' }}" / >
< input type = "hidden" id = "current-auto-filled-themes" name = "auto_filled_themes" value = "{{ auto_filled_themes|join('||') if auto_filled_themes else '' }}" / >
< input type = "hidden" id = "current-strict-theme-match" name = "strict_theme_match" value = "{{ 'true' if strict_theme_match else 'false' }}" / >
2025-09-25 15:14:15 -07:00
< div class = "commander-block" style = "display:flex; gap:14px; align-items:flex-start; margin-top:.75rem;" >
< div class = "commander-thumb" style = "flex:0 0 auto;" >
< img
2025-10-28 08:21:52 -07:00
src="{{ commander|card_image('small') }}"
srcset="{{ commander|card_image('small') }} 160w, {{ commander|card_image('normal') }} 488w"
2025-09-25 15:14:15 -07:00
sizes="(max-width: 600px) 120px, 160px"
alt="{{ commander }} image"
width="160" height="220"
style="width:160px; height:auto; border-radius:8px; box-shadow:0 6px 18px rgba(0,0,0,.55); border:1px solid var(--border); background:#0f1115;"
class="commander-img"
loading="lazy" decoding="async"
data-card-name="{{ commander }}" />
< / div >
< div style = "flex:1 1 auto;" >
< div class = "muted" style = "font-size:12px; font-weight:600; letter-spacing:.5px; text-transform:uppercase;" > Commander< / div >
< h3 class = "commander" style = "margin:.15rem 0 0 0;" data-card-name = "{{ commander }}" > {{ commander }}< / h3 >
< / div >
< / div >
{% if summary %}
{# Reuse the comprehensive deck summary partial #}
{% include "partials/deck_summary.html" %}
{% else %}
< ul class = "decklist" >
{% for card in decklist %}
{% if card.name %}
< li > {{ card.name }}{% if card.count %} × {{ card.count }}{% endif %}< / li >
{% else %}
< li > {{ card }}< / li >
{% endif %}
{% endfor %}
< / ul >
{% endif %}
< script >
// Re-run bindings after OOB swap so hover & view toggle work consistently
(function(){
try { if (window.bindAllCardImageRetries) window.bindAllCardImageRetries(); } catch(_) {}
try { if (window.attachCardHover) window.attachCardHover(); } catch(_) {}
// Deck summary initializer (idempotent) – will assign aria-selected
try { if (window.initDeckSummaryTypeView) window.initDeckSummaryTypeView(document.getElementById('random-result')); } catch(_) {}
})();
< / script >
2025-09-17 13:23:27 -07:00
< / div >