import { css, html, nothing } from 'lit'; import { customElement } from 'lit/decorators.js'; import { planetGlyph, signGlyph } from '../tokens/index.js'; import type { ProfectionsResponse } from '../types/index.js'; import { RoxyDataElement } from '../utils/base-element.js'; import { baseStyles } from '../utils/base-styles.js'; import { formatDate } from '../utils/format.js'; /** * Annual profection card. Renders a /astrology/profections response: the year's * profected whole-sign house and sign, the lord of the year and where it sits in * the natal chart, and the reading. A single focal card, not a table. * * @remarks * The profection itself is arithmetic: the age, the house it activates, the sign on it, and the lord with its natal placement. Those are the card, and they all survive `hide-readings`; the closing paragraph is the only interpretation on it. */ @customElement('roxy-profection-card') export class RoxyProfectionCard extends RoxyDataElement { static styles = [ baseStyles, css` .wrap { width: 100%; background: var(--roxy-surface, #fff); color: var(--roxy-fg, #0a0a0a); border: 1px solid var(--roxy-border, #e4e4e7); border-radius: var(--roxy-radius-md, 8px); padding: var(--roxy-space-lg, 1.5rem); box-shadow: var(--roxy-shadow-sm); display: grid; /* Never an implicit auto column: it floors at min-content, so one long * unbreakable string widens the track past the padded card. */ grid-template-columns: minmax(0, 1fr); gap: var(--roxy-space-md, 1rem); } header { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--roxy-space-sm, 0.5rem); } .title { font-size: var(--roxy-text-lg, 1.125rem); font-weight: var(--roxy-weight-bold, 600); margin: 0; color: var(--roxy-primary, #0f172a); } .badge { padding: 2px 8px; border-radius: var(--roxy-radius-full, 9999px); font-size: var(--roxy-text-xs, 0.75rem); background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 14%, transparent); color: var(--roxy-fg, #0a0a0a); } .badge b { color: var(--roxy-accent-ink, #b45309); font-weight: 600; } .focus { display: flex; flex-wrap: wrap; align-items: center; gap: var(--roxy-space-md, 1rem); padding: var(--roxy-space-md, 1rem); border-radius: var(--roxy-radius-md, 8px); background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 9%, transparent); } .age { display: grid; justify-items: center; min-width: 4.5rem; } .age .n { font-size: 2rem; font-weight: 700; line-height: 1; color: var(--roxy-accent-ink, #b45309); font-variant-numeric: tabular-nums; } .age .l { font-size: var(--roxy-text-xs, 0.75rem); color: var(--roxy-muted, #71717a); text-transform: uppercase; letter-spacing: 0.06em; } .arrow { color: var(--roxy-muted, #71717a); font-size: var(--roxy-text-sm, 0.875rem); } .house { display: grid; gap: 2px; } .house .h { font-size: var(--roxy-text-lg, 1.125rem); font-weight: 600; color: var(--roxy-fg, #0a0a0a); } .house .sign { font-size: var(--roxy-text-sm, 0.875rem); color: var(--roxy-secondary, #475569); } .house .sign .sg { margin-right: 0.3rem; } .lord { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 0.75rem; font-size: var(--roxy-text-sm, 0.875rem); } .lord .label { color: var(--roxy-muted, #71717a); text-transform: uppercase; letter-spacing: 0.06em; font-size: var(--roxy-text-xs, 0.75rem); } .lord .value { font-weight: 600; color: var(--roxy-fg, #0a0a0a); } .lord .sub { color: var(--roxy-muted, #71717a); } .interp { font-size: var(--roxy-text-sm, 0.875rem); color: var(--roxy-fg, #0a0a0a); margin: 0; line-height: var(--roxy-leading-normal, 1.5); } `, ]; protected renderData(data: ProfectionsResponse) { const sGlyph = signGlyph(data.profectedSign); const lordGlyph = planetGlyph(data.lordOfYear); const lordNatalGlyph = signGlyph(data.lordNatalPosition?.sign); return html`

${this.t('Annual profection')}

${data.targetDate ? html`${this.t('For')} ${formatDate(this.effectiveLang(), data.targetDate)}` : nothing}
${data.age} ${this.t('Age')}
${this.t('Activates')}
${this.t('House')} ${data.profectedHouse} ${sGlyph ? html`${sGlyph}` : nothing}${data.profectedSign}
${this.t('Lord of the year')} ${lordGlyph ? html`${lordGlyph} ` : nothing}${data.lordOfYear} ${ data.lordNatalPosition ? html`${this.t('Natal')} ${lordNatalGlyph ? html`${lordNatalGlyph} ` : nothing}${this.t('{{sign}} ยท house {{house}}', { sign: data.lordNatalPosition.sign, house: data.lordNatalPosition.house })}` : nothing }
${ // The house, the sign and the lord above are the profection; this is the // read of them. data.interpretation && !this.hideReadings ? html`

${data.interpretation}

` : nothing }
`; } } declare global { interface HTMLElementTagNameMap { 'roxy-profection-card': RoxyProfectionCard; } }