/* MBB Saved Favourites (M7) — styles
 *
 * v1.5.17b: brand-coloured to match the My Best Birthday palette
 * (soft pink #ffa4bb). Icon-only variant for in-card placement.
 * Three placement variants supported:
 *
 *   .mbb-fav-btn--inline-title  → injected inside the listing title heading,
 *                                  reads as "Sara's Cakes ♡". Primary path.
 *   .mbb-fav-btn--on-image      → absolute top-right overlay on the listing
 *                                  image. Used when no title heading is found.
 *   .mbb-fav-btn--injected      → last-resort fallback positioning.
 *
 * Mobile-first; the heart button is sized so it's tappable on mobile
 * without overlapping GD's existing card controls.
 *
 * Theme override hooks — change colour via CSS custom properties at
 * any scope (:root, body, or a specific container).
 */

:root {
  /* Brand palette (from My Best Birthday brand guide). Soft pink #ffa4bb
   * is the primary "save" colour; the darker variant is the filled /
   * favourited state so it reads as more saturated/active. */
  --mbb-fav-primary: #ffa4bb;
  --mbb-fav-primary-dark: #e8869c;
  --mbb-fav-primary-bg: #fff0f4;     /* soft tinted background for hover */
  --mbb-fav-text: #1f2330;
  --mbb-fav-muted: #6b7280;
  --mbb-fav-border: #e5e7eb;
  --mbb-fav-surface: #ffffff;
  --mbb-fav-surface-alt: #f9fafb;
  --mbb-fav-radius: 10px;
}

/* ──────────────────────────────────────────────
 * Heart button — base
 * ────────────────────────────────────────────── */

.mbb-fav-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--mbb-fav-border);
  border-radius: 999px;
  background: var(--mbb-fav-surface);
  color: var(--mbb-fav-text);
  font-family: inherit;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease, transform .1s ease;
  -webkit-tap-highlight-color: transparent;
}

.mbb-fav-btn:hover {
  border-color: var(--mbb-fav-primary);
  color: var(--mbb-fav-primary-dark);
  background: var(--mbb-fav-primary-bg);
}

.mbb-fav-btn:active {
  transform: scale(.94);
}

.mbb-fav-btn__icon {
  display: inline-flex;
  width: 18px;
  height: 18px;
  color: inherit;
}

.mbb-fav-btn__icon svg {
  width: 100%;
  height: 100%;
}

.mbb-fav-btn__label {
  font-weight: 500;
}

/* Favourited state — filled pink heart, brand pink border + label */
.mbb-fav-btn.is-favourited {
  color: var(--mbb-fav-primary-dark);
  border-color: var(--mbb-fav-primary);
  background: var(--mbb-fav-primary-bg);
}

.mbb-fav-btn.is-favourited .mbb-fav-btn__icon svg path {
  fill: var(--mbb-fav-primary);
  fill-opacity: 1;
  stroke: var(--mbb-fav-primary-dark);
}

/* Guest state — slightly muted, hover hints at the login prompt */
.mbb-fav-btn.is-guest {
  color: var(--mbb-fav-muted);
}
.mbb-fav-btn.is-guest:hover {
  color: var(--mbb-fav-primary-dark);
  border-color: var(--mbb-fav-primary);
}

/* ──────────────────────────────────────────────
 * Icon-only variant
 *
 * v1.5.17e (client feedback): hard reset against theme button styles.
 * Some WordPress themes apply background-color/padding/border to ALL
 * <button> elements (Elementor's body styles do this), which leaked
 * through and rendered the heart inside a coloured square. We use
 * !important here to override theme defaults specifically for our
 * icon buttons — not pretty CSS, but it's the bulletproof solution
 * for guaranteed-clean theming.
 *
 * The result is a true icon: no background, no border, no padding —
 * just the heart shape (grey outlined when unsaved, brand pink filled
 * when saved).
 * ────────────────────────────────────────────── */
.mbb-fav-btn--icon,
.mbb-fav-btn--icon:hover,
.mbb-fav-btn--icon:focus,
.mbb-fav-btn--icon:active {
  padding: 0 !important;
  width: auto !important;
  height: auto !important;
  min-width: 0 !important;
  min-height: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  background-color: transparent !important;
  background-image: none !important;
  box-shadow: none !important;
  outline: none !important;
}
.mbb-fav-btn--icon {
  color: #9aa0a6;
  /* v1.5.27 — drop the transform transition. The scale(1.12) on hover plus
   *           scale(.92) on :active visibly jitters the tiny icon and, when
   *           combined with a brief Elementor layout reflow, made the heart
   *           appear to "vanish" between unhovered → hovered → active. We
   *           keep the colour transition (which IS smooth) and lose the
   *           scaling, which the user can't really perceive on a 24px icon
   *           anyway. */
  transition: color .15s ease;
}
.mbb-fav-btn--icon:hover {
  color: var(--mbb-fav-primary-dark);
}
/* v1.5.27 — :active scale removed for the reason above. The colour change
 *           plus the toast notification is enough click feedback. */
.mbb-fav-btn--icon .mbb-fav-btn__label { display: none; }
.mbb-fav-btn--icon .mbb-fav-btn__icon {
  width: 22px;
  height: 22px;
  color: inherit;
  /* v1.5.27 — explicit baseline so the SVG sits visually on the cap-line of
   *           the heading text instead of riding above it. Combined with
   *           the inline-flex rule on the heading (below) the heart and
   *           text now share the same optical centre. */
  line-height: 1;
}
.mbb-fav-btn--icon .mbb-fav-btn__icon svg {
  width: 100%;
  height: 100%;
  display: block;
  /* v1.5.27 — overflow:visible so the stroke isn't clipped at edge pixels
   *           on retina displays, which read as a thin dropout under
   *           certain zoom levels. */
  overflow: visible;
}

/* v1.5.27 — KEY FIX for the "white flash / heart disappearing" issue.
 *
 * The previous CSS did:
 *
 *     path { fill: none;     stroke: currentColor; }      (unfavourited)
 *     .is-favourited path { fill: var(--primary); ... }   (favourited)
 *
 * with `transition: fill .15s ease`. The problem: `fill: none` is not a
 * colour — it's the keyword "no fill" — so it can't interpolate to/from
 * an actual colour value. During the 150ms transition the browser jumps
 * the fill state at one end or the other rather than smoothly fading,
 * and on a small icon this reads as a visible blink / disappearance.
 *
 * The fix: ALWAYS use a real fill colour, control visibility via
 * fill-opacity, and transition the opacity (which interpolates cleanly).
 * Unfavourited = transparent fill, stroke shows the outline.
 * Favourited   = opaque fill, same colour throughout.
 *
 * Side benefit: the outlined heart now has a true `fill: currentColor`
 * underneath, so any sub-pixel rendering quirks at the stroke join
 * are masked by a 0-opacity layer of the same colour instead of by the
 * underlying page background showing through.
 */
.mbb-fav-btn--icon .mbb-fav-btn__icon svg path {
  fill: currentColor;
  fill-opacity: 0;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: fill-opacity .15s ease, stroke .15s ease;
}

/* Favourited state — clean filled brand-pink heart, no chip. */
.mbb-fav-btn--icon.is-favourited {
  color: var(--mbb-fav-primary);
}
.mbb-fav-btn--icon.is-favourited .mbb-fav-btn__icon svg path {
  fill-opacity: 1;
  stroke: var(--mbb-fav-primary);
}
.mbb-fav-btn--icon.is-favourited:hover {
  color: var(--mbb-fav-primary-dark);
}
.mbb-fav-btn--icon.is-favourited:hover .mbb-fav-btn__icon svg path {
  stroke: var(--mbb-fav-primary-dark);
}

/* ──────────────────────────────────────────────
 * Placement variant 1 — INLINE WITH TITLE
 *
 * The button is injected INSIDE the title heading element, right after
 * the anchor. We need to:
 *   - sit it next to the title text (inline-flex with vertical alignment)
 *   - not let it inherit the heading's font-size (kills line-height)
 *   - give a tiny gap from the title text
 *
 * The parent heading also needs `display: inline-flex; align-items:center`
 * so the title text + button align horizontally instead of stacking.
 * We can't ALWAYS do that (would break themes that depend on h2 being
 * block-level), so we apply it only when the heading actually CONTAINS
 * our injected button using the :has() pseudo-class. Modern browsers
 * (Chrome 105+, Safari 15.4+, Firefox 121+) — graceful degradation for
 * older browsers means the button shows on the line BELOW the title,
 * which is still acceptable.
 * ────────────────────────────────────────────── */
.mbb-fav-btn--inline-title {
  /* Reset margin: the parent heading now uses a flex gap, so a fixed
   * margin-left was double-spacing. Gap on the parent gives consistent
   * spacing whether the title wraps to multiple lines or not. */
  margin: 0;
  vertical-align: middle;
  font-size: 13px;
  font-weight: normal;
  line-height: 1;
  /* v1.5.27 — explicit inline-flex on the button itself so it never
   *           inherits `display: block` from a theme's button reset.
   *           Without this, Elementor's broad `button { display: block; }`
   *           rules (active in some kits) would push the heart onto its
   *           own line even though the parent heading is flexed. */
  display: inline-flex !important;
  align-items: center;
  /* Tiny vertical lift so the heart's optical centre matches the
   * text's cap-height. Without this it reads as slightly low next to
   * a bold heading. Pixel value, not em — em scales with the heading
   * font-size and breaks the alignment. */
  transform: translateY(-1px);
}

/*
 * v1.5.27 — robust inline-with-title positioning.
 *
 * The previous rule depended SOLELY on the `:has()` pseudo-class to
 * decide which headings get inline-flex layout. That works in modern
 * browsers, BUT Elementor's heading widgets emit a more specific
 * selector chain (e.g. `.elementor-widget-heading .elementor-heading-title`)
 * that resets `display: block` AFTER our :has() rule, so on staging
 * the heading stayed block-level and the heart wrapped to a new line.
 *
 * Fix: provide BOTH selectors — the modern :has() form AND an explicit
 * "any heading element containing our button class" selector with
 * !important to beat Elementor's specificity. The !important is
 * scoped narrowly (only headings that physically contain our button)
 * so it can't break other headings on the page.
 *
 * Why two selectors instead of one: some browser versions (older Safari,
 * older Firefox) don't support :has() at all. The fallback approach uses
 * a descendant selector that any browser handles, paired with the JS
 * already running on the page that toggles a class on the heading.
 *
 * The JS in favourites.js was updated in lockstep to ALSO add a marker
 * class `mbb-fav-host` to the heading it injected into, so this rule
 * has a deterministic anchor on every browser.
 */
h1.mbb-fav-host,
h2.mbb-fav-host,
h3.mbb-fav-host,
h4.mbb-fav-host,
h5.mbb-fav-host,
h6.mbb-fav-host,
h1:has(> .mbb-fav-btn--inline-title),
h2:has(> .mbb-fav-btn--inline-title),
h3:has(> .mbb-fav-btn--inline-title),
h4:has(> .mbb-fav-btn--inline-title),
h5:has(> .mbb-fav-btn--inline-title),
h6:has(> .mbb-fav-btn--inline-title) {
  display: inline-flex !important;
  align-items: center !important;
  flex-wrap: wrap;
  gap: 0 8px;
}

/* Elementor often wraps the heading inside a span with its own block-level
 * styling (.elementor-heading-title). Treat that span the same way so the
 * heart sits next to the title text, not below it. */
.elementor-heading-title.mbb-fav-host,
.elementor-heading-title:has(> .mbb-fav-btn--inline-title) {
  display: inline-flex !important;
  align-items: center !important;
  flex-wrap: wrap;
  gap: 0 8px;
}

/* v1.5.27b — KEY FIX for "title still pushes heart to new line".
 *
 * Even with the heading set to inline-flex above, Elementor's <a> inside
 * the heading was rendering as an effectively block-level element that
 * took the full container width. Result: the heading was flexed but the
 * <a> ate all the horizontal room, so the heart wrapped to the next line.
 *
 * Force the link to size to its text content. `flex-shrink: 1` lets the
 * link shrink-wrap if the title is long, and `min-width: 0` defeats the
 * default flex item min-width that would otherwise prevent shrinking
 * below the intrinsic content size on small viewports. */
.mbb-fav-host > a,
.elementor-heading-title.mbb-fav-host > a {
  display: inline !important;
  flex: 0 1 auto !important;
  min-width: 0 !important;
  width: auto !important;
}

/* ──────────────────────────────────────────────
 * Placement variant 2 — IMAGE OVERLAY
 *
 * Top-right of the listing image. Used as the secondary path when no
 * title heading is detectable. Slightly translucent white circle so
 * the heart pops against any image — but kept compact and circular
 * so it still reads as an icon, not a chunky button.
 * ────────────────────────────────────────────── */
.mbb-fav-btn--on-image {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 5;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(6px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
  color: #6b7280;
}
.mbb-fav-btn--on-image:hover {
  background: rgba(255, 255, 255, 0.95);
  color: var(--mbb-fav-primary-dark);
  transform: scale(1.05);
}
.mbb-fav-btn--on-image.is-favourited {
  color: var(--mbb-fav-primary);
}

/* ──────────────────────────────────────────────
 * Placement variant 3 — FALLBACK ABSOLUTE OVERLAY
 *
 * Original strategy — top-right of the card as an absolute overlay.
 * Used only when neither a title nor an image host is found.
 * ────────────────────────────────────────────── */
.mbb-fav-btn--injected:not(.mbb-fav-btn--inline-title):not(.mbb-fav-btn--on-image) {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 2;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

/* The GD card needs to be a positioning context for absolute-positioned
 * buttons. Most GD themes already set this; we only target cards
 * that contain our absolute-positioned variants so we don't fight the theme. */
.geodir-post:has(.mbb-fav-btn--on-image),
.gd-bh-listing:has(.mbb-fav-btn--on-image),
.geodir-archive-item:has(.mbb-fav-btn--on-image),
[data-elementor-type="geodirectory-archive-item"]:has(.mbb-fav-btn--on-image) {
  position: relative;
}

/* ──────────────────────────────────────────────
 * Dashboard manager — [mbb_favourites_manager]
 * ────────────────────────────────────────────── */

.mbb-fav-manager {
  color: var(--mbb-fav-text);
  font-size: 16px;
  line-height: 1.5;
}

.mbb-fav-manager__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}

.mbb-fav-manager__heading {
  margin: 0;
  font-size: 22px;
  font-weight: 600;
}

.mbb-fav-manager__count {
  margin: 0;
  color: var(--mbb-fav-muted);
  font-size: 14px;
}

.mbb-fav-manager__empty {
  background: var(--mbb-fav-surface-alt);
  border: 1px dashed var(--mbb-fav-border);
  border-radius: var(--mbb-fav-radius);
  padding: 24px;
  text-align: center;
  color: var(--mbb-fav-muted);
}
.mbb-fav-manager__empty p { margin: 0 0 8px; }
.mbb-fav-manager__empty p:last-child { margin: 0; }

.mbb-fav-manager__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.mbb-fav-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--mbb-fav-surface);
  border: 1px solid var(--mbb-fav-border);
  border-radius: var(--mbb-fav-radius);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.mbb-fav-row:hover {
  border-color: var(--mbb-fav-primary);
  box-shadow: 0 1px 4px rgba(255, 164, 187, .25);
}

.mbb-fav-row__link {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1 1 auto;
  min-width: 0; /* allow truncation */
  text-decoration: none;
  color: inherit;
}

.mbb-fav-row__thumb-wrap {
  display: block;
  width: 56px;
  height: 56px;
  flex: 0 0 56px;
  border-radius: 8px;
  overflow: hidden;
  background: var(--mbb-fav-surface-alt);
}
.mbb-fav-row__thumb-wrap--empty {
  background: linear-gradient(135deg, #fff0f4 0%, #ffd8e3 100%);
}
.mbb-fav-row__thumb-wrap img,
.mbb-fav-row__thumb {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.mbb-fav-row__body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.mbb-fav-row__title {
  font-weight: 600;
  font-size: 15px;
  /* truncate long titles cleanly */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mbb-fav-row__meta {
  font-size: 12px;
  color: var(--mbb-fav-muted);
}

.mbb-fav-row__remove {
  flex: 0 0 auto;
  background: transparent;
  border: 1px solid var(--mbb-fav-border);
  border-radius: 999px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 500;
  color: var(--mbb-fav-muted);
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background-color .15s ease;
}
.mbb-fav-row__remove:hover {
  color: #b91c1c;
  border-color: #fecaca;
  background: #fef2f2;
}

.mbb-fav-manager__empty-inline {
  list-style: none;
  padding: 16px;
  text-align: center;
  color: var(--mbb-fav-muted);
  font-size: 14px;
}

/* ──────────────────────────────────────────────
 * Toast notification (v1.5.17c)
 *
 * Subtle corner toast that confirms favourite save/remove.
 * Bottom-right on desktop, bottom-center on mobile (where thumbs
 * naturally rest). High z-index so the toast sits above sticky
 * headers, cookie banners, and chat widgets that some themes add.
 *
 * The container is positioned fixed and append-only — the actual
 * .mbb-fav-toast inside slides in via translateY transition.
 * One toast at a time (JS clears the container before each insert),
 * so layout is simple and predictable.
 * ────────────────────────────────────────────── */
.mbb-fav-toast-container {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 100000;
  pointer-events: none; /* don't intercept clicks on the page */
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}

.mbb-fav-toast {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border-radius: 999px;
  background: #1f2330;
  color: #ffffff;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.3;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.18);
  pointer-events: auto; /* in case we want to allow interaction later */
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .25s ease, transform .25s ease;
  max-width: calc(100vw - 48px);
}
.mbb-fav-toast.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.mbb-fav-toast__icon {
  display: inline-flex;
  width: 18px;
  height: 18px;
}

/* Save variant — brand pink heart against the dark toast for contrast */
.mbb-fav-toast.is-save .mbb-fav-toast__icon {
  color: var(--mbb-fav-primary);
}

/* Remove variant — muted/neutral heart outline, signals "no longer saved" */
.mbb-fav-toast.is-remove .mbb-fav-toast__icon {
  color: #d1d5db;
}

.mbb-fav-toast__text {
  display: inline-block;
}

/* ──────────────────────────────────────────────
 * Small-screen tweaks
 * ────────────────────────────────────────────── */
@media (max-width: 480px) {
  .mbb-fav-btn__label { display: none; }
  .mbb-fav-btn { padding: 6px 9px; }
  .mbb-fav-row__thumb-wrap {
    width: 48px;
    height: 48px;
    flex-basis: 48px;
  }
  /* Bottom-center on mobile — easier to read with thumbs at the bottom */
  .mbb-fav-toast-container {
    right: 16px;
    left: 16px;
    bottom: 16px;
    align-items: center;
  }
  .mbb-fav-toast {
    font-size: 13px;
    padding: 9px 14px;
  }
}
