/* Shared editor styles for every Blocksify block. Enqueued by blocksify.php
   on enqueue_block_assets so the stylesheet reaches inside the block editor
   iframe (WP 6.5+ renders blocks in an iframe and enqueue_block_editor_assets
   only loads into the outer admin page).

   Accent color flows through a CSS variable (--blocksify-accent). Shared
   rules read from the variable; block-specific CSS changes the accent for
   its block by setting the variable at the block's own class scope. This
   side-steps specificity wars with core block-editor styles — shared rules
   can use plain selectors (high enough specificity to beat core) without
   blocking per-block color overrides. */

/* ─────────────────────────────────────────────────────────────────────────
   Layer 0 — Design tokens (Inspector chrome).

   Primitives + chrome read these via var() with fallbacks matching the
   baseline byte-for-byte. User-level retheming (or Phase 4 composite
   consistency) flows through this single :root block; individual
   primitives never redefine these values, only consume them. Frontend
   (future Form block) gets its own namespace --blocksify--form-field-*,
   never reuse these Inspector tokens.

   Two token families:
   - field-*  → Inspector form-field visuals (input, select, segmented,
                swatch, numeric, dimension, …). 26-32px bordered surfaces.
   - panel-*  → Inspector surface chrome (popover body, card, bordered
                section). Larger radius, no fixed height.
   ───────────────────────────────────────────────────────────────────── */
:root {

	/* Field — color */
	--blocksify--field-bg: #fff;
	--blocksify--field-bg-disabled: #f0f0f0;
	--blocksify--field-text: #1e1e1e;
	--blocksify--field-text-disabled: #8c8f94;
	--blocksify--field-border: #949494;
	/* Softer border — matches WP core's `__experimentalToggleGroupControl`
	   (Button block Width / Font Size selector). Used by SegmentedControl
	   outer + dividers and other places that want the WP-core minimalist
	   feel instead of the louder `--field-border` (#949494). */
	--blocksify--field-border-soft: #dddddd;
	--blocksify--field-surface: #f5f5f5;

	/* No Blocksify-layer token for focus/hover border — components
	   reference `var(--wp-admin-theme-color, #3858e9)` directly. Earlier
	   attempts piped through an intermediate token + chained
	   --wp-components-color-accent, but the components-accent var gets
	   set to a fixed indigo in some WP contexts and shadowed the
	   admin-scheme color. Direct admin-theme-color ref keeps Blocksify
	   primitives in lockstep with WP's native controls. Fallback #3858e9
	   matches @wordpress/base-styles default. */

	/* Field — dimension */
	--blocksify--field-height: 32px;
	--blocksify--field-height-sm: 28px;
	--blocksify--field-radius: 3px;
	--blocksify--field-padding-x: 8px;

	/* Button — taller than fields (32px vs 26px) so action CTAs have a
	   clearer tap target than inline form inputs. Pairs with fields in
	   composite layouts where a Save/Apply button sits below field rows
	   (modal footer, Popover action) rather than inline at 26px rhythm. */
	--blocksify--button-height: 32px;

	/* Surface — elevated / rounded container chrome (popover, card,
	   bordered section, placeholder). "Surface" chosen over "panel"
	   because WP's PanelBody owns the "panel" term for the collapsible
	   settings sections inside block Inspector — tokens using that
	   prefix would read as PanelBody styling, which isn't the case. */
	--blocksify--surface-radius: 4px;

	/* Rhythm */
	--blocksify--stack-gap: 12px;
	--blocksify--inline-gap: 4px;

	/* Icon */
	--blocksify--icon-size: 18px;
	--blocksify--icon-btn-size: 28px;

	/* Type */
	--blocksify--text-label: 12px;
	--blocksify--text-body: 12px;
	--blocksify--text-weight: 500;

	/* Tracking highlight — soft amber wash painted in transient editor
	   feedback overlays (gap zones during slider hover, future
	   padding / margin zones, etc). One token so the tint stays
	   coordinated with the section's `--blocksify-accent` family
	   without forcing per-overlay color literals. Adjust here to
	   re-tune every tracking surface at once. */
	--blocksify--tracking-color: rgba(245, 166, 35, 0.18);

	/* Muted text — used by primitives + chrome for inactive / secondary
	   labels (PresetSlider numeric input placeholder, StylingRepeater
	   empty-row hint, etc). Promoted to a shared token on the second
	   consumer per FOUNDATION §5.2 "tokenize when shared across
	   components". Inspector chrome default is WP admin's #757575
	   neutral — matches existing primitive baselines byte-for-byte. */
	--blocksify--text-muted: #757575;
}

/* Global chrome accent — declared on the canvas body (NOT :root) so the
   var() re-resolves --wp-admin-theme-color to the value WP's own block
   selection outline uses (#3858e9 on .editor-styles-wrapper), not the
   html-level value (#007cba). A :root declaration would freeze the
   html-level resolution and inherit it down, leaving the add-block button
   a different blue than the selection outline. Declaring here keeps the
   add-block button + selection outlines in lockstep with WP's editor
   accent. The Settings sidebar lives in the OUTER admin page (not this
   iframe) and redeclares the token in settings/style.css. */
.editor-styles-wrapper {
	--blocksify-primary: var(--wp-admin-theme-color, #3858e9);
}

/* ─────────────────────────────────────────────────────────────────────────
   Layer 0.5 — Control baselines.

   Utility classes that lock the "bordered form-field shell" composition
   across primitives. A primitive's own CSS owns its specific layout
   (grid template, child placement, internal dividers); the shared look
   (height, border, radius, bg, hover/focus treatment) lives here so 5+
   primitives can't drift into five-different-shell-heights. Tokens feed
   these rules; utilities feed the primitives.

   Accessibility (WCAG 2.1 AA target):
   - 2.4.7 Focus Visible: :focus-within promotes the shell border to the
     admin theme color, giving a visible indicator on every focused field.
   - 1.4.11 Non-text Contrast: admin theme color on white shell bg
     clears the 3:1 ratio.
   - Hover gets the SAME visual as focus so mouse + keyboard users get
     a consistent signal; :focus-within still wins for a11y because it
     fires on keyboard nav alone (hover never triggers without pointer).
   No outline rings, no box-shadow focus; border-color change is the
   single indicator across the whole Inspector. */

.bsy-field-shell {
	height: var(--blocksify--field-height, 26px);
	border: 1px solid var(--blocksify--field-border, #949494);
	border-radius: var(--blocksify--field-radius, 2px);
	background: var(--blocksify--field-bg, #fff);
	color: var(--blocksify--field-text, #1e1e1e);
	transition: border-color 120ms ease;
}

/* Defeat WP admin's forms.css `input[type="number"] { min-height: 30px }`
   (and equivalents on select / textarea). WP's selector is specificity
   (0,1,1) — our `.bsy-field-shell` alone is (0,1,0) so WP wins on
   min-height and forces 30px, which breaks the 26px field-shell rhythm.
   Element-prefixed override ties at (0,1,1) and we load after WP, so we
   win on cascade. min-height: 0 lets the explicit height: 26px above
   take effect. */
input.bsy-field-shell,
select.bsy-field-shell,
textarea.bsy-field-shell {
	min-height: 0;
}

/* overflow is NOT on the shell — it's a per-primitive concern. Compounds
   with inner dividers that cross the rounded outer radius (SegmentedControl
   options, DimensionField inner slot border) add their own `overflow: hidden`
   in their primitive CSS. Primitives with a single native element
   (NumericField input, UnitSelect select, future TextField) must NOT clip —
   native input vertical sizing + focus rings would be cut off. */

.bsy-field-shell:hover:not(.is-disabled) {
	border-color: var(--wp-admin-theme-color, #3858e9);
}

/* Focus ring matches WP core's `controlBoxShadowFocus` exactly: border 1px
 * + box-shadow 0 0 0 0.5px = 1.5px effective ring (NOT 2px — verify in
 * `@wordpress/components/build-module/utils/config-values.mjs`). The
 * 0.5px is sub-pixel emphasis on top of the 1px border-color change so
 * focused fields read as slightly stronger than hover (which is just
 * border-color, no shadow). Outline transparent + offset for Windows
 * High Contrast mode visibility (WHCM ignores box-shadow but renders
 * outlines). */
.bsy-field-shell:focus-within:not(.is-disabled) {
	border-color: var(--wp-admin-theme-color, #3858e9);
	box-shadow: 0 0 0 0.5px var(--wp-admin-theme-color, #3858e9);
	outline: 2px solid transparent;
	outline-offset: -2px;
}

.bsy-field-shell.is-disabled {
	opacity: 0.5;
	pointer-events: none;
}

/* Multiline modifier — relaxes the fixed single-line height so textareas
   (or any future auto-grow field) can span multiple rows. min-height keeps
   the baseline rhythm at one field-height so a 1-line textarea still lines
   up with single-line siblings; content beyond grows the field vertically
   (or the native textarea resize grip, if the primitive allows it). */
.bsy-field-shell--multiline {
	height: auto;
	min-height: var(--blocksify--field-height, 26px);
}

/* Block icon color used in List View, inserter card, Document Overview,
   toolbar. Uses WP's user-configurable admin theme color (`#3858e9`
   default) so Blocksify blocks read as native WordPress blocks in the
   inserter library — following the user's chosen admin scheme rather
   than a fixed brand color. Selected/highlighted rows flip to inherit
   so the row's own color (usually white on dark bg) wins. */
.bsy-block-icon {
	color: var(--wp-admin-theme-color, #3858e9);
}

.is-selected .bsy-block-icon,
[aria-selected="true"] .bsy-block-icon,
.is-highlighted .bsy-block-icon {
	color: inherit;
}

/* Outline-style block icons (Container, Icon, Content Loop) declare
   `fill="none"` on the outer svg + `stroke="currentColor"` so they
   render as stroke-only. WP / Gutenberg's CSS for block-icon contexts
   (e.g. `.block-editor-block-icon svg { fill: currentColor }`) overrides
   our attribute-level declaration because presentation attributes have
   lower specificity than author CSS. Re-assert `fill: none` for svgs
   that explicitly opt in via the `fill="none"` attribute, plus their
   direct path / circle / line / rect / polygon children that inherit
   the fill from the svg. */
.bsy-block-icon[fill="none"],
.bsy-block-icon[fill="none"] > * {
	fill: none;
}

/* Toolbar action icons shipped as outline (fill="none") — e.g.
   WrapInContainer's "Add to Container". Two differences from
   `.bsy-block-icon`:
   1. No always-on brand color. A toolbar ACTION button should read with
      the toolbar's own icon color (dark `#1e1e1e` idle) like every other
      action (bold, italic, …), NOT a permanent brand-blue that makes it
      look perpetually "active". Color shifts to the WP theme color only
      on hover / keyboard focus, matching native toolbar affordance feel.
   2. Same fill="none" re-assertion (WP forces fill:currentColor on
      toolbar button svgs). */
.bsy-toolbar-icon[fill="none"],
.bsy-toolbar-icon[fill="none"] > * {
	fill: none;
}

.components-button:hover .bsy-toolbar-icon,
.components-button:focus-visible .bsy-toolbar-icon {
	color: var(--wp-admin-theme-color, #3858e9);
}

/* Default accent for every Blocksify block, plus per-block overrides. Kept
   here (not in each block's own editor.css) so the shared rules that read
   the variable and the rules that set it land in the same stylesheet — no
   load-order flicker between a block's CSS and this file. Anchored on
   the WP auto-injected `wp-block-blocksify-` class so the variable
   reaches every block wrapper regardless of whether its save markup
   carries a `bsy-*` class on the outer (Button / Icon / Image have a
   bare outer; Section / Container / Text have `bsy-{name}-{uid}`).
   Descendants inherit the variable via the cascade. Add a new entry
   only when a block needs a non-default accent. */
[class*="wp-block-blocksify-"] {
	/* Follow the user's WP admin color scheme (Users → Profile → Admin
	   Color Scheme); fall back to Blocksify blue when the var is absent
	   (non-admin context / old WP). Editor-only — the wp-block-blocksify-
	   class is stripped on the frontend. */
	--blocksify-accent: var(--wp-admin-theme-color, #3858e9);
}

.wp-block-blocksify-section {
	--blocksify-accent: #f5a623;
}

/* Positioning context for the absolute label badge and any block-specific
   absolute children (resize handles, appender buttons). Editor-only — the
   frontend CSS leaves this alone to avoid creating stacking contexts that
   would sandbox third-party child blocks. Covers BOTH the outer block
   wrapper (matched via WP's auto-injected `wp-block-blocksify-`, since
   Button/Icon/Image outer save markup has no `bsy-*` class) AND inner
   BEM elements (matched via `bsy-`) like `bsy-section__inner` or
   `bsy-icon__inner` that host absolute resize handles / appenders. */
:where([class*="wp-block-blocksify-"], [class*="bsy-"]) {
	position: relative;
}

/* Default hover / selected outline. Anchor on `wp-block-blocksify-` —
   the class WP auto-injects on every block's editor wrapper regardless
   of `supports.className: false` — so the rule fires even on blocks
   whose outer save-markup wrapper has no `bsy-*` class (Button, Icon
   outer, Image outer). Pairing `.wp-block` with the attribute selector
   gives specificity 0,3,0 — enough to beat core's
   `.block-editor-block-list__block.is-selected` (0,2,0) without
   relying on load order inside the iframe. !important on outline and
   box-shadow is belt-and-suspenders in case core ever ships !important
   on the same properties. box-shadow: none clears core's thick
   selection glow so only our 1px outline reads as the block edge.
   ::after: none kills any core pseudo-element used to draw the selected
   frame (some WP versions use ::after instead of box-shadow). */
.wp-block[class*="wp-block-blocksify-"]:hover,
.wp-block[class*="wp-block-blocksify-"].is-hovered,
.wp-block[class*="wp-block-blocksify-"].is-selected {
	outline: 1px solid var(--blocksify-accent) !important;
	outline-offset: -1px !important;
	transition: outline 120ms;
}

/* `box-shadow: none !important` clears core's thick selection glow so only
   our 1px outline reads as the block edge. The `:not(.has-bsy-shadow)`
   guard preserves the user's authored Box Shadow on selected/hovered
   sections — otherwise composite-emitted `box-shadow:` per-instance CSS
   gets killed exactly when the user clicks the section to author it. WP's
   selection glow is suppressed here regardless; the user's shadow draws
   from the per-instance class rule injected by `<style>` inside the block. */
.wp-block[class*="wp-block-blocksify-"]:hover:not(.has-bsy-shadow),
.wp-block[class*="wp-block-blocksify-"].is-hovered:not(.has-bsy-shadow),
.wp-block[class*="wp-block-blocksify-"].is-selected:not(.has-bsy-shadow) {
	box-shadow: none !important;
}

.wp-block[class*="wp-block-blocksify-"].is-selected::after,
.wp-block[class*="wp-block-blocksify-"].is-hovered::after {
	content: none !important;
}

/* Tab-style label badge floating just above the top-left edge. Text comes
   from data-blocksify-label set in each block's edit.js via the blockLabel()
   helper (see src/shared/helpers.js). Hidden on selected — WP's block
   toolbar already shows the block name and the two would visually collide.

   Anchored on `wp-block-blocksify-` (WP auto-injects this on every
   Blocksify block's editor wrapper) so the rule reliably matches every
   outer wrapper, including blocks whose save markup has no `bsy-*`
   class (Button outer, Icon outer, Image outer wrappers). Inner BEM
   elements like `bsy-button__text` / `__link` / `__icon` don't carry
   `wp-block-blocksify-`, so the substring matcher leaves them alone —
   no stray `::before` rectangles painted on `attr(data-blocksify-label)
   = ''` placeholders. */
.wp-block[class*="wp-block-blocksify-"]:hover::before,
.wp-block[class*="wp-block-blocksify-"].is-hovered::before {
	content: attr(data-blocksify-label);
	position: absolute;
	top: 0;
	left: 0;
	transform: translateY(-100%);
	background: var(--blocksify-accent);
	color: #fff;
	font-size: 11px;
	line-height: 1.5;
	padding: 1px 6px;
	border-radius: 3px 3px 0 0;
	white-space: nowrap;
	pointer-events: none;
	z-index: 10;
}

.wp-block[class*="wp-block-blocksify-"].is-selected::before {
	content: none;
}

/* Cascade suppression — hide the outline + badge on a Blocksify block when
   the real interaction is happening in something nested inside it:
   - a Blocksify descendant being hovered (nested layout case: hovering a
     Container shouldn't also light the Section around it)
   - a descendant that's selected AND hovered (editing case: pointer sitting
     on the active edit surface of an inner block)
   Pairing .is-selected with :hover on the descendant is deliberate — once
   the user moves the pointer off the edited block into the parent's own
   padding, the parent's chrome should come back so hover remains a useful
   navigation signal.
   :not(.is-selected) on the outer block preserves the selection outline:
   once a user has clicked a Section, the amber frame should stay anchored
   regardless of where the pointer drifts inside — mousing into a Container
   must not visually drop the selected block's edge. outline-style: none
   with !important is needed because the default rule above uses !important
   too (to beat core). `.wp-block` constraint mirrors the badge rule above:
   only block wrappers count as "Blocksify descendants" for cascade
   suppression — inner BEM spans hovering shouldn't suppress their parent
   block's chrome. */
.wp-block[class*="wp-block-blocksify-"]:not(.is-selected):has(
.wp-block[class*="wp-block-blocksify-"]:hover,
.wp-block[class*="wp-block-blocksify-"].is-hovered,
.is-selected:hover
) {
	outline-style: none !important;
}

.wp-block[class*="wp-block-blocksify-"]:not(.is-selected):has(
.wp-block[class*="wp-block-blocksify-"]:hover,
.wp-block[class*="wp-block-blocksify-"].is-hovered,
.is-selected:hover
)::before {
	content: none;
}

/* Inspector tabs — icon-above-label tabs that sit at the top of every
   Blocksify block's Inspector. The wrapper is rendered by TabPanel, which
   emits <div class="components-tab-panel__tabs"> for the tab strip and
   <div class="components-tab-panel__tab-content"> for the panel body. We
   scope everything to .bsy-inspector-tabs so these rules don't reach
   other TabPanels WP renders elsewhere.

   `grid-auto-flow: column; grid-auto-columns: 1fr` — tabs partition the
   row equally regardless of count. Phase 4 dropped the 3rd "Advanced"
   tab (consolidated into General); this rule handles 2-tab cleanly
   without a hardcoded count. Future blocks with different tab counts
   work without CSS changes. */
.bsy-inspector-tabs > .components-tab-panel__tabs {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 1fr;
	border-top: 1px solid #e0e0e0;
	border-bottom: 1px solid #e0e0e0;
}


/* Each tab is its own bordered cell — vertical dividers between tabs give a
   segmented look, with the active tab marked by a solid bottom color. The
   right border is placed on every tab and cleared on the last one, so the
   grid's final cell doesn't push a divider past the sidebar edge.
   !important beats core's `.components-tab-panel__tabs-item` styles (0,2,0)
   that would otherwise fight our rules at the same specificity. */
.bsy-inspector-tabs__tab {
	height: auto !important;
	padding: 10px 4px !important;
	border-radius: 0 !important;
	background: transparent !important;
	color: var(--blocksify--field-text, #1e1e1e) !important;
	box-shadow: none !important;
	border-right: 1px solid #e0e0e0;
	border-bottom: 2px solid transparent;
	margin-bottom: -1px;
}

.bsy-inspector-tabs__tab:last-child {
	border-right-color: transparent;
}

/* Active tab: keep text + icon at the default color, signal active state
   via the bottom-border underline only. Border color follows the WP admin
   theme color so it matches the rest of the editor's interactive accents
   (buttons, slider thumbs, focus rings). */
.bsy-inspector-tabs__tab.is-active {
	border-bottom-color: var(--wp-admin-theme-color, #3858e9);
}

/* Kill core TabPanel's own active-state indicator (rendered via ::after on
   .components-tab-panel__tabs-item.is-active). Ours lives on the element's
   border so any core pseudo would double up. */
.bsy-inspector-tabs__tab::after,
.bsy-inspector-tabs__tab::before {
	content: none !important;
	display: none !important;
}

.bsy-inspector-tabs__label {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--blocksify--inline-gap, 4px);
	width: 100%;
	font-size: 12px;
	line-height: 2;
}

.bsy-inspector-tabs__label svg {
	fill: currentcolor;
}

/* The tab strip already owns the horizontal divider below the tabs; the
   first PanelBody in the active tab renders its own border-top by default
   and the two would stack into a visible double line. Suppress the panel
   border only for the first child so subsequent PanelBodies keep their
   separator. */
.bsy-inspector-tabs__panel > .components-panel__body:first-child {
	border-top: none;
}

/* PanelBody header polish — two UX fixes against WP defaults:
   1. Focus ring only on keyboard nav. `:focus-visible` is the modern
      UA distinction; mouse clicks no longer flash a blue outline,
      but Tab still shows it (WCAG 2.4.7 keyboard nav preserved).
   2. No background on the title row when panel is already open. WP's
      `.components-panel__body > .components-panel__body-title:hover`
      paints `rgb(240, 240, 240)` on the H2 wrapper (NOT the button
      inside) — match the same selector with `.is-opened` to override.
      The bg signals "click to expand"; once content is visible the
      cue is redundant. Closed state keeps it so the affordance
      survives. Cursor + label color change still satisfy a11y. */
.components-panel__body-toggle.components-button:focus:not(:focus-visible) {
	box-shadow: none;
}
.components-panel__body.is-opened > .components-panel__body-title:hover,
.components-panel__body.is-opened > .components-panel__body-title:focus-within {
	background: transparent;
}

/* Block visibility editor treatment — when the active device matches a
   `Hide on {device}` toggle in the Visibility panel, the block on canvas
   gets a diagonal striped overlay + dim. The class is added by each
   block's edit.js when `isHiddenAtDevice(visibility, activeDevice)`
   returns true (`src/shared/helpers.js`). Frontend `display: none` is
   handled separately by per-instance @media rules emitted from
   `Blocksify_CSS_Generator`. The pattern (stripe angle, opacity, color)
   matches Spectra's `.spectra-responsive-hidden` so the visual cue is
   familiar to switchers. Stripes use a transparent-on-transparent
   gradient so any block background still shows through behind the
   stripe pattern. */
.is-hidden-at-this-device {
	background:
		repeating-linear-gradient(
			125deg,
			rgba(0, 0, 0, 0.05),
			rgba(0, 0, 0, 0.05) 1px,
			transparent 2px,
			transparent 9px
		);
	opacity: 0.4;
}

/* Visibility panel help text — sits below the 3 ToggleControls. Subtle
   gray to match WP's `.components-base-control__help` rhythm without
   pulling in the BaseControl wrapper. */
.bsy-visibility__help {
	margin: 8px 0 0;
	font-size: 12px;
	font-style: normal;
	color: #757575;
}

/* Generic hover-mode dim utility — apply to any plain control that
   doesn't have its own per-device infrastructure (ToggleControl,
   loose RangeControl, etc). Mirrors the dim treatment ResponsiveField
   self-applies via `.is-hover-mode.does-not-support-hover` so the
   visual is consistent across both.

   Same pointer-events split: root catches mouseenter (so a Tooltip
   wrapper around it can fire) while descendants block click /
   keystrokes. Cursor `not-allowed` for the visual cue. */
.bsy-disabled-in-hover {
	opacity: 0.45;
	cursor: not-allowed;
}

.bsy-disabled-in-hover * {
	pointer-events: none;
}

/* Placeholder state for tabs with no controls yet (e.g. Advanced before its
   controls are built). Kept low-contrast so the empty tab doesn't compete
   with populated ones. */
.bsy-inspector-empty {
	padding: 24px 16px;
	color: #757575;
	font-size: 12px;
	font-style: italic;
	text-align: center;
}

/* Layout utilities — shared section layouts for composite controls.
   Composites that need non-trivial section layouts (multi-column, grid,
   stack with standard gap) compose via className instead of authoring
   one-off CSS. Values pull from the Phase 3 design-token layer so rhythm
   stays consistent across controls. */

.bsy-layout-stack {
	display: flex;
	flex-direction: column;
	gap: var(--blocksify--stack-gap, 12px);
}

.bsy-layout-grid-2 {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--blocksify--stack-gap, 12px);
}

/* Background-video editor placeholder — replaces the live YouTube
 * iframe in the editor canvas to avoid YouTube Error 153 (player
 * config error inside nested iframes). Renders the video's hqdefault
 * thumbnail with a "▶ YouTube" badge so the editing user knows which
 * clip is wired up. Frontend renders the real iframe (no nesting,
 * no error). Editor-only CSS — frontend doesn't ship this class. */
.bsy-bg-video--placeholder {
	background-color: #1e1e1e;
}

.bsy-bg-video__badge {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	padding: 6px 12px;
	background: rgba(0, 0, 0, 0.7);
	color: #fff;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.02em;
	border-radius: 4px;
	pointer-events: none;
}

/* Topbar hover-mode indicator — persistent pill in the editor header that
   surfaces hover-mode state when the Inspector sidebar is collapsed.
   Inspector picker + banner are the primary affordance; this is the
   secondary echo so closing the sidebar doesn't leave the canvas frozen
   with no exit hint.

   Imperatively mounted via createRoot from HoverModeTopbarIndicator
   chrome. Styled here (not in the chrome's own editor.css) because
   wp-scripts root entries don't bundle JS-imported editor CSS — only
   block entries do. editor-common.css is the established escape hatch
   PHP enqueues directly via enqueue_block_assets. */
.bsy-hover-mode-topbar-mount {
	display: inline-flex;
	align-items: center;
	margin-right: 12px;
}

/* Topbar indicator: pill (informational, not clickable) + separate close
 * button on the right. Pill carries the educational tooltip; close button
 * is the only "exit hover mode" affordance to avoid accidental toggles
 * from clicking near the pill. */
.bsy-hover-mode-topbar-indicator {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	font-size: 12px;
	color: #50575e;
	line-height: 1;
	user-select: none;
}

.bsy-hover-mode-topbar-indicator__pill {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	cursor: default;
	outline: none;
}

.bsy-hover-mode-topbar-indicator__pill:focus-visible {
	box-shadow: 0 0 0 2px var(--wp-admin-theme-color, #3858e9);
	border-radius: 2px;
}

.bsy-hover-mode-topbar-indicator__close {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	height: 22px;
	padding: 0;
	border: 0;
	border-radius: 4px;
	background: transparent;
	color: #50575e;
	cursor: pointer;
	transition: background 120ms ease, color 120ms ease;
}

.bsy-hover-mode-topbar-indicator__close:hover {
	background: rgba(0, 0, 0, 0.06);
	color: var(--wp-admin-theme-color, #3858e9);
}

.bsy-hover-mode-topbar-indicator__close:focus-visible {
	outline: 2px solid var(--wp-admin-theme-color, #3858e9);
	outline-offset: -1px;
}

.bsy-hover-mode-topbar-indicator__dot {
	display: inline-block;
	width: 8px;
	height: 8px;
	flex-shrink: 0;
	border-radius: 50%;
	background: var(--wp-admin-theme-color, #3858e9);
	animation: blocksify-hover-mode-topbar-pulse 1.6s ease-in-out infinite;
}

@keyframes blocksify-hover-mode-topbar-pulse {

	0%,
	100% {
		opacity: 0.6;
		transform: scale(1);
	}

	50% {
		opacity: 1;
		transform: scale(1.2);
	}
}

@media (prefers-reduced-motion: reduce) {

	.bsy-hover-mode-topbar-indicator__dot {
		animation: none;
	}
}

/* =====================================================================
 * Inspector chrome — cross-block opt-in patterns
 *
 * These classes normalize WP-supplied UI (LinkControl, ToggleControl
 * stacks) so any Blocksify block's inspector picks up the project's
 * field-shell visual baseline + tighter rhythm. Block authors opt in
 * by adding the relevant class to their PanelBody / wrapper div.
 * ===================================================================== */

/* `.bsy-panel-link-control` — opt-in on a PanelBody that mounts
 * `__experimentalLinkControl`. Strips WP's default insets so the
 * control sits flush with adjacent rows; restyles the input base to
 * use --blocksify--field-* tokens (matches TextField / NumericField /
 * Select primitive baseline). Chip-preview sub-elements truncate URLs
 * with ellipsis instead of pushing the panel width. */
.bsy-panel-link-control .block-editor-link-control,
.bsy-panel-link-control .block-editor-link-control__search-input-wrapper,
.bsy-panel-link-control .block-editor-link-control__search-input-container,
.bsy-panel-link-control .block-editor-link-control__field,
.bsy-panel-link-control .block-editor-url-input,
.bsy-panel-link-control .components-base-control,
.bsy-panel-link-control .components-base-control__field,
.bsy-panel-link-control .components-input-control,
.bsy-panel-link-control .components-input-control__container {
	padding: 0;
	margin: 0;
	/* WP ships hardcoded `min-width: 300px` on `.block-editor-link-control__field`
	 * for popover usage. In our 248px-wide inspector panel that pushes the
	 * input chain past the panel right edge by ~50px. Reset everywhere in
	 * the chain so the deepest element (input) shrinks to fit parent width.
	 * Only zeroing margin/padding + width constraints — DON'T touch
	 * border / background, otherwise the input loses WP's default visual
	 * (input border lives on the `<input>` element itself, not on the
	 * wrapper chain). */
	min-width: 0;
	max-width: 100%;
	box-sizing: border-box;
}

/* Apply Blocksify field-shell visual to `.components-input-base` (the
 * WP wrapper that draws the input border + bg). Mirrors the
 * `.bsy-field-shell` utility from this file's primitive section
 * so the Link input reads identical to a Blocksify TextField /
 * NumericField. We chain `.components-panel__body` (the PanelBody root
 * that carries our `blocksify-panel-link-control` className) to push
 * specificity to (0,3,0) — beats WP's Emotion class (0,1,0) plus any
 * (0,2,0) chained rules WP ships, without needing `!important`. */
.components-panel__body.bsy-panel-link-control .components-input-base {
	height: var(--blocksify--field-height, 32px);
	min-height: var(--blocksify--field-height, 32px);
	border-radius: var(--blocksify--field-radius, 3px);
	background: var(--blocksify--field-bg, #fff);
	box-shadow: none;
}

/* Input element — `!important` ONLY on `height` + `min-height`. WP
 * ships those two via a TRIPLE-CHAINED Emotion class
 * (`.aed-fbb-c-e-cbbd-onxfbl.aed-fbb-c-e-cbbd-onxfbl.aed-fbb-c-e-cbbd-onxfbl`)
 * giving specificity (0,3,0) — ties with our (0,3,0) selector and WP's
 * stylesheet loads later, so without `!important` they win by source
 * order and the input stays at 40px (clipping the visible 32px field).
 * The other size constraints (min-width / max-width / width / box-sizing)
 * win cleanly by specificity alone — no `!important` needed. */
.components-panel__body.bsy-panel-link-control .components-input-control__input {
	height: calc(var(--blocksify--field-height, 32px) - 2px) !important;
	min-height: 0 !important;
	min-width: 0;
	max-width: 100%;
	width: 100%;
	box-sizing: border-box;
}

/* Chip preview — when URL is set, LinkControl renders the URL as a
 * `__search-item.is-current` "chip" with edit / unlink / copy actions.
 * WP's default has 16px left + right padding which indents the chip
 * inward from the panel content edge, leaving the icon misaligned
 * with the toggles below. Reset to flush with panel padding so the
 * chip's globe icon aligns vertically with the toggle dots. Targeting
 * `.is-current` modifier (NOT bare `__search-item`) so we don't
 * affect the suggestion-list items underneath, which legitimately
 * use that padding for clickable rows. */
.bsy-panel-link-control .block-editor-link-control__search-item.is-current {
	padding-left: 0;
	padding-right: 0;
	padding-top: 10px;
	padding-bottom: 10px;
}

.bsy-panel-link-control .block-editor-link-control__search-item-icon {
	border-radius: 100px;
}

/* Submit / clear / suffix buttons inside the input keep matching
 * height so they align with the wrapper. */
.bsy-panel-link-control .components-input-control__suffix button,
.bsy-panel-link-control .block-editor-link-control__search-submit {
	min-height: 0;
	height: calc(var(--blocksify--field-height, 32px) - 2px);
}

/* Apply / Cancel button row (rendered by LinkControl below the input
 * when in edit mode). Tighten the top padding so the action row sits
 * close to the input field. */
.bsy-panel-link-control .block-editor-link-control__search-actions {
	padding: 8px 0 0;
}

/* Suggestions dropdown — when LinkControl is used standalone (vs inside
 * a Popover) WP doesn't ship card styling for the results list. In our
 * inspector context that produces a transparent flush-left list with
 * no visual separation from the panel content above. Add a card visual
 * (Blocksify field-shell tokens) so the dropdown reads as an elevated
 * results panel.
 *
 * Important: only target `__search-results-wrapper` (the OUTER list
 * container). Don't touch `__search-item` (used for both chip preview
 * AND individual suggestion items — overriding them broke the items'
 * internal title + path + badge layout in earlier iterations). */
.bsy-panel-link-control .block-editor-link-control__search-results-wrapper {
	background: var(--blocksify--field-bg, #fff);
	border: 1px solid var(--blocksify--field-border, #949494);
	border-radius: var(--blocksify--field-radius, 3px);
	margin-top: 3px;
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
	overflow: hidden;
}

.bsy-panel-link-control .block-editor-link-control__search-results-wrapper .block-editor-link-control__search-results {
	margin-top: 0;
	padding: 8px;
}

/* `.bsy-toggle-stack` — opt-in wrapper for sequential
 * `<ToggleControl>`s where WP's default 16px marginBottom reads as too
 * loose for related grouped toggles (e.g. "Open link in a new tab" /
 * "rel=nofollow" / "rel=sponsored" — all part of the same link-attribute
 * cluster). 8px gap is the sweet spot — tighter than WP's 16px (which
 * reads as "unrelated rows"), looser than the 4px we tried first
 * (which read as "no breathing room"). WP's `__nextHasNoMarginBottom`
 * prop is unreliable across versions; CSS scoping gives a stable
 * result regardless. */
.bsy-toggle-stack > .components-toggle-control {
	margin-bottom: 8px;
}

.bsy-toggle-stack > .components-toggle-control:last-child {
	margin-bottom: 0;
}

/* `.bsy-field-section` — label-above-field pair without WP's
 * `BaseControl` wrapper (which adds 3 nested div/span layers + emotion
 * styles that fight Blocksify field-shell). Pairs `<ControlLabel>` with
 * the field below at a tight 4px gap; designed to nest inside a
 * `.bsy-layout-stack` so adjacent sections get the standard 12px
 * outer gap.
 *
 * Uses `.bsy-field-control-label` direct-child margin since
 * `ControlLabel` itself is `display: inline-flex` and doesn't carry a
 * default bottom margin (primitives don't dictate spacing). */
.bsy-field-section > .bsy-field-control-label {
	margin-bottom: 4px;
}

/* ─────────────────────────────────────────────────────────────────────────
   BlockRoot wrapper + Container-child margin override.

   Top-level Blocksify blocks use the `BlockRoot` chrome component
   (`src/shared/chrome/BlockRoot/`) which renders an outer `<div
   class="wp-block bsy-block-root">` ONLY when the block is at root
   level (no parent block). The wrapper carries `wp-block` so it picks
   up WP's content-column treatment via
     `.editor-styles-wrapper :where(:not(.is-layout-flex,.is-layout-grid))
        > .wp-block { margin-inline: auto }`
   That centers the wrapper inside `is-root-container`'s content-size
   max-width box, so the inner block element (still wrapper-less by
   default) sits at content-column-LEFT instead of canvas-LEFT.

   `.bsy-block-root` carries no visual styling — wrapper is layout-only.
   Margin-block reset prevents stacking with adjacent block margins
   (the inner block's WP rules already supply the rhythm).

   For blocks NESTED inside a Blocksify Container, the same WP
   auto-margin rule would apply to the inner block (Container is not
   `is-layout-flex`, our flex implementation is per-instance CSS, not
   WP layout machinery). On flex children, `margin-inline: auto`
   consumes free space → buttons get pushed off flex-start. The
   override below zeros margin-inline for direct children of any
   Blocksify Container. Specificity (0,2,0) — equal to WP's rule,
   source order wins. User Spacing-trait margin emit lands per-instance
   at (0,2,0) doubled, source-orders later via inline `<style>`, so
   explicit user margins still win.
   ───────────────────────────────────────────────────────────────────── */
.bsy-block-root {
	margin-block: 0;
	position: relative;
}

.editor-styles-wrapper [class*="bsy-container-"] > .wp-block {
	margin-left: 0;
	margin-right: 0;
}

/* ─────────────────────────────────────────────────────────────────────────
   IconToolbarButton chrome — preview slot fill-none override.

   The `<IconToolbarButton>` chrome (src/shared/chrome/IconToolbarButton/)
   renders the picked icon inside the WP `<ToolbarButton>` icon slot.
   Outline icons (Lucide etc.) carry `fill="none"` as an SVG presentation
   attribute, but WP's `.components-button.is-pressed svg` rule applies
   `fill: currentColor`, which beats the attribute (CSS > attribute) AND
   strips inline `style="fill:none"` that JS tries to inject (React's
   `cloneElement` through WP's `<Icon>` drops the inline style during
   reconciliation — verified by DOM probe). `!important` is the
   load-bearing override that lets users see picked outline icons as
   actual outlines, not solid silhouettes, while the button is pressed.

   Rule lives here (NOT next to the chrome) because wp-scripts'
   splitChunks cacheGroup only extracts files named `style.css` to the
   per-entry CSS bundle; any other CSS file imported from `src/index.js`
   gets silently dropped from `build/index.css`. `editor-common.css` is
   copied verbatim by `scripts/rename-css.js` and enqueued by
   `blocksify_enqueue_editor_common` on `enqueue_block_assets`, which
   fires both inside the editor iframe AND in the outer admin shell
   where toolbar buttons render — exactly the scope this rule needs.
   ───────────────────────────────────────────────────────────────────── */
.bsy-chrome-icon-toolbar__preview svg,
.bsy-chrome-icon-toolbar__preview svg * {
	fill: none !important;
}
