You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
717 lines
24 KiB
717 lines
24 KiB
|
4 months ago
|
/**
|
||
|
|
* words.css — eidos visual for the Words editor (content layer).
|
||
|
|
*
|
||
|
|
* Targets the `data-words-*` attributes the engine's render tree emits
|
||
|
|
* (see soma `engine/render.ts`) plus the editor chrome that layers over
|
||
|
|
* the content: the left block gutter and the floating selection bubble
|
||
|
|
* (their Svelte lives in `words-block-gutter.svelte` /
|
||
|
|
* `words-bubble.svelte`; the visuals live here). The settings drawer
|
||
|
|
* keeps its own recipe.
|
||
|
|
*
|
||
|
|
* Tokens are the `--words-*` recipe surface (eidos/lib/recipes/base.ts).
|
||
|
|
* The reading typography is deliberately document-grade (generous size +
|
||
|
|
* line-height + block rhythm), not the tight UI scale.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/* ── Frame ────────────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
[data-words] {
|
||
|
|
/* size cascade — md is the default; sm / lg override below.
|
||
|
|
content-px is gutter-aware (leaves room for the block handle in the
|
||
|
|
left margin + the settings button in the right margin) with enough
|
||
|
|
clearance that the dashed block outline never crowds the grip. */
|
||
|
|
--_words-content-px: 3rem;
|
||
|
|
--_words-content-py: var(--words-content-py-md);
|
||
|
|
--_words-content-min: var(--words-content-min-block-size-md);
|
||
|
|
--_words-content-max: var(--words-content-max-block-size-md);
|
||
|
|
--_words-content-font-size: var(--words-font-size-lg);
|
||
|
|
--_words-radius: var(--words-radius-md);
|
||
|
|
|
||
|
|
position: relative;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
inline-size: 100%;
|
||
|
|
font-family: var(--words-font-family);
|
||
|
|
color: var(--words-color);
|
||
|
|
background: var(--words-bg);
|
||
|
|
border: var(--words-border-width) solid var(--words-border);
|
||
|
|
border-radius: var(--_words-radius);
|
||
|
|
box-shadow: var(--words-shadow);
|
||
|
|
transition:
|
||
|
|
border-color var(--words-transition-duration) var(--words-transition-ease),
|
||
|
|
box-shadow var(--words-transition-duration) var(--words-transition-ease);
|
||
|
|
}
|
||
|
|
|
||
|
|
[data-words][data-size='sm'] {
|
||
|
|
--_words-content-px: 2.5rem;
|
||
|
|
--_words-content-py: var(--words-content-py-sm);
|
||
|
|
--_words-content-min: var(--words-content-min-block-size-sm);
|
||
|
|
--_words-content-max: var(--words-content-max-block-size-sm);
|
||
|
|
--_words-content-font-size: var(--words-font-size-md);
|
||
|
|
--_words-radius: var(--words-radius-sm);
|
||
|
|
}
|
||
|
|
|
||
|
|
[data-words][data-size='lg'] {
|
||
|
|
--_words-content-px: 3.5rem;
|
||
|
|
--_words-content-py: var(--words-content-py-lg);
|
||
|
|
--_words-content-min: var(--words-content-min-block-size-lg);
|
||
|
|
--_words-content-max: var(--words-content-max-block-size-lg);
|
||
|
|
--_words-content-font-size: calc(var(--words-font-size-lg) + 2px);
|
||
|
|
--_words-radius: var(--words-radius-lg);
|
||
|
|
}
|
||
|
|
|
||
|
|
[data-words]:focus-within {
|
||
|
|
border-color: var(--words-border-hover);
|
||
|
|
box-shadow: var(--words-focus-shadow);
|
||
|
|
}
|
||
|
|
|
||
|
|
[data-words][data-invalid] {
|
||
|
|
border-color: var(--words-invalid-border);
|
||
|
|
}
|
||
|
|
|
||
|
|
[data-words][data-disabled] {
|
||
|
|
opacity: var(--words-disabled-opacity);
|
||
|
|
pointer-events: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Pre-mount frame (client-only editor — see words.svelte). Holds the
|
||
|
|
min height so swapping in the live editor doesn't shift layout. */
|
||
|
|
[data-words][aria-busy='true'] {
|
||
|
|
min-block-size: calc(var(--_words-content-min) + 2 * var(--_words-content-py));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Left gutter — block handle ───────────────────────────────────────── */
|
||
|
|
|
||
|
|
[data-words-block-gutter] {
|
||
|
|
position: absolute;
|
||
|
|
inset-inline-start: 0.35rem;
|
||
|
|
z-index: 2;
|
||
|
|
/* nudge so the grip centres on the block's first line */
|
||
|
|
margin-block-start: 0.12em;
|
||
|
|
/* slide smoothly between blocks as the cursor moves */
|
||
|
|
transition: top 120ms var(--words-transition-ease);
|
||
|
|
animation: words-gutter-in 140ms var(--words-transition-ease);
|
||
|
|
}
|
||
|
|
@keyframes words-gutter-in {
|
||
|
|
from {
|
||
|
|
opacity: 0;
|
||
|
|
transform: translateX(-4px);
|
||
|
|
}
|
||
|
|
to {
|
||
|
|
opacity: 1;
|
||
|
|
transform: translateX(0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
[data-words-block-gutter] [data-words-block-handle] {
|
||
|
|
color: var(--words-placeholder-color);
|
||
|
|
cursor: grab;
|
||
|
|
transition:
|
||
|
|
transform var(--words-transition-duration) var(--words-transition-ease),
|
||
|
|
color var(--words-transition-duration) var(--words-transition-ease);
|
||
|
|
}
|
||
|
|
/* subtle displacement when the cursor lands on the handle */
|
||
|
|
[data-words-block-gutter] [data-words-block-handle]:hover {
|
||
|
|
color: var(--words-content-color);
|
||
|
|
transform: translateX(1px) scale(1.18);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* dashed outline emphasising the block the handle acts on */
|
||
|
|
[data-words-block-outline] {
|
||
|
|
position: absolute;
|
||
|
|
z-index: 1;
|
||
|
|
pointer-events: none;
|
||
|
|
border: 1px dashed var(--words-border-hover);
|
||
|
|
border-radius: var(--words-radius-sm);
|
||
|
|
animation: words-outline-in var(--words-transition-duration) var(--words-transition-ease);
|
||
|
|
}
|
||
|
|
@keyframes words-outline-in {
|
||
|
|
from {
|
||
|
|
opacity: 0;
|
||
|
|
}
|
||
|
|
to {
|
||
|
|
opacity: 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Selection bubble toolbar ─────────────────────────────────────────── */
|
||
|
|
|
||
|
|
/* Floating card, viewport-anchored (the soma BubbleMenu writes
|
||
|
|
--_words-bubble-x / -y from the selection's client rect, so position
|
||
|
|
is fixed). Centred horizontally on the selection; sits above it for
|
||
|
|
side='top', below for side='bottom'. */
|
||
|
|
[data-words-bubble-menu] {
|
||
|
|
position: fixed;
|
||
|
|
inset-block-start: var(--_words-bubble-y, 0);
|
||
|
|
inset-inline-start: var(--_words-bubble-x, 0);
|
||
|
|
z-index: 30;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: var(--words-command-gap);
|
||
|
|
padding: var(--space-1);
|
||
|
|
background: var(--words-bg);
|
||
|
|
border: var(--words-border-width) solid var(--words-border);
|
||
|
|
border-radius: var(--words-radius-md);
|
||
|
|
box-shadow: var(--shadow-overlay);
|
||
|
|
animation: words-bubble-in 120ms var(--words-transition-ease);
|
||
|
|
}
|
||
|
|
[data-words-bubble-menu][data-side='top'] {
|
||
|
|
transform: translate(-50%, calc(-100% - 0.5rem));
|
||
|
|
}
|
||
|
|
[data-words-bubble-menu][data-side='bottom'] {
|
||
|
|
transform: translate(-50%, 0.5rem);
|
||
|
|
}
|
||
|
|
[data-words-bubble-menu][hidden] {
|
||
|
|
display: none;
|
||
|
|
}
|
||
|
|
/* Opacity-only so the keyframe doesn't fight the data-side transform. */
|
||
|
|
@keyframes words-bubble-in {
|
||
|
|
from {
|
||
|
|
opacity: 0;
|
||
|
|
}
|
||
|
|
to {
|
||
|
|
opacity: 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Active mark — the soma CommandButton stamps data-active / aria-pressed
|
||
|
|
on the composed eidos Button; tint it to read as "on". (The Button
|
||
|
|
recipe owns every other state: hover, focus, disabled, sizing.) */
|
||
|
|
[data-words-bubble-menu] [data-button][data-active] {
|
||
|
|
background: var(--words-primary-solid);
|
||
|
|
color: var(--words-command-solid-color);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Thin vertical rule between groups. */
|
||
|
|
[data-words-bubble-menu] [data-words-bubble-divider] {
|
||
|
|
flex: 0 0 auto;
|
||
|
|
inline-size: 1px;
|
||
|
|
block-size: 1.15rem;
|
||
|
|
margin-inline: var(--space-0-5);
|
||
|
|
background: var(--words-border);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Turn-into trigger (an eidos Button) — keep it slim in the bubble. */
|
||
|
|
[data-words-bubble-menu] [data-words-bubble-trigger] {
|
||
|
|
white-space: nowrap;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Inline link editor row (replaces the toolbar while editing a link). */
|
||
|
|
[data-words-bubble-menu] [data-words-bubble-link] {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: var(--space-1);
|
||
|
|
}
|
||
|
|
[data-words-bubble-menu] [data-words-bubble-link] input {
|
||
|
|
inline-size: 15rem;
|
||
|
|
padding: var(--space-1) var(--space-2);
|
||
|
|
border: var(--words-border-width) solid var(--words-border);
|
||
|
|
border-radius: var(--words-command-radius);
|
||
|
|
background: var(--words-bg);
|
||
|
|
color: var(--words-content-color);
|
||
|
|
font-family: inherit;
|
||
|
|
font-size: var(--words-font-size-md);
|
||
|
|
outline: none;
|
||
|
|
}
|
||
|
|
[data-words-bubble-menu] [data-words-bubble-link] input:focus {
|
||
|
|
border-color: var(--words-border-hover);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Turn-into menu item — label + trailing active tick. */
|
||
|
|
[data-words-bubble-into-item] {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
gap: var(--space-4);
|
||
|
|
}
|
||
|
|
/* trailing active tick (eidos Icon) */
|
||
|
|
[data-words-bubble-into-item] [data-icon] {
|
||
|
|
color: var(--words-primary-text);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Block inspector ──────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
/* Shared body — a vertical stack of labelled property rows. Reused by
|
||
|
|
every inspector presentation (sidebar / drawer / popover). The vertical
|
||
|
|
layout gives each control a full-width row, so nothing crowds. */
|
||
|
|
/* The inspector body lives inside a soma `Words.Drawer` (for live provider
|
||
|
|
reactivity); that host adds no layout — only the inner panel does. */
|
||
|
|
[data-words-inspector-host] {
|
||
|
|
display: contents;
|
||
|
|
}
|
||
|
|
[data-words-inspector] {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
gap: var(--space-4);
|
||
|
|
padding: var(--space-4);
|
||
|
|
}
|
||
|
|
[data-words-inspector-title] {
|
||
|
|
font-size: var(--words-font-size-md);
|
||
|
|
font-weight: var(--words-strong-font-weight);
|
||
|
|
color: var(--words-content-color);
|
||
|
|
}
|
||
|
|
[data-words-inspector-section] {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
gap: var(--space-2-5);
|
||
|
|
}
|
||
|
|
[data-words-inspector-section-title] {
|
||
|
|
font-size: var(--words-font-size-sm);
|
||
|
|
font-weight: var(--words-strong-font-weight);
|
||
|
|
color: var(--words-placeholder-color);
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 0.05em;
|
||
|
|
}
|
||
|
|
[data-words-inspector-row] {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
gap: var(--space-1-5);
|
||
|
|
}
|
||
|
|
[data-words-inspector-rowhead] {
|
||
|
|
display: flex;
|
||
|
|
align-items: baseline;
|
||
|
|
justify-content: space-between;
|
||
|
|
}
|
||
|
|
[data-words-inspector-label] {
|
||
|
|
font-size: var(--words-font-size-sm);
|
||
|
|
color: var(--words-command-color);
|
||
|
|
}
|
||
|
|
[data-words-inspector-value] {
|
||
|
|
font-size: var(--words-font-size-sm);
|
||
|
|
color: var(--words-content-color);
|
||
|
|
font-variant-numeric: tabular-nums;
|
||
|
|
}
|
||
|
|
[data-words-inspector-empty] {
|
||
|
|
padding: var(--space-2) 0;
|
||
|
|
font-size: var(--words-font-size-sm);
|
||
|
|
color: var(--words-placeholder-color);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Sidebar — docked, always visible (builder-style). The rail reserves a
|
||
|
|
right gutter; the sidebar itself is absolutely positioned so the frame's
|
||
|
|
height follows the CONTENT, not the (usually taller) inspector. A flex
|
||
|
|
row would stretch the frame to the inspector's height and leave dead
|
||
|
|
space below the text — the inspector instead scrolls within the content
|
||
|
|
height. */
|
||
|
|
[data-words][data-inspector='sidebar'] {
|
||
|
|
padding-inline-end: 16rem;
|
||
|
|
}
|
||
|
|
[data-words-sidebar] {
|
||
|
|
position: absolute;
|
||
|
|
inset-block: 0;
|
||
|
|
inset-inline-end: 0;
|
||
|
|
inline-size: 16rem;
|
||
|
|
overflow-y: auto;
|
||
|
|
border-inline-start: var(--words-border-width) solid var(--words-border);
|
||
|
|
border-start-end-radius: var(--_words-radius);
|
||
|
|
border-end-end-radius: var(--_words-radius);
|
||
|
|
background: var(--words-bg);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Drawer — slide-in panel from the right edge + a fixed toggle. */
|
||
|
|
[data-words-drawer-toggle] {
|
||
|
|
position: absolute;
|
||
|
|
inset-block-start: var(--space-3);
|
||
|
|
inset-inline-end: var(--space-3);
|
||
|
|
z-index: 21;
|
||
|
|
}
|
||
|
|
[data-words-drawer-panel] {
|
||
|
|
position: absolute;
|
||
|
|
inset-block: 0;
|
||
|
|
inset-inline-end: 0;
|
||
|
|
z-index: 20;
|
||
|
|
inline-size: 16rem;
|
||
|
|
max-inline-size: 85%;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
overflow-y: auto;
|
||
|
|
background: var(--words-bg);
|
||
|
|
border-inline-start: var(--words-border-width) solid var(--words-border);
|
||
|
|
border-start-end-radius: var(--_words-radius);
|
||
|
|
border-end-end-radius: var(--_words-radius);
|
||
|
|
box-shadow: var(--shadow-overlay);
|
||
|
|
transform: translateX(100%);
|
||
|
|
transition: transform var(--words-transition-duration) var(--words-transition-ease);
|
||
|
|
}
|
||
|
|
[data-words-drawer-panel][data-open] {
|
||
|
|
transform: translateX(0);
|
||
|
|
}
|
||
|
|
[data-words-drawer-panel-head] {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
|
||
|
|
border-block-end: var(--words-border-width) solid var(--words-border);
|
||
|
|
font-size: var(--words-font-size-md);
|
||
|
|
font-weight: var(--words-strong-font-weight);
|
||
|
|
color: var(--words-content-color);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Popover — a corner toggle floats the inspector. */
|
||
|
|
[data-words-popover-anchor] {
|
||
|
|
position: absolute;
|
||
|
|
inset-block-start: var(--space-3);
|
||
|
|
inset-inline-end: var(--space-3);
|
||
|
|
z-index: 21;
|
||
|
|
}
|
||
|
|
[data-words-inspector-popover] {
|
||
|
|
inline-size: 16rem;
|
||
|
|
padding: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Content surface (the contenteditable) ───────────────────────────── */
|
||
|
|
|
||
|
|
[data-words-content] {
|
||
|
|
position: relative;
|
||
|
|
flex: 1 1 auto;
|
||
|
|
min-block-size: var(--_words-content-min);
|
||
|
|
max-block-size: var(--_words-content-max);
|
||
|
|
overflow-y: auto;
|
||
|
|
padding: var(--_words-content-py) var(--_words-content-px);
|
||
|
|
font-size: var(--_words-content-font-size);
|
||
|
|
line-height: 1.7;
|
||
|
|
color: var(--words-content-color);
|
||
|
|
outline: none;
|
||
|
|
-webkit-font-smoothing: antialiased;
|
||
|
|
text-rendering: optimizeLegibility;
|
||
|
|
}
|
||
|
|
|
||
|
|
[data-words-content] :where([data-words-node='block']):first-child {
|
||
|
|
margin-block-start: 0;
|
||
|
|
}
|
||
|
|
[data-words-content] :where([data-words-node='block']):last-child {
|
||
|
|
margin-block-end: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Placeholder ──────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
[data-words-placeholder] {
|
||
|
|
position: absolute;
|
||
|
|
inset-block-start: var(--_words-content-py);
|
||
|
|
inset-inline-start: var(--_words-content-px);
|
||
|
|
font-size: var(--_words-content-font-size);
|
||
|
|
line-height: 1.7;
|
||
|
|
color: var(--words-placeholder-color);
|
||
|
|
pointer-events: none;
|
||
|
|
user-select: none;
|
||
|
|
}
|
||
|
|
[data-words-placeholder][data-hidden] {
|
||
|
|
display: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Block rhythm ─────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
[data-words-content] :where(p, h1, h2, h3, blockquote, pre, ul, ol, table, figure, hr, [data-words-block='callout']) {
|
||
|
|
margin-block: var(--words-block-gap) 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Paragraph ────────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
[data-words-block='paragraph'] {
|
||
|
|
margin-block: var(--words-block-gap) 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Headings ─────────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
[data-words-block='heading'] {
|
||
|
|
margin-block: calc(var(--words-block-gap) * 1.5) 0;
|
||
|
|
color: var(--words-heading-color);
|
||
|
|
font-weight: var(--words-heading-font-weight);
|
||
|
|
line-height: var(--words-heading-line-height);
|
||
|
|
letter-spacing: -0.01em;
|
||
|
|
}
|
||
|
|
h1[data-words-block='heading'] {
|
||
|
|
font-size: var(--words-heading-h1-font-size);
|
||
|
|
}
|
||
|
|
h2[data-words-block='heading'] {
|
||
|
|
font-size: var(--words-heading-h2-font-size);
|
||
|
|
}
|
||
|
|
h3[data-words-block='heading'] {
|
||
|
|
font-size: var(--words-heading-h3-font-size);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Quote ────────────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
blockquote[data-words-block='quote'] {
|
||
|
|
padding-inline-start: var(--words-quote-px);
|
||
|
|
border-inline-start: var(--words-quote-border-width) solid var(--words-primary-border);
|
||
|
|
color: var(--words-quote-color);
|
||
|
|
font-style: italic;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Code block ───────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
pre[data-words-block='code'] {
|
||
|
|
padding: calc(var(--words-code-py) * 3) calc(var(--words-code-px) * 3);
|
||
|
|
border-radius: var(--words-radius-sm);
|
||
|
|
background: var(--words-code-bg);
|
||
|
|
color: var(--words-code-color);
|
||
|
|
font-family: var(--words-code-font-family);
|
||
|
|
font-size: 0.9em;
|
||
|
|
line-height: 1.6;
|
||
|
|
overflow-x: auto;
|
||
|
|
tab-size: 2;
|
||
|
|
}
|
||
|
|
pre[data-words-block='code'] code {
|
||
|
|
font-family: inherit;
|
||
|
|
white-space: pre;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* syntax tokens (highlightWordsCode) */
|
||
|
|
[data-words-code-token='keyword'] {
|
||
|
|
color: var(--words-primary-text);
|
||
|
|
font-weight: var(--words-strong-font-weight);
|
||
|
|
}
|
||
|
|
[data-words-code-token='string'] {
|
||
|
|
color: var(--words-affirm-text);
|
||
|
|
}
|
||
|
|
[data-words-code-token='number'] {
|
||
|
|
color: var(--words-fulfill-text);
|
||
|
|
}
|
||
|
|
[data-words-code-token='comment'] {
|
||
|
|
color: var(--words-content-color);
|
||
|
|
opacity: 0.6;
|
||
|
|
font-style: italic;
|
||
|
|
}
|
||
|
|
[data-words-code-token='function'] {
|
||
|
|
color: var(--words-secondary-text);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Lists ────────────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
[data-words-block='list'] {
|
||
|
|
padding-inline-start: var(--words-list-padding-inline-start);
|
||
|
|
}
|
||
|
|
[data-words-block='list'][data-words-list-kind='check'] {
|
||
|
|
padding-inline-start: 0;
|
||
|
|
list-style: none;
|
||
|
|
}
|
||
|
|
li[data-words-node='list-item'] {
|
||
|
|
margin-block: 0.25em;
|
||
|
|
}
|
||
|
|
li[data-words-node='list-item'][data-words-indent='1'] {
|
||
|
|
margin-inline-start: var(--words-list-padding-inline-start);
|
||
|
|
}
|
||
|
|
li[data-words-node='list-item'][data-words-indent='2'] {
|
||
|
|
margin-inline-start: calc(var(--words-list-padding-inline-start) * 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* check toggle */
|
||
|
|
[data-words-list-kind='check'] li[data-words-node='list-item'] {
|
||
|
|
display: flex;
|
||
|
|
align-items: flex-start;
|
||
|
|
gap: var(--space-2);
|
||
|
|
}
|
||
|
|
[data-words-check-toggle] {
|
||
|
|
flex: 0 0 auto;
|
||
|
|
inline-size: 1.1em;
|
||
|
|
block-size: 1.1em;
|
||
|
|
margin-block-start: 0.3em;
|
||
|
|
border: 1.5px solid var(--words-border-hover);
|
||
|
|
border-radius: var(--words-radius-sm);
|
||
|
|
background: var(--words-bg);
|
||
|
|
cursor: pointer;
|
||
|
|
transition:
|
||
|
|
background var(--words-transition-duration) var(--words-transition-ease),
|
||
|
|
border-color var(--words-transition-duration) var(--words-transition-ease);
|
||
|
|
}
|
||
|
|
[data-words-check-toggle][data-words-checked='true'] {
|
||
|
|
border-color: var(--words-primary-solid);
|
||
|
|
background: var(--words-primary-solid)
|
||
|
|
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-7'/%3E%3C/svg%3E")
|
||
|
|
center / 70% no-repeat;
|
||
|
|
}
|
||
|
|
[data-words-checked='true'] :where(span[data-words-node='text']) {
|
||
|
|
color: var(--words-content-color);
|
||
|
|
opacity: 0.55;
|
||
|
|
text-decoration: line-through;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Table ────────────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
table[data-words-block='table'] {
|
||
|
|
inline-size: 100%;
|
||
|
|
border-collapse: collapse;
|
||
|
|
font-size: 0.95em;
|
||
|
|
}
|
||
|
|
table[data-words-block='table'] :where(td, th) {
|
||
|
|
padding: var(--space-1-5) var(--space-2-5);
|
||
|
|
border: var(--words-border-width) solid var(--words-border);
|
||
|
|
text-align: start;
|
||
|
|
vertical-align: top;
|
||
|
|
}
|
||
|
|
table[data-words-block='table'] th {
|
||
|
|
background: var(--words-code-bg);
|
||
|
|
font-weight: var(--words-strong-font-weight);
|
||
|
|
}
|
||
|
|
[data-words-node='table-cell'][data-words-cell-align='center'] {
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
[data-words-node='table-cell'][data-words-cell-align='right'] {
|
||
|
|
text-align: end;
|
||
|
|
}
|
||
|
|
[data-words-node='table-cell'][data-words-cell-vertical='middle'] {
|
||
|
|
vertical-align: middle;
|
||
|
|
}
|
||
|
|
[data-words-node='table-cell'][data-words-cell-vertical='bottom'] {
|
||
|
|
vertical-align: bottom;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Image ────────────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
figure[data-words-block='image'] {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
gap: var(--space-2);
|
||
|
|
}
|
||
|
|
figure[data-words-block='image'] img {
|
||
|
|
max-inline-size: 100%;
|
||
|
|
block-size: auto;
|
||
|
|
border-radius: var(--words-radius-sm);
|
||
|
|
}
|
||
|
|
figure[data-words-block='image'][data-words-image-align='left'] {
|
||
|
|
align-items: flex-start;
|
||
|
|
}
|
||
|
|
figure[data-words-block='image'][data-words-image-align='right'] {
|
||
|
|
align-items: flex-end;
|
||
|
|
}
|
||
|
|
figure[data-words-block='image'] figcaption {
|
||
|
|
font-size: 0.85em;
|
||
|
|
color: var(--words-quote-color);
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
figure[data-words-block='image'][data-words-block-selected] {
|
||
|
|
outline: 2px solid var(--words-primary-solid);
|
||
|
|
outline-offset: 3px;
|
||
|
|
border-radius: var(--words-radius-sm);
|
||
|
|
}
|
||
|
|
figure[data-words-block='image'][data-words-image-status='uploading'] {
|
||
|
|
opacity: 0.6;
|
||
|
|
}
|
||
|
|
figure[data-words-block='image'][data-words-image-status='error'] {
|
||
|
|
outline: 2px solid var(--words-threat-solid);
|
||
|
|
outline-offset: 3px;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Divider ──────────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
hr[data-words-block='divider'] {
|
||
|
|
block-size: 0;
|
||
|
|
border: none;
|
||
|
|
border-block-start: var(--words-border-width) solid var(--words-border);
|
||
|
|
margin-block: calc(var(--words-block-gap) * 1.25) 0;
|
||
|
|
}
|
||
|
|
hr[data-words-block='divider'][data-words-block-selected] {
|
||
|
|
border-block-start-color: var(--words-primary-solid);
|
||
|
|
border-block-start-width: 2px;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Callout ──────────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
[data-words-block='callout'] {
|
||
|
|
padding: var(--space-3) var(--space-4);
|
||
|
|
border: var(--words-border-width) solid var(--words-neutral-border);
|
||
|
|
border-inline-start-width: 3px;
|
||
|
|
border-radius: var(--words-radius-sm);
|
||
|
|
background: var(--words-neutral-track);
|
||
|
|
}
|
||
|
|
[data-words-callout-title] {
|
||
|
|
margin-block-end: var(--space-1);
|
||
|
|
font-weight: var(--words-strong-font-weight);
|
||
|
|
}
|
||
|
|
[data-words-block='callout'] :where([data-words-node='block']):first-child {
|
||
|
|
margin-block-start: 0;
|
||
|
|
}
|
||
|
|
[data-words-callout-intent='affirm'] {
|
||
|
|
border-color: var(--words-affirm-border);
|
||
|
|
background: var(--words-affirm-track);
|
||
|
|
}
|
||
|
|
[data-words-callout-intent='affirm'] [data-words-callout-title] {
|
||
|
|
color: var(--words-affirm-text);
|
||
|
|
}
|
||
|
|
[data-words-callout-intent='fulfill'] {
|
||
|
|
border-color: var(--words-fulfill-border);
|
||
|
|
background: var(--words-fulfill-track);
|
||
|
|
}
|
||
|
|
[data-words-callout-intent='fulfill'] [data-words-callout-title] {
|
||
|
|
color: var(--words-fulfill-text);
|
||
|
|
}
|
||
|
|
[data-words-callout-intent='risk'] {
|
||
|
|
border-color: var(--words-risk-border);
|
||
|
|
background: var(--words-risk-track);
|
||
|
|
}
|
||
|
|
[data-words-callout-intent='risk'] [data-words-callout-title] {
|
||
|
|
color: var(--words-risk-text);
|
||
|
|
}
|
||
|
|
[data-words-callout-intent='threat'] {
|
||
|
|
border-color: var(--words-threat-border);
|
||
|
|
background: var(--words-threat-track);
|
||
|
|
}
|
||
|
|
[data-words-callout-intent='threat'] [data-words-callout-title] {
|
||
|
|
color: var(--words-threat-text);
|
||
|
|
}
|
||
|
|
[data-words-callout-intent='loss'] {
|
||
|
|
border-color: var(--words-loss-border);
|
||
|
|
background: var(--words-loss-track);
|
||
|
|
}
|
||
|
|
[data-words-callout-intent='loss'] [data-words-callout-title] {
|
||
|
|
color: var(--words-loss-text);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Inline marks ─────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
[data-words-marks~='bold'] {
|
||
|
|
font-weight: var(--words-strong-font-weight);
|
||
|
|
}
|
||
|
|
[data-words-marks~='italic'] {
|
||
|
|
font-style: italic;
|
||
|
|
}
|
||
|
|
[data-words-marks~='underline'] {
|
||
|
|
text-decoration-line: underline;
|
||
|
|
text-underline-offset: 0.18em;
|
||
|
|
}
|
||
|
|
[data-words-marks~='strike'] {
|
||
|
|
text-decoration-line: line-through;
|
||
|
|
}
|
||
|
|
[data-words-marks~='underline'][data-words-marks~='strike'] {
|
||
|
|
text-decoration-line: underline line-through;
|
||
|
|
}
|
||
|
|
[data-words-marks~='code'] {
|
||
|
|
padding: var(--words-code-py) var(--words-code-px);
|
||
|
|
border-radius: var(--words-code-radius);
|
||
|
|
background: var(--words-code-bg);
|
||
|
|
font-family: var(--words-code-font-family);
|
||
|
|
font-size: 0.9em;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Link ─────────────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
a[data-words-node='link'] {
|
||
|
|
color: var(--words-primary-text);
|
||
|
|
text-decoration-line: underline;
|
||
|
|
text-underline-offset: 0.15em;
|
||
|
|
text-decoration-thickness: 1px;
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
a[data-words-node='link']:hover {
|
||
|
|
text-decoration-thickness: 2px;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Find/replace matches ─────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
mark[data-words-find-match] {
|
||
|
|
border-radius: 2px;
|
||
|
|
background: var(--words-fulfill-track);
|
||
|
|
color: inherit;
|
||
|
|
}
|
||
|
|
mark[data-words-find-match][data-words-find-active] {
|
||
|
|
background: var(--words-fulfill-solid);
|
||
|
|
color: var(--words-fulfill-text);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ── Selection ────────────────────────────────────────────────────────── */
|
||
|
|
|
||
|
|
[data-words-content] ::selection {
|
||
|
|
background: color-mix(in srgb, var(--words-primary-solid) 22%, transparent);
|
||
|
|
}
|