/* ===========================================================================
   Bizhaven training booking — step 1 (session picker) and the step-2 header.
   Tokens are the live Elementor kit's, not invented:
     Primary/Secondary #403E41 · Accent #26C5AA · Saved #734CA0 · Montserrat
   Scoped under .bh-* so nothing leaks into Elementor's own styles.
   WCAG 2.1 AA: body text >= 4.5:1, real labels, visible focus.
   ======================================================================== */

.bh-panel,
.bh-chosen,
.bh-booking,
.bh-hero__eyebrow,
.bh-hero__title,
.bh-hero__sub,
.bh-hero__price,
.bh-hero__points,
.bh-step2,
.bh-why__title,
.bh-why__body,
.bh-why__law,
.bh-why__list,
.bh-team,
.bh-team__title,
.bh-team__intro,
.bh-team__member {
  --bh-ink-900: oklch(0.26 0.006 320);
  --bh-ink-700: oklch(0.38 0.006 320);
  --bh-ink-500: oklch(0.52 0.008 320);   /* 4.6:1 on white - the AA floor */
  --bh-ink-300: oklch(0.74 0.010 320);
  --bh-rule:    oklch(0.90 0.008 320);
  --bh-raised:  #fff;
  --bh-wash:    oklch(0.975 0.012 175);  /* faintest teal, selected rows */
  --bh-teal:    #26C5AA;                 /* fills only - too light for text */
  --bh-teal-ink: oklch(0.42 0.085 175);  /* teal dark enough to read on white */
  --bh-aub-600: oklch(0.47 0.135 305);

  --bh-sans: "Montserrat", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --bh-s1: 0.375rem; --bh-s2: 0.75rem; --bh-s3: 1.125rem;
  --bh-s4: 1.75rem;  --bh-s5: 2.5rem;
  --bh-radius: 14px; --bh-radius-sm: 9px;
  --bh-ease: cubic-bezier(0.16, 1, 0.3, 1);
}

.bh-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* --- panel --------------------------------------------------------------- */
.bh-panel {
  /* Re-establish colour: the panel can sit on a dark Elementor section, where
     inherited light text would be invisible against its own white surface. */
  color: var(--bh-ink-700);
  font-family: var(--bh-sans);
  background: var(--bh-raised);
  border: 1px solid var(--bh-rule);
  border-radius: var(--bh-radius);
  box-shadow: 0 1px 2px oklch(0.26 0.006 320 / 0.05),
              0 8px 24px -12px oklch(0.26 0.006 320 / 0.14);
  /* Grows to fit the longest session date rather than sitting at a fixed width.
     Montserrat's digits are proportional, so the widest string this format can
     produce ("Wednesday, September 24, 2044") is ~296px; the bounds keep the
     panel from collapsing on short dates or eating its column on long ones. */
  width: fit-content;
  min-width: min(21rem, 100%);
  max-width: min(30rem, 100%);
  box-sizing: border-box;
}
.bh-panel * { box-sizing: border-box; }

.bh-panel__head { padding: var(--bh-s4) var(--bh-s4) var(--bh-s3); border-bottom: 1px solid var(--bh-rule); }
.bh-panel .bh-panel__title {
  margin: 0; font-family: var(--bh-sans); font-weight: 700;
  font-size: clamp(1.28rem, 1.20rem + 0.38vw, 1.55rem);
  line-height: 1.15; letter-spacing: -0.015em; color: var(--bh-ink-900);
}
.bh-panel__meta { margin: var(--bh-s1) 0 0; font-size: 0.88rem; color: var(--bh-ink-500); }
.bh-panel__body { padding: var(--bh-s4); }
.bh-panel--notice { max-width: 34rem; }

.bh-fieldset { border: 0; margin: 0 0 var(--bh-s5); padding: 0; }
.bh-empty { margin: 0; color: var(--bh-ink-700); }

/* --- session rows -------------------------------------------------------- */
.bh-sessions { display: grid; gap: var(--bh-s2); }

.bh-session {
  position: relative; display: block;
  padding: var(--bh-s3);
  border: 1px solid var(--bh-rule); border-radius: var(--bh-radius-sm);
  background: var(--bh-raised); cursor: pointer;
  transition: border-color 160ms var(--bh-ease), background-color 160ms var(--bh-ease), transform 160ms var(--bh-ease);
}
.bh-session:hover { border-color: var(--bh-ink-300); transform: translateY(-1px); }

/* Hidden, not removed: display:none would drop it from the accessibility tree
   and break keyboard selection within the radio group. */
.bh-session input {
  position: absolute; width: 1px; height: 1px; margin: 0; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; appearance: none;
}

/* Selected reads as fill AND doubled border weight, so it is not signalled by
   colour alone. The ring paints inside the box and cannot shift layout. */
.bh-session:has(input:checked) {
  border-color: var(--bh-teal-ink); background: var(--bh-wash);
  box-shadow: inset 0 0 0 1px var(--bh-teal-ink);
}
/* Focus lands on the card, because the input it belongs to is invisible. */
.bh-session:has(input:focus-visible) { outline: 3px solid var(--bh-aub-600); outline-offset: 2px; }

.bh-session__when {
  display: block; font-weight: 600; font-size: 1.09rem; line-height: 1.65; color: var(--bh-ink-900);
}
/* A date is one unit. Broken across lines, "Wednesday, September 23," over
   "2026" reads as two separate dates for a moment, so the panel widens to hold
   it instead - it is fit-content and bounded by its own max-width.

   Only once there is room for it. Measured: "Wednesday, September 23, 2026"
   sets 291.8px, and card padding plus panel chrome add 96px, so the panel needs
   388px. Below that the card grows past its column instead of wrapping - at a
   278px panel it measured 291.8px and overflowed - which puts a horizontal
   scrollbar on the whole page. Wrapping is the better failure on a phone.

   The breakpoint: the page keeps 40px of gutter, so 28rem (448px) leaves 408px
   for a panel that needs 388px. The widest date this format can ever produce
   ("Wednesday, September 24, 2044") is ~296px, needing 392px, so that still
   clears. */
@media (min-width: 28rem) {
  .bh-session__when { white-space: nowrap; }
}
.bh-session__time {
  display: block; font-weight: 400; font-size: 0.88rem; line-height: 1.65; color: var(--bh-ink-500);
  /* Not inherited from the parent: the time string is longer than the date and
     is allowed to wrap rather than widen the panel further. */
  white-space: normal;
}

/* --- call to action ------------------------------------------------------ */
.bh-panel .bh-cta,
.bh-chosen .bh-cta,
.bh-cta.bh-cta {
  font-family: var(--bh-sans); font-weight: 600; font-size: 0.9375rem;
  display: block; width: 100%; padding: 0.95rem 1.5rem;
  border: 0; border-radius: 99px; text-align: center; text-decoration: none;
  /* Primary button: the site's #26C5AA with white text. See DESIGN.md - this
     pairing is 2.18:1 and is a documented brand exception to the AA floor
     everything else on these pages meets. */
  background: var(--bh-teal); color: #fff; cursor: pointer;
  transition: background-color 160ms var(--bh-ease), transform 160ms var(--bh-ease);
}
.bh-cta:hover, .bh-cta:focus { background: oklch(0.68 0.12 175); color: #fff; transform: translateY(-1px); }
.bh-cta:focus-visible { outline: 3px solid var(--bh-aub-600); outline-offset: 3px; }
.bh-cta--inline { display: inline-block; width: auto; padding-inline: 2rem; }

/* --- step 2: the chosen session, restated -------------------------------- */
.bh-chosen {
  font-family: var(--bh-sans);
  display: flex; flex-wrap: wrap; gap: var(--bh-s3);
  align-items: baseline; justify-content: space-between;
  padding: var(--bh-s3) var(--bh-s4); margin-bottom: var(--bh-s5);
  background: var(--bh-wash); border: 1px solid var(--bh-rule); border-radius: var(--bh-radius);
  color: var(--bh-ink-700);
}
.bh-chosen b { color: var(--bh-ink-900); }
.bh-chosen__meta { display: block; font-weight: 400; font-size: 0.88rem; color: var(--bh-ink-700); }
.bh-chosen a { font-size: 0.88rem; font-weight: 600; color: var(--bh-teal-ink); }

.bh-notice { color: #8a1c1c; font-family: var(--bh-sans); }

@media (prefers-reduced-motion: reduce) {
  .bh-session, .bh-cta { transition-duration: 0.01ms !important; }
  .bh-session:hover, .bh-cta:hover { transform: none; }
}


/* ===========================================================================
   Step 1 hero.

   Elementor emits custom CSS classes on WIDGETS but not on containers, so
   nothing here may depend on a class on the hero container - it will not exist.
   Every selector therefore hangs off a widget class, and the purple band itself
   stays Elementor's (it is the page's existing brand background).

   Elementor's kit rule `.elementor-widget-heading .elementor-heading-title`
   is 0,2,0 and repaints every heading the kit's dark ink. Chaining the widget
   class to `.elementor-widget-heading` makes these 0,3,0, so band text wins
   without !important.
   ======================================================================== */

.bh-hero__title,
.bh-hero__sub,
.bh-hero__price,
.bh-hero__points,
.bh-hero__eyebrow { font-family: var(--bh-sans); }

/* The one deliberate kicker on the page: a teal accreditation pill with dark
   text, not a tracked all-caps eyebrow. The pill sits on the inner heading
   because the widget wrapper is a full-width block and cannot be a pill. */
.bh-hero__eyebrow { margin-bottom: var(--bh-s3); }
.bh-hero__eyebrow .elementor-widget-container { display: flex; }
.bh-hero__eyebrow.elementor-widget-heading .elementor-heading-title {
  display: inline-flex;
  align-items: center;
  /* Dark ink, NOT white. White on #26C5AA is 2.18:1; the dark ink is 7.16:1.
     The documented white-on-teal exception covers the CTA only - that is a
     button, this is a label, and it was never part of that decision. It went
     white by accident when the button change replaced the first matching
     `color: ink-900; background: teal` pair in this file. */
  color: var(--bh-ink-900);
  background: var(--bh-teal);
  font-size: clamp(0.82rem, 0.80rem + 0.10vw, 0.88rem);
  font-weight: 600;
  letter-spacing: 0.01em;
  padding: 0.4rem 0.9rem;
  border-radius: 99px;
  gap: 0.5rem;
}
/* The shield-check the comp carries, as a mask rather than inline SVG.

   It cannot be markup: Elementor's heading widget runs the title through
   wp_kses_post() at render (includes/widgets/heading.php:449), and kses does not
   allow <svg>/<path>, so the icon is stripped on output no matter who saved it
   or how. A <span> survives, which is why "per seat" above can be markup.

   A mask keeps the comp's behaviour intact: it paints currentColor through the
   SVG's alpha, so the icon tracks the pill's ink - including the contrast fix
   above - and the shield's opacity=".22" comes through as 22% alpha, exactly as
   the two-path original rendered it. */
.bh-hero__eyebrow .elementor-heading-title::before {
  content: "";
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 20 20%22%3E%3Cpath d=%22M10 1.5l6.5 2.4v5.2c0 4-2.7 7.6-6.5 9.4-3.8-1.8-6.5-5.4-6.5-9.4V3.9L10 1.5z%22 opacity=%22.22%22/%3E%3Cpath d=%22M8.9 12.7L6.2 10l1.2-1.2 1.5 1.5 4-4L14.1 7.5l-5.2 5.2z%22/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 20 20%22%3E%3Cpath d=%22M10 1.5l6.5 2.4v5.2c0 4-2.7 7.6-6.5 9.4-3.8-1.8-6.5-5.4-6.5-9.4V3.9L10 1.5z%22 opacity=%22.22%22/%3E%3Cpath d=%22M8.9 12.7L6.2 10l1.2-1.2 1.5 1.5 4-4L14.1 7.5l-5.2 5.2z%22/%3E%3C/svg%3E") center / contain no-repeat;
}

.bh-hero__title.elementor-widget-heading .elementor-heading-title {
  color: #fff;
  font-weight: 700;
  font-size: clamp(2.45rem, 1.90rem + 2.60vw, 3.90rem);
  line-height: 1.1;
  letter-spacing: -0.03em;
  text-wrap: pretty;
}
/* No max-width. It was 34rem (544px) inside a 753px copy column, which is what
   made the title wrap two words early - not the wrapping mode, which is where I
   looked first. The copy column itself is the measure. */
.bh-hero__title { margin-top: var(--bh-s5); }

.bh-hero__sub { margin-top: var(--bh-s3); }
.bh-hero__sub p {
  color: oklch(0.94 0.012 305);
  font-size: clamp(1.28rem, 1.20rem + 0.38vw, 1.55rem);
  line-height: 1.7;
  text-wrap: pretty;
  margin: 0;
  /* ch, not rem: the measure should follow the type, and this is the one place
     the design caps line length. */
  max-width: 34ch;
}

.bh-hero__price.elementor-widget-heading .elementor-heading-title {
  color: #fff;
  font-weight: 700;
  font-size: clamp(2.05rem, 1.70rem + 1.60vw, 3.10rem);
  letter-spacing: -0.03em;
  /* line-height deliberately left to inherit. The design's 28px above and 56px
     below were measured WITH the inherited 1.65 leading around the figure;
     tightening it here would close those gaps by ~15px a side. */
}
.bh-hero__price { margin-top: var(--bh-s4); }
/* "$15.99 per seat": the figure carries the qualifier, as in the comp, so the
   price is never a bare number a reader has to interpret. Baseline-aligned, so
   the small text sits on the figure's baseline rather than its box. */
.bh-hero__price.elementor-widget-heading .elementor-heading-title {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 0.6rem;
}
/* :not(.bh-price-free) because a free session renders the word "Free" as the
   figure itself, not as the small qualifier after it. */
.bh-hero__price .elementor-heading-title span:not(.bh-price-free) {
  font-size: 0.88rem;
  font-weight: 400;
  letter-spacing: normal;
  color: oklch(0.94 0.012 305);
}

/* Benefit list: a labelled definition list, not a card grid and not an icon
   list - the label/description pairing is what dl/dt/dd is actually for. */
.bh-hero__points { margin-top: 3.5rem; }
/* 24rem matches the comp, which caps this dl at 381px inside a 754px column.
   The measure is deliberately much narrower than the column: short lines beside
   a lot of quiet band. Don't "fix" the empty space by widening it. */
.bh-hero__points dl { margin: 0; max-width: 24rem; }
.bh-hero__points dt {
  color: #fff; font-weight: 700;
  font-size: clamp(1rem, 0.97rem + 0.16vw, 1.09rem);
  line-height: 1.65; margin: 0;
}
.bh-hero__points dd {
  color: oklch(0.94 0.012 305); margin: 0 0 var(--bh-s3);
  font-size: 0.88rem; line-height: 1.65;
}
.bh-hero__points dd:last-child { margin-bottom: 0; }

/* --- the "why / what we cover" band under the hero ---------------------- */
.bh-why__body, .bh-why__list {
  font-family: var(--bh-sans);
  color: var(--bh-ink-700);
}
.bh-why__body .elementor-widget-container,
.bh-why__body p,
.bh-why__list .elementor-icon-list-text { color: var(--bh-ink-700); }
.bh-why__title.elementor-widget-heading .elementor-heading-title {
  color: var(--bh-ink-900);
  font-weight: 700;
  font-size: clamp(2.05rem, 1.70rem + 1.60vw, 3.10rem);
  line-height: 1.1;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
.bh-why__title { margin-top: var(--bh-s5); }
.bh-why__body p, .bh-why__list li { line-height: 1.75; max-width: 68ch; text-wrap: pretty; }

/* ===========================================================================
   Step 2 — Events Manager's own booking form.

   EM owns this markup, so everything is scoped under .bh-booking and chained
   for specificity where EM or the Elementor kit already style the element
   (kit `h3`, EM's section titles, input resets). Nothing here changes EM's
   field names or structure: validation, bookings and emails stay EM's job.

   The roster is the design problem: 5-10 attendees is normal, so attendee
   fields go three-up on wide screens rather than a single tall column.
   ======================================================================== */

.bh-booking {
  font-family: var(--bh-sans);
  color: var(--bh-ink-700);
}
.bh-booking .em-booking-form { margin: 0; }

/* --- sections: rules, not stacked cards -------------------------------- */
.bh-booking .em-booking-section {
  border: 0;
  background: none;
  padding: 0;
  margin: 0 0 var(--bh-s5);
}
/* EM themes itself through three custom properties declared on `.em`.
   Redefining them one level deeper is far better than fighting its selectors:
   it recolours every section head, rule and border in one place, and keeps
   working if EM restructures its markup. */
.bh-booking .em {
  --main-bg: transparent;
  --main-h3-color: var(--bh-ink-900);
  --main-border-color: var(--bh-rule);
}

/* Geometry and type are not tokenised, so these still need to outrank EM's own
   `.em.em-event-booking-form h3.em-booking-section-title` (0,3,1). */
.bh-booking .em.em-event-booking-form h3.em-booking-section-title,
.bh-booking .em.em-event-booking-form h3.em-booking-form-tickets-title,
.bh-booking .em.em-event-booking-form h3.em-booking-form-details-title,
.bh-booking .em.em-event-booking-form h3.em-booking-form-summary-title {
  margin: 0 0 var(--bh-s3);
  padding: 0 0 var(--bh-s2);
  /* EM boxes its section heads on all four sides; we want a single rule. */
  border: 0;
  border-bottom: 1px solid var(--bh-rule);
  font-family: var(--bh-sans);
  /* EM declares `font-weight: 300 !important` and `font-size: 24px !important`
     on these headings, so matching !important is the only way to set type
     here - not a shortcut. */
  font-weight: 700 !important;
  font-size: 1.02rem !important;
  line-height: 1.3;
  letter-spacing: -0.005em;
}

/* --- fields ------------------------------------------------------------- */
.bh-booking .em-input-text,
.bh-booking .em-ticket-select { margin: 0 0 var(--bh-s3); }

.bh-booking label {
  display: block;
  margin: 0 0 var(--bh-s1);
  color: var(--bh-ink-700);
  font-size: 0.85rem;
  font-weight: 600;
}
.bh-booking input[type="text"],
.bh-booking input[type="email"],
.bh-booking input[type="tel"],
.bh-booking textarea,
.bh-booking select {
  width: 100%;
  box-sizing: border-box;
  padding: 0.6rem 0.7rem;
  font-family: var(--bh-sans);
  font-size: 0.95rem;
  color: var(--bh-ink-900);
  background: var(--bh-raised);
  border: 1px solid var(--bh-rule);
  border-radius: var(--bh-radius-sm);
  transition: border-color 0.16s var(--bh-ease), box-shadow 0.16s var(--bh-ease);
}
.bh-booking :where(input, textarea, select):focus-visible {
  outline: none;
  border-color: var(--bh-teal-ink);
  box-shadow: 0 0 0 3px oklch(0.42 0.085 175 / 0.18);
}
.bh-booking select { max-width: 8rem; }

/* --- the attendee roster ----------------------------------------------- */
/* Row separators and the four-up grid live in the roster block further down. */

@media (min-width: 44rem) {
  /* Three-up so a ten-person roster stays scannable instead of scrolling.
     !important is load-bearing here, not laziness: EM's JS writes an inline
     `display: block` on each attendee block it clones for seats 2..n, and an
     inline style cannot be outranked by a selector. */
  .bh-booking .em-ticket-booking {
    display: grid !important;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--bh-s2) var(--bh-s3);
    align-items: end;
  }
  .bh-booking .em-ticket-booking > :where(p, div) { margin-bottom: 0; }
  /* the number badge is the row's ::before, so nothing here may span columns */
}

/* --- price line above the roster --------------------------------------- */
.bh-booking .em-ticket > :where(div, p):has(> strong) { color: var(--bh-ink-700); }

/* --- booking summary --------------------------------------------------- */
.bh-booking .em-bs-row {
  display: flex;
  justify-content: space-between;
  gap: var(--bh-s3);
  padding: var(--bh-s2) 0;
}
.bh-booking .em-bs-row-total {
  border-top: 1px solid var(--bh-rule);
  margin-top: var(--bh-s1);
  font-weight: 700;
  color: var(--bh-ink-900);
}
.bh-booking .em-bs-cell-qty { color: var(--bh-ink-500); }
.bh-booking .em-bs-cell-price { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* --- submit ------------------------------------------------------------- */
.bh-booking .em-booking-form-buttons,
.bh-booking .em-booking-buttons { margin: var(--bh-s4) 0 0; }
.bh-booking input.em-booking-submit,
.bh-booking input.em-form-submit,
.bh-booking .em-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  max-width: none;
  padding: 0.8rem 1.4rem;
  font-family: var(--bh-sans);
  font-size: 0.98rem;
  font-weight: 700;
  color: var(--bh-ink-900);
  background: var(--bh-teal);
  border: 0;
  border-radius: 99px;
  cursor: pointer;
  transition: background-color 0.16s var(--bh-ease), transform 0.16s var(--bh-ease);
}
.bh-booking input.em-booking-submit:hover,
.bh-booking .em-button:hover { background: oklch(0.74 0.13 175); }
.bh-booking input.em-booking-submit:active,
.bh-booking .em-button:active { transform: translateY(1px); }

@media (prefers-reduced-motion: reduce) {
  .bh-booking :where(input, select, textarea, .em-button) { transition: none; }
  .bh-booking input.em-booking-submit:active { transform: none; }
}


/* --- after a successful booking ----------------------------------------- */
/* Once EM reports success there is nothing left to change, so the "Change
   session" link goes. Done with :has() rather than JS so it holds whether EM
   returns the success notice over AJAX (the default) or on a page load - and
   the session line itself stays, as confirmation of what was booked. */
.bh-step2:has(.em-notice-success) .bh-chosen__change,
.bh-step2:has(.em-booking-message-success) .bh-chosen__change {
  display: none;
}

/* ===========================================================================
   Step 2 layout — the brand header, the seat control, the numbered roster and
   the sticky total bar.

   The roster is the design problem: a ten-seat booking is normal, so fields go
   four-up (number + first + last + email) with the column labels printed once
   at the top instead of repeating "First name" ten times. Each field keeps its
   own real <label> for assistive tech; those labels are visually hidden on wide
   screens and shown again on narrow ones, where the grid collapses.
   ======================================================================== */

/* --- brand header band -------------------------------------------------- */
.bh-step2__head {
  /* Full-bleed out of the theme's 1140px column, with the inner text pulled
     back to align with the content below it. */
  margin-inline: calc(50% - 50vw);
  padding: var(--bh-s5) max(var(--bh-s4), calc(50vw - 570px));
  margin-bottom: var(--bh-s5);
  position: relative;
  isolation: isolate;
  font-family: var(--bh-sans);
  background: oklch(0.34 0.095 305);
}
.bh-step2__head::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(115deg,
      oklch(0.30 0.095 305 / 0.96) 0%,
      oklch(0.34 0.100 305 / 0.86) 52%,
      oklch(0.42 0.115 300 / 0.70) 100%);
}
.bh-step2 .bh-step2__title {
  margin: 0;
  color: #fff;
  font-size: clamp(1.9rem, 1.2rem + 2.2vw, 2.9rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.022em;
  /* Deliberately NOT text-wrap: balance. Balance evens the two lines out, which
     on a course title broke after "Prevention" and left ~420px of the first line
     empty. Normal wrapping fills the line, which is what reads as intentional
     here. `pretty` is still fine - it only guards against a short last line. */
  text-wrap: pretty;
}

/* --- the ticket block: price and seats side by side, roster beneath ------ */
/* The seats field lives on the same grid as every other field on the page.
   That is the whole fix. It was previously a bespoke inline control in a flex
   row, which is why it needed a patch every time something moved: it had no
   structural home, so its position was the sum of whatever margins EM and this
   file happened to set. Now its cell comes from the grid and its spacing comes
   from `gap`, so there are no margins left to fight over.

   The control keeps a modest width inside its cell: alignment comes from the
   grid, size comes from the content. A seat count does not need 368px, but its
   left edge does need to agree with the First Name field above it. */
.bh-booking .em-ticket { display: block; }
.bh-booking .em-ticket > .em-tickets-spaces { margin: 0; }

@media (min-width: 44rem) {
  .bh-booking .em-ticket {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--bh-s2) var(--bh-s3);
    align-items: start;
  }
  .bh-booking .em-ticket > .em-tickets-spaces { grid-column: 1; }
  .bh-booking .em-ticket > .bh-roster__title,
  .bh-booking .em-ticket > .em-ticket-bookings { grid-column: 1 / -1; }
}

/* --- roster ------------------------------------------------------------- */
.bh-booking .bh-roster__title {
  margin: var(--bh-s4) 0 var(--bh-s2);
  color: var(--bh-ink-900);
  font-family: var(--bh-sans);
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -0.005em;
}

.bh-booking .em-ticket-bookings { display: grid; gap: var(--bh-s2); }

.bh-roster__head { display: none; }

/* Seat numbers come from a CSS counter, not from PHP: EM's JS clones a row for
   each extra seat, so anything written server-side would only ever number the
   first one. EM's own "Attendee 3" text stays in the markup, visually hidden, so
   assistive tech still announces which seat a field belongs to. */
.bh-booking .em-ticket-bookings { counter-reset: bh-seat; }
.bh-booking .em-ticket-booking { counter-increment: bh-seat; }
.bh-booking .em-ticket-booking > strong {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.bh-booking .em-ticket-booking::before {
  content: counter(bh-seat);
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 99px;
  background: var(--bh-wash);
  color: var(--bh-teal-ink);
  font-family: var(--bh-sans);
  font-size: 0.82rem;
  font-weight: 700;
}

@media (min-width: 48rem) {
  .bh-roster__head,
  .bh-booking .em-ticket-booking {
    /* !important because EM's JS writes an inline display:block on every
       attendee block it clones for seats 2..n. */
    display: grid !important;
    grid-template-columns: 2rem repeat(3, minmax(0, 1fr));
    gap: var(--bh-s2) var(--bh-s3);
    align-items: end;
  }
  .bh-roster__head {
    padding-bottom: var(--bh-s1);
    color: var(--bh-ink-700);
    font-size: 0.85rem;
    font-weight: 600;
  }
  /* Centred so the "#" sits over the number badges below it, which are 28px
     circles centred in the same 32px column. */
  .bh-roster__num { color: var(--bh-ink-500); text-align: center; }
  .bh-booking .em-ticket-booking { border: 0; margin: 0; padding: 0; }
  .bh-booking .em-ticket-booking > :where(p, div) { margin: 0; }
  .bh-booking .em-ticket-booking::before { align-self: center; }
  /* Column headings carry the naming on wide screens; the per-field labels stay
     in the DOM for screen readers rather than being removed. */
  .bh-booking .em-ticket-booking label {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

}

/* --- sticky total bar --------------------------------------------------- */
.bh-total-bar {
  /* In flow by default - see the :has() rule below for when it becomes sticky. */
  position: static;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--bh-s3);
  margin-top: var(--bh-s5);
  padding: var(--bh-s3) var(--bh-s4);
  background: var(--bh-raised);
  border: 1px solid var(--bh-rule);
  border-radius: var(--bh-radius);
  box-shadow: 0 -2px 4px oklch(0.26 0.006 320 / 0.04),
              0 12px 32px -14px oklch(0.26 0.006 320 / 0.22);
}
/* the section headings are redundant inside a one-line bar */
.bh-total-bar .em-booking-form-summary-title,
.bh-total-bar .em-booking-form-section-confirm .em-booking-section-title { display: none; }
.bh-total-bar .em-booking-form-section-summary,
.bh-total-bar .em-booking-form-section-confirm { margin: 0; }
.bh-total-bar .em-booking-section { margin: 0; }
.bh-total-bar .em-bs-row { padding: 0; }
.bh-total-bar .em-bs-row-item { font-size: 0.85rem; color: var(--bh-ink-500); }
.bh-total-bar .em-bs-row-total {
  border: 0;
  margin: 0;
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--bh-ink-900);
}
.bh-total-bar .em-booking-form-buttons,
.bh-total-bar .em-booking-buttons { margin: 0; }

/* --- who is booking: three across, not a stacked column ----------------- */
@media (min-width: 44rem) {
  .bh-booking .em-booking-form-details {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--bh-s2) var(--bh-s3);
    align-items: end;
  }
  .bh-booking .em-booking-form-details > :where(p, div) { margin: 0; }
  /* the login prompt and anything else non-field runs full width */
  .bh-booking .em-booking-form-details > .em-login-trigger,
  .bh-booking .em-booking-form-details > div:not([class*="input"]) { grid-column: 1 / -1; }
}

/* EM draws a rule between attendee blocks via
   `.em.em-event-booking-form .em-tickets .em-ticket-booking`, which outranks a
   two-class selector. In the four-up grid the rows read as a table, so the
   per-row rules are noise. */
.bh-booking .em.em-event-booking-form .em-tickets .em-ticket-booking {
  border: 0;
  margin: 0;
  padding: 0;
}

/* Compact the total bar. It is sticky, so every pixel of its height is a pixel
   of roster permanently covered while the buyer is typing. Total first and
   large, the line item beneath it small - hence column-reverse, since EM emits
   the line item before the total. */
.bh-total-bar { padding: var(--bh-s2) var(--bh-s4); }
/* Every rule below is prefixed to outrank EM's own `.em.em-event-booking-form`
   spacing, which is what kept the bar at 179px. */
.bh-booking .em .bh-total-bar :where(section, div, p, h3) {
  margin-top: 0;
  margin-bottom: 0;
  padding-top: 0;
  padding-bottom: 0;
}
/* One line, total first: EM emits the line item before the total, so the row is
   reversed rather than reordering its markup. Stacking them made the bar 127px
   tall, and every pixel of a sticky bar is roster the buyer cannot see. */
.bh-booking .em .bh-total-bar .em-booking-summary {
  display: flex;
  flex-direction: row-reverse;
  align-items: baseline;
  justify-content: flex-end;
  gap: var(--bh-s3);
}
.bh-booking .em .bh-total-bar .em-bs-section { display: block; }
.bh-booking .em .bh-total-bar .em-bs-row { display: flex; align-items: baseline; }
.bh-booking .em .bh-total-bar .em-bs-row { padding: 0; gap: var(--bh-s2); }
.bh-booking .em .bh-total-bar .em-bs-row-total {
  border: 0;
  font-size: 1.5rem;
  line-height: 1.15;
  letter-spacing: -0.03em;
  color: var(--bh-ink-900);
}
.bh-booking .em .bh-total-bar .em-bs-row-item { font-size: 0.82rem; line-height: 1.4; color: var(--bh-ink-500); }

/* (Bar clearance is set further down, on the same section.) */


/* The header band bleeds out of the theme's centred column with
   `margin-inline: calc(50% - 50vw)`. 50vw counts the scrollbar gutter, so on a
   scrolling page that is ~8px wider than the visible viewport and the page gains
   a horizontal scrollbar. overflow-x: clip removes it WITHOUT creating a scroll
   container, so the sticky total bar keeps working (overflow: hidden would break
   it). Scoped with :has() so it only applies to pages carrying step 2. */
html:has(.bh-step2),
html:has(.bh-step2),
body:has(.bh-step2) { overflow-x: clip; }

/* Only the total goes in the bar. EM nests the line item in three wrappers that
   each carry their own spacing, which kept the bar over 130px tall - and a
   sticky bar's height is roster the buyer cannot see while typing. The seat
   count is already on screen twice (the Seats select and the numbered rows), so
   the line item is the redundant part. */
.bh-booking .em .bh-total-bar .em-booking-summary:not(.skeleton) .em-bs-row-item,
.bh-booking .em .bh-total-bar .em-booking-summary:not(.skeleton) .em-bs-section-items { display: none; }
.bh-booking .em .bh-total-bar .em-booking-form-summary,
.bh-booking .em .bh-total-bar .em-booking-summary { display: block; }

/* EM ships `!important` on its heading sizes (same as the h3 section titles),
   so the roster heading has to match it to sit at section-title size. */
.bh-booking .bh-roster__title {
  font-size: 1.02rem !important;
  font-weight: 700 !important;
  line-height: 1.3;
}

/* No rule above the total: with the line item hidden it separated nothing. */
.bh-booking .em .bh-total-bar .em-bs-row-total { border-top: 0; margin-top: 0; }
.bh-booking .em .bh-total-bar { align-items: center; }

/* With the line item hidden, any rule inside the bar separates nothing. EM puts
   borders on several of the summary wrappers, so this clears them all. */
.bh-booking .em .bh-total-bar :where(section, div, p, span) { border: 0; }

/* ===========================================================================
   Bringing step 2 in line with the approved comp.
   ======================================================================== */

/* The comp shows one price, in the note beside the seat select. EM also prints a
   separate labelled "Price" block immediately before it, which said the same
   number twice. */
.bh-booking .em-ticket > .ticket-price { display: none; }


/* Total bar: the number is the point, so the "Total Price" label goes and the
   figure carries the weight, with the seat count beneath it.

   `:not(.skeleton)` matters. Events Manager renders its loading placeholder from
   a <template> using the SAME class names as the real summary, so hiding the
   desc cell unqualified hid the placeholder too - which is why changing the seat
   count blanked the total for the length of the request instead of showing
   EM's shimmer. */
.bh-booking .em .bh-total-bar .em-booking-summary:not(.skeleton) .em-bs-row-total .em-bs-cell-desc { display: none; }
.bh-booking .em .bh-total-bar .em-bs-row-total {
  display: block;
  font-size: 1.6rem;
  line-height: 1.05;
}
.bh-booking .em .bh-total-bar .em-bs-row-total .em-bs-cell-price {
  font-variant-numeric: tabular-nums;
}
.bh-total-bar__seats {
  display: block;
  margin-top: 0.15rem;
  color: var(--bh-ink-500);
  font-family: var(--bh-sans);
  font-size: 0.85rem;
  font-weight: 400;
  letter-spacing: 0;
}


/* The roster needs the full column - four fields per row at 46rem left the
   page looking cropped, with the header band and session bar running wide and
   everything below them squeezed into two thirds of the width. */
.bh-booking .em-booking-form { width: 100%; }

/* Keep the sticky bar from becoming a wall. EM nests the summary in several
   spacing-carrying wrappers and adds a Sub Total row of its own; inside the bar
   only the final figure is wanted. */
.bh-booking .em .bh-total-bar .em-booking-summary:not(.skeleton) .em-bs-row:not(.em-bs-row-total) { display: none; }
.bh-booking .em .bh-total-bar .em-booking-form-summary,
.bh-booking .em .bh-total-bar .em-booking-summary,
.bh-booking .em .bh-total-bar .em-bs-section { display: block; }
.bh-total-bar { padding: var(--bh-s3) var(--bh-s4); align-items: center; }

/* The bar's height was EM's spacing, not its content: 40px on the summary
   wrapper, plus 20px padding AND 20px margin on each .em-bs-section, plus a
   subtotals section that stayed in the flow after its row was hidden. Measured
   at 214px; the content inside it is ~54px. !important because these come from
   `.em.em-event-booking-form` selectors that outrank a four-class chain. */
.bh-booking .em .bh-total-bar .em-booking-form-summary,
.bh-booking .em .bh-total-bar .em-booking-summary,
.bh-booking .em .bh-total-bar .em-bs-section {
  padding: 0 !important;
  margin: 0 !important;
}
.bh-booking .em .bh-total-bar .em-bs-section-subtotals,
.bh-booking .em .bh-total-bar .em-bs-section-items { display: none !important; }
.bh-booking .em .bh-total-bar input.em-booking-submit { margin: 0 !important; }

/* EM's `.em.pixelbones h4` is 0,2,1 and carries !important, so the earlier
   two-class rule for the roster heading lost on specificity even with
   !important of its own. Adding .em to the chain makes this 0,3,0. */
.bh-booking .em .bh-roster__title {
  border-bottom: 1px solid var(--bh-rule);
  padding-bottom: var(--bh-s2);
  color: var(--bh-ink-900);
  font-family: var(--bh-sans);
  font-size: 1.02rem !important;
  font-weight: 700 !important;
  line-height: 1.3 !important;
  letter-spacing: -0.005em;
  margin: var(--bh-s4) 0 var(--bh-s2) !important;
}

/* Nothing inside the bar separates anything now that only the total shows. */
.bh-booking .em .bh-total-bar :where(section, div, span, p) { border: 0 !important; }

/* Reserve room for the sticky bar. The padding has to sit on the content
   BEFORE the bar, not on .bh-booking - the bar is inside .bh-booking, so
   padding there lands after it and changes nothing. Without this a short page,
   which is exactly what the default of one seat produces, leaves the bar
   covering the seat control with no scroll room to move it out of the way. */
/* (clearance is applied with the sticky state below) */


/* ===========================================================================
   The total bar only becomes sticky once it has a reason to be.

   With a short roster the whole form fits on screen, so pinning the bar to the
   viewport achieved nothing except covering the seat control - the page could
   not scroll far enough to move it out of the way. It earns its persistence
   only when the roster is long enough to push the button out of view.

   The threshold is four attendee rows, expressed as a sibling chain so it is
   unaffected by the column-heading row sitting first in the container, and it
   re-evaluates on its own as Events Manager adds and removes rows - no JS and
   no seat-count duplication.
   ======================================================================== */
.bh-step2:has(.em-ticket-booking ~ .em-ticket-booking ~ .em-ticket-booking ~ .em-ticket-booking) .bh-total-bar {
  position: sticky;
  bottom: 0;
}
/* No extra clearance is reserved. A sticky element returns to its natural
   position at maximum scroll, and there is page below the form (the footer) to
   scroll through, so the last row always reaches daylight on its own. Reserving
   120px only made the roster jump when the fourth row appeared - the same
   threshold that turns stickiness on - for space that was never needed. */


/* ===========================================================================
   Outranking Events Manager.

   Everything below exists for one reason: EM's own rules live at 0,3,0-0,5,1
   and frequently carry !important, so the plain resets earlier in this file
   silently lost. Each block names the EM rule it is answering and matches its
   weight - the !importants here are answers to EM's !importants, not shortcuts.

   Symptom this fixed: the page had THREE different left edges (section
   headings at 0, fields at +15, roster rows at +30) where the design has one.
   ======================================================================== */

/* EM: `.em.em-event-booking-form .em-booking-section { padding: 20px 15px }` (0,3,0)
   That 15px was the second left edge, and the 20px was most of the vertical bloat. */
.bh-booking .em.em-event-booking-form .em-booking-section { padding: 0; }

/* EM: `.em...em-ticket-bookings { padding: 0 15px 20px !important }` (0,4,0 !imp)
   The third left edge. Nothing in this file targeted it before. */
.bh-booking .em.em-event-booking-form .em-tickets .em-ticket-bookings { padding: 0 !important; }

/* EM: `.em.pixelbones h3 { margin-bottom: 20px !important }`
   Design wants 12px between a section heading and its first field. */
.bh-booking .em.em-event-booking-form h3.em-booking-section-title { margin-bottom: var(--bh-s2) !important; }

/* EM: `.input-user-field`/`.input-group`/`.em.pixelbones p { margin-bottom: 25px !important }`
   This phantom 25px was inflating every field's margin box: it tripled the
   booker row gap, made each roster row 63px instead of 40px, and broke the
   bottom-alignment of the per-seat note against the seat select, because
   `align-items: flex-end` aligns margin boxes. */
.bh-booking .em.em-event-booking-form .em-booking-form .input-user-field,
.bh-booking .em.em-event-booking-form .em-booking-form .input-group,
.bh-booking .em.em-event-booking-form .em-booking-form .input-type { margin-bottom: 0 !important; }

/* EM: `.em.pixelbones.input label:not([data-nostyle]) { font-size/weight/margin !important }` (0,5,1)
   Every label was rendering at EM's 16px/400 instead of the design's 13.6px/600. */
.bh-booking .em.pixelbones.input label:not([data-nostyle]) {
  font-size: 0.85rem !important;
  font-weight: 600 !important;
  margin-bottom: var(--bh-s1) !important;
}

/* EM: `.em.pixelbones.input input[type=…] { height/padding/border/radius !important }` (0,4,1)
   Fields were wearing EM's skin - 38px tall, 4px radius, EM's border colour. */
.bh-booking .em.pixelbones.input input[type="text"],
.bh-booking .em.pixelbones.input input[type="email"],
.bh-booking .em.pixelbones.input input[type="tel"],
.bh-booking .em.pixelbones.input input[type="number"],
.bh-booking .em.pixelbones.input select,
.bh-booking .em.pixelbones.input textarea {
  height: auto !important;
  /* EM sets line-height 1.5 on inputs (22.8px at this size), which made every
     field 44px against the design's 40.2px - and that 4px compounds down an
     eight-row roster. 1.25 lands on the design height exactly. */
  line-height: 1.25 !important;
  padding: 0.6rem 0.7rem !important;
  border: 1px solid var(--bh-rule) !important;
  border-radius: var(--bh-radius-sm) !important;
}

/* EM: `.em.em-event-booking-form .em-button.em-booking-submit { padding: 15px; font-size: … }` (0,4,0)
   The data-nostyle opt-out kills EM's pixelbones button skin but not this rule. */
.bh-booking .em .em-button.em-booking-submit {
  /* Same line-height story as the inputs: EM's 1.5 made the button 49.1px
     against the design's 46.2px. */
  padding: 0.85rem 1.5rem;
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.2;
}


/* Buttons match the site's: #26C5AA with the kit's dark ink. Pinned at EM's
   weight because `.em.em-event-booking-form .em-button` sets its own colours. */
.bh-booking .em .em-button.em-booking-submit,
.bh-booking .em input.em-booking-submit {
  background: var(--bh-teal) !important;
  color: #fff !important;
}
.bh-booking .em .em-button.em-booking-submit:hover,
.bh-booking .em input.em-booking-submit:hover {
  background: oklch(0.68 0.12 175) !important;
}

/* --- the seats control ---------------------------------------------------
   Two faults, one cause each.

   1. `p.em-tickets-spaces` and the select both still carried EM's
      `margin-bottom` (25px and 15px). `.em-ticket` uses align-items: flex-end,
      which aligns MARGIN boxes, so those margins pushed the per-seat note 20px
      below the select instead of level with it, and left a block of dead space
      under the control. Killing the margins is what actually aligns them.

   2. The select was 43px wide with 11.2px of right padding, so a two-digit
      value collided with the dropdown arrow. It needs room for two digits plus
      the arrow, and must not be shrunk by the flex container.
   ------------------------------------------------------------------------ */
.bh-booking .em.em-event-booking-form .em-ticket > .em-tickets-spaces,
.bh-booking .em.pixelbones.input select.em-ticket-select {
  margin-bottom: 0 !important;
}
.bh-booking .em.pixelbones.input select.em-ticket-select {
  /* Sized from its content, not from a guess. The widest option ("20") is
     18.7px of glyph; with the padding either side and the borders the field
     needs 65px, so `auto` plus a 4.5rem floor lands at 72px - a little slack,
     and it re-derives itself if the seat cap ever changes. The previous 8rem
     cap was arbitrary and made it nearly twice as wide as its content.

     The right padding is for the arrow, which is a background image: without it
     a two-digit value collides with the glyph. */
  width: auto !important;
  min-width: 4.5rem;
  max-width: none;
  padding-right: 2.1rem !important;
}


/* Rhythm between sections. Zeroing EM's 20px section padding (which was also
   the second left edge) removed the only thing separating one section from the
   next, so "How many supervisors?" sat flush against the last booker field.
   The design's section gap is 40px, matching the gap already set below the
   chosen-session bar. */
.bh-booking .em.em-event-booking-form .em-booking-form-section-tickets { margin-top: var(--bh-s5); }

/* EM right-aligns the price cell, which is correct in its own summary table
   where the figure is the last column. In the bar the cell is the only thing
   left, and the section shrinks to its content, so right-alignment pushed the
   figure 18px in from the seat line beneath it and read as centred. */
.bh-booking .em .bh-total-bar .em-bs-cell-price,
.bh-booking .em .bh-total-bar .em-bs-row-total { text-align: left; }


/* The total figure sits flush with the seat line beneath it. EM's price cell is
   the last column of its own summary table, so it carries right-alignment and a
   set width; inside the bar it is the only cell left, and those two things
   offset it 14-18px from the line below - varying with the price's width, which
   is what made it read as centred. A flex row anchored to the start removes both
   the alignment and the set width from the equation. */
.bh-booking .em .bh-total-bar .em-bs-row-total {
  display: flex;
  justify-content: flex-start;
  text-align: left;
}
.bh-booking .em .bh-total-bar .em-bs-row-total .em-bs-cell-price {
  width: auto !important;
  margin: 0 !important;
  text-align: left;
}


/* Every field on this form is required, so the asterisk marks nothing. Hidden
   rather than deleted because EM owns that markup; the requirement is carried by
   aria-required on the inputs instead, which is a stronger signal than a glyph. */
.bh-booking .em-form-required { display: none; }

/* ===========================================================================
   Step 1 hero band.

   The purple comes from here rather than from Elementor's container background,
   so it deploys with the code and matches step 2's header exactly — same
   gradient stops, so the two pages read as one flow.

   Targeted with :has() rather than by Elementor's element id
   (.elementor-element-0f4178e). The id is stable in the database but silently
   wrong the moment anyone rebuilds the hero; "the top-level container holding
   our hero title" stays true. Elementor emits no custom class on containers, or
   this would simply be .bh-hero.

   !important because Elementor writes the container's background into
   post-<id>.css at .elementor-<page> .elementor-element.elementor-element-<id>,
   which ties on specificity and loads later.
   ======================================================================== */
/* `:has()` is a descendant match, and Elementor puts `e-parent` on ANY container
   that holds widgets - not just top-level ones - so the plain
   `.e-con.e-parent:has(.bh-hero__title)` also matched the copy column and
   painted the gradient a second time inside the first. The visible seam was that
   inner edge. `:not(:has(> ...))` excludes the column that holds the title
   directly, leaving only the band that wraps it, and survives the containers
   being switched between boxed and full. */
.e-con.e-parent:has(.bh-hero__title):not(:has(> .bh-hero__title)) {
  position: relative;
  isolation: isolate;
  background-color: oklch(0.34 0.095 305);
  /* No photograph: the gradient alone, as in the approved mockup. */
  background-image: linear-gradient(115deg,
      oklch(0.30 0.095 305 / 0.96) 0%,
      oklch(0.34 0.100 305 / 0.86) 52%,
      oklch(0.42 0.115 300 / 0.70) 100%);
}


/* Vertical rhythm in the hero is set with margin-TOP throughout, deliberately.
   Elementor zeroes widget bottom margins with
   `.e-con .elementor-widget.elementor-widget { margin-block-end: 0 }` (0,3,0),
   so any margin-bottom written at single-class specificity here is dead on
   arrival. margin-top is untouched by it. Gives the design's 40/18/28/56. */

/* Column splits, for the hero and for the why band.

   Elementor drives every container's flex from three custom properties -
   `.e-con.e-flex { flex: var(--flex-grow) var(--flex-shrink) var(--flex-basis) }`
   in its frontend.css - so the durable hook is to set those vars rather than to
   override the `flex` shorthand. No !important, and the editor's own Flex
   controls keep working because they write the same three vars.

   Its Flex Size control cannot express this on its own: "Grow" sets shrink to 0,
   and a container defaults to `--width: 100%`, so two 100%-wide columns in a row
   simply overflow. Basis is the property that matters here and Elementor's
   container UI excludes it. Hence `--flex-basis: 0` below: the columns take
   their size from the free space, not from their content.

   `.e-con.e-flex` is 0,3,0 so these match it and win on document order. Keyed to
   the .bh-* widget inside each column, because Elementor emits no custom class
   on containers - see includes/widgets/common-base.php:800, where _css_classes
   is a widget-only control. */
.e-con.e-flex:has(> .bh-hero__title),
.e-con.e-flex:has(> .bh-why__title) {
  --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0;
  /* The floor is what makes these columns WRAP instead of collapsing. With
     basis 0 and nothing to stop the shrink, a narrow viewport squeezed the hero
     copy to 59px beside a 362px panel rather than dropping it to its own line -
     flex only wraps when an item cannot fit, and an item that shrinks to nothing
     always fits. `min()` keeps the floor from becoming an overflow of its own
     once the column is the full width. */
  min-width: min(100%, 20rem);
}
.e-con.e-flex:has(> .bh-hero__panel) {
  --flex-grow: 0; --flex-shrink: 0; --flex-basis: auto;
  --width: auto;   /* else the default 100% is the basis and nothing fits */
  /* Cap at the panel's own ceiling rather than at the comp's 362px. The column
     sizes to its content, so a hard 362px here overrode `.bh-panel`'s
     `width: fit-content` and forced long dates to wrap - "Wednesday, September
     23, 2026" broke across two lines. Deferring to the panel's own 30rem lets
     it widen exactly as far as the longest date needs and no further.

     The bound still has to exist: with no upcoming session the panel holds a
     single paragraph, which has nothing to wrap against and stretched to 765px,
     squeezing the headline column down to its 20rem floor. */
  max-width: min(100%, 30rem);
}

/* ===========================================================================
   Step 1 - the "why / what we cover" band and the presenter roster.
   Both bind to the .bh-* widget classes rather than to Elementor element ids,
   so the rules survive the page being duplicated for the next training.
   ======================================================================== */

/* --- the law callout ----------------------------------------------------- */
/* The statutory requirement is the one paragraph a buyer has to be able to
   quote to their boss, so it is lifted out of the prose onto its own surface.
   A tinted box, not a side-stripe: full border, no accent bar. */
.bh-why__law {
  font-family: var(--bh-sans);
  background: var(--bh-wash);
  border: 1px solid oklch(0.88 0.030 175);
  border-radius: var(--bh-radius-sm);
  padding: var(--bh-s3) var(--bh-s4);
  margin-top: var(--bh-s3);
}
.bh-why__law p {
  margin: 0;
  color: var(--bh-ink-900);
  font-size: 1rem;
  line-height: 1.7;
  max-width: none;          /* the box is already the measure */
  text-wrap: pretty;
}
.bh-why__law b, .bh-why__law strong { color: var(--bh-teal-ink); font-weight: 700; }

/* --- why band spacing --------------------------------------------------- */
/* The two columns are real Elementor containers (row direction, 56px column
   gap, wrapping on mobile), so nothing here sets the layout - only the
   internal rhythm Elementor's zeroed widget margins leave behind. */
.bh-why__body { margin-top: var(--bh-s3); }
.bh-why__list { margin-top: var(--bh-s3); }
.bh-why__list .elementor-icon-list-text { line-height: 1.6; }

/* The check mark. Elementor ships Font Awesome's `fas-check` as an inline SVG -
   a heavy filled tick, vertically centred against the whole item. The comp uses
   a light stroked check (stroke-width 2.4, round caps) in teal ink, sitting on
   the FIRST line. Two separate fixes:

   1. Alignment. Elementor reads `--icon-vertical-align` (default `center`), so
      setting the var beats its `.elementor-widget .elementor-icon-list-item`
      rule without a specificity fight. Then the icon box is made exactly one
      line tall and the mark centred inside it, so it lines up with the first
      line of text at any font size - no magic offset to re-tune later. `1lh` is
      the honest way to say "one line"; the em value before it is the fallback
      for browsers that lack the unit.
   2. The glyph. Elementor's SVG geometry cannot be restyled into a stroked
      check, so it is hidden and the mark painted as a mask - the same technique
      as the accreditation pill, and for the same reason. */
.bh-why__list {
  --icon-vertical-align: flex-start;
}
.bh-why__list .elementor-icon-list-icon {
  flex: 0 0 18px;
  height: 1.6em;
  height: 1lh;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* The gap to the text and the gap between rows are the widget's own Text Indent
   and Space Between, both set to 12px. Doing it from here needed !important:
   Elementor writes Text Indent as a per-element `padding-inline-end` at 0,3,0,
   which a plain `padding: 0` cannot reach. Only the stray 5px of text padding is
   answered here. */
.bh-why__list .elementor-icon-list-text { padding-left: 0; }
.bh-why__list .elementor-icon-list-icon svg { display: none; }
.bh-why__list .elementor-icon-list-icon::before {
  content: "";
  width: 18px;
  height: 18px;
  background-color: var(--bh-teal-ink);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 20 20%22 fill=%22none%22 stroke=%22%23000%22 stroke-width=%222.4%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Cpath d=%22M4 10.5l4 4 8-9%22/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 20 20%22 fill=%22none%22 stroke=%22%23000%22 stroke-width=%222.4%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Cpath d=%22M4 10.5l4 4 8-9%22/%3E%3C/svg%3E") center / contain no-repeat;
}

/* --- presenter roster ---------------------------------------------------- */
.bh-team__title.elementor-widget-heading .elementor-heading-title {
  /* the same step as .bh-why__title, so the two section heads sit on one scale */
  color: var(--bh-ink-900);
  font-weight: 700;
  font-size: clamp(2.05rem, 1.70rem + 1.60vw, 3.10rem);
  line-height: 1.1;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
.bh-team__title { margin-top: var(--bh-s5); }
.bh-team__intro { margin-top: var(--bh-s2); }
.bh-team__intro p {
  margin: 0;
  font-family: var(--bh-sans);
  color: var(--bh-ink-700);
  font-size: 1.0625rem;
  line-height: 1.7;
  max-width: 60ch;
  text-wrap: pretty;
}

/* Five faces wrapping down to one is 2D, so this is Grid, and auto-fit means it
   reflows without a single breakpoint. The 184px floor is the width at which a
   two-line name plus a role line still reads; below it the track would rather
   drop to fewer columns than squeeze. Keyed to the member class so adding or
   removing a presenter in Elementor needs no CSS change. */
.e-con:has(> .bh-team__member),
.e-con-inner:has(> .bh-team__member) {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(184px, 1fr));
  gap: 28px;
  margin-top: var(--bh-s4);
}
/* Nothing here sets the card's own layout: each image-box is configured
   natively as Image Position "Top" at 100% width with 12px spacing, so
   Elementor's own elementor-position-top styles stack the photo over the name.
   Overriding display/width from here needed !important and fought the editor. */
.bh-team__member { margin: 0; }
.bh-team__member .elementor-image-box-wrapper { text-align: left; }
.bh-team__member .elementor-image-box-img img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  object-position: 50% 20%;  /* faces sit above centre in these portraits */
  border-radius: var(--bh-radius-sm);
  display: block;
  background: var(--bh-wash);  /* so a slow image is not a white hole */
}
.bh-team__member .elementor-image-box-title {
  font-family: var(--bh-sans);
  color: var(--bh-ink-900);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.35;
  margin: 0;
  text-wrap: balance;
}
/* The name and the role arrive in one field as `Name<span><br>Role</span>`.
   Promoting the span to a block gives the two lines; the <br> would then add a
   second one, so it goes. */
.bh-team__member .elementor-image-box-title br { display: none; }
.bh-team__member .elementor-image-box-title span {
  display: block;
  margin-top: 0.2rem;
  color: var(--bh-ink-500);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.45;
  letter-spacing: 0;
}

/* ===========================================================================
   The total while it is being recalculated.

   Changing the seat count sends EM to admin-ajax.php, which is most of a second
   even on a fast host - almost all of it WordPress booting, not EM's sums - so
   the figure cannot just sit there stale or blank. EM already solves this: it
   swaps a <template> skeleton into the summary, ships a shimmer for it, and
   fires em_booking_summary_updating / _updated around the request. Nothing here
   adds a spinner of its own; it makes EM's own placeholder land in the design.
   ======================================================================== */

/* One bar, where the figure will appear, at the figure's own size - so the bar
   does not change height when the real number arrives. */
.bh-booking .em .bh-total-bar .em-booking-summary.skeleton .em-bs-section-items,
.bh-booking .em .bh-total-bar .em-booking-summary.skeleton .em-bs-row-item { display: none; }

.bh-booking .em .bh-total-bar .em-booking-summary.skeleton .em-bs-row-total {
  display: flex;
  align-items: center;
  gap: var(--bh-s2);
}
.bh-booking .em .bh-total-bar .em-booking-summary.skeleton .em-bs-cell-desc { display: none; }
.bh-booking .em .bh-total-bar .em-booking-summary.skeleton .em-bs-cell-price {
  display: block;
  /* `flex: 0 0` and not `width`. The summary is a flex item of the bar and takes
     its size from its content; the skeleton HAS no text, so the whole chain
     collapsed and the placeholder shrank to 0 wide at `width: 6.5rem`. Refusing
     to shrink is what gives it - and its ancestors - a size at all. */
  flex: 0 0 6.5rem;   /* about the width of "$1,279.20" at the total's size */
  min-width: 6.5rem;
  height: 1.7rem;     /* the figure's own line box, so nothing jumps */
}

/* EM's default placeholder grey is #d6d6d6, which is heavier than anything else
   on this bar. Its two variables are the documented way in. */
.bh-booking .em .bh-total-bar .em-booking-summary.skeleton {
  --background-color-skeleton: oklch(0.94 0.005 320);
  --background-color-skeleton-softer: oklch(0.91 0.005 320);
}

/* The seat line is derived from the select, not from EM's response, so it is
   already correct while the request is out - but it should not read as final
   next to a figure that is still loading. */
.bh-total-bar:has(.skeleton) .bh-total-bar__seats { opacity: 0.45; }

@media (prefers-reduced-motion: reduce) {
  /* EM's shimmer is a moving highlight; without it the bar still reads as
     "not the number yet", so this only stops the motion. */
  .bh-booking .em .bh-total-bar .em-booking-summary.skeleton .item::after {
    animation: none;
  }
}

/* wpautop leaves empty paragraphs around shortcode output when this layout is
   rendered inside an event's own page (`#_EVENTNOTES` runs through wpautop).
   They are invisible but each carries a bottom margin, which pushed the session
   panel 43px taller than the comp. Nothing legitimate is an empty paragraph. */
.bh-hero p:empty,
.bh-hero__panel p:empty,
.bh-booking p:empty { display: none; }

/* Events Manager always prints its "Who is booking?" section, even when it has
   no fields to show - which is what a logged-in visitor gets, because EM takes
   those details from the account. The bare heading reads as a bug, so hide the
   section when it is genuinely empty. */
.bh-booking .em-booking-form-section-details:not(:has(input, select, textarea)) {
  display: none;
}

/* ---------------------------------------------------------------------------
   Presenters, stacked.

   The training lists five people as a grid of square portraits, where a name and
   a role is all there is room for. A webinar has one or two speakers and a real
   biography each, which reads better as full-width rows: portrait on the left,
   name, role and bio on the right.

   Opt in per card with `bh-team__member--row`; the container follows, because a
   container cannot carry a class of its own (`_css_classes` is widget-only) and
   :has() lets the children decide the layout.
   ------------------------------------------------------------------------ */
.e-con:has(> .bh-team__member--row),
.e-con-inner:has(> .bh-team__member--row) {
  grid-template-columns: 1fr;
  /* A bio runs taller than its portrait, so consecutive rows close up unless the
     gap is bigger than the one used between grid portraits. */
  gap: var(--bh-s5);
}
/* A hairline between speakers, so a long bio does not run into the next name.
   Not on the first: it would fence the section off from its intro. */
.bh-team__member--row + .bh-team__member--row {
  border-top: 1px solid var(--bh-rule);
  padding-top: var(--bh-s5);
}
.bh-team__member--row .elementor-image-box-img {
  width: 132px;
  flex: 0 0 132px;
}
.bh-team__member--row .elementor-image-box-wrapper {
  display: flex;
  align-items: flex-start;
  gap: var(--bh-s3);
  text-align: left;
}
.bh-team__member--row .elementor-image-box-content { flex: 1 1 auto; }
.bh-team__member--row .elementor-image-box-description {
  margin-top: 0.55rem;
  color: var(--bh-ink-700);
  font-size: 0.9375rem;
  line-height: 1.65;
  max-width: 62ch;   /* the bios run long; keep them readable */
}
@media (max-width: 34rem) {
  /* On a narrow screen the portrait beside a paragraph leaves neither enough
     room, so the row becomes a stack of its own. */
  .bh-team__member--row .elementor-image-box-wrapper { flex-direction: column; }
  .bh-team__member--row .elementor-image-box-img { width: 108px; flex-basis: auto; }
}


/* ===========================================================================
   The training calendar on /trainings/, and its preview popup.

   Events Manager wraps this markup in `.em.pixelbones`, its own CSS framework,
   which resets typography and spacing - the same thing that flattened the step-1
   layout. Every rule here is therefore chained to `.em-calendar-preview` or
   `.em-modal-popup` so it outranks pixelbones without a single `!important`,
   and so nothing leaks into EM output elsewhere. `.em.pixelbones`
   sits on the SAME element as `.em-calendar-preview`, so chaining the two raises
   these to 0,4,0 - pixelbones sets font-size, border-radius and background on
   `.button` at a specificity that beat 0,3,0, which is why the first attempt
   took the font and weight but not the size, radius or fill.

   The event pills themselves are coloured by `dbem_category_default_color`, a
   database setting, not from here: EM writes it inline as
   `--event-background-color`. It is the brand aubergine because white on EM's
   default lime measured 2.41:1.
   ======================================================================== */

.em-modal-popup,
.em-calendar-preview {
  --bh-ink-900: oklch(0.26 0.006 320);
  --bh-ink-700: oklch(0.38 0.006 320);
  --bh-ink-500: oklch(0.52 0.008 320);
  --bh-rule:    oklch(0.90 0.008 320);
  --bh-raised:  #fff;
  --bh-teal:    #26C5AA;
  --bh-teal-ink: oklch(0.42 0.085 175);
  --bh-aub:     #734CA0;
  --bh-sans:    "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --bh-radius:  14px;
}

/* --- the popup shell ----------------------------------------------------- */
.em-modal-popup .em-modal-content {
  font-family: var(--bh-sans);
  color: var(--bh-ink-700);
  background: var(--bh-raised);
  border: 1px solid var(--bh-rule);
  border-radius: var(--bh-radius);
  box-shadow: 0 1px 2px oklch(0.26 0.006 320 / 0.05),
              0 18px 44px -18px oklch(0.26 0.006 320 / 0.28);
  overflow: hidden;
}

/* --- the event inside it ------------------------------------------------- */
.em.pixelbones.em-calendar-preview .em-item-title,
.em.pixelbones.em-calendar-preview .em-event-title,
.em-calendar-preview .em-item-title a,
.em-calendar-preview .em-event-title a {
  font-family: var(--bh-sans);
  font-weight: 700;
  font-size: 1.05rem;
  line-height: 1.35;
  color: var(--bh-ink-900);
  text-decoration: none;
  text-wrap: balance;
}
.em-calendar-preview .em-item-title a:hover,
.em-calendar-preview .em-event-title a:hover { color: var(--bh-teal-ink); }

.em.pixelbones.em-calendar-preview .em-item-meta,
.em.pixelbones.em-calendar-preview .em-item-meta-line {
  font-family: var(--bh-sans);
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--bh-ink-500);
}
/* EM draws these icons as a background-image SVG, not a font glyph or a mask,
   so `color` cannot reach them - an earlier rule setting them aubergine did
   nothing at all. Only `filter` can recolour a background SVG, and there is no
   filter chain that lands on an arbitrary brand hue, so the meta icons keep
   their own colour. The one that has to change is white-on-teal, below. */
.em-calendar-preview .em-icon { opacity: 1; }

/* Every meta line is identical: one face, size, weight and colour. An earlier
   version gave date and time more weight, then more colour, as a hierarchy -
   both read as an inconsistency rather than as emphasis, so the block is now
   uniform and the icons carry the distinction between the lines. */
.em-modal-popup .em-item-meta-line,
.em.pixelbones.em-calendar-preview .em-item-meta-line {
  font-weight: 400 !important;
  color: var(--bh-ink-700) !important;
}

/* --- actions ------------------------------------------------------------- */
.em-calendar-preview .em-item-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }

/* DESIGN.md fixes these: Montserrat 600 at 0.9375rem, pill radius, Title Case.
   The size and weight are part of the spec, not incidental - they match the
   site header's buttons so this popup does not introduce a second button voice.

   These carry !important. Chaining
   `.em.pixelbones` to reach 0,4,0 was not enough: the font family and weight
   took, and font-size, border-radius, background and text-transform did not, so
   whatever sets those is heavier still - the theme renders the label as
   "MORE INFO", uppercase and letterspaced, which no rule here asks for. Rather
   than keep escalating selectors against a framework we do not control, the six
   properties that were losing are forced, and only inside the popup. */
.em.pixelbones.em-calendar-preview .em-item-actions .button,
.em.pixelbones.em-calendar-preview .em-item-actions a.button,
.em-modal-popup .em-item-actions .button,
.em-modal-popup .em-item-actions a.button {
  font-family: var(--bh-sans);
  font-weight: 600 !important;
  font-size: 0.9375rem !important;
  text-transform: none !important;
  letter-spacing: 0 !important;
  border-radius: 99px !important;
  padding: 0.7rem 1.35rem !important;
  /* The theme sets display:block with line-height:38px against 15.6px of
     content box, which drops the label below centre. Flex centres it on both
     axes and lets the padding decide the height. */
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 0.45rem !important;
  line-height: 1.2 !important;
  height: auto !important;
  border-radius: 99px;
  /* The navbar's Log In: white, brand ink, a 2px teal ring. Measured off
     span.loginm rather than guessed - the ink there is #2D2D2D, which is not
     DESIGN.md's #403E41, and matching the button people already know beats
     matching the token. */
  border: 2px solid var(--bh-teal) !important;
  background: #fff !important;
  color: #2D2D2D !important;
  text-decoration: none;
  line-height: 1.2;
  transition: none !important;
}
/* Log In and Sign Up swap on hover - filled becomes outlined and outlined
   becomes filled. The navbar does it instantly (transition-duration 0s), so
   these do too rather than introducing a timing the site does not use. */
.em-modal-popup .em-item-actions .button:hover,
.em.pixelbones.em-calendar-preview .em-item-actions .button:hover {
  background: var(--bh-teal) !important;
  color: #fff !important;
  border-color: var(--bh-teal) !important;
}

/* Book Now is the site's primary button: #26C5AA with white, per DESIGN.md.
   That pairing is the documented brand exception to the contrast floor. */
.em.pixelbones.em-calendar-preview .em-item-actions .em-event-book-now,
.em.pixelbones.em-calendar-preview .em-item-actions a.em-event-book-now,
.em-modal-popup .em-item-actions .em-event-book-now,
.em-modal-popup .em-item-actions a.em-event-book-now {
  background: var(--bh-teal) !important;
  border-color: var(--bh-teal) !important;
  color: #fff !important;
}
/* brightness(0) crushes the SVG to black, invert(1) lifts it to white - the one
   reliable way to recolour a background-image icon. */
.em-modal-popup .em-item-actions .em-event-book-now .em-icon,
.em.pixelbones.em-calendar-preview .em-item-actions .em-event-book-now .em-icon,
.em-modal-popup .em-item-actions .button:only-child .em-icon,
.em.pixelbones.em-calendar-preview .em-item-actions .button:only-child .em-icon {
  filter: brightness(0) invert(1);
}

/* A lone action is the primary action. When bookings are closed EM renders only
   "More Info", and an outline button on its own reads as disabled rather than
   as the one thing to do. */
.em-modal-popup .em-item-actions .button:only-child,
.em.pixelbones.em-calendar-preview .em-item-actions .button:only-child {
  background: var(--bh-teal) !important;
  border-color: var(--bh-teal) !important;
  color: #fff !important;
}

.em-modal-popup .em-item-actions .em-event-book-now:hover,
.em.pixelbones.em-calendar-preview .em-item-actions .em-event-book-now:hover,
.em-modal-popup .em-item-actions .button:only-child:hover,
.em.pixelbones.em-calendar-preview .em-item-actions .button:only-child:hover {
  background: #fff !important;
  color: #2D2D2D !important;
  border-color: var(--bh-teal) !important;
}

/* The ticket icon is forced white for the teal fill; on hover the fill goes
   white, so the icon has to come back or it vanishes into the button. */
.em-modal-popup .em-item-actions .em-event-book-now:hover .em-icon,
.em.pixelbones.em-calendar-preview .em-item-actions .em-event-book-now:hover .em-icon,
.em-modal-popup .em-item-actions .button:only-child:hover .em-icon,
.em.pixelbones.em-calendar-preview .em-item-actions .button:only-child:hover .em-icon {
  filter: none !important;
}

.em.pixelbones.em-calendar-preview .em-item-actions .button:focus-visible {
  outline: 3px solid var(--bh-aub);
  outline-offset: 2px;
}

/* --- the placeholder tile when an event has no image --------------------- */
.em.pixelbones.em-calendar-preview .em-item-image-placeholder {
  background: oklch(0.975 0.012 175);
  color: var(--bh-teal-ink);
  border-radius: 10px;
}
.em-calendar-preview .em-item-image-placeholder .day { font-weight: 700; }

@media (prefers-reduced-motion: reduce) {
  .em-calendar-preview .em-item-actions .button { transition-duration: 0.01ms; }
}


/* ===========================================================================
   Booking confirmation — the last screen in the flow
   ---------------------------------------------------------------------------
   On success Events Manager inserts

     <div class="em-booking-message em-booking-message-success">

   as a sibling before the form, then hides every form section except the
   summary. So this box, the chosen-session card and the total bar are the whole
   page. It was EM's Bootstrap alert - #d1e7dd on #0f5132, 2.5px radius, 13px
   text - which is the only thing in the flow still looking like the plugin, and
   it carried less weight than the session card above it despite being the end
   of a paid transaction.

   EM sets !important on padding, margin, border, border-radius, display,
   color, background-color and border-color, so every one of those has to be
   answered in kind. That is the reason for the !important below; it is not
   habit.

   !important alone is not enough, and neither is one anchor. EM styles this
   box from three rules of increasing specificity, and they do not all carry the
   same properties - which is why a half-working override looks so confusing:

     .em-booking-message                                   (0,1,0)
         padding, margin, border, border-radius, display
     .em-booking-message.em-booking-message-success        (0,2,0)
         colour, background-colour, border-colour
     .em.em-event-booking-form .em-booking-message         (0,4,0)
       .em-booking-message-success
         colour, background-colour, border-colour - again

   Beating only the first two gets the shape right and leaves the box still
   Bootstrap green, because the colours are re-asserted at (0,4,0). Every
   selector below therefore carries .bh-booking .em.em-event-booking-form for
   (0,5,0), which wins outright rather than depending on an enqueue order a
   plugin update could reshuffle.

   Both states are styled, not just success. They are one component sharing one
   selector base, so restyling only the success variant would take more code and
   leave the error - seen at a worse moment - looking foreign.
   ======================================================================== */

.bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-success,
.bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-error {
  --bh-ink-900: oklch(0.26 0.006 320);
  --bh-ink-700: oklch(0.38 0.006 320);
  --bh-ink-500: oklch(0.52 0.008 320);
  --bh-rule:    oklch(0.90 0.008 320);
  --bh-raised:  #fff;
  --bh-teal:    #26C5AA;
  /* No semantic red in the kit - derived here in the same oklch idiom, tinted
     toward the brand hue like every other neutral rather than a stock red. */
  --bh-danger:  oklch(0.52 0.170 22);

  font-family: var(--bh-sans, "Montserrat", ui-sans-serif, system-ui, sans-serif);

  /* Icon in its own column so a message that wraps aligns to the text column
     instead of running back under the tick. */
  display: grid !important;
  grid-template-columns: auto 1fr;
  align-items: start;
  gap: 0.875rem;

  margin: 0 0 1.75rem !important;
  padding: 1.5rem 1.75rem !important;

  /* The confirmation is the page's raised surface, matching .bh-panel. The
     session card above it is already a pale teal wash; washing this one too
     would stack two tinted boxes and flatten the hierarchy at the exact moment
     it matters most. White plus a teal mark gives it the presence instead. */
  background-color: var(--bh-raised) !important;
  border: 1px solid var(--bh-rule) !important;
  border-radius: 14px !important;
  box-shadow: 0 1px 2px oklch(0.26 0.006 320 / 0.05),
              0 8px 24px -12px oklch(0.26 0.006 320 / 0.14);

  color: var(--bh-ink-900) !important;
  /* Sized against .bh-panel__title rather than body copy. This is the last
     screen in a paid transaction; at 17px it read quieter than the session card
     sitting above it, which is the wrong way round. */
  font-size: clamp(1.15rem, 1.09rem + 0.28vw, 1.3rem);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.3;
  text-wrap: pretty;
}

/* The mark. Drawn in CSS - no asset, no request, and it recolours with the
   token. Teal is the affirmative colour everywhere else on this site, so a
   stock Bootstrap green here would be reintroducing the second colour system
   this rule exists to remove. */
.bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-success::before,
.bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-error::before {
  content: "";
  width: 1.625rem;
  height: 1.625rem;
  border-radius: 50%;
  background-color: var(--bh-teal);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 0.875rem;
  /* stroke is #fff */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 8.5l3.5 3.5 7.5-7.5'/%3E%3C/svg%3E");
  /* Optical alignment to the cap height of the first line, not the line box. */
  margin-top: 0.0625rem;
  flex: none;
}

.bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-error::before {
  background-color: var(--bh-danger);
  background-size: 0.8125rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M8 3.5v5.5M8 12.2v.3'/%3E%3C/svg%3E");
}

/* EM's own <p> spacing inside the message, plus its !important colour. */
.bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-success p,
.bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-error p {
  margin: 0 !important;
  color: inherit !important;
  font: inherit;
}
.bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-success p + p,
.bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-error p + p {
  /* A second paragraph is the supporting line - what happens next - so it
     steps down in weight and size rather than repeating the headline. It stays
     at --bh-ink-700, the body-text token, not the --bh-ink-500 hint grey: this
     is the only place the buyer is told an email is coming, which makes it
     content, not a hint. */
  margin-top: 0.4375rem !important;
  color: var(--bh-ink-700) !important;
  font-size: 0.9375rem;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0;
}
.bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-success > :nth-child(2),
.bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-error > :nth-child(2) {
  grid-column: 2;
}

/* A message arriving is the one moment on this page worth marking. Single
   element, single transition - not entrance choreography. `backwards` only, so
   if animations never run the box still renders at its normal state rather
   than being gated invisible. */
@media (prefers-reduced-motion: no-preference) {
  .bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-success,
  .bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-error {
    animation: bh-confirm-in 160ms cubic-bezier(0.16, 1, 0.3, 1) backwards;
  }
}
@keyframes bh-confirm-in {
  from { opacity: 0; transform: translateY(-4px); }
}

/* 1.75rem of side padding is 56px of a 375px screen. Step it down so the
   message keeps its measure on a phone; the icon column stays put, so the
   wrapped supporting line still aligns under the headline rather than under
   the tick. */
@media (max-width: 30rem) {
  .bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-success,
  .bh-booking .em.em-event-booking-form .em-booking-message.em-booking-message-error {
    padding: 1.25rem 1.125rem !important;
    gap: 0.75rem;
  }
}

/* --- the total bar, once the booking is done ----------------------------- */
/* The submit button lives in the confirm section, which EM hides on success -
   so the bar is left as a heavy, shadowed action bar with nothing to action.
   In this state it is a receipt line: same content, none of the urgency. */
.bh-booking:has(.em-booking-message-success) .bh-total-bar {
  position: static;
  box-shadow: none;
  background: transparent;
  border-color: var(--bh-rule);
  padding-block: 1rem;
}
