natus wheel: aspect line system, element tooltip overhaul, ring/spoke changes — TDD
- DON/DOFF toggle: aspect lines persist across planet switches & outside clicks; cleared only by DON (new planet) or DOFF; planet-keyed --asp-* colors (--sixU/--terU on light palettes) - planet tooltip: aspect rows w. 2× thick line legend, planet symbol + .tt-asp-in 'in' + sign icon + orb; applying/separating direction symbols - element tooltip: 80px square badge (float right); DON/DOFF hidden; symbol-based contributor rows (☉ @ 15.3° ♈ +1); Stellium/Parade +N underlined headers; parade sign-grouped w. parenthetical planet symbols, counterclockwise order - ring swap: planets outer (0.50–0.68r), houses inner (0.32–0.48r) to reduce stellia crowding - house spokes: angle cusps only (ASC/IC/DSC/MC); non-angle spokes removed - outside-click guard: bounding-rect check for DON/DOFF/PRV/NXT so pointer-events:none buttons don't trigger close - add element-square & energy-vector icon dirs (Ardor/Ossum/Tempo/Nexus/Pneuma/Humor SVGs) - T11a–f Jasmine specs for DON/DOFF line persistence Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 575.92 576.62">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #007e6e;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #02b8a1;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-3" d="M60.91,511.29l71.65-136.9,97.75-187.79,63.33-121.28,125.49,240.37,107.55,205.57-465.77.03ZM356.95,428.87c-13.35.49-27.13-3.86-27.46-15.87l-.93-32.96c-.02-.56,1.33-1.81,1.58-1.95l28.47-.06,2.82-17.62-32.06-.11-.81-2.11.21-137.2-16.05.25-59.68,85.59-41.14,59.57,1.32,11.65,89.23.02-.35,32.7c-.16,14.62-13.39,18.37-27.93,18.17v9.04s83.05-.03,83.05-.03l-.26-9.06Z"/>
|
||||
<polygon class="cls-2" points="49.23 509.31 76.73 394.84 282.73 65.32 49.23 509.31"/>
|
||||
<path class="cls-1" d="M356.95,428.87l.26,9.06-83.05.03v-9.04c14.54.2,27.77-3.55,27.93-18.17l.35-32.7-90.55-.02v-11.65l41.14-59.57,59.68-85.59,16.05-.25-.21,137.2.81,2.11,32.06.11-2.82,17.62-28.47.06c-.24.14-1.59,1.4-1.58,1.95l.93,32.96c.34,12.01,14.12,16.36,27.46,15.87ZM302.55,360.36l-.29-103.19-70.06,103.09,70.35.1Z"/>
|
||||
<polygon class="cls-3" points="302.55 360.36 232.2 360.25 302.26 257.17 302.55 360.36"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 575.92 576.62">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #ed1f81;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #9d1d59;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-2" d="M451.82,504.82H53.65s.04-433.24.04-433.24h398.13s0,433.24,0,433.24ZM314.3,279.4c-25.3-32.05-69.43-29.71-101.12-5.51,11.97-52.09,51.89-98.16,106.46-99.95l.19-9.77c-40.62-1.43-80.27,14.5-108.46,45.06-29.51,31.99-43.84,74.88-39.56,117.91,3.23,32.51,20.25,66.56,51.61,79.61,19.31,8.04,41.43,7.9,60.57-.55,45.98-20.31,61.02-87.9,30.31-126.8Z"/>
|
||||
<polygon class="cls-3" points="522.26 164.53 522.23 412.55 463.03 505.05 463.03 71.71 488.6 111.55 522.26 164.53"/>
|
||||
<path class="cls-1" d="M314.3,279.4c30.71,38.9,15.67,106.49-30.31,126.8-19.14,8.46-41.26,8.59-60.57.55-31.36-13.06-48.38-47.11-51.61-79.61-4.28-43.03,10.06-85.92,39.56-117.91,28.18-30.56,67.84-46.49,108.46-45.06l-.19,9.77c-54.57,1.79-94.49,47.86-106.46,99.95,31.68-24.2,75.81-26.53,101.12,5.51ZM266.02,398.71c20.66-5.9,29.08-30.26,29.63-50.89.4-15.16-1.85-30.25-7.19-44.48-1.73-4.6-4.14-8.48-6.9-12.39-6.92-9.8-17.54-15.98-29.66-16.66-11.29-.63-22.42,2.3-31.32,8.91l-11.2,8.3c-3.77,23.16-4.16,47.03,3.29,69.31,3.35,10.01,7.66,19.24,14.98,27.02,10.55,11.21,24.05,14.98,38.37,10.89Z"/>
|
||||
<path class="cls-2" d="M266.02,398.71c-14.32,4.09-27.82.33-38.37-10.89-7.32-7.78-11.64-17.01-14.98-27.02-7.45-22.28-7.06-46.14-3.29-69.31l11.2-8.3c8.91-6.61,20.04-9.54,31.32-8.91,12.12.68,22.73,6.86,29.66,16.66,2.77,3.92,5.18,7.8,6.9,12.39,5.34,14.22,7.6,29.32,7.19,44.48-.55,20.63-8.97,44.99-29.63,50.89Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 575.92 576.62">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #e18528;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #965924;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1" d="M55.89,331.57L271.03.48l195,331.05-410.14.04ZM306.26,259.35c5.73-11.88,4.08-25.51-2.7-36.66-4.08-6.51-8.98-11.72-14.89-16.48l-14.03-11.31c8.86-5.42,16.89-10.62,23.44-18.07,8.79-10,11.18-23.83,4.65-35.7-10.66-19.37-36.98-24.01-57.4-17.16-7.89,2.64-14.89,7.46-19.76,14.16-10.53,14.49-8.6,34.29,3.62,47.26,6.01,6.38,12.21,11.51,18.96,16.7l-12.3,9.02c-4.28,3.14-8.01,6.64-11.22,10.93-8.34,10.28-10.89,23.46-5.75,35.87,4.37,10.55,13.06,18.45,23.89,22.32,22.98,8.22,52.33,2.27,63.5-20.89Z"/>
|
||||
<polygon class="cls-3" points="271.03 576.14 55.89 341.35 466.03 341.34 271.03 576.14"/>
|
||||
<path class="cls-3" d="M476.03,331.57S276.4,2.34,277.03.48l243,322.43-44,8.65Z"/>
|
||||
<polygon class="cls-3" points="277.03 573.53 476.03 341.34 520.03 327.91 277.03 573.53"/>
|
||||
<path class="cls-2" d="M306.26,259.35c-11.17,23.16-40.52,29.11-63.5,20.89-10.83-3.87-19.52-11.78-23.89-22.32-5.15-12.42-2.6-25.59,5.75-35.87,3.22-4.29,6.94-7.79,11.22-10.93l12.3-9.02c-6.75-5.2-12.95-10.33-18.96-16.7-12.21-12.97-14.15-32.76-3.62-47.26,4.87-6.7,11.87-11.51,19.76-14.16,20.42-6.85,46.75-2.2,57.4,17.16,6.53,11.86,4.14,25.69-4.65,35.7-6.55,7.45-14.58,12.65-23.44,18.07l14.03,11.31c5.91,4.76,10.81,9.97,14.89,16.48,6.77,11.15,8.43,24.78,2.7,36.66ZM280.81,177.03c7.65-9.56,10.35-22,5.96-33.5-5.11-13.4-19.81-17.24-33.32-13.39-13.12,3.74-20.07,17.59-15,30.52,2.18,5.55,5.82,10.47,10.41,14.21l18.27,14.9c5.07-3.85,9.61-7.66,13.67-12.73ZM288.03,263.92c8.56-14.97-.95-30.48-13.68-40.79l-19.94-16.14-9.02,9.16c-9.75,11.69-12.77,27.27-7.58,41.57,4.47,12.3,16.15,19.16,28.98,18.3,8.67-.58,16.78-4.31,21.24-12.1Z"/>
|
||||
<path class="cls-1" d="M288.03,263.92c-4.45,7.79-12.57,11.52-21.24,12.1-12.84.86-24.51-5.99-28.98-18.3-5.2-14.3-2.17-29.88,7.58-41.57l9.02-9.16,19.94,16.14c12.73,10.3,22.24,25.81,13.68,40.79Z"/>
|
||||
<path class="cls-1" d="M280.81,177.03c-4.06,5.07-8.6,8.88-13.67,12.73l-18.27-14.9c-4.59-3.74-8.23-8.66-10.41-14.21-5.07-12.92,1.87-26.78,15-30.52,13.51-3.85,28.2,0,33.32,13.39,4.39,11.5,1.68,23.95-5.96,33.5Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 786 786.96">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
font-size: 108px;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2 {
|
||||
fill: #e93726;
|
||||
font-family: SitkaText, Sitka;
|
||||
font-variation-settings: 'opsz' 11, 'wght' 400;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #e18528;
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
letter-spacing: -.01em;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #f58530;
|
||||
}
|
||||
|
||||
.cls-6, .cls-7 {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #965924;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
letter-spacing: 0em;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
font-size: 310.77px;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #9b2220;
|
||||
stroke: #fff;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
stroke: #965924;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke-width: 7.09px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-10" x="92.3" y="92.78" width="601.4" height="601.4" rx="12" ry="12"/>
|
||||
<g>
|
||||
<path class="cls-5" d="M580.99,249.49c-19.32-5.9-30.05-22.42-27.78-41.95,1.26-10.83,5.25-21.18,13.26-29.63-.9,7.39-.16,17.58,6.53,18.66.94-8.84.15-15.28,6.11-23.24l7.92-11.21c6.24-8.83,7.5-19.28,3.37-29.88,15.44,8.26,23.82,24.55,21.89,41.85l-1.67,10.88c.29,2.7,1.62,5.21,4.15,5.78s4.78-1.16,5.94-3.78c2-4.52.44-9.18.65-14.62,10.88,11.73,16.51,26.9,15.31,42.17-1.29,16.3-12.35,30.71-28.53,34.91,6.83-7.12,8.79-15.99,5.72-24.9-1.81-5.25-5.27-9.43-8.83-13.86-5.7-6.72-8.45-14.75-6.72-23.31-7.89,5.36-9.91,14.69-7.9,23.13l3.66,11c1.09,3.28-1.67,6.64-4.54,7.12-3.56.6-5.85-1.73-6.87-5l-.94-7.53c-8.34,10.07-9.51,23.62-.92,32.49.96-.69.98.39.19.91Z"/>
|
||||
<path class="cls-7" d="M588.15,117.12c-41.42,3.95-71,40.77-67.08,81.3,3.95,40.77,40.15,70.73,80.91,67.01,40.76-3.72,70.94-39.73,67.45-80.54-3.49-40.81-39.62-71.73-81.28-67.76Z"/>
|
||||
</g>
|
||||
<g>
|
||||
<text class="cls-2" transform="translate(222.21 483.35)"><tspan x="0" y="0">Ar</tspan></text>
|
||||
<text class="cls-1" transform="translate(248.16 633.66)"><tspan x="0" y="0">A</tspan><tspan class="cls-4" x="69.45" y="0">r</tspan><tspan class="cls-9" x="117.31" y="0">dor</tspan></text>
|
||||
</g>
|
||||
<g>
|
||||
<path class="cls-3" d="M130.74,202.06l55.67-85.67,50.46,85.66h-106.13ZM195.52,183.37c1.48-3.07,1.05-6.6-.7-9.49-1.06-1.68-2.32-3.03-3.85-4.27l-3.63-2.93c2.29-1.4,4.37-2.75,6.06-4.68,2.28-2.59,2.89-6.17,1.2-9.24-2.76-5.01-9.57-6.21-14.85-4.44-2.04.68-3.85,1.93-5.11,3.66-2.72,3.75-2.22,8.87.94,12.23,1.55,1.65,3.16,2.98,4.91,4.32l-3.18,2.33c-1.11.81-2.07,1.72-2.9,2.83-2.16,2.66-2.82,6.07-1.49,9.28,1.13,2.73,3.38,4.77,6.18,5.78,5.95,2.13,13.54.59,16.43-5.41Z"/>
|
||||
<polygon class="cls-8" points="186.41 265.34 130.74 204.59 236.87 204.59 186.41 265.34"/>
|
||||
<path class="cls-8" d="M239.46,202.06s-51.66-85.19-51.5-85.67l62.88,83.44-11.39,2.24Z"/>
|
||||
<polygon class="cls-8" points="187.96 264.67 239.46 204.59 250.84 201.11 187.96 264.67"/>
|
||||
<path class="cls-6" d="M195.52,183.37c-2.89,5.99-10.48,7.53-16.43,5.41-2.8-1-5.05-3.05-6.18-5.78-1.33-3.21-.67-6.62,1.49-9.28.83-1.11,1.8-2.02,2.9-2.83l3.18-2.33c-1.75-1.34-3.35-2.67-4.91-4.32-3.16-3.36-3.66-8.48-.94-12.23,1.26-1.73,3.07-2.98,5.11-3.66,5.28-1.77,12.1-.57,14.85,4.44,1.69,3.07,1.07,6.65-1.2,9.24-1.69,1.93-3.77,3.27-6.06,4.68l3.63,2.93c1.53,1.23,2.8,2.58,3.85,4.27,1.75,2.89,2.18,6.41.7,9.49ZM188.94,162.07c1.98-2.47,2.68-5.69,1.54-8.67-1.32-3.47-5.12-4.46-8.62-3.46s-5.19,4.55-3.88,7.9c.56,1.44,1.51,2.71,2.69,3.68l4.73,3.86c1.31-1,2.49-1.98,3.54-3.29ZM190.81,184.55c2.21-3.88-.25-7.89-3.54-10.55l-5.16-4.18-2.33,2.37c-2.52,3.02-3.31,7.06-1.96,10.76,1.16,3.18,4.18,4.96,7.5,4.74,2.24-.15,4.34-1.12,5.5-3.13Z"/>
|
||||
<path class="cls-3" d="M190.81,184.55c-1.15,2.02-3.25,2.98-5.5,3.13-3.32.22-6.34-1.55-7.5-4.74-1.34-3.7-.56-7.73,1.96-10.76l2.33-2.37,5.16,4.18c3.29,2.67,5.75,6.68,3.54,10.55Z"/>
|
||||
<path class="cls-3" d="M188.94,162.07c-1.05,1.31-2.23,2.3-3.54,3.29l-4.73-3.86c-1.19-.97-2.13-2.24-2.69-3.68-1.31-3.34.48-6.93,3.88-7.9s7.3,0,8.62,3.46c1.14,2.98.44,6.2-1.54,8.67Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 786 786.96">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
stroke: #512d7c;
|
||||
stroke-width: 8.18px;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2 {
|
||||
fill: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #272f69;
|
||||
stroke: #fff;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
fill: #231f20;
|
||||
font-family: MyriadPro-Regular, 'Myriad Pro';
|
||||
font-size: 75px;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
font-size: 310.77px;
|
||||
}
|
||||
|
||||
.cls-5, .cls-6 {
|
||||
fill: #5567af;
|
||||
font-family: SitkaText, Sitka;
|
||||
font-variation-settings: 'opsz' 11, 'wght' 400;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
font-size: 108px;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
stroke: #7450a1;
|
||||
stroke-width: 6px;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #e93726;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #7450a1;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-3" x="92.3" y="92.78" width="601.4" height="601.4" rx="12" ry="12"/>
|
||||
<g>
|
||||
<text class="cls-5" transform="translate(134.58 483.35)"><tspan x="0" y="0">Hm</tspan></text>
|
||||
<text class="cls-6" transform="translate(216.39 633.66)"><tspan x="0" y="0">Humor</tspan></text>
|
||||
</g>
|
||||
<rect class="cls-7" x="92.3" y="92.81" width="98.49" height="98.49"/>
|
||||
<g>
|
||||
<path class="cls-8" d="M618.7,244.79l9.99-.73c-29.83,18.68-68.85,9.52-87.52-21.03,11.14-6.18,24.3-5.58,34.4,1.85l12.6,9.26c9.04,6.64,19.28,10.29,30.53,10.65Z"/>
|
||||
<path class="cls-8" d="M599.45,214.59c5.27.42,9.33,1.57,13.69-.05,8.88-3.26,6.62-14.12,16.13-12.67,2.78.43,6.28,2.78,6.56,6.47.54,7.08-5.71,12.22-12.82,13.36-8.5,1.36-17-1.6-23.57-7.12Z"/>
|
||||
<path class="cls-1" d="M649.68,241.67c-30.08,32.38-79.38,32.02-109.26-.43-22.86-24.82-25.69-61.22-7.87-89.75,13.05-20.89,35.85-33.88,60.33-34.67,24.03-.78,47.55,10.41,62.01,30.32,20.91,28.79,19.4,68.02-5.22,94.52Z"/>
|
||||
<path class="cls-8" d="M565,205.05c5.97.4,11.82,2.39,16.78,5.1,9.16,5,16.42,12.16,25.72,15.76,5.24,2.02,10.84,2.79,16.36,2.07,7.13-.95,14.42-4.77,17.45-11.52,3.43-7.04,1.75-16.07-5.79-19.58-4.16-2.38-9.37-2.85-13.85-1.26-4.36,1.51-8.09,4.77-10.06,9.3.53-13.96,15.64-22.6,28.39-17.39,12.64,5.95,16.59,21.1,10.7,33.3-4.49,9.97-14.93,16.05-25.45,17.41-13.35,1.86-25.58-3.25-36-10.8-7.97-5.53-15.35-11.45-24.92-12.07-11.98-2.34-24.76-.55-36.28,3.57-.76.27-1.53.55-2.29.85,10.99-10.62,24.5-15.61,39.24-14.76h0Z"/>
|
||||
<path class="cls-2" d="M589.8,201.51c-12.11-.34-20.79-8.81-22.17-20.67-.7-5.98,2.31-11.82,5.05-17.28l8.31-11.95c3.27-4.71,6.06-9.3,8.24-15.11l16.35,24.56c3.12,4.69,4.92,9.51,6.1,15.16,2.79,13.29-7.92,25.67-21.88,25.28Z"/>
|
||||
<path class="cls-8" d="M603.17,168.39l-6.68-1.6.32.06c-7.64-1.19-14.51,4.49-14.3,12.17.07,7.14,9.57,10.96,14.17,5.33,4.92-4.75,4.17-11.72,1.63-17.62,6.93,5.38,8.05,14.59,3.04,21.38-3.59,4.56-10.16,6.11-15.48,4.05-7.6-2.62-11.16-11.46-8.53-18.83,2.55-8.65,11.47-13.74,20.22-12.43.11.01.22.03.32.06l6.68,1.6c3.82,1.02,2.47,6.66-1.4,5.83h0Z"/>
|
||||
</g>
|
||||
<text class="cls-4" transform="translate(103.07 164.07)"><tspan x="0" y="0">20</tspan></text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 786 786.96">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
font-size: 310.77px;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2 {
|
||||
fill: #02a04a;
|
||||
font-family: SitkaText, Sitka;
|
||||
font-variation-settings: 'opsz' 11, 'wght' 400;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
font-size: 108px;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
letter-spacing: 0em;
|
||||
}
|
||||
|
||||
.cls-4, .cls-5 {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #007e6e;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
letter-spacing: -.02em;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #086d38;
|
||||
stroke: #fff;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
stroke: #007e6e;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke-width: 7.64px;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #02b8a1;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-8" x="92.3" y="92.78" width="601.4" height="601.4" rx="12" ry="12"/>
|
||||
<g>
|
||||
<text class="cls-1" transform="translate(188.79 483.35)"><tspan x="0" y="0">Nx</tspan></text>
|
||||
<text class="cls-2" transform="translate(237.82 633.66)"><tspan class="cls-7" x="0" y="0">N</tspan><tspan class="cls-3" x="80.54" y="0">e</tspan><tspan x="136.37" y="0">xus</tspan></text>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="cls-9" d="M614.31,184.62c-14.86,8.98-36.61,18.58-53.5,19.71-2.33-4.65-2.85-9.35-2.72-14.67.47-18.24,14.86-33.55,32.97-35.01l4.88-.4c.95.91,1.83.2,2.78.29,12.6,1.24,23.29,8.9,28.77,19.95-4.14,4.18-8.42,7.24-13.2,10.13Z"/>
|
||||
<path class="cls-9" d="M553.79,194.24c4.02,4.41-4.84,9.31-.81,11.92,3.05,1.98,7.17,2.18,10.5,1.72,9.99-1.36,19.25-4.21,28.61-8.1,10.11-4.21,19.83-8.84,28.77-15.14,5.21-3.67,15.34-11.69,12.87-15.68-1.44-2.33-4.5-2.11-6.69-2.58l-3-3.55,13.37-1.53,9.18.11c2.39.03,4.82,1.17,5.96,3.24,3.26,5.9-7.93,15.44-14.45,20.35-22.14,16.68-54.36,30.57-80.51,34.95-2.1.35-4.6-.14-6.73.73-6.07-.48-12.84-.15-14.33-5.1-1.93-6.42,10.04-16,17.26-21.34Z"/>
|
||||
<path class="cls-9" d="M610.58,224.52c-12.13,6.06-27.36,4.61-37.9-4.1,21.04-5.96,39.86-14.39,58.5-26-1.03,13.37-9.06,24.34-20.6,30.11Z"/>
|
||||
<path class="cls-9" d="M618.19,132.28l3.55,7.06,7.02,3.16-7.33,3.3-3.28,7.22c-1.19-2.27-1.23-5.41-3.19-7.35l-6.57-3.22,6.67-3.05,3.14-7.13Z"/>
|
||||
</g>
|
||||
<path class="cls-5" d="M590.59,116.9c-41.5,2.57-72.27,38.33-69.76,78.93,2.53,41.08,37.95,72.35,79,69.8,40.81-2.53,72.01-37.57,69.79-78.43-2.22-40.85-37.29-72.89-79.03-70.3Z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="cls-9" d="M136.04,226.58l15.2-29.04,20.73-39.83,13.43-25.72,26.62,50.98,22.81,43.6h-98.79ZM198.83,209.1c-2.83.1-5.75-.82-5.83-3.37l-.2-6.99c0-.12.28-.38.33-.41h6.04s.6-3.75.6-3.75l-6.8-.02-.17-.45.05-29.1-3.4.05-12.66,18.15-8.73,12.63.28,2.47h18.93s-.07,6.94-.07,6.94c-.03,3.1-2.84,3.9-5.92,3.85v1.92s17.62,0,17.62,0l-.06-1.92Z"/>
|
||||
<polygon class="cls-6" points="133.56 226.16 139.39 201.88 183.09 132 133.56 226.16"/>
|
||||
<path class="cls-4" d="M198.83,209.1l.06,1.92h-17.61s0-1.91,0-1.91c3.09.04,5.89-.75,5.92-3.85l.07-6.93h-19.2v-2.47l8.73-12.63,12.66-18.15,3.4-.05-.05,29.1.17.45,6.8.02-.6,3.74h-6.04c-.05.04-.34.31-.33.43l.2,6.99c.07,2.55,2.99,3.47,5.83,3.37ZM187.29,194.57l-.06-21.89-14.86,21.86,14.92.02Z"/>
|
||||
<polygon class="cls-9" points="187.29 194.57 172.37 194.55 187.23 172.68 187.29 194.57"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 786 786.96">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-2, .cls-3, .cls-4 {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #ed1f81;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #6b2365;
|
||||
stroke: #fff;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
stroke-width: 6.55px;
|
||||
}
|
||||
|
||||
.cls-2, .cls-3, .cls-4 {
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.cls-2, .cls-4 {
|
||||
stroke: #ed1f81;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
stroke: #9d1d59;
|
||||
stroke-width: 8.18px;
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
stroke-width: 4.91px;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
font-size: 310.77px;
|
||||
}
|
||||
|
||||
.cls-7, .cls-8 {
|
||||
fill: #9e3e97;
|
||||
font-family: SitkaText, Sitka;
|
||||
font-variation-settings: 'opsz' 11, 'wght' 400;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
font-size: 108px;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #9d1d59;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-6" x="92.3" y="92.78" width="601.4" height="601.4" rx="12" ry="12"/>
|
||||
<g>
|
||||
<text class="cls-7" transform="translate(143.49 483.35)"><tspan x="0" y="0">Om</tspan></text>
|
||||
<text class="cls-8" transform="translate(223.8 633.66)"><tspan x="0" y="0">Ossum</tspan></text>
|
||||
</g>
|
||||
<g>
|
||||
<path class="cls-3" d="M643.1,134.32c35.09,30.18,34.97,82.97.8,113.27-20.57,18.25-49.88,22.94-74.59,13.63-27.45-10.34-45.86-35.24-48.13-63.78-2.28-28.78,11.49-55.62,36.37-70.43,26.9-16.02,61.47-13.39,85.54,7.31Z"/>
|
||||
<g>
|
||||
<path class="cls-4" d="M621.65,156.13l-8.14,18.74c-1.78,4.11-1.84,8.31-1.41,12.73l1.59,16.07"/>
|
||||
<line class="cls-2" x1="584.35" y1="143.95" x2="621.65" y2="156.13"/>
|
||||
<path class="cls-2" d="M584.35,143.95l-11.33,17.17c-2.55,3.84-7.55,5.37-11,8.32l-4.74,4.04c-.08,4.98.56,9.95-1.31,14.53l-5.13,12.55c-.59,1.45.23,3.19-.78,4.27"/>
|
||||
<path class="cls-4" d="M613.7,203.68l4.68,2.83c3.5,2.09,5.49,4.84,6.83,8.81l4.06,12.05"/>
|
||||
<path class="cls-5" d="M586.67,143.15l3.43,9.97c.34.8.68,1.69.69,2.58,0,0,.28,11.65.28,11.65.01.59.7.82.78,1.25.06.24-.2.46-.15.76.04.38-.05.74-.5.65-.38-1.04-.7-1.92-1.18-3.23-1.61-4.28-2.83-8.2-4.57-12.06l-3.43-9.97c-.98-3.08,3.51-4.64,4.64-1.6h0Z"/>
|
||||
<path class="cls-2" d="M621.65,156.13l18.53,41.29c-3,10.38-6.34,20.4-10.92,29.95"/>
|
||||
<path class="cls-2" d="M550.06,204.83l6.96,11.57c2.21,3.67,3.47,9.08,7.1,11.57l16.21,6.98c2.68,1.16,5.63,3.26,8.69,2.45l37.03-9.76,3.22-.28"/>
|
||||
<polyline class="cls-4" points="550.06 204.83 560.08 207.84 580.85 217.72 585.52 233.49"/>
|
||||
<path class="cls-5" d="M614.66,205.93l-3.55,1.52c-4.22,1.75-8.26,4.77-12.82,5.2.2-.19,8.81-8.28,8.64-8.11.54-.39,1.71-1.21,2.25-1.6l3.55-1.52c3.01-1.2,4.88,3.17,1.93,4.51h0Z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path class="cls-5" d="M236.82,235.06h-86.5s0-94.12,0-94.12h86.49s0,94.12,0,94.12ZM206.94,186.08c-5.5-6.96-15.08-6.46-21.97-1.2,2.6-11.32,11.27-21.32,23.13-21.71l.04-2.12c-8.82-.31-17.44,3.15-23.56,9.79-6.41,6.95-9.52,16.27-8.59,25.62.7,7.06,4.4,14.46,11.21,17.3,4.19,1.75,9,1.72,13.16-.12,9.99-4.41,13.26-19.1,6.58-27.55Z"/>
|
||||
<polygon class="cls-9" points="252.12 161.13 252.12 215.01 239.26 235.1 239.26 140.97 244.81 149.62 252.12 161.13"/>
|
||||
<path class="cls-1" d="M206.94,186.08c6.67,8.45,3.4,23.13-6.58,27.55-4.16,1.84-8.96,1.87-13.16.12-6.81-2.84-10.51-10.23-11.21-17.3-.93-9.35,2.18-18.67,8.59-25.62,6.12-6.64,14.74-10.1,23.56-9.79l-.04,2.12c-11.86.39-20.53,10.4-23.13,21.71,6.88-5.26,16.47-5.76,21.97,1.2ZM196.46,212.01c4.49-1.28,6.32-6.57,6.44-11.06.09-3.29-.4-6.57-1.56-9.66-.37-1-.9-1.84-1.5-2.69-1.5-2.13-3.81-3.47-6.44-3.62-2.45-.14-4.87.5-6.8,1.93l-2.43,1.8c-.82,5.03-.9,10.22.71,15.06.73,2.17,1.66,4.18,3.26,5.87,2.29,2.44,5.23,3.25,8.34,2.37Z"/>
|
||||
<path class="cls-5" d="M196.46,212.01c-3.11.89-6.04.07-8.34-2.37-1.59-1.69-2.53-3.69-3.26-5.87-1.62-4.84-1.53-10.02-.71-15.06l2.43-1.8c1.94-1.43,4.35-2.07,6.8-1.93,2.63.15,4.94,1.49,6.44,3.62.6.85,1.13,1.69,1.5,2.69,1.16,3.09,1.65,6.37,1.56,9.66-.12,4.48-1.95,9.77-6.44,11.06Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 786 786.96">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #037988;
|
||||
stroke: #fff;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
stroke: #188dcd;
|
||||
stroke-width: 7.09px;
|
||||
}
|
||||
|
||||
.cls-2, .cls-3 {
|
||||
fill: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
font-size: 108px;
|
||||
}
|
||||
|
||||
.cls-4, .cls-5 {
|
||||
fill: #0bb3c8;
|
||||
font-family: SitkaText, Sitka;
|
||||
font-variation-settings: 'opsz' 11, 'wght' 400;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #231f20;
|
||||
font-family: MyriadPro-Regular, 'Myriad Pro';
|
||||
font-size: 75px;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
font-size: 310.77px;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
stroke: #06608d;
|
||||
stroke-width: 7.64px;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #e93726;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="92.3" y="92.78" width="601.4" height="601.4" rx="12" ry="12"/>
|
||||
<g>
|
||||
<text class="cls-5" transform="translate(208.54 483.35)"><tspan x="0" y="0">Pn</tspan></text>
|
||||
<text class="cls-4" transform="translate(191.14 633.66)"><tspan x="0" y="0">Pneuma</tspan></text>
|
||||
</g>
|
||||
<rect class="cls-7" x="92.07" y="92.51" width="98.49" height="98.49"/>
|
||||
<g>
|
||||
<path class="cls-3" d="M589.51,116.75c41.41-3.06,76.65,28.14,79.72,68.58,3.11,40.94-27.57,76.7-68.47,79.88-40.9,3.18-76.74-27.4-80-68.33-3.24-40.67,27.1-77.06,68.75-80.14Z"/>
|
||||
<g>
|
||||
<path class="cls-2" d="M540.98,191.66l94.51-.1c5.42,0,9.38-3.32,11.77-7.42,2.46-4.22,2.34-9.31-.33-14.08s-8.55-7.14-13.74-6.05c-5.56,1.16-9.58,5.2-10.56,11.06l-1.37,3.31"/>
|
||||
<path class="cls-2" d="M555.16,175.84l41.08-.22c5.22-.04,9.65-3.47,11.75-7.8,1.97-4.05,2.07-9.05-.38-13.57-2.52-4.65-7.73-7.06-12.64-6.38-5.36.74-9.63,4.27-11.31,9.68l-1.59,5.05"/>
|
||||
<path class="cls-2" d="M554.61,207.47l54.7.22c6.92.04,11.86,6.32,12.41,12.51.65,7.38-3.84,13.8-10.9,14.98-6.86,1.15-14.24-3.17-15.3-10.44l-.96-2.91"/>
|
||||
</g>
|
||||
</g>
|
||||
<text class="cls-6" transform="translate(102.84 163.77)"><tspan x="0" y="0">12</tspan></text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 786 786.96">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #a78a30;
|
||||
stroke: #fff;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
letter-spacing: 0em;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
letter-spacing: 0em;
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
stroke: #97ad3b;
|
||||
stroke-width: 5.45px;
|
||||
}
|
||||
|
||||
.cls-4, .cls-5 {
|
||||
fill: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #97ad3b;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
stroke: #617633;
|
||||
stroke-width: 8.18px;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
font-size: 310.77px;
|
||||
}
|
||||
|
||||
.cls-7, .cls-8 {
|
||||
fill: #ffd035;
|
||||
font-family: SitkaText, Sitka;
|
||||
font-variation-settings: 'opsz' 11, 'wght' 400;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #231f20;
|
||||
font-family: MyriadPro-Regular, 'Myriad Pro';
|
||||
font-size: 75px;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
letter-spacing: -.03em;
|
||||
}
|
||||
|
||||
.cls-11 {
|
||||
letter-spacing: -.07em;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
font-size: 108px;
|
||||
}
|
||||
|
||||
.cls-12 {
|
||||
fill: #e93726;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="92.3" y="92.78" width="601.4" height="601.4" rx="12" ry="12"/>
|
||||
<g>
|
||||
<text class="cls-7" transform="translate(209.37 483.35)"><tspan class="cls-10" x="0" y="0">T</tspan><tspan class="cls-3" x="184.81" y="0">p</tspan></text>
|
||||
<text class="cls-8" transform="translate(224.4 633.66)"><tspan class="cls-11" x="0" y="0">T</tspan><tspan class="cls-2" x="60.38" y="0">empo</tspan></text>
|
||||
</g>
|
||||
<rect class="cls-12" x="92.3" y="92.78" width="98.49" height="98.49"/>
|
||||
<g>
|
||||
<path class="cls-5" d="M523.34,209.57c10.37,40.36,52.59,65.03,92.15,53.27,25.27-7.51,44.99-27.56,51.59-53.25,7.85-30.54-4.25-62.27-30.01-79.95-25.03-17.18-58.69-17.16-83.68-.03-25.78,17.67-37.89,49.45-30.05,79.97Z"/>
|
||||
<g>
|
||||
<path class="cls-6" d="M594.92,204.58c6.01,9.69,17.98,10.43,20.31,23.51l-40.45.06c1.14-6.81,5.67-11.44,11.01-14.91,3.51-2.22,6.23-3.92,9.13-8.66Z"/>
|
||||
<path class="cls-6" d="M593.13,189.03c-2.81-8.51-14.28-10.71-16.68-21.2,5.71-2.79,11.47-1.63,16.56.73,6.41,2.99,12.97,3.07,19.39-.03.77-.33,1.11.7.72,1.12-3.37,8.56-13.05,11.13-16.16,18.96-.32.8.24,1.64-.56,2.28-.58.46-1.13,1.22-1.98.69-.96-.59-.94-1.53-1.27-2.55Z"/>
|
||||
<path class="cls-6" d="M593.3,200.02c-.11-.44-.28-1.76-.12-2.18.43-1.1,2.44-1.95,3.39-.42.67,1.07,1.26,1.87-.19,3.26-.82.79-2.64,1.06-3.08-.66Z"/>
|
||||
<path class="cls-4" d="M569.36,146.38l51.4-.12c1.71,4.37,2.19,8.69,1.61,13.12-3.2,24.61-18.64,25.22-18.48,31.87.12,5.19,8.21,7.28,12.69,14.55,5.67,9.19,7.16,20.13,4.69,30.59l-52.04-.08-1.36-8.12c-.39-2.33.19-4,.4-6.05,2.3-22.2,17.94-24.12,18.26-30.85.28-6.03-13.4-7.93-17.34-25.88-1.37-6.26-2.02-12.33.16-19.02Z"/>
|
||||
</g>
|
||||
</g>
|
||||
<text class="cls-9" transform="translate(122.31 164.04)"><tspan x="0" y="0">2</tspan></text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 297.64 298">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
stroke: #188dcd;
|
||||
stroke-width: 7.09px;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2 {
|
||||
fill: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
stroke: #06608d;
|
||||
stroke-width: 7.64px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-2" d="M141.55,75.25c41.41-3.06,76.65,28.14,79.72,68.58,3.11,40.94-27.57,76.7-68.47,79.88-40.9,3.18-76.74-27.4-80-68.33-3.24-40.67,27.1-77.06,68.75-80.14Z"/>
|
||||
<g>
|
||||
<path class="cls-1" d="M93.02,150.16l94.51-.1c5.42,0,9.38-3.32,11.77-7.42,2.46-4.22,2.34-9.31-.33-14.08s-8.55-7.14-13.74-6.05c-5.56,1.16-9.58,5.2-10.56,11.06l-1.37,3.31"/>
|
||||
<path class="cls-1" d="M107.2,134.34l41.08-.22c5.22-.04,9.65-3.47,11.75-7.8,1.97-4.05,2.07-9.05-.38-13.57-2.52-4.65-7.73-7.06-12.64-6.38-5.36.74-9.63,4.27-11.31,9.68l-1.59,5.05"/>
|
||||
<path class="cls-1" d="M106.66,165.98l54.7.22c6.92.04,11.86,6.32,12.41,12.51.65,7.38-3.84,13.8-10.9,14.98-6.86,1.15-14.24-3.17-15.3-10.44l-.96-2.91"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 297.64 298">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #f58530;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: none;
|
||||
stroke: #965924;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke-width: 7.09px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1" d="M136.33,208.12c-19.32-5.9-30.05-22.42-27.78-41.95,1.26-10.83,5.25-21.18,13.26-29.63-.9,7.39-.16,17.58,6.53,18.66.94-8.84.15-15.28,6.11-23.24l7.92-11.21c6.24-8.83,7.5-19.28,3.37-29.88,15.44,8.26,23.82,24.55,21.89,41.85l-1.67,10.88c.29,2.7,1.62,5.21,4.15,5.78s4.78-1.16,5.94-3.78c2-4.52.44-9.18.65-14.62,10.88,11.73,16.51,26.9,15.31,42.17-1.29,16.3-12.35,30.71-28.53,34.91,6.83-7.12,8.79-15.99,5.72-24.9-1.81-5.25-5.27-9.43-8.83-13.86-5.7-6.72-8.45-14.75-6.72-23.31-7.89,5.36-9.91,14.69-7.9,23.13l3.66,11c1.09,3.28-1.67,6.64-4.54,7.12-3.56.6-5.85-1.73-6.87-5l-.94-7.53c-8.34,10.07-9.51,23.62-.92,32.49.96-.69.98.39.19.91Z"/>
|
||||
<path class="cls-2" d="M143.49,75.75c-41.42,3.95-71,40.77-67.08,81.3,3.95,40.77,40.15,70.73,80.91,67.01,40.76-3.72,70.94-39.73,67.45-80.54-3.49-40.81-39.62-71.73-81.28-67.76Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 297.64 298">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: none;
|
||||
stroke: #007e6e;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke-width: 7.64px;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #02b8a1;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g>
|
||||
<path class="cls-2" d="M169.65,142.49c-14.86,8.98-36.61,18.58-53.5,19.71-2.33-4.65-2.85-9.35-2.72-14.67.47-18.24,14.86-33.55,32.97-35.01l4.88-.4c.95.91,1.83.2,2.78.29,12.6,1.24,23.29,8.9,28.77,19.95-4.14,4.18-8.42,7.24-13.2,10.13Z"/>
|
||||
<path class="cls-2" d="M109.13,152.11c4.02,4.41-4.84,9.31-.81,11.92,3.05,1.98,7.17,2.18,10.5,1.72,9.99-1.36,19.25-4.21,28.61-8.1,10.11-4.21,19.83-8.84,28.77-15.14,5.21-3.67,15.34-11.69,12.87-15.68-1.44-2.33-4.5-2.11-6.69-2.58l-3-3.55,13.37-1.53,9.18.11c2.39.03,4.82,1.17,5.96,3.24,3.26,5.9-7.93,15.44-14.45,20.35-22.14,16.68-54.36,30.57-80.51,34.95-2.1.35-4.6-.14-6.73.73-6.07-.48-12.84-.15-14.33-5.1-1.93-6.42,10.04-16,17.26-21.34Z"/>
|
||||
<path class="cls-2" d="M165.92,182.39c-12.13,6.06-27.36,4.61-37.9-4.1,21.04-5.96,39.86-14.39,58.5-26-1.03,13.37-9.06,24.34-20.6,30.11Z"/>
|
||||
<path class="cls-2" d="M173.53,90.16l3.55,7.06,7.02,3.16-7.33,3.3-3.28,7.22c-1.19-2.27-1.23-5.41-3.19-7.35l-6.57-3.22,6.67-3.05,3.14-7.13Z"/>
|
||||
</g>
|
||||
<path class="cls-1" d="M145.94,74.78c-41.5,2.57-72.27,38.33-69.76,78.93,2.53,41.08,37.95,72.35,79,69.8,40.81-2.53,72.01-37.57,69.79-78.43-2.22-40.85-37.29-72.89-79.03-70.3Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 297.64 298">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
stroke-width: 6.55px;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2, .cls-3 {
|
||||
fill: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.cls-1, .cls-3 {
|
||||
stroke: #ed1f81;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
stroke: #9d1d59;
|
||||
stroke-width: 8.18px;
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
fill: #ed1f81;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
stroke-width: 4.91px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-2" d="M198.1,92.95c35.09,30.18,34.97,82.97.8,113.27-20.57,18.25-49.88,22.94-74.59,13.63-27.45-10.34-45.86-35.24-48.13-63.78-2.28-28.78,11.49-55.62,36.37-70.43,26.9-16.02,61.47-13.39,85.54,7.31Z"/>
|
||||
<g>
|
||||
<path class="cls-3" d="M176.65,114.75l-8.14,18.74c-1.78,4.11-1.84,8.31-1.41,12.73l1.59,16.07"/>
|
||||
<line class="cls-1" x1="139.35" y1="102.57" x2="176.65" y2="114.75"/>
|
||||
<path class="cls-1" d="M139.35,102.57l-11.33,17.17c-2.55,3.84-7.55,5.37-11,8.32l-4.74,4.04c-.08,4.98.56,9.95-1.31,14.53l-5.13,12.55c-.59,1.45.23,3.19-.78,4.27"/>
|
||||
<path class="cls-3" d="M168.7,162.3l4.68,2.83c3.5,2.09,5.49,4.84,6.83,8.81l4.06,12.05"/>
|
||||
<path class="cls-4" d="M141.67,101.77l3.43,9.97c.34.8.68,1.69.69,2.58,0,0,.28,11.65.28,11.65.01.59.7.82.78,1.25.06.24-.2.46-.15.76.04.38-.05.74-.5.65-.38-1.04-.7-1.92-1.18-3.23-1.61-4.28-2.83-8.2-4.57-12.06l-3.43-9.97c-.98-3.08,3.51-4.64,4.64-1.6h0Z"/>
|
||||
<path class="cls-1" d="M176.65,114.75l18.53,41.29c-3,10.38-6.34,20.4-10.92,29.95"/>
|
||||
<path class="cls-1" d="M105.06,163.45l6.96,11.57c2.21,3.67,3.47,9.08,7.1,11.57l16.21,6.98c2.68,1.16,5.63,3.26,8.69,2.45l37.03-9.76,3.22-.28"/>
|
||||
<polyline class="cls-3" points="105.06 163.45 115.08 166.46 135.85 176.34 140.52 192.11"/>
|
||||
<path class="cls-4" d="M169.66,164.55l-3.55,1.52c-4.22,1.75-8.26,4.77-12.82,5.2.2-.19,8.81-8.28,8.64-8.11.54-.39,1.71-1.21,2.25-1.6l3.55-1.52c3.01-1.2,4.88,3.17,1.93,4.51h0Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 297.64 298">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
stroke: #97ad3b;
|
||||
stroke-width: 5.45px;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2 {
|
||||
fill: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #97ad3b;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
stroke: #617633;
|
||||
stroke-width: 8.18px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-2" d="M78.68,167.8c10.37,40.36,52.59,65.03,92.15,53.27,25.27-7.51,44.99-27.56,51.59-53.25,7.85-30.54-4.25-62.27-30.01-79.95-25.03-17.18-58.69-17.16-83.68-.03s-37.89,49.45-30.05,79.97Z"/>
|
||||
<g>
|
||||
<path class="cls-3" d="M150.26,162.81c6.01,9.69,17.98,10.43,20.31,23.51l-40.45.06c1.14-6.81,5.67-11.44,11.01-14.91,3.51-2.22,6.23-3.92,9.13-8.66Z"/>
|
||||
<path class="cls-3" d="M148.47,147.26c-2.81-8.51-14.28-10.71-16.68-21.2,5.71-2.79,11.47-1.63,16.56.73,6.41,2.99,12.97,3.07,19.39-.03.77-.33,1.11.7.72,1.12-3.37,8.56-13.05,11.13-16.16,18.96-.32.8.24,1.64-.56,2.28-.58.46-1.13,1.22-1.98.69-.96-.59-.94-1.53-1.27-2.55Z"/>
|
||||
<path class="cls-3" d="M148.64,158.25c-.11-.44-.28-1.76-.12-2.18.43-1.1,2.44-1.95,3.39-.42.67,1.07,1.26,1.87-.19,3.26-.82.79-2.64,1.06-3.08-.66Z"/>
|
||||
<path class="cls-1" d="M124.7,104.6l51.4-.12c1.71,4.37,2.19,8.69,1.61,13.12-3.2,24.61-18.64,25.22-18.48,31.87.12,5.19,8.21,7.28,12.69,14.55,5.67,9.19,7.16,20.13,4.69,30.59l-52.04-.08-1.36-8.12c-.39-2.33.19-4,.4-6.05,2.3-22.2,17.94-24.12,18.26-30.85.28-6.03-13.4-7.93-17.34-25.88-1.37-6.26-2.02-12.33.16-19.02Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 297.64 298">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
stroke: #512d7c;
|
||||
stroke-width: 8.18px;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2 {
|
||||
fill: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
stroke: #7450a1;
|
||||
stroke-width: 6px;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #7450a1;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-3" d="M174.04,203.87l9.99-.73c-29.83,18.68-68.85,9.52-87.52-21.03,11.14-6.18,24.3-5.58,34.4,1.85l12.6,9.26c9.04,6.64,19.28,10.29,30.53,10.65Z"/>
|
||||
<path class="cls-3" d="M154.79,173.68c5.27.42,9.33,1.57,13.69-.05,8.88-3.26,6.62-14.12,16.13-12.67,2.78.43,6.28,2.78,6.56,6.47.54,7.08-5.71,12.22-12.82,13.36-8.5,1.36-17-1.6-23.57-7.12Z"/>
|
||||
<path class="cls-1" d="M205.02,200.76c-30.08,32.38-79.38,32.02-109.26-.43-22.86-24.82-25.69-61.22-7.87-89.75,13.05-20.89,35.85-33.88,60.33-34.67,24.03-.78,47.55,10.41,62.01,30.32,20.91,28.79,19.4,68.02-5.22,94.52Z"/>
|
||||
<path class="cls-3" d="M120.34,164.14c5.97.4,11.82,2.39,16.78,5.1,9.16,5,16.42,12.16,25.72,15.76,5.24,2.02,10.84,2.79,16.36,2.07,7.13-.95,14.42-4.77,17.45-11.52,3.43-7.04,1.75-16.07-5.79-19.58-4.16-2.38-9.37-2.85-13.85-1.26-4.36,1.51-8.09,4.77-10.06,9.3.53-13.96,15.64-22.6,28.39-17.39,12.64,5.95,16.59,21.1,10.7,33.3-4.49,9.97-14.93,16.05-25.45,17.41-13.35,1.86-25.58-3.25-36-10.8-7.97-5.53-15.35-11.45-24.92-12.07-11.98-2.34-24.76-.55-36.28,3.57-.76.27-1.53.55-2.29.85,10.99-10.62,24.5-15.61,39.24-14.76h0Z"/>
|
||||
<path class="cls-2" d="M145.14,160.6c-12.11-.34-20.79-8.81-22.17-20.67-.7-5.98,2.31-11.82,5.05-17.28l8.31-11.95c3.27-4.71,6.06-9.3,8.24-15.11l16.35,24.56c3.12,4.69,4.92,9.51,6.1,15.16,2.79,13.29-7.92,25.67-21.88,25.28Z"/>
|
||||
<path class="cls-3" d="M158.51,127.47l-6.68-1.6.32.06c-7.64-1.19-14.51,4.49-14.3,12.17.07,7.14,9.57,10.96,14.17,5.33,4.92-4.75,4.17-11.72,1.63-17.62,6.93,5.38,8.05,14.59,3.04,21.38-3.59,4.56-10.16,6.11-15.48,4.05-7.6-2.62-11.16-11.46-8.53-18.83,2.55-8.65,11.47-13.74,20.22-12.43.11.01.22.03.32.06l6.68,1.6c3.82,1.02,2.47,6.66-1.4,5.83h0Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -8,10 +8,17 @@
|
||||
*
|
||||
* `data` shape — matches the /epic/natus/preview/ proxy response:
|
||||
* {
|
||||
* planets: { Sun: { sign, degree, retrograde }, … },
|
||||
* planets: { Sun: { sign, degree, speed, retrograde }, … },
|
||||
* houses: { cusps: [f×12], asc: f, mc: f },
|
||||
* elements: { Fire: n, Water: n, Stone: n, Air: n, Time: n, Space: n },
|
||||
* aspects: [{ planet1, planet2, type, angle, orb }, …],
|
||||
* elements: {
|
||||
* Fire: { count: n, contributors: [{planet, sign}, …] },
|
||||
* Stone: { count: n, contributors: […] },
|
||||
* Air: { count: n, contributors: […] },
|
||||
* Water: { count: n, contributors: […] },
|
||||
* Time: { count: n, stellia: [{ sign, planets: [{planet, sign}] }] },
|
||||
* Space: { count: n, parades: [{ signs: […], planets: [{planet, sign}] }] },
|
||||
* },
|
||||
* aspects: [{ planet1, planet2, type, angle, orb, applying_planet }, …],
|
||||
* distinctions: { "1": n, …, "12": n },
|
||||
* house_system: "O",
|
||||
* }
|
||||
@@ -46,7 +53,7 @@ const NatusWheel = (() => {
|
||||
Jupiter: '♃', Saturn: '♄', Uranus: '♅', Neptune: '♆', Pluto: '♇',
|
||||
};
|
||||
|
||||
// Alchemical element symbol → CSS modifier class suffix (matches rootvars palette)
|
||||
// Alchemical element code → CSS var suffix (--pri{Cap}) e.g. 'au' → --priAu
|
||||
const PLANET_ELEMENTS = {
|
||||
Sun: 'au', Moon: 'ag', Mercury: 'hg', Venus: 'cu', Mars: 'fe',
|
||||
Jupiter: 'sn', Saturn: 'pb', Uranus: 'u', Neptune: 'np', Pluto: 'pu',
|
||||
@@ -65,15 +72,31 @@ const NatusWheel = (() => {
|
||||
// Clockwise ring order for element cycling
|
||||
const ELEMENT_ORDER = ['Fire', 'Stone', 'Time', 'Space', 'Air', 'Water'];
|
||||
|
||||
// Aspect stroke colors remain in JS — they are data-driven, not stylistic.
|
||||
const ASPECT_COLORS = {
|
||||
Conjunction: 'var(--priYl, #f0e060)',
|
||||
Sextile: 'var(--priGn, #60c080)',
|
||||
Square: 'var(--priRd, #c04040)',
|
||||
Trine: 'var(--priGn, #60c080)',
|
||||
Opposition: 'var(--priRd, #c04040)',
|
||||
const CLASSIC_ELEMENTS = new Set(['Fire', 'Stone', 'Air', 'Water']);
|
||||
|
||||
const ASPECT_SYMBOLS = {
|
||||
Conjunction: '☌',
|
||||
Semisextile: '⚺',
|
||||
Sextile: '⚹',
|
||||
Square: '□',
|
||||
Trine: '△',
|
||||
Quincunx: '⚻',
|
||||
Opposition: '☍',
|
||||
};
|
||||
|
||||
const APPLY_SYM = '⇥'; // →| applying (converging toward exact)
|
||||
const SEP_SYM = '↦'; // |→ separating (diverging from exact)
|
||||
|
||||
// SVG stroke-dasharray and width per aspect type — color comes from applying planet.
|
||||
const ASPECT_STYLES = {
|
||||
Conjunction: { dash: 'none', width: 1.2 },
|
||||
Semisextile: { dash: '1 4', width: 0.6 },
|
||||
Sextile: { dash: '6 4', width: 0.8 },
|
||||
Square: { dash: '2 4', width: 1.2 },
|
||||
Trine: { dash: '12 4', width: 0.8 },
|
||||
Quincunx: { dash: '12 4 2 4', width: 0.8 },
|
||||
Opposition: { dash: '10 4 2 4 2 4', width: 1.2 },
|
||||
};
|
||||
// Element fill colors live in _natus.scss (.nw-sign--* / .nw-element--*).
|
||||
|
||||
const HOUSE_LABELS = [
|
||||
'', 'Self', 'Worth', 'Education', 'Family', 'Creation', 'Ritual',
|
||||
@@ -108,16 +131,44 @@ const NatusWheel = (() => {
|
||||
// AbortController for the outside-click dismiss listener.
|
||||
let _outsideClickController = null;
|
||||
|
||||
// ── Aspect overlay state ──────────────────────────────────────────────────
|
||||
|
||||
let _aspectsVisible = false;
|
||||
let _aspectGroup = null; // D3 selection of the nw-aspects <g>
|
||||
let _aspectIndex = {}; // planetName → [{partner, type, orb, applying_planet}]
|
||||
let _aspectPlanet = null; // name of planet whose lines are currently drawn
|
||||
|
||||
// ── Static asset base path ────────────────────────────────────────────────
|
||||
|
||||
let _staticBase = null;
|
||||
|
||||
function _getStaticBase() {
|
||||
if (_staticBase) return _staticBase;
|
||||
const scripts = document.querySelectorAll('script[src]');
|
||||
for (const s of scripts) {
|
||||
if (s.src.includes('natus-wheel')) {
|
||||
_staticBase = s.src.replace(/natus-wheel\.js.*$/, '');
|
||||
return _staticBase;
|
||||
}
|
||||
}
|
||||
_staticBase = '/static/apps/gameboard/';
|
||||
return _staticBase;
|
||||
}
|
||||
|
||||
// ── Helpers ───────────────────────────────────────────────────────────────
|
||||
|
||||
/** Convert ecliptic longitude to SVG angle.
|
||||
*
|
||||
* American convention: ASC sits at 9 o'clock (left). SVG 0° is 3 o'clock
|
||||
* and increases clockwise, so ecliptic (counter-clockwise, ASC-relative)
|
||||
* maps to SVG via:
|
||||
* svg_angle = -(ecliptic - asc) - 180° (in radians)
|
||||
* The −180° offset places ASC exactly at the left (9 o'clock) position.
|
||||
/**
|
||||
* Normalise an element value that may be either a legacy flat integer
|
||||
* (old stored chart_data) or the new enriched object {count, contributors?, …}.
|
||||
* Always returns an object with at least a `count` key.
|
||||
*/
|
||||
function _elNorm(v) {
|
||||
if (!v) return { count: 0 };
|
||||
if (typeof v === 'number') return { count: v };
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Convert ecliptic longitude to SVG angle (ASC at 9 o'clock). */
|
||||
function _toAngle(degree, asc) {
|
||||
return (-(degree - asc) - 180) * Math.PI / 180;
|
||||
}
|
||||
@@ -133,13 +184,46 @@ const NatusWheel = (() => {
|
||||
return ((ecliptic % 360) + 360) % 360 % 30;
|
||||
}
|
||||
|
||||
/** Inline SVG for a zodiac sign, sized to 1em, using current text colour. */
|
||||
/** Inline SVG for a zodiac sign icon (preloaded path). */
|
||||
function _signIconSvg(signName) {
|
||||
const d = _signPaths[signName];
|
||||
if (!d) return '';
|
||||
return `<svg viewBox="0 0 640 640" width="1em" height="1em" class="tt-sign-icon" aria-hidden="true"><path d="${d}"/></svg>`;
|
||||
}
|
||||
|
||||
/** <img> for an element-square badge (Ardor.svg etc.). */
|
||||
function _elementSquareImg(elementKey) {
|
||||
const info = ELEMENT_INFO[elementKey];
|
||||
if (!info) return '';
|
||||
const src = _getStaticBase() + 'icons/element-squares/' + info.name + '.svg';
|
||||
return `<img src="${src}" class="tt-el-square" width="80" height="80" alt="${info.name}" aria-hidden="true">`;
|
||||
}
|
||||
|
||||
/** <img> for an energy-vector icon (fire.svg, stone.svg etc.) — inline in text. */
|
||||
function _elementVectorImg(elementKey) {
|
||||
const info = ELEMENT_INFO[elementKey];
|
||||
if (!info) return '';
|
||||
const src = _getStaticBase() + 'icons/energy-vectors/' + info.classical + '.svg';
|
||||
return `<img src="${src}" class="tt-el-vec" width="1em" height="1em" alt="${info.classical}" aria-hidden="true">`;
|
||||
}
|
||||
|
||||
/** CSS color string for an aspect line, keyed to the applying planet. */
|
||||
function _aspectColor(applying_planet) {
|
||||
const code = PLANET_ELEMENTS[applying_planet];
|
||||
if (!code) return '#888';
|
||||
return `rgba(var(--asp-${code[0].toUpperCase() + code.slice(1)}), 0.85)`;
|
||||
}
|
||||
|
||||
/** Small inline SVG showing the aspect line pattern — used in tooltip legend. */
|
||||
function _aspectLineSvg(type, applying_planet) {
|
||||
const style = ASPECT_STYLES[type] || { dash: 'none', width: 0.8 };
|
||||
const color = _aspectColor(applying_planet);
|
||||
const dash = style.dash === 'none' ? '' : ` stroke-dasharray="${style.dash}"`;
|
||||
return `<svg class="tt-asp-line" width="28" height="10" aria-hidden="true">` +
|
||||
`<line x1="2" y1="5" x2="26" y2="5" stroke="${color}" stroke-width="${style.width * 2}"${dash}/>` +
|
||||
`</svg>`;
|
||||
}
|
||||
|
||||
|
||||
// ── Cycle helpers ─────────────────────────────────────────────────────────
|
||||
|
||||
@@ -161,25 +245,61 @@ const NatusWheel = (() => {
|
||||
_activeIdx = null;
|
||||
}
|
||||
|
||||
/** Dismiss tooltip and reset all active state. */
|
||||
function _clearAspectLines() {
|
||||
if (_aspectGroup) _aspectGroup.selectAll('*').remove();
|
||||
if (_svg) _svg.selectAll('.nw-planet-group').classed('nw-planet--asp-active', false);
|
||||
}
|
||||
|
||||
/** Dismiss tooltip and reset all active state. Aspect lines persist. */
|
||||
function _closeTooltip() {
|
||||
_clearActive();
|
||||
if (_tooltipEl) _tooltipEl.style.display = 'none';
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw aspect lines for `planetName` into the persistent nw-aspects group.
|
||||
* Only runs when _aspectsVisible is true.
|
||||
*/
|
||||
function _showPlanetAspects(planetName) {
|
||||
if (!_aspectsVisible || !_aspectGroup || !_currentData) return;
|
||||
_clearAspectLines();
|
||||
_aspectPlanet = null;
|
||||
|
||||
const asc = _currentData.houses.asc;
|
||||
const degrees = {};
|
||||
Object.entries(_currentData.planets).forEach(([n, p]) => { degrees[n] = p.degree; });
|
||||
|
||||
const myDeg = degrees[planetName];
|
||||
if (myDeg === undefined) return;
|
||||
const a1 = _toAngle(myDeg, asc);
|
||||
|
||||
(_aspectIndex[planetName] || []).forEach(({ partner, type, applying_planet }) => {
|
||||
const partnerDeg = degrees[partner];
|
||||
if (partnerDeg === undefined) return;
|
||||
const a2 = _toAngle(partnerDeg, asc);
|
||||
const style = ASPECT_STYLES[type] || { dash: 'none', width: 0.8 };
|
||||
const color = _aspectColor(applying_planet);
|
||||
|
||||
const line = _aspectGroup.append('line')
|
||||
.attr('x1', _cx + R.planetR * Math.cos(a1))
|
||||
.attr('y1', _cy + R.planetR * Math.sin(a1))
|
||||
.attr('x2', _cx + R.planetR * Math.cos(a2))
|
||||
.attr('y2', _cy + R.planetR * Math.sin(a2))
|
||||
.attr('stroke', color)
|
||||
.attr('stroke-width', style.width * 2)
|
||||
.attr('stroke-opacity', 0.9);
|
||||
|
||||
if (style.dash !== 'none') line.attr('stroke-dasharray', style.dash);
|
||||
});
|
||||
_aspectPlanet = planetName;
|
||||
if (_svg) {
|
||||
_svg.select(`[data-planet="${planetName}"]`).classed('nw-planet--asp-active', true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Position the tooltip in the vertical half of the wheel opposite to the
|
||||
* clicked planet/element, with the horizontal edge aligned to the item.
|
||||
*
|
||||
* Vertical (upper/lower):
|
||||
* item in lower half (itemY ≥ svgCY) → lower edge 1rem above centreline
|
||||
* item in upper half (itemY < svgCY) → upper edge 1rem below centreline
|
||||
*
|
||||
* Horizontal (left/right of centre):
|
||||
* item left of centre → tooltip left edge aligns with item left edge
|
||||
* item right of centre → tooltip right edge aligns with item right edge
|
||||
*
|
||||
* "1rem" is approximated as 16 px.
|
||||
* clicked planet/element.
|
||||
*/
|
||||
function _positionTooltipAtItem(ring, idx) {
|
||||
const svgNode = _svg ? _svg.node() : null;
|
||||
@@ -194,7 +314,6 @@ const NatusWheel = (() => {
|
||||
const svgCX = svgRect.left + svgRect.width / 2;
|
||||
const svgCY = svgRect.top + svgRect.height / 2;
|
||||
|
||||
// Item screen rect — fall back to SVG centre if element not found.
|
||||
let iRect = { left: svgCX, top: svgCY, width: 0, height: 0, right: svgCX, bottom: svgCY };
|
||||
{
|
||||
let el = null;
|
||||
@@ -211,13 +330,9 @@ const NatusWheel = (() => {
|
||||
const itemX = iRect.left + iRect.width / 2;
|
||||
const itemY = iRect.top + iRect.height / 2;
|
||||
|
||||
// Horizontal: align tooltip edge with item edge on the same side.
|
||||
// Clamp within the SVG rect so the tooltip stays over the wheel.
|
||||
const left = Math.max(svgRect.left + REM, Math.min(svgRect.right - ttW - REM,
|
||||
itemX < svgCX ? iRect.left : iRect.right - ttW
|
||||
));
|
||||
|
||||
// Vertical: place in the opposite half, 1rem from centreline.
|
||||
const top = Math.max(svgRect.top + REM, Math.min(svgRect.bottom - ttH - REM,
|
||||
itemY >= svgCY ? svgCY - REM - ttH : svgCY + REM
|
||||
));
|
||||
@@ -229,6 +344,12 @@ const NatusWheel = (() => {
|
||||
/** Lock-activate a planet by cycle index. */
|
||||
function _activatePlanet(idx) {
|
||||
_clearActive();
|
||||
// Aspect lines persist across planet switches — cleared only by DON or DOFF.
|
||||
// Re-opening the same planet restores _aspectsVisible so DON shows as ×.
|
||||
const item0 = _planetItems[idx];
|
||||
if (item0.name !== _aspectPlanet) {
|
||||
_aspectsVisible = false;
|
||||
}
|
||||
_activeRing = 'planets';
|
||||
_activeIdx = idx;
|
||||
const item = _planetItems[idx];
|
||||
@@ -244,12 +365,41 @@ const NatusWheel = (() => {
|
||||
const rx = pdata.retrograde ? ' ℞' : '';
|
||||
const icon = _signIconSvg(pdata.sign) || signData.symbol || '';
|
||||
|
||||
// Aspect list — always shown in small font; lines on SVG toggled separately.
|
||||
let aspectHtml = '';
|
||||
const myAspects = _aspectIndex[item.name] || [];
|
||||
if (myAspects.length) {
|
||||
aspectHtml = '<small class="tt-aspects">';
|
||||
myAspects.forEach(({ partner, type, orb, applying_planet }) => {
|
||||
const psym = PLANET_SYMBOLS[partner] || partner[0];
|
||||
const ppdata = _currentData.planets[partner] || {};
|
||||
const sicon = _signIconSvg(ppdata.sign) || (SIGNS.find(s => s.name === ppdata.sign) || {}).symbol || '';
|
||||
const asym = ASPECT_SYMBOLS[type] || type;
|
||||
const dirsym = applying_planet === item.name ? APPLY_SYM : SEP_SYM;
|
||||
const lineSvg = _aspectLineSvg(type, applying_planet);
|
||||
aspectHtml +=
|
||||
`<div class="tt-asp-row">` +
|
||||
`${lineSvg} ${asym} ${psym} <span class="tt-asp-in">in</span> ${sicon}` +
|
||||
` <span class="tt-asp-orb">(${dirsym} ${orb}°)</span>` +
|
||||
`</div>`;
|
||||
});
|
||||
aspectHtml += '</small>';
|
||||
}
|
||||
|
||||
if (_ttBody) {
|
||||
_ttBody.innerHTML =
|
||||
`<div class="tt-title tt-title--${el}">${item.name} (${sym})</div>` +
|
||||
`<div class="tt-description">@${inDeg}° ${pdata.sign} (${icon})${rx}</div>`;
|
||||
`<div class="tt-description">@${inDeg}° ${pdata.sign} (${icon})${rx}</div>` +
|
||||
aspectHtml;
|
||||
}
|
||||
|
||||
_updateAspectToggleUI();
|
||||
_showPlanetAspects(item.name);
|
||||
_positionTooltipAtItem('planets', idx);
|
||||
if (_tooltipEl) {
|
||||
_tooltipEl.querySelector('.nw-asp-don')?.style.removeProperty('display');
|
||||
_tooltipEl.querySelector('.nw-asp-doff')?.style.removeProperty('display');
|
||||
}
|
||||
}
|
||||
|
||||
/** Lock-activate an element slice by cycle index. */
|
||||
@@ -261,19 +411,100 @@ const NatusWheel = (() => {
|
||||
const grp = _svg.select(`[data-element="${item.key}"]`);
|
||||
grp.classed('nw-element--active', true);
|
||||
|
||||
const info = ELEMENT_INFO[item.key] || {};
|
||||
const elCounts = _currentData.elements;
|
||||
const total = Object.values(elCounts).reduce((s, v) => s + v, 0);
|
||||
const count = elCounts[item.key] || 0;
|
||||
const pct = total > 0 ? Math.round((count / total) * 100) : 0;
|
||||
const elKey = item.key.toLowerCase();
|
||||
const info = ELEMENT_INFO[item.key] || {};
|
||||
const elData = _elNorm((_currentData.elements || {})[item.key]);
|
||||
const count = elData.count || 0;
|
||||
const elKey = item.key.toLowerCase();
|
||||
const squareImg = _elementSquareImg(item.key);
|
||||
const vecImg = _elementVectorImg(item.key);
|
||||
|
||||
let bodyHtml = '';
|
||||
|
||||
const pct = Math.round(count / 10 * 100);
|
||||
|
||||
if (CLASSIC_ELEMENTS.has(item.key)) {
|
||||
const contribs = elData.contributors || [];
|
||||
bodyHtml = `<div class="tt-el-body-line">${vecImg} +${count} (${pct}%)</div>`;
|
||||
if (contribs.length) {
|
||||
bodyHtml += '<div class="tt-el-contribs">';
|
||||
contribs.forEach(c => {
|
||||
const psym = PLANET_SYMBOLS[c.planet] || c.planet[0];
|
||||
const pdata = (_currentData.planets || {})[c.planet] || {};
|
||||
const inDeg = pdata.degree !== undefined ? _inSignDeg(pdata.degree).toFixed(1) : '?';
|
||||
const sicon = _signIconSvg(c.sign) || (SIGNS.find(s => s.name === c.sign) || {}).symbol || '';
|
||||
bodyHtml += `<div class="tt-asp-row">${psym} @ ${inDeg}° ${sicon} +1</div>`;
|
||||
});
|
||||
bodyHtml += '</div>';
|
||||
}
|
||||
|
||||
} else if (item.key === 'Time') {
|
||||
const stellia = elData.stellia || [];
|
||||
bodyHtml = `<div class="tt-el-body-line">${vecImg} +${count} (${pct}%)</div>`;
|
||||
if (stellia.length) {
|
||||
bodyHtml += '<div class="tt-el-contribs">';
|
||||
stellia.forEach(st => {
|
||||
const bonus = st.planets.length - 1;
|
||||
bodyHtml += `<div class="tt-el-formation-header">Stellium +${bonus}</div>`;
|
||||
st.planets.forEach(p => {
|
||||
const psym = PLANET_SYMBOLS[p.planet] || p.planet[0];
|
||||
const pdata = (_currentData.planets || {})[p.planet] || {};
|
||||
const inDeg = pdata.degree !== undefined ? _inSignDeg(pdata.degree).toFixed(1) : '?';
|
||||
const sicon = _signIconSvg(p.sign) || (SIGNS.find(s => s.name === p.sign) || {}).symbol || '';
|
||||
bodyHtml += `<div class="tt-asp-row tt-el-planet-row">${psym} @ ${inDeg}° ${sicon}</div>`;
|
||||
});
|
||||
});
|
||||
bodyHtml += '</div>';
|
||||
} else {
|
||||
bodyHtml += `<div class="tt-el-formation">—</div>`;
|
||||
}
|
||||
|
||||
} else if (item.key === 'Space') {
|
||||
const parades = elData.parades || [];
|
||||
bodyHtml = `<div class="tt-el-body-line">${vecImg} +${count} (${pct}%)</div>`;
|
||||
if (parades.length) {
|
||||
bodyHtml += '<div class="tt-el-contribs">';
|
||||
parades.forEach(pd => {
|
||||
const bonus = pd.signs.length - 1;
|
||||
bodyHtml += `<div class="tt-el-formation-header">Parade +${bonus}</div>`;
|
||||
// Group planets by sign, sorted by ecliptic degree (counterclockwise = ascending)
|
||||
const bySign = {};
|
||||
pd.planets.forEach(p => {
|
||||
if (!bySign[p.sign]) bySign[p.sign] = [];
|
||||
bySign[p.sign].push(p);
|
||||
});
|
||||
Object.keys(bySign).forEach(sign => {
|
||||
bySign[sign].sort((a, b) => {
|
||||
const da = ((_currentData.planets || {})[a.planet] || {}).degree || 0;
|
||||
const db = ((_currentData.planets || {})[b.planet] || {}).degree || 0;
|
||||
return da - db;
|
||||
});
|
||||
});
|
||||
pd.signs.forEach(sign => {
|
||||
const planets = bySign[sign] || [];
|
||||
const sicon = _signIconSvg(sign) || (SIGNS.find(s => s.name === sign) || {}).symbol || sign;
|
||||
const psyms = planets.map(p => PLANET_SYMBOLS[p.planet] || p.planet[0]).join(' ');
|
||||
bodyHtml += `<div class="tt-asp-row tt-el-planet-row">${sicon} (${psyms})</div>`;
|
||||
});
|
||||
});
|
||||
bodyHtml += '</div>';
|
||||
} else {
|
||||
bodyHtml += `<div class="tt-el-formation">—</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
if (_ttBody) {
|
||||
_ttBody.innerHTML =
|
||||
`<div class="tt-title tt-title--el-${elKey}">[${info.abbr}] ${info.name}</div>` +
|
||||
`<div class="tt-description">${info.classical} · ${count} (${pct}%)</div>`;
|
||||
`<div class="tt-el-header">` +
|
||||
squareImg +
|
||||
`<span class="tt-title tt-title--el-${elKey}">${info.name}</span>` +
|
||||
`</div>` +
|
||||
bodyHtml;
|
||||
}
|
||||
_positionTooltipAtItem('elements', idx);
|
||||
if (_tooltipEl) {
|
||||
_tooltipEl.querySelector('.nw-asp-don')?.style.setProperty('display', 'none');
|
||||
_tooltipEl.querySelector('.nw-asp-doff')?.style.setProperty('display', 'none');
|
||||
}
|
||||
}
|
||||
|
||||
/** Advance the active ring by +1 (NXT) or -1 (PRV). */
|
||||
@@ -287,37 +518,75 @@ const NatusWheel = (() => {
|
||||
}
|
||||
}
|
||||
|
||||
function _updateAspectToggleUI() {
|
||||
if (!_tooltipEl) return;
|
||||
const don = _tooltipEl.querySelector('.nw-asp-don');
|
||||
const doff = _tooltipEl.querySelector('.nw-asp-doff');
|
||||
if (!don || !doff) return;
|
||||
don.classList.toggle('btn-disabled', _aspectsVisible);
|
||||
doff.classList.toggle('btn-disabled', !_aspectsVisible);
|
||||
don.textContent = _aspectsVisible ? '×' : 'DON';
|
||||
doff.textContent = !_aspectsVisible ? '×' : 'DOFF';
|
||||
}
|
||||
|
||||
function _toggleAspects() {
|
||||
_aspectsVisible = !_aspectsVisible;
|
||||
_updateAspectToggleUI();
|
||||
if (_aspectsVisible) {
|
||||
if (_activeRing === 'planets' && _activeIdx !== null) {
|
||||
_showPlanetAspects(_planetItems[_activeIdx].name);
|
||||
}
|
||||
} else {
|
||||
_clearAspectLines();
|
||||
_aspectPlanet = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject PRV/idx/NXT controls into #id_natus_tooltip and wire their events.
|
||||
* Inject PRV/NXT + DON|DOFF controls into the tooltip.
|
||||
* DON|DOFF lives in the top-left corner; PRV/NXT float left/right.
|
||||
* Called on every draw() so a fresh innerHTML replaces any stale state.
|
||||
*/
|
||||
function _injectTooltipControls() {
|
||||
_tooltipEl = document.getElementById('id_natus_tooltip');
|
||||
if (!_tooltipEl) return;
|
||||
_tooltipEl.innerHTML =
|
||||
`<button type="button" class="btn btn-equip nw-asp-don">DON</button>` +
|
||||
`<button type="button" class="btn btn-unequip btn-disabled nw-asp-doff">DOFF</button>` +
|
||||
'<div class="nw-tt-body"></div>' +
|
||||
'<button type="button" class="btn btn-nav-left nw-tt-prv">PRV</button>' +
|
||||
'<button type="button" class="btn btn-nav-right nw-tt-nxt">NXT</button>';
|
||||
_ttBody = _tooltipEl.querySelector('.nw-tt-body');
|
||||
_tooltipEl.querySelector('.nw-tt-prv').addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
_stepCycle(-1);
|
||||
e.stopPropagation(); _stepCycle(-1);
|
||||
});
|
||||
_tooltipEl.querySelector('.nw-tt-nxt').addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
_stepCycle(1);
|
||||
e.stopPropagation(); _stepCycle(1);
|
||||
});
|
||||
_tooltipEl.querySelector('.nw-asp-don')
|
||||
.addEventListener('click', (e) => { e.stopPropagation(); _toggleAspects(); });
|
||||
_tooltipEl.querySelector('.nw-asp-doff')
|
||||
.addEventListener('click', (e) => { e.stopPropagation(); _toggleAspects(); });
|
||||
// Sync button to current state in case of redraw mid-session.
|
||||
_updateAspectToggleUI();
|
||||
}
|
||||
|
||||
/** Attach a document-level click listener that closes the tooltip when the
|
||||
* user clicks outside the tooltip (including on empty wheel areas).
|
||||
* Planet/element groups stop propagation so their own clicks are not caught. */
|
||||
/** Document-level click listener that closes tooltip when clicking outside. */
|
||||
function _attachOutsideClick() {
|
||||
if (_outsideClickController) _outsideClickController.abort();
|
||||
_outsideClickController = new AbortController();
|
||||
document.addEventListener('click', (e) => {
|
||||
if (_activeRing === null) return;
|
||||
if (_tooltipEl && _tooltipEl.contains(e.target)) return;
|
||||
// DON/DOFF have pointer-events:none when disabled — check bounding rect directly
|
||||
if (_tooltipEl) {
|
||||
for (const cls of ['.nw-asp-don', '.nw-asp-doff', '.nw-tt-prv', '.nw-tt-nxt']) {
|
||||
const btn = _tooltipEl.querySelector(cls);
|
||||
if (!btn) continue;
|
||||
const r = btn.getBoundingClientRect();
|
||||
if (e.clientX >= r.left && e.clientX <= r.right && e.clientY >= r.top && e.clientY <= r.bottom) return;
|
||||
}
|
||||
}
|
||||
_closeTooltip();
|
||||
}, { signal: _outsideClickController.signal });
|
||||
}
|
||||
@@ -327,26 +596,24 @@ const NatusWheel = (() => {
|
||||
const size = Math.min(rect.width || 400, rect.height || 400);
|
||||
_cx = size / 2;
|
||||
_cy = size / 2;
|
||||
// viewBox pins the coordinate system to size×size; preserveAspectRatio
|
||||
// centres it inside the SVG element regardless of its aspect ratio.
|
||||
svgEl.setAttribute('viewBox', `0 0 ${size} ${size}`);
|
||||
svgEl.setAttribute('preserveAspectRatio', 'xMidYMid meet');
|
||||
_r = size * 0.46; // leave a small margin
|
||||
_r = size * 0.46;
|
||||
|
||||
R = {
|
||||
elementInner: _r * 0.20,
|
||||
elementOuter: _r * 0.28,
|
||||
planetInner: _r * 0.32,
|
||||
planetOuter: _r * 0.48,
|
||||
houseInner: _r * 0.50,
|
||||
houseOuter: _r * 0.68,
|
||||
planetInner: _r * 0.50,
|
||||
planetOuter: _r * 0.68,
|
||||
houseInner: _r * 0.32,
|
||||
houseOuter: _r * 0.48,
|
||||
signInner: _r * 0.70,
|
||||
signOuter: _r * 0.90,
|
||||
labelR: _r * 0.80, // sign symbol placement
|
||||
houseNumR: _r * 0.59, // house number placement
|
||||
planetR: _r * 0.40, // planet symbol placement
|
||||
aspectR: _r * 0.29, // aspect lines end here (inner circle)
|
||||
ascMcR: _r * 0.92, // ASC/MC tick outer
|
||||
labelR: _r * 0.80,
|
||||
houseNumR: _r * 0.40,
|
||||
planetR: _r * 0.59,
|
||||
aspectR: _r * 0.29,
|
||||
ascMcR: _r * 0.92,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -389,12 +656,10 @@ const NatusWheel = (() => {
|
||||
const sigGroup = g.append('g').attr('class', 'nw-signs');
|
||||
|
||||
SIGNS.forEach((sign, i) => {
|
||||
const startDeg = i * 30; // ecliptic 0–360
|
||||
const startDeg = i * 30;
|
||||
const endDeg = startDeg + 30;
|
||||
const startA = _toAngle(startDeg, asc);
|
||||
const endA = _toAngle(endDeg, asc);
|
||||
// D3 arc expects startAngle < endAngle in its own convention; we swap
|
||||
// because our _toAngle goes counter-clockwise
|
||||
const [sa, ea] = startA > endA ? [endA, startA] : [startA, endA];
|
||||
|
||||
sigGroup.append('path')
|
||||
@@ -407,22 +672,18 @@ const NatusWheel = (() => {
|
||||
}))
|
||||
.attr('class', `nw-sign--${sign.element.toLowerCase()}`);
|
||||
|
||||
// Icon at midpoint
|
||||
const midA = (sa + ea) / 2;
|
||||
const lx = _cx + R.labelR * Math.cos(midA);
|
||||
const ly = _cy + R.labelR * Math.sin(midA);
|
||||
const cr = _r * 0.065; // slightly larger than planet circles so icons breathe
|
||||
// scale the 640×640 icon viewBox down to 85% of the circle diameter
|
||||
const cr = _r * 0.065;
|
||||
const sf = (cr * 2 * 0.85) / 640;
|
||||
|
||||
// Colored circle behind icon
|
||||
sigGroup.append('circle')
|
||||
.attr('cx', lx)
|
||||
.attr('cy', ly)
|
||||
.attr('r', cr)
|
||||
.attr('class', `nw-sign-icon-bg--${sign.element.toLowerCase()}`);
|
||||
|
||||
// Inline SVG path — translate origin to label centre, scale, re-centre icon
|
||||
if (_signPaths[sign.name]) {
|
||||
sigGroup.append('path')
|
||||
.attr('d', _signPaths[sign.name])
|
||||
@@ -438,19 +699,15 @@ const NatusWheel = (() => {
|
||||
const arc = d3.arc();
|
||||
const houseGroup = g.append('g').attr('class', 'nw-houses');
|
||||
|
||||
// Pre-compute angles; normalise the last house's nextCusp across 360° wrap.
|
||||
const houses = cusps.map((cusp, i) => {
|
||||
let nextCusp = cusps[(i + 1) % 12];
|
||||
if (nextCusp <= cusp) nextCusp += 360; // close the circle for house 12
|
||||
if (nextCusp <= cusp) nextCusp += 360;
|
||||
const startA = _toAngle(cusp, asc);
|
||||
const endA = _toAngle(nextCusp, asc);
|
||||
// _toAngle is strictly decreasing with degree after normalisation,
|
||||
// so startA > endA always — D3 arc needs sa < ea.
|
||||
const sa = endA, ea = startA;
|
||||
return { i, startA, sa, ea, midA: (sa + ea) / 2 };
|
||||
});
|
||||
|
||||
// 1. Fills first so cusp lines + numbers are never buried beneath them.
|
||||
houses.forEach(({ i, sa, ea }) => {
|
||||
houseGroup.append('path')
|
||||
.attr('transform', `translate(${_cx},${_cy})`)
|
||||
@@ -463,14 +720,15 @@ const NatusWheel = (() => {
|
||||
.attr('class', i % 2 === 0 ? 'nw-house-fill--even' : 'nw-house-fill--odd');
|
||||
});
|
||||
|
||||
// 2. Cusp lines + house numbers on top.
|
||||
houses.forEach(({ i, startA, midA }) => {
|
||||
houseGroup.append('line')
|
||||
.attr('x1', _cx + R.houseInner * Math.cos(startA))
|
||||
.attr('y1', _cy + R.houseInner * Math.sin(startA))
|
||||
.attr('x2', _cx + R.signInner * Math.cos(startA))
|
||||
.attr('y2', _cy + R.signInner * Math.sin(startA))
|
||||
.attr('class', 'nw-house-cusp');
|
||||
if (i % 3 === 0) {
|
||||
houseGroup.append('line')
|
||||
.attr('x1', _cx + R.houseInner * Math.cos(startA))
|
||||
.attr('y1', _cy + R.houseInner * Math.sin(startA))
|
||||
.attr('x2', _cx + R.signInner * Math.cos(startA))
|
||||
.attr('y2', _cy + R.signInner * Math.sin(startA))
|
||||
.attr('class', 'nw-house-cusp');
|
||||
}
|
||||
|
||||
houseGroup.append('text')
|
||||
.attr('x', _cx + R.houseNumR * Math.cos(midA))
|
||||
@@ -486,7 +744,7 @@ const NatusWheel = (() => {
|
||||
function _drawPlanets(g, data) {
|
||||
const asc = data.houses.asc;
|
||||
const planetGroup = g.append('g').attr('class', 'nw-planets');
|
||||
const ascAngle = _toAngle(asc, asc); // start position for animation
|
||||
const ascAngle = _toAngle(asc, asc);
|
||||
|
||||
const TICK_OUTER = _r * 0.96;
|
||||
|
||||
@@ -494,8 +752,6 @@ const NatusWheel = (() => {
|
||||
const finalA = _toAngle(pdata.degree, asc);
|
||||
const el = PLANET_ELEMENTS[name] || '';
|
||||
|
||||
// Per-planet group — click event lives here so the symbol text and ℞
|
||||
// indicator don't block mouse events on the circle.
|
||||
const planetEl = planetGroup.append('g')
|
||||
.attr('class', 'nw-planet-group')
|
||||
.attr('data-planet', name)
|
||||
@@ -512,7 +768,6 @@ const NatusWheel = (() => {
|
||||
}
|
||||
});
|
||||
|
||||
// Tick line — from planet circle outward past the zodiac ring
|
||||
const tick = planetEl.append('line')
|
||||
.attr('class', el ? `nw-planet-tick nw-planet-tick--${el}` : 'nw-planet-tick')
|
||||
.attr('x1', _cx + R.planetR * Math.cos(ascAngle))
|
||||
@@ -520,7 +775,6 @@ const NatusWheel = (() => {
|
||||
.attr('x2', _cx + TICK_OUTER * Math.cos(ascAngle))
|
||||
.attr('y2', _cy + TICK_OUTER * Math.sin(ascAngle));
|
||||
|
||||
// Circle behind symbol
|
||||
const circleBase = pdata.retrograde ? 'nw-planet-circle--rx' : 'nw-planet-circle';
|
||||
const circle = planetEl.append('circle')
|
||||
.attr('cx', _cx + R.planetR * Math.cos(ascAngle))
|
||||
@@ -528,7 +782,6 @@ const NatusWheel = (() => {
|
||||
.attr('r', _r * 0.05)
|
||||
.attr('class', el ? `${circleBase} nw-planet--${el}` : circleBase);
|
||||
|
||||
// Symbol — pointer-events:none so click is handled by the group
|
||||
const label = planetEl.append('text')
|
||||
.attr('x', _cx + R.planetR * Math.cos(ascAngle))
|
||||
.attr('y', _cy + R.planetR * Math.sin(ascAngle))
|
||||
@@ -540,7 +793,6 @@ const NatusWheel = (() => {
|
||||
.attr('pointer-events', 'none')
|
||||
.text(PLANET_SYMBOLS[name] || name[0]);
|
||||
|
||||
// Retrograde indicator — also pointer-events:none
|
||||
let rxLabel = null;
|
||||
if (pdata.retrograde) {
|
||||
rxLabel = planetEl.append('text')
|
||||
@@ -554,8 +806,6 @@ const NatusWheel = (() => {
|
||||
.text('℞');
|
||||
}
|
||||
|
||||
// Animate from ASC → final position (staggered)
|
||||
// circle uses cx/cy; text uses x/y — must be separate transitions.
|
||||
const interpAngle = d3.interpolate(ascAngle, finalA);
|
||||
const transition = () => d3.transition()
|
||||
.delay(idx * 40)
|
||||
@@ -584,34 +834,33 @@ const NatusWheel = (() => {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the aspect index (planet → aspects list) and create the persistent
|
||||
* nw-aspects group. Lines are drawn per-planet on click, not here.
|
||||
*/
|
||||
function _drawAspects(g, data) {
|
||||
const asc = data.houses.asc;
|
||||
const aspectGroup = g.append('g').attr('class', 'nw-aspects');
|
||||
_aspectIndex = {};
|
||||
Object.entries(data.planets).forEach(([name]) => { _aspectIndex[name] = []; });
|
||||
|
||||
// Build degree lookup
|
||||
const degrees = {};
|
||||
Object.entries(data.planets).forEach(([name, p]) => { degrees[name] = p.degree; });
|
||||
|
||||
data.aspects.forEach(({ planet1, planet2, type }) => {
|
||||
if (degrees[planet1] === undefined || degrees[planet2] === undefined) return;
|
||||
const a1 = _toAngle(degrees[planet1], asc);
|
||||
const a2 = _toAngle(degrees[planet2], asc);
|
||||
aspectGroup.append('line')
|
||||
.attr('x1', _cx + R.aspectR * Math.cos(a1))
|
||||
.attr('y1', _cy + R.aspectR * Math.sin(a1))
|
||||
.attr('x2', _cx + R.aspectR * Math.cos(a2))
|
||||
.attr('y2', _cy + R.aspectR * Math.sin(a2))
|
||||
.attr('stroke', ASPECT_COLORS[type] || '#888')
|
||||
.attr('stroke-width', type === 'Opposition' || type === 'Square' ? 1.2 : 0.8);
|
||||
data.aspects.forEach(({ planet1, planet2, type, orb, applying_planet }) => {
|
||||
if (!(planet1 in _aspectIndex) || !(planet2 in _aspectIndex)) return;
|
||||
const shared = { type, orb, applying_planet };
|
||||
_aspectIndex[planet1].push({ partner: planet2, ...shared });
|
||||
_aspectIndex[planet2].push({ partner: planet1, ...shared });
|
||||
});
|
||||
|
||||
_aspectGroup = g.append('g').attr('class', 'nw-aspects');
|
||||
}
|
||||
|
||||
function _drawElements(g, data) {
|
||||
const el = data.elements;
|
||||
const total = ELEMENT_ORDER.reduce((s, k) => s + (el[k] || 0), 0);
|
||||
const el = data.elements;
|
||||
const total = ELEMENT_ORDER.reduce((s, k) => s + _elNorm(el[k]).count, 0);
|
||||
if (total === 0) return;
|
||||
|
||||
const pieData = ELEMENT_ORDER.map(k => ({ key: k, value: el[k] || 0 }));
|
||||
const pieData = ELEMENT_ORDER.map(k => ({
|
||||
key: k,
|
||||
value: _elNorm(el[k]).count,
|
||||
}));
|
||||
|
||||
const pie = d3.pie().value(d => d.value).sort(null)(pieData);
|
||||
const arc = d3.arc().innerRadius(R.elementInner).outerRadius(R.elementOuter);
|
||||
@@ -643,12 +892,8 @@ const NatusWheel = (() => {
|
||||
// ── Public API ────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Preload zodiac sign SVGs from `basePath` (default: same dir as this script).
|
||||
* Returns a Promise that resolves when all 12 are cached in _signPaths.
|
||||
* Safe to call multiple times; re-fetches every call so swapped files are picked up.
|
||||
*
|
||||
* To swap a sign icon: replace the corresponding .svg file in zodiac-signs/
|
||||
* and call NatusWheel.preload() before the next draw().
|
||||
* Preload zodiac sign SVGs from `basePath`.
|
||||
* Returns a Promise that resolves when all 12 are cached.
|
||||
*/
|
||||
async function preload(basePath) {
|
||||
const base = basePath ||
|
||||
@@ -686,18 +931,16 @@ const NatusWheel = (() => {
|
||||
|
||||
const g = _svg.append('g').attr('class', 'nw-root');
|
||||
|
||||
// Outer circle border
|
||||
g.append('circle')
|
||||
.attr('cx', _cx).attr('cy', _cy).attr('r', R.signOuter)
|
||||
.attr('class', 'nw-outer-ring');
|
||||
|
||||
// Inner filled disc (aspect area background)
|
||||
g.append('circle')
|
||||
.attr('cx', _cx).attr('cy', _cy).attr('r', R.elementOuter)
|
||||
.attr('class', 'nw-inner-disc');
|
||||
|
||||
_drawAspects(g, data);
|
||||
_drawElements(g, data);
|
||||
_drawAspects(g, data); // above element ring, below houses/signs/planets
|
||||
_drawHouses(g, data);
|
||||
_drawSigns(g, data);
|
||||
_drawAscMc(g, data);
|
||||
@@ -706,8 +949,7 @@ const NatusWheel = (() => {
|
||||
|
||||
function redraw(data) {
|
||||
if (!_svg) return;
|
||||
const svgNode = _svg.node();
|
||||
draw(svgNode, data);
|
||||
draw(_svg.node(), data);
|
||||
}
|
||||
|
||||
function clear() {
|
||||
@@ -717,6 +959,10 @@ const NatusWheel = (() => {
|
||||
_outsideClickController.abort();
|
||||
_outsideClickController = null;
|
||||
}
|
||||
_aspectsVisible = false;
|
||||
_aspectPlanet = null;
|
||||
_aspectGroup = null;
|
||||
_currentData = null;
|
||||
}
|
||||
|
||||
return { preload, draw, redraw, clear };
|
||||
|
||||
@@ -282,6 +282,155 @@ describe("NatusWheel — tick lines, raise, and cycle navigation", () => {
|
||||
// x ≥ 200 (right side): left = iRect.right - ttW = x + 10 - 0 = x + 10
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// ── DON / DOFF aspect line persistence ───────────────────────────────────────
|
||||
//
|
||||
// Aspect lines belong to the page session, not the tooltip:
|
||||
// - DON draws lines into .nw-aspects and disables DON btn (shows ×)
|
||||
// - closing the tooltip does NOT clear lines
|
||||
// - re-opening the SAME planet preserves _aspectsVisible → DON still disabled
|
||||
// - opening a DIFFERENT planet resets state: lines cleared, DON active
|
||||
// - DOFF clears lines; re-opening same planet finds DON active
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe("NatusWheel — DON/DOFF aspect line persistence", () => {
|
||||
|
||||
const ASPECT_CHART = {
|
||||
planets: {
|
||||
Sun: { sign: "Capricorn", degree: 280.4, retrograde: false },
|
||||
Moon: { sign: "Scorpio", degree: 220.1, retrograde: false },
|
||||
Mars: { sign: "Taurus", degree: 40.7, retrograde: false },
|
||||
},
|
||||
houses: {
|
||||
cusps: [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330],
|
||||
asc: 0, mc: 270,
|
||||
},
|
||||
elements: { Fire: 0, Stone: 0, Air: 0, Water: 1, Time: 0, Space: 0 },
|
||||
aspects: [
|
||||
{ planet1: "Sun", planet2: "Mars", type: "Trine",
|
||||
orb: 0.3, angle: 120, applying_planet: "Sun" },
|
||||
{ planet1: "Sun", planet2: "Moon", type: "Sextile",
|
||||
orb: 2.9, angle: 60, applying_planet: "Moon" },
|
||||
],
|
||||
distinctions: {
|
||||
"1": 0, "2": 0, "3": 0, "4": 0,
|
||||
"5": 0, "6": 0, "7": 0, "8": 0,
|
||||
"9": 0, "10": 0, "11": 0, "12": 0,
|
||||
},
|
||||
house_system: "O",
|
||||
};
|
||||
|
||||
let svgEl, tooltipEl;
|
||||
|
||||
beforeEach(() => {
|
||||
svgEl = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
svgEl.setAttribute("id", "id_natus_svg");
|
||||
svgEl.setAttribute("width", "400");
|
||||
svgEl.setAttribute("height", "400");
|
||||
svgEl.style.width = "400px";
|
||||
svgEl.style.height = "400px";
|
||||
document.body.appendChild(svgEl);
|
||||
|
||||
tooltipEl = document.createElement("div");
|
||||
tooltipEl.id = "id_natus_tooltip";
|
||||
tooltipEl.className = "tt";
|
||||
tooltipEl.style.display = "none";
|
||||
document.body.appendChild(tooltipEl);
|
||||
|
||||
NatusWheel.draw(svgEl, ASPECT_CHART);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
NatusWheel.clear();
|
||||
svgEl.remove();
|
||||
tooltipEl.remove();
|
||||
});
|
||||
|
||||
function clickPlanet(name) {
|
||||
svgEl.querySelector(`[data-planet="${name}"]`)
|
||||
.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
}
|
||||
function clickDon() { tooltipEl.querySelector(".nw-asp-don") .dispatchEvent(new MouseEvent("click", { bubbles: true })); }
|
||||
function clickDoff() { tooltipEl.querySelector(".nw-asp-doff").dispatchEvent(new MouseEvent("click", { bubbles: true })); }
|
||||
function aspectLines() { return svgEl.querySelectorAll(".nw-aspects line").length; }
|
||||
function donDisabled() { return tooltipEl.querySelector(".nw-asp-don").classList.contains("btn-disabled"); }
|
||||
|
||||
// T11a — DON draws lines
|
||||
it("T11a: clicking DON draws aspect lines into .nw-aspects", () => {
|
||||
clickPlanet("Sun");
|
||||
expect(aspectLines()).toBe(0);
|
||||
clickDon();
|
||||
expect(aspectLines()).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
// T11b — closing tooltip must not clear aspect lines
|
||||
it("T11b: closing the tooltip (outside click) does not clear aspect lines", () => {
|
||||
clickPlanet("Sun");
|
||||
clickDon();
|
||||
const lineCount = aspectLines();
|
||||
expect(lineCount).toBeGreaterThan(0);
|
||||
|
||||
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
expect(tooltipEl.style.display).toBe("none");
|
||||
expect(aspectLines()).toBe(lineCount);
|
||||
});
|
||||
|
||||
// T11c — re-opening same planet preserves DON-disabled state
|
||||
it("T11c: re-opening the same planet after DON keeps DON disabled (lines still active)", () => {
|
||||
clickPlanet("Sun");
|
||||
clickDon();
|
||||
expect(donDisabled()).toBe(true);
|
||||
|
||||
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
clickPlanet("Sun");
|
||||
|
||||
expect(donDisabled()).toBe(true);
|
||||
expect(aspectLines()).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
// T11d — switching planet leaves previous DONned lines intact; DON active for new planet
|
||||
it("T11d: opening a different planet leaves DONned lines intact — DON active for new planet", () => {
|
||||
clickPlanet("Sun");
|
||||
clickDon();
|
||||
const lineCount = aspectLines();
|
||||
expect(lineCount).toBeGreaterThan(0);
|
||||
|
||||
clickPlanet("Moon");
|
||||
|
||||
expect(donDisabled()).toBe(false); // Moon's DON is fresh/active
|
||||
expect(aspectLines()).toBe(lineCount); // Sun's lines still there
|
||||
});
|
||||
|
||||
// T11f — DONning a second planet replaces the first planet's lines + tick
|
||||
it("T11f: clicking DON on a second planet clears the first planet's lines", () => {
|
||||
clickPlanet("Sun");
|
||||
clickDon();
|
||||
expect(aspectLines()).toBeGreaterThan(0);
|
||||
|
||||
clickPlanet("Moon");
|
||||
clickDon();
|
||||
|
||||
expect(donDisabled()).toBe(true); // Moon's DON now disabled
|
||||
// Moon aspects — Sun's lines replaced (lines may be 0 if Moon has no aspects)
|
||||
const sunGrp = svgEl.querySelector('[data-planet="Sun"]');
|
||||
expect(sunGrp.classList.contains('nw-planet--asp-active')).toBe(false);
|
||||
});
|
||||
|
||||
// T11e — DOFF clears lines; re-opening same planet starts fresh
|
||||
it("T11e: DOFF clears lines; re-opening same planet finds DON active again", () => {
|
||||
clickPlanet("Sun");
|
||||
clickDon();
|
||||
clickDoff();
|
||||
expect(aspectLines()).toBe(0);
|
||||
|
||||
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
clickPlanet("Sun");
|
||||
|
||||
expect(donDisabled()).toBe(false);
|
||||
expect(aspectLines()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
xdescribe("NatusWheel — half-wheel tooltip positioning", () => {
|
||||
|
||||
const HALF_CHART = {
|
||||
|
||||
@@ -450,7 +450,8 @@ html.natus-open .natus-modal-wrap {
|
||||
stroke-linecap: round;
|
||||
transition: stroke-opacity 0.15s ease;
|
||||
}
|
||||
.nw-planet-group.nw-planet--active .nw-planet-tick {
|
||||
.nw-planet-group.nw-planet--active .nw-planet-tick,
|
||||
.nw-planet-group.nw-planet--asp-active .nw-planet-tick {
|
||||
stroke: rgba(var(--terUser), 1);
|
||||
stroke-opacity: 0.7;
|
||||
filter: drop-shadow(0 0 3px rgba(var(--terUser), 0.8))
|
||||
@@ -467,7 +468,21 @@ html.natus-open .natus-modal-wrap {
|
||||
.nw-planet-tick--np { stroke: rgba(var(--priNp), 1); }
|
||||
.nw-planet-tick--pu { stroke: rgba(var(--priPu), 1); }
|
||||
|
||||
// Aspects
|
||||
// Aspects — per-planet color tokens (light shades on dark palettes; mid on light)
|
||||
:root {
|
||||
--asp-Au: var(--sixAu); --asp-Ag: var(--sixAg);
|
||||
--asp-Hg: var(--sixHg); --asp-Cu: var(--sixCu);
|
||||
--asp-Fe: var(--sixFe); --asp-Sn: var(--sixSn);
|
||||
--asp-Pb: var(--sixPb); --asp-U: var(--sixU);
|
||||
--asp-Np: var(--sixNp); --asp-Pu: var(--sixPu);
|
||||
}
|
||||
body[class*="-light"] {
|
||||
--asp-Au: var(--terAu); --asp-Ag: var(--terAg);
|
||||
--asp-Hg: var(--terHg); --asp-Cu: var(--terCu);
|
||||
--asp-Fe: var(--terFe); --asp-Sn: var(--terSn);
|
||||
--asp-Pb: var(--terPb); --asp-U: var(--terU);
|
||||
--asp-Np: var(--terNp); --asp-Pu: var(--terPu);
|
||||
}
|
||||
.nw-aspects { opacity: 0.8; }
|
||||
|
||||
// Element pie — deasil order: Fire → Stone → Time → Space → Air → Water
|
||||
@@ -487,12 +502,24 @@ html.natus-open .natus-modal-wrap {
|
||||
position: fixed;
|
||||
z-index: 200;
|
||||
pointer-events: auto;
|
||||
padding: 0.75rem 1.5rem;
|
||||
padding: 0.75rem 0.75rem 0.75rem 1.5rem;
|
||||
min-width: 14rem;
|
||||
|
||||
.tt-title { font-size: 1rem; font-weight: 700; }
|
||||
.tt-title { font-size: 1.25rem; font-weight: 700; margin-bottom: 0.3rem; }
|
||||
.tt-description { font-size: 0.75rem; }
|
||||
.tt-sign-icon { fill: currentColor; vertical-align: middle; margin-bottom: 0.1em; }
|
||||
|
||||
// DON|DOFF aspect line toggle — stacked at top-left outside the tooltip box,
|
||||
// matching the PRV/NXT pattern at the bottom corners.
|
||||
.nw-asp-don,
|
||||
.nw-asp-doff {
|
||||
position: absolute;
|
||||
left: -1rem;
|
||||
margin: 0;
|
||||
}
|
||||
.nw-asp-don { top: -1rem; }
|
||||
.nw-asp-doff { top: 1.2rem; }
|
||||
|
||||
.nw-tt-prv,
|
||||
.nw-tt-nxt {
|
||||
position: absolute;
|
||||
@@ -502,6 +529,82 @@ html.natus-open .natus-modal-wrap {
|
||||
.nw-tt-prv { left: -1rem; }
|
||||
.nw-tt-nxt { right: -1rem; }
|
||||
|
||||
// Aspect list — always visible below planet description
|
||||
.tt-aspects {
|
||||
display: block;
|
||||
margin-top: 0.6rem;
|
||||
font-size: 0.94rem;
|
||||
font-weight: 600;
|
||||
opacity: 0.85;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.tt-asp-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tt-asp-line { flex-shrink: 0; vertical-align: middle; }
|
||||
|
||||
.tt-asp-orb,
|
||||
.tt-asp-in {
|
||||
opacity: 0.6;
|
||||
font-size: 0.65rem;
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
|
||||
// Element tooltip — title + square badge
|
||||
.tt-el-header {
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.tt-el-square {
|
||||
float: right;
|
||||
display: block;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.tt-el-vec {
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
margin: 0 0.1em;
|
||||
}
|
||||
|
||||
.tt-el-body-line {
|
||||
font-size: 0.75rem;
|
||||
opacity: 0.9;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.tt-el-contribs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.2rem;
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
|
||||
.tt-el-planet-row {
|
||||
opacity: 0.75;
|
||||
margin-left: 0.5rem;
|
||||
margin-top: -0.1rem;
|
||||
}
|
||||
|
||||
.tt-el-formation-header {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
margin-top: 0.35rem;
|
||||
}
|
||||
|
||||
.tt-el-formation {
|
||||
font-size: 0.75rem;
|
||||
opacity: 0.7;
|
||||
margin-top: 0.2rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
// Planet title colors — senary (brightest) tier on dark palettes
|
||||
.tt-title--au { color: rgba(var(--sixAu), 1); } // Sun
|
||||
.tt-title--ag { color: rgba(var(--sixAg), 1); } // Moon
|
||||
|
||||
@@ -126,49 +126,49 @@
|
||||
--priOr: 225, 133, 40;
|
||||
--secOr: 187, 111, 30;
|
||||
--terOr: 150, 88, 17;
|
||||
// yellow (
|
||||
// yellow (A-Time)
|
||||
--priYl: 255, 207, 52;
|
||||
--secYl: 211, 172, 44;
|
||||
--terYl: 168, 138, 33;
|
||||
// lime
|
||||
// lime (B-Time)
|
||||
--priLm: 151, 174, 60;
|
||||
--secLm: 124, 145, 48;
|
||||
--terLm: 97, 117, 36;
|
||||
// green
|
||||
// green (A-Space)
|
||||
--priGn: 0, 160, 75;
|
||||
--secGn: 0, 135, 62;
|
||||
--terGn: 0, 109, 48;
|
||||
// teal
|
||||
// teal (B-Space)
|
||||
--priTk: 0, 184, 162;
|
||||
--secTk: 0, 154, 136;
|
||||
--terTk: 0, 125, 110;
|
||||
// cyan
|
||||
// cyan (A-Air)
|
||||
--priCy: 13, 179, 200;
|
||||
--secCy: 12, 150, 168;
|
||||
--terCy: 0, 121, 136;
|
||||
// blue
|
||||
// blue (B-Air)
|
||||
--priBl: 20, 141, 205;
|
||||
--secBl: 18, 119, 173;
|
||||
--terBl: 8, 95, 140;
|
||||
// indigo
|
||||
// indigo (A-Water)
|
||||
--priId: 79, 102, 212;
|
||||
--secId: 66, 88, 184;
|
||||
--terId: 53, 74, 156;
|
||||
--quaId: 44, 60, 131;
|
||||
--quiId: 32, 44, 106;
|
||||
--sixId: 21, 29, 71;
|
||||
// violet
|
||||
// violet (B-Water)
|
||||
--priVt: 120, 72, 183;
|
||||
--secVt: 108, 65, 165;
|
||||
--terVt: 96, 58, 147;
|
||||
--quaVt: 80, 45, 124;
|
||||
--quiVt: 64, 30, 100;
|
||||
--sixVt: 43, 20, 66;
|
||||
// fuschia
|
||||
// fuschia (A-Stone)
|
||||
--priFs: 158, 61, 150;
|
||||
--secFs: 133, 47, 126;
|
||||
--terFs: 107, 31, 101;
|
||||
// magenta
|
||||
// magenta (B-Stone)
|
||||
--priMe: 237, 30, 129;
|
||||
--secMe: 196, 18, 108;
|
||||
--terMe: 158, 1, 86;
|
||||
|
||||
@@ -282,6 +282,155 @@ describe("NatusWheel — tick lines, raise, and cycle navigation", () => {
|
||||
// x ≥ 200 (right side): left = iRect.right - ttW = x + 10 - 0 = x + 10
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// ── DON / DOFF aspect line persistence ───────────────────────────────────────
|
||||
//
|
||||
// Aspect lines belong to the page session, not the tooltip:
|
||||
// - DON draws lines into .nw-aspects and disables DON btn (shows ×)
|
||||
// - closing the tooltip does NOT clear lines
|
||||
// - re-opening the SAME planet preserves _aspectsVisible → DON still disabled
|
||||
// - opening a DIFFERENT planet resets state: lines cleared, DON active
|
||||
// - DOFF clears lines; re-opening same planet finds DON active
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe("NatusWheel — DON/DOFF aspect line persistence", () => {
|
||||
|
||||
const ASPECT_CHART = {
|
||||
planets: {
|
||||
Sun: { sign: "Capricorn", degree: 280.4, retrograde: false },
|
||||
Moon: { sign: "Scorpio", degree: 220.1, retrograde: false },
|
||||
Mars: { sign: "Taurus", degree: 40.7, retrograde: false },
|
||||
},
|
||||
houses: {
|
||||
cusps: [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330],
|
||||
asc: 0, mc: 270,
|
||||
},
|
||||
elements: { Fire: 0, Stone: 0, Air: 0, Water: 1, Time: 0, Space: 0 },
|
||||
aspects: [
|
||||
{ planet1: "Sun", planet2: "Mars", type: "Trine",
|
||||
orb: 0.3, angle: 120, applying_planet: "Sun" },
|
||||
{ planet1: "Sun", planet2: "Moon", type: "Sextile",
|
||||
orb: 2.9, angle: 60, applying_planet: "Moon" },
|
||||
],
|
||||
distinctions: {
|
||||
"1": 0, "2": 0, "3": 0, "4": 0,
|
||||
"5": 0, "6": 0, "7": 0, "8": 0,
|
||||
"9": 0, "10": 0, "11": 0, "12": 0,
|
||||
},
|
||||
house_system: "O",
|
||||
};
|
||||
|
||||
let svgEl, tooltipEl;
|
||||
|
||||
beforeEach(() => {
|
||||
svgEl = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
svgEl.setAttribute("id", "id_natus_svg");
|
||||
svgEl.setAttribute("width", "400");
|
||||
svgEl.setAttribute("height", "400");
|
||||
svgEl.style.width = "400px";
|
||||
svgEl.style.height = "400px";
|
||||
document.body.appendChild(svgEl);
|
||||
|
||||
tooltipEl = document.createElement("div");
|
||||
tooltipEl.id = "id_natus_tooltip";
|
||||
tooltipEl.className = "tt";
|
||||
tooltipEl.style.display = "none";
|
||||
document.body.appendChild(tooltipEl);
|
||||
|
||||
NatusWheel.draw(svgEl, ASPECT_CHART);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
NatusWheel.clear();
|
||||
svgEl.remove();
|
||||
tooltipEl.remove();
|
||||
});
|
||||
|
||||
function clickPlanet(name) {
|
||||
svgEl.querySelector(`[data-planet="${name}"]`)
|
||||
.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
}
|
||||
function clickDon() { tooltipEl.querySelector(".nw-asp-don") .dispatchEvent(new MouseEvent("click", { bubbles: true })); }
|
||||
function clickDoff() { tooltipEl.querySelector(".nw-asp-doff").dispatchEvent(new MouseEvent("click", { bubbles: true })); }
|
||||
function aspectLines() { return svgEl.querySelectorAll(".nw-aspects line").length; }
|
||||
function donDisabled() { return tooltipEl.querySelector(".nw-asp-don").classList.contains("btn-disabled"); }
|
||||
|
||||
// T11a — DON draws lines
|
||||
it("T11a: clicking DON draws aspect lines into .nw-aspects", () => {
|
||||
clickPlanet("Sun");
|
||||
expect(aspectLines()).toBe(0);
|
||||
clickDon();
|
||||
expect(aspectLines()).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
// T11b — closing tooltip must not clear aspect lines
|
||||
it("T11b: closing the tooltip (outside click) does not clear aspect lines", () => {
|
||||
clickPlanet("Sun");
|
||||
clickDon();
|
||||
const lineCount = aspectLines();
|
||||
expect(lineCount).toBeGreaterThan(0);
|
||||
|
||||
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
expect(tooltipEl.style.display).toBe("none");
|
||||
expect(aspectLines()).toBe(lineCount);
|
||||
});
|
||||
|
||||
// T11c — re-opening same planet preserves DON-disabled state
|
||||
it("T11c: re-opening the same planet after DON keeps DON disabled (lines still active)", () => {
|
||||
clickPlanet("Sun");
|
||||
clickDon();
|
||||
expect(donDisabled()).toBe(true);
|
||||
|
||||
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
clickPlanet("Sun");
|
||||
|
||||
expect(donDisabled()).toBe(true);
|
||||
expect(aspectLines()).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
// T11d — switching planet leaves previous DONned lines intact; DON active for new planet
|
||||
it("T11d: opening a different planet leaves DONned lines intact — DON active for new planet", () => {
|
||||
clickPlanet("Sun");
|
||||
clickDon();
|
||||
const lineCount = aspectLines();
|
||||
expect(lineCount).toBeGreaterThan(0);
|
||||
|
||||
clickPlanet("Moon");
|
||||
|
||||
expect(donDisabled()).toBe(false); // Moon's DON is fresh/active
|
||||
expect(aspectLines()).toBe(lineCount); // Sun's lines still there
|
||||
});
|
||||
|
||||
// T11f — DONning a second planet replaces the first planet's lines + tick
|
||||
it("T11f: clicking DON on a second planet clears the first planet's lines", () => {
|
||||
clickPlanet("Sun");
|
||||
clickDon();
|
||||
expect(aspectLines()).toBeGreaterThan(0);
|
||||
|
||||
clickPlanet("Moon");
|
||||
clickDon();
|
||||
|
||||
expect(donDisabled()).toBe(true); // Moon's DON now disabled
|
||||
// Moon aspects — Sun's lines replaced (lines may be 0 if Moon has no aspects)
|
||||
const sunGrp = svgEl.querySelector('[data-planet="Sun"]');
|
||||
expect(sunGrp.classList.contains('nw-planet--asp-active')).toBe(false);
|
||||
});
|
||||
|
||||
// T11e — DOFF clears lines; re-opening same planet starts fresh
|
||||
it("T11e: DOFF clears lines; re-opening same planet finds DON active again", () => {
|
||||
clickPlanet("Sun");
|
||||
clickDon();
|
||||
clickDoff();
|
||||
expect(aspectLines()).toBe(0);
|
||||
|
||||
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
clickPlanet("Sun");
|
||||
|
||||
expect(donDisabled()).toBe(false);
|
||||
expect(aspectLines()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
xdescribe("NatusWheel — half-wheel tooltip positioning", () => {
|
||||
|
||||
const HALF_CHART = {
|
||||
|
||||