/* * doc.css — the Humdrum Preview document house style. * * One stylesheet for documents that come from Kevin. Built on the AppKit * token contract (tokens.css), the AppKit type tokens (display / body / * mono), and the seven themes. Reused across: * - the standalone markdown renderer (index.html) * - the iA Writer template * - the Obsidian export * * It does NOT declare @font-face — the host supplies the fonts (embedded in * the standalone HTML, bundled in the iA template, present in Obsidian). It * only references the three families by name. * * Print target: US Letter, tuned for black-and-white. See @media print. */ /* ─── Tokens: global ──────────────────────────────────────────────── */ :root { --font-display: Georgia, serif; --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace; /* Document measure + rhythm */ --doc-measure: 42rem; /* ~68ch comfortable reading column */ --doc-pad: 2.5rem; --leading: 1.62; --leading-tight: 1.18; --radius-sm: 4px; --radius: 8px; } /* ─── Tokens: themes (from _shared-app-kit/tokens.css) ────────────── */ :root, [data-theme="flexoki"] { --bg:#FFFCF0; --bg-card:#F2F0E5; --bg-elevated:#F2F0E5; --border:#E6E4D9; --border-strong:#CECDC3; --text:#100F0F; --text-muted:#6F6E69; --text-faint:#B7B5AC; --text-on-accent:#FFFCF0; --selection:#DDF1E4; --accent:#24837B; --red:#AF3029; --orange:#BC5215; --yellow:#AD8301; --green:#66800B; --cyan:#24837B; --blue:#205EA6; --purple:#5E409D; --pink:#A02F6F; } [data-theme="flexoki-dark"] { --bg:#100F0F; --bg-card:#1C1B1A; --bg-elevated:#282726; --border:#282726; --border-strong:#403E3C; --text:#CECDC3; --text-muted:#878580; --text-faint:#575653; --text-on-accent:#100F0F; --selection:#122F2C; --accent:#3AA99F; --red:#D14D41; --orange:#DA702C; --yellow:#D0A215; --green:#879A39; --cyan:#3AA99F; --blue:#4385BE; --purple:#8B7EC8; --pink:#CE5D97; } [data-theme="uchu"] { --bg:#FDFCFB; --bg-card:#FFFFFF; --bg-elevated:#FFFFFF; --border:#E9E7E3; --border-strong:#C9C6BF; --text:#17161B; --text-muted:#605D6A; --text-faint:#A8A5B0; --text-on-accent:#FDFCFB; --selection:#E4DCFC; --accent:#6032E8; --red:#E5484D; --orange:#F76808; --yellow:#FFB224; --green:#30A46C; --cyan:#00A2C7; --blue:#0D74CE; --purple:#6032E8; --pink:#D6409F; } [data-theme="uchu-dark"] { --bg:#17161B; --bg-card:#1F1D23; --bg-elevated:#2A2730; --border:#2A2730; --border-strong:#3F3B48; --text:#F2EFF7; --text-muted:#A8A5B0; --text-faint:#605D6A; --text-on-accent:#17161B; --selection:#2E1B66; --accent:#A786FF; --red:#FF6369; --orange:#FF8B3E; --yellow:#FFD15E; --green:#63E094; --cyan:#59D3E8; --blue:#6CAEFF; --purple:#A786FF; --pink:#F36DBF; } /* Humdrum — accent locked to #0F80EA per spec (tokens.css). Color families derived in OKLCH at L0.60 C0.18, hue per family. Same accent in dark. */ [data-theme="humdrum"] { --bg:#F5F3EE; --bg-card:#FFFFFF; --bg-elevated:#FFFFFF; --border:#E2DFD7; --border-strong:#C3BFB3; --text:#2A2825; --text-muted:#6D6A63; --text-faint:#ADA99F; --text-on-accent:#FFFFFF; --selection:oklch(0.85 0.07 253); --accent:#0F80EA; --red:oklch(0.60 0.180 22); --orange:oklch(0.60 0.180 50); --yellow:oklch(0.60 0.180 85); --green:oklch(0.60 0.180 140); --cyan:oklch(0.60 0.180 205); --blue:#0F80EA; --purple:oklch(0.60 0.180 295); --pink:oklch(0.60 0.180 350); } [data-theme="humdrum-dark"] { --bg:#1F1D1A; --bg-card:#282622; --bg-elevated:#32302C; --border:#32302C; --border-strong:#4A4740; --text:#E8E5DD; --text-muted:#A8A49B; --text-faint:#6D6A63; --text-on-accent:#FFFFFF; --selection:oklch(0.35 0.13 253); --accent:#0F80EA; --red:oklch(0.60 0.180 22); --orange:oklch(0.60 0.180 50); --yellow:oklch(0.60 0.180 85); --green:oklch(0.60 0.180 140); --cyan:oklch(0.60 0.180 205); --blue:#0F80EA; --purple:oklch(0.60 0.180 295); --pink:oklch(0.60 0.180 350); } [data-theme="eink"] { --bg:#FFFFFF; --bg-card:#FFFFFF; --bg-elevated:#FFFFFF; --border:#000000; --border-strong:#000000; --text:#000000; --text-muted:#000000; --text-faint:#000000; --text-on-accent:#FFFFFF; --selection:#000000; --accent:#000000; --red:#000; --orange:#000; --yellow:#000; --green:#000; --cyan:#000; --blue:#000; --purple:#000; --pink:#000; } /* ─── The document ────────────────────────────────────────────────── */ .doc { font-family: var(--font-body); font-weight: 400; font-size: 1.0625rem; /* 17px screen baseline */ line-height: var(--leading); color: var(--text); background: var(--bg); max-width: var(--doc-measure); margin: 0 auto; padding: var(--doc-pad); -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; font-feature-settings: "kern" 1, "liga" 1; hanging-punctuation: first; } .doc > :first-child { margin-top: 0; } .doc > :last-child { margin-bottom: 0; } /* Frontmatter properties, shown under the title when enabled. */ .doc .doc-props { display: grid; grid-template-columns: max-content 1fr; gap: 0.25em 1.2em; margin: 0 0 1.8em; padding: 0.7em 0 0.9em; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); font-size: 0.88rem; break-inside: avoid; } .doc .doc-props dt { font-family: var(--font-mono); font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); align-self: baseline; } .doc .doc-props dd { margin: 0; color: var(--text); } /* Headings — display face */ .doc h1, .doc h2, .doc h3, .doc h4, .doc h5, .doc h6 { font-family: var(--font-display); line-height: var(--leading-tight); color: var(--text); margin: 1.2em 0 0; text-wrap: balance; } .doc h1 { font-size: 3rem; font-weight: 700; letter-spacing: -0.01em; margin-top: 0; margin-bottom: 0.6em; } .doc h2 { font-size: 2.2rem; font-weight: 700; letter-spacing: -0.005em; } .doc h3 { font-size: 1.6rem; font-weight: 400; } .doc h4 { font-size: 1.18rem; font-weight: 700; font-family: var(--font-body); } .doc h5 { font-size: 1rem; font-weight: 700; font-family: var(--font-body); text-transform: uppercase; letter-spacing: 0.06em; } .doc h6 { font-size: 0.9rem; font-weight: 500; font-family: var(--font-body); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.08em; } /* Cover wrapper (leading H1 + subtitle). On screen it's just a title block with breathing room; in print it becomes a full centered cover page. */ .doc .cover { margin-bottom: 2.5em; } /* A subtitle: first paragraph right after h1 reads lighter */ .doc h1 + p { font-size: 1.2rem; font-weight: 300; color: var(--text-muted); line-height: 1.45; } .doc p { margin: 0 0 1.1em; } /* Links */ .doc a { color: var(--accent); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.15em; text-decoration-color: color-mix(in oklab, var(--accent) 45%, transparent); } .doc a:hover { text-decoration-color: var(--accent); } /* Emphasis */ .doc strong { font-weight: 700; } .doc em { font-style: italic; } .doc mark { background: color-mix(in oklab, var(--yellow) 32%, transparent); color: inherit; padding: 0 0.15em; border-radius: 2px; } .doc del { color: var(--text-faint); } /* Lists */ .doc ul, .doc ol { margin: 0 0 1.1em; padding-left: 1.5em; } .doc li { margin: 0.3em 0; } .doc li::marker { color: var(--text-muted); } .doc ul ul, .doc ol ol, .doc ul ol, .doc ol ul { margin-bottom: 0; } /* Task lists (GitHub-style checkboxes) */ .doc li.task-list-item { list-style: none; margin-left: -1.3em; } .doc li.task-list-item input { margin-right: 0.5em; accent-color: var(--accent); } /* Blockquote */ .doc blockquote { margin: 1.4em 0; padding: 0.2em 0 0.2em 1.2em; border-left: 3px solid var(--accent); color: var(--text-muted); font-style: italic; } .doc blockquote p:last-child { margin-bottom: 0; } /* Callouts — `> [!type] Title`. Body fully rendered. Each type is the theme accent, only the hue nudged (and a couple muted), so the set stays one family instead of a rainbow. --hue rotates, --chroma mutes; both relative to accent. */ .doc .callout { --hue: 0; --chroma: 1; --co: oklch(from var(--accent) l calc(c * var(--chroma)) calc(h + var(--hue))); margin: 1.4em 0; padding: 0.7em 1em; border: 1px solid var(--border); border-left: 4px solid var(--co); border-radius: var(--radius); background: color-mix(in oklab, var(--co) 7%, var(--bg-card)); color: var(--text); font-style: normal; } .doc .callout-title { font-family: var(--font-body); font-weight: 700; color: var(--co); margin-bottom: 0.35em; line-height: 1.3; } .doc .callout > p:last-child { margin-bottom: 0; } /* Per-type --hue / --chroma are set inline by DocKit.styleCallouts so custom callout types get distinct hues too. */ /* Bare callouts (e.g. `> [!nav]` day navigation) are screen chrome — hide them in every output (screen, HTML, PDF, print). */ .doc .doc-nav { display: none !important; } /* ─── Book (compiled multi-note document) ─────────────────────────── */ .doc.book .book-toc { margin: 0 0 2.2em; } .doc.book .book-toc h2 { margin-top: 0; } .doc.book .book-toc ol { font-size: 1.05rem; line-height: 1.9; padding-left: 1.4em; } .doc.book .book-toc a { text-decoration: none; color: var(--text); } .doc.book .book-toc a:hover { color: var(--accent); } .doc.book .chapter { margin: 0; } /* In continuous mode, separate chapters with a rule instead of a page break. */ .doc.book.continuous .chapter + .chapter { border-top: 1px solid var(--border-strong); margin-top: 2.5em; padding-top: 2em; } /* Base snapshot — a frozen table standing in for an Obsidian Base view. Presented as a labelled card so it clearly reads as a data table. */ .doc .base-snapshot { margin: 1.6em 0; border: 1px solid var(--border-strong); border-radius: var(--radius); background: var(--bg-card); overflow: hidden; } .doc .base-head { display: flex; align-items: baseline; gap: 0.5em; padding: 0.5em 0.9em; background: color-mix(in oklab, var(--accent) 9%, var(--bg-card)); border-bottom: 1px solid var(--border-strong); font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); } .doc .base-head .base-name { font-weight: 600; color: var(--text); letter-spacing: 0.02em; } .doc .base-head .base-count { margin-left: auto; text-transform: none; letter-spacing: 0; } .doc .base-snapshot table { margin: 0; width: 100%; font-size: 0.9rem; } .doc .base-snapshot th { background: transparent; } .doc .base-snapshot th, .doc .base-snapshot td { padding: 0.45em 0.9em; } .doc .base-snapshot tbody tr:nth-child(even) { background: color-mix(in oklab, var(--text) 3.5%, transparent); } .doc .base-snapshot tbody tr:last-child td { border-bottom: none; } .doc .base-list { margin: 0; padding: 0.4em 0.9em 0.5em 1.9em; } .doc .base-list li { margin: 0.2em 0; } .doc .base-list li::marker { color: var(--text-faint); } /* Code */ .doc code { font-family: var(--font-mono); font-size: 0.88em; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.08em 0.35em; } .doc pre { font-family: var(--font-mono); font-size: 0.84rem; line-height: 1.55; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 1em 1.2em; margin: 1.4em 0; overflow-x: auto; } .doc pre code { background: none; border: none; padding: 0; font-size: inherit; } /* Tables */ .doc table { width: 100%; border-collapse: collapse; margin: 1.5em 0; font-size: 0.94rem; } .doc th, .doc td { text-align: left; padding: 0.5em 0.8em; border-bottom: 1px solid var(--border); } .doc thead th { font-weight: 700; border-bottom: 2px solid var(--border-strong); background: var(--bg-card); } .doc tbody tr:last-child td { border-bottom: 1px solid var(--border-strong); } /* Rules + images + figures */ .doc hr { border: none; border-top: 1px solid var(--border-strong); margin: 2.5em 0; } .doc img { max-width: 100%; height: auto; border-radius: var(--radius); } .doc figure { margin: 1.6em 0; } .doc figcaption { font-size: 0.86rem; color: var(--text-muted); margin-top: 0.5em; text-align: center; } .doc kbd { font-family: var(--font-mono); font-size: 0.8em; background: var(--bg-card); border: 1px solid var(--border-strong); border-bottom-width: 2px; border-radius: var(--radius-sm); padding: 0.1em 0.4em; } ::selection { background: var(--selection); } /* eink: differentiate by weight + border, never colour */ [data-theme="eink"] .doc { font-weight: 500; } [data-theme="eink"] .doc h1, [data-theme="eink"] .doc h2, [data-theme="eink"] .doc h3, [data-theme="eink"] .doc strong { font-weight: 800; } [data-theme="eink"] .doc a { text-decoration-color: #000; } [data-theme="eink"] .doc .callout { background: transparent; border: 2px solid #000; } [data-theme="eink"] .doc .callout-title { color: #000; } [data-theme="eink"] .doc mark { background: transparent; border-bottom: 3px solid #000; border-radius: 0; } /* ─── Interactive affordances (screen only) ───────────────────────── */ /* Clickable task checkboxes. Force native, clickable inputs so a host theme (e.g. Obsidian's Minimal) can't restyle them into something that swallows the click — that would stop the change event and break write-back. */ .doc input[type="checkbox"] { -webkit-appearance: checkbox !important; appearance: checkbox !important; pointer-events: auto !important; opacity: 1 !important; position: static !important; cursor: pointer; width: auto; height: auto; margin: 0 0.4em 0 0; background-image: none !important; box-shadow: none !important; -webkit-mask: none !important; mask: none !important; } /* Kill any host-theme pseudo-element checkmark (e.g. Minimal) that would render on top of the native box. */ .doc input[type="checkbox"]::before, .doc input[type="checkbox"]::after { content: none !important; display: none !important; background: none !important; } /* Drag handles for reorderable list items + table rows. Absolutely placed in the gutter so they never shift the content; fade in on hover. */ .doc li, .doc td:first-child { position: relative; } .doc .dk-h { position: absolute; left: -1.25em; top: 0.15em; width: 1em; text-align: center; color: var(--text-faint); font-family: var(--font-mono); cursor: grab; opacity: 0; transition: opacity 0.12s ease; user-select: none; touch-action: none; } .doc td:first-child > .dk-h { left: -0.9em; top: 0.5em; } .doc li:hover > .dk-h, .doc tr:hover .dk-h { opacity: 1; } .doc .dk-h:active { cursor: grabbing; } .doc li.dk-drag, .doc tr.dk-drag { background: var(--bg-hover, rgba(0,0,0,0.05)); opacity: 0.7; } [data-theme="eink"] .doc .dk-h { color: #000; } /* ─── Print: US Letter, black-and-white first ─────────────────────── */ @page { size: letter; /* 8.5 × 11 in */ margin: 0.9in 1in; } @media print { html, body { background: #fff !important; } /* Drag handles and day-nav never print. */ .doc .dk-h, .doc .doc-nav { display: none !important; } /* Layout for every printed doc (colour or B&W). */ .doc { max-width: none; margin: 0; padding: 0; font-size: 11pt; line-height: 1.5; } /* ── Colour mode (.pdf-color): keep the theme's colours, force a white page. Used by the plugin's "Save as PDF" (Humdrum Light). ── */ .doc.pdf-color { --bg: #fff; background: #fff; } .doc.pdf-color, .doc.pdf-color * { -webkit-print-color-adjust: exact; print-color-adjust: exact; } /* ── B&W mode (default browser print): collapse to black ink. ── */ .doc:not(.pdf-color) { --bg:#fff; --bg-card:#fff; --bg-elevated:#fff; --text:#000; --text-muted:#1a1a1a; --text-faint:#444; --border:#bbb; --border-strong:#000; --accent:#000; --selection:#000; color: #000; background: #fff; } .doc:not(.pdf-color) a { color: #000; text-decoration-color: #000; } /* Surface link targets in B&W print (skip with .no-print-urls). */ .doc:not(.pdf-color) a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.82em; color: #444; word-break: break-all; } .doc.no-print-urls a::after { content: none; } .doc:not(.pdf-color) code, .doc:not(.pdf-color) pre, .doc:not(.pdf-color) kbd { background: #fff !important; border: 1px solid #999; } .doc:not(.pdf-color) thead th { background: #f2f2f2 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } .doc:not(.pdf-color) blockquote { border-left: 3px solid #000; color: #1a1a1a; } .doc:not(.pdf-color) .callout { background: #fff !important; border: 1px solid #000; border-left: 4px solid #000; } .doc:not(.pdf-color) .callout-title { color: #000; } .doc:not(.pdf-color) .base-snapshot { border: 1px solid #000; background: #fff !important; } .doc:not(.pdf-color) .base-head { background: #f2f2f2 !important; border-bottom: 1px solid #000; color: #000; -webkit-print-color-adjust: exact; print-color-adjust: exact; } .doc:not(.pdf-color) .base-snapshot tbody tr:nth-child(even) { background: #f6f6f6 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } .doc:not(.pdf-color) mark { background: transparent; border-bottom: 2px solid #000; } /* Pagination hygiene */ .doc h1, .doc h2, .doc h3, .doc h4, .doc h5, .doc h6 { break-after: avoid; break-inside: avoid; } .doc p, .doc blockquote, .doc li { orphans: 3; widows: 3; } .doc pre, .doc table, .doc figure, .doc img, .doc blockquote { break-inside: avoid; } .doc thead { display: table-header-group; } /* repeat header on each page */ .doc tr { break-inside: avoid; } /* Manual extra break: any element carrying .page-break. Both properties for cross-engine support (modern break-* + legacy). */ .doc .page-break { break-before: page; page-break-before: always; } /* Single-note pagination: each H1 starts a new page; H2 and below just flow with their normal spacing. (Gated to :not(.book) — books break on chapters, not headings.) */ .doc:not(.book) h1 { break-before: page; page-break-before: always; margin-top: 0; /* an H1 opening a page sits at the top */ } /* A leading H1 (cover off) just leads page one — no break before it. */ .doc:not(.book) > h1:first-child { break-before: avoid; page-break-before: avoid; } /* ── Book mode: break on chapters, not headings ── */ .doc.book .chapter { break-before: page; page-break-before: always; } .doc.book.continuous .chapter { break-before: auto; page-break-before: auto; } .doc.book .book-toc { break-after: page; page-break-after: always; break-inside: avoid; } /* No double break right after the cover or the TOC. */ .doc.book .cover + .chapter, .doc.book .book-toc + .chapter, .doc.book .cover + .book-toc { break-before: avoid; page-break-before: avoid; } /* Cover page: the leading H1 (+ subtitle) begins ~25% down the sheet — the classic title-page drop. A fixed top padding instead of flex centering, because Chromium's printToPDF ignores flex min-height in paged context. Page is 11in; content top sits at the 0.9in @page margin, so 1.85in of padding lands the title at ~2.75in ≈ 25%. */ .doc .cover { break-before: auto; page-break-before: auto; break-after: page; page-break-after: always; break-inside: avoid; padding-top: 1.85in; } .doc .cover h1 { break-before: auto; page-break-before: auto; margin-top: 0; } }