lumargh_better-bujo/styles.css

596 lines
28 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Better Bujo — bullet-journal markers in place of Obsidian's checkboxes.
*
* Canonical glyph table (keyed on the `data-task` attribute Obsidian sets on
* each list item, in both Reading mode and Live Preview):
*
* - [ ] open task → • (small dot; click cycles → / → x → · )
* - [/] task in progress → / (the ✗'s first stroke; part of the cycle)
* - [x] done → ✗ (two pen-strokes; optional strike
* via the bb-strike-done body class)
* - [>] migrated (month) → >
* - [<] future log → <
* - [o] event → ○ (click cycles o → p → O → o)
* - [p] event in progress→ ◐ (half-filled ring; part of the o/p/O cycle)
* - [O] event done → ● (same size as ○; click cycles back)
* - [-] cancelled → •, marker and whole line struck through, faint
* - … plain list item → (en dash, not a bullet)
* - [9:30 AM] … time event → configurable: dash/AM-PM/circle
* ~ … emotion/thought → styled line (the `~` glyph stays as typed)
*
* Strategy: never remove Obsidian's native marker elements — restyle them in
* place. The checkbox <input> keeps its box (which Obsidian and themes already
* position correctly in both modes) and the glyph is drawn on its ::after,
* replacing the default checkmark mask. Likewise the plain-bullet dot lives on
* `.list-bullet::after` in BOTH modes, so one rule turns it into a dash. This
* way alignment is inherited from whatever theme is active, with no hand-tuned
* offsets.
*
* Every rule is scoped under `.better-bujo` (added to each window's <body> on
* load) so disabling the plugin restores Obsidian's native rendering. */
.better-bujo {
--bb-marker-color: var(--text-muted);
--bb-event-color: var(--text-accent);
--bb-done-color: var(--text-faint);
/* Marker column geometry in Live Preview, expressed in checkbox-size units
so it is independent of font sizes: lead = space before the marker box,
gap = space between marker box and text. Values match Obsidian's default
metrics at the default font size. */
--bb-marker-lead: calc(var(--checkbox-size) * 0.45);
--bb-marker-gap: calc(var(--checkbox-size) * 0.22);
/* Shared pen-stroke for the in-progress slash and the two strokes of the
done ✗, so the slash is literally the ✗'s first stroke at the same angle. */
--bb-stroke-w: max(1.5px, calc(var(--checkbox-size) * 0.1));
--bb-stroke-h: calc(var(--checkbox-size) * 0.62);
/* Wet-ink bleed: a tight dark halo plus a soft outer one and a faint
bottom-right pooling, so each glyph reads like ink soaked into paper
rather than a crisp printed mark. Reused by every marker below. */
--bb-ink-shadow:
0 0 0.03em rgba(42, 22, 10, 0.55),
0 0 0.1em rgba(55, 28, 12, 0.22),
0.01em 0.015em 0.05em rgba(30, 14, 6, 0.18);
/* The actual hand-drawn effect: an inline SVG turbulence filter warps the
rendered glyph edges so the otherwise-perfect font characters get the
uneven wobble of a penned mark. Tune the wobble with baseFrequency (how
often it waves) and scale (how far it pushes the edges). */
--bb-rough: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='r'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.12' numOctaves='2' seed='7' result='n'/%3E%3CfeDisplacementMap in='SourceGraphic' in2='n' scale='1.6'/%3E%3C/filter%3E%3C/svg%3E#r");
}
/* Normalize the checkbox's lead-in/gap under one ruler. Obsidian's native
chain mixes em units that resolve against different font sizes (the label's
-0.25em uses the editor font, the input's 0.85em its own UI font), which
makes it impossible for other marker types to reproduce — so plain bullets
and emotion markers below reuse these same variables instead. */
.better-bujo .markdown-source-view.mod-cm6 .task-list-label {
margin-inline-start: 0;
}
.better-bujo .markdown-source-view.mod-cm6 .task-list-label .task-list-item-checkbox {
margin-inline-start: var(--bb-marker-lead);
margin-inline-end: var(--bb-marker-gap);
}
/* ===========================================================================
* Task / event markers — restyle the native checkbox into a glyph.
*
* The <input> stays in the layout (its box is what themes align), but its
* chrome is stripped in every state: Obsidian's defaults give it a border,
* an accent background when :checked, and a checkmark mask on :checked::after.
* ======================================================================== */
.better-bujo input.task-list-item-checkbox,
.better-bujo input.task-list-item-checkbox:checked,
.better-bujo input.task-list-item-checkbox:hover,
.better-bujo input.task-list-item-checkbox:active,
.better-bujo input.task-list-item-checkbox:focus {
-webkit-appearance: none;
appearance: none;
border: none;
box-shadow: none;
background-color: transparent;
filter: none;
/* Some themes (e.g. Minimal) restyle alternative checkboxes themselves:
they mask the input and rotate it (Minimal turns [>] into a via
rotate(90deg)). Neutralize so the glyph on ::after renders as typed. */
transform: none;
-webkit-mask-image: none;
mask-image: none;
}
/* The glyph. Absolutely positioned over the checkbox box and centered, so a
glyph larger than the box overflows symmetrically without shifting any
text. `content` below is the open-task default; data-task rules swap it. */
.better-bujo input.task-list-item-checkbox::after {
content: "\2022"; /* • — open task, the default for any unrecognised marker */
position: absolute;
inset: 0;
width: auto;
height: auto;
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
-webkit-mask-image: none;
mask-image: none;
color: var(--bb-marker-color);
font-family: var(--font-text);
font-size: var(--checkbox-size);
line-height: 1;
/* Hand-drawn: warp the glyph edges, add ink bleed, and a touch of off-axis
tilt so the mark never sits perfectly square, the way a pen wouldn't. */
filter: var(--bb-rough);
text-shadow: var(--bb-ink-shadow);
transform: rotate(-4deg);
}
/* Open task ( - [ ] ) → a hand-drawn filled dot instead of the font •.
Obsidian leaves data-task off (or empty) on unchecked tasks, so target the
task checkbox whose line carries no real marker. `inset: 0; margin: auto`
centers the dot in the same box the • occupied. */
.better-bujo .markdown-rendered li.task-list-item:is(:not([data-task]), [data-task=""], [data-task=" "]) > input.task-list-item-checkbox::before,
.better-bujo .markdown-rendered li.task-list-item:is(:not([data-task]), [data-task=""], [data-task=" "]) > p > input.task-list-item-checkbox::before,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line:is(:not([data-task]), [data-task=""], [data-task=" "]) input.task-list-item-checkbox::before {
content: "";
position: absolute;
inset: 0;
margin: auto;
box-sizing: border-box;
width: calc(var(--checkbox-size) * 0.26);
height: calc(var(--checkbox-size) * 0.26);
background-color: var(--bb-marker-color);
/* Lopsided radii + tilt + ink bleed match the event rings' hand-drawn look. */
border-radius: 47% 53% 52% 48% / 53% 47% 53% 47%;
transform: rotate(-8deg);
filter: var(--bb-rough);
box-shadow: var(--bb-ink-shadow);
}
.better-bujo .markdown-rendered li.task-list-item:is(:not([data-task]), [data-task=""], [data-task=" "]) > input.task-list-item-checkbox::after,
.better-bujo .markdown-rendered li.task-list-item:is(:not([data-task]), [data-task=""], [data-task=" "]) > p > input.task-list-item-checkbox::after,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line:is(:not([data-task]), [data-task=""], [data-task=" "]) input.task-list-item-checkbox::after {
content: "";
}
/* Glyphs per marker. `data-task` lives on the <li> in Reading mode (the
checkbox is its direct child, or inside a <p> in loose lists) and on the
line div in Live Preview. Child combinators in Reading mode keep nested
list items from inheriting their parent's marker. */
/* ✗ done + / in-progress — drawn from identical rounded pen-strokes (not font
glyphs), so the in-progress slash is literally the ✗'s first (/) stroke at
the same angle, thickness and ink bleed. Each stroke is a centered rounded
bar; rotate(45deg) is the / diagonal. The done ✗ adds the mirror \ on
::before below. */
.better-bujo li[data-task="/"] > input.task-list-item-checkbox::after,
.better-bujo li[data-task="/"] > p > input.task-list-item-checkbox::after,
.better-bujo .HyperMD-task-line[data-task="/"] input.task-list-item-checkbox::after,
.better-bujo li[data-task="x"] > input.task-list-item-checkbox::after,
.better-bujo li[data-task="x"] > p > input.task-list-item-checkbox::after,
.better-bujo .HyperMD-task-line[data-task="x"] input.task-list-item-checkbox::after,
.better-bujo li[data-task="X"] > input.task-list-item-checkbox::after,
.better-bujo li[data-task="X"] > p > input.task-list-item-checkbox::after,
.better-bujo .HyperMD-task-line[data-task="X"] input.task-list-item-checkbox::after,
.better-bujo li[data-task="x"] > input.task-list-item-checkbox::before,
.better-bujo li[data-task="x"] > p > input.task-list-item-checkbox::before,
.better-bujo .HyperMD-task-line[data-task="x"] input.task-list-item-checkbox::before,
.better-bujo li[data-task="X"] > input.task-list-item-checkbox::before,
.better-bujo li[data-task="X"] > p > input.task-list-item-checkbox::before,
.better-bujo .HyperMD-task-line[data-task="X"] input.task-list-item-checkbox::before {
content: "";
position: absolute;
inset: 0;
margin: auto;
width: var(--bb-stroke-w);
height: var(--bb-stroke-h);
background-color: var(--bb-marker-color);
border-radius: var(--bb-stroke-w);
transform: rotate(45deg);
filter: var(--bb-rough);
box-shadow: var(--bb-ink-shadow);
}
/* The done ✗'s second stroke: the mirror diagonal. */
.better-bujo li[data-task="x"] > input.task-list-item-checkbox::before,
.better-bujo li[data-task="x"] > p > input.task-list-item-checkbox::before,
.better-bujo .HyperMD-task-line[data-task="x"] input.task-list-item-checkbox::before,
.better-bujo li[data-task="X"] > input.task-list-item-checkbox::before,
.better-bujo li[data-task="X"] > p > input.task-list-item-checkbox::before,
.better-bujo .HyperMD-task-line[data-task="X"] input.task-list-item-checkbox::before {
transform: rotate(-45deg);
}
/* Done tasks read like any other line: undo Obsidian's native fade and
strikethrough. The strike comes back when the user enables it in settings
(the plugin then adds bb-strike-done next to better-bujo on <body>). */
.better-bujo .markdown-rendered ul > li.task-list-item[data-task="x"],
.better-bujo .markdown-rendered ul > li.task-list-item[data-task="X"],
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="x"],
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="X"] {
text-decoration: none;
color: inherit;
}
.better-bujo.bb-strike-done .markdown-rendered ul > li.task-list-item[data-task="x"],
.better-bujo.bb-strike-done .markdown-rendered ul > li.task-list-item[data-task="X"],
.better-bujo.bb-strike-done .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="x"],
.better-bujo.bb-strike-done .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="X"] {
text-decoration: line-through;
}
.better-bujo li[data-task=">"] > input.task-list-item-checkbox::after,
.better-bujo li[data-task=">"] > p > input.task-list-item-checkbox::after,
.better-bujo .HyperMD-task-line[data-task=">"] input.task-list-item-checkbox::after {
content: ">";
font-size: 1em;
font-weight: 500;
margin-top: 0.05em;
}
.better-bujo li[data-task="<"] > input.task-list-item-checkbox::after,
.better-bujo li[data-task="<"] > p > input.task-list-item-checkbox::after,
.better-bujo .HyperMD-task-line[data-task="<"] input.task-list-item-checkbox::after {
content: "<";
font-size: 1em;
font-weight: 500;
margin-bottom: 0.05em;
}
/* Events (o / O) — drawn as a CSS circle rather than font glyphs (○ ● from a
font come from whatever fallback has them, so their sizes can differ). The
circle lives on ::before: open is the outline, done the same circle filled.
All dimensions derive from --checkbox-size, so the pair is always equal. */
.better-bujo li[data-task="o"] > input.task-list-item-checkbox::before,
.better-bujo li[data-task="o"] > p > input.task-list-item-checkbox::before,
.better-bujo .HyperMD-task-line[data-task="o"] input.task-list-item-checkbox::before,
.better-bujo li[data-task="O"] > input.task-list-item-checkbox::before,
.better-bujo li[data-task="O"] > p > input.task-list-item-checkbox::before,
.better-bujo .HyperMD-task-line[data-task="O"] input.task-list-item-checkbox::before,
.better-bujo li[data-task="p"] > input.task-list-item-checkbox::before,
.better-bujo li[data-task="p"] > p > input.task-list-item-checkbox::before,
.better-bujo .HyperMD-task-line[data-task="p"] input.task-list-item-checkbox::before {
content: "";
position: absolute;
inset: 0;
margin: 0.4em 0 0 0.3em;
box-sizing: border-box;
width: calc(var(--checkbox-size) * 0.5);
height: calc(var(--checkbox-size) * 0.5);
border: max(1px, calc(var(--checkbox-size) * 0.08)) solid var(--bb-marker-color);
/* Lopsided radii + tilt turn the perfect CSS circle into a wobbly,
hand-drawn ring; the ink shadow makes the stroke bleed like the glyphs. */
border-radius: 47% 53% 52% 48% / 53% 47% 53% 47%;
transform: rotate(-8deg);
filter: var(--bb-rough);
box-shadow: var(--bb-ink-shadow);
}
/* No inner symbol for the event states — blank out the • that would otherwise
sit inside the ring. */
.better-bujo li[data-task="o"] > input.task-list-item-checkbox::after,
.better-bujo li[data-task="o"] > p > input.task-list-item-checkbox::after,
.better-bujo .HyperMD-task-line[data-task="o"] input.task-list-item-checkbox::after,
.better-bujo li[data-task="O"] > input.task-list-item-checkbox::after,
.better-bujo li[data-task="O"] > p > input.task-list-item-checkbox::after,
.better-bujo .HyperMD-task-line[data-task="O"] input.task-list-item-checkbox::after,
.better-bujo li[data-task="p"] > input.task-list-item-checkbox::after,
.better-bujo li[data-task="p"] > p > input.task-list-item-checkbox::after,
.better-bujo .HyperMD-task-line[data-task="p"] input.task-list-item-checkbox::after {
content: "";
}
/* ● — completed event: the same circle, filled. */
.better-bujo li[data-task="O"] > input.task-list-item-checkbox::before,
.better-bujo li[data-task="O"] > p > input.task-list-item-checkbox::before,
.better-bujo .HyperMD-task-line[data-task="O"] input.task-list-item-checkbox::before {
background-color: var(--bb-marker-color);
}
/* ◐ — in-progress event: the same ring, half filled. Clicking cycles the
event o → p → O → o. */
.better-bujo li[data-task="p"] > input.task-list-item-checkbox::before,
.better-bujo li[data-task="p"] > p > input.task-list-item-checkbox::before,
.better-bujo .HyperMD-task-line[data-task="p"] input.task-list-item-checkbox::before {
background-image: linear-gradient(90deg, var(--bb-marker-color) 50%, transparent 50%);
}
.better-bujo li[data-task="~"] > input.task-list-item-checkbox::after,
.better-bujo li[data-task="~"] > p > input.task-list-item-checkbox::after,
.better-bujo .HyperMD-task-line[data-task="~"] input.task-list-item-checkbox::after {
content: "~";
}
/* Cancelled tasks: the whole line is struck through and faint, like crossing
out an irrelevant task on paper. Mirrors Obsidian's native done styling,
which targets these same elements. The marker's ::after is absolutely
positioned, so the line's text-decoration doesn't propagate into it — the
strike across the full item is drawn via ::before instead, so the same
hand-drawn filter can be applied. */
.better-bujo .markdown-rendered li[data-task="-"],
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="-"] {
text-decoration: none;
color: var(--bb-done-color);
position: relative;
}
/* Hand-drawn strikethrough: a thin bar absolutely centred on the line, warped
by the same rough filter as every other glyph. `rotate(-0.6deg)` gives a
barely-perceptible descending tilt, the way a hand-ruled line would. */
.better-bujo .markdown-rendered li[data-task="-"]::before,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="-"]::before {
content: "";
position: absolute;
left: 0;
right: 0;
top: 50%;
height: max(2px, 0.09em);
transform: translateY(-50%) rotate(-0.6deg);
background-color: currentColor;
filter: var(--bb-rough);
pointer-events: none;
z-index: 1;
}
.better-bujo li[data-task="-"] > input.task-list-item-checkbox::after,
.better-bujo li[data-task="-"] > p > input.task-list-item-checkbox::after,
.better-bujo .HyperMD-task-line[data-task="-"] input.task-list-item-checkbox::after {
color: var(--bb-done-color);
}
/* Non-standard markers (>, <, ~, -) are not a checkbox state, so clicking
them shouldn't toggle anything. In Live Preview the click is forwarded by
the <label>; in Reading mode the <input> itself is the target. The standard
open/done pair ([ ] ↔ [x]) stays clickable in both modes, and events
(o / O) stay clickable too — the plugin toggles them o ↔ O. */
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task=">"] .task-list-label,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="<"] .task-list-label,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="~"] .task-list-label,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="-"] .task-list-label,
.better-bujo .markdown-rendered li[data-task=">"] > input.task-list-item-checkbox,
.better-bujo .markdown-rendered li[data-task="<"] > input.task-list-item-checkbox,
.better-bujo .markdown-rendered li[data-task="~"] > input.task-list-item-checkbox,
.better-bujo .markdown-rendered li[data-task="-"] > input.task-list-item-checkbox {
pointer-events: none;
}
/* Event and in-progress markers act on click — show they're interactive. */
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="o"] input.task-list-item-checkbox,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="O"] input.task-list-item-checkbox,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="p"] input.task-list-item-checkbox,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-task-line[data-task="/"] input.task-list-item-checkbox,
.better-bujo .markdown-rendered li[data-task="o"] > input.task-list-item-checkbox,
.better-bujo .markdown-rendered li[data-task="O"] > input.task-list-item-checkbox,
.better-bujo .markdown-rendered li[data-task="p"] > input.task-list-item-checkbox,
.better-bujo .markdown-rendered li[data-task="/"] > input.task-list-item-checkbox,
.better-bujo .markdown-rendered li[data-task="o"] > p > input.task-list-item-checkbox,
.better-bujo .markdown-rendered li[data-task="O"] > p > input.task-list-item-checkbox,
.better-bujo .markdown-rendered li[data-task="p"] > p > input.task-list-item-checkbox,
.better-bujo .markdown-rendered li[data-task="/"] > p > input.task-list-item-checkbox {
cursor: var(--cursor-link);
}
/* ===========================================================================
* Plain "- " list items → en dash instead of a bullet.
*
* In both modes Obsidian draws the bullet dot on `.list-bullet::after`
* (absolutely positioned and centered inside the span; the dot itself is
* `background-color` + `border-radius` on a 0.3em box). Swapping the dot for
* an en dash inside that same box inherits the theme's bullet position
* exactly. The span's own text (the typed `-` in Live Preview) stays hidden
* by Obsidian's `color: transparent`, which we leave alone.
*
* Live Preview is scoped to non-task lines so the dash never bleeds onto the
* raw `- [x]` text of an active task line; Reading-mode task bullets are
* already `display: none` natively.
* ======================================================================== */
.better-bujo .markdown-rendered .list-bullet::after,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-list-line:not(.HyperMD-task-line) .list-bullet::after {
content: "\2013"; /* */
width: auto;
height: auto;
border: none;
border-radius: 0;
background-color: transparent;
transform: rotate(-4deg);
color: var(--bb-marker-color);
line-height: 1;
filter: var(--bb-rough);
text-shadow: var(--bb-ink-shadow);
}
/* Align plain-item text with task text in Live Preview by giving the bullet
span the exact marker box of a task checkbox: lead → box → gap → text. The
bullet's parent span carries the list's --list-padding-inline-start, so
subtract it from the lead. */
.better-bujo .markdown-source-view.mod-cm6.is-live-preview .HyperMD-list-line:not(.HyperMD-task-line) .list-bullet {
width: var(--checkbox-size);
margin-inline-start: calc(var(--bb-marker-lead) - var(--list-padding-inline-start));
margin-inline-end: var(--bb-marker-gap);
}
/* ===========================================================================
* Time-based events ("- [9:30 AM] …").
*
* Three rendering styles, chosen in settings:
*
* default — dash bullet unchanged; [time] wrapped in .bb-clock-bracket for
* a muted highlight, brackets kept visible.
* ampm — brackets stripped; bullet replaced with a small "AM"/"PM" label
* (classes bb-clock-am / bb-clock-pm / bb-clock-line-am / -pm).
* circle — brackets stripped; bullet replaced with an event-style ring
* (classes bb-clock-circle / bb-clock-line-circle).
*
* `inset: 0; margin: auto` centers the replacement in the bullet box used by
* the dash, so it aligns with every other marker.
* ======================================================================== */
/* "default" style: muted colour on the [time] bracket span. */
.better-bujo .bb-clock-bracket {
color: var(--text-muted);
font-variant-numeric: tabular-nums;
}
/* "ampm" style: shared layout for the AM/PM text label. */
.better-bujo .markdown-rendered li.bb-clock-am .list-bullet::after,
.better-bujo .markdown-rendered li.bb-clock-pm .list-bullet::after,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-list-line.bb-clock-line-am .list-bullet::after,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-list-line.bb-clock-line-pm .list-bullet::after {
position: absolute;
inset: 0;
margin: auto;
display: flex;
align-items: center;
justify-content: center;
width: var(--checkbox-size);
height: var(--checkbox-size);
font-size: calc(var(--checkbox-size) * 0.34);
font-weight: 700;
letter-spacing: -0.02em;
color: var(--bb-marker-color);
transform: rotate(-4deg);
filter: var(--bb-rough);
}
.better-bujo .markdown-rendered li.bb-clock-am .list-bullet::after,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-list-line.bb-clock-line-am .list-bullet::after {
content: "AM";
}
.better-bujo .markdown-rendered li.bb-clock-pm .list-bullet::after,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-list-line.bb-clock-line-pm .list-bullet::after {
content: "PM";
}
/* "circle" style: wobbly hand-drawn ring, matching the event ○ proportions. */
.better-bujo .markdown-rendered li.bb-clock-circle .list-bullet::after,
.better-bujo .markdown-source-view.mod-cm6 .HyperMD-list-line.bb-clock-line-circle .list-bullet::after {
content: "";
position: absolute;
inset: 0;
margin: auto;
box-sizing: border-box;
width: calc(var(--checkbox-size) * 0.5);
height: calc(var(--checkbox-size) * 0.5);
background-color: transparent;
border: max(1px, calc(var(--checkbox-size) * 0.08)) solid var(--bb-marker-color);
border-radius: 47% 53% 52% 48% / 53% 47% 53% 47%;
transform: rotate(-8deg);
filter: var(--bb-rough);
box-shadow: var(--bb-ink-shadow);
}
/* ===========================================================================
* Emotion / thought lines ("~ …"). Tagged with .bb-emotion by the plugin.
* ======================================================================== */
.better-bujo .bb-emotion {
font-style: italic;
color: var(--text-muted);
}
/* Reading mode: the post-processor moves the `~` into .bb-emotion-marker and
strips it from the text. Indent the paragraph like a list item (3ch, same
as .markdown-rendered li) and clone the reading checkbox chain
(-1.5 / 1 / 0.5 × checkbox-size) so marker and text join the columns. */
.better-bujo .markdown-rendered .bb-emotion {
margin-inline-start: 3ch;
}
.better-bujo .markdown-rendered .bb-emotion .bb-emotion-marker {
display: inline-block;
width: var(--checkbox-size);
margin-inline-start: calc(var(--checkbox-size) * -1.5);
margin-inline-end: calc(var(--checkbox-size) * 0.5);
text-align: center;
color: var(--bb-marker-color);
filter: var(--bb-rough);
text-shadow: var(--bb-ink-shadow);
}
/* In Live Preview the leading `~` is wrapped in .bb-emotion-marker by the
editor extension. Give it the same marker box as a task checkbox (no list
padding on these lines) so the `~` sits in the marker column and the text
aligns with task text. */
.better-bujo .markdown-source-view.mod-cm6.is-live-preview .bb-emotion-marker {
display: inline-block;
width: var(--checkbox-size);
margin-inline-start: var(--bb-marker-lead);
margin-inline-end: var(--bb-marker-gap);
text-align: center;
color: var(--bb-marker-color);
filter: var(--bb-rough);
text-shadow: var(--bb-ink-shadow);
}
/* ===========================================================================
* Dotted grid — optional dot-grid paper background (bb-dotted-grid on <body>).
*
* Vertical extent: the sizer (.cm-sizer / .markdown-preview-sizer) wraps the
* note content plus the embedded backlinks ("Backlinks in document"), so the
* grid spans exactly that — it scrolls with the text and stops at the
* backlinks instead of filling the rest of the pane. The backlinks block
* itself sits on a full-width opaque cover (its own pseudo-element, painted
* between the dots and the backlinks content), so the grid visually ends
* where the backlinks begin.
*
* Horizontal extent: under readable line length the sizer is width-capped
* (max-width: var(--file-line-width)), so the dots are drawn on a
* pseudo-element stretched to the full pane width (50% - 50vw spill on each
* side); the scroller clips the spill so no horizontal scrollbar appears.
* z-index: 0 on the sizer opens a stacking context that sandwiches the
* z-index: -1 dots between the pane background and the text.
*
* Spacing comes from --bb-grid-spacing, set inline on <body> from the
* plugin's "Grid spacing" setting.
* ======================================================================== */
.better-bujo.bb-dotted-grid {
--bb-grid-dot-color: var(--background-modifier-border);
}
.better-bujo.bb-dotted-grid .markdown-source-view.mod-cm6 .cm-sizer,
.better-bujo.bb-dotted-grid .markdown-preview-view .markdown-preview-sizer {
position: relative;
z-index: 0;
}
.better-bujo.bb-dotted-grid .markdown-source-view.mod-cm6 .cm-sizer::before,
.better-bujo.bb-dotted-grid .markdown-preview-view .markdown-preview-sizer::before {
content: '';
position: absolute;
inset: 0 calc(50% - 50vw);
z-index: -1;
pointer-events: none;
background-image: radial-gradient(circle, var(--bb-grid-dot-color) 1px, transparent 1.5px);
background-size: var(--bb-grid-spacing, 20px) var(--bb-grid-spacing, 20px);
}
/* Mask the dots behind (and beside) the embedded backlinks. Same negative
z-index layer as the grid pseudo-element; tree order puts the cover on
top of the dots, and the backlinks content paints above both. */
.better-bujo.bb-dotted-grid .embedded-backlinks {
position: relative;
}
.better-bujo.bb-dotted-grid .embedded-backlinks::before {
content: '';
position: absolute;
inset: 0 calc(50% - 50vw);
z-index: -1;
pointer-events: none;
background-color: var(--background-primary);
}
/* Keep the pseudo-element's horizontal spill from creating a scrollbar.
(clip computes to hidden here since overflow-y is a scroll value.)
The editor scroller needs overflow-y stated explicitly: CodeMirror only
sets overflow-x: auto, and its vertical scrolling relies on overflow-y:
visible computing to auto against that — overriding overflow-x with a
non-scrolling value would otherwise turn vertical scrolling off. */
.better-bujo.bb-dotted-grid .markdown-source-view.mod-cm6 .cm-scroller {
overflow-y: auto;
}
.better-bujo.bb-dotted-grid .markdown-source-view.mod-cm6 .cm-scroller,
.better-bujo.bb-dotted-grid .markdown-preview-view {
overflow-x: clip;
}