diff --git a/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/HeroCard.svelte b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/HeroCard.svelte new file mode 100644 index 00000000..bb4e2c77 --- /dev/null +++ b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/HeroCard.svelte @@ -0,0 +1,292 @@ + + +{#snippet card()} +
+ +
+ {#if isToday}{t('today', lang)} · {/if}{formatLongDate(day.iso, lang)} +
+

{day.name}

+
+ {#if day.rankName} + {day.rankName} + {/if} + {#if day.colorNames.length} + {firstOr(day.colorNames)} + {/if} + {#if day.seasonNames.length} + {firstOr(day.seasonNames)} + {/if} + {#if day.psalterWeek} + {t('psalterWeek', lang)}: {humanizePsalterWeek(day.psalterWeek, lang)} + {/if} + {#if day.sundayCycle} + {t('cycle', lang)}: {humanizeSundayCycle(day.sundayCycle)} + {/if} +
+ {#if day.rite1962 && day.rite1962.commemorations.length} +
+
+ + {t1962('commemorations', lang)} +
+
+ {#each day.rite1962.commemorations as c (c.id)} + {c.name} + {/each} +
+
+ {/if} + {#if day.rite1962?.stationChurches?.length} +
+ + + {t1962('stationChurch', lang)}: + {#each day.rite1962.stationChurches as s, i (s.key + (s.mass ?? ''))} + {#if i > 0} · {/if}{s.name}{#if s.mass} ({s.mass.replace(/_/g, ' ')}){/if} + {/each} + +
+ {/if} + {#if href} + + {/if} +
+{/snippet} + +{#if href} + + {@render card()} + +{:else} + {@render card()} +{/if} + + diff --git a/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.svelte b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.svelte index 4834fbc8..61330971 100644 --- a/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.svelte +++ b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/[[yyyy=calendarYear]]/[[mm=calendarMonth]]/[[dd=calendarDay]]/+page.svelte @@ -6,13 +6,8 @@ import { getMonthName, getWeekdayShort, - formatLongDate, - hexFor, rankEmphasis, - humanizePsalterWeek, - humanizeSundayCycle, t, - t1962, dioceseLabel, DIOCESES_1962, DIOCESES_1969, @@ -22,6 +17,7 @@ } from '../../../../calendarI18n'; import { litBg, litInk, LIT_COLOR_VAR } from '../../../../calendarColors'; import RingView from './RingView.svelte'; + import HeroCard from '../../../../HeroCard.svelte'; let { data }: { data: PageData } = $props(); @@ -134,10 +130,6 @@ const pageTitle = $derived(t('calendar', lang)); - function firstOr(arr: string[], fallback = ''): string { - return arr && arr.length ? arr[0] : fallback; - } - // When switching rites we drop ?diocese because the ID spaces differ (1962 has // diocesan calendars, 1969 only "general" or "switzerland"). The server // re-applies each rite's default if none is given. @@ -214,56 +206,7 @@ {/if} {#if hero} - {@const heroColor = hero.colorKeys[0] ?? 'GREEN'} - {@const heroIsToday = hero.iso === todayIso} - -
- -
- {#if heroIsToday}{t('today', lang)} · {/if}{formatLongDate(hero.iso, lang)} -
-

{hero.name}

-
- {#if hero.rankName} - {hero.rankName} - {/if} - {#if hero.colorNames.length} - {firstOr(hero.colorNames)} - {/if} - {#if hero.seasonNames.length} - {firstOr(hero.seasonNames)} - {/if} - {#if hero.psalterWeek} - {t('psalterWeek', lang)}: {humanizePsalterWeek(hero.psalterWeek, lang)} - {/if} - {#if hero.sundayCycle} - {t('cycle', lang)}: {humanizeSundayCycle(hero.sundayCycle)} - {/if} -
- {#if hero.rite1962 && hero.rite1962.commemorations.length} -
- {#each hero.rite1962.commemorations as c (c.id)} - {c.name} - {/each} -
- {/if} - {#if hero.rite1962?.stationChurches?.length} -
- - - {t1962('stationChurch', lang)}: - {#each hero.rite1962.stationChurches as s, i (s.key + (s.mass ?? ''))} - {#if i > 0} · {/if}{s.name}{#if s.mass} ({s.mass.replace(/_/g, ' ')}){/if} - {/each} - -
- {/if} - -
-
+ {/if} @@ -577,155 +520,6 @@ margin: 0; } - /* ====== Today banner (design handoff) ====== */ - .today-card-link { - display: block; - text-decoration: none; - color: inherit; - margin-bottom: 1.5rem; - } - .today-banner { - position: relative; - border-radius: var(--radius-card); - padding: 2rem 2.2rem; - box-shadow: var(--shadow-md); - overflow: hidden; - transition: transform var(--transition-normal), box-shadow var(--transition-normal), - background 650ms cubic-bezier(0.33, 1, 0.68, 1), - color 650ms cubic-bezier(0.33, 1, 0.68, 1); - } - .today-banner::before { - content: ''; - position: absolute; - inset: 0; - background: - radial-gradient(circle at 10% 110%, rgba(255, 255, 255, 0.14), transparent 45%), - radial-gradient(circle at 95% -10%, rgba(0, 0, 0, 0.12), transparent 45%); - pointer-events: none; - } - .today-banner > * { - position: relative; - } - .today-card-link:hover .today-banner { - transform: translateY(-2px); - box-shadow: 0 14px 32px rgba(0, 0, 0, 0.22); - } - .today-card-link:active .today-banner { - transform: translateY(0); - } - .today-card-link:focus-visible .today-banner { - outline: 3px solid var(--color-primary); - outline-offset: 3px; - } - .tc-cross { - position: absolute; - top: 1.2rem; - right: 1.6rem; - font-size: 3.4rem; - line-height: 1; - opacity: 0.28; - font-family: serif; - } - .tc-today { - font-size: 0.74rem; - letter-spacing: 0.16em; - text-transform: uppercase; - font-weight: 700; - opacity: 0.88; - margin-bottom: 0.6rem; - } - .tc-name { - font-size: clamp(1.4rem, 3vw, 2rem); - line-height: 1.12; - margin: 0 0 0.3rem; - letter-spacing: -0.01em; - font-weight: 700; - } - .tc-tags { - margin-top: 0.9rem; - display: flex; - gap: 0.5rem; - flex-wrap: wrap; - } - .tc-tag { - padding: 0.3rem 0.75rem; - border-radius: var(--radius-pill); - background: rgba(255, 255, 255, 0.22); - font-size: 0.72rem; - font-weight: 700; - letter-spacing: 0.06em; - text-transform: uppercase; - } - .tc-commems { - margin-top: 1.4rem; - padding-top: 1.1rem; - border-top: 1px solid rgba(255, 255, 255, 0.22); - display: flex; - flex-wrap: wrap; - gap: 0.4rem 0.6rem; - } - .tc-commem { - padding: 0.3rem 0.7rem; - border-radius: var(--radius-pill); - background: rgba(255, 255, 255, 0.18); - border: 1px solid rgba(255, 255, 255, 0.22); - font-size: 0.82rem; - } - .tc-stations { - margin-top: 0.9rem; - display: flex; - align-items: baseline; - gap: 0.55rem; - font-size: 0.85rem; - line-height: 1.45; - } - .tc-stations-label { - font-size: 0.95rem; - opacity: 0.7; - flex-shrink: 0; - } - .tc-stations-title { - font-weight: 600; - letter-spacing: 0.03em; - text-transform: uppercase; - font-size: 0.72rem; - opacity: 0.85; - margin-right: 0.35rem; - } - .tc-station-name { - font-style: italic; - } - .tc-station-mass { - opacity: 0.75; - font-size: 0.78rem; - } - .tc-stations-sep { - opacity: 0.6; - } - .tc-arrow { - position: absolute; - bottom: 1.1rem; - right: 1.4rem; - font-size: 1.6rem; - font-weight: 300; - opacity: 0.55; - transition: transform var(--transition-normal), opacity var(--transition-normal); - } - .today-card-link:hover .tc-arrow { - opacity: 1; - transform: translateX(4px); - } - @media (max-width: 640px) { - .today-banner { - padding: 1.5rem 1.4rem; - } - .tc-cross { - font-size: 2.4rem; - top: 1rem; - right: 1rem; - } - } - /* ====== View switcher + color legend ====== */ .overview-controls { display: flex; diff --git a/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/detail/[yyyy=calendarYear]/[mm=calendarMonth]/[dd=calendarDay]/+page.svelte b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/detail/[yyyy=calendarYear]/[mm=calendarMonth]/[dd=calendarDay]/+page.svelte index 206cb95d..b4a84650 100644 --- a/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/detail/[yyyy=calendarYear]/[mm=calendarMonth]/[dd=calendarDay]/+page.svelte +++ b/src/routes/[faithLang=faithLang]/[calendar=calendarLang]/[rite=calendarRite]/detail/[yyyy=calendarYear]/[mm=calendarMonth]/[dd=calendarDay]/+page.svelte @@ -5,20 +5,12 @@ formatLongDate, getMonthName, hexFor, - humanizePsalterWeek, - humanizeSundayCycle, properLabel, t, t1962, type CalendarLang } from '../../../../../calendarI18n'; - - function kindLabel(kind: 'tempora' | 'sancti', l: CalendarLang): string { - if (kind === 'tempora') - return l === 'de' ? 'Temporale' : l === 'la' ? 'Temporale' : 'Temporal'; - return l === 'de' ? 'Sanktorale' : l === 'la' ? 'Sanctorale' : 'Sanctoral'; - } - import { litBg, litInk } from '../../../../../calendarColors'; + import HeroCard from '../../../../../HeroCard.svelte'; let { data }: { data: PageData } = $props(); @@ -57,7 +49,6 @@ const prevHref = $derived(shiftDay(-1)); const nextHref = $derived(shiftDay(1)); - const isToday = $derived(iso === todayIso); const monthTitle = $derived(`${getMonthName(month, lang)} ${year}`); @@ -82,47 +73,12 @@ -
-
- {formatLongDate(iso, lang)} - {#if isToday} - {t('today', lang)} - {/if} -
-

{day.name}

-
- {#if day.rankName} - {day.rankName} - {/if} - {#if day.seasonNames.length} - {day.seasonNames[0]} - {/if} - {#if day.colorNames.length} - - - {day.colorNames[0]} - - {/if} - {#if day.psalterWeek} - {t('psalterWeek', lang)}: {humanizePsalterWeek(day.psalterWeek, lang)} - {/if} - {#if day.sundayCycle} - {t('cycle', lang)}: {humanizeSundayCycle(day.sundayCycle)} - {/if} -
-
+ {#if day.rite1962} {@const d = day.rite1962}
-
-
{t1962('source', lang)}
-
{kindLabel(d.kind, lang)}
-
{#if d.vigilOf}
{t1962('vigilOf', lang)}
@@ -154,21 +110,6 @@
{/if} - {#if d.stationChurches?.length} -
-

{t1962('stationChurch', lang)}

-
    - {#each d.stationChurches as s (s.key + (s.mass ?? ''))} -
  • - {s.name} - {#if s.mass} - {s.mass.replace(/_/g, ' ')} - {/if} -
  • - {/each} -
-
- {/if} {#if d.propers.length}

{t1962('propers', lang)}

@@ -278,62 +219,6 @@ color: var(--color-text-primary); } - .detail-hero { - border-radius: var(--radius-card); - padding: 1.5rem 1.75rem; - box-shadow: var(--shadow-md); - } - .hero-date { - display: flex; - align-items: center; - gap: 0.5rem; - font-size: var(--text-sm); - opacity: 0.85; - margin-bottom: 0.25rem; - } - .today-pip { - font-size: 0.62rem; - letter-spacing: 0.14em; - text-transform: uppercase; - font-weight: 700; - padding: 3px 8px; - border-radius: 100px; - background: rgba(0, 0, 0, 0.12); - } - .hero-name { - margin: 0 0 0.75rem; - font-size: 2rem; - line-height: 1.2; - } - .hero-tags { - display: flex; - flex-wrap: wrap; - gap: 0.5rem; - } - - .tag { - display: inline-flex; - align-items: center; - gap: 0.4rem; - padding: 0.25rem 0.7rem; - background: rgba(0, 0, 0, 0.14); - color: inherit; - border-radius: var(--radius-pill); - font-size: var(--text-sm); - font-weight: 500; - } - .tag-rank { - background: rgba(0, 0, 0, 0.22); - font-weight: 600; - } - .color-swatch { - width: 12px; - height: 12px; - border-radius: 50%; - border: 1px solid rgba(255, 255, 255, 0.4); - display: inline-block; - } - .detail { background: var(--color-surface); border-radius: var(--radius-card); @@ -366,7 +251,6 @@ color: var(--color-text-primary); } .commems h4, - .stations h4, .propers h4 { margin: 0.5rem 0 0.4rem; font-size: 0.72rem; @@ -375,12 +259,10 @@ color: var(--color-text-secondary); font-weight: 600; } - .commems, - .stations { + .commems { margin-top: 0.75rem; } - .commems ul, - .stations ul { + .commems ul { list-style: none; padding: 0; margin: 0; @@ -388,8 +270,7 @@ flex-direction: column; gap: 0.35rem; } - .commems li, - .stations li { + .commems li { display: flex; align-items: center; gap: 0.5rem; @@ -398,19 +279,10 @@ border-radius: var(--radius-sm, 6px); font-size: 0.85rem; } - .commem-name, - .station-name { + .commem-name { flex: 1 1 auto; color: var(--color-text-primary); } - .station-name { - font-style: italic; - } - .station-mass { - color: var(--color-text-tertiary); - font-size: 0.78rem; - text-transform: capitalize; - } .propers { margin-top: 1rem;