natus wheel: ASC/MC angles — tooltips, aspect lines, section headers, tooltip polish
- ASC/MC clickable w. DON/DOFF aspect lines (fixed: open w.o. lines; DON/DOFF both work; angles ring handled in _toggleAspects; lines origin at R.planetR) - btn-disabled click-through fix: pointer-events:auto on DON/DOFF; bounding-rect workaround removed - planet tooltip: applying ⇥ left, separating ↦ right; sign shown for angle partners - sign tooltip: Planets + Cusps section headers; ordinal house + domain; em-dash fallback - house tooltip: Planets header; Angular/Succedent/Cadent + phase labels; em-dash fallback - element tooltips: Planets header for Fire/Stone/Air/Water; Stellium/Parade as section-header labels; compact single-stellium Tempo; Parade sign : planets format - tt-ord: no negative margin in .tt-angle-house context Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -373,33 +373,33 @@ html.natus-open .natus-modal-wrap {
|
||||
.nw-axis-line { stroke: rgba(var(--secUser), 1); stroke-width: 1.5px; }
|
||||
.nw-axis-label { fill: rgba(var(--secUser), 1); }
|
||||
|
||||
// Sign ring — uniform --priMe bg at half opacity
|
||||
// Sign ring — uniform --priYl bg at half opacity
|
||||
.nw-sign--fire,
|
||||
.nw-sign--stone,
|
||||
.nw-sign--air,
|
||||
.nw-sign--water {
|
||||
fill: rgba(var(--priMe), 0.25);
|
||||
fill: rgba(var(--priYl), 0.25);
|
||||
stroke: rgba(var(--terUser), 1);
|
||||
stroke-width: 0.75px;
|
||||
}
|
||||
|
||||
// Icon bg circles — element fill + matching border
|
||||
.nw-sign-icon-bg--fire { fill: rgba(var(--terRd), 0.92); stroke: rgba(var(--priOr), 1); stroke-width: 1px; }
|
||||
.nw-sign-icon-bg--stone { fill: rgba(var(--priYl), 0.92); stroke: rgba(var(--priLm), 1); stroke-width: 1px; }
|
||||
.nw-sign-icon-bg--air { fill: rgba(var(--terGn), 0.92); stroke: rgba(var(--priTk), 1); stroke-width: 1px; }
|
||||
.nw-sign-icon-bg--water { fill: rgba(var(--priCy), 0.92); stroke: rgba(var(--priBl), 1); stroke-width: 1px; }
|
||||
.nw-sign-icon-bg--fire { fill: rgba(var(--quaRd), 0.92); stroke: rgba(var(--priOr), 1); stroke-width: 1px; }
|
||||
.nw-sign-icon-bg--stone { fill: rgba(var(--quaFs), 0.92); stroke: rgba(var(--priMe), 1); stroke-width: 1px; }
|
||||
.nw-sign-icon-bg--air { fill: rgba(var(--quiCy), 0.92); stroke: rgba(var(--priBl), 1); stroke-width: 1px; }
|
||||
.nw-sign-icon-bg--water { fill: rgba(var(--sixId), 0.92); stroke: rgba(var(--priVt), 1); stroke-width: 1px; }
|
||||
|
||||
// Inline SVG path icons — per-element colors
|
||||
.nw-sign-icon--fire { fill: rgba(var(--priOr), 1); text-shadow: 2px 2px 2px rgba(0, 0, 0, 1); }
|
||||
.nw-sign-icon--stone { fill: rgba(var(--terLm), 1); text-shadow: 2px 2px 2px rgba(0, 0, 0, 1); }
|
||||
.nw-sign-icon--air { fill: rgba(var(--priTk), 1); text-shadow: 2px 2px 2px rgba(0, 0, 0, 1); }
|
||||
.nw-sign-icon--water { fill: rgba(var(--terBl), 1); text-shadow: 2px 2px 2px rgba(0, 0, 0, 1); }
|
||||
.nw-sign-icon--fire { fill: rgba(var(--priOr), 1); }
|
||||
.nw-sign-icon--stone { fill: rgba(var(--priMe), 1); }
|
||||
.nw-sign-icon--air { fill: rgba(var(--priBl), 1); }
|
||||
.nw-sign-icon--water { fill: rgba(var(--priVt), 1); }
|
||||
|
||||
// House ring — uniform --priFs bg
|
||||
// House ring — uniform --priGn bg
|
||||
.nw-house-cusp { stroke: rgba(var(--terUser), 1); stroke-width: 1.2px; }
|
||||
.nw-house-num { fill: rgba(var(--ninUser), 1); }
|
||||
.nw-house-fill--even { fill: rgba(var(--priFs), 0.25); stroke: rgba(var(--terUser), 1); stroke-width: 0.75px; }
|
||||
.nw-house-fill--odd { fill: rgba(var(--priFs), 0.25); stroke: rgba(var(--terUser), 1); stroke-width: 0.75px; }
|
||||
.nw-house-fill--even { fill: rgba(var(--secGn), 0.25); stroke: rgba(var(--terUser), 1); stroke-width: 0.75px; }
|
||||
.nw-house-fill--odd { fill: rgba(var(--quiGn), 0.25); stroke: rgba(var(--terUser), 1); stroke-width: 0.75px; }
|
||||
|
||||
// Planets — base geometry
|
||||
.nw-planet-circle,
|
||||
@@ -431,17 +431,34 @@ html.natus-open .natus-modal-wrap {
|
||||
.nw-planet-label--pu { fill: rgba(var(--sixPu), 1); stroke: rgba(var(--sixPu), 0.6); }
|
||||
.nw-rx { fill: rgba(var(--terUser), 1); }
|
||||
|
||||
// Hover and active-lock glow — planet groups and element slice groups
|
||||
// Hover and active-lock glow — planet, element, sign, house groups
|
||||
.nw-planet-group,
|
||||
.nw-element-group { cursor: pointer; }
|
||||
.nw-element-group,
|
||||
.nw-sign-group,
|
||||
.nw-house-group { cursor: pointer; }
|
||||
|
||||
.nw-planet-group:hover,
|
||||
.nw-planet-group.nw-planet--active,
|
||||
.nw-planet-group.nw-planet--asp-active,
|
||||
.nw-element-group:hover,
|
||||
.nw-element-group.nw-element--active {
|
||||
.nw-element-group.nw-element--active,
|
||||
.nw-sign-group:hover,
|
||||
.nw-sign-group.nw-sign--active,
|
||||
.nw-house-group:hover,
|
||||
.nw-house-group.nw-house--active {
|
||||
filter: drop-shadow(0 0 5px rgba(var(--ninUser), 0.9));
|
||||
}
|
||||
|
||||
// Zodiac icon circles — muted by default, full opacity on hover/active
|
||||
.nw-sign-icon-bg { opacity: 0.5; }
|
||||
.nw-sign-group:hover .nw-sign-icon-bg,
|
||||
.nw-sign-group.nw-sign--active .nw-sign-icon-bg { opacity: 1; }
|
||||
|
||||
// House numbers — muted by default, full opacity on hover/active
|
||||
.nw-house-num { opacity: 0.75; }
|
||||
.nw-house-group:hover .nw-house-num,
|
||||
.nw-house-group.nw-house--active .nw-house-num { opacity: 1; }
|
||||
|
||||
// ── Planet tick lines — hidden until parent group is active ──────────────────
|
||||
.nw-planet-tick {
|
||||
fill: none;
|
||||
@@ -521,6 +538,14 @@ body[class*="-light"] {
|
||||
font-size: 1.2rem;
|
||||
opacity: 0.85;
|
||||
}
|
||||
.tt-angle-sym {
|
||||
font-variant-caps: all-small-caps;
|
||||
font-size: 1.1rem;
|
||||
opacity: 0.85;
|
||||
}
|
||||
.tt-angle-house .tt-ord {
|
||||
margin-left: 0;
|
||||
}
|
||||
.tt-planet-loc {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -560,6 +585,19 @@ body[class*="-light"] {
|
||||
margin-top: 0.1rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.tt-sign-section-header {
|
||||
font-size: 0.65rem;
|
||||
font-weight: 600;
|
||||
opacity: 0.55;
|
||||
letter-spacing: 0.04em;
|
||||
margin-bottom: 0.15rem;
|
||||
}
|
||||
.tt-sign-cusps {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.15rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
// House tooltip — "House of X" | number; planets in house
|
||||
.tt-house-header {
|
||||
@@ -581,12 +619,24 @@ body[class*="-light"] {
|
||||
opacity: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.tt-house-type {
|
||||
display: block;
|
||||
font-size: 0.6em;
|
||||
font-weight: 400;
|
||||
opacity: 0.7;
|
||||
margin-top: 0.1em;
|
||||
}
|
||||
.tt-house-planets {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.15rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.tt-house-planet-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
|
||||
// DON|DOFF aspect line toggle — stacked at top-left outside the tooltip box,
|
||||
// matching the PRV/NXT pattern at the bottom corners.
|
||||
@@ -595,6 +645,7 @@ body[class*="-light"] {
|
||||
position: absolute;
|
||||
left: -1rem;
|
||||
margin: 0;
|
||||
pointer-events: auto; // override btn-disabled; click must land here, not pass through to SVG
|
||||
}
|
||||
.nw-asp-don { top: -1rem; }
|
||||
.nw-asp-doff { top: 1.2rem; }
|
||||
@@ -627,12 +678,30 @@ body[class*="-light"] {
|
||||
|
||||
.tt-asp-line { flex-shrink: 0; vertical-align: middle; }
|
||||
|
||||
.tt-asp-orb,
|
||||
.tt-asp-orb {
|
||||
margin-left: auto;
|
||||
opacity: 0.6;
|
||||
font-size: 0.65rem;
|
||||
padding-left: 0.5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tt-asp-in {
|
||||
opacity: 0.6;
|
||||
font-size: 0.65rem;
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
.tt-dim {
|
||||
opacity: 0.6;
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
.tt-ord {
|
||||
font-size: 0.6rem;
|
||||
vertical-align: 0.25rem;
|
||||
line-height: 0;
|
||||
opacity: 1;
|
||||
margin-left: -0.25rem;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
// Element tooltip — title + square badge
|
||||
.tt-el-header {
|
||||
@@ -672,9 +741,14 @@ body[class*="-light"] {
|
||||
|
||||
.tt-el-formation-header {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
font-weight: 700;
|
||||
margin-top: 0.35rem;
|
||||
.tt-el-formation-label {
|
||||
font-size: 0.65rem;
|
||||
font-weight: 600;
|
||||
opacity: 0.55;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
}
|
||||
|
||||
.tt-el-formation {
|
||||
@@ -708,6 +782,24 @@ body[class*="-light"] {
|
||||
.tt-title--el-water { color: rgba(var(--priId), 1); }
|
||||
}
|
||||
|
||||
// Sign tooltip title + sign icon SVG — element border colors (Stone/Air/Fire/Water schema)
|
||||
#id_natus_tooltip,
|
||||
#id_natus_tooltip_2 {
|
||||
.tt-title--sign-fire { color: rgba(var(--priOr), 1); }
|
||||
.tt-title--sign-stone { color: rgba(var(--priMe), 1); }
|
||||
.tt-title--sign-air { color: rgba(var(--priBl), 1); }
|
||||
.tt-title--sign-water { color: rgba(var(--priVt), 1); }
|
||||
|
||||
.tt-sign-icon-wrap--fire .tt-sign-icon,
|
||||
.tt-planet-sign-icon--fire .tt-sign-icon { fill: rgba(var(--priOr), 1); }
|
||||
.tt-sign-icon-wrap--stone .tt-sign-icon,
|
||||
.tt-planet-sign-icon--stone .tt-sign-icon { fill: rgba(var(--priMe), 1); }
|
||||
.tt-sign-icon-wrap--air .tt-sign-icon,
|
||||
.tt-planet-sign-icon--air .tt-sign-icon { fill: rgba(var(--priBl), 1); }
|
||||
.tt-sign-icon-wrap--water .tt-sign-icon,
|
||||
.tt-planet-sign-icon--water .tt-sign-icon { fill: rgba(var(--priVt), 1); }
|
||||
}
|
||||
|
||||
// On light palettes — switch to tertiary tier for legibility
|
||||
body[class*="-light"] #id_natus_tooltip,
|
||||
body[class*="-light"] #id_natus_tooltip_2 {
|
||||
|
||||
@@ -819,3 +819,137 @@ describe("NatusWheel — house ring click tooltips", () => {
|
||||
expect(tooltipEl.style.display).toBe("none");
|
||||
});
|
||||
});
|
||||
|
||||
// ── T15 — ASC / MC angle click tooltips + aspect lines ────────────────────────
|
||||
//
|
||||
// ASC and MC labels are clickable groups ([data-angle='ASC'] / [data-angle='MC']).
|
||||
// Clicking shows a tooltip similar to a planet tooltip:
|
||||
// Title: "Ascendant" (ASC) or "Midheaven" (MC)
|
||||
// Degree in sign + sign name, plus the house number the angle defines.
|
||||
// Aspect list for planets within 10° orb of the angle (client-side computed).
|
||||
// Aspect lines drawn to those planets.
|
||||
// Clicking same angle again closes the tooltip.
|
||||
// Planet tooltips include angle aspects in their own aspect lists.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe("NatusWheel — angle (ASC/MC) click tooltips", () => {
|
||||
|
||||
// ASC=0°(Aries): Sun@8° → Conjunction orb 8° ✓; Mars@188° → Opposition orb 8° ✓
|
||||
// MC=90°(Cancer): Moon@97° → Conjunction orb 7° ✓
|
||||
const ANGLE_CHART = {
|
||||
planets: {
|
||||
Sun: { sign: "Aries", degree: 8.0, retrograde: false },
|
||||
Moon: { sign: "Cancer", degree: 97.0, retrograde: false },
|
||||
Mars: { sign: "Libra", degree: 188.0, retrograde: false },
|
||||
},
|
||||
houses: {
|
||||
cusps: [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330],
|
||||
asc: 0.0,
|
||||
mc: 90.0,
|
||||
},
|
||||
elements: { Fire: 2, Stone: 0, Air: 1, Water: 1, Time: 0, Space: 0 },
|
||||
aspects: [],
|
||||
distinctions: {
|
||||
"1":1,"2":0,"3":0,"4":1,"5":0,"6":0,
|
||||
"7":1,"8":0,"9":0,"10":1,"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, ANGLE_CHART);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
NatusWheel.clear();
|
||||
svgEl.remove();
|
||||
tooltipEl.remove();
|
||||
});
|
||||
|
||||
// T15a — ASC label is a clickable group with data-angle='ASC'
|
||||
it("T15a: clicking [data-angle='ASC'] shows tooltip with 'Ascendant' title and house 1", () => {
|
||||
const ascGroup = svgEl.querySelector("[data-angle='ASC']");
|
||||
expect(ascGroup).not.toBeNull("expected [data-angle='ASC'] to exist in the SVG");
|
||||
|
||||
ascGroup.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
expect(tooltipEl.style.display).toBe("block");
|
||||
const text = tooltipEl.textContent;
|
||||
expect(text).toContain("Ascendant");
|
||||
// ASC=0° is the cusp of House 1
|
||||
expect(text).toContain("1");
|
||||
});
|
||||
|
||||
// T15b — MC label is a clickable group with data-angle='MC'
|
||||
it("T15b: clicking [data-angle='MC'] shows tooltip with 'Midheaven' title and house 10", () => {
|
||||
const mcGroup = svgEl.querySelector("[data-angle='MC']");
|
||||
expect(mcGroup).not.toBeNull("expected [data-angle='MC'] to exist in the SVG");
|
||||
|
||||
mcGroup.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
expect(tooltipEl.style.display).toBe("block");
|
||||
const text = tooltipEl.textContent;
|
||||
expect(text).toContain("Midheaven");
|
||||
expect(text).toContain("10");
|
||||
});
|
||||
|
||||
// T15c — ASC tooltip shows degree-in-sign and sign name
|
||||
it("T15c: ASC tooltip shows the in-sign degree and sign of the Ascendant", () => {
|
||||
const ascGroup = svgEl.querySelector("[data-angle='ASC']");
|
||||
ascGroup.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
const text = tooltipEl.textContent;
|
||||
// ASC=0° → 0° Aries
|
||||
expect(text).toContain("Aries");
|
||||
expect(text).toContain("0.0");
|
||||
});
|
||||
|
||||
// T15d — clicking same angle a second time hides the tooltip
|
||||
it("T15d: clicking the same angle again hides the tooltip", () => {
|
||||
const ascGroup = svgEl.querySelector("[data-angle='ASC']");
|
||||
ascGroup.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
expect(tooltipEl.style.display).toBe("block");
|
||||
|
||||
ascGroup.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
expect(tooltipEl.style.display).toBe("none");
|
||||
});
|
||||
|
||||
// T15e — ASC tooltip lists planets within 10° orb (client-side computed)
|
||||
it("T15e: ASC tooltip includes aspect rows for planets within 10° orb", () => {
|
||||
const ascGroup = svgEl.querySelector("[data-angle='ASC']");
|
||||
ascGroup.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
const bodyHtml = tooltipEl.querySelector(".nw-tt-body").innerHTML;
|
||||
// Sun at 8° → Conjunction (orb 8°) ✓ — _pSym emits data-planet attr
|
||||
expect(bodyHtml).toContain('data-planet="Sun"');
|
||||
// Mars at 188° → Opposition to ASC (0°), angular distance 172° → orb 8° ✓
|
||||
expect(bodyHtml).toContain('data-planet="Mars"');
|
||||
});
|
||||
|
||||
// T15f — planet tooltip includes ASC in its aspect list when within orb
|
||||
it("T15f: planet tooltip for Sun lists ASC as an aspect partner", () => {
|
||||
const sunGroup = svgEl.querySelector("[data-planet='Sun']");
|
||||
expect(sunGroup).not.toBeNull();
|
||||
|
||||
sunGroup.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
const bodyHtml = tooltipEl.querySelector(".nw-tt-body").innerHTML;
|
||||
expect(bodyHtml).toContain("ASC");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user