/* Bundled font faces — generated by scripts/generate-fonts.mjs */
@import './fonts.css';
@import './popover-animation.css';
@import './keyframes.css';
@import '../tools/image/crop-editor.css';
@import '../tools/image/crop-modal.css';
@import '../tools/image/alt-popover.css';

/*
  Import Tailwind CSS sub-modules individually instead of `@import 'tailwindcss'`
  (we ship a scoped preflight below instead of tailwindcss/preflight.css), but
  the UTILITIES MUST be imported INTO the `utilities` cascade layer — exactly as
  the canonical `@import "tailwindcss"` does.

  Why: this bundle is injected into the host page's <head> (UI.loadStyles), so
  Blok's generated utilities (.text-3xl, .grid, every sm:/lg: responsive variant)
  live alongside a host Tailwind v4 app's own. Per the CSS cascade-layer spec,
  UN-LAYERED declarations ALWAYS beat LAYERED ones, regardless of specificity,
  source order, or media queries. So an un-layered `@import 'tailwindcss/utilities.css'`
  makes Blok's `.text-3xl` override the host's layered `sm:text-4xl` on the HOST's
  own elements — collapsing the host's responsive layout the instant the editor
  mounts. Importing utilities into layer(utilities) keeps the host in control of
  its own utilities (Blok's, prepended first, fall earlier in the same layer).

  theme.css stays un-layered on purpose: it only emits :root token *values*
  (--text-3xl, --color-*), which never override a host's utility classes, and
  Blok wants its own token values to win for a consistent editor appearance.

  UI.loadStyles ALSO prepends the canonical `@layer theme, base, components,
  utilities;` order statement so that, since this bundle registers the utilities
  layer first, the host's base (preflight) layer still slots in BEFORE utilities
  rather than after it. See ui.ts.

  See: https://github.com/tailwindlabs/tailwindcss/discussions/13188
*/
@import 'tailwindcss/theme.css';
@import 'tailwindcss/utilities.css' layer(utilities);

@import './isolation.css';
@import './preflight.css';

/*
  Top-Layer reset — duplicated from isolation.css so that audits reading
  main.css directly (test/unit/components/utils/tooltip.test.ts) find the
  rule without walking @imports. Keys off the `data-blok-top-layer` marker
  that src/components/utils/top-layer.ts sets on every promoted element,
  so one rule covers every current and future popover/tooltip caller. The
  isolation.css copy still paints in isolation-import order; this one is
  cascade-equivalent because both target the same selector with the same
  declarations.
*/
[data-blok-top-layer][popover] {
  inset: auto;
  margin: 0;
  border: 0;
  padding: 0;
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  overflow: visible;
}

/* Restore browser-default scrollbar appearance inside Blok boundaries
   (Chromium/Safari ::-webkit-scrollbar). */
[data-blok-interface] ::-webkit-scrollbar,
[data-blok-popover] ::-webkit-scrollbar {
  width: revert;
  height: revert;
  background-color: revert;
}

/*
  Exclude non-source directories from Tailwind's automatic content detection.
  Without this, Tailwind v4 scans all non-gitignored files (including docs/,
  test/, .claude/) and picks up false class candidates from code examples,
  test fixtures, and markdown — generating dead CSS in the production bundle.
*/
@source not "../../docs";
@source not "../../test";
@source not "../../.claude";
@source not "../../scripts";
@source not "../../.storybook";

@custom-variant mobile (@media (max-width: 650px));
@custom-variant not-mobile (@media (min-width: 651px));
@custom-variant can-hover (@media (hover: hover));

/*
  Theme-aware dark variant for components outside the scoped preflight
  (e.g. emoji picker, which is appended to document.body).
  The component sets data-theme="dark"|"light" on its root element after
  resolving the Blok theme; this variant replaces Tailwind's built-in dark:
  which incorrectly keys off prefers-color-scheme alone.
*/
@custom-variant theme-dark (&:where([data-theme="dark"], [data-theme="dark"] *));

@import './tokens.css';
@import './colors.css';

@import './checklist.css';

/*
  The default border color has changed to `currentcolor` in Tailwind CSS v4,
  so we've added these compatibility styles to make sure everything still
  looks the same as it did with Tailwind CSS v3.

  If we ever want to remove these styles, we need to add an explicit border
  color utility to any element that depends on these defaults.
*/
:where([data-blok-interface], [data-blok-popover]) *,
:where([data-blok-interface], [data-blok-popover]) ::after,
:where([data-blok-interface], [data-blok-popover]) ::before,
:where([data-blok-interface], [data-blok-popover]) ::backdrop,
:where([data-blok-interface], [data-blok-popover]) ::file-selector-button {
  border-color: var(--color-gray-200, currentcolor);
}

/**
 * Component classes for the Styles API.
 * These single-class names can be safely used with classList.add() by external plugins.
 * Each class bundles multiple Tailwind utilities using @apply.
 */
@utility blok-block {
  /* Base Blok styles - applied to block tool wrappers.
     Padding routes through the public --blok-block-padding-top/-bottom/-inline
     tokens (fallbacks preserve the historical 7px/7px/2px) so read-only hosts
     can tighten block rhythm without overriding [data-blok-tool]. */
  @apply pt-[var(--blok-block-padding-top,7px)] pb-[var(--blok-block-padding-bottom,7px)] px-[var(--blok-block-padding-inline,2px)] [&::-webkit-input-placeholder]:leading-normal!;
}
@utility blok-inline-tool-button {
  /* Inline Tools styles */
  @apply flex justify-center items-center border-0 rounded h-full p-0 w-7 bg-transparent cursor-pointer leading-normal text-black;
}
@utility blok-inline-tool-button--active {
  @apply bg-icon-active-bg text-icon-active-text;
}
@utility blok-input {
  /* Input element styles */
  @apply w-full rounded-[3px] border border-line-gray px-3 py-2.5 outline-hidden shadow-input data-blok-placeholder:before:static! data-blok-placeholder:before:inline-block data-blok-placeholder:before:w-0 data-blok-placeholder:before:whitespace-nowrap data-blok-placeholder:before:pointer-events-none;
}
@utility blok-loader {
  /* Loader styles with spinning animation */
  @apply relative border border-line-gray before:absolute before:left-1/2 before:top-1/2 before:w-[18px] before:h-[18px] before:rounded-full before:content-[''] before:-ml-[11px] before:-mt-[11px] before:border-2 before:border-line-gray before:border-l-active-icon before:animate-rotation;
}
@utility blok-button {
  /* Button styles */
  @apply p-[13px] rounded-[3px] border border-line-gray text-[14.9px] bg-white text-center cursor-pointer text-gray-text shadow-button-base hover:shadow-button-base-hover [&_svg]:h-5 [&_svg]:mr-[0.2em] [&_svg]:-mt-0.5;

  &:hover {
    background-color: var(--blok-button-focus-bg-hover);
  }
}
@utility blok-settings-button {
  /* Settings button styles */
  @apply inline-flex items-center justify-center rounded-[3px] cursor-pointer border-0 outline-hidden bg-transparent align-bottom text-inherit m-0 min-w-toolbox-btn min-h-toolbox-btn [&_svg]:w-auto [&_svg]:h-auto mobile:w-toolbox-btn-mobile mobile:h-toolbox-btn-mobile mobile:rounded-lg mobile:[&_svg]:w-icon-mobile mobile:[&_svg]:h-icon-mobile can-hover:hover:bg-bg-light;
}
@utility blok-settings-button--active {
  @apply text-active-icon;
}
@utility blok-settings-button--focused {
  @apply shadow-button-focused bg-item-focus-bg;
}
@utility blok-settings-button--focused-animated {
  @apply animate-button-clicked;
}

/**
 * Navigation mode focus marker
 * Escape makes the focused block a real selection (data-blok-selected), which
 * paints the highlight — so this marker adds no width/margin (the old
 * w-content-width + mx-auto shifted the block right).
 */
[data-blok-navigation-focused="true"] {
  @apply rounded-md;
}

/**
 * Delete button hover styles
 * Makes the delete button text and icon appear red on hover
 */
@media (hover: hover) {
  [data-blok-item-name="delete"]:hover {
    @apply text-item-confirm-bg transition-colors;
  }
}

/**
 * Drop indicator styles for drag and drop
 * Shows a visual line at the top or bottom of a block during drag
 * The --drop-indicator-depth CSS variable controls indentation based on target nesting level
 */
[data-drop-indicator] {
  @apply relative;
}

/*
 * Shared drop-line look for every orientation. The bar is a rounded rule whose
 * colour and thickness come from the design tokens, so the horizontal
 * (top/bottom) and vertical (left/right) indicators are visually identical;
 * each orientation rule below only sets which axis the thickness applies to and
 * where the bar is pinned.
 */
[data-drop-indicator]::before {
  @apply content-[''] absolute rounded-xs pointer-events-none z-10;
  background-color: var(--blok-dnd-drop-indicator-bg);
}

/*
 * Horizontal drop indicator: a rule across the top or bottom edge of the block.
 * `--drop-line-start` is the x-offset where the coloured line begins; the line
 * and the grayish lead-in below both reference it so they meet exactly.
 */
[data-drop-indicator="top"],
[data-drop-indicator="bottom"] {
  --drop-line-start: calc(var(--drop-indicator-side-left, 0px) + var(--drop-indicator-depth, 0) * var(--blok-space-3));
}

[data-drop-indicator="top"]::before,
[data-drop-indicator="bottom"]::before {
  height: var(--blok-dnd-drop-indicator-thickness);
  /* Confine the line to the content box: the holder spans the editor gutters,
   * so the side offsets pull the line in to the visible content width. The
   * depth indent (list nesting) is added on top of the content-left offset. */
  left: var(--drop-line-start);
  right: var(--drop-indicator-side-right, 0px);
}

[data-drop-indicator="bottom"]::before {
  @apply bottom-0;
  transform: translateY(50%);
}

[data-drop-indicator="top"]::before {
  @apply top-0;
  transform: translateY(-50%);
}

/*
 * Grayish lead-in for a list-item drop line: same-thickness rule from the
 * editor's left edge to where the coloured line starts. Underlaps it by 2px a
 * layer below, so the two read as one rule transitioning gray -> blue. Shown
 * only via the controller-set `data-drop-indicator-lead` attribute (lists).
 */
[data-drop-indicator-lead]::after {
  @apply content-[''] absolute rounded-xs pointer-events-none;
  z-index: 9;
  height: var(--blok-dnd-drop-indicator-thickness);
  left: 0;
  right: calc(100% - var(--drop-line-start) - 2px);
  background-color: var(--blok-dnd-drop-indicator-lead-bg);
}

[data-drop-indicator-lead][data-drop-indicator="bottom"]::after {
  @apply bottom-0;
  transform: translateY(50%);
}

[data-drop-indicator-lead][data-drop-indicator="top"]::after {
  @apply top-0;
  transform: translateY(-50%);
}

/*
 * Vertical drop indicator: a bar on the left or right edge of the holder,
 * signalling a column-layout drop. Same look as the horizontal rule, only the
 * thickness applies to the width and the bar is pinned to a side edge. The bar
 * is short, so it uses a slimmer width to read like the horizontal line.
 */
[data-drop-indicator="left"]::before,
[data-drop-indicator="right"]::before {
  width: var(--blok-dnd-drop-indicator-thickness-vertical);
  /* Span the full column-row height when the target sits in a column_list: the
   * controller sets these to the row's top/bottom offset (negative, so the bar
   * grows past the single block). Default 0/0 → the bar matches the block. */
  top: var(--drop-indicator-side-top, 0);
  bottom: var(--drop-indicator-side-bottom, 0);
}

[data-drop-indicator="left"]::before {
  /* Pull the bar out into the gutter so it sits clear of the content edge. */
  left: calc(var(--drop-indicator-side-left, 0px) - var(--blok-space-2));
  transform: translateX(-50%);
}

[data-drop-indicator="right"]::before {
  right: calc(var(--drop-indicator-side-right, 0px) - var(--blok-space-2));
  transform: translateX(50%);
}

/* Spring-loaded: flash selection highlight on toggle after it auto-expands */
[data-blok-spring-loaded] [data-blok-element-content] {
  animation: spring-loaded-flash 700ms ease-out forwards;
  border-radius: var(--blok-space-1);
}

/*
 * Arrival pulse: briefly highlight the block that a #<id> URL points to
 * after scroll + select. Class is applied/removed by highlightBlockArrival().
 */
.blok-block--target {
  animation: blok-block-target-pulse 1.5s ease-out;
  border-radius: var(--blok-space-1);
}

@media (prefers-reduced-motion: reduce) {
  .blok-block--target {
    /* Skip the keyframe tween but keep the hold so the class still clears. */
    animation: none;
    background-color: var(--blok-selection);
  }
}

/**
 * Content alignment
 * Applies horizontal alignment to block content based on the editor's contentAlign setting.
 * Left alignment overrides the mx-auto Tailwind class on [data-blok-element-content].
 */
[data-blok-content-align="left"] [data-blok-element-content] {
  margin-left: 0;
}

[data-blok-content-align="center"] [data-blok-element-content] {
  margin-left: auto;
  margin-right: auto;
}

[data-blok-content-align="right"] [data-blok-element-content] {
  margin-left: auto;
  /* The base class is mx-auto — without zeroing margin-right the rule
     collapses into centering. */
  margin-right: 0;
}

/**
 * Cross-block TEXT selection paint. A range spanning two blocks crosses two
 * contenteditable hosts; WebKit paints only the anchor host's part of it, and so
 * does a single-range ::highlight(). One ::highlight() range PER HOST is the
 * form all three engines paint, so cross-block-highlight.ts registers those and
 * stamps the wrapper — but only where needed: Firefox rewrites the range
 * mid-drag and would draw both at double opacity. Chromium paints ::selection
 * over the line box and a highlight over the text box, so it is left alone.
 *
 * Unlayered on purpose: the colour overridden here is the
 * `[&_::selection]:bg-selection-inline` utility UI.make puts on the wrapper,
 * which sits in @layer utilities and would win on layer order alone.
 */
[data-blok-cross-selection] ::selection {
  background-color: transparent;
}

[data-blok-interface] ::highlight(blok-cross-block-selection) {
  background-color: var(--blok-selection-inline);
}

/**
 * Content width mode
 * 'full' (data-blok-width="full" on the editor wrapper) removes the
 * --max-width-content constraint so content fills its container. The default
 * 'narrow' mode leaves the attribute absent and keeps the max-w-blok-content
 * Tailwind utility intact. Unlayered selector overrides the @layer utilities rule.
 * The --blok-content-max-width token stays authoritative in both modes; full mode
 * only swaps the fallback from --max-width-content to none.
 */
[data-blok-width="full"] [data-blok-element-content] {
  max-width: var(--blok-content-max-width, none);
}

/**
 * Editor gutter — host-overridable space for the floating plus/drag controls,
 * which render outside the content column. Logical props keep RTL correct.
 */
[data-blok-redactor] {
  padding-inline-start: var(--blok-editor-gutter-start, 0px);
  padding-inline-end: var(--blok-editor-gutter-end, 0px);
}

/*
 * Default gutter: Blok owns the width its floating +/⠿ block controls
 * need (56px), so hosts no longer hardcode a magic number. Declared at
 * zero specificity so any host declaration on the wrapper or an ancestor
 * (e.g. `.host [data-blok-interface] { --blok-editor-gutter-start: 0px }`)
 * wins. Must stay source-ordered BEFORE the read-only collapse below:
 * both rules are (0,0,0) on the same wrapper element, so the later one
 * wins in read-only mode.
 */
:where([data-blok-interface]) {
  --blok-editor-gutter-start: 56px;
}

/*
 * config.toolbarPosition: 'right' — the +/⠿ controls and the width reserved
 * for them both move to the inline-END gutter: the start gutter collapses and
 * an equal one opens at the end, so the text reclaims the space the controls
 * used to occupy. Logical tokens, so RTL mirrors for free.
 *
 * Source order matters twice: AFTER the default above (both (0,0,0) on the same
 * wrapper, later wins) and BEFORE the read-only / hidden-toolbar collapses,
 * which must still zero BOTH gutters when there are no controls to house.
 */
:where([data-blok-toolbar-position="right"]) {
  --blok-editor-gutter-start: 0px;
  --blok-editor-gutter-end: 56px;
}

/*
 * ...and the bar itself follows. Physical properties, because the default is a
 * physical `right:100%` Tailwind utility and unlayered physical overrides beat
 * it without the lightningcss logical-lowering trap noted above.
 *
 * LTR only: an RTL editor already docks this bar to the physical left, which IS
 * the mirrored side once the gutter above moves. Mobile is excluded because
 * below 650px the buttons are free-standing overlay pills, not a gutter bar.
 */
@media (min-width: 651px) {
  [data-blok-toolbar-position="right"]:not([data-blok-rtl="true"]) [data-blok-toolbar-actions] {
    right: auto;
    left: 100%;
    padding-right: 0;
    padding-left: 5px;
  }
}

/*
 * The gutter exists solely to house the edit-mode +/⠿ controls, so it
 * collapses automatically in read-only mode. This redeclares the gutter
 * tokens (rather than overriding padding-inline directly) because
 * lightningcss lowers the base rule's `padding-inline-start` into a
 * `:lang()`-guarded physical-property rule in the production build,
 * pushing it to (0,2,0) — a `:where(...) [data-blok-redactor] { padding-
 * inline: 0 }` override at (0,1,0) loses that fight in production (verified
 * live against the built bundle: the read-only editor kept its gutter).
 * Custom-property declarations are immune to logical-property lowering and
 * layer flattening, so redeclaring the tokens here always wins by normal
 * CSS inheritance: this wrapper sits closer to the redactor than any host
 * container that set the tokens further out, and inheritance resolves from
 * the nearest ancestor regardless of selector specificity.
 * A host that wants a gutter to persist declares the token on the wrapper
 * itself at >= (0,1,1) (one level closer than this rule's (0,0,0)), e.g.
 * `.host [data-blok-interface] { --blok-editor-gutter-start: 56px }`.
 *
 * NOTE: plain read-only ([data-blok-readonly]) deliberately keeps the
 * gutter. The block-hover copy-link control still renders there, and
 * readOnly.set() flips modes in place — collapsing on read-only made the
 * whole document jump sideways on every toggle. Only chromeless read-only
 * (readOnly: { hideControls: true }, stamped as data-blok-controls-hidden
 * by UI.toggleReadOnly) has a genuinely dead gutter.
 */
:where([data-blok-controls-hidden]) {
  --blok-editor-gutter-start: 0px;
  --blok-editor-gutter-end: 0px;
}

/*
 * Same collapse when the hover toolbar is disabled via config.hideToolbar
 * (the wrapper is stamped with data-blok-toolbar-hidden in UI.make): the
 * gutter exists solely to house the toolbar's +/⠿ controls, so a toolbar-less
 * editor reserves no space for them. Token redeclaration for the same
 * production-cascade reasons as the read-only rule above; a host can opt the
 * gutter back in with any (0,1,1)+ declaration on the wrapper.
 */
:where([data-blok-toolbar-hidden]) {
  --blok-editor-gutter-start: 0px;
  --blok-editor-gutter-end: 0px;
}

/*
 * Block nesting indent. BlockHierarchy writes only the MULTIPLIER (the inline
 * --_blok-block-depth) and the cascade turns it into the margin; it used to
 * stamp the margin itself, which a container tool could only decline with
 * `!important`. Multiplier x step, because the STEP inherits: the reset below
 * reaches a holder the moment it is mounted into a child slot, however late
 * that is (a framework adapter commits its slot a render after core inserts the
 * child, and nothing re-indents afterwards) — a JS `closest()` check cannot.
 * Physical `margin-left` keeps the pre-token behaviour and dodges the
 * lightningcss logical-property lowering trap noted in the gutter comment.
 * --blok-block-indent-step is public: declare it on your own slot to opt
 * indentation back IN, or on any ancestor to rescale nesting.
 */
:where([data-blok-element]) {
  margin-left: calc(var(--_blok-block-depth, 0) * var(--blok-block-indent-step, 24px));
}

/* Every child slot — first-party containers (toggle, callout, header toggle,
 * column, column_list, table cell) and every adapter's child slot carry this
 * marker — positions its own children, so depth must not add margin on top. */
:where([data-blok-nested-blocks]) {
  --blok-block-indent-step: 0px;
}

/**
 * Multi-block drag visual feedback
 * Makes selected blocks semi-transparent during multi-block drag operation
 */
[data-blok-dragging-multi="true"] [data-blok-selected="true"] {
  @apply opacity-40 transition-opacity duration-200;
}

/*
 * List start-padding indirection. Hosts set the public tokens once at any
 * ancestor: --blok-list-padding-start indents every list style;
 * --blok-checklist-padding-start overrides it for checklists only (so a
 * host can indent bulleted/ordered lists without indenting checklists).
 * Redeclaring a custom property (rather than overriding padding) is immune
 * to the production @layer flattening + logical-property lowering that
 * makes selector-specificity overrides unreliable (see the read-only
 * gutter comment above).
 */
[data-list-style] {
  --_blok-list-pad: var(--blok-list-padding-start, 0px);
}

[data-list-style="checklist"] {
  --_blok-list-pad: var(--blok-checklist-padding-start, var(--blok-list-padding-start, 0px));
}

/**
 * List item selection styles
 * Applies selection background to the list item itself (not the content wrapper)
 * so that margin-left indentation is respected
 */
[data-blok-selected="true"] [data-blok-element-content]:has([data-list-style]) {
  @apply bg-transparent;
}

[data-blok-selected="true"] [data-list-style] [role="listitem"] {
  @apply bg-selection rounded-[4px];
}

[data-blok-selected="true"] [data-list-style] [role="listitem"] [contenteditable] {
  @apply select-none;
}

/**
 * Embed selection styles
 * The embed figure can be narrower than the content box (percent width +
 * alignment), so painting the selection on the full-width content wrapper
 * highlights empty gutters. Drop the wrapper background and draw a padded
 * selection rectangle that hugs the figure's real dimensions instead.
 */
[data-blok-selected="true"] [data-blok-element-content]:has([data-role="embed-figure"]) {
  @apply bg-transparent;
}

[data-blok-selected="true"] [data-role="embed-figure"]::before {
  @apply content-[''] absolute -inset-2 rounded-md bg-selection pointer-events-none;
}

/**
 * Child-container heading overrides (callout, toggle heading)
 * Inside [data-blok-toggle-children], headings should match paragraph spacing
 * rather than using their large root-level top margins (mt-8, mt-[26px], etc.).
 */
[data-blok-toggle-children] :is(h1, h2, h3, h4, h5, h6) {
  @apply mt-px;
}

/**
 * Callout emoji vertical centering for heading first children.
 * Headings have taller line boxes than the emoji button, so the emoji
 * needs a top margin to shift its center down to match the heading's
 * first line center: (heading-line-box − emoji-line-box) / 2 + the 1px mt-px
 * the child carries.
 *
 * Both line boxes are host-settable, so the offset has to be DERIVED from those
 * tokens rather than precomputed. As the literals 8.5px / 4.6px / 2px it only
 * centred at the default sizes — scaling `fontSize.heading.1` alongside
 * `fontSize.callout` left the emoji 5.25px adrift.
 *
 * The formula is written once and each level contributes only its own size
 * token (repeating the fallback that level's rule declares in heading.css).
 * `1em` is the emoji's line box: the button carries `text-[1.5em] leading-[1]`,
 * so ONE em of the button is exactly the emoji line — see EMOJI_BUTTON_STYLES
 * for why em must be read against the element's own font here.
 */
[data-blok-component="callout"] button:has(+ [data-blok-toggle-children] > :first-child :is(h1, h2, h3)) {
  --_blok-callout-emoji-line: 1em;

  margin-top: calc((var(--_blok-callout-heading-size) * var(--blok-heading-line-height, 1.3) - var(--_blok-callout-emoji-line)) / 2 + 1px);
}
[data-blok-component="callout"] button:has(+ [data-blok-toggle-children] > :first-child h1) {
  --_blok-callout-heading-size: var(--blok-heading-1-font-size, 1.875rem);
}
[data-blok-component="callout"] button:has(+ [data-blok-toggle-children] > :first-child h2) {
  --_blok-callout-heading-size: var(--blok-heading-2-font-size, 1.5rem);
}
[data-blok-component="callout"] button:has(+ [data-blok-toggle-children] > :first-child h3) {
  --_blok-callout-heading-size: var(--blok-heading-3-font-size, 1.25rem);
}

/**
 * Table cell block minimum height.
 * Keeps .blok-block inside table cells above 1.6em so empty non-contenteditable
 * paragraphs in readonly mode match edit-mode height (leading-[1.6em] parity).
 * Kept inline in main.css because the unit test reads main.css directly via
 * readFileSync (test/unit/tools/table/table-core.test.ts).
 */
[data-blok-table-cell-blocks] .blok-block {
  @apply p-0 m-0 min-h-[1.6em];
}

@import './tables.css';
@import './slash-search.css';
@import './emoji-picker.css';
@import './database.css';
@import './media-empty.css';
@import './image.css';
@import './video.css';
@import './audio.css';
@import './embed.css';
@import './heading.css';
@import './bookmark.css';
@import './file.css';
@import './columns.css';
@import './resize-cue.css';
@import './presence.css';

/*
  Callout body type scale.

  A callout renders its text as a CHILD paragraph block, which carries the
  paragraph size utility. Without this rule the paragraph token would win
  inside callouts, so a host setting both `fontSize.callout` and
  `fontSize.paragraph` could never make callout text differ from body text —
  `fontSize.callout` would size only the emoji row. Un-layered and (0,2,0), so
  it beats the layered (dev) / later-source-order (prod) size utility on the
  child.

  It resolves to `inherit`, NOT to the token, because the wrapper has already
  applied it (CALLOUT_WRAPPER_CLASSES, which also carries the callout →
  paragraph → inherit fallback chain). Naming the token twice down one
  inheritance chain squares any relative value: `calc(1em * 1.5)` gave a 24px
  wrapper a 36px paragraph, so callout text outgrew both plain body text and
  the emoji sized off the wrapper.
*/
[data-blok-tool="callout"] [data-blok-tool="paragraph"] {
  font-size: inherit;
}

/*
  Image tool — selectors audited by unit tests (no backdrop-filter regression,
  lightbox bar/btn sizing, pan cursor + transform spring). Kept inline in
  main.css (not image.css) so the suite's direct readFileSync of main.css
  can grep authored rules without walking @imports. See test helper at
  test/unit/styles/helpers/read-main-css.ts for the general pattern; these
  specific rules must stay here to satisfy tests that read main.css directly.
*/
[data-blok-tool="image"] .blok-image-toolbar {
  position: absolute;
  top: 10px; right: 10px;
  display: inline-flex;
  background: var(--blok-overlay-surface);
  border-radius: var(--blok-space-2);
  padding: var(--blok-space-1);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 120ms ease, transform 120ms ease;
  pointer-events: none;
  box-shadow:
    inset 0 0 0 1px var(--blok-overlay-ring),
    var(--blok-image-shadow-toolbar);
  z-index: 2;
}
[data-blok-tool="image"] .blok-image-toolbar__align-popover {
  position: absolute;
  top: calc(100% + var(--blok-space-1));
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  gap: var(--blok-space-0-5);
  padding: var(--blok-space-1);
  background: var(--blok-overlay-surface);
  border-radius: var(--blok-space-2);
  box-shadow:
    inset 0 0 0 1px var(--blok-overlay-ring),
    var(--blok-image-shadow-toolbar);
  z-index: 3;
}
.blok-image-lightbox {
  --blok-space-0-5: 2px;
  --blok-space-1: 4px;
  --blok-space-1-5: 6px;
  --blok-space-2: 8px;
  --blok-space-3: 12px;
  --blok-space-4: 16px;
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  z-index: 9999;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
/*
  Re-assert viewport coverage when promoted to the Top Layer. The
  `[data-blok-top-layer][popover]` reset above sets `inset: auto` (specificity
  0,2,0) which would otherwise outrank `.blok-image-lightbox { inset: 0 }`
  (0,1,0) and shrink the dialog to its content — exposing the editor behind it
  and letting drag gestures start native rubber-band text selection on the
  editor.
*/
.blok-image-lightbox[data-blok-top-layer][popover] {
  inset: 0;
  width: 100vw;
  height: 100vh;
  max-width: 100vw;
  max-height: 100vh;
}
.blok-image-lightbox.is-dragging {
  cursor: grabbing;
}
.blok-image-lightbox__image {
  max-width: 95vw;
  max-height: 95vh;
  object-fit: contain;
  transform: scale(1);
  transform-origin: center center;
  transition: transform 420ms cubic-bezier(0.34, 1.56, 0.64, 1);
  pointer-events: none;
  position: relative;
  z-index: 1;
  will-change: transform;
}
.blok-image-lightbox.is-dragging .blok-image-lightbox__image {
  transition: none;
}
.blok-image-lightbox__bar {
  position: absolute;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: var(--blok-space-0-5);
  padding: var(--blok-space-1-5);
  background: var(--blok-image-lightbox-toolbar-bg);
  color: var(--blok-image-lightbox-toolbar-fg);
  border-radius: var(--blok-space-3);
  box-shadow:
    0 0 0 1px var(--blok-image-lightbox-toolbar-ring),
    0 4px 24px var(--blok-image-lightbox-toolbar-shadow-main),
    0 16px 40px -8px var(--blok-image-lightbox-toolbar-shadow-ambient);
  cursor: default;
  z-index: 1;
}
.blok-image-lightbox__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: var(--blok-space-2);
  color: inherit;
  cursor: pointer;
  font: inherit;
  transition: background 80ms ease, color 80ms ease;
}
.blok-image-lightbox__btn[disabled] {
  opacity: 0.35;
  cursor: default;
  pointer-events: none;
}
.blok-image-lightbox__nav {
  position: absolute;
  left: 24px;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--blok-space-1);
  padding: var(--blok-space-1-5);
  background: var(--blok-image-lightbox-toolbar-bg);
  color: var(--blok-image-lightbox-toolbar-fg);
  border-radius: var(--blok-space-3);
  box-shadow:
    0 0 0 1px var(--blok-image-lightbox-toolbar-ring),
    0 4px 24px var(--blok-image-lightbox-toolbar-shadow-main),
    0 16px 40px -8px var(--blok-image-lightbox-toolbar-shadow-ambient);
  cursor: default;
  z-index: 1;
}
