2025-09-23 09:19:23 -07:00
|
|
|
{% if theme %}
|
|
|
|
|
<div class="theme-detail-card">
|
|
|
|
|
{% if standalone_page %}
|
2025-10-28 08:21:52 -07:00
|
|
|
<div class="breadcrumb"><a href="/themes/" class="btn btn-ghost text-[11px] px-1.5 py-0.5">← Catalog</a></div>
|
2025-09-23 09:19:23 -07:00
|
|
|
{% endif %}
|
|
|
|
|
<h3 id="theme-detail-heading-{{ theme.id }}" tabindex="-1">{{ theme.theme }}
|
|
|
|
|
{% if diagnostics and yaml_available %}
|
2025-10-28 08:21:52 -07:00
|
|
|
<a href="/themes/yaml/{{ theme.id }}" target="_blank" class="text-[11px] font-normal ml-2">(YAML)</a>
|
2025-09-23 09:19:23 -07:00
|
|
|
{% endif %}
|
|
|
|
|
</h3>
|
|
|
|
|
{% if theme.description %}
|
|
|
|
|
<p class="desc">{{ theme.description }}</p>
|
|
|
|
|
{% else %}
|
|
|
|
|
{% if theme.synergies %}
|
|
|
|
|
<p class="desc" data-fallback-desc="1">Built around {{ theme.synergies[:6]|join(', ') }}.</p>
|
|
|
|
|
{% else %}
|
|
|
|
|
<p class="desc" data-fallback-desc="1">No description.</p>
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% endif %}
|
2025-10-28 08:21:52 -07:00
|
|
|
<div class="text-xs mb-2 flex gap-2 flex-wrap">
|
2025-09-23 09:19:23 -07:00
|
|
|
{% if theme.popularity_bucket %}<span class="theme-badge {% if theme.popularity_bucket=='Very Common' %}badge-pop-vc{% elif theme.popularity_bucket=='Common' %}badge-pop-c{% elif theme.popularity_bucket=='Uncommon' %}badge-pop-u{% elif theme.popularity_bucket=='Niche' %}badge-pop-n{% elif theme.popularity_bucket=='Rare' %}badge-pop-r{% endif %}" title="Popularity: {{ theme.popularity_bucket }}" aria-label="Popularity bucket: {{ theme.popularity_bucket }}">{{ theme.popularity_bucket }}</span>{% endif %}
|
|
|
|
|
{% if diagnostics and theme.editorial_quality %}<span class="theme-badge badge-quality-{{ theme.editorial_quality }}" title="Editorial quality: {{ theme.editorial_quality }}" aria-label="Editorial quality: {{ theme.editorial_quality }}">{{ theme.editorial_quality }}</span>{% endif %}
|
|
|
|
|
{% if diagnostics and theme.has_fallback_description %}<span class="theme-badge badge-fallback" title="Fallback generic description" aria-label="Fallback generic description">Fallback</span>{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="synergy-section">
|
|
|
|
|
<h4>Synergies {% if not uncapped %}(capped){% endif %}</h4>
|
|
|
|
|
<div class="theme-synergies">
|
|
|
|
|
{% for s in theme.synergies %}<span class="theme-badge">{{ s }}</span>{% endfor %}
|
|
|
|
|
</div>
|
|
|
|
|
{% if diagnostics %}
|
|
|
|
|
{% if not uncapped and theme.uncapped_synergies %}
|
2025-10-28 08:21:52 -07:00
|
|
|
<button hx-get="/themes/fragment/detail/{{ theme.id }}?diagnostics=1&uncapped=1" hx-target="#theme-detail" hx-swap="innerHTML" class="mt-2">Show Uncapped ({{ theme.uncapped_synergies|length }})</button>
|
2025-09-23 09:19:23 -07:00
|
|
|
{% elif uncapped %}
|
2025-10-28 08:21:52 -07:00
|
|
|
<button hx-get="/themes/fragment/detail/{{ theme.id }}?diagnostics=1" hx-target="#theme-detail" hx-swap="innerHTML" class="mt-2">Hide Uncapped</button>
|
2025-09-23 09:19:23 -07:00
|
|
|
{% if theme.uncapped_synergies %}
|
2025-10-28 08:21:52 -07:00
|
|
|
<div class="theme-synergies mt-1.5">
|
2025-09-23 09:19:23 -07:00
|
|
|
{% for s in theme.uncapped_synergies %}<span class="theme-badge">{{ s }}</span>{% endfor %}
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
2025-10-28 08:21:52 -07:00
|
|
|
<div class="examples mt-3">
|
|
|
|
|
<h4 class="mb-1.5">Example Cards</h4>
|
|
|
|
|
<div class="example-card-grid grid grid-cols-[repeat(auto-fill,minmax(230px,1fr))] gap-3.5">
|
2025-09-23 09:19:23 -07:00
|
|
|
{% if theme.example_cards %}
|
|
|
|
|
{% for c in theme.example_cards %}
|
2025-09-24 13:57:23 -07:00
|
|
|
{% set base_c = (c.split(' - Synergy (')[0] if ' - Synergy (' in c else c) %}
|
2025-10-28 08:21:52 -07:00
|
|
|
<div class="ex-card card-sample text-center" data-card-name="{{ base_c }}" data-role="example_card" data-tags="{{ theme.synergies|join(', ') }}" data-original-name="{{ c }}">
|
|
|
|
|
<img class="card-thumb w-full h-auto border border-[var(--border)] rounded-[10px]" loading="lazy" decoding="async" alt="{{ c }} image" src="{{ base_c|card_image('small') }}" />
|
|
|
|
|
<div class="text-[11px] mt-1 whitespace-nowrap overflow-hidden text-ellipsis font-semibold card-ref" data-card-name="{{ base_c }}" data-tags="{{ theme.synergies|join(', ') }}" data-original-name="{{ c }}">{{ c }}</div>
|
2025-09-23 09:19:23 -07:00
|
|
|
</div>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
{% else %}
|
2025-10-28 08:21:52 -07:00
|
|
|
<div class="text-xs opacity-70">No curated example cards.</div>
|
2025-09-23 09:19:23 -07:00
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
2025-10-28 08:21:52 -07:00
|
|
|
<h4 class="my-3.5 mb-1.5">Example Commanders</h4>
|
|
|
|
|
<div class="example-commander-grid grid grid-cols-[repeat(auto-fill,minmax(230px,1fr))] gap-3.5">
|
2025-09-23 09:19:23 -07:00
|
|
|
{% if theme.example_commanders %}
|
|
|
|
|
{% for c in theme.example_commanders %}
|
2025-09-24 13:57:23 -07:00
|
|
|
{% set base_c = (c.split(' - Synergy (')[0] if ' - Synergy (' in c else c) %}
|
2025-10-28 08:21:52 -07:00
|
|
|
<div class="ex-commander commander-cell text-center" data-card-name="{{ base_c }}" data-role="commander_example" data-tags="{{ theme.synergies|join(', ') }}" data-original-name="{{ c }}">
|
|
|
|
|
<img class="card-thumb w-full h-auto border border-[var(--border)] rounded-[10px]" loading="lazy" decoding="async" alt="{{ c }} image" src="{{ base_c|card_image('small') }}" />
|
|
|
|
|
<div class="text-[11px] mt-1 font-semibold whitespace-nowrap overflow-hidden text-ellipsis card-ref" data-card-name="{{ base_c }}" data-tags="{{ theme.synergies|join(', ') }}" data-original-name="{{ c }}">{{ c }}</div>
|
2025-09-23 09:19:23 -07:00
|
|
|
</div>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
{% else %}
|
2025-10-28 08:21:52 -07:00
|
|
|
<div class="text-xs opacity-70">No curated commander examples.</div>
|
2025-09-23 09:19:23 -07:00
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{% else %}
|
|
|
|
|
<div class="empty">Theme not found.</div>
|
|
|
|
|
{% endif %}
|
|
|
|
|
<script>
|
|
|
|
|
// Accessibility: automatically move focus to the detail heading after the fragment is swapped in
|
|
|
|
|
(function(){
|
|
|
|
|
try { var h=document.getElementById('theme-detail-heading-{{ theme.id }}'); if(h){ h.focus({preventScroll:false}); } } catch(_e){}
|
|
|
|
|
})();
|
2025-09-24 13:57:23 -07:00
|
|
|
// Post-render normalization: ensure any annotated ' - Synergy (...)' names use base name for Scryfall URLs
|
|
|
|
|
(function(){
|
|
|
|
|
try {
|
|
|
|
|
document.querySelectorAll('.example-card-grid img.card-thumb, .example-commander-grid img.card-thumb').forEach(function(img){
|
|
|
|
|
var orig = img.getAttribute('data-original-name') || img.getAttribute('data-card-name') || '';
|
|
|
|
|
var m = /(.*?)(\s*-\s*Synergy\s*\(.*\))$/i.exec(orig);
|
|
|
|
|
if(m){
|
|
|
|
|
var base = m[1].trim();
|
|
|
|
|
if(base){
|
|
|
|
|
img.setAttribute('data-card-name', base);
|
|
|
|
|
var current = img.getAttribute('src')||'';
|
|
|
|
|
// Replace fuzzy param only if it still contains the annotated portion
|
|
|
|
|
var before = decodeURIComponent((current.split('fuzzy=')[1]||'').split('&')[0] || '');
|
|
|
|
|
if(before && before !== base){
|
2025-10-28 08:21:52 -07:00
|
|
|
img.src = '/api/images/small/' + encodeURIComponent(base);
|
2025-09-24 13:57:23 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch(_){ }
|
|
|
|
|
})();
|
2025-09-23 09:19:23 -07:00
|
|
|
</script>
|