Synastry
${
typeof score === 'number'
? html`${score} / 100 `
: nothing
}
Synastry response missing planet positions. Pass
data with person1.planets and
person2.planets arrays from the natal-chart endpoint, or
use the <roxy-data> fallback.
${summaryText ? html`
${summaryText}
` : nothing}
${interAspects.length > 0 ? this.renderAspects(interAspects) : nothing}
${
strengths.length > 0 || challenges.length > 0
? html`
${
strengths.length
? html`
Strengths
${strengths.map((s) => html`${s} `)}
`
: nothing
}
${
challenges.length
? html`
Challenges
${challenges.map((s) => html`${s} `)}
`
: nothing
}
`
: nothing
}
`;
}
return html`
Synastry
${
typeof score === 'number'
? html`${score} / 100 `
: nothing
}
Synastry dual wheel
${this.renderSpokes()} ${this.renderSigns()}
${this.renderInterAspectLines(p1Planets, p2Planets, interAspects)}
${this.renderRing(p1Planets, P1_R, 'p1', 1)} ${this.renderRing(p2Planets, P2_R, 'p2', 2)}
${this.renderAscendants(d)}
Person 1
Person 2
harmonious
challenging
${summaryText ? html`
${summaryText}
` : nothing}
${interAspects.length > 0 ? this.renderAspects(interAspects) : nothing}
${
strengths.length > 0 || challenges.length > 0
? html`
${
strengths.length
? html`
Strengths
${strengths.map((s) => html`${s} `)}
`
: nothing
}
${
challenges.length
? html`
Challenges
${challenges.map((s) => html`${s} `)}
`
: nothing
}
`
: nothing
}
`;
}
private toAngle(longitude: number): number {
return 180 - longitude;
}
private renderSpokes() {
return Array.from({ length: 12 }, (_, i) => {
const angle = this.toAngle(i * 30);
const start = polarToCartesian(CENTER, CENTER, P2_R - 14, angle);
const end = polarToCartesian(CENTER, CENTER, OUTER_R, angle);
return svg`