.be-social-gallery {
  --be-social-columns-landscape: 4;
  --be-social-columns-portrait: 2;
  --be-social-columns: var(--be-social-columns-landscape);
  --be-social-gap-scale-landscape: 1.6;
  --be-social-gap-scale-portrait: 2;
  --be-social-gap-scale: var(--be-social-gap-scale-landscape);
  --be-social-gap: clamp(6px, calc(var(--be-social-gap-scale) * 1cqw), 28px);
  --be-social-tile-aspect: 9 / 16;
  --be-social-lightbox-chrome-bg: #0f0f0f;
  width: 100%;
  /* Flex column so the .be-social-filler-pane sibling below the grid
     can grow to fill any remaining vertical space inside the parent
     Elementor column. The flex `gap` separates the grid from the
     filler band when the pane has actual leftover space to fill —
     a small visual breathing space between the bottom row of tiles
     and the painted filler. When the pane has zero leftover space
     (this widget is the sibling-height limiter), the pane is hidden
     entirely via `display: none` from `be-social-filler.js` so the
     gap doesn't manifest as unpainted whitespace below the grid. The
     fills-its-parent's-height (height: 100%) only does work when the
     parent has a definite height to give. */
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--be-social-gap);
}

/* Bridge the Elementor widget chain so:
   1) The gallery's `height: 100%` (above) has a definite parent height
      to resolve against when the widget sits in an Elementor flex-column
      container with a sibling-stretched height (the common "two galleries
      side-by-side" layout). Without `height: 100%` on both wrappers, the
      chain collapses to content height and the filler's flex-grow has
      nothing to grow into.
   2) `1cqw` inside the widget (used by `--be-social-gap`) resolves
      consistently. CSS spec evaluates container query units against the
      nearest *ancestor* with `container-type` set; the queried element
      is not its own container. So if `container-type: inline-size`
      lived on `.be-social-gallery`, `1cqw` evaluated FROM the gallery
      itself (e.g. for its own flex `gap`) would fall through to the
      viewport, blowing the gap up to the clamp's upper bound on wide
      screens — while `1cqw` evaluated from descendants like
      `.be-social-grid` would correctly resolve against the gallery.
      Putting `container-type` on the widget container instead means
      `1cqw` resolves to the same width (the widget container = the
      gallery's width since `.be-social-gallery` is `width: 100%`)
      whether evaluated from the gallery or any of its descendants.
   Safe in non-flex contexts: `height: 100%` against an auto-sized
   parent resolves to auto, so the widget's effective height stays
   driven by its content. Scoped to our widget id so we don't touch any
   other plugin's widget. */
.elementor-widget.elementor-widget-be_social_media,
.elementor-widget.elementor-widget-be_social_media > .elementor-widget-container {
  height: 100%;
}

.elementor-widget.elementor-widget-be_social_media > .elementor-widget-container {
  container-type: inline-size;
}

/* Force full-width on the widget wrapper itself. Without this, the
   widget collapses to content width when its Elementor parent
   container is `flex-direction: row` (because flex-row items default
   to content size unless flex-grow / explicit width says otherwise).
   The gallery inside then has `width: 100%` of a too-narrow box, the
   2-col grid lays out at the wrong width, and adjacent BSM widgets in
   the same row end up overlapping vertically.

   Pre-2026-05-07 the workaround was per-instance: editor user had to
   set the widget's Width control to "Full Width" / "Inherit" on every
   instance, which adds `.elementor-widget__width-inherit` and
   equivalent rules. Easy to forget. Baking it into the widget's CSS
   makes every BSM instance fill its parent reliably regardless of
   Elementor parent flex-direction. Users who specifically want a
   narrower BSM widget can still override via Elementor's
   Advanced > Width control (their override has higher specificity). */
.elementor-widget.elementor-widget-be_social_media {
  width: 100%;
  max-width: 100%;
}

@media (orientation: portrait) {
  .be-social-gallery {
    --be-social-columns: var(--be-social-columns-portrait);
    --be-social-gap-scale: var(--be-social-gap-scale-portrait);
  }
}

@supports not (width: 1cqw) {
  .be-social-gallery {
    --be-social-gap: clamp(6px, calc(var(--be-social-gap-scale) * 1vw), 28px);
  }
}

.be-social-grid {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: repeat(var(--be-social-columns), minmax(0, 1fr));
  gap: var(--be-social-gap);
  align-items: stretch;
}

.be-social-tile {
  /* The tile is a flex column so the inner stage can grow past its
     aspect-ratio'd intrinsic height when the grid row is stretched
     taller (because the featured 2-row tile's height divided by 2
     doesn't always land on the same number a single tile's aspect
     ratio gives — typically a 3-4 CSS px gap). With `flex: 1 1 auto`
     on the stage, the stage's intrinsic aspect-ratio'd height drives
     grid row sizing, AND the stage stretches to fill the tile when
     the row turns out larger. No letterbox below the poster.

     Cross-browser: this works in both Chromium and WebKit. We tried
     `aspect-ratio` directly on the tile (cleaner) but WebKit
     collapses any grid item whose only children are absolutely
     positioned to 0 height — its row-sizing pass doesn't honor
     aspect-ratio without in-flow content. Keeping the stage in
     normal flow (with `position: relative` + `flex: 1 1 auto`) lets
     both engines size the tile correctly. */
  display: flex;
  flex-direction: column;
  min-width: 0;
  border-radius: 4px;
  overflow: hidden;
  background: #0f0f0f;
}

/* Vertical filler. Two nested elements below the grid:
     <div class="be-social-filler-pane">      ← layout owner + background
       <div class="be-social-filler" />       ← optional glass overlay
     </div>
   The OUTER pane:
   - flex:1 1 auto — grows to fill any remaining vertical space the
     parent Elementor column gives the gallery (this is the role the
     filler used to play on its own pre-3.12.0).
   - When this widget is the sibling-height limiter (its grid is the
     tallest of the side-by-side widgets), there's no leftover space
     for the pane to fill. `be-social-filler.js` flips the PANE to
     `display: none` so the gallery's flex `gap` doesn't render as
     unpainted whitespace below the grid. CSS-only conditional
     collapse isn't possible: flex `gap` is unconditional between
     siblings even when one shrinks to 0, and `padding-top` /
     `margin-top` tricks all bottom out at the padding floor.
   - position: relative + overflow: hidden so the inner glass overlay
     (when Frosty Glass is on) is clipped to the pane's rounded
     corners. The padding-box of the pane is what the absolute child
     fills, so border + border-radius wrap the glass cleanly.
   - Same default border-radius as a tile so the user's Style >
     Preview Poster border controls (which include the pane in their
     selectors since 3.12.0) wrap it the same way.
   - Background defaults to transparent; Style > Vertical Filler >
     Background paints it via Elementor dynamic CSS pointed at the
     pane (not the inner filler — see Widget::register_style_vertical_filler_section
     for the rationale).
   - aria-hidden in the markup so screen readers ignore it. */
.be-social-filler-pane {
  flex: 1 1 auto;
  min-height: 0;
  position: relative;
  overflow: hidden;
  border-radius: 4px;
  background: transparent;
}

/* Inner filler. Absolutely positioned overlay that fills the pane.
   When Frosty Glass is on, render() adds .be-platform-glass (and
   optionally .be-platform-glass--liquid) here; the platform CSS in
   be-platform-ui.css >= 0.10.1 supplies the visual recipe
   (backdrop-filter blur + saturate + optional SVG displacement),
   tuned per-widget by the Blur / Saturation / Depth NUMBER controls
   that emit `--be-platform-glass-*` custom properties on this
   selector. backdrop-filter on this element refracts what is painted
   BEHIND it within the pane's stacking context — i.e. the pane's
   background — which is why the user's chosen Background image /
   gradient is what we want them to see through the glass.

   When Frosty Glass is off, this element is a transparent no-op
   overlay. The user just sees the pane's background as-is.

   border-radius: inherit so the glass clip-edge follows the pane's
   user-customised radius. (overflow:hidden on the pane already
   clips us, but inheriting the radius prevents any rendering
   sub-pixel surprises.) */
.be-social-filler {
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

/* Editor panel: when the Minimum Height switcher is OFF, dim the
   sibling Value control so it reads as visible-but-disabled. The
   switcher's <input type="checkbox"> reflects the toggle state; the
   sibling combinator (`~`) reaches the value control because both
   live as siblings in the section's controls list. Pointer events
   are blocked at the wrapper so the user can't accidentally edit the
   dimmed value; opacity + grayscale give the standard
   "disabled control" affordance. Pure CSS — no JS wiring needed.

   Only paints inside the Elementor editor (where `#elementor-panel`
   exists); never affects the rendered front-end. Cross-tab safe:
   Elementor renders panel controls fresh on tab switch, so the
   :has() match re-evaluates on every render. */
#elementor-panel .elementor-control-vertical_filler_min_height_enabled:has(input[type="checkbox"]:not(:checked)) ~ .elementor-control-vertical_filler_min_height {
  opacity: 0.5;
  filter: grayscale(40%);
  pointer-events: none;
}

.be-social-gallery--feature-landscape .be-social-tile--featured {
  grid-column: span 2;
  grid-row: span 2;
}

@media (orientation: portrait) {
  .be-social-gallery--feature-landscape .be-social-tile--featured {
    grid-column: auto;
    grid-row: auto;
  }

  .be-social-gallery--feature-portrait .be-social-tile--featured {
    grid-column: span 2;
    grid-row: span 2;
  }
}

.be-social-tile__stage {
  /* In normal flow as a flex item of the tile. `aspect-ratio` gives
     the stage its natural intrinsic height (= width × inverse-ratio),
     which the grid's row-sizing algorithm reads through the tile to
     compute row heights. `flex: 1 1 auto` then lets the stage grow
     PAST that natural height when the grid stretches the tile (e.g.,
     because the featured tile drives the row height to a fraction
     larger than a single tile's aspect-ratio'd height) — eliminates
     the few-px black `#0f0f0f` letterbox at the bottom that used to
     show through.

     `position: relative` keeps the stage as the containing block for
     the absolutely-positioned poster + link overlay below. */
  position: relative;
  width: 100%;
  flex: 1 1 auto;
  aspect-ratio: var(--be-social-tile-aspect);
  overflow: hidden;
  border-radius: inherit;
  background: #0f0f0f;
}

.be-social-tile__poster {
  /* Fill the stage completely, regardless of the source image's natural
     aspect ratio AND regardless of whether the image has loaded yet.
     The img is a replaced element, which means the browser computes
     its used size partly from its natural dimensions: when the source
     hasn't loaded (naturalWH = 0×0) or its aspect doesn't match the
     stage, the naive `width: 100%; height: 100%` can be reduced by the
     replaced-element sizing path and collapse the box to 0 height.

     `min-width: 100%` + `min-height: 100%` set a floor on the used
     size, forcing the box to fill the stage in both axes regardless
     of natural dimensions or loading state. `object-fit: cover` then
     scales the source to fill the box (cropping as needed).

     We deliberately avoid `aspect-ratio: var(--be-social-tile-aspect)`
     here: pinning the box to the consumer-declared aspect would
     re-introduce a tiny letterbox INSIDE the stage, because the
     stage's actual height is the GRID row's stretched height (which
     can be a fraction of a px off from var(--be-social-tile-aspect)
     when the featured 2-row tile drives row sizing). The min-*
     approach lets the box match whatever the stage actually is. */
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  min-width: 100%;
  min-height: 100%;
  object-fit: cover;
}

.be-social-tile__link {
  position: absolute;
  inset: 0;
  z-index: 2;
  text-decoration: none;
  background: transparent;
}

.be-social-tile__link:focus-visible {
  outline: none;
}

/* Hover Effect = Darken (default). Slight dark wash on hover/focus to
   indicate the tile is interactive. The :focus-visible rule mirrors :hover
   for keyboard users. Driven by the be-social-gallery--hover-darken
   modifier class emitted from PHP render() based on the Style > Preview
   Poster > Hover Effect dropdown. */
.be-social-gallery--hover-darken .be-social-tile__link {
  background: rgba(15, 15, 15, 0);
  transition: background 0.15s ease;
}

.be-social-gallery--hover-darken .be-social-tile__link:hover,
.be-social-gallery--hover-darken .be-social-tile__link:focus-visible {
  background: rgba(15, 15, 15, 0.12);
}

/* Hover Effect = None: explicitly nothing. Kept as a no-op rule so the
   intent is visible in the cascade and any future addition (e.g. a
   non-darken hover such as scale, brighten) slots in here. */

.be-social-tile__loader {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background:
    linear-gradient(100deg, rgba(255, 255, 255, 0) 30%, rgba(255, 255, 255, 0.18) 50%, rgba(255, 255, 255, 0) 70%),
    #171717;
  background-size: 220% 100%;
  animation: be-social-shimmer 1.2s linear infinite;
}

/* Tile-loader spinner styling is delegated to be-platform-spinner from
   wp-be-platform's be-platform-ui stylesheet. Override its custom
   properties here so the spinner reads as a small white-on-dark ring on
   the shimmering tile placeholder. */
.be-social-tile__loader .be-platform-spinner {
  --be-platform-spinner-size: 36px;
  --be-platform-spinner-track: rgba(255, 255, 255, 0.25);
  --be-platform-spinner-color: rgba(255, 255, 255, 0.85);
  --be-platform-spinner-duration: 0.9s;
}

@keyframes be-social-shimmer {
  from {
    background-position: 120% 0;
  }
  to {
    background-position: -120% 0;
  }
}

/* be-social-spin keyframes and the be-social-lightbox-open body-lock rule
   were deleted in 1.17.0. Their replacements live in wp-be-platform's
   be-platform-ui stylesheet (be-platform-spin keyframes and
   be-platform-scroll-lock-body, respectively). */

.be-social-lightbox[hidden] {
  display: none;
}

.be-social-lightbox {
  --be-social-lightbox-chrome-bg: #0f0f0f;
  position: fixed;
  inset: 0;
  /* Sit above page intro/cinematic overlays (e.g. wp-curtains-plugin uses up
     to 999997) so the lightbox always wins. Override per-page if needed by
     setting `--be-social-lightbox-z-index` on the gallery wrapper. */
  z-index: var(--be-social-lightbox-z-index, 2147483647);
}

.be-social-lightbox__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(8, 8, 10, 0.82);
}

.be-social-lightbox__dialog {
  position: relative;
  z-index: 1;
  margin: 2vh auto;
  width: min(92vw, 720px);
  max-height: 96vh;
  display: grid;
  grid-template-rows: auto auto;
  gap: 0.5rem;
  padding: 0.5rem;
  border-radius: 10px;
  overflow: hidden;
  background: var(--be-social-lightbox-chrome-bg);
  box-shadow: 0 18px 42px rgba(0, 0, 0, 0.45);
}

.be-social-lightbox__header {
  min-height: 2rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.35rem 0.5rem;
  border-radius: 8px;
  background: var(--be-social-lightbox-chrome-bg);
}

.be-social-lightbox__actions {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin-left: auto;
}

.be-social-lightbox__hint[hidden] {
  display: none;
}

.be-social-lightbox__hint {
  min-width: 0;
  font-size: 0.8rem;
  line-height: 1;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.9);
  text-align: left;
}

.be-social-lightbox__body {
  position: relative;
  display: flex;
  justify-content: center;
  min-height: 120px;
}

.be-social-lightbox__media-wrap {
  position: relative;
  width: min(100%, calc((96vh - 6rem) * 0.5625));
  max-height: calc(96vh - 6rem);
  aspect-ratio: 9 / 16;
  overflow: hidden;
  border-radius: 8px;
  background: #000;
}

.be-social-lightbox__media-wrap--image {
  width: min(100%, calc(96vh - 6rem));
  aspect-ratio: 1 / 1;
}

.be-social-lightbox__frame,
.be-social-lightbox__image {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

.be-social-lightbox__frame:not([hidden]),
.be-social-lightbox__image:not([hidden]) {
  display: block;
}

.be-social-lightbox__image {
  object-fit: contain;
  background: #000;
}

/* The lightbox loader uses be-platform-loader (overlay) +
   be-platform-spinner (ring) from wp-be-platform's be-platform-ui
   stylesheet. The platform defaults already match the historical
   look (48px / 3px / 1.1s ring; 180ms fade). The only thing we need
   to scope is the loader background — we want #fff for the lightbox
   while the loader is visible, where the platform default is
   transparent. */
.be-social-lightbox__loader {
  --be-platform-loader-bg: #fff;
}

/* Error overlay shown in place of (on top of) the iframe when the
   safety-net timeout fires without iframe.onload having fired. Sits
   inside .be-social-lightbox__media-wrap, fills it edge-to-edge, and
   centers a short message + an Attempt Reload button. The widget's
   Style > Lightbox > Error Text controls (typography + color) write
   into `body .be-social-lightbox__error-text` via Elementor's
   autogenerated CSS — these defaults take over when no per-widget
   styling is set. */
.be-social-lightbox__error[hidden] {
  display: none;
}

.be-social-lightbox__error {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 1.5rem;
  background: #000;
  text-align: center;
}

.be-social-lightbox__error-text {
  margin: 0;
  font-size: 1rem;
  line-height: 1.4;
  color: #fff;
  max-width: 28rem;
}

/* Defaults shown when the widget's Style > Lightbox > Reload Button
   controls are unset. Each Elementor control writes to
   `body .be-social-lightbox__retry…` (specificity 0,1,1) which wins over
   these single-class defaults (0,1,0); leaving a control empty falls
   back to whatever's defined here. `box-sizing: border-box` keeps the
   button geometry stable when the user opts in to a border. The
   normal/hover transition is intentionally NOT exposed as a control —
   it's the affordance that makes the hover state register as
   interactive. */
.be-social-lightbox__retry {
  -webkit-appearance: none;
  appearance: none;
  display: inline-block;
  box-sizing: border-box;
  padding: 0.55rem 1.1rem;
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-size: 0.9rem;
  color: #463825;
  background: #e9d9c7;
  cursor: pointer;
  text-decoration: none;
  box-shadow: none;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.be-social-lightbox__retry:hover,
.be-social-lightbox__retry:focus-visible {
  background: #eac18b;
  color: #463825;
  outline: none;
}

.be-social-lightbox__icon-button {
  -webkit-appearance: none;
  appearance: none;
  width: 2rem;
  height: 2rem;
  border: 0 !important;
  border-radius: 999px;
  display: inline-grid;
  place-items: center;
  padding: 0;
  color: #463825 !important;
  background: #e9d9c7 !important;
  text-decoration: none !important;
  box-shadow: none !important;
  cursor: pointer;
  outline: none !important;
  transition: background 0.15s ease, color 0.15s ease;
}

.be-social-lightbox__icon-button:hover,
.be-social-lightbox__icon-button:focus-visible {
  color: #463825 !important;
  background: #eac18b !important;
}

.be-social-lightbox__close:hover,
.be-social-lightbox__close:focus-visible {
  color: #463825 !important;
  background: #eac18b !important;
}

.be-social-lightbox__nav {
  position: fixed;
  z-index: 3;
  top: 50%;
  transform: translateY(-50%);
  width: 2.6rem;
  height: 2.6rem;
  /* Scope the icon font-size only to the nav chips (header chips inherit
     body size at 16px, which proportions FA correctly inside the smaller
     2rem chip). The 2.6rem nav chip needs a bigger glyph to read as a
     navigation control rather than a stray punctuation mark. */
  font-size: 1.5rem;
}

.be-social-lightbox__prev {
  left: max(1rem, calc((100vw - 820px) / 2));
}

.be-social-lightbox__next {
  right: max(1rem, calc((100vw - 820px) / 2));
}

/* be-social-section-divider was consolidated into
   be-platform-section-divider in 1.17.0. The widget's
   add_section_divider() helper now emits the platform class directly. */

.be-social-section-help {
  margin: 0 0 6px;
  font-size: 12px;
  font-style: italic;
  color: #6d7882;
  line-height: 1.4;
}

/* Wrap around the "Fetch and Store Poster Images" button + its help text.
   Provides breathing room around the button (so it isn't jammed against
   the textarea / divider above) and pins the help text styling so an
   Elementor RAW_HTML control wrapper can't override font / colour. */
.be-social-fetch-covers-wrap {
  margin: 12px 0;
}

.be-social-fetch-covers-wrap .be-social-fetch-covers-btn {
  margin-bottom: 10px;
}

.be-social-fetch-covers-wrap .be-social-section-help {
  margin: 0;
  font-size: 12px;
  font-style: italic;
  color: #6d7882;
  line-height: 1.4;
}

.be-social-section-help--warn {
  padding: 8px 10px;
  border-left: 3px solid #d63638;
  background: rgba(214, 54, 56, 0.06);
  color: #3c434a;
  font-style: normal;
}

/* Elementor Repeater centers the "Add Item" button by default. In this
   widget's Manual Post URLs control, flush-left reads more like a normal
   list action and lines up with the surrounding controls. Editor panel
   only; never reaches the rendered front end. */
#elementor-panel .elementor-control-manual_posts .elementor-repeater-add {
  margin-inline-start: 0;
  margin-inline-end: auto;
}

.be-social-actions-wrap {
  display: block;
}

.be-social-action-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* The horizontal rule between the action buttons and the validation panel
   is styled by be-platform-rule (from wp-be-platform's be-platform-ui).
   The element keeps the be-social-validation-separator class purely so
   the editor JS in tmg-elementor-editor.js can target it to toggle the
   `hidden` attribute once a validation result lands. */

.be-social-validation-panel {
  margin-top: 0;
  padding: 10px 12px;
  border-radius: 4px;
  border-left: 3px solid #6d7882;
  background: #f6f7f7;
  color: #3c434a;
  font-size: 12px;
  line-height: 1.55;
}

.be-social-validation-panel--ok {
  border-left-color: #00a32a;
}

.be-social-validation-panel--error {
  border-left-color: #d63638;
}

.be-social-validation-panel > strong {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  letter-spacing: 0.01em;
}

.be-social-validation-panel--ok > strong {
  color: #00a32a;
}

.be-social-validation-panel--error > strong {
  color: #d63638;
}

.be-social-validation-panel p.be-social-section-help {
  margin: 10px 0 4px;
}

.be-social-validation-panel ul {
  margin: 4px 0 8px 18px;
  padding: 0;
  list-style: disc;
}

.be-social-validation-panel li {
  margin: 5px 0;
}

