9aa7620461
Номер «N.» рисовался через .definitionContent > :first-child::before, но tiptap-react оборачивает содержимое NodeViewContent в дополнительный блочный div [data-node-view-content-react], поэтому :first-child — это обёртка, а не <p>. Инлайновый ::before на блочной обёртке с блочным <p> внутри падал на свою строку (регрессия «+1 строка» из #420). Селекторы переведены на .definitionContent p:first-child / p:last-child — номер и сброс полей теперь бьют по самому абзацу (контент определения — paragraph+, вложенных абзацев нет, так что попадание однозначно), работает и с обёрткой, и без неё. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
157 lines
4.5 KiB
CSS
157 lines
4.5 KiB
CSS
/* Superscript reference marker. The visible number comes from the numbering
|
|
plugin decoration which sets the --footnote-number CSS variable. */
|
|
.reference {
|
|
cursor: pointer;
|
|
color: var(--mantine-color-blue-6);
|
|
font-weight: 500;
|
|
vertical-align: super;
|
|
font-size: 0.75em;
|
|
line-height: 0;
|
|
user-select: none;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.reference::after {
|
|
content: var(--footnote-number, "");
|
|
}
|
|
|
|
.reference:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.reference.selected {
|
|
background-color: var(--mantine-color-blue-1);
|
|
border-radius: 2px;
|
|
}
|
|
|
|
/* Read-only popover shown on hover/click of a reference. */
|
|
.popover {
|
|
position: absolute;
|
|
z-index: 1000;
|
|
max-width: 360px;
|
|
padding: var(--mantine-spacing-sm);
|
|
background: var(--mantine-color-body);
|
|
color: var(--mantine-color-default-color);
|
|
border: 1px solid var(--mantine-color-default-border);
|
|
border-radius: var(--mantine-radius-md);
|
|
box-shadow: var(--mantine-shadow-md);
|
|
font-size: var(--mantine-font-size-sm);
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.popoverHeader {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--mantine-spacing-xs);
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.popoverNumber {
|
|
font-weight: 600;
|
|
color: var(--mantine-color-dimmed);
|
|
}
|
|
|
|
.popoverBody {
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
}
|
|
|
|
/* Bottom footnotes container. Flex column so the heading (rendered AFTER the
|
|
editable NodeViewContent in the DOM for #146) is lifted back above the list
|
|
visually via `order`, instead of sitting in-flow before the contentDOM. */
|
|
.list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
margin-top: var(--mantine-spacing-lg);
|
|
padding-top: var(--mantine-spacing-md);
|
|
border-top: 1px solid var(--mantine-color-default-border);
|
|
}
|
|
|
|
.listHeading {
|
|
order: -1; /* visually above the list, though it follows it in the DOM (#146) */
|
|
font-weight: 600;
|
|
font-size: var(--mantine-font-size-sm);
|
|
color: var(--mantine-color-dimmed);
|
|
margin-bottom: var(--mantine-spacing-xs);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.03em;
|
|
}
|
|
|
|
.definition {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
/* Tight spacing between the content and the trailing ↩ back-link. */
|
|
gap: 0.3em;
|
|
padding: 2px 0;
|
|
/* Footnotes read smaller than body text (16px). Matches .listHeading. */
|
|
font-size: var(--mantine-font-size-sm);
|
|
}
|
|
|
|
/* The "N." number is decorative (from the --footnote-number CSS var on the
|
|
wrapper, never in the document model) and is rendered inline at the start of
|
|
the first content line via ::before. This keeps text and wrapped lines flush
|
|
to the left margin — no hanging indent — while the editable contentDOM stays
|
|
the FIRST DOM child (#146).
|
|
|
|
The rules below target `p:first-child`, NOT `> :first-child`: tiptap-react
|
|
wraps the NodeViewContent children in an extra block-level div
|
|
(`[data-node-view-content-react]`, style="white-space: inherit"), so
|
|
`.definitionContent`'s first child is that wrapper, not the paragraph. An
|
|
inline ::before on the block wrapper (whose child is a block <p>) drops onto
|
|
its own line above the text — the "+1 line" regression. `p:first-child`
|
|
reaches the real first paragraph so the number stays inline, and it works
|
|
whether or not the wrapper is present (definition content is `paragraph+`,
|
|
so there are no nested paragraphs to mis-match). */
|
|
.definitionContent {
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
}
|
|
|
|
.definitionContent p:first-child::before {
|
|
content: var(--footnote-number, "?") ". ";
|
|
color: var(--mantine-color-dimmed);
|
|
font-variant-numeric: tabular-nums;
|
|
user-select: none;
|
|
}
|
|
|
|
/* The inner editable paragraph inherits `.ProseMirror p { margin: 0.5em 0 }`.
|
|
Drop the outer margins so the definition sits tight to the heading above and
|
|
the ::before number aligns with the top of the row — same approach used for
|
|
callouts in core.css. Target the paragraphs directly (through the
|
|
tiptap-react content wrapper), same reasoning as the ::before rule above. */
|
|
.definitionContent p:first-child {
|
|
margin-top: 0;
|
|
}
|
|
|
|
.definitionContent p:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.backLink {
|
|
flex: 0 0 auto;
|
|
cursor: pointer;
|
|
color: var(--mantine-color-blue-6);
|
|
user-select: none;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.backLink:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
/* Multi-backlink row (#168): ↩ a b c — one lettered link per reference
|
|
occurrence. Sits on the right, after the content, like the single ↩. */
|
|
.backLinks {
|
|
flex: 0 0 auto;
|
|
display: inline-flex;
|
|
align-items: baseline;
|
|
gap: 0.3em;
|
|
user-select: none;
|
|
}
|
|
|
|
.backLinkArrow {
|
|
color: var(--mantine-color-dimmed);
|
|
font-size: 0.9em;
|
|
}
|