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" >
2026-03-20 09:03:20 -07:00
{% if show_theme_popularity_badges and 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 show_theme_quality_badges and theme.quality_tier %}< span class = "theme-badge badge-quality-{{ theme.quality_tier|lower }}" title = "Quality: {{ theme.quality_tier }} ({{ (theme.quality_score * 100)|round|int }}%)" aria-label = "Quality tier: {{ theme.quality_tier }}" > {{ theme.quality_tier }}< / span > {% endif %}
{% if show_theme_pool_badges and theme.pool_tier %}< span class = "theme-badge badge-pool-{{ theme.pool_tier|lower }}" title = "Pool: {{ theme.pool_tier }} (~{{ theme.pool_size }} cards)" aria-label = "Pool tier: {{ theme.pool_tier }}" > {{ theme.pool_tier }}< / span > {% endif %}
2025-09-23 09:19:23 -07:00
{% 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 >
2026-03-20 09:03:20 -07:00
<!-- Badge Explanations -->
{% if (show_theme_quality_badges and theme.quality_tier) or (show_theme_pool_badges and theme.pool_tier) or (show_theme_popularity_badges and theme.popularity_bucket) %}
< details class = "mt-3 text-xs" style = "max-width: 800px;" open >
< summary class = "cursor-pointer opacity-70 hover:opacity-100 font-semibold" style = "user-select: none;" >
ℹ ️ Badge Details
< / summary >
< div class = "mt-2 space-y-3 px-4 py-3 bg-gray-50 dark:bg-gray-800/50 rounded-lg border border-gray-200 dark:border-gray-700" >
{% if show_theme_quality_badges and theme.quality_tier %}
< div class = "badge-explanation" >
< div class = "flex items-start gap-2" >
< span class = "theme-badge badge-quality-{{ theme.quality_tier|lower }} flex-shrink-0"
title="Quality: {{ theme.quality_tier }} ({{ (theme.quality_score * 100)|round|int }}%)">
{{ theme.quality_tier }}
< / span >
< div class = "flex-1 text-sm text-gray-700 dark:text-gray-300" >
< strong > Quality Score:< / strong > {{ (theme.quality_score * 100)|round|int }}%
< ul class = "mt-1 ml-4 list-disc space-y-0.5 text-xs text-gray-600 dark:text-gray-400" >
{% if theme.quality_score >= 0.70 %}
< li > High card count and unique synergies ({{ theme.synergy_count }} synergies)< / li >
{% elif theme.quality_score >= 0.60 %}
< li > Good card selection with {{ theme.synergy_count }} documented synergies< / li >
{% elif theme.quality_score >= 0.40 %}
< li > Moderate card pool with {{ theme.synergy_count }} synergies< / li >
{% else %}
< li > Limited card pool and synergies ({{ theme.synergy_count }} synergies)< / li >
{% endif %}
{% if theme.has_fallback_description %}
< li > Auto-generated description (could benefit from custom curation)< / li >
{% else %}
< li > Custom curated description< / li >
{% endif %}
{% if theme.curated_synergies or theme.enforced_synergies or theme.inferred_synergies %}
< li > Synergy breakdown: {{ theme.curated_synergies|length }} curated, {{ theme.enforced_synergies|length }} enforced, {{ theme.inferred_synergies|length }} inferred< / li >
{% else %}
< li > No synergy breakdown available< / li >
{% endif %}
{% if theme.deck_archetype %}
< li > Deck archetype: {{ theme.deck_archetype }}< / li >
{% else %}
< li > No deck archetype classification< / li >
{% endif %}
{% if theme.editorial_quality == 'final' %}
< li > Fully reviewed and curated (editorial status: final)< / li >
{% elif theme.editorial_quality == 'refined' %}
< li > Reviewed and refined (editorial status: refined)< / li >
{% elif theme.editorial_quality == 'draft' %}
< li > Draft quality (editorial status: draft)< / li >
{% elif theme.editorial_quality == 'auto' %}
< li > Auto-generated content (editorial status: auto)< / li >
{% endif %}
< / ul >
< div class = "mt-2 text-xs text-gray-500 dark:text-gray-500" > 💡 < a href = "https://github.com/mwisnowski/mtg_python_deckbuilder" target = "_blank" rel = "noopener noreferrer" class = "underline hover:text-gray-700 dark:hover:text-gray-300" > Help improve theme quality on GitHub< / a > < / div >
< / div >
< / div >
< / div >
{% endif %}
{% if show_theme_pool_badges and theme.pool_tier %}
< div class = "badge-explanation" >
< div class = "flex items-start gap-2" >
< span class = "theme-badge badge-pool-{{ theme.pool_tier|lower }} flex-shrink-0"
title="Pool: {{ theme.pool_tier }} (~{{ theme.pool_size }} cards)">
{{ theme.pool_tier }}
< / span >
< div class = "flex-1 text-sm text-gray-700 dark:text-gray-300" >
< strong > Card Pool Size:< / strong > ~{{ theme.pool_size }} cards available
< ul class = "mt-1 ml-4 list-disc space-y-0.5 text-xs text-gray-600 dark:text-gray-400" >
{% if theme.pool_tier == 'Vast' %}
< li > Extensive card selection with {{ theme.pool_size }}+ cards available for deckbuilding< / li >
< li > Provides maximum flexibility and optimization potential< / li >
{% elif theme.pool_tier == 'Large' %}
< li > Large card selection with {{ theme.pool_size }} cards available< / li >
< li > Offers strong flexibility for different deck strategies< / li >
{% elif theme.pool_tier == 'Moderate' %}
< li > Moderate selection with {{ theme.pool_size }} cards available< / li >
< li > Sufficient options for focused deck strategies< / li >
{% elif theme.pool_tier == 'Small' %}
< li > Limited selection with {{ theme.pool_size }} cards available< / li >
< li > May require creative deckbuilding approaches< / li >
{% elif theme.pool_tier == 'Tiny' %}
< li > Very limited pool with only {{ theme.pool_size }} cards available< / li >
< li > Highly focused niche theme with restricted card choices< / li >
{% endif %}
< / ul >
< / div >
< / div >
< / div >
{% endif %}
{% if show_theme_popularity_badges and theme.popularity_bucket %}
< div class = "badge-explanation" >
< div class = "flex items-start gap-2" >
< 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 %} flex-shrink-0"
title="Popularity: {{ theme.popularity_bucket }}">
{{ theme.popularity_bucket }}
< / span >
< div class = "flex-1 text-sm text-gray-700 dark:text-gray-300" >
< strong > Theme Popularity:< / strong > {{ theme.popularity_bucket }}
< ul class = "mt-1 ml-4 list-disc space-y-0.5 text-xs text-gray-600 dark:text-gray-400" >
{% if theme.popularity_bucket == 'Very Common' %}
< li > Extremely popular theme seen in many commander decks< / li >
< li > High adoption rate across diverse commanders and strategies< / li >
< li > Well-established with extensive community support and resources< / li >
{% elif theme.popularity_bucket == 'Common' %}
< li > Popular theme frequently used in commander deckbuilding< / li >
< li > Strong adoption rate with good community support< / li >
< li > Well-documented strategies and card synergies available< / li >
{% elif theme.popularity_bucket == 'Uncommon' %}
< li > Moderately popular theme with regular usage< / li >
< li > Decent adoption rate, particularly in specific archetypes< / li >
< li > Some community resources and discussion available< / li >
{% elif theme.popularity_bucket == 'Niche' %}
< li > Specialized theme with limited but dedicated following< / li >
< li > Lower adoption rate, often used in specific deck strategies< / li >
< li > May require more research to optimize effectively< / li >
{% elif theme.popularity_bucket == 'Rare' %}
< li > Rarely used theme with minimal adoption< / li >
< li > Very low usage rate across commander decks< / li >
< li > May offer unique deckbuilding opportunities for brewers< / li >
{% endif %}
< / ul >
< / div >
< / div >
< / div >
{% endif %}
< / div >
< / details >
{% endif %}
2025-09-23 09:19:23 -07:00
< 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) %}
2026-03-20 09:03:20 -07:00
< div class = "ex-card text-center" data-card-name = "{{ base_c }}" data-role = "example_card" data-tags = "{{ theme.synergies|join(', ') }}" data-original-name = "{{ c }}" >
2025-10-28 08:21:52 -07:00
< 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 >