File: //home/iddeczhh/public_html/wp-content/plugins/extendify/src/QuickEdit/quick-edit.css
@import "tailwindcss" source(none) important;
@import "../tailwind.css" source(none);
@source ".";
@theme {
/* Body-level bars/menus render outside WP admin's font context, so they
need an explicit system UI stack. */
--font-qe:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu,
Cantarell, "Helvetica Neue", sans-serif;
}
/* DOMHighlighter renders one motion.div for both hover preview AND
selected-block X-close. Hover state has `pointer-events: none` inline,
selected state has `auto` — keep the selected rect, hide the hover. */
/* no-prefix */
html.extendify-quick-edit-on #extendify-agent-dom-mount
[style*="pointer-events: none"] {
@apply hidden!;
}
/* Once a block is being edited in Quick Edit, the agent's selected-block
X-close (rendered as a div[role="button"] inside its portal at the cover's
top-center) reads as orphaned — the user moved past the agent's
block-selection step and now owns Cancel via the QE toolbar. Suppress it
while a QE canvas is mounted.
Wrapped in @layer utilities so this `!important` rule competes in the same
layer as the agent bundle's Tailwind `.extendify-agent .flex {
display: flex !important }`. Per the cascade-layer spec, important rules
in any declared layer beat important rules outside layers — without this
wrapping, the layered .flex !important would always win regardless of
selector specificity. */
@layer utilities {
/* no-prefix */
html:has(.extendify-quick-edit-canvas) #extendify-agent-dom-mount
div[role="button"] {
@apply hidden!;
}
}
/* Admin-bar Edit Mode pill. Lives outside our scope wrapper, so
each rule carries a `no-prefix` marker. */
/* no-prefix */
#wpadminbar #wp-admin-bar-extendify-quick-edit-toggle > a.ab-item {
@apply inline-flex! items-center! gap-[8px]!;
}
/* no-prefix */
#wpadminbar
#wp-admin-bar-extendify-quick-edit-toggle
.extendify-quick-edit-toggle-pill {
@apply inline-block! relative! shrink-0! h-[16px]! w-[28px]! rounded-full! bg-[rgba(255,255,255,0.25)]!;
transition: background 0.18s ease !important;
}
/* no-prefix */
#wpadminbar
#wp-admin-bar-extendify-quick-edit-toggle
.extendify-quick-edit-toggle-thumb {
/* Literal color, not bg-white — the theme vars don't reach
#wpadminbar, so var-based utilities silently no-op here. */
@apply absolute! top-[2px]! left-[2px]! h-[12px]! w-[12px]! rounded-full! bg-[#fff]!;
transition: transform 0.18s ease !important;
}
/* On state — pill turns the AI Agent button's blue (not the partner
color), thumb slides right. */
/* no-prefix */
html.extendify-quick-edit-on #wpadminbar
#wp-admin-bar-extendify-quick-edit-toggle
.extendify-quick-edit-toggle-pill {
@apply bg-[#3858e9]!;
}
/* no-prefix */
html.extendify-quick-edit-on #wpadminbar
#wp-admin-bar-extendify-quick-edit-toggle
.extendify-quick-edit-toggle-thumb {
@apply translate-x-[12px]!;
}
/* Ask AI flash — `lib/ask-ai.js#flashSelection` adds the class. */
/* no-prefix */
@keyframes extendify-quick-edit-ask-flash {
0% {
outline-color: rgba(56, 88, 233, 0);
box-shadow: 0 0 0 0 rgba(56, 88, 233, 0);
}
30% {
outline-color: rgba(56, 88, 233, 1);
box-shadow: 0 0 0 6px rgba(56, 88, 233, 0.35);
}
100% {
outline-color: rgba(56, 88, 233, 0);
box-shadow: 0 0 0 0 rgba(56, 88, 233, 0);
}
}
/* no-prefix */
.extendify-quick-edit-ask-flash {
@apply rounded-[4px]! outline-offset-[4px]!;
outline: 3px solid transparent !important;
animation: extendify-quick-edit-ask-flash 1.4s ease-out both !important;
}
/* Above WP admin bar (z 100000). */
#extendify-quick-edit-root {
@apply relative z-[100001];
}
/* The agent's highlighter-mode CSS sets pointer-events: none on
page-wide buttons/links so the selector-tool can capture clicks.
Re-enable them inside our UI surfaces. `html` prefix is required
to win specificity against the agent's `!important` rule.
The canvas inclusion is what keeps the LinkControl popover (and
any other BlockTools-slotted popover) clickable when the agent
sidebar is open — `BlockTools` puts its popover Slot inside the
canvas, so the popover renders inside `.wp-site-blocks`, in the
highlighter-mode scope. */
/* no-prefix */
html .extendify-quick-edit-bar,
html .extendify-quick-edit-bar *,
html .extendify-quick-edit-floating-bar,
html .extendify-quick-edit-floating-bar *,
html .extendify-quick-edit-image-menu,
html .extendify-quick-edit-image-menu *,
html .extendify-quick-edit-canvas,
html .extendify-quick-edit-canvas * {
@apply pointer-events-auto!;
}
/* Restore pointer-events on `.wp-block-button` wrapper divs inside
highlighter-mode. The agent ships a secondary rule (in agent.css) that
drops pointer-events on `.wp-block-button` whenever the parent
`.wp-block-buttons` contains exactly one button:
.extendify-agent-highlighter-mode
.wp-block-buttons:has(> .wp-block-button):not(:has(>
.wp-block-button:nth-of-type(2))) > .wp-block-button
That selector's specificity is (0,6,0) once `:has` / `:not` are scored,
so a plain `html.extendify-quick-edit-on .extendify-agent-highlighter-mode
.wp-block-button` rescue loses the cascade even with !important. Mirror
the same `:has` / `:not` chain to outweigh it; the rescue still fires only
when the agent's rule fires, which is exactly the bug scope.
The inner `<a class="wp-block-button__link">` still has pointer-events:none
from the broader `.extendify-agent-highlighter-mode a` rule, so link-nav
prevention is intact — we only restore the wrapper div so hover/click
targeting resolves to the button via QE's findTagged walk-up. */
/* no-prefix */
html.extendify-quick-edit-on .extendify-agent-highlighter-mode
.wp-block-buttons:has(> .wp-block-button):not(
:has(> .wp-block-button:nth-of-type(2))
)
> .wp-block-button {
@apply pointer-events-auto!;
}
/* Cursor contract for edit mode. Tagged blocks read as selectable
(crosshair); anchors and form controls inside them keep their native
cursors so the click rule (lib/click-rule.js) telegraphs which
branch a click will hit before the user clicks. Scoped to
`html.extendify-quick-edit-on` so cursors don't bleed into normal
browsing. */
/* no-prefix */
html.extendify-quick-edit-on [data-extendify-agent-block-id],
html.extendify-quick-edit-on [data-extendify-part-block-id],
html.extendify-quick-edit-on [data-extendify-quick-edit-product-id],
html.extendify-quick-edit-on [data-extendify-quick-edit-wpform-field-id] {
@apply cursor-crosshair;
}
/* no-prefix */
html.extendify-quick-edit-on [data-extendify-agent-block-id] a[href],
html.extendify-quick-edit-on [data-extendify-part-block-id] a[href],
html.extendify-quick-edit-on [data-extendify-quick-edit-product-id] a[href],
html.extendify-quick-edit-on
[data-extendify-quick-edit-wpform-field-id]
a[href] {
@apply cursor-pointer;
}
/* `revert` restores the UA-default cursor — text on inputs/textarea,
default/pointer on select/button — so form controls inside tagged
blocks still feel like form controls. */
/* no-prefix */
html.extendify-quick-edit-on [data-extendify-agent-block-id]
:is(input, textarea, select, button),
html.extendify-quick-edit-on
[data-extendify-part-block-id]
:is(input, textarea, select, button),
html.extendify-quick-edit-on
[data-extendify-quick-edit-product-id]
:is(input, textarea, select, button),
html.extendify-quick-edit-on
[data-extendify-quick-edit-wpform-field-id]
:is(input, textarea, select, button) {
@apply cursor-[revert];
}
/* keyboard-entry.js adds tabindex="0" to every tagged block so Tab can
walk between blocks for accessibility. Side effect: a mouse click on
a tagged block focuses it, the browser paints its :focus-visible
ring (1px solid blue in Chrome), and the ring lingers on after the
QE click-rule / Esc clears the committed selection — because focus
stays on the element until something else takes it. The hover bar's
showBar (driven by both mouseover AND focusin) already paints the
dashed outline as the visual focus indicator, so the browser ring
is both redundant and visually conflicting. Suppress it on every
tagged-block flavour while edit mode is on. */
/* no-prefix */
html.extendify-quick-edit-on [data-extendify-agent-block-id]:focus,
html.extendify-quick-edit-on [data-extendify-agent-block-id]:focus-visible,
html.extendify-quick-edit-on [data-extendify-part-block-id]:focus,
html.extendify-quick-edit-on [data-extendify-part-block-id]:focus-visible,
html.extendify-quick-edit-on [data-extendify-quick-edit-product-id]:focus,
html.extendify-quick-edit-on
[data-extendify-quick-edit-product-id]:focus-visible,
html.extendify-quick-edit-on [data-extendify-quick-edit-wpform-field-id]:focus,
html.extendify-quick-edit-on
[data-extendify-quick-edit-wpform-field-id]:focus-visible {
@apply outline-none;
}
/* WP's `<InputControl>` (and `<TextControl>` via it) layers a visual
`__backdrop` div over the input element to draw the focus border.
By WP design it carries `pointer-events: none` so clicks pass through
to the input behind. Our broader `.extendify-quick-edit-canvas *`
rule above forces every descendant to `pointer-events: auto`, which
re-enables the backdrop and makes it eat real-user clicks on the
LinkControl URL input (the "click does nothing" symptom). Pin the backdrop back to none — scoped to the LinkControl
shell + the QE canvas's WP popovers so we don't touch input-controls
in unrelated UI (the AI Agent's chat input, WP admin forms, etc.). */
/* no-prefix */
html.extendify-quick-edit-on .block-editor-link-control
.components-input-control__backdrop,
html.extendify-quick-edit-on
.extendify-quick-edit-canvas
.components-popover
.components-input-control__backdrop {
@apply pointer-events-none!;
}
/* The tagged-descendant cursor rules above scope by `[data-extendify-*]`
ancestor. WP's LinkControl popover (Quick Edit canvas → BlockTools →
Popover.Slot) can end up portaled inside a tagged element when the
live block's parent is itself a tagged container; the form-control
override on `:is(input, ...)` matches the `<input>` itself, but
WP wraps the input in `.components-input-control` + similar divs
that catch hover events around the input edge and read as crosshair.
Pin the cursor on the popover root + every interactive descendant
so the LinkControl always feels like a form, regardless of which
tagged ancestor it lands under. */
/* no-prefix */
html.extendify-quick-edit-on .block-editor-link-control,
html.extendify-quick-edit-on .block-editor-link-control *,
html.extendify-quick-edit-on .extendify-quick-edit-canvas .components-popover,
html.extendify-quick-edit-on
.extendify-quick-edit-canvas
.components-popover
* {
@apply cursor-[revert];
}
html.extendify-quick-edit-on .block-editor-link-control input,
html.extendify-quick-edit-on .block-editor-link-control textarea,
html.extendify-quick-edit-on
.extendify-quick-edit-canvas
.components-popover
input,
html.extendify-quick-edit-on
.extendify-quick-edit-canvas
.components-popover
textarea {
@apply cursor-text;
}
/* The `cursor: revert` block above reverts buttons inside
the LinkControl popover (pencil / unlink / copy) to the UA default,
which is the arrow cursor — not pointer. WP's `.components-button`
normally sets `cursor: pointer` but our blanket revert wins. Pin
pointer on the link-control's `<button>` and `<a>` (URL preview)
so every interactive element in the popover feels clickable. */
/* no-prefix */
html.extendify-quick-edit-on .block-editor-link-control button,
html.extendify-quick-edit-on .block-editor-link-control a,
html.extendify-quick-edit-on
.extendify-quick-edit-canvas
.components-popover
button,
html.extendify-quick-edit-on
.extendify-quick-edit-canvas
.components-popover
a {
@apply cursor-pointer;
}
/* The URL preview (`.block-editor-link-control__preview-title`,
an `<a>` rendered by `<ExternalLink>`) renders as white text on the
popover's white background when the QE canvas hosts a button block —
the canvas inherits Extendable's button-text color (white) and the
popover anchor picks it up via `color: inherit` somewhere in the
ExternalLink chain. `!important` wins the cascade unambiguously;
the rule is already QE-scoped to `html.extendify-quick-edit-on` so
it can't bleed into other surfaces. */
/* no-prefix */
html.extendify-quick-edit-on .block-editor-link-control__preview-title,
html.extendify-quick-edit-on .block-editor-link-control__preview-title:hover,
html.extendify-quick-edit-on .block-editor-link-control__preview-title:focus,
html.extendify-quick-edit-on .block-editor-link-control__preview-title *,
html.extendify-quick-edit-on .block-editor-link-control__preview-title:hover *,
html.extendify-quick-edit-on .block-editor-link-control__preview-title:focus * {
/* Literal color — the theme vars don't reach this portaled popover. */
@apply text-[#1e1e1e]! opacity-100!;
}
/* Hide core's developer-facing "Additional CSS class(es)" row (hardcoded, no
filter to remove it) — the only Advanced setting rendered in a fieldset. */
/* no-prefix */
html.extendify-quick-edit-on .block-editor-link-control__settings
.block-editor-link-control__setting:has(> fieldset) {
@apply hidden!;
}
/* Hover bar (plain DOM, see lib/hover-bar.js). Body-scoped so
every rule needs `no-prefix`. The ::before bridges the gap between
bar and block so the cursor can cross without losing hover. */
/* The bar carries `pointer-events: auto` so its ::before hover bridge
catches the cursor when traversing block → pill (with
`none`, cursor passed under the bar and would resolve to whatever
tagged ancestor was below, sometimes an unsupported one — the bar
then cleared mid-gesture). Wheel events on the bar are forwarded to
the page scroller via a JS handler in hover-bar.js#renderBar — pills
stay clickable AND the page still scrolls when the cursor is over
the bar. */
/* no-prefix */
.extendify-quick-edit-bar {
@apply pointer-events-auto fixed z-high inline-flex max-w-none flex-row flex-nowrap gap-[6px] p-0 whitespace-nowrap;
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu,
Cantarell, "Helvetica Neue", sans-serif;
}
/* Transparent 12px bridge to the block (above or below the bar)
so the cursor can cross the gap without losing hover. */
/* no-prefix */
.extendify-quick-edit-bar::before {
@apply absolute left-0 right-0 h-[12px] bg-transparent;
content: "";
}
/* no-prefix */
.extendify-quick-edit-bar[data-extendify-quick-edit-placement="above"]::before {
@apply -bottom-[12px];
}
/* no-prefix */
.extendify-quick-edit-bar[data-extendify-quick-edit-placement="below"]::before {
@apply -top-[12px];
}
/* When the bar is pinned inside a viewport-filling block (e.g. a
hero Cover) it already overlaps the block — no bridge needed. */
/* no-prefix */
.extendify-quick-edit-bar[data-extendify-quick-edit-placement="inside"]::before {
@apply hidden;
}
/* no-prefix */
.extendify-quick-edit-pill {
@apply inline-flex cursor-pointer items-center gap-[6px] rounded-full border-0 bg-gray-800 px-[12px] py-[6px] text-[12px] font-medium leading-[1.4] text-white;
box-shadow:
0 4px 12px rgba(15, 23, 42, 0.25),
0 0 0 1px rgba(255, 255, 255, 0.15);
transition:
background 0.15s ease,
transform 0.15s ease,
box-shadow 0.15s ease;
}
/* no-prefix */
.extendify-quick-edit-pill:hover {
@apply -translate-y-px bg-gray-900;
box-shadow:
0 6px 16px rgba(15, 23, 42, 0.35),
0 0 0 1px rgba(255, 255, 255, 0.2);
}
/* no-prefix */
.extendify-quick-edit-pill:focus-visible {
@apply outline-offset-[3px];
outline: 2px solid var(--color-design-main);
}
/* no-prefix */
.extendify-quick-edit-pill-ai {
background: #3858e9;
}
/* no-prefix */
.extendify-quick-edit-pill-ai:hover {
background: #2145e6;
}
/* Hover outline — drawn as a body-level `position: fixed` overlay,
NOT as a class on the block element itself. See
`lib/hover-bar.js#ensureOutline` for the why: putting the outline
on the block puts it inside whatever ancestor `overflow: hidden`
clip region the theme establishes, so it gets cropped on full-
width pattern containers (the user's report: "only see it on the
top"). Body-level fixed sidesteps that.
Visual style mirrors the Agent's DOMHighlighter so hover and
selection feel like the same UI:
- Theme primary color (--wp--preset--color--primary) instead
of a hardcoded blue — matches whatever the partner brand is
set to in Site Editor → Styles → Colors.
- 4px dashed stroke instead of 2px solid — chunkier, reads
more clearly as "this is selectable."
- mix-blend-mode: hard-light — keeps the stroke visible
against any background (light hero / dark cover / patterned).
- Spring-like transition via cubic-bezier with a slight
overshoot — approximates framer-motion's spring without the
runtime cost of importing framer-motion just for this.
Coefficients picked to match the agent's
(stiffness: 700, damping: 40, mass: 0.25) feel — quick
expand, gentle settle. */
/* no-prefix */
.extendify-quick-edit-hover-outline {
/* z-index 99997: below hover bar (99999) but above page content */
@apply pointer-events-none fixed z-[99997] box-border rounded-[4px] opacity-0 outline-offset-0 mix-blend-hard-light;
outline: 4px dashed var(--wp--preset--color--primary, #3b82f6);
/* Subtle overshoot — `cubic-bezier(0.34, 1.4, 0.64, 1)` was too
bouncy in practice (peak ~140% of final). Tightened to ~108%
peak — feels alive without obviously springing. */
transition:
top 0.2s cubic-bezier(0.34, 1.08, 0.64, 1),
left 0.2s cubic-bezier(0.34, 1.08, 0.64, 1),
width 0.2s cubic-bezier(0.34, 1.08, 0.64, 1),
height 0.2s cubic-bezier(0.34, 1.08, 0.64, 1),
opacity 0.1s ease-out;
}
/* no-prefix */
.extendify-quick-edit-hover-outline.is-visible {
@apply opacity-100;
}
/* wp.media frame: lock to a single tab + hide filters/details so
the modal is just "pick an image". Scoped to the QE-only mode class
(added to `frame.modal.$el` in InlineEditor.jsx) rather than `body` so
frames opened by the AI Agent / other features aren't affected — the
mode class is added by QE alone, so it's the discriminator on its own.
It lands on wp.media's outer modal wrapper, which carries no
`.media-modal` class of its own; the old `.media-modal.*` prefix
therefore matched nothing and the chrome leaked back in. */
/* no-prefix */
.extendify-quick-edit-mode-browse .media-frame-router,
.extendify-quick-edit-mode-upload .media-frame-router {
@apply hidden!;
}
/* no-prefix */
.extendify-quick-edit-mode-browse .media-frame-content
.attachments-browser
.media-toolbar,
.extendify-quick-edit-mode-upload
.media-frame-content
.attachments-browser
.media-toolbar {
@apply hidden!;
}
/* no-prefix */
.extendify-quick-edit-mode-browse .media-frame-content .media-sidebar,
.extendify-quick-edit-mode-upload .media-frame-content .media-sidebar {
@apply hidden!;
}
/* wp.media still reserves absolute offsets for the chrome hidden above;
core's own `hide-router` class is no use — MediaFrame re-toggles it
off on every state change. */
/* no-prefix */
.extendify-quick-edit-mode-browse .media-frame-content,
.extendify-quick-edit-mode-upload .media-frame-content {
@apply top-[50px]!;
}
/* no-prefix */
.extendify-quick-edit-mode-browse .attachments-browser:not(.has-load-more)
.attachments,
.extendify-quick-edit-mode-browse
.attachments-browser.has-load-more
.attachments-wrapper,
.extendify-quick-edit-mode-browse .attachments-browser .uploader-inline,
.extendify-quick-edit-mode-upload
.attachments-browser:not(.has-load-more)
.attachments,
.extendify-quick-edit-mode-upload
.attachments-browser.has-load-more
.attachments-wrapper,
.extendify-quick-edit-mode-upload .attachments-browser .uploader-inline {
/* Arbitrary [0px], not top-0/right-0 — spacing utilities compile to
calc(var(--spacing)*0) and the var doesn't reach this body-level
modal, so the rule would silently no-op. */
@apply top-[0px]! right-[0px]!;
}
/* While an upload is in flight, cover wp.media's content with our own
loading state so the library/gallery view doesn't flash mid-upload.
Modal-scoped — without that, this overlay painted a white sheet over
the AI Agent's media frame too, which read as "screen goes blank"
the instant the agent's media library responded to a click. */
/* no-prefix */
.extendify-quick-edit-media-uploading .media-frame-content::after {
@apply absolute inset-[0px] z-[5] bg-[#fff];
content: "";
}
/* no-prefix */
.extendify-quick-edit-media-uploading .media-frame-content::before {
@apply absolute top-1/2 left-1/2 z-[6] mr-[0px] mb-[0px] -mt-[16px] -ml-[16px] h-[32px] w-[32px] rounded-full border-[3px] border-[#ddd] border-t-[color:var(--ext-design-main,#2271b1)];
content: "";
animation: extendify-quick-edit-media-uploading-spin 0.8s linear infinite;
}
/* no-prefix */
@keyframes extendify-quick-edit-media-uploading-spin {
to {
transform: rotate(360deg);
}
}
/* Offset the wp.media modal past the Agent sidebar (which has
`inert` removed while open). */
/* no-prefix */
html:has(#extendify-agent-sidebar:not([inert])) .media-modal-backdrop {
@apply left-[384px]!;
}
/* no-prefix */
html:has(#extendify-agent-sidebar:not([inert])) .media-modal {
@apply left-[calc(384px+30px)]!;
}
/* BlockEditor-based text editor (BlockTextEditor.jsx). */
/* Hide every Ariakit tooltip portal while a QE canvas is mounted.
Many rounds of trying to land both 36px-custom-button
tooltips and 48px-BlockToolbar-button tooltips in a clear spot
below the bar (pointer-events tricks, top placement, height
equalization, Floating-UI-aware transforms) all hit one or the
other case. The dev's call: drop the tooltips here and revisit
later.
Scope is `body:has(.extendify-quick-edit-floating-bar)` so this
ONLY hides tooltips while a QE canvas is mounted. Outside an
active editing session — AI Agent sidebar, WP admin chrome,
other plugins' tooltips — is completely untouched. Inside a
session, LinkControl + other in-canvas popovers share this
portal too and lose their tooltips alongside the bar's, which
is fine for the editing-session contract.
Each trigger keeps its `aria-label` so screen readers still
announce. */
/* no-prefix */
body:has(.extendify-quick-edit-floating-bar) [id^="portal/tooltip"] {
@apply hidden;
}
/* no-prefix */
.extendify-quick-edit-floating-bar {
@apply pointer-events-auto;
}
/* The portaled BlockToolbar ships with extra Gutenberg chrome we
don't want — block transform menu, block settings 3-dots,
parent-selector, and the format-toolbar's "More" overflow chevron
(which surfaces Highlight / Inline code / Strikethrough / etc.).
With our custom Text-color + Highlight buttons rendered alongside
the toolbar, the More overflow is redundant — and it kept slipping
in alongside our buttons making the toolbar look cluttered. Hide
it. */
/* no-prefix */
.extendify-quick-edit-floating-bar-inner .block-editor-block-mover,
.extendify-quick-edit-floating-bar-inner .block-editor-block-parent-selector,
.extendify-quick-edit-floating-bar-inner
.block-editor-block-toolbar__group-collapsed-toolbar,
/* Block-level settings 3-dot menu */
.extendify-quick-edit-floating-bar-inner .block-editor-block-settings-menu,
/* Block transform / switcher button (the "Heading" icon you can click
to convert to another block type — out of scope for Quick Edit) */
.extendify-quick-edit-floating-bar-inner .block-editor-block-switcher,
/* The chevron that surfaces overflow toolbar groups. */
.extendify-quick-edit-floating-bar-inner .block-editor-block-toolbar__group-collapsed-button,
/* RichText format toolbar's "More" overflow toggle (down arrow). Hide its
dropdown wrapper too — left visible, the 0-width wrapper still counts as
a flex item and costs one phantom gap after the last format button. */
.extendify-quick-edit-floating-bar-inner [aria-label="More"],
.extendify-quick-edit-floating-bar-inner
.components-dropdown-menu:has(> [aria-label="More"]) {
@apply hidden!;
}
/* no-prefix */
.extendify-quick-edit-floating-bar-inner
.block-editor-block-contextual-toolbar::before {
@apply absolute left-0 top-1/2 h-[14px] w-px -translate-y-1/2 bg-gray-300;
content: "";
}
/* BlockToolbar wrapper owns the layout↔format divider on its left, 12px each side. */
/* no-prefix */
.extendify-quick-edit-floating-bar-inner
.block-editor-block-contextual-toolbar {
@apply relative mt-0! mr-0! mb-0! ml-[8px]! pt-0! pr-0! pb-0! pl-[12px]!;
}
/* core/button has no heading/alignment group, so the toolbar opens the
bar and its left divider reads as a stray leading `|`. */
/* no-prefix */
.extendify-quick-edit-floating-bar-inner
.block-editor-block-contextual-toolbar:first-child {
@apply ml-0! pl-0!;
}
/* no-prefix */
.extendify-quick-edit-floating-bar-inner
.block-editor-block-contextual-toolbar:first-child::before {
@apply hidden;
}
/* Strip BlockToolbar's own group dividers (border-right on each
.components-toolbar-group in Gutenberg). We deliberately don't add
our own dividers between BlockToolbar's internal groups: the format
toolbar leaves a thin invisible group after B/I/link (wrapping the
"More" overflow we hide via display:none on the chevron button) —
adding a `:not(:first-of-type)::before` rule for those internal
groups draws a stray divider right next to the colors group's own
divider. Easier and cleaner to treat the whole BlockToolbar as one
visual segment and only divide between BlockToolbar, colors, and
actions. */
/* no-prefix */
.extendify-quick-edit-floating-bar-inner .components-toolbar-group,
.extendify-quick-edit-floating-bar-inner .components-toolbar,
/* The portaled BlockToolbar's contextual-toolbar wrapper carries a core
`0 1px 0 0` bottom shadow (a faux border) that draws a line under our
pill. We provide our own pill shadow on the inner — strip the core one. */
.extendify-quick-edit-floating-bar-inner .block-editor-block-contextual-toolbar {
@apply border-l-0! border-r-0! shadow-none!;
}
/* Zero Gutenberg's per-group `padding: 0 6px` + -1px margin so the bar's own
`gap` owns spacing. Not the contextual-toolbar — it owns the divider above. */
/* no-prefix */
.extendify-quick-edit-floating-bar-inner .components-toolbar-group,
.extendify-quick-edit-floating-bar-inner .components-toolbar {
@apply p-0! m-0!;
}
/* Clamp Gutenberg's 48px toolbar chrome to the button height so the bar
hugs its row instead of floating the buttons in dead vertical space. */
/* no-prefix */
.extendify-quick-edit-floating-bar-inner .block-editor-block-contextual-toolbar,
.extendify-quick-edit-floating-bar-inner .block-editor-block-toolbar,
.extendify-quick-edit-floating-bar-inner .components-accessible-toolbar,
.extendify-quick-edit-floating-bar-inner .components-toolbar-group,
.extendify-quick-edit-floating-bar-inner .block-editor-block-toolbar__slot {
@apply h-[28px]! min-h-0!;
}
/* B/I/link get no gap from Gutenberg (group + inner slot), so they rendered
edge-to-edge; gap both to match the bar's rhythm. */
/* no-prefix */
.extendify-quick-edit-floating-bar-inner .components-toolbar-group,
.extendify-quick-edit-floating-bar-inner .block-editor-block-toolbar__slot {
@apply gap-[4px]!;
}
/* One box model for all buttons — custom heading/align/color + native
B/I/link — so Gutenberg's square, dark-pressed defaults match the pill. */
/* no-prefix */
.extendify-quick-edit-floating-bar-inner .components-button {
@apply min-w-[28px]! h-[28px]! px-[4px]! py-0! rounded-[6px]! bg-transparent! text-gray-900! shadow-none!;
}
/* Drop Gutenberg's inset ::before hover/pressed bar — it fights our
full-button rounded states. */
/* no-prefix */
.extendify-quick-edit-floating-bar-inner .components-button::before {
@apply hidden!;
}
/* no-prefix */
.extendify-quick-edit-floating-bar-inner
.components-button:hover:not(:disabled) {
@apply bg-[rgba(0,0,0,0.05)]!;
}
/* Active format (bold/italic/link) — a subtle filled state instead of
Gutenberg's near-black pressed background. */
/* no-prefix */
.extendify-quick-edit-floating-bar-inner .components-button.is-pressed,
.extendify-quick-edit-floating-bar-inner
.components-button.is-pressed:hover:not(:disabled) {
@apply bg-[rgba(15,23,42,0.1)]! text-gray-900!;
}
/* no-prefix */
.extendify-quick-edit-text-align-popover .components-popover__content {
@apply p-[6px] min-w-[auto];
}
/* no-prefix */
.extendify-quick-edit-text-align-popover-inner {
@apply flex flex-col gap-[2px];
}
/* no-prefix */
.extendify-quick-edit-text-align-popover
.extendify-quick-edit-text-align-option.components-button {
@apply h-[32px] justify-start gap-[8px] px-[10px] py-0 text-[13px] font-medium;
}
/* Box model + hover inherited from the shared .components-button rule above;
the heading button only adds its text label's weight/size + a bit more
horizontal padding for the "H2" / "H3" labels. */
/* no-prefix */
.extendify-quick-edit-floating-bar-inner
.extendify-quick-edit-heading-level-button.components-button {
@apply px-[6px]! py-0! text-[13px] font-semibold;
}
/* no-prefix */
.extendify-quick-edit-heading-level-popover .components-popover__content {
@apply p-[6px] min-w-[auto];
}
/* no-prefix */
.extendify-quick-edit-heading-level-popover-inner {
@apply inline-flex gap-[2px] p-[2px];
}
/* no-prefix */
.extendify-quick-edit-heading-level-popover
.extendify-quick-edit-heading-level-option.components-button {
@apply h-[32px] min-w-[36px] px-[8px] py-0 text-[13px] font-semibold;
}
/* Box model + hover inherited from the shared .components-button rule above. */
/* no-prefix */
.extendify-quick-edit-color-popover .components-popover__content {
@apply p-[12px] min-w-[220px];
}
/* no-prefix */
.extendify-quick-edit-color-popover-inner
.components-circular-option-picker__option-wrapper {
@apply m-[4px];
}
/* Explicit "Clear" button below the swatches — the ColorPalette's
built-in clear is easy to miss. */
/* no-prefix */
.extendify-quick-edit-color-popover
.extendify-quick-edit-color-clear.components-button {
@apply block w-full mt-[8px] px-[12px]! py-[8px]! border-t! border-t-gray-300! rounded-none! text-left! text-gray-700! font-medium!;
}
/* no-prefix */
.extendify-quick-edit-color-popover
.extendify-quick-edit-color-clear.components-button:hover {
@apply bg-gray-50! text-gray-900!;
}
/* no-prefix */
.extendify-quick-edit-host {
/* The host overlays the live block 1:1. Its position is set by
BlockTextEditor's align() effect; CSS just zeros margin so theme
blockGap doesn't push us.
The blue outline lives HERE (not on the inner canvas). The host
has its width / min-height set synchronously to match the live
block on insert, so its outline paints at full size on the very
first frame. The canvas inside is empty until blocks load —
putting the outline on the canvas previously meant a 0-height
"narrow stripe" between insert and content load.
`outline-offset: 0` (flush with edge) is deliberate. With +4px,
the outline extends outside the host by 4px — for full-width
pattern containers at the page edge, those 4px land in
`body`/`html`'s `overflow-x: hidden` clip region, and the
outline disappears on the bottom + sides ("only see it on the
top," as the user reported). Flush with the edge keeps the
outline inside the host's bounds and visible everywhere. */
@apply m-0! rounded-[4px] outline-offset-0;
outline: 2px solid
color-mix(
in srgb,
var(--wp--preset--color--primary, #3b82f6) 70%,
transparent
);
}
/* no-prefix */
.extendify-quick-edit-canvas {
@apply pointer-events-auto;
}
/* While the rich-text editor is focused, transition the outline to
fully opaque so the active edit state is unambiguous. */
/* no-prefix */
.extendify-quick-edit-host:focus-within {
outline-color: var(--wp--preset--color--primary, #3b82f6);
}
/* Pin link / button-link color in the canvas to the live element's resting
value (snapshot into --qe-link-color in BlockTextEditor.jsx). Without this,
the theme's :hover on .wp-block-button__link fires as soon as the user's
cursor sits over the text they're editing, flipping the button text to
the hover color while the background stays non-hover — broken-looking.
Falls back to currentColor when no link is in the live block (e.g. a
plain heading or paragraph), making the rule a no-op. */
/* no-prefix */
.extendify-quick-edit-host a:hover,
.extendify-quick-edit-host .wp-block-button__link:hover,
.extendify-quick-edit-host .wp-block-button:hover .wp-block-button__link {
@apply text-[var(--qe-link-color,currentColor)]!;
}
/* BlockEditor's BlockList adds margin-top: 16px to its child blocks
(and 40.2px bottom). When our canvas is positioned exactly over
the live block, those margins push the rendered block 16px below
where the live one sits — the user sees the heading drift down on
click. Zero out the margins for the block immediately inside our
canvas so the rendered block top lines up with the live element.
Also zero PADDING on the block list + block wrappers — the editor
stylesheet adds horizontal padding (for the inserter chip / block-
selector chrome) that narrows the inner text's effective width, so
the same heading wraps at a different word boundary than the live
element (line-break parity). With padding zeroed and the
host's width matching liveRect.width, the text wraps at the same
word as the live element. */
/* no-prefix */
.extendify-quick-edit-canvas .block-editor-block-list__layout,
.extendify-quick-edit-canvas .block-editor-block-list__block {
@apply mt-0! mb-0! px-0!;
}
/* core/text-color wraps its target text in `<mark>`. Browsers AND many
themes give `<mark>` a yellow background by default; combined with our
text-color format's inline `background-color: transparent` (set when
only text color is picked), users sometimes still saw a yellow band
around their colored text — "changing one color changed
both". Neutralize the background in our canvas. Inline
`background-color: <color>` (set when the user also picks a
highlight) wins via specificity and renders normally. */
/* no-prefix */
.extendify-quick-edit-canvas mark {
background: none;
}
/* Hide Gutenberg's own block-level selection / hover indicators
* inside our canvas. BlockList draws a faint gray outline (or a
* "::before" rect, depending on Gutenberg version) on the selected
* block — when stacked inside our blue canvas outline it reads as a
* confusing "double box." We want OUR outline to be the one and only
* editing-state cue; the contenteditable's blinking caret is enough
* to indicate where the cursor is, no extra block highlight needed. */
/* no-prefix */
.extendify-quick-edit-canvas .block-editor-block-list__block,
.extendify-quick-edit-canvas .block-editor-block-list__block.is-selected,
.extendify-quick-edit-canvas .block-editor-block-list__block.is-hovered,
.extendify-quick-edit-canvas .block-editor-block-list__block:focus,
.extendify-quick-edit-canvas .block-editor-rich-text__editable,
.extendify-quick-edit-canvas .block-editor-rich-text__editable:focus {
@apply outline-none! shadow-none!;
}
/* no-prefix */
.extendify-quick-edit-canvas .block-editor-block-list__block::before,
.extendify-quick-edit-canvas .block-editor-block-list__block::after {
@apply hidden!;
}
/* The BlockEditor canvas needs writing flow + its standard editor
styles to behave naturally (selection, format toolbar tracking).
We don't load editor-styles globally — these are minimal restorations
so contenteditable inside .block-editor-rich-text__editable works. */
/* no-prefix */
.extendify-quick-edit-canvas .block-editor-block-list__layout {
@apply cursor-text;
}
/* Force visibility of blocks with the Extendable `ext-animate--on`
class (and any element using its initial opacity:0 animation
pattern) INSIDE the canvas. The theme's animation JS only runs
on page-load scroll events; a freshly mounted BlockEditor block
never gets animated in, so opacity stays 0 and the user sees an
empty canvas. We deliberately keep the class on the block (it's
part of attrs.className and round-trips through serialize) and
override visibility cosmetically here.
`transform: none !important` is the matching half: the theme's
pre-animation rule is `.ext-animate--on:not(.ext-animate--off) {
transform: scale(0.8); opacity: 0; }`, and a sibling rule
`.ext-animate { transform: none; opacity: 1; }` flips both when
the JS adds `ext-animate` on scroll-into-view. Inside the canvas
the BlockEditor renders the parsed markup with `ext-animate--on`
but NOT `ext-animate` (that class is JS-added, not saved), so
without this override headings/paragraphs render at 80% scale
while the live element sits at scale 1 — the user reported this
as "the text gets a little smaller when I click Quick Edit." */
/* no-prefix */
.extendify-quick-edit-canvas .ext-animate--on,
.extendify-quick-edit-canvas .block-editor-block-list__block.ext-animate--on,
.extendify-quick-edit-canvas .ext-animate--on * {
@apply opacity-100! transform-none!;
}
/* Modals portal to <body>, so the no-prefix marker keeps these out of the
.extendify-quick-edit scope. The agent sidebar uses z-higher (999999),
so the modal overlay sits at 1_000_000 to stay on top when both are open. */
/* no-prefix */
.components-modal__screen-overlay:has(.extendify-quick-edit-modal) {
@apply z-[1000000]!;
}
/* When wp.media's frame opens on top of our modal (e.g. SiteIdentityModal's
"Change logo" → MediaUpload), our modal would otherwise sit on top
(z-index 1000000) and block clicks on the media library grid. Hide our
modal while wp.media is open; it reappears when the user picks an image
or closes the frame.
Trigger on `body.modal-open` — wp.media (legacy Backbone code) adds
that class directly on open and removes it on close. Round-3 used
`:has(.media-modal)`, which stayed true after wp.media closed (wp.media
hides via display:none and leaves the element in the DOM).
Our own QE modals MUST NOT trip this rule. @wordpress/components Modal
also adds `body.modal-open` on mount, so every QE modal hid itself on
first open. Each QE modal now passes
`bodyOpenClassName={QE_MODAL_BODY_OPEN_CLASS}` — see modal-root.js. */
/* no-prefix */
body.modal-open .components-modal__frame:has(.extendify-quick-edit-modal),
body.modal-open
.components-modal__screen-overlay:has(.extendify-quick-edit-modal) {
@apply invisible!;
}
/* ----------------------------------------------------------------
* Modal polish — keep visual language aligned with the auto-launch
* page + AI Agent so the user-perceived experience feels like one
* product. Agent's tokens:
* --ext-design-main primary brand (banner / primary buttons)
* --ext-design-secondary, --ext-design-tertiary (accents, less used)
*
* The agent's sidebar uses rounded-2xl + shadow-lg + bg-white; we
* mirror that on the modal frame so the modal feels like a natural
* extension of the agent's UI rather than a stock WP component.
*
* Falls back to neutral defaults when the partner data hasn't set
* the design vars (single-color sites, themes that don't import the
* Extendable design system). Keeps the modal looking polished even
* outside the auto-launch flow.
* ---------------------------------------------------------------- */
/* no-prefix */
.components-modal__frame:has(.extendify-quick-edit-modal),
.extendify-quick-edit-modal-root .components-modal__frame {
@apply overflow-hidden rounded-[16px]!;
box-shadow:
0 10px 15px -3px rgba(0, 0, 0, 0.12),
0 4px 6px -4px rgba(0, 0, 0, 0.08) !important;
}
/* no-prefix */
.components-modal__frame:has(.extendify-quick-edit-modal)
.components-modal__header {
@apply border-b border-b-gray-300 px-[24px] py-[18px];
}
/* no-prefix */
.components-modal__frame:has(.extendify-quick-edit-modal)
.components-modal__header-heading {
@apply text-[15px] font-semibold tracking-[-0.01em];
}
/* no-prefix */
.components-modal__frame:has(.extendify-quick-edit-modal)
.components-modal__content {
@apply px-[24px] pt-[18px] pb-[22px];
}
/* Primary save button uses the brand color so the action feels
continuous with the agent's "Send" pill / launch CTAs. */
/* no-prefix */
.extendify-quick-edit-modal-actions .components-button.is-primary {
@apply bg-[var(--ext-design-main,#2c39bd)]! shadow-none! rounded-[8px]! px-[14px]! py-[6px]! font-medium!;
}
/* no-prefix */
.extendify-quick-edit-modal-actions
.components-button.is-primary:hover:not(:disabled) {
@apply bg-[var(--ext-design-main,#2c39bd)]! brightness-[1.08];
}
/* no-prefix */
.extendify-quick-edit-modal-actions
.components-button.is-primary:focus:not(:disabled) {
box-shadow:
0 0 0 2px #fff,
0 0 0 4px var(--ext-design-main, #2c39bd) !important;
}
/* no-prefix */
.extendify-quick-edit-modal-actions .components-button.is-tertiary {
@apply rounded-[8px]! px-[12px]! py-[6px]! font-medium! text-gray-700!;
}
/* no-prefix */
.extendify-quick-edit-modal-actions
.components-button.is-tertiary:hover:not(:disabled) {
@apply bg-gray-100! text-gray-800!;
}
/* Tighter, consistent control rhythm inside modals — replaces
wp-components' default 24px gaps with 14px so the modal feels
compact and intentional, matching the agent's chat density. */
/* no-prefix */
.extendify-quick-edit-modal .components-base-control {
@apply mb-[14px];
}
/* no-prefix */
.extendify-quick-edit-modal .components-base-control__label {
/* normal-case: WP defaults to uppercase via inheritance in some themes */
@apply mb-[6px] text-[12px] font-semibold normal-case tracking-[0] text-gray-800;
}
/* no-prefix */
.extendify-quick-edit-modal .components-text-control__input,
.extendify-quick-edit-modal .components-textarea-control__input {
@apply rounded-[8px] border border-gray-300;
transition:
border-color 0.12s ease,
box-shadow 0.12s ease;
}
/* no-prefix */
.extendify-quick-edit-modal .components-text-control__input:focus,
.extendify-quick-edit-modal .components-textarea-control__input:focus {
@apply border-[color:var(--ext-design-main,#2c39bd)]! outline-none!;
box-shadow: 0 0 0 3px
color-mix(in srgb, var(--ext-design-main, #2c39bd) 18%, transparent) !important;
}
/* no-prefix */
.extendify-quick-edit-modal-actions {
@apply flex justify-end gap-[8px] mt-[18px] pt-[14px] border-t border-t-gray-300;
}
/* no-prefix */
.extendify-quick-edit-modal-label {
@apply mt-[12px] mr-0 mb-[6px] ml-0 text-[11px] font-medium uppercase text-gray-700;
}
/* no-prefix */
.extendify-quick-edit-link-current {
@apply mt-[8px] mr-0 mb-[12px] ml-0 rounded-[6px] bg-gray-50 px-[12px] py-[8px] text-[12px] text-gray-700;
}
/* no-prefix */
.extendify-quick-edit-link-current code {
@apply text-gray-900;
}
/* LinkControl + format-toolbar popovers inside the canvas. WP's Popover
writes the anchor's viewport rect into style.top/left and renders as
`position: absolute`, which interprets those coords relative to the
nearest positioned ancestor. In our setup that's
`.extendify-quick-edit-host` (position: absolute, sized to track the
live block), so the popover drifts by host.top/left and its width is
capped by host.width — the user reads this as "edit box too short" +
"hard to click where intended." Forcing position: fixed lets the
coords land in viewport space and frees the popover from the canvas
width. */
/* no-prefix */
.extendify-quick-edit-canvas .components-popover {
@apply fixed!;
}
/* Without a positioned offsetParent, floating-ui's coords ignore the admin
bar's html margin-top and the popover renders 32px above its anchor. */
/* no-prefix */
.extendify-quick-edit-popover-slot {
@apply relative;
}
/* LinkControl in edit mode (forceIsEditingLink) renders its own Apply / Cancel
below the URL input. Our modal already has Save / Cancel for that, and
the user reads two action rows as broken — hide the inner one. The link
value still propagates via the onChange we pass to LinkControl. */
/* no-prefix */
.extendify-quick-edit-modal-nav .block-editor-link-control__search-actions,
.extendify-quick-edit-modal-nav .block-editor-link-control__search-submit,
.extendify-quick-edit-modal-nav
.block-editor-link-control__search-input-actions,
.extendify-quick-edit-modal-nav
.block-editor-link-control
.block-editor-link-control__settings {
@apply hidden!;
}
/* no-prefix */
.extendify-quick-edit-logo-row {
@apply flex items-center gap-[16px] mt-[8px];
}
/* no-prefix */
.extendify-quick-edit-logo-preview {
@apply max-h-[80px] max-w-[120px] rounded-[6px] border border-gray-300 bg-gray-50 object-contain p-[4px];
}
/* no-prefix */
.extendify-quick-edit-logo-buttons {
@apply flex flex-col gap-[6px];
}
/* Product price modal: currency-prefixed regular + sale inputs. */
/* no-prefix */
.extendify-quick-edit-price-fields {
@apply flex flex-col gap-[12px];
}
/* no-prefix */
.extendify-quick-edit-price-row {
@apply flex items-end gap-[8px];
}
/* The modal-rhythm margin (above) would misalign input and prefix under
items-end; the fields' gap handles spacing. */
/* no-prefix */
.extendify-quick-edit-price-row .components-base-control {
@apply mb-0;
}
/* no-prefix */
.extendify-quick-edit-price-prefix {
/* 32px = the WP TextControl input height, so the symbol centers on it. */
@apply flex h-[32px] items-center text-[14px] font-medium text-gray-700;
}
/* AI generation + Unsplash image-picker modals */
/* no-prefix */
.extendify-quick-edit-ai-form {
@apply flex flex-col gap-[16px];
}
/* no-prefix */
.extendify-quick-edit-ai-generating {
@apply inline-flex items-center gap-[8px] rounded-[6px] bg-gray-50 px-[12px] py-[8px] text-[13px] text-gray-700;
}
/* no-prefix */
.extendify-quick-edit-ai-credits {
@apply text-[12px] text-gray-600 text-right;
}
/* no-prefix */
.extendify-quick-edit-ai-preview {
@apply flex max-h-[60vh] items-center justify-center overflow-hidden rounded-[6px] bg-gray-50;
}
/* no-prefix */
.extendify-quick-edit-ai-preview img {
@apply max-h-[60vh] max-w-full object-contain;
}
/* The padding-top:100% trick beats theme/WP button min-height rules
that override aspect-ratio. */
/* no-prefix */
.extendify-quick-edit-image-grid {
@apply grid grid-cols-3 gap-[8px] mt-[12px];
/* No inner scroll — the WP Modal body already scrolls. Two
scrollbars (modal + grid) was confusing and trapped the user
on the inner scroller while the outer modal still had room. */
}
/* no-prefix */
.extendify-quick-edit-image-grid-item-credit {
@apply pointer-events-none absolute bottom-0 left-0 right-0 px-[8px] py-[6px] text-[11px] leading-[1.3] text-white opacity-0;
background: linear-gradient(
to top,
rgba(0, 0, 0, 0.65) 0%,
rgba(0, 0, 0, 0) 100%
);
transition: opacity 0.15s ease;
}
/* no-prefix */
.extendify-quick-edit-image-grid-item:hover
.extendify-quick-edit-image-grid-item-credit,
.extendify-quick-edit-image-grid-item:focus-visible
.extendify-quick-edit-image-grid-item-credit {
@apply opacity-100;
}
/* no-prefix */
.extendify-quick-edit-image-grid-item-credit a {
@apply pointer-events-auto text-inherit underline;
}
/* no-prefix */
.extendify-quick-edit-image-attribution {
@apply mt-[12px] pt-[10px] border-t border-t-gray-300 text-[11px] text-gray-600;
}
/* no-prefix */
.extendify-quick-edit-image-attribution a {
@apply text-inherit underline;
}
/* no-prefix */
.extendify-quick-edit-image-grid-item {
/* min-h-0: defeat WP button-style min-height rules */
@apply relative w-full min-h-0 cursor-pointer overflow-hidden rounded-[6px] border-0 bg-transparent p-0;
transition: transform 0.12s ease;
}
/* no-prefix */
.extendify-quick-edit-image-grid-item::before {
@apply block pt-[100%];
content: "";
}
/* no-prefix */
.extendify-quick-edit-image-grid-item:hover:not(:disabled) {
@apply scale-[1.02];
}
/* no-prefix */
.extendify-quick-edit-image-grid-item:disabled {
@apply cursor-not-allowed;
}
/* no-prefix */
.extendify-quick-edit-image-grid-item img {
@apply absolute inset-0 block h-full w-full object-cover;
}
/* no-prefix */
.extendify-quick-edit-image-grid-item-overlay {
@apply absolute inset-0 flex items-center justify-center bg-[rgba(0,0,0,0.45)];
}
/* Reduced motion (a11y M7). Stop the infinite upload spinner and the pulsing
Ask-AI flash (the motions vestibular-sensitive users most need gone) and
drop the hover outline's spring so it tracks instantly. All `!important`:
the surrounding environment ships a global `prefers-reduced-motion` reset
that forces a tiny non-zero duration (~0.01ms) onto everything, so these
must win over it — and over the base rules — for Extendify's own
reduced-motion intent to be authoritative rather than theme-dependent.
Selectors are page-level (the flash class, the body-level fixed outline,
wp.media's modal), so they carry `no-prefix` like the originals. */
@media (prefers-reduced-motion: reduce) {
/* no-prefix */
.extendify-quick-edit-media-uploading .media-frame-content::before {
@apply animate-none!;
}
/* no-prefix */
.extendify-quick-edit-ask-flash {
@apply animate-none!;
}
/* no-prefix */
.extendify-quick-edit-hover-outline {
/* Shorthand, not transition-none — only the shorthand zeroes the
duration the global reset forces to 0.01ms. */
transition: none !important;
}
}