[data-words] { --_words-gap: var(--words-gap-md); --_words-radius: var(--words-radius-md); --_words-content-px: var(--words-content-px-md); --_words-content-py: var(--words-content-py-md); --_words-content-min-block-size: var(--words-content-min-block-size-md); /* Gutter reserved for the block-handle grip + inserter "+" overlay. Rendered as a SEPARATE column outside the editor box (its own background + dot pattern), with a small gap before the editor. The grip + "+" are positioned by JS at viewport coordinates that land inside this column. */ --_words-rail-px: 2rem; --_words-rail-gap: 0.5rem; --_words-rail-bg: color-mix(in srgb, var(--words-toolbar-border) 35%, transparent); --_words-rail-dot: color-mix(in srgb, var(--words-status-color) 65%, transparent); --_words-toolbar-px: var(--words-toolbar-px-md); --_words-toolbar-py: var(--words-toolbar-py-md); --_words-button-size: var(--words-button-size-md); --_words-font-size: var(--words-font-size-md); /* `--_words-accent-*` is TSC-emitted from `lib/recipes/base.ts > words._accent-*`. */ --_words-selection-bg: color-mix(in srgb, var(--_words-accent-solid) 78%, transparent); --_words-selection-color: var(--words-selection-color); --_words-check-size: calc(var(--_words-button-size) * 0.46); --_words-check-mark-width: calc(var(--_words-check-size) * 0.32); --_words-check-mark-height: calc(var(--_words-check-size) * 0.56); --_words-check-mark-stroke: var(--words-border-width); --_words-check-mark-offset: calc(var(--_words-check-size) * -0.05); --toolbar-gap-md: var(--words-toolbar-gap); --toolbar-padding-inline-sm: var(--_words-toolbar-px); --toolbar-padding-inline-md: var(--_words-toolbar-px); --toolbar-padding-block-sm: var(--_words-toolbar-py); --toolbar-padding-block-md: var(--_words-toolbar-py); --toolbar-control-height-sm: var(--_words-button-size); --toolbar-control-height-md: var(--_words-button-size); --toolbar-control-px-sm: var(--words-command-px); --toolbar-control-px-md: var(--words-command-px); --toolbar-control-gap-sm: var(--words-command-gap); --toolbar-control-gap-md: var(--words-command-gap); --toolbar-font-size-sm: var(--_words-font-size); --toolbar-font-size-md: var(--_words-font-size); --toolbar-bg: var(--words-toolbar-bg); --toolbar-border: transparent; --toolbar-shadow: none; --toolbar-color: var(--words-command-color); --toolbar-font-family: var(--words-font-family); --toolbar-line-height: var(--words-line-height); --toolbar-group-gap: var(--words-command-gap); --toolbar-control-border-width: var(--words-border-width); --toolbar-control-border: transparent; --toolbar-control-radius: var(--words-command-radius); --toolbar-control-bg: transparent; --toolbar-control-color: var(--words-command-color); --toolbar-control-border-hover: var(--words-command-border-hover); --toolbar-control-bg-hover: var(--words-command-bg-hover); --toolbar-control-color-hover: var(--words-command-color-hover); --toolbar-control-border-active: var(--_words-accent-border); --toolbar-control-bg-active: var(--_words-accent-track); --toolbar-control-color-active: var(--_words-accent-text); --toolbar-focus-shadow: var(--words-focus-shadow); --toolbar-disabled-opacity: var(--words-disabled-opacity); --toolbar-transition-duration: var(--words-transition-duration); --toolbar-transition-ease: var(--words-transition-ease); position: relative; display: flex; flex-direction: column; inline-size: 100%; max-inline-size: var(--words-max-inline-size); overflow: hidden; border: var(--words-border-width) solid var(--words-border); border-radius: var(--_words-radius); background: var(--words-bg); box-shadow: var(--words-shadow); color: var(--words-color); font-family: var(--words-font-family); font-size: var(--_words-font-size); line-height: var(--words-line-height); transition: border-color var(--words-transition-duration) var(--words-transition-ease), box-shadow var(--words-transition-duration) var(--words-transition-ease), background var(--words-transition-duration) var(--words-transition-ease); } [data-words][data-size='sm'] { --_words-gap: var(--words-gap-sm); --_words-radius: var(--words-radius-sm); --_words-content-px: var(--words-content-px-sm); --_words-content-py: var(--words-content-py-sm); --_words-content-min-block-size: var(--words-content-min-block-size-sm); --_words-toolbar-px: var(--words-toolbar-px-sm); --_words-toolbar-py: var(--words-toolbar-py-sm); --_words-button-size: var(--words-button-size-sm); --_words-font-size: var(--words-font-size-sm); } [data-words][data-size='lg'] { --_words-gap: var(--words-gap-lg); --_words-radius: var(--words-radius-lg); --_words-content-px: var(--words-content-px-lg); --_words-content-py: var(--words-content-py-lg); --_words-content-min-block-size: var(--words-content-min-block-size-lg); --_words-toolbar-px: var(--words-toolbar-px-lg); --_words-toolbar-py: var(--words-toolbar-py-lg); --_words-button-size: var(--words-button-size-lg); --_words-font-size: var(--words-font-size-lg); } [data-words][data-variant='outline'] { background: transparent; box-shadow: none; } [data-words][data-variant='ghost'] { border-color: transparent; background: transparent; box-shadow: none; } [data-words]:hover:not([data-disabled]):not([data-readonly]) { border-color: var(--words-border-hover); } [data-words][data-focused] { border-color: var(--_words-accent-border); box-shadow: var(--words-focus-shadow); } [data-words][data-invalid] { border-color: var(--words-invalid-border); } [data-words][data-disabled] { cursor: not-allowed; opacity: var(--words-disabled-opacity); } /* ── Layout ────────────────────────────────────────────────────────────── The editor host is a grid: rail | gap | (toolbar/content/status) | drawer. The rail is a dedicated column OUTSIDE the editor card that visually holds the block-handle grip + inserter "+" overlays — with its own grey background and dotted pattern, separated from the editor by a small gap mirroring the drawer's gap on the other side. When `` the columns flip. Children without a grid-area placement (BubbleMenu / SlashMenu / HiddenInput / find-replace) are absolute-positioned and don't participate. */ [data-words]:has([data-words-drawer]) { display: grid; grid-template-columns: var(--_words-rail-px) var(--_words-rail-gap) minmax(0, 1fr) max-content; grid-template-rows: auto minmax(0, 1fr) auto; grid-template-areas: 'rail . toolbar drawer' 'rail . content drawer' 'rail . status drawer'; column-gap: 0; } /* Left-side drawer — drawer first, then rail at the END mirroring the right-side layout (rail is on the SAME side as the grip, opposite to the drawer). */ [data-words]:has([data-words-drawer][data-side='left']) { grid-template-columns: max-content minmax(0, 1fr) var(--_words-rail-gap) var(--_words-rail-px); grid-template-areas: 'drawer toolbar . rail' 'drawer content . rail' 'drawer status . rail'; } /* Rail visual — pseudo-element on the editor host that fills the `rail` grid area with the dotted grey band. The grip + "+" overlays are JS-positioned via viewport coordinates that land here. */ [data-words]:has([data-words-drawer])::before { content: ''; grid-area: rail; background-color: var(--_words-rail-bg); background-image: radial-gradient( circle 1px, var(--_words-rail-dot) 99%, transparent 100% ); background-size: 5px 5px; background-position: 50% 50%; background-repeat: repeat; border-radius: var(--_words-radius); pointer-events: none; } [data-words]:has([data-words-drawer]) > [data-words-toolbar] { grid-area: toolbar; } [data-words]:has([data-words-drawer]) > [data-words-content], [data-words]:has([data-words-drawer]) > [data-words-placeholder] { grid-area: content; } [data-words]:has([data-words-drawer]) > [data-words-status] { grid-area: status; } [data-words]:has([data-words-drawer]) > [data-words-drawer] { grid-area: drawer; } [data-words-drawer] { display: flex; flex-direction: column; inline-size: 14rem; max-inline-size: 18rem; block-size: 100%; min-block-size: 100%; padding: 0; border-inline-start: var(--words-border-width) solid var(--words-toolbar-border); background: var(--words-toolbar-bg); color: var(--words-command-color); font-size: var(--words-status-font-size); overflow: hidden; transition: inline-size 160ms ease; } /* Left-side drawer: the visual seam goes on the inline-end edge (toward the editor content) instead of inline-start. */ [data-words-drawer][data-side='left'] { border-inline-start: 0; border-inline-end: var(--words-border-width) solid var(--words-toolbar-border); } [data-words-drawer]:not([data-open]) { inline-size: 2.25rem; max-inline-size: 2.25rem; } [data-words-drawer-header] { display: flex; align-items: center; gap: var(--words-command-gap); padding-block: var(--words-toolbar-py-sm); padding-inline: var(--words-toolbar-px-sm); border-block-end: var(--words-border-width) solid var(--words-toolbar-border); background: color-mix(in srgb, var(--_words-accent-solid) 5%, transparent); } [data-words-drawer-collapse] { display: inline-flex; align-items: center; justify-content: center; inline-size: 1.5rem; block-size: 1.5rem; padding: 0; border: 0; border-radius: var(--words-command-radius); background: transparent; color: var(--words-command-color); cursor: pointer; } [data-words-drawer-collapse]:hover { background: color-mix(in srgb, var(--_words-accent-solid) 12%, transparent); } /* Document-overview toggle in the drawer header. Sits on the far right (margin-inline-start: auto). Active when the document panel is in the stack. */ [data-words-drawer-document-toggle] { margin-inline-start: auto; display: inline-flex; align-items: center; justify-content: center; inline-size: 1.5rem; block-size: 1.5rem; padding: 0; border: 0; border-radius: var(--words-command-radius); background: transparent; color: var(--words-status-color); cursor: pointer; opacity: 0.7; transition: background-color 120ms ease, color 120ms ease, opacity 120ms ease; } [data-words-drawer-document-toggle]:hover { opacity: 1; background: color-mix(in srgb, var(--_words-accent-solid) 12%, transparent); color: var(--words-command-color); } [data-words-drawer-document-toggle][data-active] { opacity: 1; background: var(--_words-accent-solid); color: var(--_words-accent-on); } /* Insert panel — catalog of block constructors. Two columns on the default drawer width so the labels fit comfortably; falls back to single column on narrow drawers. */ [data-words-drawer-insert] { display: grid; grid-template-columns: 1fr 1fr; gap: 0.35rem; } [data-words-drawer-insert-item] { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.45rem 0.55rem; border: var(--words-border-width) solid var(--words-toolbar-border); border-radius: var(--words-command-radius); background: var(--words-toolbar-bg); color: var(--words-command-color); font: inherit; font-size: var(--words-font-size-sm); cursor: pointer; text-align: start; transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease; } [data-words-drawer-insert-item]:hover { border-color: var(--_words-accent-border); background: color-mix(in srgb, var(--_words-accent-solid) 8%, transparent); color: var(--_words-accent-text); } [data-words-drawer-insert-item-label] { flex: 1 1 auto; min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } [data-words-drawer-title] { font-weight: var(--words-strong-font-weight); letter-spacing: 0.02em; text-transform: uppercase; font-size: var(--words-status-font-size); color: var(--words-status-color); } [data-words-drawer-body] { display: flex; flex-direction: column; gap: 0; padding: 0; overflow-y: auto; flex: 1; } [data-words-drawer-section] { padding-block: var(--words-toolbar-py-sm); padding-inline: var(--words-toolbar-px-sm); border-block-end: var(--words-border-width) solid color-mix(in srgb, var(--words-toolbar-border) 60%, transparent); } [data-words-drawer-section]:last-child { border-block-end: 0; } [data-words-drawer-section][data-flush]:not(:last-child) { margin-block-end: var(--words-toolbar-py-sm); } [data-words-drawer-section][data-flush]:first-child { padding-block-start: 0; } /* Hierarchical panels (HIER) — each scope in the modes[] stack is a collapsible
with its own header + body. Default heuristic: the topmost (most-specific) panel is open, the rest collapsed but accessible by tapping the header chevron. */ [data-words-drawer-panel] { display: flex; flex-direction: column; border-block-end: var(--words-border-width) solid color-mix(in srgb, var(--words-toolbar-border) 60%, transparent); } [data-words-drawer-panel]:last-child { border-block-end: 0; } [data-words-drawer-panel-header] { display: flex; align-items: center; justify-content: space-between; gap: var(--words-command-gap); padding-block: 0.35rem; padding-inline: var(--words-toolbar-px-sm); border: 0; background: transparent; color: var(--words-status-color); font-size: var(--words-status-font-size); font-weight: var(--words-strong-font-weight); letter-spacing: 0.04em; text-transform: uppercase; text-align: start; cursor: pointer; } [data-words-drawer-panel-header]:hover { background: color-mix(in srgb, var(--_words-accent-solid) 5%, transparent); color: var(--_words-accent-text); } [data-words-drawer-panel][data-open] [data-words-drawer-panel-header] { background: color-mix(in srgb, var(--_words-accent-solid) 4%, transparent); color: var(--words-command-color); } /* Per-scope accent — each category of scope gets a distinct hue so the user can read the panel's *kind* at a glance: - Text scopes (format, block) → primary (project accent) - Structure scopes (cell, row, table, list, list-item) → secondary - Media scopes (image, code) → fulfill (tealish) - Default (document) → neutral Variables here resolve from the eidos color tokens, so themes re-tint everything coherently. */ [data-words-drawer-panel][data-mode='default'] { --_drawer-scope-accent: var(--words-toolbar-border); --_drawer-scope-tint: var(--words-toolbar-bg); } [data-words-drawer-panel][data-mode='format'], [data-words-drawer-panel][data-mode='block'] { --_drawer-scope-accent: var(--_words-accent-border); --_drawer-scope-tint: color-mix(in srgb, var(--_words-accent-solid) 6%, transparent); } [data-words-drawer-panel][data-mode='cell'], [data-words-drawer-panel][data-mode='row'], [data-words-drawer-panel][data-mode='table'], [data-words-drawer-panel][data-mode='list'], [data-words-drawer-panel][data-mode='list-item'] { --_drawer-scope-accent: var(--words-secondary-text); --_drawer-scope-tint: color-mix(in srgb, var(--words-secondary-text) 6%, transparent); } [data-words-drawer-panel][data-mode='image'], [data-words-drawer-panel][data-mode='code'] { --_drawer-scope-accent: var(--words-fulfill-text); --_drawer-scope-tint: color-mix(in srgb, var(--words-fulfill-text) 6%, transparent); } /* Depth indicator — leaf panel is full-strength scope accent; deeper panels render the same hue at decreasing alpha so the precedence is readable visually. */ [data-words-drawer-panel][data-depth='0'] { border-inline-start: 3px solid var(--_drawer-scope-accent); } [data-words-drawer-panel][data-depth='1'] { border-inline-start: 3px solid color-mix(in srgb, var(--_drawer-scope-accent) 65%, transparent); } [data-words-drawer-panel][data-depth='2'] { border-inline-start: 3px solid color-mix(in srgb, var(--_drawer-scope-accent) 40%, transparent); } [data-words-drawer-panel][data-depth='3'] { border-inline-start: 3px solid color-mix(in srgb, var(--_drawer-scope-accent) 25%, transparent); } /* When the panel is open, paint its header with the scope tint so the active scope reads at a glance. */ [data-words-drawer-panel][data-open] [data-words-drawer-panel-header] { background: var(--_drawer-scope-tint); color: var(--_drawer-scope-accent); } /* Action chip active state — inherit the scope accent so the selected variant matches the panel's color identity. */ [data-words-drawer-panel] [data-words-drawer-action][data-active] { background: color-mix(in srgb, var(--_drawer-scope-accent, var(--_words-accent-solid)) 20%, var(--words-bg)); border-color: var(--_drawer-scope-accent, var(--_words-accent-border)); color: var(--_drawer-scope-accent, var(--_words-accent-text)); } [data-words-drawer-panel-title] { flex: 1; } [data-words-drawer-panel-body] { display: flex; flex-direction: column; gap: 0.4rem; padding-block-end: var(--words-toolbar-py-sm); padding-inline: var(--words-toolbar-px-sm); } [data-words-drawer-section-subtitle] { color: var(--words-status-color); font-size: var(--words-status-font-size); font-weight: var(--words-strong-font-weight); letter-spacing: 0.04em; text-transform: uppercase; } /* Drawer-scoped Editable — Notion/Linear-style inline edit. Resting state shows the preview with a faded pencil to its right (revealed on hover or focus-within). Edit mode swaps to a textarea (alt/caption can run long) with icon-only Submit (✓) and Cancel (✕) beneath, right-aligned. Per the user's reference design. */ [data-editable][data-words-drawer-editable] { display: flex; inline-size: 100%; max-inline-size: 100%; align-items: center; gap: 0.25rem; } [data-editable][data-words-drawer-editable] [data-editable-area] { flex: 1 1 auto; min-inline-size: 0; } [data-editable][data-words-drawer-editable] [data-editable-preview] { inline-size: 100%; min-block-size: auto; white-space: normal; line-height: 1.35; color: var(--words-command-color); } [data-editable][data-words-drawer-editable] [data-editable-preview][data-placeholder-shown] { color: var(--words-status-color); font-style: italic; } /* Pencil hides until the user signals intent (hover anywhere on the editable row, focus-within, or focus on the preview itself). */ [data-editable][data-words-drawer-editable] [data-editable-edit-trigger] { flex: 0 0 auto; inline-size: 1.5rem; block-size: 1.5rem; min-inline-size: 1.5rem; padding: 0; border: 0; background: transparent; color: var(--words-status-color); opacity: 0; transition: opacity 120ms ease, background-color 120ms ease, color 120ms ease; } [data-editable][data-words-drawer-editable]:hover [data-editable-edit-trigger], [data-editable][data-words-drawer-editable]:focus-within [data-editable-edit-trigger] { opacity: 0.7; } [data-editable][data-words-drawer-editable] [data-editable-edit-trigger]:hover { opacity: 1; background: var(--words-command-bg-hover); color: var(--words-command-color-hover); } /* Edit mode: stack vertically. Textarea fills the row, action chips sit beneath right-aligned. */ [data-editable][data-words-drawer-editable][data-editing] { flex-direction: column; align-items: stretch; } [data-editable][data-words-drawer-editable][data-editing] [data-editable-area] { inline-size: 100%; } [data-editable][data-words-drawer-editable] textarea[data-editable-input] { inline-size: 100%; min-block-size: 4.5rem; resize: vertical; padding: 0.4rem 0.5rem; border: var(--words-border-width) solid var(--words-toolbar-border); border-radius: var(--words-command-radius); background: var(--words-bg, var(--words-toolbar-bg)); color: var(--words-command-color); font: inherit; line-height: 1.35; outline: none; } [data-editable][data-words-drawer-editable] textarea[data-editable-input]:focus-visible { border-color: var(--_words-accent-border); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_words-accent-solid) 22%, transparent); } [data-editable][data-words-drawer-editable][data-editing] [data-editable-control] { display: inline-flex; justify-content: flex-end; gap: 0.25rem; margin-block-start: 0.35rem; } /* Icon-only submit / cancel chips. Square, compact. */ [data-editable][data-words-drawer-editable] [data-editable-submit-trigger], [data-editable][data-words-drawer-editable] [data-editable-cancel-trigger] { flex: 0 0 auto; inline-size: 1.75rem; block-size: 1.75rem; min-inline-size: 1.75rem; padding: 0; border-radius: var(--words-command-radius); } [data-editable][data-words-drawer-editable] [data-editable-submit-trigger] { border: 0; background: var(--_words-accent-solid); color: var(--_words-accent-on); } [data-editable][data-words-drawer-editable] [data-editable-submit-trigger]:hover { background: color-mix(in srgb, var(--_words-accent-solid) 85%, white 0%); filter: brightness(0.95); } [data-editable][data-words-drawer-editable] [data-editable-cancel-trigger] { border: var(--words-border-width) solid var(--words-toolbar-border); background: transparent; color: var(--words-status-color); } [data-editable][data-words-drawer-editable] [data-editable-cancel-trigger]:hover { border-color: var(--words-threat-text); color: var(--words-threat-text); } /* Drawer header trail — shows the breadcrumb of stacked modes after the leaf so the user knows what scopes are stacked underneath. */ [data-words-drawer-trail] { display: inline-flex; gap: 0.2rem; margin-inline-start: 0.4rem; color: var(--words-status-color); font-size: var(--words-status-font-size); font-weight: normal; letter-spacing: 0; text-transform: none; } [data-words-drawer-trail-sep] { opacity: 0.5; } [data-words-drawer-actions][data-flush] { margin-block-start: 0.4rem; } /* Color picker — palette of swatches + a native for free-pick + a clear button when a value is set. */ [data-words-drawer-color-picker] { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem; } [data-words-drawer-color-swatch] { inline-size: 1.25rem; block-size: 1.25rem; padding: 0; border: 1px solid color-mix(in srgb, var(--words-toolbar-border) 60%, transparent); border-radius: 999px; cursor: pointer; transition: transform 80ms ease, box-shadow 80ms ease; } [data-words-drawer-color-swatch]:hover { transform: scale(1.15); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_words-accent-solid) 30%, transparent); } [data-words-drawer-color-swatch][data-active] { box-shadow: 0 0 0 2px var(--words-bg), 0 0 0 4px var(--_words-accent-solid); } [data-words-drawer-color-input] { inline-size: 1.6rem; block-size: 1.4rem; padding: 0; border: 1px dashed color-mix(in srgb, var(--words-toolbar-border) 80%, transparent); border-radius: var(--words-command-radius); background: transparent; cursor: pointer; } [data-words-drawer-color-input]:hover { border-style: solid; border-color: var(--_words-accent-border); } [data-words-drawer-color-clear] { display: inline-flex; align-items: center; justify-content: center; inline-size: 1.25rem; block-size: 1.25rem; padding: 0; border: 1px solid color-mix(in srgb, var(--words-toolbar-border) 60%, transparent); border-radius: 999px; background: transparent; color: var(--words-status-color); font-size: var(--words-font-size-md); line-height: 1; cursor: pointer; } [data-words-drawer-color-clear]:hover { border-color: var(--words-threat-text); color: var(--words-threat-text); } /* Image float bar — floats above the selected image with quick actions (align L/C/R, delete, dismiss). Positioned via inline `top` / `left` set by the component from getBoundingClientRect. */ [data-words-image-float-bar] { position: fixed; transform: translateX(-50%); display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.3rem; border-radius: var(--words-command-radius); background: var(--words-toolbar-bg); border: var(--words-border-width) solid var(--_words-accent-border); box-shadow: var(--words-shadow); z-index: var(--z-index-popover); white-space: nowrap; } [data-words-image-float-action] { display: inline-flex; align-items: center; justify-content: center; inline-size: 1.75rem; block-size: 1.75rem; padding: 0; border: 0; border-radius: var(--words-command-radius); background: transparent; color: var(--words-command-color); cursor: pointer; } [data-words-image-float-action]:hover { background: color-mix(in srgb, var(--_words-accent-solid) 12%, transparent); color: var(--_words-accent-text); } [data-words-image-float-action][data-active] { background: var(--_words-accent-solid); color: var(--_words-accent-on); } [data-words-image-float-action][data-tone='risk']:hover { background: color-mix(in srgb, var(--words-threat-text) 15%, transparent); color: var(--words-threat-text); } [data-words-image-float-action][data-tone='ghost'] { color: var(--words-status-color); } [data-words-image-float-divider] { inline-size: 1px; block-size: 1.25rem; background: var(--words-toolbar-border); margin-inline: 0.15rem; } /* Block handle — Notion-style drag grip rendered to the left of the hovered block. Hidden by default (`opacity: 0`) and fades in on hover via opacity transition. Click reveals an action menu (Move up / Move down / Duplicate / Delete). The button itself is positioned via inline `top` / `left` set from getBoundingClientRect. */ [data-words-block-handle] { position: fixed; display: inline-flex; align-items: center; justify-content: center; /* Hit area: 28×28 — comfortably above the WCAG 2.5.5 target-size minimum (24×24) and easier to land than the previous 24×24 in the narrow gutter. The visible icon stays small via `size="sm"`. */ inline-size: 1.75rem; block-size: 1.75rem; padding: 0; border: 0; border-radius: var(--words-command-radius); background: transparent; /* Distinct color against the dotted rail. Accent on hover. */ color: var(--words-command-color); cursor: grab; opacity: 0.75; transition: opacity 120ms ease, background-color 120ms ease, color 120ms ease; z-index: var(--z-index-popover); } [data-words-block-handle]:hover, [data-words-block-handle][data-open] { opacity: 1; background: var(--words-toolbar-bg); color: var(--_words-accent-text); box-shadow: 0 0 0 var(--words-border-width) var(--_words-accent-border); } [data-words-block-handle]:active { cursor: grabbing; } /* Drag in flight: the bar STAYS fixed in the gutter (visual anchor); * only the browser's default drag-ghost of the grip travels with the * cursor. Fade the static anchor so it doesn't compete with the * floating ghost — the user reads "this is where it left from" while * the cursor carries the moving icon. */ [data-words-block-handle][data-dragging] { opacity: 0.35; background: var(--words-toolbar-bg); cursor: grabbing; } [data-words-block-handle-menu] { position: fixed; display: flex; flex-direction: column; min-inline-size: 9rem; padding: 0.25rem; border-radius: var(--words-command-radius); background: var(--words-toolbar-bg); border: var(--words-border-width) solid var(--_words-accent-border); box-shadow: var(--words-shadow); z-index: var(--z-index-popover); } [data-words-block-handle-menu] button { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.5rem; border: 0; border-radius: var(--words-command-radius); background: transparent; color: var(--words-command-color); text-align: start; font: inherit; cursor: pointer; } [data-words-block-handle-menu] button:hover:not(:disabled) { background: color-mix(in srgb, var(--_words-accent-solid) 12%, transparent); color: var(--_words-accent-text); } [data-words-block-handle-menu] button:disabled { opacity: 0.4; cursor: not-allowed; } [data-words-block-handle-menu] button[data-tone='risk']:hover:not(:disabled) { background: color-mix(in srgb, var(--words-threat-text) 15%, transparent); color: var(--words-threat-text); } [data-words-block-handle-menu-divider] { block-size: 1px; margin-block: 0.25rem; background: var(--words-toolbar-border); } /* Block inserter — hover-zone between blocks. Solves the wedge case where two atomic blocks (image, table, code) are back-to-back and no caret position exists between them. The wrapper is a thin horizontal strip anchored at the seam between two blocks; it carries a faint line and a left-margin "+" button. Click → insert a paragraph at that position. */ [data-words-block-inserter] { position: fixed; pointer-events: none; transform: translateY(-50%); display: flex; align-items: center; z-index: var(--z-index-popover); } [data-words-block-inserter-button] { pointer-events: auto; position: absolute; /* Land the "+" centered in the dedicated rail column to the left of the editor box. Same metrics as the block-handle's positioning: block.rect.left − content-px − rail-gap − rail-px/2 − 12 (button half). The inserter wrapper sits at block.rect.left, so we offset by −(content-px + rail-gap + rail-px/2 + 12). */ left: calc( -1 * (var(--_words-content-px) + var(--_words-rail-gap) + var(--_words-rail-px) / 2) - 12px ); display: inline-flex; align-items: center; justify-content: center; inline-size: 1.5rem; block-size: 1.5rem; padding: 0; border: var(--words-border-width) solid var(--words-toolbar-border); border-radius: 999px; background: var(--words-toolbar-bg); color: var(--words-status-color); cursor: pointer; box-shadow: var(--words-shadow); transition: background 120ms ease, color 120ms ease, border-color 120ms ease; } [data-words-block-inserter-button]:hover { background: var(--_words-accent-solid); border-color: var(--_words-accent-solid); color: var(--_words-accent-on); } /* When the drawer is on the LEFT side, flip the "+" button so it lands in the rail column on the editor's RIGHT side. Same metric math as the right-drawer case, just on the inline-end side. */ [data-words-block-inserter][data-side='left'] [data-words-block-inserter-button] { left: auto; right: calc( -1 * (var(--_words-content-px) + var(--_words-rail-gap) + var(--_words-rail-px) / 2) - 12px ); } [data-words-block-inserter-line] { pointer-events: auto; flex: 1 1 auto; block-size: 2px; border-radius: 1px; background: color-mix(in srgb, var(--_words-accent-solid) 35%, transparent); opacity: 0; transition: opacity 120ms ease; } [data-words-block-inserter]:hover [data-words-block-inserter-line] { opacity: 1; } /* Drop-target mode: while a block is being dragged the inserter doubles as the drop indicator. The line stays prominent (no hover needed) and grows a touch so the user can see exactly where the block will land. */ [data-words-block-inserter][data-mode='drop'] [data-words-block-inserter-line] { opacity: 1; block-size: 3px; background: var(--_words-accent-solid); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_words-accent-solid) 25%, transparent); } /* Grabbed state on the block-handle grip — visible when the user has pressed Space on the focused grip to enter keyboard-grab mode. */ [data-words-block-handle][data-grabbed] { opacity: 1; background: var(--_words-accent-solid); color: var(--_words-accent-on); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_words-accent-solid) 25%, transparent); } [data-words-drawer-section-title] { display: flex; align-items: baseline; gap: var(--words-command-gap); margin: 0 0 var(--words-toolbar-py-sm) 0; font-size: var(--words-status-font-size); font-weight: var(--words-strong-font-weight); letter-spacing: 0.04em; text-transform: uppercase; color: var(--words-status-color); } [data-words-drawer-section-count] { display: inline-flex; align-items: center; justify-content: center; min-inline-size: 1.25rem; padding-block: 0; padding-inline: 0.3rem; border-radius: 999px; background: var(--_words-accent-solid); color: var(--_words-accent-on); font-size: var(--words-status-font-size); } [data-words-drawer-empty] { margin: 0; color: var(--words-status-color); font-style: italic; font-size: var(--words-font-size-sm); } [data-words-drawer-empty][data-tone='affirm'] { color: var(--words-affirm-text); font-style: normal; } [data-words-drawer-outline] { display: flex; flex-direction: column; gap: 0.25rem; margin: 0; padding: 0; list-style: none; } [data-words-drawer-outline-item] { display: flex; align-items: baseline; gap: 0.4rem; padding-inline-start: 0; font-size: var(--words-font-size-sm); line-height: 1.3; } [data-words-drawer-outline-item][data-level='2'] { padding-inline-start: 0.75rem; } [data-words-drawer-outline-item][data-level='3'] { padding-inline-start: 1.5rem; } [data-words-drawer-outline-bullet] { flex-shrink: 0; min-inline-size: 1.5rem; color: var(--_words-accent-text); font-size: var(--words-status-font-size); font-weight: var(--words-strong-font-weight); letter-spacing: 0.04em; } [data-words-drawer-outline-text] { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } [data-words-drawer-stats] { display: grid; grid-template-columns: 1fr 1fr; gap: 0.25rem 0.5rem; margin: 0; } [data-words-drawer-stats] > div { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; font-size: var(--words-font-size-sm); } [data-words-drawer-stats] dt { margin: 0; color: var(--words-status-color); font-size: var(--words-status-font-size); text-transform: uppercase; letter-spacing: 0.04em; } [data-words-drawer-stats] dd { margin: 0; font-weight: var(--words-strong-font-weight); } [data-words-drawer-warnings] { display: flex; flex-direction: column; gap: 0.4rem; margin: 0; padding: 0; list-style: none; } [data-words-drawer-warnings] li { padding-block: 0.35rem; padding-inline: 0.5rem; border-radius: var(--words-command-radius); background: color-mix(in srgb, var(--words-toolbar-border) 30%, transparent); font-size: var(--words-font-size-sm); line-height: 1.35; } [data-words-drawer-warnings] li[data-severity='warn'] { background: color-mix(in srgb, var(--words-risk-text) 12%, transparent); color: var(--words-risk-text); } /* Contextual panel actions (DRAWER-2) ---------------------------------- */ [data-words-drawer-actions] { display: flex; flex-wrap: wrap; gap: 0.3rem; } [data-words-drawer-action] { display: inline-flex; align-items: center; justify-content: center; min-inline-size: 2rem; padding-block: 0.3rem; padding-inline: 0.55rem; border: var(--words-border-width) solid color-mix(in srgb, var(--words-toolbar-border) 80%, transparent); border-radius: var(--words-command-radius); background: var(--words-bg); color: var(--words-command-color); font-size: var(--words-font-size-sm); font-weight: var(--words-strong-font-weight); cursor: pointer; transition: background-color 100ms ease, border-color 100ms ease; } [data-words-drawer-action]:hover { background: color-mix(in srgb, var(--_words-accent-solid) 8%, var(--words-bg)); border-color: var(--_words-accent-border); } [data-words-drawer-action][data-active] { background: color-mix(in srgb, var(--_words-accent-solid) 18%, var(--words-bg)); border-color: var(--_words-accent-border); color: var(--_words-accent-text); } [data-words-drawer-action][data-tone='full'] { background: var(--_words-accent-solid); border-color: var(--_words-accent-solid); color: var(--_words-accent-on); } [data-words-drawer-action][data-tone='ghost'] { background: transparent; border-style: dashed; } [data-words-drawer-action][data-tone='risk']:hover { background: color-mix(in srgb, var(--words-risk-text) 15%, var(--words-bg)); border-color: var(--words-risk-text); color: var(--words-risk-text); } [data-words-drawer-readonly-text] { margin: 0; padding-block: 0.3rem; padding-inline: 0.5rem; border-radius: var(--words-command-radius); background: color-mix(in srgb, var(--words-toolbar-border) 30%, transparent); color: var(--words-command-color); font-size: var(--words-font-size-sm); line-height: 1.35; word-break: break-all; } [data-words-drawer-readonly-text][data-empty='true'] { color: var(--words-status-color); font-style: italic; } [data-words-drawer-readonly-text][data-tone='pending'] { background: color-mix(in srgb, var(--_words-accent-solid) 10%, transparent); color: var(--_words-accent-text); } [data-words-drawer-readonly-text][data-tone='error'] { background: color-mix(in srgb, var(--words-threat-text) 12%, transparent); color: var(--words-threat-text); } [data-words-toolbar] { /* Horizontal layout: single row with horizontal scroll on narrow viewports. Was previously `flex-wrap: wrap` which produced 2-3 line wraps on mobile with orphan icons. The horizontal-scroll pattern is what Google Docs / Word / Notion use on mobile and keeps every command reachable without changing the markup. */ display: flex; flex-wrap: nowrap; align-items: center; gap: var(--words-toolbar-gap); inline-size: 100%; padding-block: var(--_words-toolbar-py); padding-inline: var(--_words-toolbar-px); border: 0; border-block-end: var(--words-border-width) solid var(--words-toolbar-border); border-radius: 0; background: var(--words-toolbar-bg); box-shadow: none; overflow-x: auto; overflow-y: clip; scrollbar-width: thin; /* Mask a soft fade on the trailing edge when content overflows so the user has a visual cue there's more. The fade lives in a mask-image rather than a real element to keep markup unchanged. */ mask-image: linear-gradient( to inline-end, black calc(100% - 1.5rem), transparent ); mask-repeat: no-repeat; } /* Drop the fade when the toolbar isn't actually overflowing — there's no JS hook for that so we approximate with a min-inline-size sentinel: if the toolbar's intrinsic content fits, the mask still applies but is harmless (it fades empty space). Keeping for simplicity. */ [data-words-toolbar-group] { display: inline-flex; flex-wrap: nowrap; align-items: center; gap: var(--words-command-gap); min-inline-size: 0; flex-shrink: 0; } [data-words-bubble-menu] { --_words-bubble-offset: var(--words-toolbar-py-md); --_words-bubble-y-shift: calc(-100% - var(--_words-bubble-offset)); --_words-bubble-bg: var(--words-toolbar-bg); position: fixed; z-index: var(--z-index-popover); inset-block-start: var(--_words-bubble-y); inset-inline-start: var(--_words-bubble-x); display: inline-flex; align-items: center; gap: var(--words-command-gap); max-inline-size: 92vw; padding-block: var(--words-toolbar-py-sm); padding-inline: var(--words-toolbar-px-sm); border: var(--words-border-width) solid var(--_words-accent-border); border-radius: var(--words-command-radius); background: var(--_words-bubble-bg); box-shadow: var(--words-shadow); color: var(--words-command-color); transform: translate(-50%, var(--_words-bubble-y-shift)); } [data-words-bubble-menu][data-side='bottom'] { --_words-bubble-y-shift: var(--_words-bubble-offset); } [data-words-bubble-menu][hidden], [data-words-bubble-menu]:not([data-open]), [data-words-bubble-menu]:not([data-positioned]) { display: none; } [data-words-bubble-menu] [data-words-link-editor] { grid-template-columns: minmax(0, 1fr) auto; } [data-words-slash-menu] { position: fixed; z-index: var(--z-index-popover); inset-block-start: var(--_words-slash-y); inset-inline-start: var(--_words-slash-x); display: grid; gap: var(--button-gap-xs); /* Widened from 7× to 10× button-size so option descriptions ("Large section heading", "Blockquote callout") fit instead of clipping with ellipsis. Still capped at 92vw for mobile. */ inline-size: min(calc(var(--_words-button-size) * 10), 92vw); max-block-size: min(calc(var(--_words-button-size) * 10), 70vh); overflow: auto; padding: var(--words-toolbar-py-sm); border: var(--words-border-width) solid var(--_words-accent-border); border-radius: var(--words-command-radius); background: var(--words-toolbar-bg); box-shadow: var(--words-shadow); color: var(--words-command-color); transform: translateY(var(--words-toolbar-py-sm)); } [data-words-slash-menu][hidden], [data-words-slash-menu]:not([data-open]) { display: none; } [data-words-slash-option] { display: grid; grid-template-columns: var(--_words-button-size) minmax(0, 1fr); align-items: center; gap: var(--words-command-gap); inline-size: 100%; min-inline-size: 0; padding-block: var(--button-gap-xs); padding-inline: var(--words-command-px); border: var(--words-border-width) solid transparent; border-radius: var(--words-command-radius); background: transparent; color: var(--words-command-color); font: inherit; text-align: start; cursor: pointer; } [data-words-slash-option]:hover:not(:disabled):not([data-disabled]), [data-words-slash-option][data-active] { border-color: var(--_words-accent-border); background: var(--_words-accent-track); color: var(--_words-accent-text); } [data-words-slash-option]:focus-visible { box-shadow: var(--words-focus-shadow); outline: none; } [data-words-slash-option]:disabled, [data-words-slash-option][data-disabled] { cursor: not-allowed; opacity: var(--words-disabled-opacity); } [data-words-slash-icon] { display: inline-flex; align-items: center; justify-content: center; inline-size: var(--_words-button-size); block-size: var(--_words-button-size); color: inherit; } [data-words-slash-copy] { display: grid; gap: var(--words-code-py); min-inline-size: 0; } [data-words-slash-label] { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: inherit; font-weight: var(--words-strong-font-weight); } /* Description wraps to up to 2 lines instead of single-line ellipsis so the user sees the full "Plain text block" / "Large section heading" description rather than a truncated tail. line-clamp keeps the menu compact regardless of unusually long custom descriptions. */ [data-words-slash-description] { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; min-inline-size: 0; overflow: hidden; color: var(--words-status-color); font-size: var(--words-status-font-size); line-height: 1.3; } [data-words-slash-option][data-active] [data-words-slash-description] { color: inherit; } [data-words-command-button] { min-inline-size: var(--_words-button-size); block-size: var(--_words-button-size); } [data-words-command-button][data-command] { display: inline-flex; flex-direction: row; inline-size: auto; border-color: var(--_button-border); border-radius: var(--_button-radius); background: var(--_button-bg); box-shadow: var(--button-shadow); overflow: visible; } [data-words-command-button][data-active], [data-words-command-button][data-state='on'] { border-color: var(--_words-accent-border); background: var(--_words-accent-track); color: var(--_words-accent-text); } [data-words-command-button][data-command='commit'] { border-color: var(--_words-accent-solid); background: var(--_words-accent-solid); color: var(--words-command-solid-color); } [data-words-command-button][data-command='commit']:hover:not(:disabled):not([data-disabled]) { border-color: var(--_words-accent-solid-hover); background: var(--_words-accent-solid-hover); color: var(--words-command-solid-color); } [data-words-command-button]:disabled, [data-words-command-button][data-disabled] { cursor: not-allowed; opacity: var(--words-disabled-opacity); } [data-words-floating] { --_words-toolbar-px: var(--words-toolbar-px-md); --_words-toolbar-py: var(--words-toolbar-py-md); --_words-button-size: var(--button-height-xs); --_words-font-size: var(--words-font-size-md); --_words-accent-solid: var(--words-primary-solid); --_words-accent-solid-hover: var(--words-primary-solid-hover); --_words-accent-track: var(--words-primary-track); --_words-accent-border: var(--words-primary-border); --_words-accent-text: var(--words-primary-text); --toolbar-focus-shadow: var(--words-focus-shadow); --toolbar-disabled-opacity: var(--words-disabled-opacity); } [data-words-link-editor] { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--words-command-gap); padding: 0; background: transparent; } [data-words-link-editor][data-invalid] { background: color-mix(in srgb, var(--words-invalid-border) 8%, var(--words-toolbar-bg)); } [data-words-link-editor][data-disabled] { opacity: var(--words-disabled-opacity); } [data-words-heading-picker] { min-inline-size: var(--_words-button-size); block-size: var(--_words-button-size); } [data-words-toolbar-family] { display: inline-flex; align-items: center; justify-content: center; gap: var(--words-code-py); min-inline-size: calc(var(--_words-button-size) + 1rem); block-size: var(--_words-button-size); padding-inline: var(--button-gap-xs); border: var(--words-border-width) solid transparent; border-radius: var(--words-command-radius); background: transparent; color: var(--words-command-color); font: inherit; cursor: pointer; } [data-words-toolbar-family]:hover:not(:disabled):not([data-disabled]), [data-words-toolbar-family][data-active], [data-words-toolbar-family][data-state='open'] { border-color: var(--_words-accent-border); background: var(--_words-accent-track); color: var(--_words-accent-text); } [data-words-toolbar-family]:disabled, [data-words-toolbar-family][data-disabled] { cursor: not-allowed; opacity: var(--words-disabled-opacity); } [data-words-code-language-picker] { display: inline-flex; align-items: center; justify-content: center; gap: var(--words-command-gap); min-inline-size: calc(var(--_words-button-size) + 3ch); block-size: var(--_words-button-size); padding-inline: var(--button-gap-xs); border: var(--words-border-width) solid transparent; border-radius: var(--words-command-radius); background: transparent; color: var(--words-command-color); font: inherit; cursor: pointer; } [data-words-code-language-picker]:hover:not(:disabled):not([data-disabled]), [data-words-code-language-picker][data-active] { border-color: var(--_words-accent-border); background: var(--_words-accent-track); color: var(--_words-accent-text); } [data-words-code-language-picker]:disabled, [data-words-code-language-picker][data-disabled] { cursor: not-allowed; opacity: var(--words-disabled-opacity); } [data-words-code-language-value] { min-inline-size: 2.5ch; font-size: var(--words-status-font-size); font-variant-numeric: tabular-nums; text-align: start; } [data-words-find-trigger] { display: inline-flex; align-items: center; justify-content: center; align-self: flex-start; inline-size: var(--_words-button-size); min-inline-size: var(--_words-button-size); block-size: var(--_words-button-size); padding: 0; border: var(--words-border-width) solid transparent; border-radius: var(--words-command-radius); background: transparent; color: var(--words-command-color); } [data-words-find-trigger]:hover:not(:disabled):not([data-disabled]) { border-color: var(--words-command-border-hover); background: var(--words-command-bg-hover); color: var(--words-command-color-hover); } [data-words] > [data-words-find-trigger] { margin-block-start: var(--_words-toolbar-py); margin-inline-start: var(--_words-toolbar-px); } [data-words-find-trigger][data-state='open'], [data-words-find-trigger][data-has-matches] { border-color: var(--_words-accent-border); background: var(--_words-accent-track); color: var(--_words-accent-text); } [data-words-heading-picker-panel] { display: grid; grid-template-columns: repeat(4, var(--_words-button-size)); gap: var(--button-gap-xs); } [data-words-heading-picker-panel] [data-words-command-button] { inline-size: var(--_words-button-size); block-size: var(--_words-button-size); justify-self: stretch; } [data-words-toolbar-family-panel] { display: grid; gap: var(--button-gap-xs); inline-size: min(12.5rem, calc(100vw - var(--space-4))); max-inline-size: calc(100vw - var(--space-4)); } [data-words-toolbar-family-panel][data-family='table'] { inline-size: min(18rem, calc(100vw - var(--space-4))); gap: var(--button-gap-xs); } [data-words-toolbar-family-panel] [data-toolbar-button], [data-words-toolbar-family-panel] [data-words-command-button], [data-words-toolbar-family-panel] [data-words-code-language-picker], [data-words-toolbar-family-panel] [data-words-find-trigger] { justify-content: flex-start; inline-size: 100%; } [data-words-toolbar-family-panel] [data-words-command-button] { min-inline-size: 0; } [data-words-toolbar-family-panel] [data-words-command-button] .eidos-button-body { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } [data-words-toolbar-family-panel][data-family='table'] [data-words-command-button] { min-block-size: calc(var(--_words-button-size) * 1.08); block-size: calc(var(--_words-button-size) * 1.08); padding-inline: var(--button-gap-xs); } [data-words-toolbar-family-panel][data-family='table'] [data-words-command-button] .eidos-button-body { font-size: var(--words-status-font-size); } [data-words-toolbar-family-panel][data-family='table'] [data-command='table-cell-tone-muted'] { background: color-mix(in srgb, var(--words-toolbar-bg) 86%, transparent); } [data-words-toolbar-family-panel][data-family='table'] [data-command='table-cell-tone-accent'] { background: color-mix(in srgb, var(--_words-accent-solid) 14%, var(--words-bg)); color: var(--_words-accent-text); } [data-words-toolbar-family-panel][data-family='table'] [data-command='table-cell-tone-default'] { background: var(--words-bg); } [data-words-toolbar-family-section] { display: grid; gap: var(--button-gap-xs); } [data-words-toolbar-family-panel][data-family='table'] [data-words-toolbar-family-section] { gap: var(--words-code-py); } [data-words-toolbar-family-section] + [data-words-toolbar-family-section] { padding-block-start: var(--button-gap-xs); border-block-start: var(--words-border-width) solid var(--words-toolbar-border); } [data-words-toolbar-family-panel][data-family='table'] [data-words-toolbar-family-section] + [data-words-toolbar-family-section] { padding-block-start: var(--words-code-py); } [data-words-toolbar-family-label] { color: var(--words-status-color); font-size: var(--words-status-font-size); font-weight: var(--words-strong-font-weight); line-height: var(--words-line-height); } [data-words-toolbar-family-panel][data-family='table'] [data-words-toolbar-family-label] { line-height: 1.2; } [data-words-toolbar-family-grid] { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--button-gap-xs); } [data-words-toolbar-family-panel][data-family='table'] [data-words-toolbar-family-grid] { gap: var(--words-code-py); } [data-words-toolbar-family-grid][data-columns='1'] { grid-template-columns: minmax(0, 1fr); } [data-words-toolbar-family-grid][data-columns='3'] { grid-template-columns: repeat(3, minmax(0, 1fr)); } [data-words-toolbar-family-grid][data-columns='4'] { grid-template-columns: repeat(4, minmax(0, 1fr)); } [data-words-toolbar-family-panel] [data-words-code-language-picker], [data-words-toolbar-family-panel] [data-words-find-trigger] { padding-inline: var(--words-command-px); } [data-words-toolbar-family-panel] [data-words-code-language-value] { min-inline-size: auto; } [data-words-code-language-panel] { display: grid; grid-template-columns: repeat(2, minmax(8rem, 1fr)); gap: var(--button-gap-xs); } [data-words-code-language-option] { display: grid; grid-template-columns: 3.5rem minmax(0, 1fr); align-items: center; gap: var(--words-command-gap); min-inline-size: 0; block-size: var(--_words-button-size); padding-inline: var(--words-command-px); border: var(--words-border-width) solid var(--words-command-border-hover); border-radius: var(--words-command-radius); background: var(--words-bg); color: var(--words-command-color); font: inherit; cursor: pointer; text-align: start; } [data-words-code-language-option]:hover:not(:disabled):not([data-disabled]) { border-color: var(--words-command-border-hover); background: var(--words-command-bg-hover); color: var(--words-command-color-hover); } [data-words-code-language-option]:focus-visible { box-shadow: var(--words-focus-shadow); outline: none; } [data-words-code-language-option][data-active] { border-color: var(--_words-accent-border); background: var(--_words-accent-track); color: var(--_words-accent-text); } [data-words-code-language-code] { color: var(--words-status-color); font-size: var(--words-status-font-size); font-variant-numeric: tabular-nums; text-transform: uppercase; } [data-words-code-language-label] { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } [data-words-link-field] { display: flex; box-sizing: border-box; align-items: center; gap: var(--words-command-gap); inline-size: 100%; min-inline-size: 0; block-size: var(--_words-button-size); padding-inline: var(--words-command-px); border: var(--words-border-width) solid var(--words-toolbar-border); border-radius: var(--words-command-radius); background: var(--words-bg); color: var(--words-content-color); } [data-words-link-label] { display: inline-flex; flex: 0 0 auto; align-items: center; color: var(--words-status-color); font-size: var(--words-status-font-size); } [data-words-link-field] input[type='text'] { flex: 1 1 auto; min-inline-size: 0; border: 0; background: transparent; color: var(--words-content-color); font: inherit; outline: none; } [data-words-link-field]:focus-within { border-color: var(--_words-accent-border); box-shadow: var(--words-focus-shadow); } [data-words-link-field]:has(input[aria-invalid='true']) { border-color: var(--words-invalid-border); } [data-words-link-actions] { display: inline-flex; flex: 0 0 auto; align-items: center; gap: var(--words-command-gap); } [data-words-link-actions] button { display: inline-flex; flex: 0 0 var(--_words-button-size); align-items: center; justify-content: center; inline-size: var(--_words-button-size); block-size: var(--_words-button-size); padding: 0; border: var(--words-border-width) solid var(--words-command-border-hover); border-radius: var(--words-command-radius); background: var(--words-bg); color: var(--words-command-color); font: inherit; cursor: pointer; } [data-words-link-actions] button[data-words-link-apply] { border-color: var(--_words-accent-solid); background: var(--_words-accent-solid); color: var(--words-command-solid-color); } [data-words-link-actions] button:disabled { cursor: not-allowed; opacity: var(--words-disabled-opacity); } [data-words-link-error] { grid-column: 1 / -1; color: var(--words-status-error-color); font-size: var(--words-status-font-size); } [data-words-placeholder] { display: block; padding-block-start: var(--_words-content-py); padding-inline: var(--_words-content-px); color: var(--words-placeholder-color); pointer-events: none; } [data-words-placeholder][hidden], [data-words-hidden-input][hidden] { display: none; } [data-words-content] { min-block-size: var(--_words-content-min-block-size); padding-block: var(--_words-content-py); padding-inline: var(--_words-content-px); color: var(--words-content-color); outline: none; overflow-wrap: anywhere; white-space: pre-wrap; caret-color: var(--_words-accent-solid); user-select: text; -webkit-user-select: text; } [data-words-content] * { user-select: text; -webkit-user-select: text; } [data-words-placeholder]:not([hidden]) + [data-words-content] { padding-block-start: var(--words-content-py-after-placeholder); } [data-words-content]::selection, [data-words-content] ::selection { background: var(--_words-selection-bg); color: var(--_words-selection-color); } [data-words-content]:focus-visible { outline: none; } [data-words-content] :where(p, h1, h2, h3, blockquote, pre, ul, ol, table) { margin-block: 0 var(--words-block-gap); } [data-words-content] :where(p, h1, h2, h3, blockquote, pre, ul, ol, table):last-child { margin-block-end: 0; } /* Headings need more breathing room above than between body blocks so the document gets a visible rhythm. The :not(:first-child) gate keeps a heading at the top of the editor flush against the toolbar instead of opening a blank top margin. */ [data-words-content] :where(h1, h2, h3):not(:first-child) { margin-block-start: calc(var(--words-block-gap) * 1.5); } [data-words-content] :where(h1, h2, h3) { color: var(--words-heading-color); font-size: var(--words-heading-font-size); font-weight: var(--words-heading-font-weight); line-height: var(--words-heading-line-height); } [data-words-content] :where(h1) { font-size: var(--words-heading-h1-font-size); } [data-words-content] :where(h2) { font-size: var(--words-heading-h2-font-size); } [data-words-content] :where(h3) { font-size: var(--words-heading-h3-font-size); } [data-words-content] :where(strong) { font-weight: var(--words-strong-font-weight); } [data-words-content] [data-words-marks~='bold'] { font-weight: var(--words-strong-font-weight); } [data-words-content] [data-words-marks~='italic'] { font-style: italic; } [data-words-content] [data-words-marks~='underline'] { text-decoration-line: underline; } [data-words-content] [data-words-marks~='strike'] { text-decoration-line: line-through; } [data-words-content] [data-words-marks~='underline'][data-words-marks~='strike'] { text-decoration-line: underline line-through; } [data-words-content] :where(code) { border-radius: var(--words-code-radius); background: var(--words-code-bg); color: var(--words-code-color); font-family: var(--words-code-font-family); padding-block: var(--words-code-py); padding-inline: var(--words-code-px); } [data-words-content] :where(pre) { overflow-x: auto; padding-block: calc(var(--words-quote-px) * 1.25); padding-inline: calc(var(--words-quote-px) * 1.25); border: var(--words-border-width) solid color-mix(in srgb, var(--_words-accent-border) 60%, var(--words-toolbar-border)); border-radius: var(--words-code-radius); background: var(--words-code-bg); color: var(--words-code-color); font-family: var(--words-code-font-family); white-space: pre-wrap; } [data-words-content] :where(pre code) { display: block; padding: 0; border-radius: 0; background: transparent; color: inherit; font: inherit; } [data-words-content] [data-words-code-token] { font: inherit; } [data-words-content] [data-words-code-token='comment'] { color: var(--words-status-color); font-style: italic; } [data-words-content] [data-words-code-token='keyword'] { color: var(--_words-accent-text); font-weight: var(--words-strong-font-weight); } [data-words-content] [data-words-code-token='string'] { color: var(--words-affirm-text); } [data-words-content] [data-words-code-token='number'], [data-words-content] [data-words-code-token='boolean'] { color: var(--words-fulfill-text); } [data-words-content] [data-words-code-token='function'] { color: var(--words-secondary-text); } [data-words-content] [data-words-code-token='tag'] { color: var(--words-threat-text); } [data-words-content] [data-words-code-token='attribute'], [data-words-content] [data-words-code-token='property'] { color: var(--words-risk-text); } [data-words-content] [data-words-code-token='operator'], [data-words-content] [data-words-code-token='punctuation'], [data-words-content] [data-words-code-token='variable'] { color: var(--words-status-color); } [data-words-content] [data-words-marks~='code'] { border-radius: var(--words-code-radius); background: var(--words-code-bg); color: var(--words-code-color); font-family: var(--words-code-font-family); padding-block: var(--words-code-py); padding-inline: var(--words-code-px); } [data-words-content] :where(blockquote) { padding-block: calc(var(--words-quote-px) * 0.5); padding-inline-start: var(--words-quote-px); border-inline-start: calc(var(--words-quote-border-width) * 1.5) solid var(--_words-accent-border); background: color-mix(in srgb, var(--_words-accent-solid) 4%, transparent); color: var(--words-quote-color); font-style: italic; } [data-words-content] :where(ul, ol) { padding-inline-start: var(--words-list-padding-inline-start); } [data-words-content] :where(table) { inline-size: 100%; border-collapse: collapse; table-layout: fixed; overflow: hidden; border: var(--words-border-width) solid var(--words-toolbar-border); border-radius: var(--words-code-radius); background: var(--words-bg); } /* Striped rows — bumped from a faint 70%-transparent overlay to a solid toolbar-bg tint so the zebra is actually discernible against the editor background. */ [data-words-content] :where(table[data-words-table-striped] tr:nth-child(even) td), [data-words-content] :where(table[data-words-table-striped] tr:nth-child(even) th) { background: var(--words-toolbar-bg); } [data-words-content] :where(table[data-words-table-compact] td), [data-words-content] :where(table[data-words-table-compact] th) { padding-block: calc(var(--words-code-py) * 0.5); padding-inline: calc(var(--words-command-px) * 0.75); } [data-words-content] :where(td, th) { min-inline-size: calc(var(--_words-button-size) * 2); padding-block: var(--words-code-py); padding-inline: var(--words-command-px); border: var(--words-border-width) solid var(--words-toolbar-border); vertical-align: top; transition: background-color 120ms ease; } /* Subtle hover for every body cell — lets the user know cells are interactive (clickable to edit). Header rows opt out below. */ [data-words-content] :where(table) tr:hover td:not([data-words-cell-header]) { background: color-mix(in srgb, var(--_words-accent-solid) 5%, transparent); } [data-words-content] :where(th), [data-words-content] [data-words-cell-header] { background: color-mix(in srgb, var(--_words-accent-solid) 12%, var(--words-bg)); color: var(--words-heading-color); font-weight: var(--words-strong-font-weight); /* Stronger bottom border under the header row so the divider with the body is unambiguous regardless of striping. */ border-block-end-width: calc(var(--words-border-width) * 2); } [data-words-content] [data-words-cell-tone='muted'] { background: color-mix(in srgb, var(--words-toolbar-bg) 82%, transparent); } /* Accent tone — was 14% solid with full accent-text recolor, which read as "this cell is broken / special-cased random". Toned down to 8% background and kept the inherited text color so the cell still draws the eye without shouting. */ [data-words-content] [data-words-cell-tone='accent'] { background: color-mix(in srgb, var(--_words-accent-solid) 8%, var(--words-bg)); } [data-words-content] [data-words-cell-vertical='middle'] { vertical-align: middle; } [data-words-content] [data-words-cell-vertical='bottom'] { vertical-align: bottom; } [data-words-content] [data-words-node='table-cell']:focus-within { background: color-mix(in srgb, var(--_words-accent-solid) 8%, transparent); } [data-words-content] [data-words-node='table-cell'][data-words-cell-tone='muted']:focus-within { background: color-mix(in srgb, var(--_words-accent-solid) 8%, var(--words-toolbar-bg)); } [data-words-content] [data-words-node='table-cell'][data-words-cell-tone='accent']:focus-within, [data-words-content] [data-words-node='table-cell'][data-words-cell-header]:focus-within { background: color-mix(in srgb, var(--_words-accent-solid) 20%, var(--words-bg)); } /* ── Image (F3) ──────────────────────────────────────────────────────── */ [data-words-content] :where(figure[data-words-block='image']) { display: flex; flex-direction: column; align-items: center; gap: var(--words-code-py); margin-inline: 0; padding: var(--words-code-py); border: var(--words-border-width) solid var(--words-toolbar-border); border-radius: var(--words-code-radius); background: var(--words-bg); } [data-words-content] :where(figure[data-words-block='image']) img { display: block; max-inline-size: 100%; block-size: auto; border-radius: var(--words-code-radius); user-select: none; } [data-words-content] :where(figure[data-words-block='image']) figcaption { max-inline-size: 100%; color: var(--words-quote-color); font-size: var(--words-status-font-size); font-style: italic; text-align: center; } [data-words-content] [data-words-block='image'][data-words-image-align='left'] { align-items: flex-start; margin-inline-end: auto; } [data-words-content] [data-words-block='image'][data-words-image-align='right'] { align-items: flex-end; margin-inline-start: auto; } [data-words-content] [data-words-block='image'][data-words-image-status='pending'] img { opacity: var(--words-disabled-opacity); filter: grayscale(0.4); } [data-words-content] [data-words-block='image'][data-words-image-status='pending']::after { content: 'Uploading…'; color: var(--words-status-color); font-size: var(--words-status-font-size); font-style: italic; } [data-words-content] [data-words-block='image'][data-words-image-status='error'] { border-color: var(--words-threat-text); } [data-words-content] [data-words-block='image'][data-words-image-status='error']::after { content: 'Upload failed'; color: var(--words-threat-text); font-size: var(--words-status-font-size); } [data-words-content] :focus-within > figure[data-words-block='image'], [data-words-content] figure[data-words-block='image']:focus, [data-words-content] figure[data-words-block='image']:focus-within { outline: 2px solid var(--_words-accent-border); outline-offset: 2px; } /* Atomic block selection — when the user clicks an image the provider flags it as the visually-selected atomic block (selectedBlockIndex). The render decorates the figure with data-words-block-selected so we can paint a strong accent border + soft glow. The drawer enters image mode in parallel. */ [data-words-content] figure[data-words-block='image'][data-words-block-selected] { outline: 3px solid var(--_words-accent-solid); outline-offset: 3px; box-shadow: 0 0 0 6px color-mix(in srgb, var(--_words-accent-solid) 18%, transparent), 0 0 24px color-mix(in srgb, var(--_words-accent-solid) 25%, transparent); } [data-words-content] figure[data-words-block='image'] { cursor: pointer; } [data-words-content] [data-words-list-kind='check'] { list-style: none; } [data-words-content] [data-words-check-toggle] { display: inline-flex; align-items: center; justify-content: center; inline-size: var(--_words-check-size); block-size: var(--_words-check-size); margin-inline-end: var(--words-command-gap); border: var(--words-border-width) solid var(--_words-accent-border); border-radius: var(--words-command-radius); background: var(--words-bg); color: var(--words-command-solid-color); vertical-align: text-bottom; cursor: pointer; user-select: none; -webkit-user-select: none; } [data-words-content] [data-words-check-toggle]::after { content: ''; display: block; inline-size: var(--_words-check-mark-width); block-size: var(--_words-check-mark-height); border-block-end: var(--_words-check-mark-stroke) solid currentColor; border-inline-end: var(--_words-check-mark-stroke) solid currentColor; opacity: 0; transform: rotate(45deg) translateY(var(--_words-check-mark-offset)); } [data-words-content] [data-words-check-toggle][data-words-checked='true'] { border-color: var(--_words-accent-solid); background: var(--_words-accent-solid); } [data-words-content] [data-words-check-toggle][data-words-checked='true']::after { opacity: 1; } [data-words][data-disabled] [data-words-check-toggle], [data-words][data-readonly] [data-words-check-toggle] { cursor: default; opacity: var(--words-disabled-opacity); } [data-words-content] [data-words-indent] { margin-inline-start: calc(var(--words-list-padding-inline-start) * var(--_words-indent, 1)); } [data-words-content] [data-words-indent='1'] { --_words-indent: 1; } [data-words-content] [data-words-indent='2'] { --_words-indent: 2; } [data-words-content] [data-words-indent='3'] { --_words-indent: 3; } [data-words-content] [data-words-indent='4'] { --_words-indent: 4; } [data-words-content] [data-words-indent='5'] { --_words-indent: 5; } [data-words-content] [data-words-indent='6'] { --_words-indent: 6; } [data-words-content] [data-words-indent='7'] { --_words-indent: 7; } [data-words-content] [data-words-indent='8'] { --_words-indent: 8; } [data-words-content] :where(a) { color: var(--_words-accent-text); text-decoration-color: var(--_words-accent-border); } [data-words-status] { padding-block: var(--words-status-py); padding-inline: var(--_words-content-px); border-block-start: var(--words-border-width) solid var(--words-toolbar-border); color: var(--words-status-color); font-size: var(--words-status-font-size); } [data-words-status][data-status='error'] { color: var(--words-status-error-color); } [data-words-find-replace] { display: flex; flex-direction: column; gap: var(--words-command-gap); inline-size: 100%; padding: 0; border: 0; background: transparent; } [data-words-find-replace][data-disabled], [data-words-find-replace][data-readonly] { color: var(--words-status-color); } [data-words-find-replace][data-invalid] [data-words-find-counter] { color: var(--words-status-error-color); } [data-words-find-replace][data-disabled] { cursor: not-allowed; opacity: var(--words-disabled-opacity); } [data-words-find-replace][data-has-matches] [data-words-find-counter] { color: var(--_words-accent-text); } [data-words-find-row], [data-words-replace-row] { display: flex; align-items: center; gap: var(--words-command-gap); } [data-words-find-label], [data-words-replace-label] { display: inline-flex; flex: 0 0 auto; align-items: center; color: var(--words-status-color); font-size: var(--words-status-font-size); } [data-words-find-input], [data-words-replace-input] { flex: 1 1 auto; min-inline-size: 0; block-size: var(--_words-button-size); padding-inline: var(--words-command-px); border: var(--words-border-width) solid var(--words-toolbar-border); border-radius: var(--words-command-radius); background: var(--words-bg); color: var(--words-content-color); font: inherit; outline: none; } [data-words-find-input]:focus, [data-words-replace-input]:focus { border-color: var(--_words-accent-border); box-shadow: var(--words-focus-shadow); } [data-words-find-input][aria-invalid='true'] { border-color: var(--words-invalid-border); } [data-words-find-counter] { flex: 0 0 auto; min-inline-size: 3.5ch; color: var(--words-status-color); font-size: var(--words-status-font-size); font-variant-numeric: tabular-nums; text-align: end; } [data-words-find-prev], [data-words-find-next], [data-words-find-case], [data-words-find-whole], [data-words-find-regex], [data-words-find-selection], [data-words-replace-preserve], [data-words-replace-current], [data-words-replace-all] { display: inline-flex; flex: 0 0 var(--_words-button-size); align-items: center; justify-content: center; inline-size: var(--_words-button-size); block-size: var(--_words-button-size); padding: 0; border: var(--words-border-width) solid var(--words-command-border-hover); border-radius: var(--words-command-radius); background: var(--words-bg); color: var(--words-command-color); font: inherit; cursor: pointer; outline: none; } [data-words-find-prev]:hover:not(:disabled):not([data-disabled]), [data-words-find-next]:hover:not(:disabled):not([data-disabled]), [data-words-find-case]:hover:not(:disabled):not([data-disabled]), [data-words-find-whole]:hover:not(:disabled):not([data-disabled]), [data-words-find-regex]:hover:not(:disabled):not([data-disabled]), [data-words-find-selection]:hover:not(:disabled):not([data-disabled]), [data-words-replace-preserve]:hover:not(:disabled):not([data-disabled]), [data-words-replace-current]:hover:not(:disabled):not([data-disabled]), [data-words-replace-all]:hover:not(:disabled):not([data-disabled]) { border-color: var(--words-command-border-hover); background: var(--words-command-bg-hover); color: var(--words-command-color-hover); } [data-words-find-prev]:focus-visible, [data-words-find-next]:focus-visible, [data-words-find-case]:focus-visible, [data-words-find-whole]:focus-visible, [data-words-find-regex]:focus-visible, [data-words-find-selection]:focus-visible, [data-words-replace-preserve]:focus-visible, [data-words-replace-current]:focus-visible, [data-words-replace-all]:focus-visible { box-shadow: var(--words-focus-shadow); } [data-words-find-prev]:disabled, [data-words-find-next]:disabled, [data-words-find-case]:disabled, [data-words-find-whole]:disabled, [data-words-find-regex]:disabled, [data-words-find-selection]:disabled, [data-words-replace-preserve]:disabled, [data-words-replace-current]:disabled, [data-words-replace-all]:disabled { cursor: not-allowed; opacity: var(--words-disabled-opacity); } [data-words-find-case][data-active], [data-words-find-whole][data-active], [data-words-find-regex][data-active], [data-words-find-selection][data-active], [data-words-replace-preserve][data-active] { border-color: var(--_words-accent-border); background: var(--_words-accent-track); color: var(--_words-accent-text); } [data-words-replace-all] { border-color: var(--_words-accent-solid); background: var(--_words-accent-solid); color: var(--words-command-solid-color); } [data-words-replace-all]:hover:not(:disabled):not([data-disabled]) { border-color: var(--_words-accent-solid-hover); background: var(--_words-accent-solid-hover); color: var(--words-command-solid-color); } [data-words-content] mark[data-words-find-match] { border-radius: var(--words-code-radius); background: color-mix(in srgb, var(--_words-accent-solid) 22%, transparent); color: var(--_words-accent-text); padding-block: var(--words-code-py); padding-inline: var(--words-code-px); } [data-words-content] mark[data-words-find-match][data-words-find-active] { background: color-mix(in srgb, var(--_words-accent-solid) 55%, transparent); outline: 1px solid var(--_words-accent-border); } @media (prefers-reduced-motion: reduce) { [data-words], [data-words-command-button] { transition: none; } }