/* ============================================================
   myBCN Elementor Bridge  (served as mybcn-bridge.css)
   Loaded after the CelebrimborCSS master by the mybcn-celebrimbor
   mu-plugin. Maps native classic Elementor widgets on the 2.0 pages
   to the Celebrimbor tokens. Mostly scoped to .mb-* classes; a
   Site-Wide Elementor Widget Normalisations section at the end adapts
   third-party widgets across all pages.

   Version: v1.117 (12 Jul 2026)
   Full version history: mybcn-elementor-bridge-changelog.md (same folder).
   v1.117: Highlights 1rem gaps (Matt 12 Jul). Put 1rem column+row gaps back between the info
           boxes; widths recomputed to calc((100% - 3rem)/4) so four still fill the row and the
           outer boxes hug the edges.
   v1.116: Kill Xpro Pro's hidden info-box wrapper padding (Matt 12 Jul). The pro plugin
           hardcodes padding:3em 4em on .elementor-widget-xpro-infobox (not a control); zero it
           in the highlights so the boxes aren't framed in dead space.
   v1.115: Highlights no-gap, edge-to-edge (Matt 12 Jul). Zero the row gap; boxes are exact
           quarters (25%) so they touch and hug the container left/right.
   v1.114: Highlights back to four-up + button off (Matt 12 Jul). Kept 4+4 (better than 5+3);
           reverted the five-up; hid the CTA button in the highlights info boxes.
   v1.113: Tour Highlights five-up (Matt 12 Jul). Five per row — eight boxes flow 5 + 3 at ~230px.
   v1.112: Tour Highlights four-up (Matt 12 Jul). Six-up was too cramped; now EIGHT info boxes at
           four per row (two rows of four, ~280px each) — a readable width. Keeps the word-wrap fix.
   v1.111: Tour Highlights six-up, readable (Matt 12 Jul). Re-enable the single row, but force
           normal word-wrap on the info-box text (Xpro breaks the description per-character when
           narrow) + give each box an equal 1/6 width. Desktop only; below 980 = 31% 3-up + stack.
   v1.110: Six-up reverted (Matt 12 Jul). Six across (~110px each) collapsed the description to
           one letter per line; back to the 31% 3-up grid. .mb-infobox-row kept but inert.
   v1.109: Tour Highlights six-up (Matt 12 Jul). .mb-infobox-row lays all six info boxes in ONE
           row edge-to-edge (flex 1 1 0, no wrap) on desktop; below 980 falls back to 3-up/stack.
   v1.108: Info Box image-slot placeholder (Matt 11 Jul). Full-width grey "test screen" block in
           the media slot (was a tiny 10% box) until go-live photos; a real image fills it.
   v1.107: Info Box image->subtitle to 0.5rem; badge pill padding to 0.5em 1em (Matt 11 Jul).
   v1.106: Info Box image->subtitle to 0.75rem (Matt 11 Jul).
   v1.105: Info Box spacing tweaks (Matt 11 Jul). Image->subtitle gap to 1rem; the Xpro
           separator/divider gets 1rem below it (was margin 0, cramped on the description).
   v1.104: Info Box air (Matt 11 Jul). More breathing room in the Info Box adapter: bigger gaps
           below the media, subtitle and title, and above the button.
   v1.103: Xpro Info Box -> Celebrimbor adapter (Matt 11 Jul). Maps the Old Town Tour Highlights
           info boxes to the house look: subtitle = kicker eyebrow, title = display heading
           (--text-h4), description = body, badge = stone-pink pill, button = the shared dark CTA.
   v1.102: Intro + 2x2 onto the scale (Matt 11 Jul). Swap the bespoke lead clamp on the
           drop-cap intro and the 2x2 headings for the standard --text-h4 token (Cormorant),
           the scale step closest to the mock lead; intro keeps lh 1.55, headings --line-height-h4.
   v1.101: Old Town intro + 2x2 type (Matt 11 Jul). Drop-cap intro lead now matches the mock's
           display-serif .lead (clamp(1.25-1.625)/1.55), was sans .mb-lead at --text-h5; the 2x2
           headings take that same lead type; 2x2 outer text edges hug the content box (left col
           no left pad, right col no right pad).
   v1.100: 2x2 watermark-stage cross (Matt 11 Jul). Supersedes v1.99: real CSS grid with a
           centred hairline cross (cell borders) over the BARCINO watermark; equal cells,
           lines meet dead-centre, cells stay transparent. Desktop only.
   v1.99: 2x2 watermark-stage balance (Matt 11 Jul). Authored 48% columns, left-justified,
          put the gutter off-centre with dead space on the right; make the two columns share
          the row minus the 24px gutter (equal cells, centred gutter) and pad the stage 1rem
          each side (rem per house rule).
   v1.98: Xpro timeline full-bleed (Matt 11 Jul). The widget wrapper ships a hard
          padding:20px, insetting the track + connector line from the widget box; zero the
          left/right padding so the line reaches the content-width edge (vertical kept).
   v1.97: Xpro timeline, take 2 (Matt 11 Jul). The widget escapes the item Title field, so
          the &nbsp; content trick (v1.96) printed a literal "&nbsp;". Back to CSS: hide the
          date-box Title slot (.xpro-horizontal-timeline-title), keep the grey Date label;
          also step the era name (.sub-title, a raw kit <h2>) down to --text-h4, size only so
          its font is retained. (v1.96 reverted v1.95; v1.97 reinstates + extends it.)
   v1.94: Watermark-stage Elementor adapter (Matt 11 Jul). Forces the .watermark html
          widget absolute-centred on .mb-band .watermark-stage (Elementor's widget
          transform pinned it lower-right); roomier 2x2 gutter (24px cols / 48px rows).
   v1.93: Hero title subline (Matt 9 Jul). .mb-hero h1 .mb-hero-subline drops to
          0.5em on its own line (ports the mock's .hero-subline) so the title
          reads clearly bigger than the sub; the rule was missing entirely.
   v1.92: Platform brand-colour text utilities (Matt 9 Jul). .mb-brand-airbnb /
          gyg / viator / google / turitop colour a platform NAME span in its
          Celebrimbor --brand-* token, for OTA / review-source labels.
   v1.91: Breadcrumb strip (Matt 9 Jul). New .mb-crumb utility trims a band to a
          slim breadcrumb row (padding-block --space-3), overriding the fluid-xl
          band rhythm while keeping the .mb-band gutter so it stays aligned.
   v1.90: Hamburger toggler transparent (Matt 6 Jul). The Xpro menu toggler
          button had a solid #f5f5f5 fill that read as a box on the 80% bar; made
          it transparent so it blends with the bar.
   v1.89: Slim-on-scroll (Matt 6 Jul). A ~7-line script on the wordmark HTML
          widget toggles .mb-scrolled on <html> after ~40px scroll; the bar trims
          its inner padding 16->8px once scrolled (full height at the top). Xpro's
          own sticky enable was not reachable, so we drive the two-state ourselves.
   v1.88: Header truly sticky (Matt 6 Jul). Xpro's native sticky never binds (its
          JS needs .xtb-header-sticky in the markup, which this header lacks), so
          the bar itself is now position:fixed instead of absolute; it stays in
          view on scroll. Gap + 80/100% bg unchanged; clearances unchanged.
   v1.87: Floating + sticky header (Matt 6 Jul). The Xpro header (5794) floats
          detached from the top by --mb-header-gap (clamp 0.25-0.5rem) at all
          times; Xpro's native Header Sticky keeps it in view on scroll (clone
          .xpro-theme-builder-header-nav, .xtb-appear). Bar background is the
          current #f5f5f5 surface at 80%, 100% on hover; the stuck clone slims its
          inner padding (16 -> 8px). Clearances unchanged.
   v1.86: Hero mobile height (Matt 6 Jul). On phones (<=620) the hero drops its
          85vh min-height to hug content and trims the bottom padding to the side
          gutter (--grid-padding-x), removing the large dark strip below the CTA
          that the 96px bottom padding + flex-end content created. Desktop and
          tablet keep 96px + 85vh untouched. Home 2026 and every .mb-hero.
   v1.81: Eyebrow atom on a native Heading widget. The .eyebrow class lands on
          the heading wrapper, so map the Celebrimbor eyebrow shape onto the
          .elementor-heading-title (caps, 0.35em, 0.75rem, 500). Stories 9426.
   v1.80: Booking coda centring. .mb-coda centres the Band 11 column (text,
          CTA and chips) and centres the column itself in the band. Home 2026.
   v1.79: Post body full-bleed bands. .mybcn-quote-band / .mybcn-coda-band
          in the Xpro Post Content break to the viewport edges; inner blocks
          cap to --prose-width and centre, scoped to the post-content widget.
          Stories 9426, Matt 5 Jul.
   v1.78: Tinted-band dividers take the band's own dark ink
          (--color-divider-cream/-stone-pink/-blush, Celebrimbor v3.109) instead
          of the flat --color-warning. Option B (Matt 5 Jul). White/page grey.
   v1.77: Actually remove the FAQ toggle-title underline. The global <a>
          underline is a background-image, not text-decoration, so v1.76 was a
          no-op; reset background-image + padding-bottom on the title. Band 10.
   v1.76: FAQ toggle titles lose the stray link underline (the title is an <a>,
          so the global content-link underline leaked onto every question).
          text-decoration: none on the title, all states. Home 2026 Band 10.
   v1.75: Post body reading measure. Xpro Post Content text blocks
          (p/h2/h3/h4/ul/ol/blockquote/figure in .xpro-elementor-content)
          cap at --prose-width and centre; .mybcn-quote-band stays full
          width. Blog / Stories single-post template 9426.
   v1.74: Who We Are founder portraits become photo-ready: .mb-who-portraits
          .mb-frame.has-photo drops the placeholder skin and fills the 4:5
          frame edge to edge (object-fit cover), keeping the v1.66 ratio and
          float shadow. Mirrors the tour-card and gallery has-photo rules.
   v1.73: Mobile tour cards lead with the photo (order:-1, whatever the DOM
          order) and give the framed photo a definite 3:2 box so it fills with
          no band gap. Home 2026 Band 4 / 4b.
   v1.72: Tour-row photo frames: .mb-tour .mb-frame.has-photo drops the grey
          placeholder skin and lets the Image widget fill the frame edge to
          edge (object-fit cover, a real <img> for SEO), mirroring the gallery
          has-photo rule. Home 2026 Band 4 walk cards.
   v1.71: FAQ toggle ports the mock v2.63 accordion canon: white card
          items (page surface, 1px border, 24px side padding, 14px gaps)
          with a right-aligned + / minus title marker, muted ink warming
          to terracotta on hover and focus, minus when open, plus a
          focus-visible outline. Replaces the pre-v2.63 minimal underline
          look and the active-title primary-colour flip.
   v1.70: Gallery photo-ready. .mb-gallery cells that carry a real photo
          (.has-photo) drop the placeholder frame skin and pour the Image
          widget edge to edge with object-fit cover, per the mock's
          "photos fill their cells" note.
   v1.69: Reviews-band platforms line (.mb-platforms): small uppercase
          tracked label per the mock. The Feedspace embed loses its
          .mb-frame wrapper Elementor-side (the shrink-wrapping frame made
          the carousel script measure a ~19px container and break).
   v1.68: Brand-eyebrow fix: text-transform and letter-spacing gain
          !important (the base uppercase eyebrow rule sits later in source,
          so v1.67's mixed-case never rendered).
   v1.67: Claim-band exceptions. .mb-claim-h stacks the three claim
          sentences and takes off-white (--section-dark-text) instead of
          pure white; .mb-eyebrow--brand is warm sand and mixed case on
          dark. The band's page-grey tilt divider is Elementor-side.
   v1.66: Who We Are offset portrait pair (.mb-who-portraits): side-by-side
          2-col grid, second figure dropped 56px (28px <=620), 4:5 frames
          with --shadow-soft, mock-canon captions. Mock v2.8 device, was
          missing from the live build.
   v1.65: Quote-line hierarchy. .mb-quote returns to the display h3 size
          (v1.64 had it inherit the intro size, which read SMALLER than the
          supporting text); the block, width cap and supporting paragraph
          keep the v1.64 intro treatment.
   v1.64: Founders' quote reads as the intro. .mb-quote-block caps the Band 5
          column to the .mb-lead-entity measure (57ch, centred) and sets the
          intro's display type on its text; .mb-quote drops the h3 size and
          gains a terracotta opening quote mark (replaces the mock's left rule,
          Matt 04 Jul 2026).
   v1.63: Fluid wave shape-divider height. .mb-band shape dividers scale
          1rem (<=620) to 2rem (>=980) via clamp, interpolated between the
          bridge's established breakpoints; !important beats Elementor's
          per-element height rule.
   v1.62: Tinted bands self-paint. .mb-stone-pink and .mb-blush now paint
          their own background like .mb-cream (v1.47), guarding against a
          band losing its inline background colour (item 157 drift).
          Element-level Elementor rules still out-specify the class, so a
          deliberate inline colour (e.g. the light-cream coda) wins.
   v1.61: Footer link underline. Suppress the Celebrimbor background-image
          link highlight on dark-footer links (off-palette blue at rest);
          hover keeps a plain text underline.
   v1.60: Footer consolidation + colour-specificity fix. Footer layout
          (direction, wrap, widths, collapse) moved to the Xpro 2704
          Elementor container settings; the bridge block is skin-only and
          re-asserts the footer text palette above .mb-band text-editor.
   v1.59: Footer flex-direction fix. The cols, brand, links and legal
          containers were inheriting Elementor's default column; set them
          to row so the footer lays out across, not stacked.
   v1.58: Footer (.mb-footer). Dark site footer ported from the Home 2026
          mock into the Xpro footer template 2704: brand block, four link
          columns, legal bar; tokens from the dark-section group; 980/620
          responsive collapse.
   v1.57: Icon-led stat chips. .mb-chip--time/group/price/scope and
          .mb-chip.is-ticket carry a small masked line icon in currentColor.
          Untyped .mb-chip unchanged, so deploy-safe before the home rebuild
          re-emits the type classes. Mirrors the Home 2026 mock v2.69.
   v1.56: Band 4 format-card alignment (.mb-format-cards). Reserve the heading
          and pill rows to two lines and float the link to the card foot so the
          three "How You Can Take a Tour" cards share one baseline (desktop).

   Contents (in source order):
     - Bands: max-width, boxed gutter, fluid rhythm, column collapse, gallery bento
     - Container queries
     - Full-bleed layout utilities, dark-band text
     - Headings, sub-labels, dividers
     - Body copy, leads, hero subtitle, eyebrows, kickers, quotes
     - Meta chips, text links (neumorphic chip + surface matching)
     - Buttons (dark .btn--cta family)
     - Decoration layer: hero scrim, cards (3 families), framed photo slots, FAQ
     - Footer (dark chrome): brand block, link columns, legal bar
     - Site-wide normalisations: header overlap, Xpro menu, EAC breadcrumb
   ============================================================ */

/* Bands ------------------------------------------------------ */
.mb-band > .e-con-inner { max-width: var(--grid-max-width); }

/* Boxed-container gutter (v1.15, scoped to 2.0 at v1.43): with the kit's global
   Container Padding now 0, the horizontal reading gutter lives here. 2.0 .mb-band
   bands use var(--grid-padding-x) (the fluid clamp 24px on phones up to 96px on
   desktop, Celebrimbor v3.99, single source); legacy 1.0 boxed bands keep the
   tighter clamp(16px, 4vw, 32px). Both apply on every BOXED container's inner
   (including on mobile), while content_width:full containers stay edge-to-edge for
   full-bleed media. Nested boxed containers reset to 0 so the gutter applies once,
   at the outermost boxed (avoids the double gutter on the hero's boxed content
   wrapper inside the boxed band). .mb-band { padding-inline:0 } stays to kill the
   per-band 20px L/R baked into the page _elementor_data. */
.mb-band { padding-inline: 0 !important; }
.e-con-boxed > .e-con-inner { padding-inline: clamp(var(--space-4), 4vw, var(--space-8)); } /* legacy 1.0 default: 16-32px */
.mb-band.e-con-boxed > .e-con-inner { padding-inline: var(--grid-padding-x); }              /* 2.0 bands: roomy 24-96px (v1.43) */
.e-con-boxed .e-con-boxed > .e-con-inner { padding-inline: 0; }

/* Fluid band rhythm (v1.34, site-wide). Content bands breathe on
   --space-fluid-xl (48px at 375px -> 96px at 1440px), replacing the baked
   64px band padding-block. Boxed containers apply band padding to the
   .e-con-inner child, so this targets the inner (not the outer .mb-band):
   setting it on the outer at v1.31/v1.32 stacked on top of the inner's 64px
   and doubled the rhythm. !important beats the Elementor consumption rule
   .e-con > .e-con-inner { padding-block-start: var(--padding-block-start) }.
   Hero (.mb-hero, own 96px on its inner) excluded.
   Plan: operations/design/celebrimbor-fluid-spacing-application-plan.md */
.mb-band:not(.mb-hero) > .e-con-inner { padding-block: var(--space-fluid-xl) !important; }

/* Breadcrumb strip (v1.91). .mb-crumb trims a band to a slim breadcrumb row,
   overriding the fluid-xl rhythm above with tight vertical padding. It stays a
   .mb-band, so the horizontal gutter (--grid-padding-x) is unchanged and the crumb
   still aligns with the bands above and below. Reusable across all tour pages. */
.mb-band.mb-crumb > .e-con-inner { padding-block: var(--space-3) !important; }

/* Hero mobile height (v1.86, Matt 6 Jul 2026). The hero keeps its baked 96px
   inner padding and 85vh min-height on tablet/desktop. On phones the 85vh
   re-opens a dead strip: the inner is justify-content:flex-end, so any height
   above the content collects ABOVE it, and the 96px bottom padding then reads
   as a large dark band under the CTA. On <=620: drop the min-height so the hero
   hugs its content, and shrink the bottom padding to the reading gutter
   (--grid-padding-x, 24-43px on phones) so the band matches the side gutter.
   Top padding stays (clears the 59px absolute header). !important beats the
   baked page min-height and Elementor's (0,4,0) .e-con-inner padding consumption
   (a plain class rule loses to it even with the inline padding stripped, so the
   generator's hero settings are left as-is). Desktop/tablet unchanged. */
@media (max-width: 38.75rem) {
  .mb-hero { min-height: 0 !important; }
  .mb-hero > .e-con-inner { padding-bottom: var(--grid-padding-x) !important; }
}

/* Fluid card-row gutter (v1.33 intent, rule added v1.35). Multi-card grid rows
   carry .mb-cards (the Mírdain generator row() default); their gap grows on the
   fluid scale, 24px at 375px to 40px at 1440px. !important beats Elementor's
   gap:var(--gap) from the per-row flex_gap. Framed tour rows (.mb-tour, gap:0)
   are not .mb-cards and stay flush. */
.mb-cards { gap: var(--space-fluid-md) !important; }

/* Multi-column band collapse (bridge v1.38) ------------------
   Mirrors the DESIGN.md column-collapse convention (agreed 28 Jun 2026, Matt)
   onto the live Elementor columns. The staging grid (.span-*) already follows
   it; the live pages use Elementor flex columns through .mb-cards rows, so the
   same behaviour is enforced here. Hard rule: below desktop no band shows more
   than two columns.

   The Mírdain generator tags each multi-card row with its desktop column count:
     .mb-cards-3  three-up  (Band 3 tiers, the format cards, the FAQ trio)
     .mb-cards-4  four-up   (the Story cards)
     .mb-cards-6  six-up    (the .span-2 row)
     .mb-gallery  the photo gallery (held at 2-up below desktop, never 1)
   Columns carry .mb-col (the existing dual-keyed column convention). Desktop
   widths (>980) are left to Elementor; these rules only act at the collapse
   points. !important beats Elementor's per-device width controls and inline
   per-breakpoint styles, as the .mb-cards gap rule above does. Two-up basis
   subtracts half the row gap so two cells plus one gap make 100% when wrapped.
   Breakpoints match the Celebrimbor set: --bp-lg 61.25rem (980), --bp-sm
   38.75rem (620). Footers are Xpro chrome (template 2704), out of mb-* scope.
   Tour rows (.mb-tour) are already two-up and keep their own 768px stack. */

/* Three-up: collapse straight 3 -> 1 at 980, no 2+1 orphan stage. */
@media (max-width: 61.25rem) {
  .mb-cards-3 { flex-wrap: wrap; }
  .mb-cards-3 > .mb-col {
    flex: 1 1 100% !important;
    max-width: 100% !important;
  }
}

/* Four-up Stories: 4 -> 2+2 at 980, then -> 1 at 620. */
@media (max-width: 61.25rem) {
  .mb-cards-4 { flex-wrap: wrap; }
  .mb-cards-4 > .mb-col {
    flex: 1 1 calc(50% - (var(--space-fluid-md) / 2)) !important;
    max-width: calc(50% - (var(--space-fluid-md) / 2)) !important;
  }
}
@media (max-width: 38.75rem) {
  .mb-cards-4 > .mb-col {
    flex: 1 1 100% !important;
    max-width: 100% !important;
  }
}

/* Six-up (.span-2): cap to two columns at 980, then -> 1 at 620. */
@media (max-width: 61.25rem) {
  .mb-cards-6 { flex-wrap: wrap; }
  .mb-cards-6 > .mb-col {
    flex: 1 1 calc(50% - (var(--space-fluid-md) / 2)) !important;
    max-width: calc(50% - (var(--space-fluid-md) / 2)) !important;
  }
}
@media (max-width: 38.75rem) {
  .mb-cards-6 > .mb-col {
    flex: 1 1 100% !important;
    max-width: 100% !important;
  }
}

/* Desktop multi-card rows (bridge v1.44): pair with the <=980 collapse above.
   Above 980 the authored width % (31% three-up, 23% four-up, 32+33+33% on the FAQ)
   plus the .mb-cards gap exceeded 100% on non-shrinking Elementor flex cols, so the
   last card wrapped to an orphan row (3+1, 2+1). Let the cards share the row minus
   the gaps instead: flex:1 1 0 with min-width:0 fits N columns on one row at any
   desktop width, no wrap. width:auto neutralises Elementor's inline width %.
   Gated at min-width:61.3125rem (981px) so it never overlaps the collapse points. */
@media (min-width: 61.3125rem) {
  .mb-cards-3 > .mb-col,
  .mb-cards-4 > .mb-col,
  .mb-cards-6 > .mb-col {
    flex: 1 1 0 !important;
    width: auto !important;
    max-width: 100% !important;
    min-width: 0 !important;
  }
}

/* Band 4 "How You Can Take a Tour" format cards (.mb-format-cards, also .mb-cards-3):
   line the three cards up so the pills, paragraph and link share a baseline and the
   links bottom-align, matching the Home 2026 mock. The cards are equal-height flex
   columns, so margin-top:auto floats each link to the card foot; the heading (2nd
   widget) and pill (3rd widget) rows are reserved to two lines so a one-line heading
   or one-line pill set still lines up with the wrapping Private card. Desktop only:
   below 980 the row collapses to one column (see the .mb-cards-3 collapse above),
   where cross-card alignment is moot. Subgrid would be cleaner but Elementor's
   grid-track sizing fought it; revisit at the V4 Global Classes migration. v1.56. */
@media (min-width: 61.3125rem) {
  .mb-format-cards > .mb-card > .elementor-element:nth-child(2) { min-height: 4em; }
  .mb-format-cards > .mb-card > .elementor-element:nth-child(3) { min-height: 5.8em; }
  .mb-format-cards > .mb-card > .elementor-element:last-child { margin-top: auto !important; }
}

/* Gallery: asymmetric bento (bridge v1.40). Maps the mock .bento onto the live
   Elementor container. The mock is a 12-column CSS grid: the dominant cell spans
   8 columns and 2 rows, the five supporting cells span 4. Elementor containers
   are flexbox by default, so .mb-gallery is forced to display:grid here and each
   cell carries .mb-cell-hero (dominant) or .mb-cell. Auto-placement then fills a
   clean rectangle: hero at cols 1-8 over two rows, two cells stacked at cols 9-12,
   and a three-cell row beneath. Below desktop it stays within two columns: cells
   go 2-up (span 6), the dominant goes full, and the last orphan widens to full,
   matching the mock's own collapse and the never-more-than-two convention. The
   row gap uses the fluid token, like the .mb-cards rows. This is the one band that
   overrides the flex container with grid, so its children take grid placement, not
   flex width: neutralise Elementor's inline child width with width:auto. */
.mb-gallery {
  display: grid !important;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-rows: minmax(160px, auto);
  gap: var(--space-fluid-md);
}
.mb-gallery > .e-con { width: auto !important; max-width: none !important; }
.mb-gallery > .mb-cell      { grid-column: span 4; }
.mb-gallery > .mb-cell-hero { grid-column: span 8; grid-row: span 2; }
@media (max-width: 61.25rem) {
  .mb-gallery > .mb-cell      { grid-column: span 6; }
  .mb-gallery > .mb-cell-hero { grid-column: span 12; grid-row: auto; }
  .mb-gallery > .mb-cell:last-child { grid-column: span 12; }
}
@media (max-width: 38.75rem) {
  .mb-gallery { grid-auto-rows: minmax(120px, auto); }
}
/* Gallery photo cells (v1.70, photo-ready for the item-4 photo pass): a cell
   that carries a real photo takes .has-photo next to .mb-frame. The placeholder
   skin (grey fill, border, centred label styling) drops away and the native
   Image widget pours edge to edge with object-fit cover, per the mock's
   "photos fill their cells" note. The Image widget path per cell keeps a real
   <img> (alt text, lazy load, srcset) for image SEO, unlike a background
   image. min-height/padding zeroed so the grid tracks own the cell size. */
.mb-gallery > .has-photo { background: none; border: 0; padding: 0;
  overflow: hidden; min-height: 0; }
.mb-gallery > .has-photo .elementor-widget-image,
.mb-gallery > .has-photo .elementor-widget-image .elementor-widget-container {
  width: 100% !important; max-width: none !important; height: 100%; }
.mb-gallery > .has-photo img {
  display: block; width: 100%; height: 100%; object-fit: cover; }

/* Container queries (bridge v1.2, 22 Jun 2026): make the capped band
   inner and the column containers query containers, so the Celebrimbor
   cqi heading scale sizes section headings to the content width and
   column headings to their column, instead of the viewport. Pairs with
   CelebrimborCSS v3.84. .mb-col is the column convention: every column
   container on a 2.0 page carries it (dual-keyed css_classes/_css_classes). */
.mb-band > .e-con-inner { container-type: inline-size; }
.mb-col { container-type: inline-size; }

/* Full-bleed layout model (bridge v1.13, opt-in) ------------------
   End-state: set Elementor's global Container Padding to 0 so every section
   is full-bleed by default (mobile media can reach the screen edge), and let
   the horizontal reading gutter live here as a clamp, not as a fixed global px.
   Opt-in for now; the site-wide flip moves .mb-gutter onto .mb-band >
   .e-con-inner and zeroes the global padding together. */
.mb-gutter { padding-inline: var(--grid-padding-x); } /* 24px phones -> 96px desktop (v1.42, single source) */
.mb-bleed { margin-inline: calc(-1 * var(--grid-padding-x)); width: auto; max-width: none; } /* break a media child out of a .mb-gutter container to the section edge */
.mb-dark .elementor-heading-title { color: var(--color-surface) !important; }
.mb-dark .elementor-widget-text-editor,
.mb-dark .elementor-widget-text-editor p { color: var(--color-surface-page); }
.mb-dark .mb-eyebrow { color: var(--color-primary-l1) !important; }
/* Claim-band exceptions (v1.67, mock canon): the dark claim h2 is off-white,
   not pure white, and stacks its three sentences (span per line, no wrap,
   mock .claim h2 span); the brand eyebrow is warm sand and mixed case
   ("myBCN", never "MYBCN", the mock .eyebrow--brand exception). Sand text is
   fine ON DARK (footer precedent, v1.60); it stays background-only on light
   surfaces per the Celebrimbor AA note. !important to override the two
   dark-band defaults above at equal weight, source order wins. */
.mb-dark .mb-claim-h .elementor-heading-title { color: var(--section-dark-text) !important; }
.mb-claim-h .elementor-heading-title span { display: block; white-space: nowrap; }
/* transform/tracking need !important too: the base .mb-band .mb-eyebrow
   uppercase rule sits LATER in this file, so source order alone loses (v1.68). */
.mb-dark .mb-eyebrow--brand { color: var(--color-warning) !important; text-transform: none !important; letter-spacing: .04em !important; }

/* Headings --------------------------------------------------- */
.mb-band .elementor-widget-heading .elementor-heading-title {
  color: var(--color-dark);
  font-weight: 600;
  line-height: 1.12;
}
/* Display serif is for section headings only (H1/H2). H3-H6 widgets stay
   sans (Celebrimbor font policy). The old broad font-family rule above
   set display on every heading widget and out-specified the H3 sans
   override (0,3,0 vs 0,2,1), so cards rendered serif on WordPress while
   the Vercel mock, which has no .elementor-widget-heading wrapper, did not. */
.mb-band h1.elementor-heading-title,
.mb-band h2.elementor-heading-title { font-family: var(--font-family-display); }
.mb-band h1.elementor-heading-title { font-size: var(--text-h1); }
.mb-band h2.elementor-heading-title { font-size: var(--text-h2); }
/* Section headings are light display serif (canon: h1/h2 = 300, DESIGN.md
   type scale). The blanket heading rule above sets 600 at (0,3,0), which
   out-specifies a plain h2 rule, so this override carries the wrapper class
   to win. h3-h6 stay 600. (Bridge v1.5, Home 9141 fidelity.) */
.mb-band .elementor-widget-heading h1.elementor-heading-title,
.mb-band .elementor-widget-heading h2.elementor-heading-title {
  font-weight: var(--font-weight-300-light);
}
.mb-band .elementor-widget-heading h3.elementor-heading-title {
  font-family: var(--font-family-sans); font-weight: var(--font-weight-400-normal); font-size: var(--text-h3);
}
/* sub-label headings (How You Can Take a Tour / Our Walks / Combine Sites) */
.mb-band .mb-sublabel .elementor-heading-title {
  font-family: var(--font-family-sans); font-weight: 600;
  font-size: var(--text-sm); letter-spacing: .12em; text-transform: uppercase;
  color: var(--color-primary-d1);
}
/* Dividers on TINTED bands take that band's own dark ink (Option B, Matt 5 Jul 2026):
   --color-divider-{cream|stone-pink|blush}, a visibly darker step of the band's tint in the
   same hue as its neu-buttons. It sits one shade below the ±10 neu-shadow MATE
   (--color-tint-dark-*), which is tuned as a soft shadow and is too faint for a 1px rule.
   Replaces the flat --color-warning sand that painted every tinted band the same, so each
   band reads as one coherent set (divider = the band's own dark edge). White and page-grey
   bands keep grey (the widget's stored --color-border); dark bands keep their own. Elementor
   stores the colour as the per-widget --divider-color, whose generated rule out-specifies a
   plain descendant selector, so !important is needed. */
.mb-cream .elementor-widget-divider      { --divider-color: var(--color-divider-cream) !important; }
.mb-stone-pink .elementor-widget-divider { --divider-color: var(--color-divider-stone-pink) !important; }
.mb-blush .elementor-widget-divider      { --divider-color: var(--color-divider-blush) !important; }

/* Body copy -------------------------------------------------- */
.mb-band .elementor-widget-text-editor {
  font-family: var(--font-family-sans);
  color: var(--color-text);
  font-size: var(--text-base);
  line-height: 1.6;
}
.mb-band .mb-lead { font-size: var(--text-h5); line-height: 1.5; }
/* v1.101/1.102: drop-cap intro lead is display serif (was the generic sans .mb-lead at
   --text-h5). v1.102 puts it on the scale at --text-h4 (Cormorant), the step closest to the
   mock's lead clamp(1.25-1.625); keeps the readable 1.55 line-height. Scoped to drop-cap leads. */
.mb-band .mb-lead.dropcap { font-family: var(--font-family-display); font-size: var(--text-h4); line-height: 1.55; }
/* Entity-declaration lead: the centred display-serif statement under the hero
   (mock .lead start-3). The class sits on the text-editor widget (_css_classes),
   so this rule follows the .elementor-widget-text-editor sans default above and
   wins on source order. Capped to the 8-of-12 column measure and centred; below
   that width the block is naturally full width, as the mock does on mobile. */
.mb-band .mb-lead-entity {
  font-family: var(--font-family-display);
  font-size: clamp(1.25rem, 2.2vw, 1.625rem);
  line-height: 1.55;
  color: var(--color-dark);
  /* Cap by READING MEASURE, not a fixed proportion. width:min(100%, 57ch) holds
     ~57 characters per line at every width and fills the band only when the screen
     is too narrow to keep that measure, with no breakpoint and no snap. The lead
     font is itself fluid (clamp above), so the ch cap grows and shrinks with the
     type and the measure stays ~constant from desktop to phone: 57ch is ~707px at
     the 26px desktop size (the old 6-of-12 width) and ~544px at the 20px floor on a
     portrait tablet, still ~57 chars, where the old fixed 50% fell to ~37 chars.
     This is the Measure and Readability standard (cap by characters per line)
     applied to a fluid display lead. !important because Elementor custom-frontend.css
     constrains widget sizing
     (.e-con.e-con > .e-con-inner > .elementor-widget { max-width:100% }, (0,4,0)). */
  width: min(100%, 57ch) !important;
  margin-inline: auto;
}
/* Hero subtitle: the sub line under the hero h1 (mock .hero .sub). A steady
   1.0625rem, distinct from the larger generic .mb-lead. Off-white colour comes
   from .mb-dark, the width from the v1.18 hero-copy cap, so only the size lives
   here; font and line-height inherit the sans body default. */
.mb-hero .mb-hero-subtitle { font-size: 1.0625rem; }
.mb-band .mb-eyebrow {
  font-family: var(--font-family-sans); font-weight: 600;
  font-size: var(--text-sm); letter-spacing: .12em; text-transform: uppercase;
  color: var(--color-primary-d1); margin: 0 0 .4em;
}
/* Reviews-band platforms line (v1.69, mock .platforms): the quiet uppercase
   source-platform label under the What Guests Say hairline. */
.mb-band .mb-platforms { font-size: .8125rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--color-text-muted); margin: 10px 0 0; }
/* Platform brand-colour text utilities (v1.92). Colour a single platform NAME
   span in its brand token (Celebrimbor --brand-*, mirrors Bree's OTA colours).
   For OTA / review-source labels: the .mb-platforms line and review-card cites.
   Overrides the muted parent colour; use on a name span, not fine grey text. */
.mb-brand-airbnb  { color: var(--brand-airbnb)  !important; }
.mb-brand-gyg     { color: var(--brand-gyg)     !important; }
.mb-brand-viator  { color: var(--brand-viator)  !important; }
.mb-brand-google  { color: var(--brand-google)  !important; }
.mb-brand-turitop { color: var(--brand-turitop) !important; }

/* Watermark-stage on 2.0 Elementor pages (v1.94). Adapts Celebrimbor's .watermark
   device to Elementor's widget wrappers: the BARCINO html widget carries .watermark on
   its wrapper, so force it absolute-centred on the stage (Elementor's per-widget transform
   otherwise pins it to the lower-right and it reads as barely-there). Also a roomier 2x2
   gutter than the default .mb-cards gap: column matches the mock (24px), rows breathe (48px). */
.mb-band .watermark-stage { position: relative; column-gap: var(--space-6) !important; row-gap: var(--space-12) !important; }
.mb-band .elementor-widget.watermark {
  position: absolute !important; left: 50% !important; top: 50% !important;
  right: auto !important; bottom: auto !important;
  transform: translate(-50%, -50%) !important; margin: 0 !important;
  width: max-content; max-width: 100%; z-index: 0; pointer-events: none;
}
/* v1.100: 2x2 watermark-stage CROSS (Matt 11 Jul; supersedes v1.99's equal-flex-column).
   Desktop: turn the stage into a real 2x2 CSS grid, gap 0, and draw a centred hairline cross
   with cell borders — right border on the left column, bottom border on the top row — so the
   vertical and horizontal lines always meet dead-centre. Cells stay transparent so the BARCINO
   watermark shows through. The .watermark html widget is the stage's FIRST DOM child and is
   absolute-positioned (not a grid item), so the four .mb-col cells are DOM children 2..5: the
   left column = 2 & 4 (even), the top row = 2 & 3. Stage keeps 1rem side padding; cells get
   1rem inner padding for breathing room from the lines (rem per the house rule). Below 980 the
   stage stacks 1-up via Elementor flex-direction:column + the v1.94 row-gap, no cross. */
.mb-band .watermark-stage { padding-left: 0 !important; padding-right: 0 !important; }
/* v1.101/1.102: 2x2 headings take the intro's display-serif type, standardised to --text-h4
   (Cormorant) with the h4 line-height. */
.mb-band .watermark-stage .elementor-heading-title {
  font-family: var(--font-family-display) !important;
  font-size: var(--text-h4) !important;
  line-height: var(--line-height-h4) !important;
}
@media (min-width: 61.3125rem) {
  .mb-band .watermark-stage {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    column-gap: 0 !important; row-gap: 0 !important;
  }
  .mb-band .watermark-stage > .mb-col {
    width: auto !important; max-width: none !important; padding: 1rem !important;
  }
  /* v1.101: outer text edges hug the content box — left column loses its left pad, right
     column loses its right pad — mirrored, so text runs to the band content border. */
  .mb-band .watermark-stage > .mb-col:nth-child(even) { padding-left: 0 !important; }
  .mb-band .watermark-stage > .mb-col:nth-child(odd)  { padding-right: 0 !important; }
  .mb-band .watermark-stage > .mb-col:nth-child(even) { border-right: 1px solid var(--color-border) !important; }
  .mb-band .watermark-stage > .mb-col:nth-child(2),
  .mb-band .watermark-stage > .mb-col:nth-child(3) { border-bottom: 1px solid var(--color-border) !important; }
}

/* Xpro Horizontal Timeline date de-dup (v1.97). The date box needs BOTH the item Title and
   Date filled to render, and prints both; the widget escapes the Title field, so a &nbsp;
   there shows literally (v1.96's content trick failed). So fill both with the period and hide
   the Title slot; the grey Date label carries the single visible period. Also step the era
   name (.sub-title, a raw kit <h2>) down to --text-h4 — size + line-height only, font kept. */
.mb-band .xpro-horizontal-timeline-title { display: none !important; }
.mb-band .xpro-horizontal-timeline-sub-title {
  font-size: var(--text-h4) !important;
  line-height: var(--line-height-h4) !important;
}
/* v1.98: the Xpro wrapper's hard padding:20px insets the track + connector line; drop the
   left/right so the line runs to the content-width edge (top/bottom breathing room kept). */
.mb-band .xpro-horizontal-timeline-wrapper { padding-left: 0 !important; padding-right: 0 !important; }
.mb-band .mb-kicker {
  font-family: var(--font-family-sans); font-weight: 600;
  font-size: var(--text-sm); letter-spacing: .08em; text-transform: uppercase;
  color: var(--color-primary-d1); margin: 0 0 .25em;
}
.mb-band .mb-subtitle { font-family: var(--font-family-display); font-style: italic;
  font-size: var(--text-h5); color: var(--color-text-muted); margin: 0 0 .4em; }
/* Founders' quote block (v1.64, Matt 04 Jul 2026): the Band 5 quote reads as the
   Band 2 intro. .mb-quote-block sits on the COLUMN container and mirrors the
   .mb-lead-entity measure: the intro's fluid display size on the wrapper (so the
   57ch cap resolves against the same font and the width matches the intro
   exactly), centred. Elementor containers take width from the --width custom
   property, so both --width and max-width are set. The text-editor children get
   the intro type explicitly ((0,3,0) beats the (0,2,0) sans body default); the
   .mb-eyebrow attribution keeps its own p-level style. NOTE: this replaces the
   mock's terracotta LEFT RULE quote identity with a terracotta QUOTE MARK, Matt's
   call 04 Jul 2026; carry into the mock, Celebrimbor and DESIGN.md to close drift. */
.mb-band .mb-quote-block {
  font-size: clamp(1.25rem, 2.2vw, 1.625rem);
  --width: min(100%, 57ch);
  max-width: min(100%, 57ch);
  margin-inline: auto;
}
.mb-quote-block .elementor-widget-text-editor {
  font-family: var(--font-family-display);
  font-size: clamp(1.25rem, 2.2vw, 1.625rem);
  line-height: 1.55;
  color: var(--color-dark);
}
/* The quote line itself carries MORE weight than the supporting paragraph
   (Matt 04 Jul 2026: quote > support, not equal): back to the display h3 size
   inside the intro-sized block, so the hierarchy reads quote-then-comment. */
.mb-band blockquote.mb-quote { font-family: var(--font-family-display); font-style: italic;
  font-size: var(--text-h3); line-height: 1.3; color: var(--color-dark); border: 0; margin: 0 0 .5em; padding: 0; }
/* Decorative opening quote mark: display serif, terracotta (carries the brand
   terracotta from the retired left rule), hung above the first line. */
.mb-band blockquote.mb-quote::before {
  content: "\201C";
  display: block;
  font-family: var(--font-family-display);
  font-style: normal;
  font-size: 2.75em;
  line-height: .55;
  color: var(--color-primary);
  margin-bottom: .2em;
}

/* Booking coda (v1.80, Band 11): the quiet centred CTA block. .mb-coda sits on the
   column; text-align centres the heading and the chip line, align-items centres the
   button (a flex item) and the widget boxes, and margin-inline auto centres the column
   itself in the band. Mirrors the mock .book { text-align: center }. The heading and
   button also carry their own align:center so their per-widget align setting does not
   fight this. */
.mb-band .mb-coda { text-align: center; align-items: center; margin-inline: auto; }

/* Who We Are offset portrait pair (v1.66, mock v2.8 canon): the two founder
   figures sit side by side as a 2-column grid with the SECOND dropped 56px
   (28px on phones), the asymmetric editorial device. Each figure is a plain
   column container (frame + caption); display:grid needs !important against
   Elementor's own container display. Frames go 4:5 portrait with the diffused
   float shadow (the mock reserves --shadow-soft for this hero-card moment);
   the inline placeholder min-height is overridden so the ratio owns the
   height. Captions match the mock figcaption (small, muted, name in dark). */
.mb-band .mb-who-portraits { display: grid !important; grid-template-columns: 1fr 1fr;
  gap: clamp(16px, 2vw, 24px); align-items: start; }
.mb-who-portraits > .e-con:last-child { margin-top: 56px; }
@media (max-width: 38.75rem) { .mb-who-portraits > .e-con:last-child { margin-top: 28px; } }
.mb-who-portraits .mb-frame { aspect-ratio: 4 / 5; min-height: 0 !important;
  box-shadow: var(--shadow-soft); }
.mb-who-portraits .mb-meta { font-size: .8125rem; color: var(--color-text-muted);
  line-height: 1.5; margin: 10px 0 0; }
.mb-who-portraits .mb-meta strong { color: var(--color-dark); font-weight: 600; }
/* Who We Are portrait photo slots (v1.74): the founder frames take .has-photo like
   the gallery cells and the Band 4/4b tour cards, so the placeholder skin drops and
   the Image widget fills the 4:5 frame edge to edge (object-fit cover, a real <img>
   for SEO). The 4:5 ratio and the diffused float shadow stay from the v1.66 rule
   above. Elementor's stock placeholder holds each slot until the founder portraits
   are dropped in. Mirrors the .mb-tour .mb-frame.has-photo rule. */
.mb-who-portraits .mb-frame.has-photo { background: none; padding: 0; }
.mb-who-portraits .mb-frame.has-photo .elementor-widget-image,
.mb-who-portraits .mb-frame.has-photo .elementor-widget-image .elementor-widget-container { width: 100% !important; max-width: none !important; height: 100%; }
.mb-who-portraits .mb-frame.has-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Meta chips ------------------------------------------------- */
.mb-band .mb-meta { line-height: 2; margin: .4em 0; }
.mb-band .mb-chip { display: inline-block; border: 1px solid var(--color-border);
  background: var(--color-surface); border-radius: 999px; padding: 3px 11px;
  font-family: var(--font-family-sans); font-size: var(--text-sm);
  color: var(--color-text-muted); margin: 0 6px 6px 0; }
.mb-band .mb-chip.is-ticket { background: var(--color-tint-stone-pink); }
/* Icon-led stat chips (v1.57). A small line icon, set by a type-modifier class,
   sits before the duration/group/price stat, plus the Interior+Exterior scope
   chip and the Tickets-not-included caveat. The icon is a CSS mask painted in
   currentColor, so it follows the chip's own text colour on every surface.
   Untyped .mb-chip stays exactly as before, so this is safe to deploy ahead of
   the generated markup carrying the modifier classes (the bare chips simply
   show no icon until the home build re-emits them). */
.mb-band .mb-chip--time, .mb-band .mb-chip--group, .mb-band .mb-chip--price,
.mb-band .mb-chip--scope, .mb-band .mb-chip.is-ticket {
  display: inline-flex; align-items: center; gap: 0.34em;
}
.mb-band .mb-chip--time::before, .mb-band .mb-chip--group::before,
.mb-band .mb-chip--price::before, .mb-band .mb-chip--scope::before,
.mb-band .mb-chip.is-ticket::before {
  content: ""; flex: none; width: 1.1em; height: 1.1em; background: currentColor;
  -webkit-mask: var(--mb-chip-ic) center / contain no-repeat;
  mask: var(--mb-chip-ic) center / contain no-repeat;
}
.mb-band .mb-chip--time  { --mb-chip-ic: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='9'/><path d='M12,7.5v4.7l3,1.8'/></svg>"); }
.mb-band .mb-chip--group { --mb-chip-ic: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='9' cy='8' r='3.3'/><path d='M3.5,19a5.5,5.5,0,0,1,11,0'/><path d='M16,5.2a3,3,0,0,1,0,5.6'/><path d='M18,14a5.2,5.2,0,0,1,2.5,5'/></svg>"); }
.mb-band .mb-chip--price { --mb-chip-ic: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M3.5,4.5h7l9,9a1.5,1.5,0,0,1,0,2.1l-4.9,4.9a1.5,1.5,0,0,1-2.1,0l-9-9Z'/><circle cx='7.6' cy='8.6' r='1.3'/></svg>"); }
.mb-band .mb-chip--scope { --mb-chip-ic: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4,20.5h16'/><path d='M6,20.5V8l6-4,6,4V20.5'/><path d='M10,20.5v-4.5h4v4.5'/><path d='M9,11h0M15,11h0'/></svg>"); }
.mb-band .mb-chip.is-ticket { --mb-chip-ic: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4,7.5h16v3a1.8,1.8,0,0,0,0,3.6v2.4H4V14.1a1.8,1.8,0,0,0,0-3.6Z'/><path d='M14,7.5v9' stroke-dasharray='1.5,2'/></svg>"); }

/* Text links: soft neumorphic chip (ports the mock .text-link, Matt: adopt
   chips, 22 Jun 2026). The chip surface follows its background via
   --mb-link-surface so the two-tone shadow reads: white by default, cream on
   cream bands (.mb-cream) and flat cream format cards, and the card's own
   surface inside the other card families. The arrow is already in the link
   copy, so no ::after. (Bridge v1.6.) */
.mb-band .mb-link { margin: 0; }
.mb-band .mb-link a {
  display: inline-flex; align-items: center; width: fit-content;
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-family-sans); font-size: 0.9375rem; font-weight: 500;
  line-height: 1; color: var(--color-text); text-decoration: none;
  background: var(--mb-link-surface, var(--color-surface));
  border: 1px solid var(--mb-link-surface, var(--color-surface));
  border-radius: var(--radius-sm);
  box-shadow:
    var(--space-2) var(--space-2) var(--space-4) var(--mb-link-shadow-dark, var(--color-border)),
    calc(-1 * var(--space-2)) calc(-1 * var(--space-2)) var(--space-4) var(--mb-link-shadow-light, var(--color-surface));
  transition: box-shadow var(--transition-base), color var(--transition-base), border-color var(--transition-base);
}
.mb-band .mb-link a:hover,
.mb-band .mb-link a:focus-visible { border-color: var(--color-border); color: var(--color-dark); }
.mb-band .mb-link a:active {
  color: var(--color-text-muted);
  box-shadow:
    inset var(--space-1) var(--space-1) var(--space-3) var(--mb-link-shadow-dark, var(--color-border)),
    inset calc(-1 * var(--space-1)) calc(-1 * var(--space-1)) var(--space-3) var(--mb-link-shadow-light, var(--color-surface));
}
/* Surface matching for the chip's neumorphic shadow. */
.mb-cream { background: var(--color-tint-cream); --mb-link-surface: var(--color-tint-cream); --mb-link-shadow-light: var(--color-tint-light-cream); --mb-link-shadow-dark: var(--color-tint-dark-cream); }
.mb-card:has(> .mb-num) { --mb-link-surface: var(--color-surface-page); --mb-link-shadow-light: var(--color-surface); --mb-link-shadow-dark: var(--color-surface-muted); }
.mb-card:has(.mb-frame),
.mb-tour { --mb-link-surface: var(--color-surface); --mb-link-shadow-light: var(--color-surface); --mb-link-shadow-dark: var(--color-border); }
.mb-card:not(:has(> .mb-num)):not(:has(.mb-frame)) { --mb-link-surface: var(--color-tint-cream); --mb-link-shadow-light: var(--color-tint-light-cream); --mb-link-shadow-dark: var(--color-tint-dark-cream); }
.mb-stone-pink { background: var(--color-tint-stone-pink); --mb-link-surface: var(--color-tint-stone-pink); --mb-link-shadow-light: var(--color-tint-light-stone-pink); --mb-link-shadow-dark: var(--color-tint-dark-stone-pink); }
.mb-blush { background: var(--color-tint-blush); --mb-link-surface: var(--color-tint-blush); --mb-link-shadow-light: var(--color-tint-light-blush); --mb-link-shadow-dark: var(--color-tint-dark-blush); }

/* Band wave shape dividers: fluid height (v1.63). 1rem at and below the 620
   mobile point, 2rem at and above the 980 desktop point, interpolated linearly
   between them (the bridge's established 620/980 breakpoints; slope 16px over
   360px = 4.444vw, intercept 16px - 620 x 16/360 = -0.722rem). !important
   because Elementor writes the stored control height as a per-element rule
   (.elementor-element-XXX > .elementor-shape-top svg) that out-specifies a
   single class, same fight as the v1.54 divider colour. The stored Elementor
   value stays 2rem as the no-bridge fallback. Currently only Home Band 3
   carries waves; scoped to .mb-band so any future wave band inherits it. */
.mb-band > .elementor-shape svg { height: clamp(1rem, 4.444vw - 0.722rem, 2rem) !important; }

/* Buttons: the native Elementor button (the build hooks it with .mb-cta)
   renders the dark Celebrimbor .btn--cta everywhere, including the hero:
   dark --cta-bg fill, cream --cta-text, Gaudi arch radius (--btn-arch-depth
   --space-4 --space-4 0), 2px border, FLAT at rest (the lift is on hover
   only). One dark CTA family across the page (Matt 22 Jun: all dark like the
   booking coda; the v1.5 sharp corners were reverted to arch in v1.8, and the
   dark-hero terracotta cta-invert was dropped in v1.9). */
.mb-band .elementor-button {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-family-sans); font-weight: var(--font-weight-500-medium);
  font-size: 0.875rem; line-height: 1; letter-spacing: 0; text-transform: none;
  text-decoration: none; padding: var(--btn-pad-y) var(--btn-pad-x-right) var(--btn-pad-y) var(--btn-pad-x-left);
  background: var(--cta-bg); color: var(--cta-text);
  border-style: solid; border-width: var(--border-width-strong); border-color: var(--cta-border);
  border-radius: var(--btn-arch-depth) var(--space-4) var(--space-4) 0;
  box-shadow: none;
  transition: background .2s ease, border-color .2s ease, color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.mb-band .elementor-button:hover {
  background: var(--cta-hover-bg); border-color: var(--cta-hover-border); color: var(--cta-hover-text);
  box-shadow: var(--shadow-cta-hover); transform: translateY(-1px);
}
.mb-band .elementor-button:active {
  background: var(--cta-active-bg); border-color: var(--cta-active-border); color: var(--cta-active-text);
  box-shadow: none; transform: translateY(0);
}
.mb-band .elementor-button:focus-visible { outline: 3px solid var(--focus-outline); outline-offset: 2px; }
/* Xpro Info Box -> Celebrimbor adapter (v1.103, Matt 11 Jul). The xpro-infobox parts don't
   carry the mb-* hooks, so map them to the house look here for the Tour Highlights. !important
   because Xpro emits id-scoped per-widget rules that otherwise tie/beat these on source order.
   Button mirrors the shared dark CTA token set; badge is a stone-pink pill; subtitle is the
   kicker eyebrow (killing Xpro's gradient text fill); title is the display heading. */
.mb-band .xpro-infobox-subtitle {
  font-family: var(--font-family-sans) !important; font-weight: 600 !important;
  font-size: var(--text-sm) !important; letter-spacing: .08em !important; text-transform: uppercase !important;
  color: var(--color-primary-d1) !important; -webkit-text-fill-color: var(--color-primary-d1) !important;
  background: none !important; margin: 0 0 .5em !important;
}
.mb-band .xpro-infobox-title {
  font-family: var(--font-family-display) !important; font-weight: 300 !important;
  font-size: var(--text-h4) !important; line-height: var(--line-height-h4) !important;
  color: var(--color-dark) !important; margin: 0 0 .5em !important;
}
.mb-band .xpro-infobox-description,
.mb-band .xpro-infobox-description p { color: var(--color-text) !important; }
/* v1.104/1.105: more air — space the media, subtitle/title stack, divider and button apart. */
.mb-band .xpro-infobox-media { display: block !important; width: 100% !important; margin-bottom: 0.5rem !important; }
/* v1.108: image slot = full-width grey "test screen" placeholder until go-live photos; a real
   image fills it via object-fit. Overrides Xpro's tiny 10%/10vh demo media size. Pill untouched. */
.mb-band .xpro-infobox-media-img { width: 100% !important; height: 180px !important; background: #ebebeb !important; border-radius: 8px !important; overflow: hidden !important; }
.mb-band .xpro-infobox-media-img img { width: 100% !important; height: 100% !important; object-fit: cover !important; }
.mb-band .xpro-infobox-separator-simple { margin: 0 0 1rem !important; }
.mb-band .xpro-infobox-btn-wrapper { margin-top: 1.5rem !important; }
.mb-band .xpro-badge {
  font-family: var(--font-family-sans) !important; font-weight: 600 !important;
  font-size: var(--text-xs) !important; letter-spacing: .08em !important; text-transform: uppercase !important;
  color: var(--color-primary-d1) !important; background: var(--color-tint-stone-pink) !important;
  border: 0 !important; padding: .5em 1em !important; border-radius: 999px !important;
}
.mb-band .xpro-infobox-btn {
  font-family: var(--font-family-sans) !important; font-weight: var(--font-weight-500-medium) !important;
  font-size: 0.875rem !important; line-height: 1 !important; letter-spacing: 0 !important; text-transform: none !important;
  padding: var(--btn-pad-y) var(--btn-pad-x-right) var(--btn-pad-y) var(--btn-pad-x-left) !important;
  background: var(--cta-bg) !important; color: var(--cta-text) !important;
  border: var(--border-width-strong) solid var(--cta-border) !important;
  border-radius: var(--btn-arch-depth) var(--space-4) var(--space-4) 0 !important;
  box-shadow: none !important;
}
.mb-band .xpro-infobox-btn:hover {
  background: var(--cta-hover-bg) !important; color: var(--cta-hover-text) !important;
  border-color: var(--cta-hover-border) !important; box-shadow: var(--shadow-cta-hover) !important;
}
/* v1.112: Tour Highlights four-up (Matt 12 Jul). Six across was too cramped; eight info boxes at
   FOUR per row instead (two rows of four, ~280px each at a 1200px content width — a readable
   card). Each box an equal explicit 1/4 width (100% minus the three 24px gaps, /4); flex-wrap so
   the eight flow into two rows. Keeps the word-wrap fix (Xpro breaks the description per character
   when narrow). Desktop only; below 980 the authored 31% widths (3-up) then the mobile stack. */
@media (min-width: 61.3125rem) {
  .mb-band .mb-infobox-row { flex-wrap: wrap !important; }
  .mb-band .mb-infobox-row > .elementor-widget-xpro-infobox {
    flex: 0 0 calc((100% - 3rem) / 4) !important;   /* v1.117: four-up minus the three 1rem gaps */
    width: calc((100% - 3rem) / 4) !important;
    max-width: none !important;
  }
  .mb-band .mb-infobox-row .xpro-infobox-title,
  .mb-band .mb-infobox-row .xpro-infobox-subtitle,
  .mb-band .mb-infobox-row .xpro-infobox-description,
  .mb-band .mb-infobox-row .xpro-infobox-description p {
    overflow-wrap: break-word !important; word-break: normal !important;
  }
}
/* v1.114: turn off the CTA button in the Tour Highlights info boxes (Matt 12 Jul). */
.mb-band .mb-infobox-row .xpro-infobox-btn-wrapper { display: none !important; }
/* v1.115/1.117: row gap between info boxes — 1rem column + row (Matt). The outer boxes still
   hug the container edges because a flex gap sits only BETWEEN items, not on the outer edges. */
.mb-band .mb-infobox-row { column-gap: 1rem !important; row-gap: 1rem !important; }
/* v1.116: Xpro Pro hardcodes padding:3em 4em on the info-box widget WRAPPER
   (.elementor-widget-xpro-infobox) in the plugin CSS — not exposed as a control, and the
   widget's content_box_padding only zeroes the inner .xpro-infobox-content. Zero the wrapper
   so the boxes aren't framed in dead space. */
.mb-band .mb-infobox-row .elementor-widget-xpro-infobox { padding: 0 !important; }
/* The hero CTA uses the same dark .btn--cta as the rest (v1.9, Matt 22 Jun);
   the earlier terracotta cta-invert override on .mb-hero was removed so every
   CTA is one dark family. On the dark hero this reads via the cream text and
   reverses to terracotta on hover; over a real hero photo + scrim it sits
   like a standard dark hero CTA. */

/* ============================================================
   DECORATION LAYER (v1.1 fidelity pass)
   ============================================================ */

/* Hero scrim ------------------------------------------------- */
/* Full-bleed photographic hero: the band carries the background image
   (set on the hero container in Elementor); a dark bottom-up gradient
   guarantees the heading stays legible whatever the photo. Content sits
   bottom-left, above the scrim. */
.mb-hero {
  position: relative;
  /* Hero first-screen size (min-height) now lives on the Elementor container as canon:
     85svh desktop / 80svh mobile, Custom unit, emitted by gen-home-2026-elementor.py.
     Kept off the bridge so the value is visible and editable on the page, not hidden here
     (the old bridge 78svh had silently drifted from the 90svh mock). */
  display: flex;
  align-items: flex-end;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.mb-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
    rgba(18, 18, 18, 0.82) 0%,
    rgba(18, 18, 18, 0.45) 45%,
    rgba(18, 18, 18, 0.12) 78%);
  z-index: 0;
  pointer-events: none;
}
.mb-hero > .e-con-inner { position: relative; z-index: 1; justify-content: flex-end !important; }
    /* C2 (v1.37): hero copy capped by reading measure, not by a fixed
       6-of-12 grid-column calc. 82ch preserves the old desktop feel while
       removing the 980px full-width snap; the block fills naturally when
       the viewport is narrower than the measure. */
    .mb-hero > .e-con-inner > .e-con {
      width: min(100%, 82ch);
      max-width: none;
      margin-right: auto;
    }
/* C1 (v1.7.1): the hero copy lives in .e-con-inner (a full-height column flex);
   justify-content: flex-end bottom-aligns it like the mock, so it sits low and
   clear of the floating header, with the next band peeking. Elementor's own
   `.e-con.e-flex > .e-con-inner { justify-content: var(--justify-content) }`
   (0,3,0, variable unset = normal) out-specifies a plain .mb-hero rule, so this
   needs !important to win. align-items on .mb-hero itself is also Elementor-overridden. */
.mb-hero .mb-eyebrow { color: var(--color-tint-cream) !important; }
.mb-hero h1.elementor-heading-title {
  font-weight: 300;
  font-size: clamp(2.5rem, 6vw, 4.25rem);
  line-height: 1.12;
  letter-spacing: -0.01em;
}
/* Hero title subline (v1.93, ports the mock's .hero-subline). The H1 carries the
   tour name at full size; the .mb-hero-subline span drops to half (0.5em) on its
   own line, so the title reads clearly bigger than the sub (the mock's 2:1). */
.mb-hero h1 .mb-hero-subline { display: block; font-size: 0.5em; font-weight: 300; line-height: 1.2; margin-top: 0.4em; }

/* Cards: three families, kept to the Matt card-emphasis hierarchy -- */
/* tour products heaviest (white tray + soft shadow, see .mb-tour),
   Band 3 picks flat pale panels with a watermark number behind,
   format cards flat cream, story cards white with a light shadow.    */

/* Base card (bridge v1.47): one radius + interior padding for every card family,
   scoped to .mb-band so it beats Elementor's inline per-card padding (0,1,0). The
   family rules below set only surface, border and shadow. Tour rows (.mb-tour) are
   not .mb-card and keep their flush padding:0. */
.mb-band .mb-card { border-radius: var(--radius-sm); padding: var(--space-8); }

/* Band 3 "Start with a Walk" picks: flat pale panel, watermark behind. */
.mb-card:has(> .mb-num) {
  background: var(--color-surface-page);
  border: 0;
  position: relative;
  overflow: hidden;
}
.mb-card:has(> .mb-num) > .mb-num {
  position: absolute;
  inset: 0;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 0;
  pointer-events: none;
}
/* Position the numeral: its centre sits at 40% from the card top (off dead-centre,
   Matt 30 Jun). The widget-container fills the card; the heading title itself is the
   positioned element (its height is the glyph, so translateY(-50%) lands the centre at
   40%). Positioning the container instead failed: Elementor stretches it to full card
   height, so its -50% overshot and the glyph sat near the top. */
.mb-card:has(> .mb-num) > .mb-num > .elementor-widget-container {
  position: absolute;
  inset: 0;
}
.mb-card:has(> .mb-num) > .mb-num .elementor-heading-title {
  position: absolute;
  top: 40%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  text-align: center;
  margin: 0;
}
.mb-card:has(> .mb-num) > .elementor-widget:not(.mb-num) { position: relative; z-index: 1; }
.mb-band .mb-num .elementor-heading-title {
  font-family: var(--font-family-display);
  font-weight: 600;
  font-size: clamp(110px, 12vw, 160px);
  line-height: 1;
  color: var(--color-warning);
  opacity: 0.2;
}

/* Band 13 Story cards: white, hairline border, light shadow (border-only
   tier of the hierarchy). The framed photo sits inside the card padding. */
.mb-card:has(.mb-frame) {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-1);
}

/* Band 4 format cards (Semi-Private / Private / Custom): flat cream panel,
   no border or shadow (the quiet tier beneath the actual tours). */
.mb-card:not(:has(> .mb-num)):not(:has(.mb-frame)) {
  background: var(--color-tint-cream);
  border: 0;
}

/* Tour rows: the premium framed product card (heaviest tier). White tray,
   hairline border, --shadow-soft, photo flush on one side. Keyed to the
   mb-tour class the generator puts on every tour_row. */
.mb-tour {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-soft);
  border-radius: var(--radius-md);
  overflow: hidden;
  gap: 0 !important;
  align-items: stretch;
}
.mb-tour > .e-con:has(.mb-frame) { flex: 5 1 0; }
.mb-tour > .e-con:not(:has(.mb-frame)) {
  flex: 7 1 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(24px, 3vw, 40px);
}
.mb-tour .mb-frame {
  height: 100%;
  min-height: 300px;
  border-radius: 0;
  background: var(--color-border);
}
@media (max-width: 768px) {
  .mb-tour { flex-direction: column; }
  .mb-tour > .e-con:has(.mb-frame),
  .mb-tour > .e-con:not(:has(.mb-frame)) { flex: 1 1 100%; }
  /* v1.73: the photo leads every tour card on mobile, whatever the DOM order */
  .mb-tour > .e-con:has(.mb-frame) { order: -1; }
  .mb-tour .mb-frame { min-height: 220px; }
  /* v1.73: a definite photo box so object-fit cover fills it, no band gap */
  .mb-tour .mb-frame.has-photo { aspect-ratio: 3 / 2; min-height: 0; }
}

/* Tour-row photo frames (v1.72): a framed tour photo takes .has-photo like the
   gallery cells, so the placeholder skin drops and the Image widget fills the
   frame edge to edge with object-fit cover (a real <img> for SEO). Mirrors the
   .mb-gallery > .has-photo rule, scoped to .mb-tour. */
.mb-tour .mb-frame.has-photo { background: none; padding: 0; }
.mb-tour .mb-frame.has-photo .elementor-widget-image,
.mb-tour .mb-frame.has-photo .elementor-widget-image .elementor-widget-container { width: 100% !important; max-width: none !important; height: 100%; }
.mb-tour .mb-frame.has-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Framed photo slots ---------------------------------------- */
/* Filled, framed aspect boxes (gallery, founder portraits, the reviews
   slot). Replaces the dashed placeholder; once real images land they fill
   these boxes. Tour-row frames override the radius above to sit flush. */
.mb-frame {
  background: var(--color-surface-muted);
  border: 0;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.mb-frame .elementor-heading-title {
  font-family: var(--font-family-sans);
  font-weight: 500;
  font-size: var(--text-sm);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* FAQ (native details/summary) ------------------------------- */
.mb-band .mb-faq { border-bottom: 1px solid var(--color-border); padding: 12px 0; }
.mb-band .mb-faq > summary { font-family: var(--font-family-sans); font-weight: 600;
  color: var(--color-dark); cursor: pointer; font-size: var(--text-base); list-style: none; }
.mb-band .mb-faq > summary::-webkit-details-marker { display: none; }
.mb-band .mb-faq > p { margin: .6em 0 0; }

/* FAQ as the Elementor Toggle widget (.mb-faq-toggle) ----------
   v1.71: ports the mock v2.63 accordion canon. Each item is a white
   card (page surface, 1px border, 24px side padding, 14px gaps) with
   a right-aligned + / minus marker on the title, muted ink warming to
   terracotta (--color-primary) on hover and focus, minus when open.
   Elementor's own icon stays hidden; the marker is a ::after so it
   survives the widget's icon settings. Token map from the mock:
   --color-page -> --color-surface-page, --color-terracotta ->
   --color-primary. Toggle opens each item independently, like the
   old native <details>. Editable in the UI and V4-migration friendly. */
.mb-band .mb-faq-toggle .elementor-toggle-item {
  background: var(--color-surface-page);
  border: 1px solid var(--color-border);
  margin-top: 14px;
  padding: 0 24px;
}
.mb-band .mb-faq-toggle .elementor-toggle-item:first-of-type { margin-top: 0; }
.mb-band .mb-faq-toggle .elementor-tab-title {
  border: 0;
  background: transparent;
  padding: 18px 0;
  font-family: var(--font-family-sans);
  font-weight: 600;
  font-size: var(--text-base);
  line-height: 1.4;
  color: var(--color-dark);
  cursor: pointer;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}
.mb-band .mb-faq-toggle .elementor-tab-title .elementor-toggle-title {
  font-family: inherit;
  font-weight: inherit;
  font-size: inherit;
  color: inherit;
  text-decoration: none;
}
/* v1.77: kill the underline on the toggle titles. The site's global <a> rule draws its
   underline with a background-image (two linear-gradients), NOT text-decoration, and sets
   text-decoration:none itself, so the v1.76 text-decoration:none did nothing. Reset the
   background-image and the underline padding on the toggle title link, all states, the way
   the master's .link--unstyled / image-link modifiers do. */
.mb-band .mb-faq-toggle .elementor-tab-title a,
.mb-band .mb-faq-toggle .elementor-tab-title .elementor-toggle-title,
.mb-band .mb-faq-toggle .elementor-tab-title a:hover,
.mb-band .mb-faq-toggle .elementor-tab-title a:focus,
.mb-band .mb-faq-toggle .elementor-tab-title a:active {
  background-image: none;
  padding-bottom: 0;
  text-decoration: none;
}
.mb-band .mb-faq-toggle .elementor-tab-title::after {  /* custom open and close marker */
  content: "+";
  flex: none;
  width: 1em;
  text-align: center;
  font-weight: 300;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--color-text-muted);
}
.mb-band .mb-faq-toggle .elementor-tab-title:hover::after,
.mb-band .mb-faq-toggle .elementor-tab-title:focus-visible::after { color: var(--color-primary); }
.mb-band .mb-faq-toggle .elementor-tab-title.elementor-active::after { content: "\2212"; }  /* minus sign when open */
.mb-band .mb-faq-toggle .elementor-tab-title:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 3px; }
.mb-band .mb-faq-toggle .elementor-toggle-icon { display: none; }
.mb-band .mb-faq-toggle .elementor-tab-content {
  border: 0;
  background: transparent;
  padding: 0 0 20px;
  max-width: 600px;
}
.mb-band .mb-faq-toggle .elementor-tab-content > p { margin: .6em 0 0; }

/* ============================================================
   SITE-WIDE ELEMENTOR WIDGET NORMALISATIONS (bridge v1.3)
   Not mb-* scoped: these adapt third-party Elementor widgets used
   across both 1.0 and 2.0 pages to Celebrimbor. They live in the
   bridge (the WordPress/Elementor adapter), not the portable master.
   ============================================================ */

/* Header overlap (CF-71 reversal, 26 Jun 2026, Matt). The Xpro header
   floats over the page content instead of taking its own band. Global,
   every page (Matt's call 26 Jun over the scoped-to-hero recommendation;
   non-hero pages have no top compensation, so their first section sits
   under the bar). Reverses the 25 Jun CF-71 in-flow decision recorded on
   .site-header-wrap--sticky in the master.
     - position:fixed (v1.88) keeps the bar in view on scroll, out of flow so page content
       rises under it. Was absolute until v1.88; Xpro's own sticky JS never bound
       (it needs .xtb-header-sticky in the markup, absent here), so the bar owns
       its sticky. Fixed on the header creates no containing block for the mobile
       off-canvas fixed panel (only transform/filter do), so the menu is unaffected.
     - NO filter / transform / backdrop-filter on the wrapper or any
       ancestor: a filtered ancestor becomes the containing block for the
       Xpro mobile off-canvas menu (position:fixed) and clamps it into the
       header box. The glass stays on .mybcn-header-glass::before with
       isolation:isolate (master), untouched here.
     - z-index:100 matches the master float layer (below tooltip 1000,
       above page content).
     - top gap (v1.87, Matt 6 Jul): the bar floats detached from the very top
       by --mb-header-gap at all times (Matt: "always, floating header"). */
:root { --mb-header-gap: clamp(0.25rem, 0.16rem + 0.38vw, 0.5rem); }
header.xpro-theme-builder-header {
  position: fixed;
  top: var(--mb-header-gap);
  left: 0;
  right: 0;
  width: 100%;
  z-index: 100;
}

/* Non-hero top compensation (v1.39, item 137). The absolute header above takes
   no layout space, which is correct only when a page opens on a full-bleed
   .mb-hero (the hero sits under the glass, scrim keeps text legible). A 2.0 page
   whose first band is NOT a hero would tuck that band under the ~91px bar, so pad
   the body top on non-hero pages and remove it again whenever a hero is present.
   Mirrors the Vercel staging guard (body / body:has(.hero)). The header runs
   76 to 93px on desktop (96px clears it) and measures a flat 76px at <=620px
   (chrome-devtools, dev /about/approach/, 620/600/500 all 76px, 28 Jun), so the
   phone pad is 80px (76 + 4 to clear cleanly). Dev-only: legacy pages are being
   retired, so a blanket body rule is acceptable (Matt 28 Jun). */
body:not(:has(.mb-hero)) { padding-top: 96px; }
@media (max-width: 38.75rem) { body:not(:has(.mb-hero)) { padding-top: 80px; } }

/* Floating + sticky header skin (v1.87, Matt 6 Jul 2026). Xpro's native Header
   Sticky (template 5794, container 5d47ca2 > Advanced > Header Sticky) is on.
   Xpro clones the bar into .xpro-theme-builder-header-nav (position:fixed; top:0),
   fades it in with .xtb-appear on scroll, and hides the original 5d47ca2
   (display:none) while the clone shows. Both instances share the inner container
   b9cf336, so one background rule skins the static bar AND the clone.
     - Gap: the fixed clone is pulled down to --mb-header-gap to match the static
       floating bar (Xpro sets top:0). The .admin-bar variant keeps the 32px WP
       bar underneath (Xpro's own .admin-bar rule sets top:32px; we add the gap).
     - Background: the bar's current surface (#f5f5f5 = --color-surface-page) at
       80% at rest, 100% on hover (Matt). color-mix keeps it token-bound. Beats
       the Xpro widget's per-element solid fill (equal specificity, loads after)
       with !important, mirroring the master's .elementor-5794 header selector.
     - Slim on scroll only: the stuck clone trims b9cf336 vertical padding
       16px -> --space-2 (8px), ~16px shorter, so the bar reads slimmer once it
       sticks (Matt). The static top bar keeps full height.
     - Clearances unchanged: the bar stays out of flow, so the hero inner 96px and
       the non-hero body 96/80px still clear the slightly-lower bar (gap max ~8px;
       76+8 < 96 desktop, 59+4 < 80 phone). Verified live. */
.xtb-header-sticky.xtb-appear .xpro-theme-builder-header-nav { top: var(--mb-header-gap); }
.admin-bar .xtb-appear .xpro-theme-builder-header-nav { top: calc(32px + var(--mb-header-gap)); }

.elementor-5794 .elementor-element.elementor-element-b9cf336 {
  background-color: color-mix(in srgb, var(--color-surface-page) 80%, transparent) !important;
  transition: background-color .2s ease, padding-block .2s ease;
}
.elementor-5794 .elementor-element.elementor-element-b9cf336:hover {
  background-color: var(--color-surface-page) !important;
}

/* Slim-on-scroll (v1.89, Matt 6 Jul). Xpro's native sticky enable is not reachable
   (the container Header Sticky switches are styling-only here, and Elementor Pro
   custom code is unavailable), so a ~7-line script appended to the wordmark HTML
   widget (8079d731) toggles .mb-scrolled on <html> after ~40px of scroll. Two-state
   on the always-fixed bar: full height at the top, slimmer once scrolled. Trims the
   shared inner b9cf336 vertical padding 16 -> --space-2 (8px). */
.mb-scrolled .elementor-5794 .elementor-element.elementor-element-b9cf336 {
  padding-block: var(--space-2) !important;
}

/* Hamburger toggler transparent (v1.90, Matt 6 Jul). The Xpro menu toggler button
   (off-canvas <=1024) carried a solid #f5f5f5 fill that read as a box on the 80%
   translucent bar; blend it with the bar (base + hover + focus). */
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-menu-toggler,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-menu-toggler:hover,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-menu-toggler:focus {
  background-color: transparent !important;
}

.xtb-header-sticky.xtb-appear .xpro-theme-builder-header-nav .elementor-element.elementor-element-b9cf336 {
  padding-block: var(--space-2) !important;
}

/* Xpro horizontal menu: keep an open sub-menu above later nav items, at every
   level. Xpro sets EVERY .menu-item-has-children <li> (top level and nested) to
   position:relative; z-index:1, making each its own stacking context. The
   sub-menu (position:absolute; z-index:99) ranks only inside its parent <li>, so
   later sibling <li>s (also z-index:1, later in the DOM) paint over it and the
   sub-menu hides behind the following items. Clearing each parent's z-index lets
   the sub-menu's own z-index float it above the siblings; the hover/focus lift
   is belt-and-braces for the whole open item.
   v1.23 (27 Jun 2026, Matt): generalised from the direct-child combinator
   (> li, top level only) to a descendant selector, so nested families (e.g.
   Tours > Walking Tours > the tour list) work too. Confirmed live on dev that
   depth-1 lis (Walking Tours, Private Tours, Sagrada Família, Things to Do, Day
   Trips) still computed z-index:1 with the v1.17 top-level-only fix, trapping
   their level-3 flyouts behind later siblings. Header Menu (WP menu id 2) is a
   real 3-level menu; About stays 2-level and is unaffected.
   Restores the fix removed with the inline <style> widget 38170590 (header
   5794), 26 Jun 2026. In the off-canvas mode (<=1024px) the sub-menu is
   position:relative (accordion), so z-index is moot and this is harmless. */
.elementor-widget-xpro-horizontal-menu .xpro-elementor-horizontal-navbar-nav li.menu-item-has-children {
  z-index: auto;
}
.elementor-widget-xpro-horizontal-menu .xpro-elementor-horizontal-navbar-nav li.menu-item-has-children:hover,
.elementor-widget-xpro-horizontal-menu .xpro-elementor-horizontal-navbar-nav li.menu-item-has-children:focus-within {
  z-index: 101;
}

/* Xpro off-canvas sub-menu (<=1024px): keep the nested lists flat (no fly-out
   shadow) so the open drawer reads as one surface.
   NOTE: the v1.26 position:static patch is RETIRED in v1.30 (27 Jun 2026). Live
   verification (Chrome DevTools at 500px) showed the level-3 overlay was NOT
   Xpro's doing: Xpro's own responsive rule correctly sets the off-canvas dropdown
   to position:relative (accordion). The absolute overlay came from OUR master
   dropdown block (.elementor-5794 ... .xpro-elementor-dropdown-menu), which had no
   media guard; it is now scoped to min-width:1025px (master v3.97), so Xpro's
   native relative accordion applies on mobile without any position override here. */
@media (max-width: 1024px) {
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu {
    box-shadow: none !important;
  }
}

/* Xpro off-canvas (<=1024px) menu cosmetics (Matt, 27 Jun 2026). Four asks on
   the mobile menu: (1) one uniform row background, no per-row or per-state
   highlight, so the open submenu reads as a single flat block; (2) the bold top
   level stays bold, and an active or hovered sub-level link also goes bold;
   (3) the hover / active font colour moves off the mid blue (--color-focus,
   #6188b0) to the darker blue (--color-focus-d1, #396188); (4) each nested level
   is indented 1rem to show the hierarchy. The desktop hover menu (>1024px) was
   left as it was in v1.27, then matched in v1.36. */
@media (max-width: 1024px) {
  /* (1) Uniform background: never paint a different highlight behind a row, at
     any state or level. The sub-list keeps its own single background. */
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu a,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu a:hover,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu a:focus,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu a.active,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu li:hover > a,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu .current-menu-item > a {
    background: transparent !important;
  }
  /* (1b) The sub-menu list itself transparent too (v1.29, Matt 27 Jun 2026), so
     the open submenu shows the white off-canvas panel behind it instead of its
     own grey block (--color-page #f5f5f5). The whole drawer then reads as one
     flat white surface. */
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu {
    background: transparent !important;
  }
  /* (2) + (3) Sub-level link hover / active / current page: darker blue, bold.
     The top level is already bold and is left dark. */
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu a:hover,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu a:focus,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu a.active,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu .current-menu-item > a {
    color: var(--color-focus-d1, #396188) !important;
    font-weight: 600 !important;
  }
  /* (4) Indent each nested level by 1rem (compounds through the nested lists). */
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu {
    padding-inline-start: 1rem !important;
  }
  /* Close button (X) back to the brand red, matching the wordmark accent
     (--color-primary, #b06161). */
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-horizontal-menu-close,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-horizontal-menu-close i {
    color: var(--color-primary, #b06161) !important;
  }
}

/* Xpro desktop hover menu (>1024px): mirror the mobile sub-level
   hover/current treatment without changing the top-level header items. */
@media (min-width: 1025px) {
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu a:hover,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu a:focus,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu a.active,
  .elementor-widget-xpro-horizontal-menu .xpro-elementor-dropdown-menu .current-menu-item > a {
    color: var(--color-focus-d1, #396188) !important;
    font-weight: 600 !important;
  }
}

/* EAC breadcrumbs: suppress the link underline and the two-layer
   underline background so the widget matches the Celebrimbor breadcrumb;
   muted ink on hover. Was a Customizer snippet, folded in 22 Jun 2026. */
.elementor-widget-eac-addon-breadcrumbs a,
.elementor-widget-eac-addon-breadcrumbs a:link,
.elementor-widget-eac-addon-breadcrumbs a:visited {
  text-decoration: none !important;
  background-image: none !important;
}
.elementor-widget-eac-addon-breadcrumbs a:hover,
.elementor-widget-eac-addon-breadcrumbs a:focus {
  text-decoration: none !important;
  color: var(--color-text-muted) !important;
}

/* ============================================================
   Footer (myBCN 2.0 dark chrome). Layout (flex direction, wrap,
   widths, responsive collapse) lives in the Xpro footer template
   2704 Elementor container settings; this block is the skin only.
   Text colours are re-asserted above the site-wide
   .mb-band .elementor-widget-text-editor rule (0,2,0).
   ============================================================ */
.mb-footer {
  --mb-footer-fg:     var(--color-surface-muted);
  --mb-footer-muted:  var(--color-text-disabled);
  --mb-footer-title:  var(--color-warning);
  --mb-footer-accent: var(--color-primary);
  --mb-footer-rule:   var(--color-text);
  background: var(--section-dark-bg);
  color: var(--mb-footer-fg);
}
.mb-footer-cols  { gap: var(--space-12) clamp(var(--space-8), 4vw, var(--space-24)); }
.mb-footer-brand { gap: var(--space-6); }
.mb-footer-links { gap: var(--space-8) clamp(var(--space-6), 3vw, var(--space-12)); }
.mb-footer-legal {
  gap: var(--space-3) var(--space-8);
  margin-top: var(--space-12);
  padding-top: var(--space-6);
  border-top: 1px solid var(--mb-footer-rule);
  font-size: 0.8125rem;
}
.mb-footer .elementor-widget-text-editor { color: var(--mb-footer-fg); }
.mb-footer .mb-footer-tagline { color: var(--mb-footer-muted); font-size: 0.9375rem; line-height: 1.33; }
.mb-footer .mb-footer-col-title {
  color: var(--mb-footer-title);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  margin-bottom: var(--space-4);
}
.mb-footer .mb-footer-legal-meta,
.mb-footer .mb-footer-legal-links { color: var(--mb-footer-muted); }
.mb-footer-wordmark-link {
  font-family: var(--font-family-wordmark);
  font-weight: 600;
  font-size: 1.1875rem;
  line-height: 1.05;
  letter-spacing: 0.04em;
  color: var(--mb-footer-fg);
  text-decoration: none;
}
.mb-footer-wordmark-link b { display: block; font-weight: 600; color: var(--mb-footer-accent); }
.mb-footer-col ul { list-style: none; margin: 0; padding: 0; }
.mb-footer-col li { margin-bottom: var(--space-3); }
.mb-footer-col li:last-child { margin-bottom: 0; }
.mb-footer .mb-footer-col a { color: var(--mb-footer-fg); font-size: 0.9375rem; text-decoration: none; }
.mb-footer .mb-footer-col a:hover,
.mb-footer .mb-footer-col a:focus-visible { text-decoration: underline; text-underline-offset: 4px; }
.mb-footer-legal p { margin: 0; }
.mb-footer .mb-footer-legal a { color: var(--mb-footer-muted); font-size: 0.8125rem; text-decoration: none; }
.mb-footer .mb-footer-legal a:hover,
.mb-footer .mb-footer-legal a:focus-visible { text-decoration: underline; text-underline-offset: 4px; }

/* Suppress the Celebrimbor two-layer background-image link underline on the dark
   footer (it renders as an off-palette Montjuic-blue rule at rest); the hover
   state uses a plain text underline instead. */
.mb-footer .mb-footer-col a,
.mb-footer .mb-footer-legal a,
.mb-footer .mb-footer-wordmark-link { background-image: none; }

/* ------------------------------------------------------------
   Post body reading measure (bridge v1.75)
   The Xpro Post Content widget (blog / Stories single-post template)
   emits raw post HTML full-width. Cap the flow text to the Celebrimbor
   reading measure and centre it; full-width blocks such as
   .mybcn-quote-band are left to breathe. Choice A, Matt 5 Jul 2026.
   ------------------------------------------------------------ */
.elementor-widget-xpro-post-content .xpro-elementor-content > p,
.elementor-widget-xpro-post-content .xpro-elementor-content > h2,
.elementor-widget-xpro-post-content .xpro-elementor-content > h3,
.elementor-widget-xpro-post-content .xpro-elementor-content > h4,
.elementor-widget-xpro-post-content .xpro-elementor-content > ul,
.elementor-widget-xpro-post-content .xpro-elementor-content > ol,
.elementor-widget-xpro-post-content .xpro-elementor-content > blockquote,
.elementor-widget-xpro-post-content .xpro-elementor-content > figure {
  max-width: var(--prose-width);
  margin-inline: auto;
}

/* Post body full-bleed bands (bridge v1.79, Matt 5 Jul 2026). The authored
   .mybcn-quote-band / .mybcn-coda-band wrappers in the Xpro Post Content
   break out of the boxed reading column to the viewport edges; their inner
   blocks cap to --prose-width and centre. Scoped to the post-content widget
   so bare Celebrimbor band atoms on other pages keep their in-flow width. */
.elementor-widget-xpro-post-content .mybcn-quote-band,
.elementor-widget-xpro-post-content .mybcn-coda-band {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
}
.elementor-widget-xpro-post-content .mybcn-quote-band > *,
.elementor-widget-xpro-post-content .mybcn-coda-band > * {
  max-width: var(--prose-width);
  margin-inline: auto;
}

/* Eyebrow atom on a native Heading widget (v1.81). The .eyebrow class on a
   heading widget lands on the wrapper, so the Celebrimbor eyebrow shape never
   reaches the .elementor-heading-title. Map it here (caps, 0.35em tracking,
   0.75rem, weight 500); colour inherits, so it reads light on the mb-dark hero.
   Mirrors the mock .eyebrow. Stories hero 9426. */
.elementor-widget-heading.eyebrow .elementor-heading-title {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.35em;
  text-transform: uppercase;
}

/* ============================================================
   XPRO POST CAROUSEL - canon (nav, dots, link reset)   v1.82
   Site-wide: applies to every Xpro Post Carousel widget.
   Owl Carousel markup. Overrides per-widget Owl nav/dots
   settings via specificity + !important (bridge convention).
   ============================================================ */

/* Links in the carousel (post title, read-more, category):
   drop the global two-layer underline; hover colour still
   applies via Xpro's own title/button hover colour. */
.elementor-widget-xpro-post-carousel a {
  background-image: none;
  padding-bottom: 0;
}

/* Positioning context for the overlaid arrows. */
.elementor-widget-xpro-post-carousel .xpro-post-grid-main { position: relative; }
.elementor-widget-xpro-post-carousel .owl-nav { margin: 0; }
.elementor-widget-xpro-post-carousel .owl-stage-outer { padding: 10px 0 40px; }

/* Nav arrows - overlaid on the card sides. */
.elementor-widget-xpro-post-carousel .owl-nav button.owl-prev,
.elementor-widget-xpro-post-carousel .owl-nav button.owl-next {
  position: absolute;
  top: 50% !important;
  transform: translateY(-50%);
  margin: 0 !important;
  width: 44px !important;
  height: 44px !important;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: var(--color-surface) !important;
  color: var(--color-dark) !important;
  border: 1px solid var(--color-border) !important;
  border-radius: 999px !important;
  box-shadow: var(--shadow-1);
  transition: background-color var(--transition-base), color var(--transition-base), border-color var(--transition-base);
  z-index: 3;
}
.elementor-widget-xpro-post-carousel .owl-nav button.owl-prev { left: -18px !important; right: auto !important; }
.elementor-widget-xpro-post-carousel .owl-nav button.owl-next { right: -18px !important; left: auto !important; }
.elementor-widget-xpro-post-carousel .owl-nav button.owl-prev::before,
.elementor-widget-xpro-post-carousel .owl-nav button.owl-next::before { font-size: 16px; line-height: 1; }
.elementor-widget-xpro-post-carousel .owl-nav button.owl-prev:hover,
.elementor-widget-xpro-post-carousel .owl-nav button.owl-next:hover {
  background-color: var(--color-primary-d1) !important;
  border-color: var(--color-primary-d1) !important;
  color: #fff !important;
}
.elementor-widget-xpro-post-carousel .owl-nav button.owl-prev:focus-visible,
.elementor-widget-xpro-post-carousel .owl-nav button.owl-next:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

/* Dots - grey inactive, terracotta active, no box. */
.elementor-widget-xpro-post-carousel .owl-dots { margin-top: var(--space-4); text-align: center; line-height: 1; }
.elementor-widget-xpro-post-carousel .owl-dots button.owl-dot {
  width: 10px !important;
  height: 10px !important;
  margin: 0 6px !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 999px !important;
  background-color: var(--color-border) !important;
  box-shadow: none !important;
  transition: background-color var(--transition-base), transform var(--transition-base);
}
.elementor-widget-xpro-post-carousel .owl-dots button.owl-dot span { display: none !important; }
.elementor-widget-xpro-post-carousel .owl-dots button.owl-dot.active {
  background-color: var(--color-primary) !important;
  width: 20px !important; height: 20px !important;
}

/* Related-tour tag row - the tour term(s) injected into each carousel card's
   meta list by the tour-tag snippet, shown as Celebrimbor .chip--taxonomy tags
   (bumped from the 7px POI size to card-legible, laid out as a wrapping row). */
.elementor-widget-xpro-post-carousel .xpro-post-grid-meta-list {
  list-style: none;
  margin: 0 0 var(--space-2);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.elementor-widget-xpro-post-carousel .xpro-post-grid-meta-list .chip--taxonomy {
  font-size: var(--text-sm);
  line-height: 1.3;
}

/* Read-more ("Read the story ->") styled as the Band 4 .mb-link soft-chip.
   Xpro has no shadow control for the read-more, but the bridge applies the
   neumorphic shade directly. Carousel cards are white, so the white-card
   surface values are used (surface bg, border = dark shadow, surface = light). */
.elementor-widget-xpro-post-carousel a.xpro-post-grid-btn {
  display: inline-flex !important;
  align-items: center;
  width: fit-content;
  padding: var(--space-3) var(--space-4) !important;
  font-family: var(--font-family-sans);
  font-size: 0.9375rem !important;
  font-weight: 500 !important;
  line-height: 1;
  color: var(--color-text) !important;
  text-decoration: none;
  background: var(--color-surface) !important;
  border: 1px solid var(--color-surface) !important;
  border-radius: var(--radius-sm) !important;
  box-shadow:
    var(--space-2) var(--space-2) var(--space-4) var(--color-border),
    calc(-1 * var(--space-2)) calc(-1 * var(--space-2)) var(--space-4) var(--color-surface) !important;
  transition: box-shadow var(--transition-base), color var(--transition-base), border-color var(--transition-base);
}
.elementor-widget-xpro-post-carousel a.xpro-post-grid-btn:hover,
.elementor-widget-xpro-post-carousel a.xpro-post-grid-btn:focus-visible {
  border-color: var(--color-border) !important;
  color: var(--color-dark) !important;
}
.elementor-widget-xpro-post-carousel a.xpro-post-grid-btn:active {
  color: var(--color-text-muted) !important;
  box-shadow:
    inset var(--space-1) var(--space-1) var(--space-3) var(--color-border),
    inset calc(-1 * var(--space-1)) calc(-1 * var(--space-1)) var(--space-3) var(--color-surface) !important;
}
