Commit Graph

163 Commits

Author SHA1 Message Date
Disco DeDisco
3410f073f0 fan-card title symmetry; pips → Minor; tray Sig card
- title slot: <h3> → <p>; font-size 0.1 → 0.087 (deck) / 0.093 → 0.08 (sig/sea); text-wrap: balance — kills upright/reversal asymmetry & all per-card squeeze hacks
- trump 8 hyphen → U+2011, trump 9 space → U+00A0 (mig 0021) so titles wrap as intended
- pips (Earthman 1–10) → MINOR arcana (mig 0022); StageCard._arcanaDisplay() picks the right label
- PICK SEA: re-clicking a deposited slot now restores the server-rolled reversed state (sea.js _populate toggle)
- tray Sig card: render same .sig-stage-card.sea-sig-card (rank + icon, -5deg) as Sea center; --sig-card-w sized off --tray-cell-size
- title_squeeze_class kept as no-op for template compat
- 0020 (Self-Unimportance rename) included from prior turn

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 02:06:55 -04:00
Disco DeDisco
c264b6e3ee PICK SEA reversal axis: server-side roll + preview + deposited slot — TDD
- new apps/epic/utils.STACK_REVERSAL_PROBABILITY (=0.25) + stack_reversal_probability(user, room) helper; single source of truth across game phases & one-line swap point for forthcoming per-user-profile config
- sea_deck view rolls each card's `reversed` axis at fetch time using the helper, attaches to card JSON; matches the eager shuffle pattern (whole deal determined at phase start)
- room_view + sea_partial pass `stack_reversal_pct` into context for the new <p class="sea-reversal-hint">25% reversals</p> hint above the SPREAD combobox (italic, 0.7rem, 0.55 opacity)
- SeaDeal.openStage applies .stage-card--reversed + .is-reversed to stat block when card.reversed → preview lands face-reversed w. REVERSAL keywords
- _fillSlot adds .sea-card-slot--reversed → slot itself rotates 180° (bg + border + content stack flips, not just inner chars upside-down in place); .sea-pos-cross overrides to 270° to compose w. its existing 90°
- _fillSlot adds .sea-card-slot--rank-long when corner_rank.length ≥ 5 (XVIII / XXIII / XXVIII / XXXIII / XXXVIII / XLIII / XLVIII) → SCSS scaleX(0.7) + letter-spacing -0.05em squeezes horizontally w.o changing font-size

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 00:11:40 -04:00
Disco DeDisco
da57106d7a castanedan virtues + card 49 tweak; italic_word for trumps 19–21; sig/sea propagation — TDD
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
- migration 0016: card 49 gravity_reversal All-Bestowing → Bestowing
- migration 0017: implicit virtues (trumps 6–9) Sublimating/Sedimentary qualifiers + shared reversals (Indulged Folly / Indulgent Doing / Self-Indulgence / Indulging Personal History); explicit virtues (trumps 19–21) full-string emanation/reversal overrides (The Hunter's/Sleeper's/Quarry's etc.); canonicalize trump 7 name "Not Doing" → "Not-Doing"
- migrations 0018+0019: TarotCard.italic_word field; populated for trumps 19–21 (Stalking / Dreaming / Intent)
- _tarot_fan.html: data-italic-word + |italicize:card.italic_word filter applied to all rendered title slots
- new templatetags/tarot_filters.py: italicize(text, word) — escape-safe <em> wrapping
- StageCard JS: parse data-italic-word; new _escape / _italicize / _setTitle helpers wrap matching word in <em> via innerHTML when present (textContent otherwise)
- views.py _card_dict: include polarity-split overrides + italic_word so Sea Select stage gets them via fetch JSON
- _sig_select_overlay.html: emit the five new data-* attrs on sig-card markup so Sig Select stage picks them up via StageCard.fromDataset

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 23:36:35 -04:00
Disco DeDisco
270e48ab2c cards 48–49 polarity-split titles; sea-stage mobile breakpoints; @comment fix — TDD
- migration 0015 fills card 49 levity_reversal=The Vibrational Mould of Man, gravity_reversal=The All-Bestowing Eagle (card 48 already seeded in 0004)
- _tarot_fan.html: 4 new data-* attrs (data-levity-emanation / data-gravity-emanation / data-levity-reversal / data-gravity-reversal); upright + reversal slots render full polarity-split title in name slot when set, qualifier slots blank
- StageCard.fromDataset: parse the 4 new attrs; populateCard: emanationOverride / reversalOverride per polarity bypasses the standard name+qualifier rendering
- model: emanation_for / reversal_for fall back to name_title (group prefix stripped) instead of full self.name; reversal_for uses self.reversal_qualifier (was leftover self.reversal post-rename)
- sea-stage-content: --sig-card-w lifted from inline style to SCSS w. portrait ≤480px / landscape ≤500h breakpoints both stepping to 130px (mirrors fan modal triggers); default 180px
- _tarot_fan.html: rewrite multi-line {# #} that rendered as page text into {% comment %}{% endcomment %}

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 21:51:23 -04:00
Disco DeDisco
2f039559e6 Game Kit fan stage + FLIP/SPIN; sig/sea/fan refactor — TDD
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
- 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>
2026-04-30 21:01:52 -04:00
Disco DeDisco
d728900c24 fix Nomad icon fa-hat-cowboy → fa-hat-cowboy-side; setup_sea_session command
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
- migration 0011 ICONS dict corrected for fresh installs
- migration 0013 data fix for existing DBs (filters on old value to be safe)
- TarotCardSuitIconTest updated to assert fa-hat-cowboy-side
- setup_sea_session: single-gamer PICK SEA dev session w. pre-auth URL

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 12:07:41 -04:00
Disco DeDisco
98354fd27b PICK SEA slot interaction: cover/cross appear animation; focused glow; card bg fully opaque
- cover/cross card slots animate 0→1→resting opacity (2s) on deposit
- cover rests at 0.3; cross rests at 0.15; hover reveals to 1
- first-tap focus adds diffuse --ninUser + tight black box-shadow glow
- second tap removes --focused before _showStage() — glow dismisses as modal opens
- levity/gravity card backgrounds bumped to rgba alpha 1 (were 0.85)
- box-shadow 0.15s ease added to --visible transition for smooth glow out

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 11:47:50 -04:00
Disco DeDisco
e084bcc2d5 PICK SEA slot interaction: polarity card bg/border, cross-slot opacity fix, two-step tap; _hideOk ReferenceError removed from sea.js; Jasmine spec updated for two-step; migration 0012 PENTACLES cleanup — TDD
Some checks failed
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline failed
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 02:30:59 -04:00
Disco DeDisco
08aa4dc819 PICK SEA Sprint C: sea stage card viewer — FLIP in, SPIN/FYI, deposit/re-expand — TDD
- sea.js: SeaDeal module — openStage() shows big card viewer w. flip-in animation;
  SPIN toggles stage-card--reversed; FYI shows energies/operations (Energy/Operation
  titles, PRV/NXT nav); backdrop click deposits card to slot; click deposited slot
  re-opens stage; resetHand() clears hand on DEL
- sea_deck view: adds name_group/name_title/reversal/keywords_upright/keywords_reversed/
  energies/operations to each card dict (full sig-select stage data set)
- _sea_overlay.html: data-sea-user-polarity attr; sea stage HTML (sig-stage-card shell
  + fan-card-face-upright/reversal structure + sea-stat-block w. SPIN/FYI/PRV/NXT);
  FLIP click calls SeaDeal.openStage(); _fillPos removed (sea.js handles slot fill);
  _reset calls SeaDeal.resetHand()
- room.html: sea.js included alongside sig-select.js
- _card-deck.scss: sea-stage layout (fixed overlay, backdrop, content row); sea-stage-card
  w. @keyframes sea-flip-in (3D rotateY perspective); sea-stat-block scoped styles
  incl. SPIN/FYI btns, stat faces, sig-info FYI panel
- SeaDealSpec.js: 20 Jasmine specs — openStage, SPIN, FYI, backdrop dismiss, slot re-expand

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 01:12:06 -04:00
Disco DeDisco
2af59b3a7f tarot card icons + ranks; sig fallback for pre-sync Characters; DECKS label sizing — TDD
- migration 0011: The Nomad (0) → fa-hat-cowboy; The Schizo (1) → fa-hat-wizard
- corner_rank: non-MAJOR pip card 1 → 'A' (Ace); court unchanged (M/J/Q/K); TDD
- 17 unit model tests for corner_rank + suit_icon
- _role_select_context: my_tray_sig falls back to seat.significator when
  confirmed_char.significator is None (Characters created before natus_save sync)
- _card-deck.scss: DECKS label bigger (1rem, 0.32em letter-spacing) to fill
  stack height; sea-stack-name: opacity 0.6, scaleY(1.5), margin-top -0.4rem
  partially under face; sea-stack-face z-index:1

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 00:20:55 -04:00
Disco DeDisco
6d75b9541f PICK SEA styling: deck backs, card rank+icon display, fa-hand-dots Major Arcana — TDD
- migration 0010: icon='fa-hand-dots' for all Earthman Major Arcana number >= 2
  (Nomad/Schizo kept empty for distinct icons later)
- sea_deck view: switch from .values() to model instances; serializes corner_rank +
  suit_icon computed properties alongside DB fields
- sea overlay JS: _fillPos() renders <span class=fan-corner-rank> + <i fa-solid> HTML;
  tracks levity/gravity source via sea-card-slot--levity/gravity class; _reset() strips
  polarity classes; _showOk/_hideOk toggle sea-deck-stack--active
- template: gravity deck before levity; OK btn inside .sea-stack-face (absolute center);
  DECKS label (vertical-rl CCW) on stacks left; Gravity/Levity names under each pile
- _card-deck.scss: .sea-stacks-label (vertical-rl); .sea-stack-ok (absolute center on face);
  .sea-stack-name w. --quaUser/--terUser; glow on hover+:active+--active class —
  --ninUser for levity, --quaUser for gravity; sea-sig-card compact rank+icon display
- sea_partial view: ctx['room'] fix carried in from Sprint B

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 23:30:07 -04:00
Disco DeDisco
132e60864e PICK SEA Sprint B: deck stacks, OK btn, card draw, LOCK HAND/DEL — TDD
- _sea_overlay.html: DEAL btn replaced by two .sea-deck-stack--levity/gravity
  piles; .sea-pos-cover + .sea-pos-cross overlaid on center sig slot; LOCK HAND
  (disabled) + DEL (.btn-danger) in .sea-form-actions; data-sea-deck-url attr
- sea overlay inline JS: _fetchDeck() loads shuffled piles from sea_deck endpoint;
  stack click → _showOk(); click elsewhere → _hideOk(); OK click → _fillPos()
  in next spread-order position; DEL → _reset(); LOCK HAND enables at 6 fills
- SPREAD_ORDER constants for waite-smith + escape-velocity spread types
- sea_deck view: shuffles full equipped deck minus all seated Significators,
  splits into levity (first half) + gravity (second half) JSON arrays
- epic:sea_deck URL registered
- sea_partial view: ctx['room'] = room added (fixes NoReverseMatch for sea_deck URL)
- _card-deck.scss: .sea-card-slot--filled; .sea-pos-cover/cross absolute overlay;
  .sea-deck-stack + .sea-stack-face; .sea-form-actions layout; removed old DEAL rule
- 9 Sprint B FTs green; 3 Sprint A FTs green; 730 ITs green

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 23:02:49 -04:00
Disco DeDisco
39e12d6a3d PICK SEA Sprint A: async sky→sea transition via WS room:sky_confirmed — TDD
- natus_save: group_send room:sky_confirmed after confirm (carries seat_role)
- consumer: sky_confirmed handler rebroadcasts to room group
- _notify_sky_confirmed() helper mirrors _notify_pick_sky_available
- sea_partial view: renders _sea_overlay.html partial for in-page injection (403 if not sky_confirmed)
- epic:sea_partial URL registered
- _natus_overlay.html: data-user-seat-role attr; _onSkyConfirmed() fetches sea partial,
  removes natus overlay + backdrop, injects sea HTML, toggles sea-open on html root;
  room:sky_confirmed WS listener calls _onSkyConfirmed only for matching seat role
- user_seat_role added to SKY_SELECT context
- FT: PickSeaAsyncTransitionTest (3 tests, ChannelsFunctionalTest) — sea overlay,
  natus gone, sea-open class — all green

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 22:16:38 -04:00
Disco DeDisco
379e0ab80c character: significator field populated from seat on natus_save; my_tray_sig from Character when confirmed — TDD
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
Character.significator was already in the model but never set. natus_save now copies
seat.significator onto the Character on every save (draft + confirm). _role_select_context
overrides my_tray_sig from Character.significator when sky_confirmed, making Character
the authoritative source for the sig card displayed in the sea overlay.

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 21:46:21 -04:00
Disco DeDisco
b5fbc3d354 SIG SELECT: fix major arcana reversed face slot order — title first, qualifier second after spin — TDD
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
DOM-second flex child appears first after card rotates 180°; swap qualifier/name slot
assignments for major arcana so reversed face reads "The Schizo, / Enlightened" not
"Enlightened / The Schizo"; spec updated to document the slot-swap invariant

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 20:48:47 -04:00
Disco DeDisco
4852113fbd SIG SELECT FYI: .card-ref spans in Schizo effects; Energy/Operation singular titles; .sig-info CSS fix — TDD
- migration 0009: re-seeds The Schizo energies/operations w. .card-ref spans on all card titles
  (1. The Priest, 2. The Occultist, 2. Pestilence, 1. The Pervert, etc.)
- migration 0008: updated data constants to match (fresh-install canonical source)
- sig-select.js: title reads "Energy" / "Operation" (singular)
- _card-deck.scss: .sig-info-tooltip → .sig-info (fixes invisible panel + broken dismiss);
  Energy + Operation titles both use --quaUser (gold --terUser reserved for .card-ref spans)

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 20:44:50 -04:00
Disco DeDisco
239da7e5b1 fix ITs: update SigSelectRenderingTest for sig-info-* rename + energies/operations data attrs — TDD
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 20:25:47 -04:00
Disco DeDisco
ed55e4e529 SIG SELECT FYI: mechanisms→energies, articulations→operations; .sig-caution→.sig-info; .btn-caution→.btn-info — TDD
- TarotCard.mechanisms renamed to energies, articulations to operations (migration 0008);
  energies_json + operations_json properties replace old names
- migration 0008 also seeds The Schizo (card 1) w. 4 Energies (LIBIDO/NUMEN/VOLUPTAS×2)
  + 4 Operations (COVER/CROWN/BEHIND/BEFORE)
- FYI info panel renamed throughout: .sig-caution-* → .sig-info-*; data-mechanisms →
  data-energies; data-articulations → data-operations
- _renderCaution() now sets dynamic title (Energies/Operations) + .sig-info-title--energies/
  --operations colour modifier; type element shows entry.type (LIBIDO, COVER etc.)
- .btn-caution → .btn-info across note.js, role-select.js, specs, FT + _button-pad.scss rule
- Major arcana reversed face: card title always shown (reversal concept moves to FYI)
- SigSelectSpec.js rewritten: 242 specs; FYI describe block updated for energies/operations

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 20:22:19 -04:00
Disco DeDisco
2757ae855f SIG SELECT: non-major reversal display; face wrapper divs; middle arcana reversal seed — TDD
- sig-select.js: three-way reversal branch — major (qualifier + concept name),
  non-major w. reversal (suit qualifier word on own line + card title),
  non-major fallback (polarity qualifier only)
- template: .fan-card-face-upright + .fan-card-face-reversal wrapper divs for
  compact centred text groups; arcana label sits between them
- _card-deck.scss: wrapper divs display:flex; padding-top on reversal group
  equalises gap to MIDDLE ARCANA label on both sides; removes margin:auto overcorrect
- migration 0007: populates reversal qualifier word per suit on Earthman Middle
  Arcana court cards (Seething/Gloomy/Nervous/Vacant); clears The Schizo's
  incorrectly inherited Territoriality reversal

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 20:09:23 -04:00
Disco DeDisco
505744312b SIG SELECT sprint 1+2: SPIN animation; Emanation/Reversal; Ally Interaction FYI — TDD
Sprint 1 (template + SCSS):
- Stage card gains .fan-card-reversal-name + .fan-card-reversal-qualifier elements
  (pre-rotated 180° so they read forward after card spins); sig cards gain data-reversal attr
- _card-deck.scss: Z-axis rotate(180deg) spin on .stage-card--reversed; reversed elements
  dim @ opacity 0.25 normally, flip to 1 when card is spun; upright content dims in return
- Stat face labels: Upright→Emanation, Reversed→Reversal
- Fixture updated: Emanation/Reversal labels; reversal elements + data-reversal attr

Sprint 2 (FYI from mechanisms + articulations):
- sig-select.js: _openCaution() now parses data-mechanisms + data-articulations (concat)
  instead of data-cautions; _renderCaution() sets .sig-caution-title from entry.category,
  .sig-caution-effect.innerHTML from entry.effect; empty fallback: "No ally interactions"
- TarotCard model: mechanisms_json + articulations_json @property (parallel to cautions_json)
- Template: data-cautions→data-mechanisms+data-articulations; "Caution!"→"" title (set by JS);
  "Rival Interaction"→"Ally Interaction"; shoptalk <p> removed
- SigSelectSpec.js: all old caution tests migrated to {category,effect} dict format +
  data-mechanisms; 7-spec "FYI from mechanisms + articulations" describe block; 242 specs green

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 17:18:16 -04:00
Disco DeDisco
0522b5c126 SIG SELECT: FLIP→SPIN rename; stage-card reversal JS — TDD
- Template: FLIP btn label → SPIN; .btn-reverse class + .sig-flip-btn kept
- _button-pad.scss: .btn-reverse restyled w. cyan (--priCy/--terCy); .btn-tip
  removed; button section comments added (BIG, BYE, FYI, OK, SPIN etc.)
- sig-select.js: SPIN/FLIP handler also toggles .stage-card--reversed on
  stageCard; updateStage() populates .fan-card-reversal-name (data-reversal)
  + .fan-card-reversal-qualifier (polarity qualifier); resets .stage-card--reversed
  on each new hover — TDD
- SigSelectSpec.js: SPIN card animation describe block (7 specs); spec
  descriptions updated FLIP→SPIN; fixture gains reversal elements +
  data-reversal attr; 235 Jasmine specs green

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 16:51:53 -04:00
Disco DeDisco
759ce8d3e4 fix CI FT regressions: deck contribution, ROLE SELECT no-deck guard, sig qualifiers, Carte Blanche multi-slot
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
- test_deck_contribution: get_or_create _equip_earthman + unlocked_decks.add; slot_number=2 on
  _setup_in_use_deck seat; navigate to /gameboard/ (not gate — game-kit panel absent there);
  drop #id_kit_card_deck click ({% empty %} placeholder; deck renders in loop when present);
  use textContent for CSS-hidden tooltip; drop stale .deck-micro-status assertion (now mini-portal)
- ROLE SELECT FTs (RoleSelectTest + RoleSelectTrayTest): equip Earthman deck for active-slot
  user in each test that opens the fan — fixes no-deck JS guard blocking #id_role_select
- test_room_sig_select: seed The Nomad/Schizo w. correct Earthman slugs/names + Enlightened/
  Engraven qualifiers; grant super-nomad + super-schizo Notes to all gamers so Major Arcana
  appear in overlay; seed Middle Arcana w. Elevated/Graven qualifiers; rename test methods
- test_game_kit: drop stale assertIn("active", text) — availability moved to In-Use mini-portal
- Carte Blanche: CB stays equipped after multi-slot deposit (revert drop_token unequip);
  select_role existing-seat query gains order_by("slot_number") for deterministic primary seat;
  multi-slot FT: kit bag shows placeholder after first deposit (CB unequipped); cold-feet
  verifies DON via hover→portal; re-equip via portal DON before re-deposit; new
  test_carte_in_use_game_kit_shows_room_attribution checks Game Kit tooltip after deposit

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 16:29:51 -04:00
Disco DeDisco
6ad736413b super-schizo + super-nomad Notes: auto-grant to superusers; sig unlock; navbar titles — TDD
- drama/models.py: _NOTE_DISPLAY dict; Note.display_title / .display_greeting
  properties; super-schizo → "21st Century" + "Schizoid Man";
  super-nomad → "Howdy," + "Stranger"
- billboard/views.py: _NOTE_META super-schizo/nomad entries with mark_safe
  HTML descriptions ("card-ref"-styled card names), swatch_label "I"/"0",
  no palette_options; swatch_label added to note_items context
- lyric/models.py post_save: new superusers get super-schizo + super-nomad
  Notes automatically; setup_sig_session grants them explicitly too
- epic/models.py _filter_major_unlocks: accepts super-nomad / super-schizo
  as valid unlocks alongside their plain counterparts
- _navbar.html: display_greeting|safe + display_title replace slug|capfirst
- my_notes.html: note-item__image-box--label branch for swatch_label
- _note.scss: .note-item__image-box--label modifier (bold italic, solid border)
- _base.scss: .ord global ordinal superscript class (21st etc.)
- ITs: SuperuserNoteGrantTest (3); SigSelectRenderingTest +2 (super- variants)

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 01:30:02 -04:00
Disco DeDisco
1c2b8f96ab SIG SELECT: Nomad/Schizo locked by default; Note-unlock gate — TDD
- _filter_major_unlocks(cards, user): strips Major 0 (Nomad) and Major 1
  (Schizo) unless user has matching 'nomad'/'schizo' Note; unauthenticated
  users see 0 majors
- levity_sig_cards(room, user) / gravity_sig_cards(room, user): accept user
  param; default 16 court cards, up to 18 with both Note unlocks
- View wires user into both calls; _sig_unique_cards / sig_deck_cards unchanged
  (game-table deck still includes all 18 unique)
- _full_sig_setUp: seats now carry deck_variant=earthman
- SigCardHelperTest: 4 new ITs (default 16, nomad +1, schizo +1); empty-deck
  test updated to clear seats + owner
- SigSelectRenderingTest: 18-card test updated to 16-default + 3 Note-unlock ITs

Pending: superusers auto-granted nomad + schizo Notes on creation (ask user)

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 01:05:25 -04:00
Disco DeDisco
eaff2a1edb setup_sig_session: wire deck contributions; _room_deck_variant replaces owner.equipped_deck
- setup_sig_session: drop _ensure_earthman() (deck seeded by migration); set
  deck_variant=earthman on all TableSeats; users get unlocked_decks add but
  equipped_deck=None (seat owns the deck); docstring documents role-pair mapping
- _room_deck_variant(room): new helper looks up deck from any seated deck_variant,
  falls back to owner.equipped_deck for legacy rooms
- sig_deck_cards / _sig_unique_cards: use _room_deck_variant instead of
  owner.equipped_deck — sig cards now work even when users have unequipped their deck
  after role confirmation

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 00:45:22 -04:00
Disco DeDisco
e512e94056 ROLE SELECT: block role pick without deck; SigSelect qualifier spec fix — TDD
- role-select.js: _showNoDeckWarning(stack) intercepts at openFan() — fan never
  opens when data-equipped-deck=""; warning positioned fixed over card-stack via
  getBoundingClientRect(); .guard-actions wrapper for FYI/.btn-caution + NVM/.btn-cancel
- room.html: card-stack gains data-equipped-deck="{{ equipped_deck_id|default:'' }}"
- room view context: equipped_deck_id added
- _room.scss: .role-no-deck-warning — glass guard style matching #id_guard_portal
- _base.scss + _room.scss: guard portal + no-deck warning opacity 0.5 → 0.75
  (matches .tt tooltip; light-palette handled via --tooltip-bg CSS var)
- RoleSelectSpec.js: 8 Jasmine specs — no-deck (fan blocked, warning, FYI/NVM,
  no duplicate, no POST) + deck-present pass-through; afterEach cleans up warning
- SigSelectSpec.js: card fixture gains data-levity-qualifier + data-gravity-qualifier;
  all "Leavened" expectations updated to "Elevated"

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 23:52:22 -04:00
Disco DeDisco
fa68c74b51 deck contribution sprint 2 + Carte Blanche safeguards — TDD
Sprint 2 UI (game kit applet):
- _applet-game-kit.html: in-use deck → two disabled × buttons, .tt-deck-game-name;
  in-use Carte Blanche → two disabled × buttons, data-current-room-name,
  .tt-token-room-name; tooltip content mirrors kit bag panel (Default, card count,
  description, Stock version)
- gameboard.js buildMiniContent: 'In-Use' for tokens w. data-current-room-name set
- _kit_bag_panel.html: Deck section always renders (placeholder when unequipped)

View safeguards:
- select_role: look up existing deck from prior seat in same room before
  equipped_deck (Carte Blanche multi-seat); only unequip when using equipped_deck
- drop_token Carte: reject 409 if token.current_room is a different room;
  unequip from equipped_trinket on drop

ITs: SelectRoleMultiSeatTest (2), DropTokenViewTest +3 (carte drop, unequip, lock)

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 23:24:43 -04:00
Disco DeDisco
94a864b05b deck contribution sprint 1: TableSeat.deck_variant FK + select_role wiring — TDD
- epic.TableSeat gains deck_variant FK → DeckVariant (nullable, SET_NULL)
- select_role view assigns request.user.equipped_deck to seat on role confirmation
- Migration 0006_add_deck_variant_to_tableseat
- ITs: test_select_role_assigns_equipped_deck_to_seat,
       test_select_role_no_deck_leaves_deck_variant_null

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 22:38:07 -04:00
Disco DeDisco
42be0c63dc SIG SELECT: read qualifiers from model fields; drop hardcoded Leavened/Graven
- _sig_select_overlay.html: add data-levity-qualifier + data-gravity-qualifier
  to sig card elements so JS can read per-card values
- sig-select.js: derive qualifier from cardEl.dataset instead of hardcoded string
- _sea_overlay.html: use my_tray_sig.levity_qualifier / gravity_qualifier;
  collapse MIDDLE/MAJOR/else branches → MAJOR vs rest (all non-major show
  qualifier above name; empty qualifier renders empty <p>)
- views.py: SIG READY event display uses card qualifier fields directly;
  removes separate MIDDLE / MAJOR / else branches

Earthman courts now show Elevated/Graven; pips show Relieving/Grieving;
Nomad and Popes show Enlightened/Engraven.

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 22:33:42 -04:00
Disco DeDisco
fd94a72435 Earthman deck seed: Nomad gets Enlightened/Engraven; minor qualifiers Relieving/Grieving, Elevated/Graven
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
- Card 0 (The Nomad): levity_qualifier=Enlightened, gravity_qualifier=Engraven — mirrors the Popes
- Minor arcana pips (1–10): Relieving / Grieving
- Middle arcana courts (11–14): Elevated / Graven (replaces incorrect Leavened)

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 21:33:47 -04:00
Disco DeDisco
2b4f20c0e8 collapse migrations: 41 epic + 20 lyric + 12 applets + others → fresh initials + 4 themed seeds
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
- Delete all incremental migration files across all apps; regenerate 0001_initial.py
  per app via makemigrations (schema unchanged, no model edits)
- applets/0003_seed_applets.py: all 20 Applet rows in one migration
- epic/0003_seed_fiorentine_deck.py: Fiorentine Minchiate DeckVariant + 78 cards
- epic/0004_seed_earthman_deck.py: Earthman DeckVariant + 50 major + 56 minor/middle
  arcana (106 cards); stray PENTACLES courts absent — clean from the start
- epic/0005_seed_astro_reference_tables.py: 12 signs, 10 planets, 9 aspect types
  (incl. Semisquare + Sesquiquadrate), 12 house labels
- 706 ITs green on fresh DB

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 21:06:23 -04:00
Disco DeDisco
e2c9dc4e8a Earthman deck: delete stray Pentacles courts; fix tarot_fan suit order
- Migration 0041: delete Maid/Jack/Queen/King of Pentacles (suit=PENTACLES,
  arcana=MINOR, numbers 11-14) from Earthman deck — duplicates of the correct
  CROWNS courts that already exist; escaped migration 0024's rename sweep
- tarot_fan view: _suit_order now uses Earthman suit names (BRANDS/GRAILS/BLADES/CROWNS)
  in correct display order; old Fiorentine names kept as fallback

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 20:48:12 -04:00
Disco DeDisco
c3f0342a2d Earthman deck: new TarotCard fields + full 49-card major arcana reseed
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
- TarotCard: add reversal, levity/gravity_qualifier, levity/gravity_emanation, levity/gravity_reversal, mechanisms, articulations; emanation_for(polarity) + reversal_for(polarity) methods
- 0035: schema migration for new fields
- 0036: reseed major arcana — 52 cards → 50 (Nomad untouched); delete Wheel of Fortune/Junkboat/Great Hunt; insert Asteroid Belt; rename/renumber all into Pope/Horseman, Elements, Realms, Virtues, Zodiac, Lunars, Planets, Inner Rings; levity/gravity qualifiers throughout; cards 48-49 polarity-split levity/gravity emanation + reversal
- 0037: Polestar qualifiers → Precessional / Recessional
- 0038: correspondences → Fiorentine card names (Magician–Hierophant for 1-5; sign names for zodiac 22-33)
- 0039: reversals — Pope/Horseman 1-5 → Territoriality/Despotism/Capitalism/Fascism; Zodiac 22-33 → House of Self … House of Reprisal
- 0040: trump 21 → Intent (was Jovent)

⚠ pending: cards 1-2 reversal both 'Territoriality' — confirm if distinct; Implicit/Explicit Virtue qualifiers blank

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 01:51:40 -04:00
Disco DeDisco
7fcb6f307c PICK SEA: modal w. Celtic Cross layout + spread select; PICK SKY swaps to PICK SEA after sky save — TDD
- _role_select_context: at SKY_SELECT, compute sky_confirmed (confirmed Character exists for seat) + user_polarity
- room.html: PICK SEA btn + _sea_overlay.html when sky_confirmed; PICK SKY + natus overlay otherwise
- _sea_overlay.html: transparent cards col (6-position cross, Sig at center) left; priUser form col (spread select) right; NVM cancel; JS open/close via html.sea-open
- _natus.scss: .sea-* rules mirror natus layout w. reversed columns; crossing slot rotated; dotted empty slots; sig slot solid; width/max-width replaces min() to avoid rem+vw unit mix
- select defaults: "Celtic Cross, Waite-Smith" for levity (PC/NC/SC); "Celtic Cross, Escape Velocity" for gravity (EC/AC/BC)

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 21:30:27 -04:00
Disco DeDisco
04f0e87eba fix shadowed test classes restoring 41 dead tests; add missing coverage
SigReserveViewTest, SigReadyViewTest, SigConfirmViewTest each defined twice
in test_views.py — second (shorter) definition silently shadowed the first
comprehensive set, so ~180 lines of tests never ran.

- remove three duplicate class definitions (lines 1648–1749)
- absorb unique tests from shadowed copies: non-POST 405 guards for all
  three views; idempotent-ready path; invalid seconds_remaining fallback
- add test_release_while_ready_records_sig_unready (lines 667–679)
- add TarotDealViewTest for tarot_deal non-POST redirect (line 904)
- 609 → 650 tests, all green

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 15:56:36 -04:00
Disco DeDisco
7c249500bd refactor: extract apply_applet_toggle, rooms_for_user & natus helpers to utils; DRY toggle views
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
- epic/utils.py (new): _planet_house, _compute_distinctions, rooms_for_user
- applets/utils.py: apply_applet_toggle replaces 5 copy-pasted toggle loops
- dashboard/views.py: use apply_applet_toggle; fix double free_tokens/tithe_tokens query in wallet(); promote _compute_distinctions import to module level
- gameboard/views.py: use apply_applet_toggle & rooms_for_user; fix double free_tokens query in toggle_game_applets
- billboard/views.py: use apply_applet_toggle & rooms_for_user
- SCSS: %tt-token-fields placeholder in _tooltips.scss; _gameboard & _game-kit @extend it
- epic/tests/unit/test_utils.py (new): coverage for _planet_house fallback path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 15:46:30 -04:00
Disco DeDisco
758c9c5377 COVERAGE: patch 91% → 96%+ — 603 tests, tasks.py at 100%
New/extended tests across billboard, dashboard, drama, epic, gameboard,
and lyric to cover previously untested branches: dev_login view, scroll
position endpoints, sky preview error paths, drama to_prose/to_activity
branches, consumer broadcast handlers, tarot deck draw/shuffle, astrology
model __str__, character model, sig reserve/ready/confirm views, natus
preview/save views, and the full tasks.py countdown scheduler.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:23:28 -04:00
Disco DeDisco
2910012b67 PICK SKY: natal wheel planet tooltips + FT modernisation
- natus-wheel.js: per-planet <g> group with data-planet/sign/degree/retrograde
  attrs; mouseover/mouseout on group (pointer-events:none on child text/℞ so
  the whole apparatus triggers hover); tooltip uses .tt-title/.tt-description;
  in-sign degree via _inSignDeg() (ecliptic % 30); D3 switched from CDN to
  local d3.min.js
- _natus.scss: .nw-planet--hover glow; #id_natus_tooltip position:fixed z-200
- _natus_overlay.html: tooltip div uses .tt; local d3.min.js script tag
- T3/T4/T5 converted from Selenium execute_script to Jasmine unit tests
  (NatusWheelSpec.js) — NatusWheel was never defined in headless GeckoDriver;
  SpecRunner.html updated to load D3 + natus-wheel.js
- test_pick_sky.py: NatusWheelTooltipTest removed (replaced by Jasmine)
- test_component_cards_tarot / test_trinket_carte_blanche: equip assertions
  updated from legacy .equip-deck-btn/.equip-trinket-btn mini-tooltip pattern
  to current DON|DOFF (.btn-equip in main portal); mini-portal text assertions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 01:57:02 -04:00
Disco DeDisco
6248d95bf3 PICK SKY overlay: D3 natal wheel, Character model, PySwiss aspects+tz
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
PySwiss:
- calculate_aspects() in calc.py (conjunction/sextile/square/trine/opposition with orbs)
- /api/tz/ endpoint (timezonefinder lat/lon → IANA timezone)
- aspects included in /api/chart/ response
- timezonefinder==8.2.2 added to requirements
- 14 new unit tests (test_calc.py) + 12 new integration tests (TimezoneApiTest, aspect fields)

Main app:
- Sign, Planet, AspectType, HouseLabel reference models + seeded migrations (0032–0033)
- Character model with birth_dt/lat/lon/place, house_system, chart_data, celtic_cross,
  confirmed_at/retired_at lifecycle (migration 0034)
- natus_preview proxy view: calls PySwiss /api/chart/ + optional /api/tz/ auto-resolution,
  computes planet-in-house distinctions, returns enriched JSON
- natus_save view: find-or-create draft Character, confirmed_at on action='confirm'
- natus-wheel.js: D3 v7 SVG natal wheel (elements pie, signs, houses, planets, aspects,
  ASC/MC axes); NatusWheel.draw() / redraw() / clear()
- _natus_overlay.html: Nominatim place autocomplete (debounced 400ms), geolocation button
  with reverse-geocode city name, live chart preview (debounced 300ms), tz auto-fill,
  NVM / SAVE SKY footer; html.natus-open class toggle pattern
- _natus.scss: Gaussian backdrop+modal, two-column form|wheel layout, suggestion dropdown,
  portrait collapse at 600px, landscape sidebar z-index sink
- room.html: include overlay when table_status == SKY_SELECT

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 02:09:26 -04:00
Disco DeDisco
0a135c2149 implemented sig_confirm view: guards (403 unseated, 400 wrong phase, 400 not-all-ready), significator assignment from reservations, polarity_room_done + pick_sky_available broadcasts, SKY_SELECT advance when both polarities done
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 13:00:16 -04:00
Disco DeDisco
32d8d97360 wired PICK SKY server-side polarity countdown via threading.Timer (tasks.py); fixed polarity_done overlay gating on refresh; cleared sig-select floats on overlay dismiss; filtered Redact events from Most Recent applet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 00:34:05 -04:00
Disco DeDisco
df421fb6c0 added PICK SKY ready gate: SigReservation.ready + countdown_remaining fields, Room.SKY_SELECT status + sig_select_started_at, sig_ready + sig_confirm views, WS notifiers for countdown_start/cancel/polarity_room_done/pick_sky_available, migration 0031, PICK SKY btn in hex center at SKY_SELECT, tray cell 2 sig card placeholder; FTs SRG1-8 written (pending JS/consumer)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 01:17:24 -04:00
Disco DeDisco
3800c5bdad fixed attribution of .fa-hand-pointer cursor color scheme to ordering according to token-drop sequence instead of seat sequence; updates to accomodate this throughout apps.epic.models & .views, plus new apps.epic migration; assigned #id_sig_cursor_portal a z-index value corresponding to a high position but still beneath the #id_tray apparatus; minor semantic reordering of INSTALLED_APPS in core.settings
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-08 22:53:44 -04:00
Disco DeDisco
cf40f626e6 Sig select: _card-deck.scss extract, WS cursor fixes, own-role indicators, role icon refresh
- New _card-deck.scss: sig select styles moved out of _room.scss + _game-kit.scss
- sig-select.js: 3 WS bug fixes — thumbs-up deferred to window.load (layout settled
  before getBoundingClientRect), hover cursor cleared for all cards on reservation
  (not just the reserved card), applyHover guards against already-reserved roles
- Own-role indicators: gamer now sees their own role-coloured card outline + thumbs-up
- Reservation glow: replaced blurry role+ninUser double-shadow with crisp 2px outline
- Gravity qualifier: Graven text set to --terUser (matches Leavened/--quiUser pattern)
- Role card SVGs refreshed; starter-role-Blank removed
- FTs + Jasmine specs extended for sig select WS behaviour
- setup_sig_session management command for multi-browser manual testing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 11:52:49 -04:00
Disco DeDisco
520fdf7862 Sig select: caution tooltip, FLIP/FYI stat block, keyword display
- TarotCard.cautions JSONField + cautions_json property; migrations
  0027–0029 seed The Schizo (number=1) with 4 rival-interaction cautions
  (Roman-numeral card refs: I. The Pervert / II. The Occultist, etc.)
- Sig-select overlay: FLIP (stat-block toggle) + FYI (caution tooltip)
  buttons; nav PRV/NXT portaled outside tooltip at bottom corners (z-70);
  caution tooltip covers stat block (inset:0, z-60, Gaussian blur);
  tooltip click dismisses; FLIP/FYI fully dead while btn-disabled;
  nav wraps circularly (4/4 → 1/4, 1/4 → 4/4)
- SCSS: btn-disabled specificity fix (!important); btn-nav-left/right
  classes; sig-caution-* layout; stat-face keyword lists
- Jasmine suite expanded: stat block + FLIP (5 specs), caution tooltip
  (16 specs) including wrap-around and disabled-button behaviour
- IT tests: TarotCardCautionsTest (5), SigSelectRenderingTest (8)
- Role-card SVG icons added to static/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 00:22:04 -04:00
Disco DeDisco
e2cc38686f XL landscape: revert tray to landscape style; fix sig-stage stretch
- Remove _tray.scss XL (≥1800px) portrait override block entirely
- _isLandscape() no longer returns false at ≥1800px — tray uses
  landscape slide-from-top at all wide landscape widths
- sig-stage: align-self: stretch (was center) so JS sizeSigCard()
  measures correct stage width; card size no longer collapses
- Position strip: horizontal row at top (was vertical column-reverse)
- sig-overlay/sig-stage/sig-deck-grid layout polish at 1100px/1800px

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 20:11:24 -04:00
Disco DeDisco
0bcc7567bb XL landscape polish: btn-primary sizing, tray from right, footer bg, layout fixes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- .btn-xl removed; .btn-primary absorbs 4rem sizing (same as PICK SIGS/PICK ROLES)
- Landscape navbar .btn-primary: 3rem → 4rem to match base; XL stays 4rem (consistent)
- _button-pad.scss XL: base .btn ×1.2 (2.4rem); .btn-xl block deleted
- _tray.scss XL (≥1800px): portrait-style tray (slides from right, z-95)
- tray.js: _isLandscape() returns false at ≥1800px; portrait code paths run throughout
- Footer sidebar: background-color added so opaque footer masks tray sliding behind it
- Copyright .footer-container: bottom → top in landscape sidebar
- #id_room_menu: right: 2.5rem override in _room.scss XL block (cascade fix)
- navbar-text XL: 0.65rem × 1.2 = 0.78rem
- All landscape media queries: max-width: 1440px cutoff removed (already done prior)
- btn-xl class stripped from all 5 templates; test_navbar.py assertion updated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 03:02:37 -04:00
Disco DeDisco
6654785f25 XL landscape breakpoint (≥1800px): double sidebar widths + scale content
- _base.scss: new @media (orientation:landscape) and (min-width:1800px) block —
  sidebars 4rem→8rem; navbar btn 3rem→5rem; brand h1 1.2rem→2.4rem; navbar-text
  0.65rem→1.3rem; footer icons 1.75rem→3rem; nav gap 3rem→4rem; footer-container
  0.55rem→0.85rem; container margins 4rem→8rem; h2 portrait-style (2rem, centred)
- _applets.scss: gear btn right 0.5rem→2.5rem; menus right 0.5rem→2rem at ≥1800px
- _game-kit.scss: kit btn right 0.5rem→2.5rem at ≥1800px
- _room.scss: sig-overlay padding-left 4rem→8rem at ≥1800px
- _tray.scss: tray wrap left/right 4rem→8rem at ≥1800px
- room.js: sizeSigModal right inset 64px→128px at ≥1800px viewport width

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 01:41:18 -04:00
Disco DeDisco
99a69202b9 landscape layout: remove max-width cutoff; sig-select stage/grid polish
- All landscape @media queries: drop and (max-width: 1440px) — sidebar layout
  now activates for all landscape orientations regardless of viewport width
- _base.scss landscape container: add max-width:none to override the
  @media(min-width:1200px) rule and fill the full space between sidebars
- sig-select sig-deck-grid: landscape now 9×2 @ 3rem cards; 18×1 at ≥1100px
  (bumped from 992px to avoid last-card clip); card text scales with --sig-card-w
- sig-stat-block: flex:1→flex:0 0 auto with width:--sig-card-w so it matches
  preview card dimensions instead of stretching across the full stage
- room.js sizeSigModal: landscape card width clamped to [90px, 160px]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 01:30:31 -04:00
Disco DeDisco
55bb450d27 z-index audit + aperture fill + resize:end debounce + landscape sig-grid cap
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- #id_aperture_fill: position:fixed→absolute (clips to .room-page, avoids h2/navbar);
  z-index 105→90 (below blur backdrops at z-100); landscape override removed (inset:0 works both orientations)
- _base.scss: landscape footer z-index:100 (matches navbar); corrects unset z-index
- _room.scss: fix stale "navbar z-300" comment; landscape sig-deck-grid columns
  repeat(9,1fr)→repeat(9,minmax(0,90px)) to cap card size on wide viewports
- room.js: add resize:end listeners for scaleTable + sizeSigModal; new IIFE dispatches
  resize:end 500ms after resize stops so both functions re-measure settled layout
- tray.js: extract _reposition() from inline resize handler; wire to both resize and
  resize:end so tray repositions correctly after rapid resize or orientation change

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 00:48:25 -04:00