/* base.css -- lectio-web layout and typography, ALL of it. * * This file owns every non-colour rule: font stack, sizing, spacing, * line-height, borders' width/style (not colour), and layout. It must * never set a colour (background, foreground, border-color, etc.) -- that * is entirely the theme file's job (see docs/THEMES.md). Themes set colour * only and must never touch layout/type, so any lectio-web theme can be * swapped onto this same structure without reflow surprises. */ :root { /* Reading typeface. A theme may override just this by setting --theme-font * (the ONE sanctioned type override; base.css still owns sizing/spacing). */ --font-reading: var(--theme-font, Georgia, "Iowan Old Style", "Palatino Linotype", "Book Antiqua", serif); --font-ui: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; --font-mono: ui-monospace, "Cascadia Code", "SF Mono", "Roboto Mono", Menlo, Consolas, monospace; /* Named font-family palette: a theme selects a reading face by setting * --theme-font to one of these (see docs/THEMES.md). System-font stacks * only -- no webfonts (CSP). */ --font-serif: Georgia, "Times New Roman", serif; --font-serif-old: "Palatino Linotype", Palatino, "Book Antiqua", serif; --font-serif-classic: "Times New Roman", "Liberation Serif", serif; --font-serif-iowan: "Iowan Old Style", "Palatino Linotype", Georgia, serif; --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; --font-sans-humanist: "Trebuchet MS", "Segoe UI", Verdana, sans-serif; --measure: 42rem; --space-1: 0.5rem; --space-2: 1rem; --space-3: 1.5rem; --space-4: 2.5rem; } *, *::before, *::after { box-sizing: border-box; } html { font-size: 100%; } body { margin: 0; font-family: var(--font-reading); font-size: 1.125rem; line-height: 1.7; background: var(--bg); color: var(--fg); } /* Global monospace reading toggle (config web_mono / the "mono" top-bar * checkbox): forces the reading face to mono over whatever the theme uses, * for any theme. UI chrome (--font-ui) is untouched. */ body.mono { --font-reading: var(--font-mono); } .page { max-width: 64rem; margin: 0 auto; padding: var(--space-3) var(--space-2) var(--space-4); } /* Controls bar (date/version/theme) -- layout only; themes set the colours. */ .controls { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); font-family: var(--font-ui); font-size: 0.9375rem; padding-bottom: var(--space-2); margin-bottom: var(--space-3); border-bottom-width: 1px; border-bottom-style: solid; } .controls label { display: inline-flex; align-items: center; gap: 0.35rem; } .controls input, .controls select, .controls button { font: inherit; padding: 0.3rem 0.5rem; border-width: 1px; border-style: solid; border-radius: 0; /* no rounded chrome */ background: var(--bg); color: var(--fg); } /* Reader nav link + chapter stepper — layout only (themes set colour). */ .nav-link { font-family: var(--font-ui); font-size: 0.85rem; text-decoration: none; } /* The reader entry point is the primary action here -- make it stand out. */ .nav-reader { text-transform: uppercase; font-weight: bold; font-size: 1rem; letter-spacing: 0.04em; } .chap-nav { display: inline-flex; align-items: center; gap: var(--space-1); } /* Day-info header (feast/day name + optional temporal season): * RenderReadings prepends this once, ahead of every layout's own sections. * It reuses the .heading/.citation role classes (rather than a bespoke * rule) so every theme restyles it the same way it already restyles a * reading section's own heading/citation -- no new colour rule needed. */ .dayinfo { margin: 0 0 var(--space-3); } .dayinfo .heading { margin: 0 0 0.25rem; } .dayinfo .citation { margin: 0; } /* Reading pane */ .reading-section { margin: 0 0 var(--space-4); } .reading-section + .reading-section { padding-top: var(--space-3); border-top-width: 1px; border-top-style: solid; } .heading { display: block; font-family: var(--font-reading); font-size: 1.5rem; font-weight: 700; line-height: 1.3; margin: 0 0 var(--space-1); } .citation { display: block; font-family: var(--font-ui); font-size: 0.9375rem; font-style: italic; margin: 0 0 var(--space-2); } .columns { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--measure)), 1fr)); gap: var(--space-3) var(--space-4); align-items: start; } .column { min-width: 0; } .version-label { font-family: var(--font-ui); font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase; margin: 0 0 var(--space-2); padding-bottom: 0.35rem; border-bottom-width: 1px; border-bottom-style: solid; } .block { margin: 0 0 var(--space-1); max-width: var(--measure); } .block.refrain { font-style: italic; } /* Verse block: a fixed number column + a text column, so every verse's text starts at the same left edge (a straight margin) and continuation lines hang-indent under it -- matching the CLI/TUI reader. */ .block.verse { display: grid; grid-template-columns: 3rem 1fr; column-gap: 0.4rem; align-items: baseline; } .block.verse .vnum { min-width: 0; margin-right: 0; text-align: right; } .block.verse .vtext { min-width: 0; } .vnum { display: inline-block; min-width: 2.5em; font-family: var(--font-ui); font-size: 0.75rem; font-variant-numeric: tabular-nums; vertical-align: super; margin-right: 0.35em; } /* Vertical display: versions side by side in columns, like the CLI * `compare` view. A fixed --vcols track count (not auto-fit) means the * grid's total width is always the page container's, so it wraps extra * versions onto further rows instead of ever forcing horizontal scroll. */ .display-vertical { display: grid; grid-template-columns: repeat(var(--vcols, 2), 1fr); gap: var(--space-3) var(--space-4); align-items: start; } .vcol { min-width: 0; } /* Interlinear display: one .ilverse block per chapter:verse key, one * .illine per version that carries it. */ .display-interlinear { display: flex; flex-direction: column; } .ilverse { margin: 0 0 var(--space-3); padding-top: var(--space-1); border-top-width: 1px; border-top-style: solid; } .ilverse:first-child { border-top-width: 0; padding-top: 0; } .illine { margin: 0.2rem 0 0.2rem var(--space-2); } .illine .version-label { display: inline; margin: 0 0.5em 0 0; padding-bottom: 0; border-bottom-width: 0; } a { text-decoration: underline; text-underline-offset: 0.15em; } .error { font-family: var(--font-ui); } @media (max-width: 40rem) { .page { padding: var(--space-2) var(--space-1) var(--space-3); } .heading { font-size: 1.25rem; } .display-vertical { grid-template-columns: 1fr; } /* Too narrow to keep the side cluster beside the controls: let it wrap beneath them rather than squeeze both onto one cramped row. */ #controls { flex-wrap: wrap; } } /* Settings form — a simple labeled column; themes own colour. */ .settings { display: flex; flex-direction: column; gap: var(--space-2); max-width: 40rem; font-family: var(--font-ui); } .settings label { display: flex; flex-direction: column; gap: 0.25rem; align-items: flex-start; } .settings .row { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; } .settings textarea { width: 100%; font-family: var(--font-mono); } .settings .saved { font-family: var(--font-ui); } /* Bookmarks. */ .bookmark-add { display: flex; flex-wrap: wrap; gap: var(--space-1); align-items: center; margin: var(--space-2) 0; font-family: var(--font-ui); } .bookmarks { display: flex; flex-direction: column; gap: var(--space-2); font-family: var(--font-ui); } .bookmark { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: baseline; } .bookmark .tags { font-size: 0.85rem; } .tag-filter { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-bottom: var(--space-2); font-family: var(--font-ui); } /* Index top bar: the essential controls sit in one wrapping block on the left; * the utility cluster is pinned to the TOP-right, so it stays up top even when * the controls wrap onto a second line. (#controls is the index form only; the * reader's .controls form keeps the plain single-row wrap.) */ /* The side cluster must stay in the top-right CORNER, on the same row as the * left controls -- never wrap beneath them. So the bar itself does not wrap * (nowrap); the left controls (.controls-main) absorb any tightness by wrapping * their OWN items onto further lines (min-width:0 lets them shrink to do so), * while the side cluster holds the top-right corner (align-items:flex-start). */ #controls { align-items: flex-start; flex-wrap: nowrap; } .controls-main { display: flex; flex-wrap: wrap; align-items: center; /* Tighter column gap than the reader bar: this bar carries more items (reader link, date-nav, four version boxes, parts, layout), and the saved width lets the whole left cluster share one row with the pinned top-right cluster at desktop width instead of wrapping a control down. */ gap: var(--space-1) 0.7rem; min-width: 0; } /* Utility cluster (nav links + downloads), pushed to the right of the controls * bar; wraps beneath when the window is too narrow to fit it up top. */ .controls-side { margin-left: auto; display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); } /* "pobierz" disclosure: a summary styled as a nav link that reveals a small * floating panel of download options (a month calendar with its own month/year * pickers, and the shown day's txt/md/pdf export). The panel is absolutely * positioned under the link so opening it never reflows the controls bar. * Colour (border/background) is the theme's, via the shared --bg/--fg tokens. */ .export { position: relative; font-family: var(--font-ui); font-size: 0.85rem; } .export > summary { cursor: pointer; list-style: none; } .export > summary::-webkit-details-marker { display: none; } .export > summary::after { content: " \25be"; } /* down caret */ .export[open] > summary::after { content: " \25b4"; } /* up caret */ .export-panel { position: absolute; right: 0; top: calc(100% + 0.35rem); z-index: 10; display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-2); border-width: 1px; border-style: solid; background: var(--bg); white-space: nowrap; } .export-row { display: flex; align-items: center; gap: 0.5rem; } .export-row .export-label { font-weight: 600; } .export-panel select { font: inherit; } .export-panel a { margin: 0; } /* Bookmark marker: a red "*" flagging a bookmarked verse in the reader. A fixed * semantic red (not a theme colour), visible on light and dark themes alike. */ .vmark { color: #e5484d; font-weight: bold; padding-left: 0.15rem; } /* Licence footer: the AGPL-3.0 §13 source offer, on every full page. * Quiet by design but never hidden -- §13 asks for a PROMINENT offer, so * this must not be display:none'd or themed to invisibility. Colour (border * and text) is the theme's, per this file's no-colour rule. */ .licence { max-width: var(--measure); margin: var(--space-4) auto 0; padding-top: var(--space-2); border-top-width: 1px; border-top-style: solid; font-family: var(--font-ui); font-size: 0.75rem; text-align: center; }