63fd319509
Deploy / deploy (push) Successful in 1m19s
day-nav.ts's header always resolved via resolveDay(date) regardless of selected hour, so viewing Vespers/Compline on a day whose evening anticipates tomorrow's First Vespers (e.g. Aug 25, 2026: St. Louis's day, but St. Zephyrinus claims First Vespers per calendar/vespers.ts) still showed today's saint in the header while the hour's actual content had already switched to tomorrow's. Now uses resolveEveningDay for those two hours specifically. Also adds an explicit "First Vespers (of tomorrow)" / "Second Vespers (of today)" status line to the Vespers header, via new getVespersStatusLabel(), so the anticipation/commemoration result is visible rather than only inferable from which saint's name shows up. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014axryJBrRswYh2niA7WCUc
374 lines
7.7 KiB
CSS
374 lines
7.7 KiB
CSS
/* ==========================================================================
|
|
vu — design tokens adapted from michaelferrara-site's parchment/ink/oxblood
|
|
palette and EB Garamond/Source Serif 4/Inter type system (the "most me"
|
|
existing site, per the plan). Same technical pattern as reground-site and
|
|
michaelferrara-site: CSS custom properties, prefers-color-scheme dark mode,
|
|
a skip-link, explicit :focus-visible rings.
|
|
========================================================================== */
|
|
|
|
:root {
|
|
color-scheme: light dark;
|
|
|
|
--color-bg: #f7f3ea;
|
|
--color-bg-raised: #efe9db;
|
|
--color-ink: #2a2521;
|
|
--color-ink-heading: #1c1712;
|
|
--color-accent: #7a2e2e;
|
|
--color-accent-hover: #5c2222;
|
|
--color-brass: #8c7a5b;
|
|
--color-border: #ddd3bd;
|
|
--color-pending: #9a8f7d;
|
|
|
|
--font-body: 'Source Serif 4', Georgia, 'Times New Roman', serif;
|
|
--font-heading: 'EB Garamond', 'Palatino Linotype', Georgia, serif;
|
|
--font-ui: 'Inter', 'IBM Plex Sans', -apple-system, sans-serif;
|
|
|
|
--font-size-base: 19px;
|
|
--line-height-base: 1.65;
|
|
--measure: 70ch;
|
|
--radius: 4px;
|
|
|
|
--space-1: 0.5rem;
|
|
--space-2: 1rem;
|
|
--space-3: 1.75rem;
|
|
--space-4: 3rem;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
/* Matins and Compline get used in the dark far more than a marketing
|
|
site ever would — this needs to be a good reading mode, not just
|
|
present. */
|
|
--color-bg: #1a1613;
|
|
--color-bg-raised: #24201b;
|
|
--color-ink: #e9e2d4;
|
|
--color-ink-heading: #f5efe2;
|
|
--color-accent: #d98a8a;
|
|
--color-accent-hover: #e6a6a6;
|
|
--color-brass: #b3a483;
|
|
--color-border: #3a332a;
|
|
--color-pending: #7d7364;
|
|
}
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html {
|
|
font-size: 100%;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
background-color: var(--color-bg);
|
|
color: var(--color-ink);
|
|
font-family: var(--font-body);
|
|
font-size: var(--font-size-base);
|
|
line-height: var(--line-height-base);
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
h1,
|
|
h2,
|
|
h3 {
|
|
font-family: var(--font-heading);
|
|
color: var(--color-ink-heading);
|
|
line-height: 1.25;
|
|
}
|
|
|
|
button {
|
|
font: inherit;
|
|
color: inherit;
|
|
}
|
|
|
|
.skip-link {
|
|
position: absolute;
|
|
left: -9999px;
|
|
top: 0;
|
|
z-index: 100;
|
|
background: var(--color-accent);
|
|
color: var(--color-bg);
|
|
padding: var(--space-1) var(--space-2);
|
|
border-radius: 0 0 var(--radius) 0;
|
|
}
|
|
.skip-link:focus {
|
|
left: 0;
|
|
}
|
|
|
|
a:focus-visible,
|
|
button:focus-visible {
|
|
outline: 2px solid var(--color-accent);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------
|
|
Header + language toggle
|
|
-------------------------------------------------------------------------- */
|
|
|
|
.site-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--space-2);
|
|
padding: var(--space-2) var(--space-2);
|
|
border-bottom: 1px solid var(--color-border);
|
|
font-family: var(--font-ui);
|
|
}
|
|
|
|
.site-title {
|
|
font-family: var(--font-heading);
|
|
font-size: 1.4rem;
|
|
color: var(--color-ink-heading);
|
|
}
|
|
|
|
.language-toggle {
|
|
display: flex;
|
|
gap: 0.4rem;
|
|
}
|
|
|
|
.lang-btn {
|
|
font-family: var(--font-ui);
|
|
font-size: 0.8rem;
|
|
padding: 0.35rem 0.7rem;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius);
|
|
background: var(--color-bg-raised);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.lang-btn.is-active {
|
|
background: var(--color-accent);
|
|
color: var(--color-bg);
|
|
border-color: var(--color-accent);
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------
|
|
Day nav
|
|
-------------------------------------------------------------------------- */
|
|
|
|
.day-nav {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--space-2);
|
|
padding: var(--space-2);
|
|
font-family: var(--font-ui);
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
.day-nav-btn {
|
|
border: 1px solid var(--color-border);
|
|
background: var(--color-bg-raised);
|
|
border-radius: var(--radius);
|
|
padding: 0.4rem 0.75rem;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.day-nav-header {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 0.15rem;
|
|
min-width: 16rem;
|
|
text-align: center;
|
|
}
|
|
|
|
.day-nav-date {
|
|
font-weight: 600;
|
|
}
|
|
|
|
.day-nav-label {
|
|
font-family: var(--font-ui);
|
|
font-size: 0.85rem;
|
|
font-style: italic;
|
|
color: var(--color-brass);
|
|
}
|
|
|
|
.day-nav-vespers-status {
|
|
font-family: var(--font-ui);
|
|
font-size: 0.75rem;
|
|
color: var(--color-muted, var(--color-brass));
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------
|
|
Layout: hour list + hour view
|
|
-------------------------------------------------------------------------- */
|
|
|
|
.app-main {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-3);
|
|
max-width: 64rem;
|
|
margin: 0 auto;
|
|
padding: var(--space-3) var(--space-2);
|
|
}
|
|
|
|
.hour-list-nav {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.hour-list {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: var(--space-2);
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
font-family: var(--font-ui);
|
|
}
|
|
|
|
.hour-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
text-align: center;
|
|
padding: 0.6rem 0.75rem;
|
|
border: none;
|
|
background: none;
|
|
border-radius: var(--radius);
|
|
cursor: pointer;
|
|
color: var(--color-ink);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.hour-item:hover {
|
|
background: var(--color-bg-raised);
|
|
}
|
|
|
|
.hour-item.is-selected {
|
|
background: var(--color-accent);
|
|
color: var(--color-bg);
|
|
}
|
|
|
|
.hour-item.is-pending {
|
|
color: var(--color-pending);
|
|
}
|
|
|
|
.hour-item.is-selected.is-pending {
|
|
color: var(--color-bg);
|
|
opacity: 0.85;
|
|
}
|
|
|
|
.hour-sep {
|
|
display: flex;
|
|
align-items: center;
|
|
color: var(--color-border);
|
|
}
|
|
|
|
.hour-status {
|
|
font-size: 0.7rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.03em;
|
|
}
|
|
|
|
.hour-view-region {
|
|
min-width: 0;
|
|
}
|
|
|
|
.hour-view-pending p {
|
|
color: var(--color-pending);
|
|
font-style: italic;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------
|
|
Ordo parts + bilingual columns
|
|
-------------------------------------------------------------------------- */
|
|
|
|
.ordo-part {
|
|
margin-bottom: var(--space-3);
|
|
}
|
|
|
|
.ordo-part-label {
|
|
font-size: 1rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
color: var(--color-brass);
|
|
font-family: var(--font-ui);
|
|
margin: 0 0 var(--space-1);
|
|
}
|
|
|
|
.section-heading {
|
|
font-size: 1.2rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.06em;
|
|
color: var(--color-brass);
|
|
font-family: var(--font-ui);
|
|
margin: var(--space-4) 0 var(--space-2);
|
|
}
|
|
|
|
.ordo-part-citation {
|
|
font-family: var(--font-ui);
|
|
font-size: 0.85em;
|
|
font-style: italic;
|
|
color: var(--color-brass);
|
|
margin: 0 0 var(--space-1);
|
|
}
|
|
|
|
.psalm-verses {
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
.psalm-verse {
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
/* One-language vs two-language layout — the real display-width ceiling from
|
|
the plan: never more than two columns, regardless of how many languages
|
|
eventually have data. */
|
|
.lang-columns-1 {
|
|
max-width: var(--measure);
|
|
}
|
|
|
|
.lang-columns-2 {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
@media (max-width: 40rem) {
|
|
.lang-columns-2 {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
|
|
.lang-column {
|
|
/* Hymn stanzas, Preces, and other multi-line propers are authored with
|
|
meaningful line breaks (poetry lines, one versicle/response per line) —
|
|
preserve them instead of letting HTML collapse everything to one run-on
|
|
line, while still wrapping normally on narrow screens (unlike `pre`). */
|
|
white-space: pre-line;
|
|
}
|
|
|
|
.lang-column[lang='la'] {
|
|
font-style: italic;
|
|
}
|
|
|
|
.text-pending {
|
|
color: var(--color-pending);
|
|
font-style: italic;
|
|
font-family: var(--font-ui);
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.text-draft {
|
|
border-bottom: 1px dashed var(--color-brass);
|
|
}
|
|
|
|
@media print {
|
|
body {
|
|
background: #fff;
|
|
color: #000;
|
|
}
|
|
.site-header,
|
|
.day-nav,
|
|
.hour-list-nav,
|
|
.language-toggle {
|
|
display: none;
|
|
}
|
|
}
|