PICK SKY: natal wheel polish — house/sign fill fixes, button layout, localStorage FT
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful

- Fix D3 arc coordinate offset (add π/2 to all arc angles — D3 subtracts it
  internally, causing fills to render 90° CW from label midpoints)
- Fix house-12 wrap-around: normalise nextCusp += 360 when it crosses 0°,
  eliminating the 330° ghost arc that buried house fill/number layers
- Draw all house fills before cusp lines + numbers (z-order fix)
- SCSS: sign/element fills corrected to rgba(var(--priXx, R, G, B), α) —
  CSS vars are raw RGB tuples so bare var() in fill was invalid
- brighten Stone/Air/Water fallback colours; raise house fill opacities
- Button layout: SAVE SKY moves into form column (full-width, pinned bottom);
  NVM becomes a btn-sm circle anchored on the modal's top-right corner via
  .natus-modal-wrap (position:relative, outside overflow:hidden modal);
  entrance animation moved to wrapper so NVM rides the fade+slide
- Form fields wrapped in .natus-form-main (scrollable); portrait layout
  switches form-col to flex-row so form spans most width, SAVE SKY on right
- Modal max-height 92→96vh, max-width 840→920px, SVG cap 400→480px
- FT: PickSkyLocalStorageTest (2 tests) — form fields restored after NVM
  and after page refresh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-04-15 00:49:14 -04:00
parent 6248d95bf3
commit 9beb21bffe
4 changed files with 426 additions and 175 deletions

View File

@@ -62,34 +62,42 @@ html.natus-open .natus-overlay {
// ── Modal panel ───────────────────────────────────────────────────────────────
.natus-modal {
pointer-events: auto;
display: flex;
flex-direction: column;
// Thin wrapper: position:relative so the NVM circle can sit on the corner
// without being clipped by the modal's overflow:hidden.
.natus-modal-wrap {
position: relative;
pointer-events: none; // overlay handles pointer-events; children re-enable
width: 92vw;
max-width: 840px;
max-height: 92vh;
border: 0.1rem solid rgba(var(--terUser), 0.25);
border-radius: 0.5rem;
background: rgba(var(--priUser), 1);
overflow: hidden;
max-width: 920px;
// Fade + slide in
// Fade + slide in — wraps modal AND NVM btn so both animate together
opacity: 0;
transform: translateY(1rem);
transition: opacity 0.2s ease, transform 0.2s ease;
}
html.natus-open .natus-modal {
html.natus-open .natus-modal-wrap {
opacity: 1;
transform: translateY(0);
}
.natus-modal {
pointer-events: auto;
display: flex;
flex-direction: column;
width: 100%; // fills .natus-modal-wrap
max-height: 96vh;
border: 0.1rem solid rgba(var(--terUser), 0.25);
border-radius: 0.5rem;
overflow: hidden;
}
// ── Header ────────────────────────────────────────────────────────────────────
.natus-modal-header {
flex-shrink: 0;
padding: 0.6rem 1rem;
background: rgba(var(--priUser), 1);
border-bottom: 0.1rem solid rgba(var(--terUser), 0.15);
display: flex;
flex-direction: row;
@@ -121,17 +129,33 @@ html.natus-open .natus-modal {
overflow: hidden;
}
// Form column — fixed width, scrollable
// Form column — fixed width; form-main scrolls, confirm btn pinned at bottom
.natus-form-col {
flex: 0 0 240px;
overflow-y: auto;
overflow: hidden;
padding: 0.9rem 1rem;
background: rgba(var(--priUser), 1);
border-right: 0.1rem solid rgba(var(--terUser), 0.12);
display: flex;
flex-direction: column;
gap: 0.65rem;
}
// Scrollable inner container (form fields + status)
.natus-form-main {
flex: 1;
min-height: 0;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 0.65rem;
}
// Confirm btn inside form-col — full width, pinned at column bottom
.natus-form-col > #id_natus_confirm {
flex-shrink: 0;
}
// Wheel column — fills remaining space
.natus-wheel-col {
flex: 1;
@@ -140,7 +164,7 @@ html.natus-open .natus-modal {
align-items: center;
justify-content: center;
padding: 0.75rem;
background: rgba(var(--priUser), 0.5);
// background: rgba(var(--duoUser), 1);
position: relative;
}
@@ -149,8 +173,8 @@ html.natus-open .natus-modal {
width: 100%;
height: 100%;
aspect-ratio: 1 / 1;
max-width: 400px;
max-height: 400px;
max-width: 480px;
max-height: 480px;
}
// ── Form fields ───────────────────────────────────────────────────────────────
@@ -270,22 +294,29 @@ html.natus-open .natus-modal {
}
}
// ── Footer ────────────────────────────────────────────────────────────────────
// ── NVM corner btn ────────────────────────────────────────────────────────────
// Absolutely pinned to top-right corner of .natus-modal-wrap.
// transform: translate(50%,-50%) centres the circle on the corner point.
// Lives outside .natus-modal so overflow:hidden doesn't clip it.
.natus-modal-footer {
flex-shrink: 0;
padding: 0.6rem 1rem;
border-top: 0.1rem solid rgba(var(--terUser), 0.15);
display: flex;
justify-content: flex-end;
gap: 0.5rem;
#id_natus_cancel {
position: absolute;
top: 0;
right: 0;
transform: translate(50%, -50%);
z-index: 10;
margin: 0;
pointer-events: auto;
}
// ── Narrow / portrait ─────────────────────────────────────────────────────────
@media (max-width: 600px) {
.natus-modal-wrap {
width: 92vw;
}
.natus-modal {
width: 96vw;
max-height: 96vh;
}
@@ -294,10 +325,28 @@ html.natus-open .natus-modal {
overflow-y: auto;
}
// Form col stacks above wheel; internally becomes a flex-row so
// form-main gets most of the width and confirm btn sits to its right.
.natus-form-col {
flex: 0 0 auto;
flex-direction: row;
align-items: flex-end;
border-right: none;
border-bottom: 0.1rem solid rgba(var(--terUser), 0.12);
overflow: visible; // form-main handles its own scroll
gap: 0.5rem;
}
.natus-form-main {
flex: 1;
min-width: 0;
overflow-y: auto;
max-height: 40vh;
}
.natus-form-col > #id_natus_confirm {
flex-shrink: 0;
align-self: flex-end;
}
.natus-wheel-col {
@@ -305,6 +354,55 @@ html.natus-open .natus-modal {
}
}
// ── SVG wheel element styles ──────────────────────────────────────────────────
// Colors and opacity live here; geometry (cx/cy/r/font-size) stays in JS.
.nw-outer-ring {
fill: none;
stroke: rgba(var(--quaUser), 0.6);
stroke-width: 1px;
}
.nw-inner-disc {
fill: rgba(var(--quaUser), 0.6);
}
// Axes (ASC / DSC / MC / IC)
.nw-axis-line { stroke: rgba(var(--secUser), 1); stroke-width: 1.5px; }
.nw-axis-label { fill: rgba(var(--secUser), 1); }
// Sign ring — vars are RGB tuples ("R, G, B"), must be wrapped in rgba()
.nw-sign--fire { fill: rgba(var(--priRd, 192, 64, 64), 0.75); stroke: rgba(var(--quaUser), 1); stroke-width: 0.5px; }
.nw-sign--stone { fill: rgba(var(--priFs, 122, 96, 64), 0.75); stroke: rgba(var(--quaUser), 1); stroke-width: 0.5px; }
.nw-sign--air { fill: rgba(var(--priCy, 64, 144, 176), 0.75); stroke: rgba(var(--quaUser), 1); stroke-width: 0.5px; }
.nw-sign--water { fill: rgba(var(--priId, 80, 80, 160), 0.75); stroke: rgba(var(--quaUser), 1); stroke-width: 0.5px; }
.nw-sign-label { fill: rgba(var(--secUser), 1); }
// House ring
.nw-house-cusp { stroke: rgba(var(--quaUser), 0.8); stroke-width: 0.8px; }
.nw-house-num { fill: rgba(var(--quiUser), 1); }
.nw-house-fill--even { fill: rgba(var(--quaUser), 0.45); }
.nw-house-fill--odd { fill: rgba(var(--quiUser), 0.35); }
// Planets
.nw-planet-circle { fill: rgba(var(--quiUser), 1); }
.nw-planet-circle--rx { fill: rgba(var(--quiUser), 1); }
.nw-planet-label { fill: rgba(var(--quaUser), 1); stroke: rgba(var(--quaUser), 0.6); stroke-width: 0.4px; paint-order: stroke fill; }
.nw-rx { fill: rgba(var(--terUser), 1); }
// Aspects
.nw-aspects { opacity: 0.8; }
// Element pie
.nw-element--fire { fill: rgba(var(--priRd, 192, 64, 64), 0.92); stroke: rgba(var(--quaUser), 1); stroke-width: 0.5px; }
.nw-element--stone { fill: rgba(var(--priFs, 122, 96, 64), 0.92); stroke: rgba(var(--quaUser), 1); stroke-width: 0.5px; }
.nw-element--air { fill: rgba(var(--priCy, 64, 144, 176), 0.92); stroke: rgba(var(--quaUser), 1); stroke-width: 0.5px; }
.nw-element--water { fill: rgba(var(--priId, 80, 80, 160), 0.92); stroke: rgba(var(--quaUser), 1); stroke-width: 0.5px; }
// Time / Space emergent labels
.nw-element-label--time { fill: rgba(var(--priYl, 192, 160, 48), 1); }
.nw-element-label--space { fill: rgba(var(--priGn, 64, 96, 64), 1); }
// ── Sidebar z-index sink (landscape sidebars must go below backdrop) ───────────
@media (orientation: landscape) {