Outline
+{title}
+ {meta &&{meta}
} ++ {tree.length > 0 ?
Nothing in this outline yet.
} +Bible Study Project
+diff --git a/src/App.flow.test.jsx b/src/App.flow.test.jsx
index 5346822..396ab37 100644
--- a/src/App.flow.test.jsx
+++ b/src/App.flow.test.jsx
@@ -350,12 +350,14 @@ describe('Opening a read-only outline link', () => {
stubServer({ user: null });
window.history.replaceState({}, '', '/?outline=abc123');
render(
+ {n.kind && {kindLabel(n.kind)}} + {n.text.trim() || (untitled)} + {n.ref && {n.ref}} + {mins && {n.minutes} min} +
+ {n.note.trim() &&{n.note.trim()}
} + {n.scripture?.text && ( ++ “{n.scripture.text}” — {n.scripture.ref} ++ )} + {n.attachments.length > 0 && ( +
+ {n.attachments.map((a, k) => {k > 0 && ' · '}{a.type === 'word' ? 'Word' : 'See'}: {a.label}{a.detail ? ` — ${a.detail}` : ''})} +
+ )} + {n.children.length > 0 &&Outline
+{meta}
} +Nothing in this outline yet.
} +Bible Study Project
+Bible Study Project
-{error}
+ +Bible Study Project
+{error}
+Loading outline…
Loading outline…
; const current = data.outlines.find((o) => o.scope === scope) ?? data.outlines[0]; const title = current && current.scope !== 'study' ? `${data.title} — ${current.label}` : data.title; + const minutes = current ? flatten(current.tree).reduce((sum, { node }) => sum + (Number.isFinite(node.minutes) ? node.minutes : 0), 0) : 0; + const meta = current ? [current.scope === 'study' ? data.translation : `${current.label} · ${data.translation}`, minutes > 0 ? `About ${minutes} minute${minutes === 1 ? '' : 's'}` : ''].filter(Boolean).join(' · ') : ''; const outline = current ? { title, subtitle: current.scope === 'study' ? data.translation : `${current.label} · ${data.translation}`, tree: current.tree } : null; return ( -This study doesn’t have an outline yet.
- )} -This study doesn’t have an outline yet.
} + ); } diff --git a/src/utils/bibleUtils.jsx b/src/utils/bibleUtils.jsx index c22a6ee..922ede7 100644 --- a/src/utils/bibleUtils.jsx +++ b/src/utils/bibleUtils.jsx @@ -334,23 +334,36 @@ function outlineListHtml(nodes, depth) { // A page of just one outline (for printing or saving as PDF): the title, the passage, the points. export function buildOutlineHtml({ title, subtitle = '', tree }) { const total = flattenMinutes(tree); + const meta = [subtitle, total > 0 ? `About ${total} minute${total === 1 ? '' : 's'}` : ''].filter(Boolean).join(' · '); + // Simple and calm: paper tones, a serif face, hanging numerals in the accent colour, and generous space. const style = ` - body { font-family: Georgia, serif; color: #0f172a; margin: 0; padding: 40px; } - .page { max-width: 760px; margin: auto; } - h1 { margin: 0 0 0.25rem; font-size: 1.7rem; } - .sub { color: #64748b; margin: 0 0 1.5rem; } - .outline ul { list-style: none; margin: 0.25rem 0 0.25rem 1.6rem; padding: 0; } - .outline > ul { margin-left: 0; } - .outline li { margin: 0.45rem 0; line-height: 1.5; } - .outline > ul > li { margin-top: 0.9rem; font-weight: 600; } - .outline > ul > li li { font-weight: 400; } - .lbl { display: inline-block; min-width: 2.1rem; font-weight: 700; } - .ref { color: #64748b; font-size: 0.9em; font-weight: 400; } - .kind { font-size: 0.72em; text-transform: uppercase; letter-spacing: 0.05em; color: #92400e; border: 1px solid #fcd34d; border-radius: 9999px; padding: 0 0.4em; margin-right: 0.3em; font-weight: 400; } - .o-note { margin: 0.2rem 0 0 2.1rem; color: #334155; font-size: 0.95em; font-weight: 400; } - .o-quote { margin: 0.3rem 0 0.3rem 2.1rem; padding-left: 0.75rem; border-left: 3px solid #cbd5e1; font-style: italic; font-weight: 400; } - .o-attach { margin-left: 2.1rem; font-size: 0.85em; color: #64748b; font-weight: 400; } - @media print { body { padding: 0; } li { break-inside: avoid; } } + :root { --text: #2b2620; --sub: #6b6458; --accent: #a84e27; --line: #e0d8c6; --paper: #faf7f0; } + * { box-sizing: border-box; } + body { font-family: Georgia, 'Times New Roman', serif; color: var(--text); background: var(--paper); margin: 0; padding: 48px 24px 64px; -webkit-font-smoothing: antialiased; } + .page { max-width: 720px; margin: 0 auto; } + .eyebrow { font: 600 0.72rem/1 system-ui, sans-serif; letter-spacing: 0.18em; text-transform: uppercase; color: var(--accent); margin: 0 0 0.9rem; } + h1 { margin: 0; font-size: 2.1rem; line-height: 1.2; font-weight: 600; letter-spacing: -0.01em; } + .sub { font: 0.9rem/1.4 system-ui, sans-serif; color: var(--sub); margin: 0.6rem 0 0; } + .rule { height: 1px; background: var(--line); margin: 1.6rem 0 0.4rem; border: 0; } + .outline ul { list-style: none; margin: 0; padding: 0; } + .outline ul ul { margin-left: 2.4rem; } + .outline li { margin: 0.55rem 0; line-height: 1.55; font-size: 1.05rem; } + .outline > ul > li { margin-top: 1.5rem; font-size: 1.15rem; font-weight: 600; } + .outline > ul > li li { font-weight: 400; font-size: 1.05rem; } + .lbl { display: inline-block; min-width: 2.4rem; color: var(--accent); font-weight: 600; font-variant-numeric: tabular-nums; } + .ref { color: var(--sub); font: 0.82em/1 system-ui, sans-serif; font-weight: 400; white-space: nowrap; } + .kind { font: 600 0.62rem/1 system-ui, sans-serif; text-transform: uppercase; letter-spacing: 0.1em; color: var(--accent); border: 1px solid #e4b9a3; border-radius: 9999px; padding: 0.2em 0.65em; margin-right: 0.5em; vertical-align: 0.15em; } + .o-note { margin: 0.25rem 0 0 2.4rem; color: var(--sub); font-size: 0.95rem; font-weight: 400; font-style: italic; } + .o-quote { margin: 0.5rem 0 0.4rem 2.4rem; padding: 0.1rem 0 0.1rem 1rem; border-left: 3px solid #e4b9a3; font-style: italic; font-weight: 400; font-size: 1rem; } + .o-attach { margin: 0.3rem 0 0 2.4rem; font: 0.8rem/1.5 system-ui, sans-serif; color: var(--sub); font-weight: 400; } + .foot { margin-top: 3rem; padding-top: 1rem; border-top: 1px solid var(--line); font: 0.72rem/1 system-ui, sans-serif; color: var(--sub); text-align: center; letter-spacing: 0.04em; } + @media (max-width: 520px) { body { padding: 32px 18px 48px; } h1 { font-size: 1.7rem; } .outline ul ul { margin-left: 1.5rem; } .o-note, .o-quote, .o-attach { margin-left: 1.5rem; } } + @media print { + body { background: #fff; padding: 0; } + .page { max-width: none; } + li { break-inside: avoid; } + .outline > ul > li { break-after: avoid; } + } `; return ` @@ -362,9 +375,12 @@ export function buildOutlineHtml({ title, subtitle = '', tree }) {Outline
${escHtml([subtitle, total > 0 ? `About ${total} minute${total === 1 ? '' : 's'}` : ''].filter(Boolean).join(' · '))}
+ ${meta ? `${escHtml(meta)}
` : ''} +Bible Study Project