- fan modal: stage block w. idle-reveal/careen-out; carousel shifts left so focused card sits left-of-center; SPIN rotates whole card via Element.animate(); FLIP toggles polarity (Levity ↔ Gravity) via perspective rotateY w. mid-flip repaint; SPIN state retained across FLIP; FLIP btn hover-revealed only when focused card or btn is hovered (:has) - mobile breakpoints: --fan-card-w / --fan-card-h / --fan-stage-shift / --fan-carousel-step lifted to CSS vars on .tarot-fan-wrap; portrait ≤ 480px @ 150×230, landscape ≤ 500h @ 150×235; corners + face text/padding scale w. card width - shared StageCard JS module (apps/epic/stage-card.js): fromDataset, populateCard, populateKeywords, buildInfoData, renderFyi — sig/sea/fan all delegate; ~150 lines de-duplicated - shared @mixin stat-block-shared (SCSS) lifts duplicated stat-face / stat-keywords / sig-info rules; @mixin stage-card-polarity unifies sea-stage--levity/--gravity + fan[data-polarity] coloring - model rename: TarotCard.reversal → reversal_qualifier (migration 0014); render-time fallback to current polarity's qualifier when blank - class unification: .sig-info-open / .sea-info-open / .fyi-open → .fyi-open (on stat block); .sig-flip-btn / .sea-spin-btn / .fan-spin-btn → .spin-btn; same for .fyi-btn / .fyi-prev / .fyi-next - custom combobox (apps/epic/combobox.js) replaces native <select> for PICK SEA spread picker — keyboard nav, click-outside-close, aria roles; Firefox/Chrome OS-rendered <option> ignored CSS - Jasmine: FanStageSpec.js w. idle-reveal / population / SPIN / FYI / FLIP specs; sig + sea fixtures + IT view assertions updated for renamed classes - 748 ITs + Jasmine green Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
49 lines
2.5 KiB
HTML
49 lines
2.5 KiB
HTML
{% for card in cards %}
|
|
<div class="fan-card"
|
|
data-index="{{ forloop.counter0 }}"
|
|
data-suit-icon="{{ card.suit_icon }}"
|
|
data-corner-rank="{{ card.corner_rank }}"
|
|
data-name-group="{{ card.name_group }}"
|
|
data-name-title="{{ card.name_title }}"
|
|
data-arcana="{{ card.get_arcana_display }}"
|
|
data-correspondence="{{ card.correspondence|default:'' }}"
|
|
data-keywords-upright="{{ card.keywords_upright|join:',' }}"
|
|
data-keywords-reversed="{{ card.keywords_reversed|join:',' }}"
|
|
data-energies="{{ card.energies_json }}"
|
|
data-operations="{{ card.operations_json }}"
|
|
data-levity-qualifier="{{ card.levity_qualifier }}"
|
|
data-gravity-qualifier="{{ card.gravity_qualifier }}"
|
|
data-reversal-qualifier="{{ card.reversal_qualifier }}">
|
|
<div class="fan-card-corner fan-card-corner--tl">
|
|
<span class="fan-corner-rank">{{ card.corner_rank }}</span>
|
|
{% if card.suit_icon %}<i class="fa-solid {{ card.suit_icon }}"></i>{% endif %}
|
|
</div>
|
|
<div class="fan-card-face">
|
|
<div class="fan-card-face-upright">
|
|
{% if card.name_group %}<p class="fan-card-name-group">{{ card.name_group }}</p>{% endif %}
|
|
{% if card.arcana != "MAJOR" and card.levity_qualifier %}
|
|
<p class="sig-qualifier-above">{{ card.levity_qualifier }}</p>
|
|
{% endif %}
|
|
<h3 class="fan-card-name">{{ card.name_title }}{% if card.arcana == "MAJOR" and card.levity_qualifier %},{% endif %}</h3>
|
|
{% if card.arcana == "MAJOR" and card.levity_qualifier %}
|
|
<p class="sig-qualifier-below">{{ card.levity_qualifier }}</p>
|
|
{% endif %}
|
|
</div>
|
|
<p class="fan-card-arcana">{{ card.get_arcana_display }}</p>
|
|
<div class="fan-card-face-reversal">
|
|
{% if card.arcana == "MAJOR" %}
|
|
<p class="fan-card-reversal-name">{{ card.levity_qualifier|default:card.gravity_qualifier }}</p>
|
|
<p class="fan-card-reversal-qualifier">{{ card.name_title }}{% if card.levity_qualifier %},{% endif %}</p>
|
|
{% else %}
|
|
<p class="fan-card-reversal-name">{{ card.name_title }}</p>
|
|
<p class="fan-card-reversal-qualifier">{{ card.reversal_qualifier|default:card.gravity_qualifier }}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="fan-card-corner fan-card-corner--br">
|
|
<span class="fan-corner-rank">{{ card.corner_rank }}</span>
|
|
{% if card.suit_icon %}<i class="fa-solid {{ card.suit_icon }}"></i>{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|