/* ============================================================================
 * BE Platform — UI Primitives
 *
 * Tiny, theme-able CSS primitives shared by the wp-* plugins. Loaded only
 * when a consumer plugin opts in via:
 *
 *     wp_enqueue_style( 'be-platform-ui' );
 *
 * No selectors here apply automatically — every class is opt-in via markup.
 *
 * Conventions:
 *   - All public class names use the `be-platform-` prefix.
 *   - All keyframes use the `be-platform-` prefix.
 *   - Tunable values are read via `var(--be-platform-*, fallback)` with
 *     sensible defaults. Consumers can override a property by setting it
 *     on the primitive element itself, on any ancestor (it inherits down),
 *     or on `:root` for site-wide theming. Defaults are NOT redeclared on
 *     the primitive's element so parent-level overrides cascade correctly.
 *   - No !important except where required to defeat Elementor / theme rules
 *     (only `.be-platform-scroll-lock-doc body`).
 *
 * Source duplication consolidated here:
 *   - .be-social-section-divider, .hcs-section-divider          -> .be-platform-section-divider
 *   - .be-social-validation-separator, .hcs-precheck-divider    -> .be-platform-rule
 *   - .be-social-lightbox__loader span, .hcs-loader-spinner,
 *     .scg-preloader-spinner                                    -> .be-platform-spinner
 *   - .be-social-lightbox__loader, .hcs-loader (overlay shell)  -> .be-platform-loader
 *   - .be-social-lightbox-open (body lock)                      -> .be-platform-scroll-lock-body
 *   - .hcs-intro-immersive-lock (html + body lock)              -> .be-platform-scroll-lock-doc
 * ============================================================================ */


/* ----------------------------------------------------------------------------
 * Section divider — full-width rule with a centred label.
 *
 *   <div class="be-platform-section-divider"><span>Section title</span></div>
 *
 * Renders as: ──────── Section title ────────
 *
 * Used inside Elementor RAW_HTML controls (see
 * BE\Platform\Elementor\Widget_Base::add_section_divider() once #2 lands).
 * ---------------------------------------------------------------------------- */

.be-platform-section-divider {
  display: flex;
  align-items: center;
  gap: var(--be-platform-section-divider-gap, 10px);
  font-size: 12px;
  font-weight: 600;
  color: var(--be-platform-section-divider-color, rgba(0, 0, 0, 0.45));
}

.be-platform-section-divider::before,
.be-platform-section-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--be-platform-section-divider-rule, rgba(0, 0, 0, 0.15));
}


/* ----------------------------------------------------------------------------
 * Rule — thin horizontal separator for panel sections.
 *
 *   <hr class="be-platform-rule" />
 *
 * Replaces the duplicated .be-social-validation-separator and
 * .hcs-precheck-divider patterns. Default margin matches both originals.
 * ---------------------------------------------------------------------------- */

.be-platform-rule {
  margin: var(--be-platform-rule-margin, 12px 0 10px);
  border: 0;
  border-top: 1px solid var(--be-platform-rule-color, rgba(0, 0, 0, 0.12));
}

/* Cosmetic SELECT2 dropdown separator emitted by PanelChromeTrait.
   Elementor's options API cannot produce a true disabled <hr> item, so the
   sentinel option is styled into a non-text rule when Select2 renders it. */
.select2-results__option[id*="__be_platform_select_separator__"] {
  display: flex;
  align-items: center;
  min-height: 18px;
  padding-block: 6px;
  color: transparent;
  pointer-events: none;
}

.select2-results__option[id*="__be_platform_select_separator__"]::before {
  content: "";
  flex: 1;
  height: 1px;
  background: rgba(0, 0, 0, 0.16);
}


/* ----------------------------------------------------------------------------
 * Spinner — single rotating ring.
 *
 *   <span class="be-platform-spinner" role="status" aria-label="Loading"></span>
 *
 * Sized 48px / 3px stroke / 1.1s revolution by default to match the BSM
 * lightbox loader and HCS curtain loader. Override per-context via the
 * exposed custom properties:
 *
 *   .my-tile .be-platform-spinner {
 *     --be-platform-spinner-size: 36px;
 *     --be-platform-spinner-track: rgba(255,255,255,0.25);
 *     --be-platform-spinner-color: #fff;
 *     --be-platform-spinner-duration: 0.9s;
 *   }
 * ---------------------------------------------------------------------------- */

.be-platform-spinner {
  display: inline-block;
  width: var(--be-platform-spinner-size, 48px);
  height: var(--be-platform-spinner-size, 48px);
  border-radius: 50%;
  border: var(--be-platform-spinner-thickness, 3px) solid var(--be-platform-spinner-track, rgba(0, 0, 0, 0.3));
  border-top-color: var(--be-platform-spinner-color, #000);
  animation: be-platform-spin var(--be-platform-spinner-duration, 1.1s) linear infinite;
}

@keyframes be-platform-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* Respect users with vestibular sensitivities — slow the spin to a crawl
 * rather than freeze it (a frozen spinner reads as broken, but a 6s rotation
 * is barely perceptible motion). */
@media (prefers-reduced-motion: reduce) {
  .be-platform-spinner {
    animation-duration: 6s;
  }
}


/* ----------------------------------------------------------------------------
 * Loader — centred spinner overlay.
 *
 *   <div class="be-platform-loader">
 *     <span class="be-platform-spinner"></span>
 *     <p class="be-platform-loader__text">Loading…</p>
 *   </div>
 *
 * The loader fills its nearest positioned ancestor (typically a card / tile /
 * lightbox media wrap with `position: relative`). The optional text element
 * is purely opt-in markup — any content can sit alongside the spinner.
 *
 * Use the `--hidden` modifier (or set `hidden`) to fade out without taking
 * the element out of layout, so the surrounding container doesn't reflow.
 * ---------------------------------------------------------------------------- */

.be-platform-loader {
  position: absolute;
  inset: 0;
  z-index: var(--be-platform-loader-z-index, 5);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--be-platform-loader-gap, 14px);
  background: var(--be-platform-loader-bg, transparent);
  transition: opacity var(--be-platform-loader-fade, 180ms) linear;
}

.be-platform-loader--hidden {
  opacity: 0;
  pointer-events: none;
}

.be-platform-loader__text {
  margin: 0;
  color: #000;
  font-size: 14px;
  letter-spacing: 0.03em;
}


/* ----------------------------------------------------------------------------
 * Scroll lock — body variant.
 *
 * Add `be-platform-scroll-lock-body` to <body> while a modal / lightbox /
 * overlay is open to prevent the page from scrolling behind it. Suitable for
 * lightboxes and dialogs that don't need to override aggressive theme rules.
 *
 *   document.body.classList.add('be-platform-scroll-lock-body');
 * ---------------------------------------------------------------------------- */

.be-platform-scroll-lock-body {
  overflow: hidden;
}


/* ----------------------------------------------------------------------------
 * Scroll lock — document variant (aggressive).
 *
 * Add `be-platform-scroll-lock-doc` to <html> for full-viewport immersive
 * states (e.g. an intro overlay that must defeat theme styles applying
 * `overflow: auto !important` to <body>).
 *
 *   document.documentElement.classList.add('be-platform-scroll-lock-doc');
 *
 * Mirrors the HCS .hcs-intro-immersive-lock pattern. Uses !important on
 * <body> deliberately because Elementor / many themes set body overflow
 * with !important themselves.
 * ---------------------------------------------------------------------------- */

.be-platform-scroll-lock-doc,
.be-platform-scroll-lock-doc body {
  overflow: hidden !important;
}


/* ----------------------------------------------------------------------------
 * Diagnostics — per-plugin pre-flight report rendered on the BE Platform
 * Pre-flight admin page (and optionally inline inside a consumer plugin's
 * own diagnostics panel).
 *
 * Emitted by \BE\Platform\Diagnostics\Renderer as:
 *
 *   <section class="be-platform-diagnostics be-platform-diagnostics--{status}"
 *            data-plugin-id="…" data-status="…">
 *     <header class="be-platform-diagnostics__header">
 *       <h3 class="be-platform-diagnostics__title">Plugin Name</h3>
 *       <span class="be-platform-diagnostics__status
 *                    be-platform-diagnostics__status--{status}">{STATUS}</span>
 *     </header>
 *     <ul class="be-platform-diagnostics__list">
 *       <li class="be-platform-diagnostics__entry
 *                  be-platform-diagnostics__entry--{severity}">
 *         <span class="be-platform-diagnostics__severity
 *                      be-platform-diagnostics__severity--{severity}">{SEVERITY}</span>
 *         <span class="be-platform-diagnostics__message">{message}</span>
 *       </li>
 *     </ul>
 *   </section>
 *
 * Severity palette uses OKLCH for perceptual uniformity. The section-level
 * status modifier adds a left-border stripe matching the worst severity
 * present; each entry carries its own severity badge alongside the message.
 *
 * Consumers can override the palette by setting `--be-platform-diagnostics-{pass,warning,error,neutral}`
 * on any ancestor (or `:root` for site-wide theming).
 * ---------------------------------------------------------------------------- */

.be-platform-diagnostics {
  display: block;
  margin-block-end: 16px;
  background: var(--be-platform-diagnostics-bg, rgba(0, 0, 0, 0.02));
  border: 1px solid var(--be-platform-diagnostics-border, rgba(0, 0, 0, 0.08));
  border-inline-start: var(--be-platform-diagnostics-stripe, 4px) solid
    var(--be-platform-diagnostics-neutral, rgba(0, 0, 0, 0.4));
  border-radius: var(--be-platform-diagnostics-radius, 6px);
  padding: 12px 16px;
}

.be-platform-diagnostics--pass    { border-inline-start-color: var(--be-platform-diagnostics-pass,    oklch(62% 0.15 145)); }
.be-platform-diagnostics--warning { border-inline-start-color: var(--be-platform-diagnostics-warning, oklch(75% 0.15 80));  }
.be-platform-diagnostics--error   { border-inline-start-color: var(--be-platform-diagnostics-error,   oklch(58% 0.22 25));  }

.be-platform-diagnostics__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-block-end: 12px;
}

.be-platform-diagnostics__title {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
}

.be-platform-diagnostics__status {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: #fff;
  background: var(--be-platform-diagnostics-neutral, rgba(0, 0, 0, 0.4));
}

.be-platform-diagnostics__status--pass    { background: var(--be-platform-diagnostics-pass,    oklch(62% 0.15 145)); }
.be-platform-diagnostics__status--warning { background: var(--be-platform-diagnostics-warning, oklch(75% 0.15 80));  }
.be-platform-diagnostics__status--error   { background: var(--be-platform-diagnostics-error,   oklch(58% 0.22 25));  }

.be-platform-diagnostics__list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.be-platform-diagnostics__entry {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding-block: 6px;
  border-block-start: 1px solid var(--be-platform-diagnostics-border, rgba(0, 0, 0, 0.08));
}

.be-platform-diagnostics__list > .be-platform-diagnostics__entry:first-child {
  border-block-start: 0;
}

.be-platform-diagnostics__severity {
  flex: 0 0 auto;
  display: inline-block;
  min-width: 68px;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: #fff;
  text-align: center;
  background: var(--be-platform-diagnostics-neutral, rgba(0, 0, 0, 0.4));
}

.be-platform-diagnostics__severity--pass    { background: var(--be-platform-diagnostics-pass,    oklch(62% 0.15 145)); }
.be-platform-diagnostics__severity--warning { background: var(--be-platform-diagnostics-warning, oklch(75% 0.15 80));  }
.be-platform-diagnostics__severity--error   { background: var(--be-platform-diagnostics-error,   oklch(58% 0.22 25));  }

.be-platform-diagnostics__message {
  flex: 1 1 auto;
  font-size: 13px;
  line-height: 1.5;
  color: rgba(0, 0, 0, 0.85);
}

.be-platform-diagnostics__entry--empty .be-platform-diagnostics__message {
  color: rgba(0, 0, 0, 0.5);
  font-style: italic;
}

.be-platform-diagnostics-empty {
  margin-block-start: 16px;
  padding: 16px;
  background: var(--be-platform-diagnostics-bg, rgba(0, 0, 0, 0.02));
  border: 1px dashed rgba(0, 0, 0, 0.2);
  border-radius: var(--be-platform-diagnostics-radius, 6px);
  color: rgba(0, 0, 0, 0.6);
  font-style: italic;
}


/* ----------------------------------------------------------------------------
 * Overview page (BE Platform > Overview)
 *
 *   <div class="be-platform-overview">
 *     <table class="widefat striped be-platform-overview__table">
 *       ...
 *       <span class="be-platform-overview__status be-platform-overview__status--up-to-date">Up to date</span>
 *     </table>
 *   </div>
 *
 * Status badges reuse the diagnostics color palette (OKLCH greens /
 * ambers / reds) so "Up to date" / "Update available" feel consistent
 * with Pre-flight's Pass / Warning / Error.
 * ---------------------------------------------------------------------------- */

.be-platform-overview__intro {
  margin-block: 12px 18px;
  max-width: 900px;
  color: rgba(0, 0, 0, 0.7);
}

.be-platform-overview__refresh {
  margin-inline-start: 8px;
}

.be-platform-overview__table {
  margin-block-start: 12px;
}

.be-platform-overview__table th,
.be-platform-overview__table td {
  vertical-align: top;
}

.be-platform-overview__table td code {
  font-size: 11px;
  color: rgba(0, 0, 0, 0.55);
}

.be-platform-overview__status {
  display: inline-block;
  padding: 3px 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  color: #fff;
  border-radius: 999px;
  background: var(--be-platform-overview-status-neutral, rgba(0, 0, 0, 0.4));
}

.be-platform-overview__status--up-to-date       { background: var(--be-platform-diagnostics-pass,    oklch(62% 0.15 145)); }
.be-platform-overview__status--update-available { background: var(--be-platform-diagnostics-warning, oklch(75% 0.15 80));  }
.be-platform-overview__status--ahead            { background: var(--be-platform-diagnostics-info,    oklch(65% 0.12 230)); }
.be-platform-overview__status--unknown          { background: var(--be-platform-overview-status-neutral, rgba(0, 0, 0, 0.4)); }

.be-platform-overview__action-note {
  color: rgba(0, 0, 0, 0.5);
  font-size: 12px;
  font-style: italic;
}

.be-platform-overview__result {
  display: inline-block;
  padding: 4px 8px;
  font-size: 12px;
  border-radius: 4px;
}

.be-platform-overview__result--success {
  color: oklch(35% 0.15 145);
  background: oklch(95% 0.04 145);
  border: 1px solid oklch(75% 0.12 145);
}

.be-platform-overview__result--error {
  color: oklch(35% 0.2 25);
  background: oklch(95% 0.04 25);
  border: 1px solid oklch(75% 0.15 25);
}


/* ============================================================================
 * Admin-page chrome — greyscale palette shared by all four BE Platform pages
 * (Overview, Integrations, Settings, Pre-flight).
 *
 * Scoped tightly to wrappers we control (`.be-platform-overview`,
 * `.be-platform-integrations`, `.be-platform-settings`, `.be-platform-preflight`)
 * so we never bleed into other admin screens that happen to load this stylesheet.
 *
 * Design intent: a calm, uniform monochrome surface that lets badges + form
 * controls do the talking. Field labels stay on the left, controls on the right
 * (WordPress's `form-table` default — we don't override that geometry).
 * Inline `<p class="description">` help text stays as-is — no tooltip icons.
 *
 * All tunable values are exposed as `--be-platform-admin-*` custom properties
 * so a downstream admin theme could re-tint the entire chrome by overriding a
 * few variables on `:root.wp-admin`.
 * ---------------------------------------------------------------------------- */

.be-platform-overview,
.be-platform-integrations,
.be-platform-settings,
.be-platform-preflight {
  --be-platform-admin-bg:        #f3f3f3;
  --be-platform-admin-card-bg:   #ffffff;
  --be-platform-admin-border:    #d8d8d8;
  --be-platform-admin-rule:      #e6e6e6;
  --be-platform-admin-text:      #2c2c2c;
  --be-platform-admin-text-soft: #6b6b6b;
  --be-platform-admin-accent:    #3a3a3a;
}

/* Page heading — restrained, matches WP's wp-heading-inline weight but
   a touch darker / heavier so it reads as a clear page label. */
.be-platform-overview > h1,
.be-platform-integrations > h1,
.be-platform-settings > h1,
.be-platform-preflight > h1 {
  color: var(--be-platform-admin-text);
  font-weight: 600;
  margin-block-end: 16px;
}

/* Tabs — greyscale folder-tab look. Active tab visually merges with the
   card surface below it (1px overlap on the bottom border) so the tab
   bar + form read as one document. */
.be-platform-settings-tabs.nav-tab-wrapper,
.be-platform-integrations-tabs.nav-tab-wrapper {
  border-bottom-color: var(--be-platform-admin-border);
  margin-block-end: 0;
  padding-block-end: 0;
}

.be-platform-settings-tabs .nav-tab,
.be-platform-integrations-tabs .nav-tab {
  background: transparent;
  border: 1px solid transparent;
  border-bottom: 0;
  color: var(--be-platform-admin-text-soft);
  font-weight: 500;
  margin-inline-end: 4px;
}

/* Suppress core's `.nav-tab { margin-left: .5em }` on the first tab so the
   tab strip starts flush with the page heading + form card. */
.be-platform-settings-tabs .nav-tab:first-of-type,
.be-platform-integrations-tabs .nav-tab:first-of-type {
  margin-left: 0;
}

.be-platform-settings-tabs .nav-tab:hover,
.be-platform-integrations-tabs .nav-tab:hover {
  color: var(--be-platform-admin-text);
  background: rgba(0, 0, 0, 0.02);
}

.be-platform-settings-tabs .nav-tab-active,
.be-platform-settings-tabs .nav-tab-active:hover,
.be-platform-integrations-tabs .nav-tab-active,
.be-platform-integrations-tabs .nav-tab-active:hover {
  background: var(--be-platform-admin-card-bg);
  border-color: var(--be-platform-admin-border);
  border-bottom-color: var(--be-platform-admin-card-bg);
  color: var(--be-platform-admin-text);
  font-weight: 600;
}

/* Card surface — the form (and prune form below it) sit on a white card
   with a single border. Sections inside use the page's grey as a band
   between them, mirroring the screenshot pattern. */
.be-platform-settings-form,
.be-platform-integrations-form {
  background: var(--be-platform-admin-card-bg);
  border: 1px solid var(--be-platform-admin-border);
  padding: 0 24px 16px;
  margin: 0 0 16px;
}

/* Section heading band — the <h2> rendered by add_settings_section().
   Negative inline margin pulls the band edge-to-edge of the card. */
.be-platform-settings-form h2,
.be-platform-integrations-form h2 {
  margin: 0 -24px;
  padding: 12px 24px;
  background: var(--be-platform-admin-bg);
  border-block: 1px solid var(--be-platform-admin-border);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--be-platform-admin-text);
}

/* The first section's top border collides with the tab bar's bottom edge —
   suppress it for a cleaner seam. */
.be-platform-settings-form > h2:first-child,
.be-platform-integrations-form > h2:first-child {
  border-top: 0;
}

.be-platform-settings-section-description {
  margin: 12px 0 4px;
  color: var(--be-platform-admin-text-soft);
  font-style: normal;
}

/* Form-table tweaks — keep WP's geometry, just calm the colors and tighten
   the row spacing so a long settings page scans faster. */
.be-platform-settings-form .form-table,
.be-platform-integrations-form .form-table {
  margin-top: 0;
}

.be-platform-settings-form .form-table th,
.be-platform-integrations-form .form-table th {
  color: var(--be-platform-admin-text);
  font-weight: 600;
  padding-block: 14px;
}

.be-platform-settings-form .form-table td,
.be-platform-integrations-form .form-table td {
  padding-block: 14px;
}

/* Help text — Elementor-editor flavoured (small, italic, soft grey).
   Applied uniformly to every `<p class="description">` inside a
   platform-managed admin form, regardless of whether it lives in a
   form-table cell, a section description, or a custom field block. */
.be-platform-settings-form .description,
.be-platform-integrations-form .description {
  color: var(--be-platform-admin-text-soft);
  font-size: 11px;
  font-style: italic;
  line-height: 1.5;
  margin-top: 6px;
}

/* Section descriptions sit above the fields on their own line and read
   as a paragraph rather than per-field help text — slightly larger so
   they don't get lost. */
.be-platform-settings-form .be-platform-settings-section-description,
.be-platform-integrations-form .be-platform-settings-section-description {
  font-size: 12px;
  margin: 12px 0 4px;
}

/* Submit row — separated from the last form-table by a thin rule so the
   primary action reads as the page conclusion, not an afterthought. */
.be-platform-settings-form .submit,
.be-platform-integrations-form .submit {
  margin: 12px -24px 0;
  padding: 14px 24px 4px;
  border-top: 1px solid var(--be-platform-admin-rule);
}

/* Prune-to-schema secondary card — visual twin of the main settings card
   so its heading sits in the same edge-to-edge grey band as the section
   above it (BANDSINTOWN CONNECTION, etc.). Used in two places:
     - Per-tab: rendered below each plugin's primary form on Settings /
       Integrations.
     - Global: rendered below the plugins table on Overview, marked
       additionally with `--global` for any future variant tweaks. */
.be-platform-kit-prune {
  margin-top: 16px;
  background: var(--be-platform-admin-card-bg);
  border: 1px solid var(--be-platform-admin-border);
}

.be-platform-kit-prune > h2 {
  margin: 0;
  padding: 12px 24px;
  background: var(--be-platform-admin-bg);
  border-bottom: 1px solid var(--be-platform-admin-border);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--be-platform-admin-text);
}

.be-platform-kit-prune__body {
  padding: 14px 24px 16px;
}

.be-platform-kit-prune__description {
  margin: 0 0 12px;
  color: var(--be-platform-admin-text-soft);
}

.be-platform-kit-prune__form {
  margin: 0;
}

/* Empty / informational paragraphs (e.g. "No plugins have registered…") —
   render in soft grey on the page background so they read as system copy
   rather than form content. */
.be-platform-overview .description,
.be-platform-integrations .description,
.be-platform-settings .description,
.be-platform-preflight .description {
  color: var(--be-platform-admin-text-soft);
}


/* ----------------------------------------------------------------------------
 * Two-column section layout (since 0.10.0)
 *
 * Used by Sections declared with `Section::LAYOUT_TWO_COLUMN`. The Settings /
 * Integrations Renderer emits one `.be-platform-section-columns` grid per
 * such section; each column is a vertical flex stack of `.be-platform-field`
 * blocks, optionally separated by `.be-platform-field-divider` rules.
 * ---------------------------------------------------------------------------- */

.be-platform-section-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  padding: 16px 0 4px;
}

.be-platform-section-column {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.be-platform-field-divider {
  border: 0;
  border-top: 1px solid var(--be-platform-admin-rule);
  margin: 4px 0;
}


/* ----------------------------------------------------------------------------
 * Field block — self-contained label + control + description unit. Used by
 * `Settings\Renderer::render_field_block()` for two-column layouts (and any
 * future custom layout that doesn't rely on WP's form-table).
 *
 * Stacks vertically so it composes naturally inside narrow columns:
 *
 *   <div class="be-platform-field">
 *     <label class="be-platform-field__label" for="..."></label>
 *     <div class="be-platform-field__control"><input ... /></div>
 *     <p class="description"></p>
 *   </div>
 *
 * Checkbox variant inlines the input inside the label so the label text is
 * clickable:
 *
 *   <div class="be-platform-field">
 *     <label class="be-platform-field__checkbox-label" for="...">
 *       <input type="checkbox" ... /> <span class="be-platform-field__label-text">…</span>
 *     </label>
 *     <p class="description"></p>
 *   </div>
 * ---------------------------------------------------------------------------- */

.be-platform-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.be-platform-field__label {
  font-weight: 600;
  color: var(--be-platform-admin-text);
}

.be-platform-field__checkbox-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  color: var(--be-platform-admin-text);
  cursor: pointer;
}

.be-platform-field__control {
  display: block;
}

/* The Renderer-emitted `.description` already inherits the help-text style
   defined earlier in this file (grey, 11px, italic). No per-block override
   needed; this comment is here so a future contributor doesn't add one. */


/* ----------------------------------------------------------------------------
 * Disabled / conditional state (since 0.10.0)
 *
 * A `.be-platform-field` whose controlling checkbox (declared via
 * `Field::depends_on`) is unchecked carries `--disabled` on the wrapper.
 * The HTML `disabled` attribute on the input does the heavy lifting — this
 * rule just dims the surrounding label and description so the whole block
 * reads as inactive.
 *
 * Live toggling on checkbox change is handled by
 * `assets/js/be-platform-settings.js`. The initial server-side state matches
 * the persisted controlling-checkbox value, so there's no enabled-flash on
 * page load.
 * ---------------------------------------------------------------------------- */

.be-platform-field--disabled {
  opacity: 0.5;
}

.be-platform-field--disabled .be-platform-field__label,
.be-platform-field--disabled .be-platform-field__checkbox-label,
.be-platform-field--disabled .be-platform-field__label-text,
.be-platform-field--disabled .description {
  color: var(--be-platform-admin-text-soft);
}

.be-platform-field--disabled .be-platform-field__checkbox-label {
  cursor: not-allowed;
}

.be-platform-field--disabled input,
.be-platform-field--disabled select,
.be-platform-field--disabled textarea {
  cursor: not-allowed;
}


/* ----------------------------------------------------------------------------
 * Frosted / Liquid Glass — opt-in glassmorphism primitive
 *
 * Two classes, applied to a real DOM child div that the consumer's
 * render path emits inside an outer "glass element" (the surface
 * whose painted background we want to refract through):
 *
 *   <div class="be-platform-glass">                            ← outer; positioning context + clip frame
 *     <div class="be-platform-glass-overlay">                  ← inner; the actual glass surface (frost + refraction + depth)
 *     </div>
 *   </div>
 *
 *   <div class="be-platform-glass be-platform-glass--liquid">      ← + SVG displacement (Chromium / Firefox; falls back to base on WebKit)
 *     <div class="be-platform-glass-overlay"></div>
 *   </div>
 *
 * **Architecture: real DOM child overlay.** The
 * actual glass surface lives on `.be-platform-glass-overlay` (a real
 * `<div>` the consumer's render path emits). The `.be-platform-glass`
 * element itself is just a positioning context + clip frame; all the
 * visual paint (translucent tint, backdrop-filter, edge highlights,
 * inner glow) lives on the inner overlay div.
 *
 * Why a real DOM child instead of a `::before` pseudo: cross-engine
 * `backdrop-filter` semantics on pseudo-elements are not reliable —
 * macOS Safari and iOS Safari compute the pseudo's backdrop image
 * from the page-root compositing layer rather than from the parent
 * element's painted background, producing a uniform pastel wash
 * instead of refracting through the consumer's own background-image.
 * A real DOM child has unambiguous backdrop semantics in every
 * engine: the parent's `background` paints first, then the child
 * paints on top with its `backdrop-filter` reading the parent's
 * already-painted bg as backdrop. No isolation/compositing-layer
 * tricks, no engine-specific gates.
 *
 * Platform Container Glass auto-injection uses the same two-layer
 * optical model without moving Elementor's existing children:
 *
 *   <div class="elementor-element ... be-platform-glass">
 *     <div class="be-platform-glass-overlay" aria-hidden="true"></div>
 *     ...original Elementor children stay as direct children...
 *   </div>
 *
 * The overlay is absolute, fills the whole container, and ignores
 * pointer events. The original children remain direct siblings of
 * the overlay and are lifted above it with z-index. This avoids the
 * failed 0.13.x wrapper/reparenting attempts that broke the editor
 * canvas.
 *
 * For Elementor Containers, `\BE\Platform\Elementor\ContainerGlass`
 * adds the Glass controls and injects the overlay. For consumer
 * widgets, emit the two-div shape directly in `render()`.
 *
 * Consumer pattern (custom widget): emit the two-div shape
 * directly in `render()`. See BSM's `.be-social-filler-pane` →
 * `.be-social-filler.be-platform-glass` → `.be-platform-glass-overlay`
 * for the canonical example.
 *
 * The hype4-derived recipe has five always-on parameters, each tunable
 * via a CSS custom property:
 *
 *   1. Blur        (--be-platform-glass-blur)        — backdrop-filter blur radius
 *   2. Tint        (--be-platform-glass-tint)        — translucent white wash
 *   3. Refraction  (--be-platform-glass-refraction)  — opacity of the
 *                  edge-highlight / bevel layer (0 = invisible,
 *                  1 = full hype4 intensity)
 *   4. Depth       (--be-platform-glass-depth-strength) — alpha 0–1 of the
 *                  inner-glow inset shadow that gives the surface its
 *                  "milky thickness"
 *   5. Saturation  (--be-platform-glass-saturation)  — backdrop-filter saturate
 *
 * Plus a static recipe baked into the overlay (not parameterised —
 * part of the hype4 look):
 *   - Outer drop shadow
 *
 * The `--liquid` modifier ADDS an SVG `feDisplacementMap` step on top of
 * the base blur+saturate, producing genuine optical refraction (straight
 * lines behind the pane wobble, they don't just blur). The base
 * recipe's parameters all still apply when `--liquid` is on; liquid is
 * additive, not a replacement.
 *
 * Browser support — progressive enhancement:
 *   - Base recipe (blur + refraction + depth + saturation): Safari 16+, Chrome 105+, Firefox 110+ (family floor)
 *   - Liquid (the --liquid mod):                            Chrome 105+, Firefox 110+ (NOT Safari/iOS)
 *
 * Two cases fall back to the base frost via the cascade:
 *   - Browsers below the `url()`-in-`backdrop-filter` cliff (gated by
 *     `@supports (backdrop-filter: url())` below).
 *   - All WebKit browsers (every Safari version, all iOS browsers).
 *     WebKit's renderer collapses the entire backdrop-filter chain
 *     (blur + saturate + displacement → invisible) when
 *     `feDisplacementMap` is present — dramatically worse than the
 *     plain frost. The exclusion is gated by the
 *     `data-be-platform-engine="webkit"` attribute that
 *     `\BE\Platform\UI\Assets::maybe_emit_engine_detect()` sets on
 *     `<html>` from a tiny inline `<head>` script. Revisit if Apple
 *     ever ships a working displacement primitive in `backdrop-filter`.
 *
 * Default values for the five custom properties match the hype4
 * reference recipe exactly so a bare `<div class="be-platform-glass">`
 * over any background looks intentional out of the box:
 *
 *     --be-platform-glass-blur              (default 4px)
 *     --be-platform-glass-tint              (default rgba(255,255,255,0.14))
 *     --be-platform-glass-refraction        (default 1     — full intensity edge highlights)
 *     --be-platform-glass-depth-strength    (default 1     — full inner glow)
 *     --be-platform-glass-saturation        (default 100%)
 *
 * Plus one additional knob not exposed as an Elementor control but
 * available as CSS custom-property overrides for site-wide theming:
 *
 *     --be-platform-glass-depth-spread      (default 19px)
 *
 * Implementation notes:
 *   - `.be-platform-glass` (the parent / glass element) sets
 *     `position: relative` + `overflow: hidden` so the overlay can
 *     anchor and clip to whatever `border-radius` the consumer applied.
 *     No background, no backdrop-filter on this element itself — the
 *     consumer keeps their own background (Elementor's classic/gradient/
 *     image bg control) on this element, and `backdrop-filter` on the
 *     overlay INSIDE this element refracts through it.
 *   - `.be-platform-glass-overlay` (the injected overlay) holds the
 *     tint, blur, saturate, drop shadow, and inner glow. Its `::before`
 *     pseudo holds the edge-highlight / bevel layer that the Refraction
 *     slider fades in/out. It also re-publishes the parent's full
 *     content area via `position: absolute; inset: 0` and never
 *     participates in flex/grid layout.
 *   - The base class does NOT set `border-radius`. Glass corners come
 *     from the consumer's existing border control (Elementor
 *     containers already expose this; the overlay's edges follow the
 *     parent's content box, and the parent's `overflow: hidden`
 *     clips both overlay and any backdrop-filter halo to the
 *     rounded corners).
 *   - The `--liquid` SVG filter is delivered as an in-document
 *     `<svg><filter id="be-platform-glass-liquid">…</filter></svg>` block
 *     emitted on `wp_footer` / `admin_footer` by
 *     `\BE\Platform\UI\Assets::maybe_emit_glass_filter()` whenever
 *     `be-platform-ui` is enqueued. We can't inline the filter as a
 *     `data:` URL inside `backdrop-filter` because Chromium silently
 *     ignores SVG-filter `data:` URLs in `backdrop-filter` (the parser
 *     accepts the syntax — `CSS.supports` returns `true` — but the
 *     renderer produces no displacement). Per-instance tuning of the
 *     displacement (refraction `scale`, noise `baseFrequency`) is
 *     intentionally not exposed: one fixed recipe = one consistent
 *     platform look.
 * ---------------------------------------------------------------------------- */

.be-platform-glass {
  overflow: hidden;
  /* No background, no backdrop-filter on the element itself — those
     live on the `.be-platform-glass-overlay` child, which refracts
     through this element's painted background. */
}

/* Elementor Containers set `position: var(--position)` and
   `overflow: var(--overflow)` in core CSS. The auto-injected overlay
   needs the Container to be the containing block and clip frame even
   when saved Container values would otherwise make it static/visible.
   Keep this scoped to `.e-con` so consumer widgets can put
   `.be-platform-glass` on elements with their own positioning contract
   (e.g. BSM's `.be-social-filler { position:absolute; inset:0; }`). */
.be-platform-glass.e-con {
  overflow: hidden;
  position: relative !important;
}

/* The actual glass surface — real DOM child div injected as the first
   child of `.be-platform-glass`. It is a full-size absolute layer and
   never participates in the parent's flex/grid layout. */
.be-platform-glass-overlay {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;

  background: var(--be-platform-glass-tint, rgba(255, 255, 255, 0.14));

  backdrop-filter:
    blur(var(--be-platform-glass-blur, 4px))
    saturate(var(--be-platform-glass-saturation, 100%));

  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.1),
    inset 0 0
      calc(var(--be-platform-glass-depth-spread, 19px) * 2)
      var(--be-platform-glass-depth-spread, 19px)
      rgba(255, 255, 255, var(--be-platform-glass-depth-strength, 1));
}

/* Dedicated edge-glint / bevel layer. Keeping this separate from the tint and
   backdrop-filter means the Refraction slider can use a plain unitless
   opacity value, matching the 0–1 CSS variable Elementor already emits. */
.be-platform-glass-overlay::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: var(--be-platform-glass-refraction, 1);
  border: 1px solid rgba(255, 255, 255, 0.32);
  background:
    linear-gradient(
      90deg,
      transparent,
      rgba(255, 255, 255, 0.8),
      transparent
    ) top / 100% 2px no-repeat,
    linear-gradient(
      180deg,
      rgba(255, 255, 255, 0.8),
      transparent 50%,
      rgba(255, 255, 255, 0.3)
    ) left / 2px 100% no-repeat;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.45),
    inset 1px 0 0 rgba(255, 255, 255, 0.28),
    inset 0 -1px 0 rgba(0, 0, 0, 0.12),
    inset -1px 0 0 rgba(0, 0, 0, 0.06);
}

/* Keep real Elementor child content above the glass surface without
   reparenting it. Do not lift arbitrary non-Elementor helper nodes
   such as background-effect overlays; those are part of the backdrop
   the glass should refract through. */
.be-platform-glass > .elementor-element {
  position: relative;
  z-index: 1;
}

/* `--liquid` adds an SVG `feDisplacementMap` step on top of the base
   blur+saturate, producing genuine optical refraction. Applied to
   the overlay (where the base backdrop-filter lives).

   Gating is two-tier:

     1. Outer `@supports (backdrop-filter: url())` — excludes browsers
        that don't accept `url()` as a filter-function in
        `backdrop-filter` at all. They silently fall back to the base
        frost (still hype4-shape, not invisible).

     2. WebKit-exclusion via the `html[data-be-platform-engine="webkit"]`
        attribute set by `\BE\Platform\UI\Assets::maybe_emit_engine_detect()`.
        WebKit PARSES `url()` in backdrop-filter as valid (so `@supports`
        returns true) but its renderer collapses the entire chain when
        `feDisplacementMap` is present, dropping the visible blur and
        saturate along with the displacement. Net effect would be
        "transparent pane" — much worse than the base frost — so we
        exclude WebKit and let it fall through to the base overlay
        rule via the cascade.

   See the header comment of this file for why we use an in-document
   `<filter>` reference rather than a `data:` URL. */
@supports (backdrop-filter: url(#x)) {
  html:not([data-be-platform-engine="webkit"]) .be-platform-glass--liquid > .be-platform-glass-overlay {
    backdrop-filter:
      blur(var(--be-platform-glass-blur, 4px))
      saturate(var(--be-platform-glass-saturation, 100%))
      url(#be-platform-glass-liquid);
  }
}
