<?php

namespace FleekDash\Admin\Iframe;

use FleekDash\Admin\Editor\ThirdPartyEditorCssManager;

/**
 * Iframe CSS management
 *
 * Handles enqueuing and injection of CSS for iframe contexts,
 * including customizer styles, essential iframe styles, and design system tokens.
 *
 * @package FleekDash\Admin\Iframe
 * @since 2.2.0
 */
class IframeCSSManager
{
    /**
     * Layout + scrollbar rules for embedded admin (iframe body/html).
     *
     * @return string
     */
    private static function getEssentialIframeLayoutAndScrollbarCss()
    {
        return self::getEssentialIframeLayoutAndScrollbarCssCore()
            . self::getNativeWordPressSubframeScrollbarGutterCss();
    }

    /**
     * @return string
     */
    private static function getEssentialIframeLayoutAndScrollbarCssCore(): string
    {
        return self::getEssentialIframeDocumentLayoutCss()
            . self::getEssentialIframeScrollbarBaseCss()
            . self::getEssentialIframeScrollbarThumbHoverCss();
    }

    /**
     * Document layout, overflow, and horizontal scroll regions for iframe embeds.
     *
     * @return string
     */
    private static function getEssentialIframeDocumentLayoutCss(): string
    {
        return <<<'CSS'
/*
 * WordPress admin-bar offset on html.wp-toolbar (32px desktop / 46px mobile).
 * body height 100vh + html padding-top overflows the viewport → duplicate html/body scrollbars.
 */
:root {
  --fleekdash-admin-bar-offset: 32px;
}

@media screen and (max-width: 782px) {
  :root {
    --fleekdash-admin-bar-offset: 46px;
  }
}

/*
 * Single scrollport: body only. html must not scroll when wp-toolbar padding-top is applied.
 */
html:has(body.fleekdash-iframe) {
  overflow-x: hidden !important;
  overflow-y: hidden !important;
  max-width: 100%;
  height: 100vh;
  box-sizing: border-box;
}

body.fleekdash-iframe {
  height: 100vh !important;
  max-height: 100vh !important;
  overflow-x: hidden !important;
  overflow-y: auto;
  max-width: 100%;
  box-sizing: border-box;
  scrollbar-gutter: auto !important;
}

html.wp-toolbar:has(body.fleekdash-iframe.admin-bar:not(.fleekdash-adminbar-hidden)) body.fleekdash-iframe,
html.admin-bar:has(body.fleekdash-iframe.admin-bar:not(.fleekdash-adminbar-hidden)) body.fleekdash-iframe {
  height: calc(100vh - var(--fleekdash-admin-bar-offset, 32px)) !important;
  max-height: calc(100vh - var(--fleekdash-admin-bar-offset, 32px)) !important;
}

@supports (overflow: overlay) {
  body.fleekdash-iframe {
    overflow-x: hidden !important;
    overflow-y: overlay !important;
  }
}

/*
 * Gutter stays auto on all iframe shells (including trusted).
 * stable reserves a visible empty column beside thin/overlay scrollbars — removed intentionally.
 * Hover-reveal thumbs may cause a minor layout nudge on some OSes; prefer flush edge.
 */

body.fleekdash-iframe #wpwrap,
body.fleekdash-iframe #wpcontent,
body.fleekdash-iframe #wpbody-content {
  overflow-x: clip;
  max-width: 100%;
  box-sizing: border-box;
}

@supports not (overflow: clip) {
  body.fleekdash-iframe #wpwrap,
  body.fleekdash-iframe #wpcontent,
  body.fleekdash-iframe #wpbody-content {
    overflow-x: hidden;
  }
}

body.fleekdash-iframe .wp-full-overlay,
body.fleekdash-iframe .theme-overlay.active {
  scrollbar-gutter: auto;
}

/* Horizontal scroll only on inner regions that need it (not document root) */
body.fleekdash-iframe .wp-list-table-wrapper,
body.fleekdash-iframe .widefat,
body.fleekdash-iframe .form-table,
body.fleekdash-iframe .theme-browser,
body.fleekdash-iframe .themes {
  overflow-x: auto;
  max-width: 100%;
}

body.fleekdash-iframe #adminmenuback,
body.fleekdash-iframe #adminmenuwrap,
body.fleekdash-iframe #adminmenumain {
  scrollbar-gutter: auto !important;
}

CSS;
    }

    /**
     * Scrollbar width, track, thumb base, and scrollbar-color for iframe embeds.
     *
     * @return string
     */
    private static function getEssentialIframeScrollbarBaseCss(): string
    {
        return <<<'CSS'
/*
 * FleekDash iframe scrollbars — must beat includes/css/core.css:
 *   * { scrollbar-color: … !important; &::-webkit-scrollbar-thumb { border: 2px solid var(--background); } }
 * Use higher specificity + !important on scrollbar-color, and strip thumb border (matches globals.css).
 * Also style html when the viewport scrolls the root instead of body.
 */
html:has(body.fleekdash-iframe),
body.fleekdash-iframe {
  scrollbar-width: thin !important;
  scrollbar-color: transparent transparent !important;
}

html.light body.fleekdash-iframe:hover,
html.light body.fleekdash-iframe:focus-within,
html.fleek-mode-windowed-light body.fleekdash-iframe:hover,
html.fleek-mode-windowed-light body.fleekdash-iframe:focus-within,
html:not(.dark) body.fleekdash-iframe:hover,
html:not(.dark) body.fleekdash-iframe:focus-within,
html.light:has(body.fleekdash-iframe):hover,
html.fleek-mode-windowed-light:has(body.fleekdash-iframe):hover,
html:not(.dark):has(body.fleekdash-iframe):hover {
  scrollbar-color: rgba(0, 0, 0, 0.18) transparent !important;
}

html.dark body.fleekdash-iframe:hover,
html.dark body.fleekdash-iframe:focus-within,
html.fleek-mode-windowed-dark body.fleekdash-iframe:hover,
html.fleek-mode-windowed-dark body.fleekdash-iframe:focus-within,
html.fleek-mode-protected-dark body.fleekdash-iframe:hover,
html.fleek-mode-protected-dark body.fleekdash-iframe:focus-within,
html.dark:has(body.fleekdash-iframe):hover,
html.fleek-mode-windowed-dark:has(body.fleekdash-iframe):hover,
html.fleek-mode-protected-dark:has(body.fleekdash-iframe):hover {
  scrollbar-color: rgba(255, 255, 255, 0.18) transparent !important;
}

body.fleekdash-iframe::-webkit-scrollbar,
html:has(body.fleekdash-iframe)::-webkit-scrollbar,
body.fleekdash-iframe *::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

body.fleekdash-iframe::-webkit-scrollbar-button,
html:has(body.fleekdash-iframe)::-webkit-scrollbar-button,
body.fleekdash-iframe *::-webkit-scrollbar-button {
  display: none;
  width: 0 !important;
  height: 0 !important;
}

body.fleekdash-iframe::-webkit-scrollbar-corner,
html:has(body.fleekdash-iframe)::-webkit-scrollbar-corner,
body.fleekdash-iframe *::-webkit-scrollbar-corner {
  background: transparent !important;
}

body.fleekdash-iframe::-webkit-scrollbar-track,
html:has(body.fleekdash-iframe)::-webkit-scrollbar-track,
body.fleekdash-iframe *::-webkit-scrollbar-track {
  background: transparent !important;
  background-color: transparent !important;
  border: none !important;
  box-shadow: none !important;
}

/* Hidden until pointer/focus is inside the iframe document */
body.fleekdash-iframe *::-webkit-scrollbar-thumb,
body.fleekdash-iframe::-webkit-scrollbar-thumb,
html:has(body.fleekdash-iframe)::-webkit-scrollbar-thumb {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  border-radius: 6px !important;
  transition: background 0.15s ease;
}

CSS;
    }

    /**
     * Scrollbar thumb hover states and #wpwrap scrollbar-color overrides.
     *
     * @return string
     */
    private static function getEssentialIframeScrollbarThumbHoverCss(): string
    {
        return <<<'CSS'
html.light body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb,
html.light body.fleekdash-iframe:focus-within *::-webkit-scrollbar-thumb,
html.fleek-mode-windowed-light body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb,
html.fleek-mode-windowed-light body.fleekdash-iframe:focus-within *::-webkit-scrollbar-thumb,
html:not(.dark) body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb,
html:not(.dark) body.fleekdash-iframe:focus-within *::-webkit-scrollbar-thumb,
html.light:has(body.fleekdash-iframe):hover *::-webkit-scrollbar-thumb,
html.fleek-mode-windowed-light:has(body.fleekdash-iframe):hover *::-webkit-scrollbar-thumb,
html:not(.dark):has(body.fleekdash-iframe):hover *::-webkit-scrollbar-thumb,
html.light body.fleekdash-iframe:hover::-webkit-scrollbar-thumb,
html.light body.fleekdash-iframe:focus-within::-webkit-scrollbar-thumb,
html:not(.dark) body.fleekdash-iframe:hover::-webkit-scrollbar-thumb,
html:not(.dark) body.fleekdash-iframe:focus-within::-webkit-scrollbar-thumb,
html.light:has(body.fleekdash-iframe):hover::-webkit-scrollbar-thumb,
html:not(.dark):has(body.fleekdash-iframe):hover::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.18) !important;
}

html.light body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb:hover,
html.light body.fleekdash-iframe:focus-within *::-webkit-scrollbar-thumb:hover,
html.fleek-mode-windowed-light body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb:hover,
html.fleek-mode-windowed-light body.fleekdash-iframe:focus-within *::-webkit-scrollbar-thumb:hover,
html:not(.dark) body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb:hover,
html:not(.dark) body.fleekdash-iframe:focus-within *::-webkit-scrollbar-thumb:hover,
html.light:has(body.fleekdash-iframe):hover *::-webkit-scrollbar-thumb:hover,
html:not(.dark):has(body.fleekdash-iframe):hover *::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 0, 0, 0.35) !important;
}

html.dark body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb,
html.dark body.fleekdash-iframe:focus-within *::-webkit-scrollbar-thumb,
html.fleek-mode-windowed-dark body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb,
html.fleek-mode-windowed-dark body.fleekdash-iframe:focus-within *::-webkit-scrollbar-thumb,
html.fleek-mode-protected-dark body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb,
html.fleek-mode-protected-dark body.fleekdash-iframe:focus-within *::-webkit-scrollbar-thumb,
html.dark:has(body.fleekdash-iframe):hover *::-webkit-scrollbar-thumb,
html.fleek-mode-windowed-dark:has(body.fleekdash-iframe):hover *::-webkit-scrollbar-thumb,
html.fleek-mode-protected-dark:has(body.fleekdash-iframe):hover *::-webkit-scrollbar-thumb,
html.dark body.fleekdash-iframe:hover::-webkit-scrollbar-thumb,
html.dark body.fleekdash-iframe:focus-within::-webkit-scrollbar-thumb,
html.dark:has(body.fleekdash-iframe):hover::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.1) !important;
}

html.dark body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb:hover,
html.dark body.fleekdash-iframe:focus-within *::-webkit-scrollbar-thumb:hover,
html.fleek-mode-windowed-dark body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb:hover,
html.fleek-mode-protected-dark body.fleekdash-iframe:hover *::-webkit-scrollbar-thumb:hover,
html.dark:has(body.fleekdash-iframe):hover *::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.3) !important;
}

body.fleekdash-iframe #wpwrap,
body.fleekdash-iframe #wpcontent,
body.fleekdash-iframe #wpbody-content {
  scrollbar-color: transparent transparent !important;
}

html.light body.fleekdash-iframe:hover #wpwrap,
html.light body.fleekdash-iframe:hover #wpcontent,
html.light body.fleekdash-iframe:hover #wpbody-content,
html.light body.fleekdash-iframe:focus-within #wpwrap,
html.light body.fleekdash-iframe:focus-within #wpcontent,
html.light body.fleekdash-iframe:focus-within #wpbody-content,
html:not(.dark) body.fleekdash-iframe:hover #wpwrap,
html:not(.dark) body.fleekdash-iframe:hover #wpcontent,
html:not(.dark) body.fleekdash-iframe:hover #wpbody-content,
html:not(.dark) body.fleekdash-iframe:focus-within #wpwrap,
html:not(.dark) body.fleekdash-iframe:focus-within #wpcontent,
html:not(.dark) body.fleekdash-iframe:focus-within #wpbody-content {
  scrollbar-color: rgba(0, 0, 0, 0.18) transparent !important;
}

html.dark body.fleekdash-iframe:hover #wpwrap,
html.dark body.fleekdash-iframe:hover #wpcontent,
html.dark body.fleekdash-iframe:hover #wpbody-content,
html.dark body.fleekdash-iframe:focus-within #wpwrap,
html.dark body.fleekdash-iframe:focus-within #wpcontent,
html.dark body.fleekdash-iframe:focus-within #wpbody-content,
html.fleek-mode-windowed-dark body.fleekdash-iframe:hover #wpwrap,
html.fleek-mode-protected-dark body.fleekdash-iframe:hover #wpwrap,
html.fleek-mode-windowed-dark body.fleekdash-iframe:focus-within #wpwrap,
html.fleek-mode-protected-dark body.fleekdash-iframe:focus-within #wpwrap {
  scrollbar-color: rgba(255, 255, 255, 0.18) transparent !important;
}

CSS;
    }

    /**
     * Native WP thickbox / plugin-details iframes — no FleekDash scrollbar-gutter (auto only).
     *
     * @return string
     */
    private static function getNativeWordPressSubframeScrollbarGutterCss(): string
    {
        return <<<'CSS'

/*
 * WP sub-iframes + Gutenberg editor canvas (editor-canvas blob document).
 * body.iframe = thickbox; body#plugin-information = plugin details;
 * .block-editor-iframe__* = post/page block editor iframe.
 */
html[class*="fleek-mode-"]:has(body.iframe),
html[class*="fleek-mode-"]:has(body#plugin-information),
html[class*="fleek-mode-"]:has(body.block-editor-iframe__body),
html:has(body.fleekdash-iframe.iframe),
html:has(body.fleekdash-iframe#plugin-information),
html:has(body.block-editor-iframe__body),
html.block-editor-iframe__html,
html[class*="fleek-mode-"] body.iframe,
html[class*="fleek-mode-"] body#plugin-information,
html[class*="fleek-mode-"] body.block-editor-iframe__body,
body.fleekdash-iframe.iframe,
body.fleekdash-iframe#plugin-information,
body#plugin-information.fleekdash-iframe,
body.block-editor-iframe__body,
body.fleekdash-iframe.iframe #plugin-information-scrollable,
body#plugin-information #plugin-information-scrollable {
  scrollbar-gutter: auto !important;
}

CSS;
    }

    /**
     * Minimal scrollbar CSS for document.write in blocking admin_head script (before body paint).
     * Uses html.fleek-mode-* so rules apply as soon as the blocking script sets mode on <html>.
     *
     * @return string
     */
    public static function getCriticalScrollbarCssForFirstPaint(): string
    {
        return <<<'CSS'
html[class*="fleek-mode-"] {
  overflow-x: hidden !important;
  overflow-y: hidden !important;
  scrollbar-width: thin !important;
  scrollbar-color: transparent transparent !important;
  scrollbar-gutter: auto !important;
}
html[class*="fleek-mode-"] body,
body.fleekdash-iframe {
  overflow-x: hidden !important;
  scrollbar-width: thin !important;
  scrollbar-color: transparent transparent !important;
  scrollbar-gutter: auto !important;
}
html[class*="fleek-mode-"] body::-webkit-scrollbar,
html[class*="fleek-mode-"] body *::-webkit-scrollbar,
body.fleekdash-iframe::-webkit-scrollbar,
body.fleekdash-iframe *::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
html[class*="fleek-mode-"] body::-webkit-scrollbar-button,
html[class*="fleek-mode-"] body *::-webkit-scrollbar-button,
body.fleekdash-iframe::-webkit-scrollbar-button,
body.fleekdash-iframe *::-webkit-scrollbar-button {
  display: none;
  width: 0 !important;
  height: 0 !important;
}
html[class*="fleek-mode-"] body::-webkit-scrollbar-track,
html[class*="fleek-mode-"] body *::-webkit-scrollbar-track,
body.fleekdash-iframe::-webkit-scrollbar-track,
body.fleekdash-iframe *::-webkit-scrollbar-track {
  background: transparent !important;
}
html[class*="fleek-mode-"] body::-webkit-scrollbar-thumb,
html[class*="fleek-mode-"] body *::-webkit-scrollbar-thumb,
body.fleekdash-iframe::-webkit-scrollbar-thumb,
body.fleekdash-iframe *::-webkit-scrollbar-thumb {
  background: transparent !important;
  border: none !important;
}
CSS
            . self::getNativeWordPressSubframeScrollbarGutterCss();
    }

    /**
     * Enqueue customizer CSS (non-protected mode only)
     *
     * @return void
     */
    public static function enqueueCustomizerCSS()
    {
        // Check if we're in protected mode (fleek-window protection)
        if (isset($_GET['protected']) && $_GET['protected'] === 'true') {
            return; // Don't load FleekDash styles in protected mode
        }

        \wp_enqueue_style(
            'fleekdash-customizer',
            \FleekDash\Libs\Assets\getCssUrl('customizer'),
            array(),
            defined('FLEEKDASH_VERSION') ? FLEEKDASH_VERSION : '1.0'
        );
    }

    /**
     * Hide native #wpadminbar and reset wp-toolbar offsets when PHP sets fleekdash-adminbar-hidden.
     *
     * @return string
     */
    private static function getNativeAdminBarHiddenClassCss(): string
    {
        return <<<'CSS'
body.fleekdash-adminbar-hidden #wpadminbar,
html.fleekdash-inside-iframe body.fleekdash-iframe:not(.fleekdash-adminbar-native-visible) #wpadminbar,
body.fleekdash-iframe.inside-iframe:not(.fleekdash-adminbar-native-visible) #wpadminbar {
  display: none !important;
  visibility: hidden !important;
  opacity: 0 !important;
}

body.fleekdash-adminbar-hidden,
body.fleekdash-adminbar-hidden.admin-bar,
html.fleekdash-inside-iframe body.fleekdash-iframe:not(.fleekdash-adminbar-native-visible),
html.fleekdash-inside-iframe body.fleekdash-iframe:not(.fleekdash-adminbar-native-visible).admin-bar,
body.fleekdash-iframe.inside-iframe:not(.fleekdash-adminbar-native-visible),
html.wp-toolbar:has(body.fleekdash-adminbar-hidden),
html.admin-bar:has(body.fleekdash-adminbar-hidden),
html.fleekdash-inside-iframe:has(body.fleekdash-iframe:not(.fleekdash-adminbar-native-visible)) {
  padding-top: 0 !important;
  margin-top: 0 !important;
}
CSS;
    }

    /**
     * First-paint hide before {@code <body>} exists (blocking admin_head sets html.fleekdash-inside-iframe).
     *
     * Must not depend on body.fleekdash-iframe or admin_body_class — those apply when the body tag
     * opens, after this CSS is injected. Uses :has(body.fleekdash-adminbar-native-visible) so block/site
     * editor pages stop matching once the body class is present. Callers skip injection when
     * {@see EmbeddedShellAdminBarPolicy::isNativeAdminBarVisibleInEmbed()} is true (block/site editor).
     *
     * @return string
     */
    public static function getCriticalAdminBarHideCssForFirstPaint(): string
    {
        return <<<'CSS'
html.fleekdash-inside-iframe:not(:has(body.fleekdash-adminbar-native-visible)) #wpadminbar {
  display: none !important;
  visibility: hidden !important;
  opacity: 0 !important;
}

html.fleekdash-inside-iframe:not(:has(body.fleekdash-adminbar-native-visible)) {
  padding-top: 0 !important;
  margin-top: 0 !important;
}
CSS;
    }

    /**
     * First-paint #wpwrap surface before WP 7 WPDS / boot-layout CSS paints fg tokens as background.
     *
     * Injected via blocking admin_head (document.write). Uses --card when palette vars exist,
     * with starter palette fallbacks per html.light / html.dark (set by the same blocking script).
     *
     * @return string
     */
    public static function getCriticalWpwrapSurfaceCssForFirstPaint(): string
    {
        $cardSelectors = self::getWpwrapCardSurfaceSelectors();

        return <<<CSS
html:not(.fleek-mode-trusted) body.wp-admin #wpwrap,
html.fleekdash-inside-iframe:not(.fleek-mode-trusted) #wpwrap,
html.fleekdash-inside-iframe:not(.fleek-mode-trusted) body #wpwrap,
{$cardSelectors} {
  background-color: var(--card, #ffffff) !important;
  background: var(--card, #ffffff) !important;
}

html.dark:not(.fleek-mode-trusted) body.wp-admin #wpwrap,
html.dark.fleekdash-inside-iframe:not(.fleek-mode-trusted) #wpwrap,
html.dark.fleekdash-inside-iframe:not(.fleek-mode-trusted) body #wpwrap,
html.dark:not(.fleek-mode-trusted) #wpwrap:has(.boot-layout),
html.dark:not(.fleek-mode-trusted) body.dialog-body #wpwrap {
  background-color: var(--card, #101722) !important;
  background: var(--card, #101722) !important;
}

html.fleek-mode-trusted.fleekdash-inside-iframe #wpwrap,
html.fleekdash-inside-iframe.fleek-mode-trusted #wpwrap,
html.fleek-mode-trusted body.wp-admin #wpwrap,
html.fleek-mode-trusted #wpwrap {
  background: transparent !important;
  background-color: transparent !important;
}
CSS;
    }

    /**
     * Shared selectors for #wpwrap card surface (late inline + wp-components override).
     *
     * @return string
     */
    private static function getWpwrapCardSurfaceSelectors(): string
    {
        return <<<'CSS'
html:not(.fleek-mode-trusted) body:has(.inside-iframe) #wpwrap,
html.fleekdash-inside-iframe:not(.fleek-mode-trusted) #wpwrap,
html:not(.fleek-mode-trusted):has(.dialog-body),
html:not(.fleek-mode-trusted) body.dialog-body,
html:not(.fleek-mode-trusted) body.dialog-body #wpwrap,
html:not(.fleek-mode-trusted) #wpwrap:has(.boot-layout)
CSS;
    }

    /**
     * Late override: force #wpwrap to --card after WP admin / WPDS styles load.
     *
     * @return string
     */
    private static function getWpwrapCardBackgroundOverrideCss(): string
    {
        $cardSelectors = self::getWpwrapCardSurfaceSelectors();

        return <<<CSS

html:not(.fleek-mode-trusted) body.wp-admin #wpwrap,
{$cardSelectors} {
  background: var(--card, #ffffff) !important;
  background-color: var(--card, #ffffff) !important;
}

html.dark:not(.fleek-mode-trusted) body.wp-admin #wpwrap {
  background: var(--card, #101722) !important;
  background-color: var(--card, #101722) !important;
}

html.fleek-mode-trusted,
html.fleek-mode-trusted body:has(.inside-iframe),
html.fleek-mode-trusted body:has(.inside-iframe) #wpwrap,
html.fleek-mode-trusted.fleekdash-inside-iframe #wpwrap,
html.fleekdash-inside-iframe.fleek-mode-trusted #wpwrap,
html.fleek-mode-trusted body.wp-admin #wpwrap,
html.fleek-mode-trusted #wpwrap {
  background: transparent !important;
  background-color: transparent !important;
}

CSS;
    }

    /**
     * Enqueue essential iframe styles
     *
     * Includes critical CSS for hiding WordPress elements and
     * resetting margins/padding for clean iframe display.
     *
     * @return void
     */
    public static function enqueueEssentialStyles()
    {
        // CRITICAL FIX: Prevent duplicate CSS loading
        if (wp_style_is('fleekdash-essential-iframe', 'enqueued') || wp_style_is('fleekdash-essential-iframe', 'registered')) {
            return; // CSS already loaded, skip
        }

        // Register and enqueue essential iframe styles
        \wp_register_style(
            'fleekdash-essential-iframe',
            false, // No external file
            array(),
            FLEEKDASH_VERSION,
        );
        \wp_enqueue_style('fleekdash-essential-iframe');

        // Add essential iframe-specific styles that are always needed
        \wp_add_inline_style('fleekdash-essential-iframe', "
            /* Hide default WP elements - ESSENTIAL for all iframes */
            #wp-auth-check-wrap,
            #wp-auth-check,
            #adminmenumain,
            #adminmenuwrap,
            #adminmenuback,
            #wpfooter,
            #screen-meta,
            #screen-meta-links,
            .editor-header__back-button,
            .notice,
            .updated,
            .update-nag,
            .error,
            .plugin-update-tr,
            .is-dismissible {
                display: none !important;
                visibility: hidden !important;
                opacity: 0 !important;
            }

            " . self::getNativeAdminBarHiddenClassCss() . "

            /* Remove any border from the content */
            body #wpwrap #wpcontent {
            border-left: none !important;
            border-color: transparent !important;
            }

            /* Reset margins and padding */
            #wpcontent,
            #wpbody-content,
            #wpwrap {
                margin: 0 !important;
                padding: 10px !important;
            }

            #wpwrap {
                margin: 0 !important;
                padding: 0 !important;
            }

            " . self::getEssentialIframeLayoutAndScrollbarCss() . "
        ");
    }

    /**
     * Whether the current admin screen uses the block editor shell (not classic editor lists/forms).
     *
     * @return bool
     */
    public static function shouldLoadBlockEditorCssBundle(): bool
    {
        global $pagenow;

        $shouldLoad = false;

        if (isset($pagenow) && $pagenow === 'site-editor.php') {
            $shouldLoad = true;
        } elseif (
            isset($pagenow)
            && \in_array($pagenow, ['post.php', 'post-new.php'], true)
            && \function_exists('use_block_editor_for_post')
            && \function_exists('use_block_editor_for_post_type')
        ) {
            if ($pagenow === 'post-new.php') {
                $post_type = isset($_GET['post_type'])
                    ? \sanitize_key((string) $_GET['post_type'])
                    : 'post';
                $shouldLoad = (bool) \use_block_editor_for_post_type($post_type);
            } elseif (isset($_GET['post'])) {
                $post_id = (int) $_GET['post'];
                $post = $post_id > 0 ? \get_post($post_id) : null;
                $shouldLoad = $post instanceof \WP_Post && (bool) \use_block_editor_for_post($post);
            }
        }

        return $shouldLoad;
    }

    /**
     * CSS bundle entry for the current admin screen (index vs gutenberg-index).
     *
     * @return string
     */
    public static function getAdminSkinCssEntry(): string
    {
        return self::shouldLoadBlockEditorCssBundle() ? 'gutenberg-index' : 'index';
    }

    /**
     * Enqueue design system tokens CSS for wp-admin iframe embeds.
     *
     * Uses iframe-tokens.css (fonts + CSS variables only — no Tailwind) so third-party
     * class names are not overridden. In protected mode we skip index.css (full admin skin).
     * Block editor screens load gutenberg-index.css instead of index.css to avoid forms/tables skins.
     *
     * @return void
     */
    public static function enqueueDesignSystemTokens()
    {
        $isProtectedMode = isset($_GET['protected']) && $_GET['protected'] === 'true';

        if (!wp_style_is('fleekdash-css-iframe-tokens', 'enqueued') && !wp_style_is('fleekdash-css-iframe-tokens', 'registered')) {
            \wp_enqueue_style(
                'fleekdash-css-iframe-tokens',
                \FleekDash\Libs\Assets\getIframeTokensCssUrl(),
                array(),
                \FleekDash\Libs\Assets\getIframeTokensCssVersion(),
            );
        }

        // In protected mode, stop after exposing tokens only (no full index.css).
        if ($isProtectedMode) {
            global $pagenow;
            // Theme install relies on FleekDash themes.css (bundled in index.css when not protected).
            if (
                isset($pagenow) && $pagenow === 'theme-install.php'
                && !wp_style_is('fleekdash-themes-iframe', 'enqueued')
                && !wp_style_is('fleekdash-themes-iframe', 'registered')
            ) {
                \wp_enqueue_style(
                    'fleekdash-themes-iframe',
                    \FleekDash\Libs\Assets\getCssUrl('themes'),
                    array('fleekdash-css-iframe-tokens'),
                    \FleekDash\Libs\Assets\getCssVersion('themes'),
                );
            }
            return;
        }

        $useBlockEditorBundle = self::shouldLoadBlockEditorCssBundle();
        $cssEntry = self::getAdminSkinCssEntry();
        $styleHandle = $useBlockEditorBundle ? 'fleekdash-css-gutenberg-index' : 'fleekdash-css-includes';

        \wp_enqueue_style(
            $styleHandle,
            \FleekDash\Libs\Assets\getCssUrl($cssEntry),
            array('fleekdash-css-iframe-tokens'),
            \FleekDash\Libs\Assets\getCssVersion($cssEntry),
        );

        // Add design system specific styles
        \wp_add_inline_style($styleHandle, "
            /* Reset the default WordPress background */
            html.wp-toolbar,
            #wpwrap,
            #wpcontent,
            #wpbody,
            #wpbody-content {
                color: var(--foreground) !important;
                margin: 0 !important;
                /* padding: 0 !important; Removed to avoid stripping admin bar compensation */
            }

            body.wp-admin {
                color: var(--foreground) !important;
                margin: 0 !important;
                /* Don't force padding: 0 on body, let admin-bar compensation work */
            }

        " . self::getWpwrapCardBackgroundOverrideCss() . self::getIframeCardSurfaceOverridesCss());

        ThirdPartyEditorCssManager::enqueueActiveStyles($styleHandle);

        self::enqueueWpdsBridgeLate($styleHandle);
    }

    /**
     * Load WPDS bridge after WordPress admin color / WPDS styles (WP 7 sets #3858e9 on body).
     *
     * @param string $parentHandle fleekdash-css-includes or fleekdash-css-gutenberg-index
     * @return void
     */
    public static function enqueueWpdsBridgeLate(string $parentHandle): void
    {
        if (
            wp_style_is('fleekdash-wpds-bridge-late', 'enqueued')
            || wp_style_is('fleekdash-wpds-bridge-late', 'registered')
        ) {
            return;
        }

        $deps = array($parentHandle);
        $wp_style_handles = array(
            'wp-admin',
            'common',
            'forms',
            'admin-menu',
            'list-tables',
            'edit',
            'dashboard',
            'site-health',
            'wp-components',
        );

        foreach ($wp_style_handles as $handle) {
            if (wp_style_is($handle, 'registered') || wp_style_is($handle, 'enqueued')) {
                $deps[] = $handle;
            }
        }

        \wp_enqueue_style(
            'fleekdash-wpds-bridge-late',
            \FleekDash\Libs\Assets\getCssUrl('wpds-bridge'),
            array_values(array_unique($deps)),
            \FleekDash\Libs\Assets\getCssVersion('wpds-bridge'),
        );

        \wp_add_inline_style(
            'fleekdash-wpds-bridge-late',
            self::getWpwrapCardBackgroundOverrideCss(),
        );

        if (\wp_style_is('wp-components', 'registered') || \wp_style_is('wp-components', 'enqueued')) {
            \wp_add_inline_style('wp-components', self::getWpwrapCardBackgroundOverrideCss());
        }
    }

    /**
     * Force iframe admin chrome to use --card instead of page --background.
     *
     * gutenberg.css / index.css still reference --background on shells; this wins after bundle load.
     *
     * @return string
     */
    private static function getIframeCardSurfaceOverridesCss(): string
    {
        return <<<'CSS'

            /* Non-trusted iframe: WP admin shell + Gutenberg chrome use card surfaces */
            html:not(.fleek-mode-trusted) #wpcontent,
            html:not(.fleek-mode-trusted) #wpbody,
            html:not(.fleek-mode-trusted) #wpbody-content {
                background: var(--card) !important;
            }

            html:not(.fleek-mode-trusted) body #wpwrap .editor-editor-interface .editor-post-publish-panel,
            html:not(.fleek-mode-trusted) body #wpwrap .editor-editor-interface .postbox-header,
            html:not(.fleek-mode-trusted) body #wpwrap .editor-editor-interface .block-editor-tabbed-sidebar,
            html:not(.fleek-mode-trusted) body #wpwrap .editor-editor-interface .block-editor-block-breadcrumb,
            html:not(.fleek-mode-trusted) body #wpwrap .editor-editor-interface .interface-navigable-region,
            html:not(.fleek-mode-trusted) body #wpwrap .editor-editor-interface .editor-header,
            html:not(.fleek-mode-trusted) body #wpwrap .editor-editor-interface .editor-sidebar,
            html:not(.fleek-mode-trusted) body #wpwrap .editor-editor-interface .interface-complementary-area,
            html:not(.fleek-mode-trusted) body #wpwrap .editor-editor-interface .block-editor-block-parent-selector {
                background: var(--card) !important;
            }

CSS;
    }

    /**
     * Enqueue admin bar styles for FleekDash iframe embeds.
     *
     * Loads FleekDash toolbar skin only when WordPress is showing the native admin bar.
     * When hidden, {@see EmbeddedShellAdminBarPolicy::apply} sets body.fleekdash-adminbar-hidden;
     * essential iframe CSS handles display/offset (no URL re-parse here).
     *
     * @return void
     */
    public static function enqueueAdminBarStyles()
    {
        // CRITICAL FIX: Prevent duplicate CSS loading
        if (wp_style_is('fleekdash-admin-bar', 'enqueued') || wp_style_is('fleekdash-admin-bar', 'registered')) {
            return; // CSS already loaded, skip
        }

        $wp_toolbar_visible = \function_exists('is_admin_bar_showing') && \is_admin_bar_showing();

        if (!$wp_toolbar_visible) {
            return;
        }

        // Use getCssUrl() helper to get correct path (dev: includes/css, prod: assets)
        // This ensures the CSS file is found correctly in both development and production
        // The Vite build process copies admin-bar.css from includes/css/ to assets/ in production
        // Depend on WordPress default admin-bar CSS to ensure proper loading order
        \wp_enqueue_style(
            'fleekdash-admin-bar',
            \FleekDash\Libs\Assets\getCssUrl('admin-bar'),
            array('admin-bar'), // Depend on WordPress default admin-bar CSS
            FLEEKDASH_VERSION,
            'all' // Media type
        );
    }
}
