/* ============================================================
   myBCN Celebrimbor CSS
   Version:   3.111
   Date:      2026-07-09
   Authority: L3 Execution
   Part of:   design/DESIGN.md

   Design philosophy
   -----------------
   Inspired by Antoni Gaudí: every value is intentional and
   mathematically related. 16px (1rem) is the base unit. All
   sizes, spacing, and radii are expressed as rem — multiples
   or fractions of 16. One ratio governs the entire type
   system: Perfect Fourth (×1.333) ascending for headings,
   ÷1.333 descending for body text.

   Surfaces in scope
   -----------------
   WordPress (mybcn.es) — Elementor v4 + Skelementor plugin
   Instagram            — tokens shared where possible
   Email and print are out of scope for v1.

   Active design loop
   ------------------
   Reusable WordPress design decisions move through three surfaces:
   1. Xpro Widget Pattern Lab on dev.mybcn.es, page ID 9119.
   2. This CelebrimborCSS master file.
   3. Laurelin, the local CelebrimborCSS design preview.

   Keep all three current as decisions are made so another LLM or
   human editor can continue from the same source of truth.

   Colour authority
   ----------------
   Colours derive from the POI taxonomy in:
   mybcn-cafo-poi-taxonomy-site-types-visual-encoding.md
   Do not change colour tokens without updating that document.

   Inspiration sources
   -------------------
   The Open Design library (open-design/design-systems and
   open-design/design-templates: 150 brand token sets plus 109
   templates, Apache-2.0) is a reference shelf only. It is never
   poured into this file. Its tokens use a different namespace
   (--bg, --accent, --fg) and must not be treated as Celebrimbor
   tokens. To borrow from one system, use the design-inspiration
   trial workflow and record the decision. See the Inspiration
   Sources section in design/DESIGN.md.

   Replaces
   --------
   mybcn-design-system-button-system.css  (deprecated v1.2)
   mybcn-design-system-form-system.css    (deprecated v1.2)

   Contents (section banners, in file order)
   -----------------------------------------
   TOKENS; Typography container-query enhancement; BASE (body
   defaults); LINKS; TYPOGRAPHY (headings + utilities); BUTTONS;
   FORMS; CHECKBOXES; RADIO BUTTONS; TOGGLE SWITCH; INPUT GROUP;
   TOOL CARD; TOOLTIP; CHIPS; CALLOUTS (panel notes and alerts);
   BLOCKQUOTE; SITE HEADER; WORDPRESS NATIVE HEADER (Xpro template
   5794); CANONICAL 2.0 SITE HEADER (.site-header); CARD BEZEL;
   BENTO GRID; XPRO PATTERN LAB (hero quote + steps); HOME 2026
   PROMOTED UTILITIES; HOME 2026 PROMOTED COMPONENTS; MIRDAIN
   INTERIOR-PAGE DEVICES.
   Grep the uppercase banner name to jump to a section. Update this
   list when adding or renaming a section banner.

   Change log
   ----------
   Full version history: mybcn-design-system-changelog.md (same
   folder). Moved out of this head on 04 Jul 2026 (v3.107) so the
   served CSS stays lean. Add new entries there, newest first; the
   health check scans that file for duplicate version numbers.
   ============================================================ */


/* ============================================================
   TOKENS
   ============================================================ */

:root {

  /* ----------------------------------------------------------
     Palette — neutral surfaces
     Light-end sub-scale: step 10 (B-step ÷ 4) from #d7d7d7 to #ffffff
     215 → 225 → 235 → 245 → 255
     ---------------------------------------------------------- */
  --color-dark:          #121212;        /* neutral scale step 1: value 18 */
  --color-surface:       #ffffff;        /* neutral scale step 7: value 255 — raised cards, inputs */
  --color-surface-page:  #f5f5f5;        /* light sub-scale step 4: value 245 — page background */
  --color-surface-muted: #ebebeb;        /* light sub-scale step 3: value 235 — buttons, muted panels */
  --color-border-subtle: #e1e1e1;        /* light sub-scale step 2: value 225 — inner dividers, table stripes */
  --color-border:        #d7d7d7;        /* light sub-scale step 1: value 215 — borders, separators */

  /* ----------------------------------------------------------
     Palette — text
     ---------------------------------------------------------- */
  --color-text:          #393939;   /* neutral scale step 2: value 57 — decoupled from dark */
  --color-text-muted:    #616161;
  --color-text-subtle:   #616161;   /* was #888888 (3.55:1, WCAG fail) — raised to #616161 (6.18:1, AA) */
  --color-text-disabled: #b0b0b0;

  /* ----------------------------------------------------------
     Palette — semantic (POI taxonomy + UI states)
     Heritage Landmark   → primary          wheel pos  1: rgb(176,97,97)
     Entertainment Venue → focus, hover     wheel pos  8: rgb(97,136,176)
     Natural Feature     → success, CTA     wheel pos  5: rgb(97,176,97)
     Lodging             → warning, active  wheel pos  2: rgb(176,136,97)
     Settlement          → neutral          scale step 4: rgb(136,136,136)
     Error state         → error            primary-d1:   rgb(136,57,57)
     ---------------------------------------------------------- */
  --color-primary:  #b06161;   /* wheel pos  1 */
  --color-focus:    #6188b0;   /* wheel pos  8 — BACKGROUND USE ONLY — fails WCAG AA for text (~3.4:1); use --color-focus-d1 for text */
  --color-success:  #61b061;   /* wheel pos  5 — BACKGROUND USE ONLY — fails WCAG AA for text (~2.5:1); use --color-success-d1 for text */
  --color-warning:  #b08861;   /* wheel pos  2 — BACKGROUND USE ONLY — fails WCAG AA for text (~3.0:1); use --color-warning-d1 for text */
  --color-error:    #883939;   /* primary-d1 — semantic base; 5.9:1 ✓ AA on white */
  --color-neutral:  #888888;   /* neutral scale step 4 */

  /* ----------------------------------------------------------
     External platform brand colours (OTA / review sources)
     Off-wheel third-party brand hexes for labelling booking
     channels and review sources by platform. NOT part of the
     Celebrimbor colour harmony: use sparingly (a name span, a
     chip, a hover accent), never as a page/UI surface. Most fail
     WCAG AA as small body text, so pair with a bold weight or a
     larger size, not fine grey-level text. These mirror Bree's
     OTA_COLOURS map (dev/scripts/mybcn/bree/Notifications.js);
     Bree cannot consume CSS vars, so keep the two in sync by hand.
     ---------------------------------------------------------- */
  --brand-airbnb:  #FF5A5F;              /* Airbnb coral */
  --brand-gyg:     #FF5533;              /* GetYourGuide orange-red */
  --brand-viator:  #1DB0A6;              /* Viator / TripAdvisor teal */
  --brand-google:  #4285F4;              /* Google blue */
  --brand-turitop: var(--color-primary); /* TuriTop / direct = myBCN's own terracotta #b06161 (on-wheel, unlike the off-wheel OTAs above) */

  /* ----------------------------------------------------------
     Chromatic reference — 12-position colour wheel
     Source: rgb(176,97,97). Components {97,136,176} rotated
     through R,G,B channels at 30° hue intervals (Z₁₂).
     Each channel steps independently on the neutral scale.
     Suffix: -d2 (darkest) · -d1 · base · -l1 · -l2 (lightest).
     Total closure: all 60 tint/shade values use only the 7
     neutral-scale channel values {18,57,97,136,176,215,255}.
     Named positions use their semantic alias.
     Unnamed positions use --color-pN convention.
     ---------------------------------------------------------- */

  /* Pos  1 — primary · Heritage Landmark · rgb(176,97,97) */
  --color-primary-d2: #611212;
  --color-primary-d1: #883939;
  /* --color-primary:  #b06161; — semantic token above */
  --color-primary-l1: #d78888;
  --color-primary-l2: #ffb0b0;

  /* Pos  2 — warning · Lodging · rgb(176,136,97) */
  --color-warning-d2: #613912;
  --color-warning-d1: #886139;
  /* --color-warning:  #b08861; — semantic token above */
  --color-warning-l1: #d7b088;
  --color-warning-l2: #ffd7b0;

  /* Pos  3 · rgb(176,176,97) */
  --color-p3-d2: #616112;
  --color-p3-d1: #888839;
  --color-p3:    #b0b061;
  --color-p3-l1: #d7d788;
  --color-p3-l2: #ffffb0;

  /* Pos  4 · rgb(136,176,97) */
  --color-p4-d2: #396112;
  --color-p4-d1: #618839;
  --color-p4:    #88b061;
  --color-p4-l1: #b0d788;
  --color-p4-l2: #d7ffb0;

  /* Pos  5 — success · Natural Feature · rgb(97,176,97) */
  --color-success-d2: #126112;
  --color-success-d1: #398839;
  /* --color-success:  #61b061; — semantic token above */
  --color-success-l1: #88d788;
  --color-success-l2: #b0ffb0;

  /* Pos  6 · rgb(97,176,136) */
  --color-p6-d2: #126139;
  --color-p6-d1: #398861;
  --color-p6:    #61b088;
  --color-p6-l1: #88d7b0;
  --color-p6-l2: #b0ffd7;

  /* Pos  7 · rgb(97,176,176) */
  --color-p7-d2: #126161;
  --color-p7-d1: #398888;
  --color-p7:    #61b0b0;
  --color-p7-l1: #88d7d7;
  --color-p7-l2: #b0ffff;

  /* Pos  8 — focus · Entertainment Venue · rgb(97,136,176) */
  --color-focus-d2:   #123961;
  --color-focus-d1:   #396188;
  /* --color-focus:   #6188b0; — semantic token above */
  --color-focus-l1:   #88b0d7;
  --color-focus-l2:   #b0d7ff;
  --color-focus-wash: rgba(97, 136, 176, 0.15); /* focus blue at ~15% opacity — hover fills, active tints */

  /* Pos  9 · rgb(97,97,176) */
  --color-p9-d2: #121261;
  --color-p9-d1: #393988;
  --color-p9:    #6161b0;
  --color-p9-l1: #8888d7;
  --color-p9-l2: #b0b0ff;

  /* Pos 10 · rgb(136,97,176) */
  --color-p10-d2: #391261;
  --color-p10-d1: #613988;
  --color-p10:    #8861b0;
  --color-p10-l1: #b088d7;
  --color-p10-l2: #d7b0ff;

  /* Pos 11 · rgb(176,97,176) */
  --color-p11-d2: #611261;
  --color-p11-d1: #883988;
  --color-p11:    #b061b0;
  --color-p11-l1: #d788d7;
  --color-p11-l2: #ffb0ff;

  /* Pos 12 · rgb(176,97,136) — unassigned */
  --color-p12-d2: #611239;
  --color-p12-d1: #883961;
  --color-p12:    #b06188;
  --color-p12-l1: #d788b0;
  --color-p12-l2: #ffb0d7;

  /* Error ramp — asymmetric: 1 dark shade, 3 light shades.
     Semantic base anchored at primary-d1 (#883939, 5.9:1 ✓ AA).
     Light end extended to -l3 (primary-l2). No -d2 in this ramp.
     All values overlap the primary chain — total closure maintained.
     d1 is floor-adjacent: G and B channels are at minimum (18). */
  --color-error-d1: #611212;   /* rgb( 97, 18, 18) — same as primary-d2   */
  /* --color-error:  #883939;  — semantic token above, same as primary-d1 */
  --color-error-l1: #b06161;   /* rgb(176, 97, 97) — same as primary      */
  --color-error-l2: #d78888;   /* rgb(215,136,136) — same as primary-l1   */
  --color-error-l3: #ffb0b0;   /* rgb(255,176,176) — same as primary-l2   */

  /* ----------------------------------------------------------
     Montjuïc surface tints — backgrounds only
     The warm website surface slice recorded in Laurelin v2.19
     and the DESIGN.md drift note. Never use for text, borders,
     or POI markers.
     ---------------------------------------------------------- */
  --color-tint-light-cream: #f5ebe1;
  --color-tint-cream:       #ebe1d7;
  --color-tint-dark-cream:  #e1d7cd;   /* darker mate of --color-tint-light-cream; neumorphic shadow on cream */
  --color-tint-light-stone-pink: #f5e1e1;
  --color-tint-stone-pink:       #ebd7d7;
  --color-tint-dark-stone-pink:  #e1cdcd;   /* neumorphic shadow mate, symmetric about #ebd7d7 */
  --color-tint-light-blush:      #f5e1eb;
  --color-tint-blush:            #ebd7e1;
  --color-tint-dark-blush:       #e1cdd7;   /* neumorphic shadow mate, symmetric about #ebd7e1 */

  /* Divider inks (v3.109, Option B, Matt 5 Jul 2026): a VISIBLE darker step of each tinted
     band, one shade below the ±10 neu-shadow mate above (which is tuned as a soft shadow and
     is too faint for a 1px rule). A divider on a tinted band uses its band's ink, so it reads
     as the band's own dark edge instead of the old flat warm sand. Cream and blush carry
     dividers today; stone-pink is defined for completeness (its only band, the quote, has no
     divider). Same hue as the band's neu-buttons, just deep enough to see. */
  --color-divider-cream:       #d4c7b8;
  --color-divider-stone-pink:  #d4bcbc;
  --color-divider-blush:       #d4bcc8;

  /* ----------------------------------------------------------
     Borders
     ---------------------------------------------------------- */
  --border-color:        var(--color-border);
  --border-width:        1px;
  --border-width-strong: 2px;
  --border-width-edge:   4px;

  /* ----------------------------------------------------------
     Radius — rem fractions of 16px base
     ---------------------------------------------------------- */
  --radius-none: 0;
  --radius-sm:   0.5rem;    /*  8px */
  --radius-md:   1rem;      /* 16px */
  --radius-lg:   1.5rem;    /* 24px */

  /* ----------------------------------------------------------
     Shadows
     ---------------------------------------------------------- */
  --shadow-1:          0.25rem 0.25rem 1rem -0.5rem rgba(0, 0, 0, 0.8);
  --shadow-soft:       0 1.5rem 3rem -1.5rem rgba(18, 18, 18, 0.25);  /* diffused float — hero cards and overlays; shadow-1 stays default for buttons and small cards */
  --shadow-crisp:      0.25rem 0.25rem 0 0 rgba(0, 0, 0, 0.12);  /* hard-edge lift, no blur — physical depth without glow */
  --shadow-hero-text:  0.25rem 0.25rem 1rem rgba(0, 0, 0, 0.8);
  --shadow-error-ring:   0 0 0 0.25rem rgba(136, 57, 57, 0.2);
  --shadow-success-ring: 0 0 0 0.25rem rgba(97, 176, 97, 0.2);
  --shadow-cta-hover:    0.25rem 0.5rem 1.25rem -0.5rem rgba(0, 0, 0, 0.8);  /* CTA hover lift (D4, 13 Jun 2026) — 4px 8px 20px -8px on the 4/8 grid */

  /* ----------------------------------------------------------
     Dark editorial sections
     Shared contract for dark hero, dark quote, and dark
     editorial sections. Aliases base tokens so component CSS can
     describe intent without inventing new colour values.
     ---------------------------------------------------------- */
  --section-dark-bg:             var(--color-dark);
  --section-dark-alt-bg:         var(--color-text);
  --section-dark-text:           var(--color-surface-page);
  --section-dark-text-strong:    var(--color-surface);
  --section-dark-text-muted:     var(--color-surface-muted);
  --section-dark-border:         var(--color-border);
  --section-dark-padding-block:  var(--space-24);
  --section-dark-padding-inline: var(--grid-padding-x);
  --section-dark-prose-width:    var(--prose-width);
  --section-dark-text-shadow:    var(--shadow-hero-text);
  --xpro-steps-icon-bg:          var(--color-surface-muted);
  --xpro-steps-icon-text:        var(--color-text-muted);
  --xpro-steps-badge-bg:         var(--color-surface-muted);
  --xpro-steps-badge-text:       var(--color-text-subtle);
  --xpro-steps-shadow:           var(--shadow-1);
  --xpro-steps-shadow-color:     rgba(0, 0, 0, 0.8);

  /* ----------------------------------------------------------
     Hero overlay — featured image + gradient scrim
     The page featured image fills the hero; a gradient overlay
     guarantees the copy stays legible whatever the photo. Two
     variants, picked per page by how bright the photo is:
       dark  (default) — dark scrim, off-white text. For bright,
                         busy or high-key photos, and the default mood.
       light           — pale cream scrim, dark text. For already-dark
                         or low-contrast photos that a dark scrim would
                         only muddy.
     Both are bottom-anchored (heaviest at the foot) so the copy sits
     bottom-left. Values ride the neutral #121212 and cream #f5ebe1
     scales. The variant is one class (.mybcn-hero--light); the scrim
     and text colour move together via the component's local tokens.
     ---------------------------------------------------------- */
  --hero-scrim-dark:  linear-gradient(to top,
                        rgba(18, 18, 18, 0.74) 0%,
                        rgba(18, 18, 18, 0.32) 48%,
                        rgba(18, 18, 18, 0.06) 75%);
  --hero-scrim-light: linear-gradient(to top,
                        rgba(245, 235, 225, 0.86) 0%,
                        rgba(245, 235, 225, 0.42) 48%,
                        rgba(245, 235, 225, 0.08) 75%);
  --hero-fg-dark:       var(--section-dark-text);   /* #f5f5f5 off-white */
  --hero-eyebrow-dark:  var(--color-tint-cream);    /* #ebe1d7 cream */
  --hero-fg-light:      var(--color-dark);          /* #121212 */
  --hero-eyebrow-light: var(--color-text-muted);    /* #616161 */

  /* ----------------------------------------------------------
     Transitions and easing
     --transition-base:   fast utility transitions (colour, border)
     --easing-smooth:     exponential ease-out (ease-out-quint)
                          — use instead of bounce or elastic curves
     --transition-smooth: slower motion transitions (height reveals,
                          panel opens, entrance animations)
     ---------------------------------------------------------- */
  --transition-base:   0.2s ease;
  --easing-smooth:     cubic-bezier(0.16, 1, 0.3, 1);
  --transition-smooth: 0.35s var(--easing-smooth);

  /* ----------------------------------------------------------
     Typography — font families
     Two-family system. Both free Google Fonts.
     Import (add to WordPress head or @import above :root):
     https://fonts.googleapis.com/css2?
       family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700
       &family=Outfit:wght@100;200;300;400;500;600;700;800;900
       &display=swap
     ---------------------------------------------------------- */
  --font-family-display:  'Cormorant Garamond', Georgia, serif;
  --font-family-sans:     'DM Sans (Prose/UI)', 'DM Sans', system-ui, sans-serif;
  --font-family-mono:     'JetBrains Mono', 'Courier New', monospace;
  --font-family-wordmark: 'Urbanist', system-ui, sans-serif;
  /* Wordmark treatment: weight 300 ("my") + weight 700 ("BCN"),
     same font-size for both parts, default letter-spacing.
     Load: Urbanist wght 300 + 700 from Google Fonts or fontsource. */

  /* ----------------------------------------------------------
     Typography — font weights
     ---------------------------------------------------------- */
  --font-weight-300-light:     300;
  --font-weight-400-normal:    400;
  --font-weight-500-medium:    500;
  --font-weight-600-bold:      600;
  --font-weight-h6:            600;   /* H6 differentiates from body by weight, not size (v3.85) */

  /* ----------------------------------------------------------
     Typography — body scale
     Perfect Fourth descending (÷1.333) from 1rem anchor.
     Note: ÷1.333 = ×0.75 — the heading ratio inverted.
     Fixed values, no clamp.
     ---------------------------------------------------------- */
  --text-base: clamp(0.9375rem, calc(0.094vw + 0.915rem), 1rem);   /* 15 to 16px — anchor: body, inputs (buttons use --text-sm since v3.74); gently fluid since v3.85 */
  --text-sm:   0.75rem;    /* 12px — ÷1.333 — meta, labels         */
  --text-xs:   0.563rem;   /*  9px — ÷1.333 — badges, chips        */
  --text-xxs:  0.422rem;   /*  7px — ÷1.333 — legal, fine print    */

  /* Line height — body text only. Headings set their own values.   */
  --line-height-body: 1.6;

  /* ----------------------------------------------------------
     Typography — heading scale
     Perfect Fourth ascending (×1.333).
     H6 anchored at 0.75rem (12px) min / 1rem (16px) max.
     Fluid clamp(): 375px (23.4375rem) → 1440px (90rem).
     slope  = (max − min) ÷ 66.5625
     offset = min − slope × 23.4375
     ---------------------------------------------------------- */
  --text-h1: clamp(3.157rem, calc(1.580vw + 2.786rem), 4.209rem);
  --text-h2: clamp(2.369rem, calc(1.184vw + 2.092rem), 3.157rem);
  --text-h3: clamp(1.777rem, calc(0.889vw + 1.569rem), 2.369rem);
  --text-h4: clamp(1.333rem, calc(0.667vw + 1.177rem), 1.777rem);
  --text-h5: clamp(1rem,     calc(0.500vw + 0.883rem), 1.333rem);
  --text-h6: var(--text-base);   /* equals body, 15 to 16px — differentiated by weight, not size (v3.85) */

  /* ----------------------------------------------------------
     Typography — heading line heights (fluid, clamp-based)
     Expressed in rem so they can be used in clamp() alongside
     vw. Ratio tightens as font-size grows: H1 1.25→1.10,
     H2 1.28→1.15, H3 1.35→1.20, H4 1.40→1.28,
     H5 1.45→1.35, H6 1.50→1.40.
     375px (23.4375rem) → 1440px (90rem). Same viewport range
     as the font-size scale.
     slope  = (max − min) ÷ 66.5625
     offset = min − slope × 23.4375
     ---------------------------------------------------------- */
  --line-height-h1: clamp(3.473rem, calc(1.421vw + 3.140rem), 4.419rem);  /* 1.10→1.05× — floor lifted so a two-line H1 does not clip ascenders (v3.85) */
  --line-height-h2: clamp(2.724rem, calc(0.888vw + 2.516rem), 3.315rem);  /* 1.15→1.05× at 375→1440px */
  --line-height-h3: clamp(2.399rem, calc(0.667vw + 2.243rem), 2.843rem);
  --line-height-h4: clamp(1.866rem, calc(0.615vw + 1.722rem), 2.275rem);
  --line-height-h5: clamp(1.450rem, calc(0.526vw + 1.327rem), 1.800rem);
  --line-height-h6: 1.5;   /* 24px at 16px body, on the 8 grid — H6 now equals body (v3.85) */

  /* ----------------------------------------------------------
     Typography — letter spacing
     em values are inherently fluid: they scale with the
     element's computed font-size, so tracking tightens
     automatically as the clamp font-size grows. No separate
     vw interpolation required.
     ---------------------------------------------------------- */
  --letter-spacing-h1:   -0.02em;
  --letter-spacing-h2:   -0.01em;
  --letter-spacing-h3:   -0.01em;   /* gentle tightening on display (was 0, v3.85) */
  --letter-spacing-h4:    0em;
  --letter-spacing-h5:    0em;
  --letter-spacing-h6:    0em;
  --letter-spacing-label: 0.08em;   /* airy tracking for UPPERCASE eyebrows and labels (was 0.4px, v3.85) */

  /* ----------------------------------------------------------
     Spacing — fractions of 1rem (16px) base
     Naming: 1 unit = 0.25rem (4px). Fixed values, no clamp.
     ---------------------------------------------------------- */
  --space-1:  0.25rem;   /*  4px */
  --space-2:  0.5rem;    /*  8px */
  --space-3:  0.75rem;   /* 12px */
  --space-4:  1rem;      /* 16px */
  --space-6:  1.5rem;    /* 24px */
  --space-8:  2rem;      /* 32px */
  --space-9:  2.5rem;    /* 40px */
  --space-12: 3rem;      /* 48px */
  --space-24: 6rem;      /* 96px  — textarea min-height (~4 lines) */
  --space-32: 8rem;      /* 128px — select[multiple] min-height  */

  /* ----------------------------------------------------------
     Fluid spacing (v3.96) — structural rhythm only.
     Large-end spacing that scales with the viewport, so section
     and band rhythm holds across screens without per-breakpoint
     overrides. Same method as the type scale: clamp() interpolated
     linearly 375px to 1440px. Each min and max is an existing
     --space-* step above, so these only interpolate between values
     already on the fixed scale (no off-scale numbers). Micro-spacing
     (--space-1 to --space-4) stays fixed on purpose. vw, not cqi:
     section rhythm should track the screen, not a single column.
     Design: operations/design/celebrimbor-fluid-spacing-proposal.md.
     ---------------------------------------------------------- */
  --space-fluid-sm:  clamp(0.75rem, calc(1.127vw + 0.486rem), 1.5rem);  /* 12 to 24px  (--space-3 to --space-6)  */
  --space-fluid-md:  clamp(1.5rem,  calc(1.502vw + 1.148rem), 2.5rem);  /* 24 to 40px  (--space-6 to --space-9)  */
  --space-fluid-lg:  clamp(2rem,    calc(1.502vw + 1.648rem), 3rem);    /* 32 to 48px  (--space-8 to --space-12) */
  --space-fluid-xl:  clamp(3rem,    calc(4.507vw + 1.944rem), 6rem);    /* 48 to 96px  (--space-12 to --space-24)*/
  --space-fluid-2xl: clamp(6rem,    calc(3.005vw + 5.296rem), 8rem);    /* 96 to 128px (--space-24 to --space-32)*/

  /* ----------------------------------------------------------
     Grid — 12-column layout system
     Maximum content width: 1440px on all myBCN surfaces.
     ---------------------------------------------------------- */
  --grid-max-width: 90rem;           /* 1440px — max content width */
  --grid-cols:      12;
  --grid-gap:       var(--space-6);  /* 24px — column gap */
  --grid-padding-x: clamp(var(--space-6), 7vw, var(--space-24));  /* fluid side gutter: 24px (1.5rem) -> 96px (6rem), matches the mock (v3.99) */

  /* ----------------------------------------------------------
     Prose width — measure (max text width), 8-aligned
     Three intentional widths inside the 45 to 75 character
     readable band, all multiples of 8 (v3.85, was a single 65ch).
     --prose-width is the body default; -lead for intros, -wide
     for dense blocks like FAQ. Apply via .prose or directly.
     ---------------------------------------------------------- */
  --prose-width:       560px;   /* body prose, about 66 characters, 70 x 8 (Bringhurst ideal) (v3.85) */
  --prose-width-lead:  448px;   /* lead and intro, about 53 characters, 56 x 8 (v3.85) */
  --prose-width-wide:  600px;   /* dense blocks like FAQ, about 70 characters, 75 x 8 (v3.85) */

  /* ----------------------------------------------------------
     Breakpoints — reference tokens only
     Plain CSS cannot read a custom property inside a media
     query condition, and Celebrimbor has no build step, so
     these document the canonical breakpoints: the @media rules
     still carry the literal value. Canonical set agreed with
     Matt 13 Jun 2026 (D7). The old 64rem (1024px) breakpoint is
     retired in favour of --bp-lg. All @media rules in this file
     now use this canonical set (migrated 14 Jun 2026): each @media
     carries a comment naming the token it matches.
     ---------------------------------------------------------- */
  --bp-sm: 38.75rem;   /* 620px — phone */
  /* --bp-md (768px) retired 30 Jun 2026: two-breakpoint system, 620 and 980 only */
  --bp-lg: 61.25rem;   /* 980px — small laptop and 12-column collapse */

  /* ----------------------------------------------------------
     Buttons
     ---------------------------------------------------------- */
  /* Button system (v3.72) — Candidate B.
     --btn-*           = neutral, outline only, no fill (quiet action).
     --cta-*           = primary booking CTA: dark rest, terracotta hover.
     --cta-invert-*    = CTA on dark surfaces: terracotta fill, cream border.
     --btn-secondary-* = reserve secondary: terracotta ghost. */
  --btn-bg:            transparent;
  --btn-border:        var(--color-text-subtle);     /* #888888 — cool grey outline */
  --btn-text:          var(--color-text-muted);      /* #616161 — 5.74:1 ✓ AA on white */

  --btn-hover-bg:      transparent;                  /* softened v3.72 — no dark fill */
  --btn-hover-border:  var(--color-text);            /* #393939 */
  --btn-hover-text:    var(--color-text);            /* #393939 — 10.3:1 ✓ AAA on white */

  --btn-active-bg:     transparent;
  --btn-active-border: var(--color-dark);            /* #121212 */
  --btn-active-text:   var(--color-dark);            /* #121212 */

  --btn-arch-depth:    3rem;   /* arch radius = full button height. Clamps to the
                                  button height on the shorter sizes (heights are now
                                  ~32 / ~40 / ~48px), so the whole left edge is the arc.
                                  Used directly in .btn border-radius (top-left corner).
                                  Elementor: Style → Border → Border Radius, top-left. */

  /* Button sizing and Option D optical centring (13 Jun 2026).
     Buttons run at --text-sm (12px), sentence case. The arch removes the
     top-left mass, so the label gets more left than right padding to sit
     optically centred. The shift grows with size, because the 3rem arch
     clamps to the (shorter) button height, so a taller button curves
     further in at the label line. Base values here; .btn--sm and .btn--lg
     override them on their own classes. Bespoke px-derived rems, kept off
     the --space-* scale on purpose (px-to-token map decision D2). */
  --btn-pad-y:        var(--space-3);   /* 12px — base height lands ~40px */
  --btn-pad-x-left:   1.6875rem;        /* 27px — arch-answering left pad */
  --btn-pad-x-right:  1.3125rem;        /* 21px — 6px less than left (base +6 shift) */

  /* Primary booking CTA — Candidate B (Matt 06 Jun 2026).
     Dark rest, terracotta hover flip, deep-terracotta press. */
  --cta-bg:            var(--color-dark);            /* #121212 */
  --cta-border:        var(--color-dark);            /* #121212 */
  --cta-text:          var(--color-tint-cream);      /* #ebe1d7 on #121212 = 14.5:1 ✓ AAA */

  --cta-hover-bg:      var(--color-primary-d1);      /* #883939 — terracotta fill on hover */
  --cta-hover-border:  var(--color-primary-d1);      /* #883939 */
  --cta-hover-text:    var(--color-surface);         /* #ffffff on #883939 = 7.8:1 ✓ AAA */

  --cta-active-bg:     var(--color-primary-d2);      /* #611212 — deep terracotta press */
  --cta-active-border: var(--color-primary-d2);      /* #611212 */
  --cta-active-text:   var(--color-surface);         /* #ffffff on #611212 = 13.1:1 ✓ AAA */

  /* CTA on dark surfaces — terracotta fill, cream border so the shape
     lifts off the dark band (Matt 06 Jun 2026). */
  --cta-invert-bg:           var(--color-primary-d1);   /* #883939 */
  --cta-invert-border:       var(--color-tint-cream);   /* #ebe1d7 — cream border, 14.5:1 vs dark band */
  --cta-invert-text:         var(--color-surface);      /* #ffffff on #883939 = 7.8:1 ✓ AAA */
  --cta-invert-hover-bg:     var(--color-primary-d2);   /* #611212 */
  --cta-invert-hover-border: var(--color-tint-cream);   /* #ebe1d7 — border holds */
  --cta-invert-hover-text:   var(--color-surface);      /* #ffffff on #611212 = 13.1:1 ✓ AAA */

  /* Reserve secondary — terracotta ghost (not yet in production use). */
  --btn-secondary-bg:           transparent;
  --btn-secondary-border:       var(--color-primary-d1);  /* #883939 */
  --btn-secondary-text:         var(--color-primary-d1);  /* #883939 — 7.8:1 on white ✓ AAA */
  --btn-secondary-hover-bg:     var(--color-primary-d1);  /* #883939 fill on hover */
  --btn-secondary-hover-border: var(--color-primary-d1);
  --btn-secondary-hover-text:   var(--color-surface);     /* #ffffff on #883939 = 7.8:1 ✓ AAA */

  --btn-shadow:    var(--shadow-1);                  /* retained — used by toggle-slider; not applied to .btn */
  --focus-outline: var(--color-focus-d1);            /* #396188 — 5.9:1 ✓ AA on white */

  /* ----------------------------------------------------------
     Forms
     ---------------------------------------------------------- */
  --form-bg:            var(--color-surface);
  --form-border:        var(--color-border);
  --form-border-active: var(--color-success);
  --form-border-focus:  var(--color-focus);

  --form-text:          var(--color-text);
  --form-label:         var(--color-text-muted);
  --form-hint:          var(--color-text-muted);   /* #616161 on white = 6.18:1 ✓ AA */
  --form-placeholder:   var(--color-text-disabled);

  --form-disabled-bg:   var(--color-surface-page);
  --form-disabled-text: var(--color-text-disabled);

  --form-required: var(--color-success);
  --form-success:  var(--color-success);
  --form-error:    var(--color-error);     /* #883939 — 5.9:1 ✓ AA for validation text */
  --form-warning:  var(--color-warning);
  --form-info:     var(--color-focus);

  --form-shadow-focus:   var(--shadow-1);
  --form-shadow-error:   var(--shadow-error-ring);
  --form-shadow-success: var(--shadow-success-ring);

  --form-spacing-xs: var(--space-1);   /*  4px */
  --form-spacing-sm: var(--space-2);   /*  8px */
  --form-spacing-md: var(--space-3);   /* 12px */
  --form-spacing-lg: var(--space-4);   /* 16px */
  --form-spacing-xl: var(--space-6);   /* 24px */

  /* ----------------------------------------------------------
     Links
     Two background layers on prose a:
       Layer 1 (top):    2px coloured underline — focus-d1 (#396188)
       Layer 2 (below):  neutral grey fill — grows to 50% on hover
     At rest only the underline is visible. On hover the grey fill
     grows from the bottom and the underline remains on top of it.
     Text colour is focus-d1 throughout — no colour switch on hover.
     Monospace links (a code / code a) keep text-decoration only —
     no background treatment.
     ---------------------------------------------------------- */
  --link-color:             var(--color-text);           /* #393939 — link text, blends with body                */
  --link-color-visited:     var(--color-text);          /* #393939 — no special visited treatment               */
  --link-underline:         var(--color-warning-d1);  /* #886139 — resting underline (sand)                          */
  --link-highlight:         var(--color-warning-l1);  /* #d7b088 — sand wash fill on hover                    */
  --link-underline-hover:   var(--color-warning);     /* #b08861 — hover/active underline (sand, lightens)          */
  --link-underline-visited: var(--color-p10-d1);      /* #613988 — code link visited                          */
}


/* ============================================================
   Typography — container-query enhancement (v3.84, D9)
   Where container queries are supported, drive the fluid heading
   scale by the nearest query container's inline size (cqi)
   instead of the viewport (vw), so a heading sizes to its column,
   not the screen. The vw scale in :root above is the fallback:
   older browsers, or any heading with no query-container
   ancestor, resolve cqi against the viewport and so keep the old
   behaviour. Query containers are declared in the Elementor
   bridge: .mb-band > .e-con-inner (section headings cap at the
   content width) and .mb-col (column headings size to the
   column). Same min/max and slope as the vw scale, so at a
   1440px container the result is identical; narrower containers
   scale down. Letter spacing is em-based and needs no change.
   ============================================================ */
@supports (container-type: inline-size) {
  :root {
    --text-h1: clamp(3.157rem, calc(1.580cqi + 2.786rem), 4.209rem);
    --text-h2: clamp(2.369rem, calc(1.184cqi + 2.092rem), 3.157rem);
    --text-h3: clamp(1.777rem, calc(0.889cqi + 1.569rem), 2.369rem);
    --text-h4: clamp(1.333rem, calc(0.667cqi + 1.177rem), 1.777rem);
    --text-h5: clamp(1rem,     calc(0.500cqi + 0.883rem), 1.333rem);
    --text-h6: var(--text-base);   /* equals body — mirror of :root (v3.85) */

    --line-height-h1: clamp(3.473rem, calc(1.421cqi + 3.140rem), 4.419rem);  /* 1.10→1.05× floor lift, cqi mirror of :root (v3.85) */
    --line-height-h2: clamp(2.724rem, calc(0.888cqi + 2.516rem), 3.315rem);
    --line-height-h3: clamp(2.399rem, calc(0.667cqi + 2.243rem), 2.843rem);
    --line-height-h4: clamp(1.866rem, calc(0.615cqi + 1.722rem), 2.275rem);
    --line-height-h5: clamp(1.450rem, calc(0.526cqi + 1.327rem), 1.800rem);
    --line-height-h6: 1.5;   /* fixed — H6 equals body, mirror of :root (v3.85) */
  }
}


/* ============================================================
   BASE — body defaults
   Sets line-height and font stack globally so no element
   inherits the browser default of ~1.15.
   ============================================================ */

body {
  font-family: var(--font-family-sans);
  font-size: var(--text-base);
  line-height: var(--line-height-body);
  color: var(--color-text);
  background-color: var(--color-surface-page);
}

p {
  line-height: var(--line-height-body);
  margin: 0;
}

/* Prose utility — constrains text to a readable line length
   and restores paragraph spacing.
   Apply to any text container that holds body copy.
   p { margin: 0 } is set globally to prevent component bleed;
   paragraph spacing is re-introduced here via the adjacent
   sibling selector so it only fires between consecutive <p>
   elements inside a prose context.
   --space-4 (16px) gives a 1.67× ratio vs the 9.6px inter-line
   gap (line-height 1.6 on 16px base) — within the 1.5–2× ideal. */
.prose {
  max-width: var(--prose-width);
}

.prose p + p {
  margin-top: var(--space-4);
}

/* Sibling case: pages that apply .prose per paragraph (not as a wrapper) need
   the same 16px rhythm between adjacent .prose blocks. Mirrors the mock rule. */
.prose + .prose {
  margin-top: var(--space-4);
}


/* ============================================================
   LINKS
   Two background layers:
     Layer 1 (top)   — coloured underline: --link-underline
                       (warning-d1 #886139). 80% wide, 1px, centred.
     Layer 2 (below) — sand wash fill: --link-highlight (#d7b088).
                       Invisible at rest, grows to 33% on hover as
                       a gradient (dense at base, 20% at top).
   On hover, Layer 1 widens to 100% and shifts to
   --link-underline-hover (#b08861, sand base).
   Text colour is --link-color (--color-text #393939) throughout.
   No special visited treatment.
   Monospace links retain text-decoration — no background growth.
   Modifier classes reset all link treatment for image and nav.
   ============================================================ */

a {
  color: var(--link-color);
  text-decoration: none;
  background-image:
    linear-gradient(var(--link-underline), var(--link-underline)),
    linear-gradient(var(--link-highlight), var(--link-highlight));
  background-size: 80% 1px, 100% 0%;
  background-position: center bottom, center bottom;
  background-repeat: no-repeat, no-repeat;
  padding-bottom: 0.08em;
  transition: background-size var(--transition-smooth);
}

a:hover,
a:active {
  background-image:
    linear-gradient(var(--link-underline-hover), var(--link-underline-hover)),
    linear-gradient(to top, var(--link-highlight) 0%, rgba(215, 176, 136, 0.2) 100%);
  background-size: 100% 1px, 100% 33%;
}

a:visited {
  color: var(--link-color-visited);
}

a:focus-visible {
  outline: 1px solid var(--color-focus);
  outline-offset: 0.2em;
  border-radius: var(--radius-none);
}

/* Image links — suppress background-image underline automatically.
   a:has(img) catches any <a><img></a> without needing a class.
   .link--image retained for colour/decoration reset when a linked
   image sits alongside text. */
a:has(img) {
  background-image: none;
  padding-bottom: 0;
}

a.link--image,
a.link--image:hover,
a.link--image:visited,
a.link--image:active {
  color: inherit;
  text-decoration: none;
  background: none;
  padding-bottom: 0;
}

/* Full reset — nav items, chip links, button-style anchors.
   background-image: none (not background: none) so component
   background-color from .btn / .chip is not overridden by the
   higher-specificity a.link--unstyled selector.
   padding-bottom omitted for the same reason — components set
   their own padding and a.link--unstyled (0,1,1) would otherwise
   beat .btn (0,1,0) and remove its bottom padding. */
a.link--unstyled,
a.link--unstyled:hover,
a.link--unstyled:visited,
a.link--unstyled:active {
  color: inherit;
  text-decoration: none;
  background-image: none;
}

/* Image-only links: no gradient underline, no colour change on hover.
   a:hover (0,1,1) beats a:has(> img) (0,0,2) on specificity, so
   :hover and :active overrides are needed to block the gradient and
   the colour shift (which would animate SVG currentColor fills).
   Targets <a> containing only an <img> or inline <svg> — logos,
   icon buttons, avatar links. padding-bottom cleared so the
   underline offset space doesn't push layout. */
a:has(> img),
a:has(> svg) {
  background-image: none;
  padding-bottom: 0;
  color: inherit;
}

a:has(> img):hover,
a:has(> svg):hover,
a:has(> img):active,
a:has(> svg):active {
  background-image: none;
  color: inherit;
}

/* External links — indicates navigation leaving the site.
   Use .link--external explicitly on outbound hrefs. Do not
   use a[target="_blank"] as selector — internal files also
   open in new tabs and should not carry the indicator.
   ↗ is appended at 0.65em / superscript / 70% opacity so it
   reads as a subtle signal rather than a design element. */
a.link--external::after {
  content: " ↗";
  font-size: 0.65em;
  vertical-align: super;
  line-height: 1;
  opacity: 0.7;
  letter-spacing: 0;
}

/* Monospace links — <a><code>…</code></a> or <code><a>…</a></code>
   background-image underline lives on the <a>, not the <code>, so
   background:none on code alone doesn't remove it — causing a double
   underline. a:has(code) suppresses the background-image on the <a>
   itself. text-decoration then provides the single underline.
   Offset tightened: monospace sits closer to baseline than Outfit. */
a:has(code) {
  background-image: none;
  padding-bottom: 0;
}

a code,
code a {
  text-decoration: underline;
  text-decoration-color: var(--link-underline);
  text-underline-offset: 0.15em;
}

a:hover code,
a:active code {
  text-decoration-color: var(--link-underline-hover);
}

a:visited code {
  text-decoration-color: var(--link-underline-visited);
}

/* Inline prose links: links inside body copy (.prose, .lead, .ticks and
   .faq answers). A warm variant of the global link: dark body text with a
   sand underline (--color-warning) offset below it, darkening to
   sand-d1 (--color-warning-d1) on hover and focus. The global
   two-layer background-image underline is suppressed (as on monospace and
   image links) so only the single text-decoration underline shows, with no
   double rule. Standalone link-like components (.cta, .text-link, .chip,
   nav, .breadcrumb) sit outside these contexts and keep their own treatment.
   Promoted from the Mírdain interior-page chrome. Matt approved 14 Jun 2026. */
.prose a,
.lead a,
.ticks a,
.faq details p a {
  color: inherit;
  background-image: none;
  padding-bottom: 0;
  text-decoration: underline;
  text-decoration-color: var(--color-warning);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
  transition: text-decoration-color var(--transition-base);
}

.prose a:hover,
.lead a:hover,
.ticks a:hover,
.faq details p a:hover,
.prose a:focus-visible,
.lead a:focus-visible,
.ticks a:focus-visible,
.faq details p a:focus-visible {
  background-image: none;
  text-decoration-color: var(--color-warning-d1);
}


/* ============================================================
   TYPOGRAPHY — Heading elements + utilities
   H1–H2: weight 300 light
   H3:    weight 400 normal
   H4–H6: weight 600 bold
   ============================================================ */

h1, .text-h1 {
  font-family: var(--font-family-display);
  font-size: var(--text-h1);
  font-weight: var(--font-weight-300-light);
  line-height: var(--line-height-h1);
  letter-spacing: var(--letter-spacing-h1);
  color: var(--color-text);
  margin: 0;
}

h2, .text-h2 {
  font-family: var(--font-family-display);
  font-size: var(--text-h2);
  font-weight: var(--font-weight-300-light);
  line-height: var(--line-height-h2);
  letter-spacing: var(--letter-spacing-h2);
  color: var(--color-text);
  margin: 0;
}

h3, .text-h3 {
  font-family: var(--font-family-sans);
  font-size: var(--text-h3);
  font-weight: var(--font-weight-400-normal);
  line-height: var(--line-height-h3);
  letter-spacing: var(--letter-spacing-h3);
  color: var(--color-text);
  margin: 0;
}

h4, .text-h4 {
  font-family: var(--font-family-sans);
  font-size: var(--text-h4);
  font-weight: var(--font-weight-600-bold);
  line-height: var(--line-height-h4);
  letter-spacing: var(--letter-spacing-h4);
  color: var(--color-text);
  margin: 0;
}

h5, .text-h5 {
  font-family: var(--font-family-sans);
  font-size: var(--text-h5);
  font-weight: var(--font-weight-600-bold);
  line-height: var(--line-height-h5);
  letter-spacing: var(--letter-spacing-h5);
  color: var(--color-text);
  margin: 0;
}

h6, .text-h6 {
  font-family: var(--font-family-sans);
  font-size: var(--text-h6);
  font-weight: var(--font-weight-h6);
  line-height: var(--line-height-h6);
  letter-spacing: var(--letter-spacing-h6);
  color: var(--color-text);
  margin: 0;
}

.text-sm  { font-size: var(--text-sm); }
.text-xs  { font-size: var(--text-xs); }
.text-xxs { font-size: var(--text-xxs); }


/* ============================================================
   BUTTONS
   Uniform 2px border (--border-width-strong) on all four sides.
   Gaudí arch corner: a large radius on the top-left only
   (--btn-arch-depth = full button height), base-16 rounded
   top-right and bottom-right, and a sharp bottom-left.
   See .btn for the exact four-corner radius value.
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;

  padding: var(--btn-pad-y) var(--btn-pad-x-right) var(--btn-pad-y) var(--btn-pad-x-left);

  font-size: var(--text-sm);
  font-family: var(--font-family-sans);
  font-weight: var(--font-weight-500-medium);
  text-transform: none;
  letter-spacing: 0;
  line-height: 1;
  text-decoration: none;

  background: var(--btn-bg);
  border-style: solid;
  border-color: var(--btn-border);
  border-width: var(--border-width-strong);   /* 2px uniform */
  color: var(--btn-text);

  /* Arch shape — asymmetric four-corner radius (v3.50).
     Inspired by Gaudí / Gothic arches of Barcelona.
     top-left:     3rem (48px) = --btn-arch-depth = full button height.
                   Entire left edge becomes the arc; no straight left side.
     top-right:    1rem (16px) — base-16 rounded corner.
     bottom-right: 1rem (16px) — base-16 rounded corner.
     bottom-left:  0           — sharp corner.
     Fully Elementor-native: Style → Border → Border Radius (individual). */
  border-radius: var(--btn-arch-depth) var(--space-4) var(--space-4) 0;

  box-shadow: none;
  cursor: pointer;

  transition: background var(--transition-base),
              border-color var(--transition-base),
              color var(--transition-base),
              outline-color var(--transition-base);

  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}

.btn:hover {
  background: var(--btn-hover-bg);
  border-color: var(--btn-hover-border);
  color: var(--btn-hover-text);
}

.btn:active {
  background: var(--btn-active-bg);
  border-color: var(--btn-active-border);
  color: var(--btn-active-text);
}

/* Primary booking CTA — Candidate B: dark rest → terracotta hover → deep-terracotta press (v3.72). */
.btn--cta {
  background: var(--cta-bg);
  border-color: var(--cta-border);
  color: var(--cta-text);
  font-size: 0.875rem;   /* 14px — canonical CTA text size (Matt 22 Jun 2026). One
                            deliberate off-scale step above --text-sm: the primary
                            booking button reads slightly larger than utility buttons.
                            Used at base (medium) size everywhere (header, hero, booking);
                            base padding gives ~42px height. The dark fill, Gaudi arch and
                            flat-at-rest are the .btn defaults; never use .btn--cta-invert
                            for myBCN CTAs (deprecated, CTAs are always dark). */
}

.btn--cta:hover {
  background: var(--cta-hover-bg);
  border-color: var(--cta-hover-border);
  color: var(--cta-hover-text);
}

.btn--cta:active {
  background: var(--cta-active-bg);
  border-color: var(--cta-active-border);
  color: var(--cta-active-text);
}

/* CTA on dark surfaces — terracotta fill, cream border (v3.72). */
.btn--cta-invert {
  background: var(--cta-invert-bg);
  border-color: var(--cta-invert-border);
  color: var(--cta-invert-text);
}

.btn--cta-invert:hover,
.btn--cta-invert:active {
  background: var(--cta-invert-hover-bg);
  border-color: var(--cta-invert-hover-border);
  color: var(--cta-invert-hover-text);
}

/* Reserve secondary — terracotta ghost (v3.72). */
.btn--secondary {
  background: var(--btn-secondary-bg);
  border-color: var(--btn-secondary-border);
  color: var(--btn-secondary-text);
}

.btn--secondary:hover,
.btn--secondary:active {
  background: var(--btn-secondary-hover-bg);
  border-color: var(--btn-secondary-hover-border);
  color: var(--btn-secondary-hover-text);
}

/* Focus — keyboard only */
.btn:focus-visible,
.btn--cta:focus-visible,
.btn--cta-invert:focus-visible,
.btn--secondary:focus-visible {
  outline: var(--border-width-strong) solid var(--focus-outline);
  outline-offset: 2px;
}

.btn:focus:not(:focus-visible) { outline: none; }

/* Disabled */
.btn:disabled,
.btn--disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
  box-shadow: none;
}

.btn:disabled      { background: var(--btn-bg);  color: var(--btn-text);  opacity: 0.4; }
.btn--cta:disabled { background: var(--cta-bg);  color: var(--cta-text);  opacity: 0.4; }

/* Link elements styled as buttons */
a.btn, a.btn--cta, a.btn--cta-invert, a.btn--secondary { text-decoration: none; }

/* Size variants — override the padding tokens; font-size inherits --text-sm.
   The optical shift (left minus right) grows with size: sm +4px, lg +8px. */
.btn--sm {
  --btn-pad-y:       var(--space-2);   /* 8px — height ~32px */
  --btn-pad-x-left:  1.125rem;         /* 18px — 4px more than right (+4 shift) */
  --btn-pad-x-right: 0.875rem;         /* 14px */
}

.btn--lg {
  --btn-pad-y:       var(--space-4);   /* 16px — height ~48px */
  --btn-pad-x-left:  2.25rem;          /* 36px — 8px more than right (+8 shift) */
  --btn-pad-x-right: 1.75rem;          /* 28px */
}

/* Icon variant */
.btn--icon { gap: var(--space-1); }

.btn--icon svg {
  width: var(--space-4);
  height: var(--space-4);
  stroke: currentColor;
  fill: none;
}

/* Loading state */
.btn--loading {
  position: relative;
  gap: var(--space-2);
}

.spinner {
  width: var(--space-4);
  height: var(--space-4);
  border: 2px solid var(--color-focus);
  border-right-color: transparent;
  border-radius: 50%;
  display: inline-block;
  animation: spin 0.8s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

/* Button layout utilities */
.btn-group {
  display: flex;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.btn-group--centered { justify-content: center; }
.btn-group--right    { justify-content: flex-end; }

.btn--block {
  display: flex;
  width: 100%;
}

/* Elementor and addon button text surfaces.
   Elementor widget CSS can store "DM Sans" directly, bypassing the
   Celebrimbor token. Keep the registered Custom Fonts family first. */
.elementor-button,
.elementor-button .elementor-button-content-wrapper,
.elementor-button .elementor-button-text,
.mb-modalbox__wrapper-trigger,
.mb-modalbox__wrapper-btn,
.xpro-elementor-button-w-hover-card,
.xpro-elementor-button-inner,
.xpro-button-text,
.xpro-creative-btn,
.xpro-creative-btn-text,
.cbp-l-loadMore-link,
.cbp-l-loadMore-button .cbp-l-loadMore-link,
.xpro-gallery-elementor-loadmore .cbp-l-loadMore-link {
  font-family: var(--font-family-sans);
}


/* ============================================================
   FORMS
   ============================================================ */

/* Layout */
.form-section { margin-bottom: var(--form-spacing-xl); }

.form-row {
  display: flex;
  gap: var(--form-spacing-lg);
  margin-bottom: var(--form-spacing-lg);
}

.form-row--collapse { gap: var(--form-spacing-md); }

.form-col {
  flex: 1;
  min-width: 0;
}

.form-actions {
  display: flex;
  gap: var(--form-spacing-lg);
  margin-top: var(--form-spacing-xl);
  padding-top: var(--form-spacing-xl);
  border-top: var(--border-width) solid var(--form-border);
}

.form-actions--centered { justify-content: center; }
.form-actions--right    { justify-content: flex-end; }

@media (max-width: 38.75rem) {  /* --bp-sm (620px) */
  .form-row { flex-direction: column; gap: var(--form-spacing-lg); }
  .form-actions { flex-direction: column; }
  .form-actions .btn { width: 100%; }
}

/* Field */
.field { margin-bottom: var(--form-spacing-lg); }
.field:last-child { margin-bottom: 0; }

/* Labels */
.field__label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-400-normal);
  margin-bottom: var(--form-spacing-xs);
  color: var(--form-label);
  line-height: 1.4;
  text-transform: none;
  letter-spacing: var(--letter-spacing-label);
}

.field__label--required { font-weight: var(--font-weight-600-bold); }

.field__label--required::after {
  content: "*";
  color: var(--form-required);
  margin-left: var(--form-spacing-xs);
  font-weight: var(--font-weight-600-bold);
}

/* Input base */
.field__input {
  width: 100%;
  padding: var(--space-2);
  font-size: var(--text-base);
  font-family: inherit;
  color: var(--form-text);
  line-height: 1.5;
  background: var(--form-bg);
  border: var(--border-width) solid var(--form-border);
  border-radius: var(--radius-md) 0 0 0;   /* top-left only — matches button */
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
  outline: none;
  box-sizing: border-box;
}

.field__input::placeholder {
  color: var(--form-placeholder);
  opacity: 1;
  font-style: italic;
  font-size: var(--text-sm);
}

.field__input:focus,
.field__input:active {
  border-color: var(--form-border-focus);
  box-shadow: var(--form-shadow-focus);
}

.field__input:disabled,
.field__input[readonly] {
  background: var(--form-disabled-bg);
  border-color: var(--form-border);
  color: var(--form-disabled-text);
  cursor: not-allowed;
}

.field__input--error {
  border-color: var(--form-error);
  border-width: var(--border-width-strong);
  box-shadow: var(--form-shadow-error);   /* error-coloured ring — rgba(176,97,97,0.2) */
}

.field__input--error:focus {
  border-color: var(--form-error);
  border-width: var(--border-width-strong);
  box-shadow: var(--form-shadow-error);
}

.field__input--success {
  border-color: var(--form-success);
  border-width: var(--border-width-strong);
  box-shadow: var(--form-shadow-success);
}

.field__input--success:focus {
  border-color: var(--form-success);
  border-width: var(--border-width-strong);
  box-shadow: var(--form-shadow-success);
}

/* Select */
select.field__input {
  font-size: var(--text-base);
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23616161%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22butt%22%20stroke-linejoin%3D%22miter%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-2) center;
  background-size: var(--space-6);
  padding-right: var(--space-8);
}

select.field__input::-ms-expand { display: none; }
select.field__input:active { border-color: var(--form-border-active); }

select.field__input[multiple] {
  background-image: none;
  padding: var(--space-2);
  min-height: var(--space-32);   /* 8rem / 128px */
}

select.field__input[multiple] option { padding: var(--space-2); }

/* Textarea */
textarea.field__input {
  resize: vertical;
  min-height: var(--space-24);   /* 6rem / 96px — ~4 lines at 1.6 line-height */
  line-height: 1.6;
}

/* Hint text */
.field__hint {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-400-normal);
  color: var(--form-hint);
  margin-top: var(--form-spacing-xs);
  line-height: 1.5;
}

.field__hint--error   { color: var(--form-error);           font-weight: var(--font-weight-600-bold); }
.field__hint--success { color: var(--color-success-d2); }   /* #126112 on white = 7.63:1 ✓ AAA */
.field__hint--warning { color: var(--color-warning-d1); }   /* #886139 on white = 5.50:1 ✓ AA  */

/* Input group */
.input-group {
  display: flex;
  align-items: stretch;
  width: 100%;
  border: var(--border-width) solid var(--form-border);
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.input-group:focus-within {
  border-color: var(--form-border-focus);
  box-shadow: var(--form-shadow-focus);
}

.input-group .field__input { border: 0; }

.input-group__addon {
  display: inline-flex;
  align-items: center;
  padding: var(--space-2);
  border: 0;
  background: var(--btn-bg);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-400-normal);
  white-space: nowrap;
}

/* Checkboxes */
.checkbox-group,
.radio-group { margin-bottom: var(--form-spacing-lg); }

.checkbox-wrapper,
.radio-wrapper {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--form-spacing-sm) 0;
}

.checkbox-wrapper input[type="checkbox"],
.radio-wrapper input[type="radio"] {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}

/* ============================================================
   CHECKBOXES
   ============================================================ */

.checkbox-custom {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  background: var(--form-bg);
  border: var(--border-width-strong) solid var(--color-border);
  border-radius: var(--radius-none);
  cursor: pointer;
  transition: border-color var(--transition-base),
              box-shadow var(--transition-base),
              background var(--transition-base);
  flex-shrink: 0;
}

.checkbox-wrapper:hover .checkbox-custom {
  border-color: var(--form-border-focus);
}

.checkbox-wrapper input[type="checkbox"]:active + .checkbox-custom {
  border-color: var(--form-border-active);
}

.checkbox-wrapper input[type="checkbox"]:checked + .checkbox-custom {
  background: var(--form-required);
  border-color: var(--form-required);
}

.checkbox-wrapper input[type="checkbox"]:checked + .checkbox-custom::after {
  content: "";
  width: 0.625rem;
  height: 0.375rem;
  border-left: 2px solid var(--color-dark);    /* #121212 on #61b061 = 7.18:1 ✓ AAA */
  border-bottom: 2px solid var(--color-dark);
  transform: rotate(-45deg) translate(1px, -1px);
}

.checkbox-wrapper input[type="checkbox"]:focus-visible + .checkbox-custom {
  border-color: var(--form-border-focus);
  box-shadow: var(--form-shadow-focus);
}

.checkbox-wrapper input[type="checkbox"]:disabled + .checkbox-custom {
  background: var(--form-disabled-bg);
  border-color: var(--color-border);
  cursor: not-allowed;
}


/* ============================================================
   RADIO BUTTONS
   Circular indicator — border-radius: 50% is structural, not decorative.
   The circle communicates "one of many" (vs checkbox "one or more").
   ============================================================ */

.radio-custom {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  background: var(--form-bg);
  border: var(--border-width-strong) solid var(--color-border);
  border-radius: 50%;
  cursor: pointer;
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
  flex-shrink: 0;
}

.radio-wrapper:hover .radio-custom {
  border-color: var(--form-border-focus);
}

.radio-wrapper input[type="radio"]:active + .radio-custom {
  border-color: var(--form-border-active);
}

.radio-wrapper input[type="radio"]:checked + .radio-custom {
  border-color: var(--form-required);
}

.radio-wrapper input[type="radio"]:checked + .radio-custom::after {
  content: "";
  width: 0.625rem;
  height: 0.625rem;
  background: var(--form-required);
  border-radius: 50%;
}

.radio-wrapper input[type="radio"]:focus-visible + .radio-custom {
  border-color: var(--form-border-focus);
  box-shadow: var(--form-shadow-focus);
}

/* Shared checkbox / radio / toggle labels */
.checkbox-label,
.radio-label,
.toggle-label {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-400-normal);
  color: var(--form-text);
  line-height: 1.5;
  cursor: pointer;
}


/* ============================================================
   TOGGLE SWITCH
   Sharp corners — deliberate choice for this component.
   The binary state is communicated by position, colour, and motion —
   not by pill shape. Square knob on square track.
   ============================================================ */

.toggle-wrapper {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.toggle {
  position: relative;
  display: inline-block;
  width: 3rem;     /* 48px */
  height: 1.5rem;  /* 24px */
}

.toggle input { opacity: 0; width: 0; height: 0; }

.toggle-slider {
  position: absolute;
  cursor: pointer;
  top: 0; left: 0; right: 0; bottom: 0;
  background: var(--color-surface-muted);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-none);      /* sharp — interactive element rule */
  box-sizing: border-box;
  box-shadow: var(--btn-shadow);
  transition: background var(--transition-base),
              border-color var(--transition-base);
}

.toggle-slider:before {
  position: absolute;
  content: "";
  height: 1.25rem;   /* 20px — 24px track minus 1px border × 2, with 1px gap each side */
  width: 1.25rem;
  left: 1px;
  top: 50%;
  transform: translateY(-50%);
  background: var(--color-surface);      /* white knob on neutral track */
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-none);     /* square knob */
  box-sizing: border-box;
  transition: background var(--transition-base),
              border-color var(--transition-base),
              transform var(--transition-base);
}

.toggle input:checked + .toggle-slider {
  background: var(--color-success);
  border-color: var(--color-success-d1);
}

.toggle input:checked + .toggle-slider:before {
  background: var(--color-surface-page);
  border-color: var(--color-success-d1);
  transform: translateY(-50%) translateX(22px);  /* 48px track − 20px knob − 1px × 2 borders − 1px × 2 padding */
}

.toggle input:focus-visible + .toggle-slider {
  outline: var(--border-width-strong) solid var(--focus-outline);
  outline-offset: 2px;
}

.toggle input:disabled + .toggle-slider {
  background: var(--color-border);
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: none;
}

.toggle input:disabled + .toggle-slider:before {
  opacity: 0.8;
}

.toggle-wrapper:has(input:disabled) .toggle-label {
  color: var(--form-disabled-text);
  cursor: not-allowed;
}


/* ============================================================
   INPUT GROUP — side separator helpers
   ============================================================ */

.input-group__addon--left  { border-right: var(--border-width) solid var(--form-border); }
.input-group__addon--right { border-left:  var(--border-width) solid var(--form-border); }


/* ============================================================
   TOOL CARD
   Step-numbered card for multi-step workflow tooling (Palantír R&D Desk).
   Asymmetric left border echoes the button/input corner language.
   Step badge: primary as border accent; white bg + dark text passes WCAG
   (primary fill alone fails AA at 4.22:1 — see brief WCAG section).
   ============================================================ */

.tool-card {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-left-width: var(--border-width-edge);   /* 4px — asymmetric, matches button language */
  border-left-color: var(--color-primary);        /* Heritage brand accent */
  padding: var(--space-6);
  border-radius: var(--radius-none);
}

.tool-card__header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.tool-card__step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  min-width: 1.5rem;
  background: var(--color-surface);
  border: var(--border-width-strong) solid var(--color-primary);   /* brand accent border */
  color: var(--color-text);                                         /* #393939 on white = 8.57:1 ✓ AAA */
  font-size: var(--text-sm);
  font-weight: var(--font-weight-600-bold);
  font-family: var(--font-family-sans);
  line-height: 1;
  border-radius: var(--radius-none);
  flex-shrink: 0;
}

.tool-card__title {
  font-family: var(--font-family-sans);
  font-size: var(--text-h5);
  font-weight: var(--font-weight-600-bold);
  line-height: var(--line-height-h5);
  color: var(--color-text);
  margin: 0;
}

.tool-card__desc {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-400-normal);
  color: var(--color-text-muted);
  line-height: var(--line-height-body);
  margin: 0 0 var(--space-4) 0;
}


/* ============================================================
   TOOLTIP
   CSS-only. Add data-tooltip="Your text" to any element.
   Text only — pseudo-elements cannot contain HTML.
   Default position: centred above the element.
   Modifier .tooltip--below: centred below.
   Appears on :hover and :focus-visible (keyboard accessible).

   Text convention — Chicago Title Case:
   Capitalise the first and last word, and all major words
   (nouns, verbs, adjectives, adverbs). Do NOT capitalise
   articles (a, an, the), coordinating conjunctions (and, but,
   or), or prepositions (in, on, to, of, at) unless first/last.
   Example: "Opens in a New Tab" ✓  not  "Opens In A New Tab" ✗
   Do not use text-transform: capitalize — it cannot apply
   Chicago rules and would capitalise every word.
   ============================================================ */

[data-tooltip] {
  position: relative;
}

[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + var(--space-2));
  left: 50%;
  transform: translateX(-50%) translateY(var(--space-1));

  font-family: var(--font-family-sans);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-600-bold); /* Chicago-style UI text — weight 600 */
  line-height: 1.4;
  white-space: nowrap;
  color: var(--color-surface);          /* #ffffff on #121212 = 17.9:1 ✓ AAA */
  background: var(--color-dark);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-none);

  opacity: 0;
  pointer-events: none;
  z-index: 1000;
  transition: opacity var(--transition-base),
              transform var(--transition-base);
}

[data-tooltip]:hover::after,
[data-tooltip]:focus-visible::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Below variant */
[data-tooltip].tooltip--below::after {
  bottom: auto;
  top: calc(100% + var(--space-2));
  transform: translateX(-50%) translateY(calc(-1 * var(--space-1)));
}

[data-tooltip].tooltip--below:hover::after,
[data-tooltip].tooltip--below:focus-visible::after {
  transform: translateX(-50%) translateY(0);
}


/* ============================================================
   CHIPS
   Three functional scales: Taxonomy · Status · Breadcrumb.
   All chips: border-radius: 0 — sharp corners, deliberate choice for this component.
   Padding in em so each scale stays proportional to its own font size.
   ============================================================ */

.chip {
  display: inline-flex;
  align-items: center;
  column-gap: 0.2em;  /* restores space between <strong> label and value text — whitespace collapses in flex */
  line-height: 1;
  white-space: nowrap;
  border-width: var(--border-width);
  border-style: solid;
  padding: 0.25em 0.5em;
  font-family: var(--font-family-sans);
  border-radius: var(--radius-none);
}

/* Taxonomy — --text-xxs (7px) · weight 400
   POI functional categories, content tags, interest filters.
   Maximum density — never interactive standalone. */
.chip--taxonomy {
  font-size: var(--text-xxs);
  font-weight: var(--font-weight-400-normal);
  background: var(--color-surface-page);  /* #f5f5f5 */
  border-color: var(--color-border);       /* #d7d7d7 */
  color: var(--color-dark);               /* #121212 — 17.9:1 ✓ AAA */
}

/* Status — --text-xs (9px) · weight 600
   Booking states, content lifecycle, availability.
   Weight 600 holds legibility at 9px. */
.chip--status {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-600-bold);
}

.chip--status-active {
  background: var(--color-success-l2);    /* #b0ffb0 */
  border-color: var(--color-success-d1);  /* #398839 */
  color: var(--color-success-d2);         /* #126112 on #b0ffb0 ✓ AA */
}

.chip--status-pending {
  background: var(--color-warning-l2);    /* #ffd7b0 */
  border-color: var(--color-warning-d1);  /* #886139 */
  color: var(--color-warning-d2);         /* #613912 on #ffd7b0 ✓ AA */
}

.chip--status-cancelled {
  background: var(--color-error-l3);      /* #ffb0b0 — shifted one step: error ramp is offset vs success/warning */
  border-color: var(--color-error);       /* #883939 — semantic base, proportional to d1 in other ramps */
  color: var(--color-error-d1);           /* #611212 on #ffb0b0 = 7.44:1 ✓ AAA */
}

/* Breadcrumb — --text-sm (12px) · weight 400 (current item: 600)
   Page-level wayfinding and POI location hierarchy. */
.chip--breadcrumb {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-400-normal);
  background: var(--color-surface);  /* #ffffff — raised above page bg */
  border-color: var(--color-border); /* #d7d7d7 */
  color: var(--color-text);
}

.chip--breadcrumb-current {
  border-color: var(--color-border); /* #d7d7d7 — uniform border; weight 600 carries the distinction */
  color: var(--color-text);
  font-weight: var(--font-weight-600-bold);
}

/* Breadcrumb trail: centred chip wayfinding. Each crumb reuses
   .chip--breadcrumb (12px); the current page carries
   .chip--breadcrumb-current (weight 600, not a link). Separators are .sep
   (a › glyph). The flex gap is --space-1 (4px), tighter than the staging
   8px, so the arrows sit close to the chips and the row reads as one compact
   trail. Chip links suppress the global two-layer underline and gain a quiet
   border-darken hover. Promoted from the Mírdain chrome. Matt 14 Jun 2026. */
.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
}

.breadcrumb a.chip {
  text-decoration: none;
  background-image: none;
  padding-bottom: 0;
}

.breadcrumb a.chip:hover,
.breadcrumb a.chip:focus-visible {
  border-color: var(--color-text-muted);
  color: var(--color-text);
}

.breadcrumb .sep {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  line-height: 1.4;
}

/* Metadata — --text-sm (12px) · weight 400
   Secondary factual info: dates, durations, counts, attribution.
   Page-fill bg matches taxonomy — both are neutral read-only data.
   #393939 on #f5f5f5 = 9.74:1 ✓ AAA. */
.chip--meta {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-400-normal);
  background: var(--color-surface-page);  /* #f5f5f5 — same as taxonomy */
  border-color: var(--color-border);       /* #d7d7d7 */
  color: var(--color-text);               /* #393939 — 9.74:1 ✓ AAA */
}

/* Metadata inverse — version badges, build stamps, strong UI labels.
   Reversed contrast: dark bg, light text.
   #ebebeb on #393939 = 9.07:1 ✓ AAA. */
.chip--meta-inverse {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-400-normal);
  background: var(--color-text);          /* #393939 */
  border-color: var(--color-border);       /* #d7d7d7 */
  color: var(--color-surface-muted);      /* #ebebeb — 9.07:1 ✓ AAA */
}

/* Label — --text-sm (12px) · weight 600
   Spec annotation and design-system labelling. Distinct from breadcrumb
   (navigation context) and meta (quantitative read-only data). Use for
   font names, component names, and system-level identifiers in docs.
   #393939 on #ffffff = 16.1:1 ✓ AAA. */
.chip--label {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-600-bold);
  background: var(--color-surface);        /* #ffffff */
  border-color: var(--color-border);       /* #d7d7d7 */
  color: var(--color-text);               /* #393939 — 16.1:1 ✓ AAA */
}

/* Chip layout helpers — row of chips with wrapping and separator.
   .chip-row wraps chips in a flex row with standard gap.
   .chip-sep is a muted visual divider between chip groups. */
.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
}

.chip-sep {
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
  line-height: 1;
  user-select: none;
}

/* ============================================================
   Callouts — Panel Notes and Alert Boxes
   ============================================================ */

/* Panel note — editorial callout with left-border accent.
   Use for contextual notes, explanatory asides, or any inline
   annotation that should be visually separated from body content. */
.panel-note {
  margin-top: var(--space-6);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface-page);
  border-left: var(--space-1) solid var(--color-border);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  line-height: 1.7;
}

.panel-note strong {
  color: var(--color-text);
  font-weight: 600;
}

.panel-note code {
  font-family: monospace;
  background: var(--color-surface-muted);
  padding: 0 var(--space-1);
  font-size: 11px;
}

.panel-note p {
  margin: 0 0 var(--space-2);
}

.panel-note p:last-child {
  margin-bottom: 0;
}

/* Alert box — four semantic variants (error, warning, success, info).
   Compose with a type modifier: .alert--error, .alert--warning,
   .alert--success, .alert--info. Add .alert--tinted for shaded
   background. Uses currentColor for border so type modifier drives
   both text and border in one declaration. */
.alert {
  display: block;
  max-width: fit-content;
  margin: var(--space-4) auto;
  padding: var(--space-2) var(--space-4);
  background: var(--color-surface-muted);
  border: var(--border-width) solid currentColor;
  border-left-width: var(--space-1);
  border-radius: 0 calc(var(--space-2) + 0.6rem) 0 0;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-600-bold);
  text-align: center;
  box-shadow: 0.25rem 0.25rem 1rem -0.5rem currentColor; /* matches border/text colour per variant */
}

/* Type modifiers — set text + border colour */
.alert--error   { color: var(--color-error); }           /* #883939 — 5.9:1 ✓ AA on #ebebeb */
.alert--warning { color: var(--color-warning-d1); }      /* #886139 — 5.5:1 ✓ AA on #ebebeb */
.alert--success { color: var(--color-success-d1); }      /* #398839 — approx 5:1 ✓ AA on #ebebeb */
.alert--info    { color: var(--color-focus-d1); }        /* #396188 — approx 5:1 ✓ AA on #ebebeb */

/* Tinted variant — shifts background; darkens text for contrast on tint */
.alert--error.alert--tinted   { background: var(--color-error-l3);   color: var(--color-error-d1); }    /* #611212 on #ffb0b0 = 7.44:1 ✓ AAA */
.alert--warning.alert--tinted { background: var(--color-warning-l2); color: var(--color-warning-d2); }  /* #613912 on #ffd7b0 ✓ AA  */
.alert--success.alert--tinted { background: var(--color-success-l2); color: var(--color-success-d2); }  /* #126112 on #b0ffb0 = 7.63:1 ✓ AAA */
.alert--info.alert--tinted    { background: var(--color-focus-l2);   color: var(--color-focus-d2); }    /* #123961 on #b0d7ff ✓ AA  */


/* ============================================================
   BLOCKQUOTE
   Editorial pull-quote and guest testimonial.
   Brand-colour left rule (--border-width-edge, 4px) with
   radius-none — the same left-border accent language as
   .tool-card. Two accent tiers:
     Base               — primary (#b06161) for editorial pull-quotes
     .blockquote--guest — focus (#6188b0) for guest testimonials
   Quote text:  Cormorant Garamond italic, weight 300.
   Attribution: Outfit, normal weight, muted colour.
   ============================================================ */

.blockquote {
  margin: var(--space-8) 0;
  padding: var(--space-4) var(--space-6);
  border-left: var(--border-width-edge) solid var(--color-primary);   /* 4px — brand accent */
  border-radius: var(--radius-none);
  background: transparent;
}

.blockquote__text {
  font-family: var(--font-family-display);      /* Cormorant Garamond */
  font-size: var(--text-h4);
  font-style: italic;
  font-weight: 300;
  line-height: 1.5;
  color: var(--color-text);
  margin: 0 0 var(--space-3);
}

.blockquote__cite {
  display: block;
  font-family: var(--font-family-sans);         /* DM Sans */
  font-size: var(--text-sm);
  font-style: normal;
  font-weight: var(--font-weight-500-medium);
  color: var(--color-text-muted);
}

.blockquote--tinted {
  background: var(--color-surface-page);        /* #f5f5f5 — subtle warmth */
}

.blockquote--guest {
  border-left-color: var(--color-focus);        /* #6188b0 — guest testimonial tier */
}

/* PANEL NOTE — brand modifier */
.panel-note--brand {
  border-left-color: var(--color-primary);      /* #b06161 — Heritage brand accent */
}


/* ============================================================
   SITE HEADER
   Reusable contract for the global WordPress header. The Xpro
   header template applies these classes to stable Elementor
   elements, while the scoped selectors below keep the current
   dev header governed by CelebrimborCSS.
   ============================================================ */

.elementor-location-header,
.elementor-5794,
.elementor-5794 :is(.e-con, .e-con-inner),
.elementor-5794 .elementor-element.elementor-element-5d47ca2,
.elementor-5794 .elementor-element.elementor-element-5d47ca2 > .e-con-inner {
  background: transparent;
  background-color: transparent;
}

.elementor-location-header {
  margin-bottom: calc(0px - var(--border-width));
}

.elementor-location-header + :is(main, .site-main, #content, .elementor-location-single, .elementor-location-archive, .elementor) {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

/* ============================================================
   WORDPRESS NATIVE HEADER  —  Xpro / Elementor template 5794
   ------------------------------------------------------------
   This skins the LIVE WordPress header: the native Xpro Menu
   widget + native Button + wordmark snippet in template 5794, via
   .mybcn-header-glass / .mybcn-header-cta / .mybcn-wordmark plus
   the .mybcn-site-header* rules below. Decision (Matt, 25 Jun
   2026): the WordPress surface stays 100% native widgets; the
   semantic .site-header system further down is the staging / mock
   canon and is NOT used on WordPress. Do not delete.
   ============================================================ */
.mybcn-site-header,
.elementor-5794 .elementor-element.elementor-element-b9cf336,
.elementor-5794 .elementor-element.elementor-element-b9cf336.mybcn-site-header {
  width: min(calc(100% - (var(--space-8) * 2)), var(--grid-max-width));
  min-height: auto;
  margin: 0 auto;
  padding: var(--space-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: nowrap;
  background: var(--color-surface-page);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-none);
  box-shadow: var(--shadow-1);
  box-sizing: border-box;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.mybcn-site-header__logo,
.elementor-5794 .elementor-element.elementor-element-1dabd8f,
.elementor-5794 .elementor-element.elementor-element-1dabd8f.mybcn-site-header__logo {
  flex: 0 0 auto;
  width: auto;
  min-width: 0;
  margin: 0;
  padding: 0;
}

.mybcn-site-header__logo .elementor-widget-container,
.mybcn-site-header__logo .elementor-icon-wrapper,
.elementor-5794 .elementor-element.elementor-element-1dabd8f .elementor-widget-container,
.elementor-5794 .elementor-element.elementor-element-1dabd8f .elementor-icon-wrapper {
  display: flex;
  width: auto;
  margin: 0;
  padding: 0;
}

.mybcn-site-header__logo .elementor-icon,
.elementor-5794 .elementor-element.elementor-element-1dabd8f .elementor-icon {
  display: flex;
  font-size: 2.5rem;
  padding: 0;
}

.mybcn-site-header__menu,
.elementor-5794 .elementor-element.elementor-element-023a5b5,
.elementor-5794 .elementor-element.elementor-element-023a5b5.mybcn-site-header__menu {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  justify-content: center;
}

.mybcn-site-header__menu .xpro-elementor-horizontal-navbar-nav,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: nowrap;
  gap: var(--space-2);
}

.mybcn-site-header__menu .xpro-elementor-horizontal-navbar-nav > li,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar-nav > li {
  flex: 0 0 auto;
  white-space: nowrap;
}

.mybcn-site-header__cta,
.elementor-5794 .elementor-element.elementor-element-5a62caa,
.elementor-5794 .elementor-element.elementor-element-5a62caa.mybcn-site-header__cta {
  flex: 0 0 auto;
  margin-left: var(--space-2);
  margin-top: 0;
  margin-right: 0;
  margin-bottom: 0;
}

.mybcn-site-header__cta .eac-modal-box,
.mybcn-site-header__cta .mb-modalbox__wrapper,
.mybcn-site-header__cta .eac-accessible-link,
.elementor-5794 .elementor-element.elementor-element-5a62caa .eac-modal-box,
.elementor-5794 .elementor-element.elementor-element-5a62caa .mb-modalbox__wrapper,
.elementor-5794 .elementor-element.elementor-element-5a62caa .eac-accessible-link {
  margin: 0;
  padding: 0;
}

.mybcn-site-header__menu .xpro-elementor-horizontal-navbar-nav > li > a,
.mybcn-site-header__menu .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li > a,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar-nav > li > a,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li > a {
  font-family: "DM Sans (Prose/UI)", var(--font-family-sans, "DM Sans", system-ui, sans-serif);
  font-size: var(--text-base);
  line-height: 1;
  color: var(--color-text-muted);
  text-decoration: none;
  background-image: linear-gradient(var(--color-focus-d1), var(--color-focus-d1));
  background-repeat: no-repeat;
  background-position: center bottom;
  background-size: 0% 1px;
  padding: var(--space-2) var(--space-2) calc(0.5rem + 1px);
  white-space: nowrap;
  transition: color var(--transition-base);
}

.mybcn-site-header__menu .xpro-elementor-horizontal-navbar-nav > li > a:hover,
.mybcn-site-header__menu .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li > a:hover,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar-nav > li > a:hover,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li > a:hover {
  color: var(--color-focus);
  background-size: 100% 1px;
}

.mybcn-site-header__menu .xpro-elementor-horizontal-navbar-nav > li.current-menu-item > a,
.mybcn-site-header__menu .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li.current-menu-item > a,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar-nav > li.current-menu-item > a,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li.current-menu-item > a {
  color: var(--color-focus);
  background-size: 0% 1px;
}

/* Desktop dropdown presentation only. MUST stay scoped to min-width:1025px:
   below the Xpro off-canvas breakpoint the menu is a vertical accordion, and
   position:absolute here lifts the nested lists out of flow so a level-3 list
   overlays its parent row and its toggle arrow (the third level cannot be
   closed). Scoped 27 Jun 2026 after live-verifying that Xpro's own responsive
   rule correctly sets the off-canvas dropdown to position:relative; this block
   was overriding it (specificity ~0,5,0, no media guard). This retires the
   bridge v1.26 position:static patch. */
@media (min-width: 1025px) {
  .mybcn-site-header__menu .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu,
  .elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu {
    position: absolute;
    background-color: var(--color-surface-page);
    border: var(--border-width) solid var(--color-border);
    box-shadow: var(--shadow-1);
    padding: var(--space-2) 0;
    width: min(24rem, calc(100vw - var(--space-8)));
    animation: mybcn-header-dropdown-in 160ms var(--easing-smooth, ease-out) both;
    transform-origin: top center;
  }
}

.mybcn-site-header__menu .xpro-elementor-horizontal-navbar-nav > li > .xpro-elementor-dropdown-menu,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar-nav > li > .xpro-elementor-dropdown-menu {
  margin-top: var(--space-2);
}

.mybcn-site-header__menu .xpro-elementor-horizontal-navbar-nav > li > .xpro-elementor-dropdown-menu::before,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar-nav > li > .xpro-elementor-dropdown-menu::before {
  content: "";
  position: absolute;
  inset-block-start: calc(var(--space-2) * -1);
  inset-inline: 0;
  height: var(--space-2);
}

.mybcn-site-header__menu .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu .xpro-elementor-dropdown-menu,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu .xpro-elementor-dropdown-menu {
  margin-left: 0;
  transform-origin: left top;
}

.mybcn-site-header__menu .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li > a,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li > a {
  background-color: var(--color-surface-page);
  color: var(--color-text-muted);
  font-family: var(--font-family-sans);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  line-height: 1.35;
  min-width: 0;
  padding: var(--space-2) var(--space-3);
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: normal;
  background-image: none;
}

.mybcn-site-header__menu .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li > a :is(.xpro-dropdown-menu-toggle, .xpro-submenu-icon, .xpro-menu-icon, .sub-arrow, i, svg),
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li > a :is(.xpro-dropdown-menu-toggle, .xpro-submenu-icon, .xpro-menu-icon, .sub-arrow, i, svg) {
  display: inline-flex;
  align-self: center;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  margin-left: auto;
  line-height: 1;
}

.mybcn-site-header__menu .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li > a:hover,
.elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-horizontal-navbar .xpro-elementor-dropdown-menu > li > a:hover {
  color: var(--color-focus);
  background-image: none;
  background-size: 0% 1px;
}

@keyframes mybcn-header-dropdown-in {
  from {
    opacity: 0;
    transform: translateY(calc(var(--space-1) * -1));
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.mybcn-site-header__cta .mb-modalbox__wrapper-trigger,
.mybcn-site-header__cta .mb-modalbox__wrapper-btn,
.elementor-5794 .elementor-element.elementor-element-5a62caa .mb-modalbox__wrapper-trigger,
.elementor-5794 .elementor-element.elementor-element-5a62caa .mb-modalbox__wrapper-btn {
  width: auto;
  min-width: 0;
  white-space: nowrap;
  font-family: var(--font-family-sans);
  font-size: var(--text-base);
  line-height: 1;
  color: var(--cta-text);
  background: var(--cta-bg);
  border-color: var(--cta-border);
  border-width: var(--border-width) var(--border-width-strong) var(--border-width-strong) var(--border-width);
  border-style: solid;
  border-radius: var(--btn-arch-depth) var(--space-4) var(--space-4) 0;
  padding: var(--space-6) var(--space-8);
  padding-inline: var(--space-8) var(--space-3);
  box-shadow: none;
  background-image: none;
  text-decoration: none;
}

.mybcn-site-header__cta .mb-modalbox__wrapper-trigger:hover,
.mybcn-site-header__cta .mb-modalbox__wrapper-btn:hover,
.elementor-5794 .elementor-element.elementor-element-5a62caa .mb-modalbox__wrapper-trigger:hover,
.elementor-5794 .elementor-element.elementor-element-5a62caa .mb-modalbox__wrapper-btn:hover {
  color: var(--cta-hover-text);
  background: var(--cta-hover-bg);
  background-image: none;
  text-decoration: none;
}

.mybcn-site-header__cta .eac-accessible-link,
.mybcn-site-header__cta .eac-accessible-link:hover,
.mybcn-site-header__cta .eac-accessible-link:active,
.mybcn-site-header__cta .eac-accessible-link:visited,
.elementor-5794 .elementor-element.elementor-element-5a62caa .eac-accessible-link,
.elementor-5794 .elementor-element.elementor-element-5a62caa .eac-accessible-link:hover,
.elementor-5794 .elementor-element.elementor-element-5a62caa .eac-accessible-link:active,
.elementor-5794 .elementor-element.elementor-element-5a62caa .eac-accessible-link:visited {
  background-image: none;
  text-decoration: none;
  padding-bottom: 0;
}

@media (max-width: 61.25rem) {  /* --bp-lg (980px) */
  .mybcn-site-header,
  .elementor-5794 .elementor-element.elementor-element-b9cf336,
  .elementor-5794 .elementor-element.elementor-element-b9cf336.mybcn-site-header {
    width: calc(100vw - var(--space-4)) !important;
    max-width: calc(100vw - var(--space-4)) !important;
    margin-top: 0 !important;
    margin-inline: auto !important;
    padding: var(--space-2) var(--space-3);
    gap: var(--space-2);
    border-width: 0 0 var(--border-width);
    background: var(--color-surface-page);
  }

  .mybcn-site-header__logo,
  .elementor-5794 .elementor-element.elementor-element-1dabd8f,
  .elementor-5794 .elementor-element.elementor-element-1dabd8f.mybcn-site-header__logo {
    display: none;
  }

  .mybcn-site-header__menu,
  .elementor-5794 .elementor-element.elementor-element-023a5b5,
  .elementor-5794 .elementor-element.elementor-element-023a5b5.mybcn-site-header__menu {
    flex: 0 0 2.5rem !important;
    width: 2.5rem !important;
    max-width: 2.5rem !important;
  }

  .mybcn-site-header__menu .xpro-elementor-menu-toggle,
  .elementor-5794 .elementor-element.elementor-element-023a5b5 .xpro-elementor-menu-toggle {
    color: var(--color-focus);
  }

  .mybcn-site-header__cta,
  .elementor-5794 .elementor-element.elementor-element-5a62caa,
  .elementor-5794 .elementor-element.elementor-element-5a62caa.mybcn-site-header__cta {
    flex: 0 1 auto !important;
    width: auto !important;
    margin-left: auto !important;
    margin-top: 0 !important;
    margin-right: 0 !important;
    margin-bottom: 0 !important;
    max-width: calc(100vw - 7rem) !important;
  }

  .mybcn-site-header__cta .eac-modal-box,
  .mybcn-site-header__cta .mb-modalbox__wrapper,
  .mybcn-site-header__cta .eac-accessible-link,
  .elementor-5794 .elementor-element.elementor-element-5a62caa .eac-modal-box,
  .elementor-5794 .elementor-element.elementor-element-5a62caa .mb-modalbox__wrapper,
  .elementor-5794 .elementor-element.elementor-element-5a62caa .eac-accessible-link {
    display: block;
    max-width: 100%;
  }

  .mybcn-site-header__cta .mb-modalbox__wrapper-trigger,
  .mybcn-site-header__cta .mb-modalbox__wrapper-btn,
  .elementor-5794 .elementor-element.elementor-element-5a62caa .mb-modalbox__wrapper-trigger,
  .elementor-5794 .elementor-element.elementor-element-5a62caa .mb-modalbox__wrapper-btn {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: var(--space-6) var(--space-8);
    padding-inline: var(--space-8) var(--space-3);
  }
}

/* Floating detached variant — taste-skill trial T1 keep
   (Matt, 05 Jun 2026). Adds stickiness, a small viewport
   offset, translucency, and backdrop blur to the standard
   header. Blur sits on a sticky element only, never on
   scrolling content. Square corners and tokens unchanged. */
.mybcn-site-header--float {
  position: sticky;
  top: var(--space-4);
  z-index: 100; /* below tooltip (1000), above page content */
  background: rgba(255, 255, 255, 0.82);
  -webkit-backdrop-filter: blur(1rem); /* 16px, on the 8px grid (Matt, 06 Jun 2026) */
  backdrop-filter: blur(1rem);
}

/* ------------------------------------------------------------
   CF-71 move (25 Jun 2026, Matt / Claude): the header glass and
   the Book Your Tour CTA polish were lifted out of the inline
   "Header Polish CSS" HTML widget (8dd27b5f) in template 5794
   and tokenised here. Applied through the Elementor CSS Classes
   field: .mybcn-header-glass on the header container (b9cf336),
   .mybcn-header-cta on the CTA button (afcbd8ec). !important is
   needed to beat Elementor's per-element generated rules, which
   sit at equal specificity but load after this file.

   UPDATE (26 Jun 2026): Matt moved the header to native-widget
   styling bound to kit globals. .mybcn-header-glass is RETIRED
   (the class was removed from container b9cf336, so the rules
   below no longer apply); kept here for recoverability and the
   CF-71 note. .mybcn-header-cta is reduced to the hover lift only,
   see below.
   ------------------------------------------------------------ */

/* LEGACY / RETIRED 26 Jun 2026: class no longer on the header
   container. Do not re-add without re-checking the CF-71 mobile
   off-canvas containing-block issue described below. */
.mybcn-header-glass {
  /* Glass via a pseudo-layer, NOT backdrop-filter on the container
     itself: a filtered ancestor becomes the containing block for the
     Xpro mobile menu's position:fixed off-canvas panel (push-left),
     which clamped it into the header box so a sliver + the close (X)
     leaked on screen when closed. isolation:isolate gives the pseudo
     a stacking context without creating a fixed-position containing
     block. (CF-71 mobile fix, Matt, 25 Jun 2026.) */
  position: relative !important;
  isolation: isolate;
  background-color: transparent !important;
}
.mybcn-header-glass::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: rgba(255, 255, 255, 0.82);
  -webkit-backdrop-filter: blur(var(--space-4)); /* 16px */
  backdrop-filter: blur(var(--space-4));
  pointer-events: none;
}

/* .mybcn-header-cta — "Book Your Tour" CTA in header 5794.
   Reconciled 26 Jun 2026 (Matt / Claude): shape, padding, colours and
   base shadow are now OWNED by the Xpro button widget settings (bound to
   kit globals: secondary fill, mybcn_tint_cream text, mybcn_terracotta_d1
   hover, em arch radius). This class keeps ONLY the hover micro-interaction
   the widget cannot express: a 1px lift and a deeper shadow. The previous
   full-polish block (radius / padding / font-size / base shadow with
   !important) overrode and dead-ended those widget settings. */
.mybcn-header-cta .elementor-button,
.mybcn-header-cta a.elementor-button {
  background-image: none; /* block the global a gradient underline (v3.104) */
  transition: transform .2s ease, box-shadow .2s ease !important;
}

.mybcn-header-cta .elementor-button:hover,
.mybcn-header-cta a.elementor-button:hover {
  transform: translateY(-1px);
  box-shadow: 4px 8px 20px -8px rgba(0, 0, 0, 0.8) !important;
  background-image: none; /* a:hover repaints the blue underline (v3.104) */
}

/* Wordmark (25 Jun 2026, Matt / Claude): lifted out of the
   inline style on the logo <a> in the HTML widget (8079d731) in
   template 5794 into a class. Mirrors the canonical .site-header
   .wordmark, but keeps the 17px optical logo size (canon snaps to
   --text-base); the legacy header keeps 17px until the rebuild. */
.mybcn-wordmark {
  display: inline-block;
  font-family: var(--font-family-wordmark); /* Urbanist (my 300 / BCN 700) */
  font-weight: 300;
  font-size: 1.0625rem; /* 17px optical logo size */
  line-height: 1.05;
  letter-spacing: 0.04em;
  color: var(--color-dark);
  text-decoration: none;
}

.mybcn-wordmark b {
  display: block;
  font-weight: 700;
  color: var(--color-primary); /* #b06161 */
}


/* ============================================================
   CANONICAL 2.0 SITE HEADER  —  semantic .site-header system
   ------------------------------------------------------------
   Decision A (Matt, 14 Jun 2026, header sub-menu pass): the
   semantic .site-header system is the canonical myBCN 2.0 header.
   This is the STAGING / mock canon (Vercel). It is NOT used on the
   WordPress surface: the live WordPress header is the native Xpro
   block above (template 5794). The HTML-widget port of this system
   was abandoned for a 100% native build (Matt, 25 Jun 2026).

   Promoted from the Home 2026 mock header + sub-menu, tokenised
   per celebrimbor-px-to-token-map.md (D1-D8 round-up, Finding C
   colour names). The staging mock stays in px (staging track);
   this is the tokenised canon. This block now carries the full
   header: the bar, the desktop nav, the desktop sub-menu dropdown,
   the mobile sub-menu accordion, and (added v3.88, CF-71) the
   hamburger toggle and the mobile drawer shell.
   See celebrimbor-header-sub-menu-pass-handover.md.
   ============================================================ */

/* Fixed, not sticky: the full-width glass bar floats over the hero on
   load and stays pinned on scroll. (Staging default, suits the
   full-bleed hero.) The glass (translucent tint + 1rem backdrop blur)
   is painted edge-to-edge on the wrap, so it spans the whole viewport;
   the inner .site-header is just the centred content row. Always-on
   glass, no border or shadow divider (Matt, 25 Jun 2026). */
.site-header-wrap {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.82); /* intentional translucent fill */
  -webkit-backdrop-filter: blur(1rem);   /* 16px, on the 8px grid */
  backdrop-filter: blur(1rem);
}
/* WordPress surface modifier (CF-71, Matt 25 Jun 2026; SUPERSEDED 26 Jun
   2026, Matt): the 25 Jun stance was that on the live site the bar sits in
   normal flow and sticks on scroll instead of overlaying, because the
   WordPress pages had no top compensation for a fixed bar. Reversed 26 Jun:
   the live Xpro header now floats over page content on every page, applied
   in the bridge (v1.16, header.xpro-theme-builder-header position:absolute),
   not here. This .site-header-wrap--sticky modifier belongs to the staging
   .site-header mock system and is unused on the native Xpro WordPress
   header; kept for the mock. */
.site-header-wrap.site-header-wrap--sticky {
  position: static; /* staging mock only; the live WordPress overlap is now in the bridge (v1.16). */
}
/* The content row: centred to the page grid, no skin of its own.
   The glass now lives on .site-header-wrap (full-bleed). */
.site-header {
  max-width: var(--grid-max-width);
  margin: 0 auto;
  padding: var(--space-4) var(--space-6);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
}
.site-header .wordmark {
  font-family: var(--font-family-wordmark); /* wordmark: Urbanist (my 300 / BCN 700) */
  font-weight: 300;
  font-size: var(--text-base); /* 17px snapped to 16, D1 */
  line-height: 1.05;
  letter-spacing: 0.04em;
  color: var(--color-dark);
  text-decoration: none;
  flex: 0 0 auto;
}
.site-header .wordmark b {
  display: block;
  font-weight: 700;
  color: var(--color-primary); /* was staging --color-terracotta, same hex */
}
.site-header nav {
  flex: 1 1 auto;
  display: flex;
  justify-content: center;
  gap: clamp(var(--space-4), 2.5vw, var(--space-9));
}
.site-header nav a {
  font-size: var(--text-base); /* 15px snapped to 16, D1 */
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--color-text);
  text-decoration: none;
  padding-bottom: var(--space-1);
  border-bottom: var(--border-width) solid transparent;
}
.site-header nav a:hover,
.site-header nav a:focus-visible,
.site-header nav a[aria-current="page"] {
  color: var(--color-dark);
  border-bottom-color: var(--color-dark);
}
/* Header booking button uses the .btn--cta .btn--sm system, which
   owns the Option D optical padding (D2). The header only resets
   the button's top margin. */
.site-header .cta { margin-top: 0; }

/* Hamburger toggle: hidden on desktop, shown under --bp-lg where the
   mobile drawer takes over. Small-control geometry kept raw. */
.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px; /* raw control geometry */
  background: none;
  border: 0;
  padding: var(--space-1) 2px;
  cursor: pointer;
}
.nav-toggle span {
  display: block;
  width: 22px; /* raw bar geometry */
  height: 2px;
  background: var(--color-dark);
}

/* Desktop sub-menu (e.g. FAQ under About): a hover / focus dropdown.
   Keyboard reachable via :focus-within; the trigger is a real link.
   Hidden under --bp-lg (980px), where the mobile drawer takes over. */
.site-header .nav-item { position: relative; display: inline-flex; align-items: center; }
.site-header .nav-item.has-submenu > a::after { content: " \25BE"; font-size: 0.7em; opacity: 0.7; }
.site-header .submenu {
  position: absolute; top: 100%; left: 0;
  min-width: 210px; /* intentional raw: dropdown panel min width */
  list-style: none; margin: 0; padding: var(--space-2) 0;
  background: rgba(255, 255, 255, 0.97); /* intentional translucent fill */
  -webkit-backdrop-filter: blur(1rem); backdrop-filter: blur(1rem);
  border: var(--border-width) solid var(--color-border);
  box-shadow: var(--shadow-1);
  opacity: 0; visibility: hidden; transform: translateY(var(--space-1));
  transition: opacity var(--transition-base), transform var(--transition-base), visibility var(--transition-base);
  z-index: 100;
}
/* Child combinator: a parent reveals only its own panel. */
.site-header .nav-item:hover > .submenu,
.site-header .nav-item:focus-within > .submenu { opacity: 1; visibility: visible; transform: translateY(0); }
.site-header .submenu li { margin: 0; position: relative; }
.site-header .submenu a { display: block; padding: var(--space-2) var(--space-6); white-space: nowrap; border-bottom: 0; }
.site-header .submenu a:hover,
.site-header .submenu a:focus-visible { border-bottom-color: transparent; color: var(--color-dark); background: rgba(18, 18, 18, 0.05); } /* intentional hover fill */
/* Nested flyout (level 3): a family's individual tours open to the side. */
.site-header .submenu li.has-submenu > a::after { content: " \25B8"; font-size: 0.8em; opacity: 0.7; float: right; margin-left: var(--space-4); }
.site-header .submenu .submenu { top: -9px; left: 100%; } /* -9px intentional optical offset */
.site-header .submenu li.has-submenu:hover > .submenu,
.site-header .submenu li.has-submenu:focus-within > .submenu { opacity: 1; visibility: visible; transform: translateY(0); }

/* Visible keyboard focus across the header and the mobile accordion.
   2px / 3px / 2px focus-ring geometry kept raw (Finding D); the ring
   colour is a non-text border, so --color-focus passes AA here. */
.site-header a:focus-visible,
.site-header button:focus-visible,
.mobile-menu a:focus-visible,
.mobile-menu button:focus-visible,
.m-submenu a:focus-visible,
.m-sub-toggle:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 3px;
  border-radius: 2px;
}

@media (max-width: 61.25rem) { /* --bp-lg (980px): desktop nav off, hamburger + mobile drawer take over */
  .site-header nav { display: none; }
  .nav-toggle { display: inline-flex; }
}
@media (max-width: 38.75rem) { /* --bp-sm (620px) */
  .site-header { padding: var(--space-3) var(--space-4); gap: var(--space-4); }
}

/* Mobile sub-menu accordion (inside the mobile drawer, under --bp-lg).
   Touch has no hover, so the sub-menu is an inline accordion toggled
   by .m-sub-toggle. The drawer shell and hamburger that wrap it are
   defined just below (added v3.88, CF-71). */
.m-sub-toggle {
  flex: 0 0 auto; width: 44px; height: 44px; /* 44px tap target, raw */
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 0; cursor: pointer; color: var(--color-warning-d2); /* AA on cream drawer */
}
.m-sub-toggle::before {
  content: ""; width: 11px; height: 11px; /* chevron geometry, raw */
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); transition: transform var(--transition-base);
}
.m-sub-toggle[aria-expanded="true"]::before { transform: rotate(-135deg); }
.m-submenu { list-style: none; margin: var(--space-1) 0 0; padding: 0; }
.m-submenu li a {
  display: block; padding: var(--space-2) 0 var(--space-2) var(--space-1); text-decoration: none;
  font-family: var(--font-family-display); font-weight: 300;
  font-size: clamp(1.5rem, 6vw, 2rem); line-height: 1.2;
  color: var(--color-warning-d2); /* AA on cream drawer, ~7.7:1 (was warning-d1 ~4.3:1) */
}
.m-submenu li a[aria-current="page"] { color: var(--color-primary-d1); } /* AA on cream drawer, ~6:1 (was --color-primary ~3.4:1) */
/* Nested mobile accordion: a family (Walking Tours, Private Tours...) with its own indented list. */
.m-submenu .m-group { display: flex; align-items: center; }
.m-submenu .m-group > a {
  flex: 1 1 auto; padding: var(--space-2) 0 var(--space-2) var(--space-6);
  font-family: var(--font-family-display); font-weight: 300;
  font-size: clamp(1.4rem, 6vw, 1.875rem); line-height: 1.2;
  color: var(--color-warning-d2); text-decoration: none; /* AA on cream drawer, ~7.7:1 */
}
.m-submenu .m-group > a[aria-current="page"] { color: var(--color-primary-d1); } /* AA on cream drawer, ~6:1 */
.m-branch { list-style: none; }
.m-submenu .m-submenu { margin: 0; }
.m-submenu .m-submenu li a { padding-left: var(--space-9); font-size: clamp(1.2rem, 5vw, 1.5rem); }

/* Mobile drawer shell (under --bp-lg): a full-screen cream takeover
   opened by .nav-toggle, where the desktop nav is hidden. Large
   display-font links, a close button top-right, the booking CTA at the
   foot. The panel is position:fixed and the .mobile-menu is a sibling
   of the header wrap (never a child), because the wrap's glass
   backdrop-filter (v3.94) would otherwise become the containing block
   and clamp the overlay to the header box. Promoted from the Home 2026 mock at the WP header
   rebuild (CF-71); bespoke drawer insets kept raw. */
.mobile-menu { display: none; }
@media (max-width: 61.25rem) { .mobile-menu { display: block; } }
.mobile-menu__panel {
  position: fixed; inset: 0; z-index: 120; /* above header (100), below tooltip (1000) */
  background: var(--color-tint-cream);
  display: flex; flex-direction: column;
  padding: 20px clamp(28px, 8vw, 56px) clamp(28px, 6vh, 44px); /* raw drawer insets */
  overflow-y: auto;
  opacity: 0; visibility: hidden;
  transform: translateY(calc(-1 * var(--space-2)));
  transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s ease; /* slower reveal than the desktop submenu */
}
.mobile-menu.is-open .mobile-menu__panel { opacity: 1; visibility: visible; transform: translateY(0); }
.mobile-menu__top { display: flex; align-items: center; justify-content: space-between; min-height: 44px; }
.mobile-menu__top .wordmark {
  font-family: var(--font-family-sans); font-weight: 600; font-size: 1.0625rem; /* 17px optical logo */
  letter-spacing: 0.04em; color: var(--color-dark); text-decoration: none;
}
.mobile-menu__top .wordmark b { color: var(--color-primary); }

/* Wordmark link-underline suppression, single source (v3.106).
   All three wordmark lockups (legacy .mybcn-wordmark, canonical 2.0
   .site-header .wordmark, mobile .mobile-menu__top .wordmark) kill
   the global a gradient underline and its padding-bottom gap, at
   rest and in every state, with colour pinned to ink. Each selector
   keeps its own specificity: (0,1,0)+ beats the global a (0,0,1),
   and the state selectors (0,2,0)+ beat a:hover (0,1,1), so this
   block wins from any file position. Replaces the three per-block
   resets (v3.103 rest, v3.104 states) that had to move in step. */
.mybcn-wordmark,
.site-header .wordmark,
.mobile-menu__top .wordmark {
  background-image: none;
  padding-bottom: 0;
}

.mybcn-wordmark:hover, .mybcn-wordmark:active, .mybcn-wordmark:visited,
.site-header .wordmark:hover, .site-header .wordmark:active, .site-header .wordmark:visited,
.mobile-menu__top .wordmark:hover, .mobile-menu__top .wordmark:active, .mobile-menu__top .wordmark:visited {
  color: var(--color-dark);
  background-image: none;
}
.mobile-menu__close {
  position: relative; width: 44px; height: 44px; /* 44px tap target, raw */
  background: none; border: 0; cursor: pointer; color: var(--color-dark);
}
.mobile-menu__close::before, .mobile-menu__close::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 22px; height: 2px; background: currentColor; /* raw cross geometry */
}
.mobile-menu__close::before { transform: translate(-50%, -50%) rotate(45deg); }
.mobile-menu__close::after { transform: translate(-50%, -50%) rotate(-45deg); }
.mobile-menu nav { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center; gap: 2px; } /* 2px raw */
.mobile-menu nav > a,
.mobile-menu .m-group > a {
  display: block; padding: 6px 0; text-decoration: none; /* 6px raw */
  font-family: var(--font-family-display); font-weight: 300;
  font-size: clamp(2rem, 9vw, 2.75rem); line-height: 1.18;
  color: var(--color-dark);
}
.mobile-menu nav > a[aria-current="page"],
.mobile-menu .m-group > a[aria-current="page"] { color: var(--color-primary-d1); }
.mobile-menu .m-group { display: flex; align-items: center; gap: var(--space-2); }
.mobile-menu .m-group > a { flex: 0 0 auto; }
.mobile-menu__book { align-self: flex-start; margin-top: var(--space-6); }


/* ============================================================
   CARD BEZEL
   Taste-skill trial T3 keep (Matt, 05 Jun 2026). A card never
   sits flat on the background: an outer shell (tinted tray
   with hairline border) holds the inner core. Square corners
   throughout; the concentric-radius maths of the source
   pattern does not apply at radius zero.
   ============================================================ */

.bezel {
  background: var(--color-tint-cream);
  border: var(--border-width) solid var(--color-border);
  padding: var(--space-2);
  box-shadow: var(--shadow-1);
}

.bezel__core {
  height: 100%;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  padding: var(--space-6);
}

/* Soft-shadow variant — pairs the bezel (or any hero card)
   with --shadow-soft for a diffused float. */
.bezel--soft,
.card--soft {
  box-shadow: var(--shadow-soft);
}


/* ============================================================
   BENTO GRID
   Taste-skill trial T10 keep (Matt, 05 Jun 2026). Asymmetric
   card grid on the standard 12-column grid: one dominant cell
   spans 8 columns and 2 rows, supporting cells span 4. Tints
   and surfaces as cell backgrounds, square corners.
   Collapses: hero full-width and cells half-width below 64rem,
   single column below 48rem.
   ============================================================ */

.bento {
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), 1fr);
  grid-auto-rows: minmax(9rem, auto);
  gap: var(--grid-gap);
}

.bento__cell {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  grid-column: span 4;
  padding: var(--space-6);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  box-shadow: var(--shadow-1);
}

.bento__cell--hero {
  grid-column: span 8;
  grid-row: span 2;
  background: var(--color-tint-cream);
}

.bento__cell--tint-blush      { background: var(--color-tint-blush); }
.bento__cell--tint-stone-pink { background: var(--color-tint-stone-pink); }
.bento__cell--tint-light-cream{ background: var(--color-tint-light-cream); }

@media (max-width: 61.25rem) {  /* --bp-lg, was 64rem (1024), migrated to 980 per D7 */
  .bento__cell      { grid-column: span 6; }
  .bento__cell--hero { grid-column: span 12; }
}

@media (max-width: 38.75rem) {  /* --bp-sm (620px) */
  .bento { gap: var(--space-4); }
  .bento__cell,
  .bento__cell--hero { grid-column: span 12; }
}


/* ============================================================
   XPRO PATTERN LAB: HERO QUOTE + STEPS (dark sections)
   Scoped to copied Xpro widgets on the private pattern lab.
   These classes make Celebrimbor tokens the styling contract,
   while preserving the known-good Xpro widget JSON underneath.
   The two dark sections share one chrome (shell, sharp-corner
   cascade, display-serif heading tree); the per-section rules
   below carry only the differences: background, heading scale,
   and the quote vs step-flow content. Deduplicated v3.106 from
   two near-twin blocks that had to be edited in step; computed
   styles unchanged.
   ============================================================ */

/* Shared dark-section shell */
.mybcn-xpro-hero-quote,
.mybcn-xpro-steps-section {
  min-height: 50vh;
  padding-block: var(--section-dark-padding-block);
  padding-inline: var(--section-dark-padding-inline);
  color: var(--section-dark-text, #f5f5f5);
}

.mybcn-xpro-hero-quote {
  background: var(--section-dark-bg, #121212);
}

.mybcn-xpro-steps-section {
  background: var(--section-dark-alt-bg, #393939);  /* lighter, sits below the hero quote without flattening into it */
  gap: 0;
}

/* Sharp corners across both widget trees */
.mybcn-xpro-hero-quote,
.mybcn-xpro-hero-quote *,
.mybcn-xpro-steps-section,
.mybcn-xpro-steps-section * {
  border-radius: var(--radius-none);
}

/* Shared heading tree: full width, display serif, light weight */
.mybcn-xpro-hero-heading,
.mybcn-xpro-steps-heading {
  width: 100%;
  color: var(--section-dark-text, #f5f5f5);
}

.mybcn-xpro-hero-heading,
.mybcn-xpro-hero-heading *,
.mybcn-xpro-steps-heading,
.mybcn-xpro-steps-heading * {
  font-family: var(--font-family-display, 'Cormorant Garamond', Georgia, serif);
}

.mybcn-xpro-hero-heading :is(h1, h2, h3, h4, h5, h6, .xpro-heading-title, .xpro-advance-heading-title),
.mybcn-xpro-steps-heading :is(h1, h2, h3, h4, h5, h6, .xpro-heading-title, .xpro-advance-heading-title) {
  margin: 0;
  color: var(--section-dark-text, #f5f5f5);
  font-weight: var(--font-weight-300-light);
}

/* Heading scale is the one deliberate difference: hero h1, steps h2 */
.mybcn-xpro-hero-heading :is(h1, h2, h3, h4, h5, h6, .xpro-heading-title, .xpro-advance-heading-title) {
  font-size: var(--text-h1);
  line-height: var(--line-height-h1);
}

.mybcn-xpro-steps-heading :is(h1, h2, h3, h4, h5, h6, .xpro-heading-title, .xpro-advance-heading-title) {
  font-size: var(--text-h2);
  line-height: var(--line-height-h2);
}

/* Strong/highlight spans get the bright text plus shadow */
.mybcn-xpro-hero-heading :is(.xpro-heading-center, .xpro-center-title, .xpro-highlighted-text, strong),
.mybcn-xpro-steps-heading :is(.xpro-heading-center, .xpro-center-title, .xpro-highlighted-text, strong) {
  color: var(--section-dark-text-strong, #ffffff);
  text-shadow: var(--section-dark-text-shadow, 0.25rem 0.25rem 1rem rgba(0, 0, 0, 0.8));
}

/* Hero-quote content */
.mybcn-xpro-founder-quote {
  width: min(80%, var(--section-dark-prose-width));
  align-self: center;
  color: var(--section-dark-text, #f5f5f5);
}

.mybcn-xpro-founder-quote :is(blockquote, p, .xpro-blockquote-description, .xpro-quote-description) {
  margin: 0;
  color: var(--section-dark-text, #f5f5f5);
  font-family: var(--font-family-sans, 'DM Sans', system-ui, sans-serif);
  font-size: var(--text-h4);
  font-weight: var(--font-weight-400-normal);
  line-height: var(--line-height-body);
}

.mybcn-xpro-founder-quote :is(.xpro-blockquote-title, .xpro-quote-title, cite, .xpro-blockquote-designation, .xpro-quote-designation) {
  color: var(--section-dark-text-muted, #ebebeb);
  font-family: var(--font-family-sans, 'DM Sans', system-ui, sans-serif);
  font-size: var(--text-sm);
  line-height: var(--line-height-body);
}

.mybcn-xpro-founder-quote :is(.xpro-blockquote-title, .xpro-quote-title, cite) {
  font-weight: var(--font-weight-600-bold);
}

.mybcn-xpro-founder-quote :is(.xpro-blockquote-designation, .xpro-quote-designation) {
  color: var(--section-dark-border, #d7d7d7);
  font-weight: var(--font-weight-400-normal);
}

/* Steps content */
.mybcn-xpro-step-flow {
  color: var(--section-dark-text, #f5f5f5);
}

.mybcn-xpro-step-flow :is(.xpro-step-flow-title, .xpro-step-title, h1, h2, h3, h4, h5, h6) {
  color: var(--section-dark-text, #f5f5f5);
  font-family: var(--font-family-display, 'Cormorant Garamond', Georgia, serif);
  font-size: var(--text-h5);
  font-weight: var(--font-weight-400-normal);
  line-height: var(--line-height-h5);
}

.mybcn-xpro-step-flow :is(.xpro-step-flow-description, .xpro-step-description, p) {
  color: var(--section-dark-text, #f5f5f5);
  font-family: var(--font-family-sans, 'DM Sans', system-ui, sans-serif);
  font-size: var(--text-base);
  line-height: var(--line-height-body);
}

.mybcn-xpro-step-flow :is(.xpro-step-flow-icon, .xpro-step-icon, .xpro-icon) {
  color: var(--xpro-steps-icon-text, #616161);
  background: var(--xpro-steps-icon-bg, #ebebeb);
  border-color: var(--section-dark-border, #d7d7d7);
  box-shadow: var(--xpro-steps-shadow, 0.25rem 0.25rem 1rem -0.5rem rgba(0, 0, 0, 0.8));
}

.mybcn-xpro-step-flow :is(.xpro-step-flow-badge, .xpro-step-badge, .xpro-badge) {
  color: var(--xpro-steps-badge-text, #888888);
  background: var(--xpro-steps-badge-bg, #ebebeb);
  border-color: var(--section-dark-border, #d7d7d7);
  font-family: var(--font-family-sans, 'DM Sans', system-ui, sans-serif);
  font-size: var(--text-base);
}

.mybcn-xpro-step-flow :is(.xpro-step-flow-separator, .xpro-step-separator, .xpro-separator) {
  color: var(--section-dark-border, #d7d7d7);
  border-color: var(--section-dark-border, #d7d7d7);
}

/* Shared small-screen adjustments */
@media (max-width: 38.75rem) {  /* --bp-sm (620px) */
  .mybcn-xpro-hero-quote,
  .mybcn-xpro-steps-section {
    padding-inline: var(--space-4);
  }

  .mybcn-xpro-founder-quote,
  .mybcn-xpro-step-flow {
    width: 100%;
  }

  .mybcn-xpro-founder-quote :is(blockquote, p, .xpro-blockquote-description, .xpro-quote-description) {
    font-size: var(--text-base);
  }
}

/* ============================================================
   HOME 2026 — PROMOTED UTILITIES
   Utilities grown from the Home 2026 mock and promoted on Matt's
   calls (06 and 09 Jun 2026). Any page or Mírdain build can use
   them.
   ============================================================ */

/* Hero copy measure. Use inside the standard 12-column grid for
   page heroes: H1, subtitle and primary CTA share this measure.
   It spans the full grid row and caps the text at min(100%, 82ch)
   (30 Jun 2026, promoted from the Home 2026 mock). */
.mybcn-hero-copy {
  grid-column: 1 / -1;
  width: min(100%, 82ch);
}

.mybcn-hero-subtitle {
  max-width: none;
}

@media (max-width: 61.25rem) {  /* --bp-lg */
  .mybcn-hero-copy {
    grid-column: span 12;
  }
}

/* Hero band — featured image + gradient overlay (01 Jul 2026,
   promoted from the Home 2026 mock). The full-screen page hero: a
   featured image behind a dark or light gradient scrim, with the copy
   overlaid bottom-left. Dark is the default; add .mybcn-hero--light for
   the pale cream variant. One class swaps the scrim and the text colour
   together, via the local --hero-* custom properties.

   Markup:
     <section class="mybcn-hero">            (add --light for pale)
       <div class="mybcn-hero-bg"><picture>…<img></picture></div>
       <div class="mybcn-hero-scrim"></div>
       <div class="mybcn-hero-content grid">
         <div class="mybcn-hero-copy">
           <p class="eyebrow">…</p><h1>…</h1>
           <p class="mybcn-hero-subtitle sub">…</p> … CTA …
         </div>
       </div>
     </section>

   The image IS the LCP element: real <img> inside <picture>,
   fetchpriority="high", never lazy, AVIF/WebP + srcset, sized. See the
   Media layer and operations/seo/mybcn-image-sizing-and-delivery-standard.md. */
.mybcn-hero {
  --hero-fg:      var(--hero-fg-dark);
  --hero-eyebrow: var(--hero-eyebrow-dark);
  --hero-scrim:   var(--hero-scrim-dark);
  position: relative;
  min-height: 85svh;  /* desktop and tablet first-screen (Matt, 29 Jun 2026); svh stops the mobile address bar overflowing */
  display: flex;
  align-items: flex-end;
}
.mybcn-hero--light {
  --hero-fg:      var(--hero-fg-light);
  --hero-eyebrow: var(--hero-eyebrow-light);
  --hero-scrim:   var(--hero-scrim-light);
}
.mybcn-hero-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: #9a9a9a;  /* neutral fallback tone before the image paints */
}
.mybcn-hero-bg > img,
.mybcn-hero-bg > picture,
.mybcn-hero-bg > picture > img,
.mybcn-hero-bg > video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
.mybcn-hero-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--hero-scrim);
  pointer-events: none;
}
.mybcn-hero-content {
  position: relative;
  z-index: 2;
  width: 100%;
}
.mybcn-hero-content :is(h1, h2, .mybcn-hero-title),
.mybcn-hero-content .mybcn-hero-subtitle,
.mybcn-hero-content .sub {
  color: var(--hero-fg);
}
.mybcn-hero-content .eyebrow {
  color: var(--hero-eyebrow);
}

@media (max-width: 38.75rem) {  /* --bp-sm (620px): shorter first screen on phones */
  .mybcn-hero { min-height: 80svh; }
}

/* Sub-section label. A quiet serif heading that sits one step
   below an H2 section heading, used to split a section into
   named sub-sections (e.g. "How You Can Take a Tour" /
   "Our Walks"). Anchored to the H5 step so it reads as a label,
   not a title. */
.mybcn-subheading {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-400-normal);
  font-size: var(--text-h5);
  line-height: var(--line-height-h5);
  color: var(--color-dark);
}

/* Ticket / caveat note. A small muted line for a practical
   caveat placed near a price or product, e.g. "Guide only.
   Venue entry tickets are booked separately." */
.mybcn-ticket-note {
  font-size: var(--text-sm);
  line-height: var(--line-height-body);
  color: var(--color-text-muted);
  margin-top: var(--space-3);
}


/* ============================================================
   HOME 2026 — PROMOTED COMPONENTS (13 Jun 2026)
   Promoted from the Home 2026 mock and the Mirdain chrome into
   Celebrimbor tokens. Pixel-to-token decisions D1 to D8 and the
   Finding C colour map are recorded in
   design/celebrimbor-px-to-token-map.md (v0.3). The staging
   track wrote these in literal px; this is the tokenised
   canonical version.
   Updated 28 Jun 2026: card family (tier, type, story, and imaged
   cross-sell cards) reconciled and promoted.
   ============================================================ */


/* ------------------------------------------------------------
   CARD FAMILY (TIER, TYPE, AND STORY CARDS)
   Reconciled to one border-plus-shadow spec (28 Jun 2026).
   Hierarchy:
   - Tour/product cards (.tour-row) carry white background, border, and --shadow-soft (heaviest).
   - Cross-sell cards (.tier-card.has-media) carry white background, border, --shadow-soft on hover.
   - Base tier cards (.tier-card) sit flat on the page background (no shadow/border).
   - Format cards (.type-card) sit flat on cream (no shadow/border).
   - Stories cards (.story-card) carry white background and border (no shadow).
   ------------------------------------------------------------ */

.tier-card {
  background: var(--color-surface-page);   /* page bg neutral */
  padding: var(--space-9) var(--space-8) var(--space-8);
  display: flex;
  flex-direction: column;
  height: 100%;
  position: relative;
  overflow: hidden;
}

.tier-card .text-link {
  --text-link-surface: var(--color-surface-page);
  --text-link-shadow-dark: var(--color-border);
  --text-link-shadow-light: var(--color-surface);
  margin-top: auto;
}

.tier-card .card-num {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-family-display);
  font-weight: 600;
  font-size: clamp(110px, 12vw, 160px);
  line-height: 1;
  color: var(--color-warning);
  opacity: 0.1;
  z-index: 0;
  pointer-events: none;
}

.tier-card h3,
.tier-card p,
.tier-card .text-link {
  position: relative;
  z-index: 1;
}

.tier-card h3 {
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.3;
  color: var(--color-dark);
  margin-top: var(--space-4);
}

.tier-card p {
  font-size: 0.9375rem;
  color: var(--color-text-muted);
  margin: var(--space-2) 0 var(--space-4);
}

.tier-card .meta {
  font-size: var(--text-sm);
  color: var(--color-warning-d2);
  margin: var(--space-2) 0 0;
}

/* Cross-sell imaged card (.tier-card.has-media) */
.tier-card.has-media {
  padding: 0;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  overflow: hidden;
  text-decoration: none;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}

.tier-card.has-media:hover,
.tier-card.has-media:focus-visible {
  transform: translateY(-2px);
  box-shadow: var(--shadow-soft);
  border-color: var(--color-warning);
}

.tier-card.has-media .thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 3 / 2;
  background: var(--color-border);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  text-align: center;
  padding: var(--space-2);
}

.tier-card.has-media .tier-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--space-6) var(--space-6) var(--space-8);
}

.tier-card.has-media h3 {
  margin-top: 0;
}

.tier-card.has-media .text-link {
  --text-link-surface: var(--color-surface);
  margin-top: auto;
}

/* Format cards (.type-card) */
.type-card {
  background: var(--color-tint-cream);
  padding: var(--space-8) var(--space-8) var(--space-8);
  display: flex;
  flex-direction: column;
  height: 100%;
}

.type-card .text-link {
  --text-link-surface: var(--color-tint-cream);
  --text-link-shadow-dark: var(--color-warning-d1);
  --text-link-shadow-light: var(--color-tint-cream);
  margin-top: auto;
}

.type-card .kicker {
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-warning-d2);
}

.type-card h3 {
  font-family: var(--font-family-display);
  font-weight: 400;
  font-size: 1.1875rem;
  line-height: 1.25;
  color: var(--color-dark);
  margin-top: var(--space-2);
}

.type-card .meta {
  margin: var(--space-2) 0 0;
}

.type-card p {
  font-size: 0.9375rem;
  color: var(--color-text-muted);
  margin: var(--space-2) 0 var(--space-4);
}

/* Stories cards (.story-card) */
.story-card {
  background: transparent;
  border: 0;
  padding: 0;
  box-shadow: none;
}

.story-card .bezel-core {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  padding: var(--space-6) var(--space-6);
}

.story-card .thumb {
  aspect-ratio: 3 / 2;
  background: var(--color-border);
  border: var(--border-width) solid var(--color-border);
  display: grid;
  place-items: center;
  font-size: var(--text-sm);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: var(--space-4);
}

.story-card .kicker {
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-warning-d2);
}

.story-card h3 {
  font-family: var(--font-family-display);
  font-weight: 400;
  font-size: 1.375rem;
  line-height: 1.3;
  color: var(--color-dark);
  margin-top: var(--space-2);
}

.story-card p {
  font-size: 0.9375rem;
  color: var(--color-text-muted);
  margin: var(--space-2) 0 var(--space-4);
}

.story-card .text-link {
  --text-link-surface: var(--color-surface);
  --text-link-shadow-dark: var(--color-border);
  --text-link-shadow-light: var(--color-surface-page);
  margin-top: auto;
  font-size: 0.9375rem;
}

@media (max-width: 38.75rem) {  /* --bp-sm (620px) */
  .tier-card {
    padding: var(--space-8) var(--space-6) var(--space-8);
  }
}


/* ------------------------------------------------------------
   POSTCARD
   The cheat-sheet reciprocity capture: a two-column card with a
   message panel and a stamp-and-address stub split by a dashed
   perforation, plus an email capture. The single framed object
   on a page that carries --shadow-soft; everything else stays
   flat so the postcard reads as the premium piece.
   ------------------------------------------------------------ */
.postcard {
  display: grid;
  grid-template-columns: 7fr 5fr;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  box-shadow: var(--shadow-soft);
  text-align: left;
}

.postcard .message {
  padding: clamp(var(--space-6), 3vw, var(--space-9));  /* D5: 24 to 40 */
}

.postcard .message .section-h {
  margin-bottom: var(--space-3);  /* 12 */
}

.postcard .stub {
  border-left: var(--border-width) dashed var(--color-border);
  padding: clamp(var(--space-6), 3vw, var(--space-9));
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-6);  /* 18 to 24 (D6) */
}

.postcard .stamp {
  align-self: flex-end;
  border: var(--border-width) solid var(--color-warning);  /* was --color-sand */
  color: var(--color-warning-d1);                          /* was --color-sand-ink */
  font-size: var(--text-xs);  /* 9px, exact */
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: var(--space-2);  /* 8px 7px to 8/8 (D6) */
  text-align: center;
  line-height: 1.5;
}

.postcard .capture label {
  display: block;
  font-size: var(--text-sm);  /* 11px to 12 (D1) */
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);  /* 8 */
}

.postcard .capture input {
  width: 100%;
  box-sizing: border-box;
  background: var(--color-surface);
  border: none;
  border-bottom: var(--border-width) solid var(--color-border);
  padding: var(--space-2) 2px;  /* 8px vertical; 2px kept as an optical exception (Finding D) */
  font-size: var(--text-sm);  /* 13px to 12 (D1) */
  font-family: var(--font-family-sans);
  color: var(--color-text);
  margin-bottom: var(--space-4);  /* 16 */
}

.postcard .capture .cta,
.postcard .capture .btn--cta {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin-top: 0;
  text-align: center;
}

@media (max-width: 38.75rem) {  /* --bp-sm */
  .postcard { grid-template-columns: 1fr; }
  .postcard .stub {
    border-left: none;
    border-top: var(--border-width) dashed var(--color-border);
  }
  .postcard .stamp { align-self: flex-start; }
}


/* ------------------------------------------------------------
   REVIEW QUOTE CARDS
   A row of short verified guest quotes, one per platform, above
   the Feedspace widget. Flat, with a sand (warning) top rule and
   no shadow, so they do not rival the postcard. The row layout
   comes from the grid utilities in markup; this styles the card.
   ------------------------------------------------------------ */
.review-quotes {
  align-items: stretch;
}

.quote-card {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-top: 2px solid var(--color-warning);  /* sand top rule to warning */
  padding: var(--space-6);  /* 22px 20px to 24/24 (D6) */
  margin: 0;
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-300-light);
  font-size: var(--text-h5);  /* 18px to fluid display (D1) */
  line-height: 1.4;
  color: var(--color-dark);
}

.quote-card cite {
  display: block;
  margin-top: var(--space-4);  /* 14 to 16 */
  font-family: var(--font-family-sans);
  font-style: normal;
  font-size: var(--text-sm);  /* 11px to 12 (D1) */
  font-weight: var(--font-weight-600-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}


/* ------------------------------------------------------------
   ASYMMETRICAL BAND DIVIDERS
   A full-width SVG inserted at a band-colour seam. The wrapper
   background is set to the colour of the band above; the SVG
   path is filled with the colour of the band below. Two shapes
   are in use (Curve Asymmetrical and Subtle Tilt); the paths
   live in markup. Keep to two per page so they stay quiet
   punctuation, not a repeating motif.
   ------------------------------------------------------------ */
.divider {
  line-height: 0;
}

.divider svg {
  display: block;
  width: 100%;
  height: clamp(var(--space-9), 6vw, var(--space-24));  /* D8: 36 to 40 min, 80 to 96 max */
}


/* ------------------------------------------------------------
   GRID UTILITY: .start-2
   A centred ten-column block (one column wider than .start-3).
   Collapses to full width at --bp-lg.
   ------------------------------------------------------------ */
.start-2 {
  grid-column: 2 / span 10;
}

@media (max-width: 61.25rem) {  /* --bp-lg */
  .start-2 { grid-column: span 12; }
}


/* ============================================================
   MIRDAIN INTERIOR-PAGE DEVICES (promoted 13 Jun 2026)
   Editorial helpers built into the Mirdain chrome in session
   8.271 and promoted here in Celebrimbor tokens. Mapped per the
   px-to-token map: sand to --color-warning, sand-ink to
   --color-warning-d1, terracotta to --color-primary (deep
   terracotta --color-primary-d1 for small coloured text), the
   included green to --color-success-d1, round-up spacing, 13/11px
   to --text-sm, 10px micro-labels to --text-xs, weight 700 to 600
   (the weight scale tops at 600). Deferred to their own passes:
   the inline prose link (conflicts with the existing link
   system), the breadcrumb (vs .chip--breadcrumb), and the header
   sub-menu (header-nav). px-to-token map decisions D1 to D8.
   ============================================================ */

/* Timeline strip: a horizontal row of dotted nodes on a hairline,
   for a compact chronology. Brand colour and type only. */
.timeline {
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  position: relative;
  margin: 0;
  padding: 0;
}

.timeline::before {
  content: "";
  position: absolute;
  top: var(--space-1);
  left: 2%;
  right: 2%;
  height: var(--border-width);
  background: color-mix(in srgb, var(--color-warning) 45%, var(--color-surface-page));
}

.timeline li { position: relative; flex: 1; text-align: center; }

.timeline .dot {
  display: block;
  width: var(--space-2);   /* 9px dot to 8px, on the scale */
  height: var(--space-2);
  background: var(--color-warning);
  margin: 0 auto;
}

.timeline .node-label {
  display: block;
  font-size: var(--text-xs);   /* 10px to 9px */
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  margin-top: var(--space-2);
}

/* Drop cap: an oversized serif initial on the first letter of a
   block. Add the .dropcap class to the paragraph. */
.dropcap::first-letter {
  float: left;
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-500-medium);
  font-size: 3.4em;
  line-height: 0.74;
  padding: 0.08em 0.1em 0 0;
  color: var(--color-dark);
}

/* Watermark: a faint oversized display word set behind a column,
   with a centre hairline. .watermark-stage is the positioned
   wrapper, .watermark is the word, .cols holds the real content. */
.watermark-stage { position: relative; overflow: hidden; }

.watermark-stage::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: var(--border-width);
  background: var(--color-border);
}

.watermark-stage .cols { position: relative; z-index: 1; }

.watermark {
  position: absolute;
  right: -0.08em;
  bottom: -0.28em;
  z-index: 0;
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-600-bold);
  font-size: clamp(7.5rem, 18vw, 11.25rem);   /* 120 to 180px, decorative display */
  line-height: 0.8;
  letter-spacing: 0.02em;
  color: var(--color-warning);
  opacity: 0.07;
  white-space: nowrap;
  pointer-events: none;
}

@media (max-width: 61.25rem) {   /* --bp-lg */
  .watermark-stage::before { display: none; }
}

/* Pull-quote: a standalone display quote with the deliberate 3px
   terracotta left rule (a confirmed identity device, not to be
   "fixed"). */
.pullquote {
  position: relative;
  margin: 0;
  padding-left: 1.5em;   /* clears the hanging quotation mark */
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-300-light);
  font-size: clamp(1.5rem, 3vw, 2.125rem);
  line-height: 1.35;
  color: var(--color-dark);
}
.pullquote::before {
  content: "\201C";   /* hanging left double quote, replaces the side-tab border (P3 fix) */
  position: absolute;
  left: 0;
  top: -0.3em;
  font-family: var(--font-family-display);
  font-size: 2.4em;
  line-height: 1;
  color: var(--color-primary);
  pointer-events: none;
}

/* ============================================================
   BAND SURFACE TINTS
   Full-width section background utilities, one per functional
   band, drawn from the Montjuïc surface tints. Backgrounds only
   (never text, borders or POI markers). Band-colour canon:
     quotes        — light-stone-pink  (.bg-light-stone-pink)
     included      — stone-pink        (.bg-stone-pink)
     proof/reviews — cream             (.bg-cream)
     FAQ           — blush             (.bg-blush)
     booking/coda  — light-cream       (.bg-light-cream)
   Key-facts (dark) and photos (page) are structural surfaces,
   handled elsewhere. Promoted from the Mírdain chrome so blog
   posts and any page inherit them instead of inline CSS. */
.bg-light-cream      { background: var(--color-tint-light-cream); }
.bg-cream            { background: var(--color-tint-cream); }
.bg-light-stone-pink { background: var(--color-tint-light-stone-pink); }
.bg-stone-pink       { background: var(--color-tint-stone-pink); }
.bg-light-blush      { background: var(--color-tint-light-blush); }
.bg-blush            { background: var(--color-tint-blush); }

/* ============================================================
   BLOG QUOTE BAND and CODA BAND
   Two full-width bands for blog and story posts, promoted from
   the Sagrada uneven-towers post (9404) so posts inherit them
   instead of an inline <style>. The quote band tints light-
   stone-pink and holds an editorial pull-quote (.pullquote or
   .blockquote); it is the same tint as the home founders' quote,
   so every quote across the site matches. The coda band is the
   quiet closing note, light-cream and centred. No full-post
   banding: these are single-purpose bands, not a page-wide wash. */
.mybcn-quote-band {
  background: var(--color-tint-light-stone-pink);
  padding: var(--space-8) var(--space-4);
}
.mybcn-coda-band {
  background: var(--color-tint-light-cream);
  padding: var(--space-8) var(--space-4);
  text-align: center;
}

/* Feature chips: included / not-included / advisory groups. White
   chip with a warning (sand) edge; a success tick marks included,
   a deep-terracotta minus marks not-included. */
.feature-label {
  font-size: var(--text-sm);   /* 11 to 12 */
  font-weight: var(--font-weight-600-bold);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-warning-d1);   /* was --color-sand-ink */
  margin-bottom: var(--space-4);
}

.feature-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.feature-chip {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-warning);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-4);   /* 7/13 to 8/16 */
  font-size: var(--text-sm);   /* 13 to 12 */
  line-height: 1.4;
  color: var(--color-text);
}

.feature-chip .yes { color: var(--color-success-d1); font-weight: var(--font-weight-600-bold); }   /* included tick; 700 to 600 */
.feature-chip .no  { color: var(--color-primary-d1); font-weight: var(--font-weight-600-bold); }    /* not-included; deep terracotta is AA-safe for small text */

/* Media placeholder slots: a flat panel used as an image or map
   placeholder in staging. .photo-slot is the square-ish default;
   .map-slot makes it a 3:2 landscape. */
.photo-slot {
  background: var(--color-border);
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 320px;   /* placeholder height, off the spacing scale by design */
  font-size: var(--text-sm);
  box-shadow: var(--shadow-soft);
}

.map-slot { aspect-ratio: 3 / 2; min-height: 0; }

/* ------------------------------------------------------------
   Media layer (real images and video)
   ------------------------------------------------------------
   .photo-slot and .map-slot above are staging placeholders only.
   The rules below govern real photographs and video.

   Aspect ratios follow the graphical profile: 16:9 hero,
   3:2 tour card, 1:1 detail/grid. The mobile hero crop is 4:5
   portrait (Matt, 18 Jun 2026). Recommended export and WordPress
   sizes live in operations/seo/mybcn-image-sizing-and-delivery-standard.md
   ------------------------------------------------------------ */

/* Responsive baseline: stop any image, picture or video overflowing
   its container, and keep aspect ratio when only one dimension is set. */
img,
picture,
video {
  max-width: 100%;
}
img,
video {
  height: auto;
}

/* .media: a cropping frame. Give it an aspect class; the child image
   or video fills it and is cropped, not distorted, via object-fit. */
.media {
  display: block;
  overflow: hidden;
}
.media > img,
.media > video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.media--16x9 { aspect-ratio: 16 / 9; }  /* hero, section anchor */
.media--3x2  { aspect-ratio: 3 / 2; }   /* tour card */
.media--1x1  { aspect-ratio: 1 / 1; }   /* detail, grid */
.media--4x5  { aspect-ratio: 4 / 5; }   /* mobile portrait */

/* Art-directed hero: a 16:9 frame on desktop and tablet that becomes
   a 4:5 portrait on phones, to pair with a <picture> that swaps the
   asset itself. Use <picture> with a media source for the actual
   image swap, so only the matching file downloads. */
@media (max-width: 38.75rem) {  /* --bp-sm (620px) */
  .media--portrait-sm { aspect-ratio: 4 / 5; }
}

/* Visibility utilities. Prefer <picture> with a media source for
   swapping image ASSETS by breakpoint: it downloads only the matching
   file. These classes are for non-image content or as a fallback,
   because both branches can still download when used on images. */
@media (max-width: 38.75rem) {     /* --bp-sm (620px): hide on phones */
  .hide-mobile { display: none !important; }
}
@media (min-width: 38.8125rem) {   /* 621px: hide on tablet and up */
  .hide-desktop { display: none !important; }
}
