/* My Visa Lawyer — behaviour styles.
 *
 * This file is loaded by BOTH the HTML prototype and the WordPress site, so the
 * behaviour that gets reviewed is the behaviour that ships. It contains only
 * what Elementor cannot express: the sticky header's compaction, the mobile
 * drawer, focus rings, and the decorative animation's containment.
 *
 * Everything else -- colour, type, spacing, the hero split, the service band --
 * is set in the Elementor templates as editable widget settings, so the site
 * owner can change it in the editor without touching CSS. Nothing here overrides
 * a value a person can edit in Elementor.
 *
 * Durations are 160-240ms per the art direction. There is no scroll hijacking,
 * no preloader, and no animation that delays content from rendering.
 */

:root {
  --sbl-header-h: 88px;
  --sbl-header-h-compact: 68px;
  --sbl-ui-fast: 160ms;
  --sbl-ui-slow: 240ms;
  --sbl-ui-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --sbl-drawer-w: 320px;
}

@media (max-width: 1024px) {
  :root { --sbl-header-h: 72px; --sbl-header-h-compact: 72px; }
}


/* ------------------------------------------------- a note on the selectors --
 * The position rules below repeat their class: `.sbl-header.sbl-header`.
 *
 * That is not a typo. Elementor's container stylesheet sets `position: relative`
 * on every `.e-con`, at the same specificity as a single class, and it is
 * enqueued after this file. A plain `.sbl-header { position: fixed }` therefore
 * loses, and the header renders in flow, 155px tall, with the drawer panel
 * pushed out into 3680px of horizontal overflow. Repeating the class doubles the
 * specificity and settles it without resorting to !important, which would take
 * the value away from anyone trying to change it later.
 *
 * Found by measuring a real WordPress page. Nothing static could see it: the CSS
 * was correct in isolation and lost an argument it was never told it was in.
 */

/* ---------------------------------------------------------------- header --
 * The bar is fixed and the spacer is a constant height, so compacting the bar
 * moves nothing below it. Making the bar itself `sticky` and animating its
 * height would reflow the whole document on every scroll, which is the layout
 * shift the art direction rules out.
 */
/* ------------------------------------------------- the WordPress admin bar --
 * A logged-in admin gets a fixed bar across the top of the viewport at
 * z-index 99999. Our header is fixed at z-index 100 and the drawer at 200, so
 * on a real host the bar sat over the header, and over the drawer's Close
 * control — which is the one thing a keyboard user needs to find.
 *
 * ANONYMOUS VISITORS ARE UNAFFECTED. --sbl-admin-bar is 0px unless
 * body.admin-bar is present, and WordPress only prints that class for someone
 * who is logged in and has the bar switched on.
 *
 * The two static values are WordPress's own: 32px, and 46px under 782px. They
 * are the no-JavaScript answer and the value before the script runs, so there
 * is no flash. sbl-ui.js then measures the bar's actual bottom edge on
 * scroll, which matters under 600px: there WordPress makes the bar
 * position:absolute so it scrolls away with the page, and a fixed 46px offset
 * would leave a 46px gap above the header for the rest of the visit.
 */
:root { --sbl-admin-bar: 0px; }
body.admin-bar { --sbl-admin-bar: 32px; }
@media screen and (max-width: 782px) {
  body.admin-bar { --sbl-admin-bar: 46px; }
}

.sbl-header.sbl-header {
  position: fixed;
  inset: var(--sbl-admin-bar) 0 auto 0;
  z-index: 100;
  height: var(--sbl-header-h);
  display: flex;
  align-items: center;
  transition: height var(--sbl-ui-slow) var(--sbl-ui-ease),
              box-shadow var(--sbl-ui-slow) var(--sbl-ui-ease),
              background-color var(--sbl-ui-slow) var(--sbl-ui-ease);
  will-change: height;
}

.sbl-header-spacer.sbl-header-spacer {
  height: var(--sbl-header-h);
  flex: 0 0 auto;
}

/* min-height too, or the compaction never happens on WordPress.
 *
 * The Elementor container carrying .sbl-header sets its own Min Height, which
 * Elementor writes as `--min-height: 88px` with `.e-con { min-height:
 * var(--min-height) }`. min-height CLAMPS the used height: it is a box-model
 * rule, so specificity, load order and the doubled-class trick are all
 * irrelevant to it. `height: 68px` could never take effect, and the bar stayed
 * 88px however far the reader scrolled.
 *
 * Worse than doing nothing, because the class was still added: the box-shadow
 * and the logo cap fired, so the wordmark shrank inside a bar that did not.
 *
 * Only the compact state overrides it. The resting height stays Elementor's,
 * which keeps the Min Height control meaningful to whoever opens the editor --
 * this file's own rule is that it never takes away a value a person can edit.
 *
 * Nothing caught this. The behaviour test drives the file:// prototype, whose
 * header is a plain <header> with no Elementor container, and the WordPress
 * acceptance run never scrolled. Both now do. */
.sbl-header.is-compact {
  height: var(--sbl-header-h-compact);
  min-height: var(--sbl-header-h-compact);
  box-shadow: 0 1px 0 rgba(37, 43, 48, 0.10), 0 6px 20px -12px rgba(37, 43, 48, 0.35);
}

/* The logo shrinks with the bar, and NEVER has both dimensions set at once.
 *
 * Two separate problems live here, and both needed the doubled class.
 *
 * 1. ASPECT. This rule used to say `height: 34px; width: auto`. Elementor's
 *    Image widget sets the width from its own control at higher specificity, so
 *    the two combined to pin both dimensions: the wordmark is 8.22:1 and it
 *    rendered at 6.82:1 on desktop and 4.41:1 on mobile. A 47% horizontal
 *    squeeze reads as a different logo, not as a smaller one. The width is now
 *    the editor's to set, the height follows from the file, and the compact
 *    state animates a max-width cap instead of a height.
 *
 * 2. SHRINKING. Elementor's width control also writes `max-width: 190px` on the
 *    image. At 320px the container correctly shrank to 145px and the image
 *    ignored it and carried on underneath the menu button -- overflowing
 *    nothing, so no edge check could see it. `max-width: 100%` at a single
 *    class loses to Elementor's per-element rule on load order; doubling the
 *    class wins it without !important, which would take the value away from
 *    anyone trying to change it later.
 *
 * min-width: 0 on the whole chain is what lets any of it shrink at all: a flex
 * item's min-width defaults to its content's width, which here is the image.
 */
.sbl-header__logo,
.sbl-header__logo .elementor-element,
.sbl-header__logo .elementor-widget-container,
.sbl-header__logo a { min-width: 0; max-width: 100%; }

.sbl-header__logo.sbl-header__logo img,
.sbl-header__logo.sbl-header__logo svg {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  transition: max-width var(--sbl-ui-slow) var(--sbl-ui-ease);
}

.sbl-header.is-compact .sbl-header__logo.sbl-header__logo img,
.sbl-header.is-compact .sbl-header__logo.sbl-header__logo svg { max-width: min(200px, 100%); }

/* ---------------------------------------------------------------- drawer --
 * Right-hand panel. Hidden with `visibility` as well as opacity so that nothing
 * inside it is focusable while closed -- an offscreen panel that is still in the
 * tab order is the usual accessibility failure in this pattern.
 */
.sbl-drawer.sbl-drawer {
  position: fixed;
  /* Below the admin bar, so the panel's Close control is reachable rather than
     sitting underneath it. The overlay stops short of the bar too, which is
     correct: the bar is not part of the site and dimming it would suggest the
     drawer had captured it. */
  inset: var(--sbl-admin-bar) 0 0 0;
  z-index: 200;
  visibility: hidden;
  pointer-events: none;
  /* The closed panel is parked at translateX(100%), which is 320px past the
     right edge of the viewport. A fixed ancestor does not clip it, so the
     document grows by 320px and the page scrolls sideways -- on a page that
     otherwise fits exactly. Clipping here costs nothing: the drawer covers the
     whole viewport and has nothing to show outside it. */
  overflow: hidden;
}

.sbl-drawer.is-open { visibility: visible; pointer-events: auto; }

.sbl-drawer__overlay.sbl-drawer__overlay {
  position: absolute;
  inset: 0;
  background: rgba(37, 43, 48, 0.45);
  opacity: 0;
  transition: opacity var(--sbl-ui-slow) var(--sbl-ui-ease);
}

.sbl-drawer.is-open .sbl-drawer__overlay { opacity: 1; }

.sbl-drawer__panel.sbl-drawer__panel {
  position: absolute;
  inset: 0 0 0 auto;
  width: var(--sbl-drawer-w);
  max-width: 90vw;
  background: var(--sbl-limestone, #F2EEE6);
  transform: translateX(100%);
  transition: transform var(--sbl-ui-slow) var(--sbl-ui-ease);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
  box-shadow: -18px 0 44px -28px rgba(37, 43, 48, 0.6);
}

.sbl-drawer.is-open .sbl-drawer__panel { transform: translateX(0); }

/* Scroll lock. Set on <html> by the controller, which also stores the scroll
   position so closing the drawer returns the reader to where they were. */
.sbl-scroll-locked {
  overflow: hidden;
  /* iOS Safari ignores overflow:hidden on <html> during momentum scrolling;
     the controller adds position:fixed with a top offset there. */
}

/* -------------------------------------------------------------- body links --
 * Elementor's Text Editor emits a plain <a>, and with no rule of its own the
 * theme's default wins. On the theme this ships against that default is bright
 * pink, which next to the brand's ink and accent simply looks broken, and on a
 * page about someone's visa it reads as a site nobody finished.
 *
 * Scoped to prose, so it cannot touch buttons, the nav, the drawer or the
 * footer, each of which sets its own link colour.
 *
 * Underlined rather than coloured alone: WCAG 1.4.1 is not satisfied by colour
 * by itself, and a reader with a colour deficiency needs the link to be
 * identifiable without it. The offset keeps descenders legible through the rule.
 */
.sbl-page-body .elementor-widget-text-editor a,
.sbl-page-body .elementor-widget-theme-post-content a,
.sbl-prose a {
  color: var(--sbl-copper-fill, #AA573B);
  text-decoration: underline;
  text-underline-offset: 0.18em;
  text-decoration-thickness: 0.07em;
}

.sbl-page-body .elementor-widget-text-editor a:hover,
.sbl-page-body .elementor-widget-theme-post-content a:hover,
.sbl-prose a:hover {
  text-decoration-thickness: 0.14em;
}

/* The focus ring below covers these; they do not declare a second one. */

/* ------------------------------------------------------------ focus ring --
 * A visible focus ring on every interactive element. :focus-visible so it does
 * not appear on mouse clicks, with a :focus fallback for browsers without it.
 */
.sbl-header a:focus-visible,
.sbl-header button:focus-visible,
.sbl-drawer a:focus-visible,
.sbl-drawer button:focus-visible,
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--sbl-copper-fill, #AA573B);
  outline-offset: 3px;
  border-radius: 2px;
}

/* -------------------------------------------------------- decorative art --
 * A route stroke drawn over the hero photograph. It carries no information, so
 * it is aria-hidden and its absence changes nothing.
 */
.sbl-route.sbl-route {
  position: absolute;
  pointer-events: none;
  z-index: 2;
}

/* The static fallback is what is in the DOM. The player, if it loads, is
   appended alongside and the fallback is hidden. If the player never loads --
   no network, an error, reduced motion -- the fallback simply stays. */
.sbl-route__fallback { display: block; width: 100%; height: 100%; }
.sbl-route.is-animating .sbl-route__fallback { display: none; }
.sbl-route__player { width: 100%; height: 100%; }

@media (prefers-reduced-motion: reduce) {
  /* Doubled, to match the rules these override. The rules that set these
     transitions had their class doubled to win against Elementor; written at a
     single class, every override here silently lost to them and a reader who
     had asked for reduced motion got the full 240ms animation anyway. */
  .sbl-header.sbl-header,
  .sbl-header__logo.sbl-header__logo img,
  .sbl-header__logo.sbl-header__logo svg,
  .sbl-drawer__overlay.sbl-drawer__overlay,
  .sbl-drawer__panel.sbl-drawer__panel { transition-duration: 1ms; }
  /* The route stroke is never played; the controller checks this same query. */
  .sbl-route.is-animating .sbl-route__fallback { display: block; }
  .sbl-route__player { display: none; }
}

/* The hero's trust line owns the space above it, at every width, so nothing
   above has to remember to leave room. Elementor sets this from the container's
   own margin control; the rule here is for the HTML prototype, which has no
   Elementor to set it. */
.sbl-hero__trust { margin-top: 24px; }

/* ------------------------------------------------ layout Elementor cannot do
 * Three things in this composition have no Elementor control behind them. They
 * are listed here rather than hidden in a template, so that anyone wondering
 * why a value cannot be changed in the editor can see exactly which ones.
 *
 * 1. object-fit. The hero photograph has to COVER a column whose height is set
 *    by the text beside it. Elementor's Image widget offers width and height,
 *    not object-fit, so an image told to fill would distort.
 * 2. Position for the decorative route stroke, which sits over the photograph.
 * 3. The hairline between the service band's three items at desktop only. The
 *    border itself is an editable container setting; only its removal at tablet
 *    width, where the items stack, is here.
 */

.sbl-hero-media.sbl-hero-media { position: relative; overflow: hidden; }

.sbl-hero-media > .elementor-widget-image,
.sbl-hero-media > .elementor-widget-image > .elementor-widget-container,
.sbl-hero-media > .elementor-widget-image figure,
.sbl-hero-media > .elementor-widget-image a { height: 100%; width: 100%; display: block; }

.sbl-hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* 50% 50% rather than centre.
     Where the horizon and the subject sit is a framing decision, and the crop
     that survives is the one the art direction asked for. Centre is only right
     by accident. */
  object-position: 50% 50%;
  display: block;
}

.sbl-hero-media .sbl-route.sbl-route {
  top: 5%;
  right: 4%;
  width: 32%;
  max-width: 300px;
  aspect-ratio: 300 / 220;
  height: auto;
}

/* The route stroke's resting artwork, for the Elementor build where the
   container is empty and the script has nothing to fall back to. Drawn in CSS
   so it needs no upload and no SVG in the media library. */
.sbl-hero-media .sbl-route::before {
  content: '';
  position: absolute;
  inset: 0;
  background: no-repeat center / contain
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 220' fill='none'%3E%3Cpath d='M292 6C196 60 118 146 40 210' stroke='%23B29665' stroke-width='1.5' stroke-linecap='round'/%3E%3Ccircle cx='40' cy='210' r='3.5' fill='%23B29665'/%3E%3C/svg%3E");
}
.sbl-hero-media .sbl-route.is-animating::before { display: none; }

@media (prefers-reduced-motion: reduce) {
  .sbl-hero-media .sbl-route.is-animating::before { display: block; }
}
/* Visual enrichment — ADDITIVE.
 *
 * A separate stylesheet on purpose. The deployed sbl-ui.css and
 * sbl-ui.js carry corrections made directly on the sites, and copying a
 * whole freshly built file over them would silently discard that work. This
 * file only ADDS, so it can be dropped in beside whatever is already there.
 */
/* ------------------------------------------------- visual enrichment ----
 *
 * Three added sections: an image/text feature, an illustrated process, and
 * the Jameson Law recognition block.
 *
 * EVERYTHING HERE SHIPS FINISHED. There is no opacity:0 and no transform that
 * hides content, because an element hidden in CSS and revealed by JavaScript
 * is invisible when the JavaScript fails — and the one thing worse than a
 * page with no animation is a page with no content. The script ADDS
 * .is-enrich-ready to <html>, and only then does anything start hidden.
 */
.sbl-enrich-feature,
.sbl-enrich-process,
.sbl-enrich-recognition { --sbl-enrich-gap: 32px; }

.sbl-enrich-feature__row { align-items: center; }

/* 3:2 supporting images, 20px radius, clipped so a hover scale cannot bleed. */
.sbl-enrich-frame {
  border-radius: 20px;
  overflow: hidden;
  line-height: 0;
}
.sbl-enrich-media img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: inherit;
}

/* Hover lift, fine pointers only: a touch device has no hover, and emulating
   one there leaves the effect stuck on after a tap. */
@media (hover: hover) and (pointer: fine) {
  .sbl-enrich-frame img {
    transition: transform 350ms cubic-bezier(.2, .7, .2, 1);
  }
  .sbl-enrich-frame:hover img { transform: scale(1.025); }
}

.sbl-enrich-icon img {
  width: 64px;
  height: 64px;
  display: block;
}

/* The process connector. Purely decorative, and absent below 3 columns. */
.sbl-enrich-connector {
  height: 1px;
  margin: 0 0 -1px;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--sbl-copper-fill, #AA573B) 45%, transparent),
    transparent);
  transform-origin: left center;
}

.sbl-enrich-recognition .sbl-enrich-awards img { max-width: 1030px; }
.sbl-enrich-recognition .sbl-enrich-associations img { max-width: 1200px; }
/* Never crop award artwork: it carries finalist/winner/year distinctions. */
.sbl-enrich-recognition img {
  object-fit: contain;
  margin-inline: auto;
}
.sbl-enrich-caption { opacity: .78; }

@media (max-width: 767px) {
  .sbl-enrich-feature,
  .sbl-enrich-process,
  .sbl-enrich-recognition { padding-block: 48px; }
  .sbl-enrich-connector { display: none; }
}

/* ---- motion, and only once the script says it is safe ---- */
.is-sbl-enrich-ready .sbl-enrich-reveal {
  opacity: 0;
  transform: translateY(16px);
}
.is-sbl-enrich-ready .sbl-enrich-reveal.is-visible {
  opacity: 1;
  transform: none;
  transition: opacity 500ms cubic-bezier(.2, .7, .2, 1),
              transform 500ms cubic-bezier(.2, .7, .2, 1);
}
.is-sbl-enrich-ready .sbl-enrich-connector { transform: scaleX(0); }
.is-sbl-enrich-ready .sbl-enrich-connector.is-visible {
  transform: scaleX(1);
  transition: transform 1200ms cubic-bezier(.2, .7, .2, 1);
}

/* A reader who has asked for less motion gets the finished page, immediately.
   Not a slower animation — none. */
@media (prefers-reduced-motion: reduce) {
  .is-sbl-enrich-ready .sbl-enrich-reveal,
  .is-sbl-enrich-ready .sbl-enrich-reveal.is-visible,
  .is-sbl-enrich-ready .sbl-enrich-connector,
  .is-sbl-enrich-ready .sbl-enrich-connector.is-visible {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .sbl-enrich-frame:hover img { transform: none; }
}

/* --- team and recognition geometry, per IMPLEMENTATION.md --- */
.sbl-enrich-team,
.sbl-enrich-recognition { padding-block: 72px; }
.sbl-enrich-team__row { align-items: center; }

/* A group photograph is never cropped: trimming its edges edits who is in it. */
.sbl-enrich-team .sbl-enrich-frame img,
.sbl-enrich-recognition img { object-fit: contain; height: auto; }

.sbl-enrich-team figcaption,
.sbl-enrich-recognition figcaption {
  font-size: .9em;
  opacity: .78;
  margin-top: 10px;
}

/*
 * The award strip at phone width.
 *
 * Six badges squeezed into 342px makes every year unreadable, and the years
 * and categories ARE the content — finalist is not winner, and Professional
 * Services is not Legal Services. So on a narrow screen the strip keeps a
 * legible minimum width and scrolls inside its own region, rather than the
 * page scrolling sideways. tabindex and role make that region reachable and
 * announced, because a scrollable box that only a mouse can reach is not
 * usable by everyone who needs it.
 */
@media (max-width: 767px) {
  .sbl-enrich-team,
  .sbl-enrich-recognition { padding-block: 40px; }
  .sbl-enrich-awards {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
  }
  .sbl-enrich-awards img { min-width: 0; max-width: 100%; width: 100%; height: auto; object-fit: contain; }
}

/* ------------------------------- live QA corrections, 23 September 2026 ----
 *
 * Found on the deployed My Visa Lawyer homepage, not in a mockup.
 */

/*
 * THE 62/38 ROW WRAPPED.
 *
 * Measured live: the row was 1137px, its children 705px (62%) and 432px (38%),
 * and the gap 48px. 705 + 432 + 48 = 1185. A percentage width is a share of
 * the CONTAINER, and the gap is added on top of it, so any pair of percentages
 * summing to 100 overflows by exactly the gap and the second child drops below
 * the first. The same arithmetic broke the 31% cards earlier in this project;
 * it is not a rounding error and no amount of shaving the percentages fixes it
 * honestly.
 *
 * The fix is to stop expressing the split as a width at all. flex-basis: 0
 * with flex-grow 62 and 38 divides the space that REMAINS after the gap, in
 * the same ratio, so the row always fits. min-width: 0 is not optional: a flex
 * child's automatic minimum size is its content, and a long unbroken word or a
 * wide image would otherwise push the row wide again from the inside.
 */
@media (min-width: 768px) {
  .sbl-enrich-team__row,
  .sbl-enrich-feature__row,
  .sbl-enrich-recognition .e-con-inner > .e-con,
  .sbl-enrich-recognition .elementor-element > .e-con-inner {
    flex-wrap: nowrap;
  }

  /* The feature bands wrap for the same reason and were measured doing it
     live: 48/52 plus a gap is more than 100% of the row. They do not need a
     ratio defended to the pixel, so both children simply share what is left
     after the gap. */
  .sbl-enrich-feature__row > .e-con,
  .sbl-enrich-feature__row > .elementor-element {
    flex: 1 1 0;
    width: auto;
    min-width: 0;
  }
  .sbl-enrich-team__row > .e-con,
  .sbl-enrich-team__row > .elementor-element {
    flex-basis: 0;
    width: auto;
    min-width: 0;
  }
  .sbl-enrich-team__row > .e-con:first-child,
  .sbl-enrich-team__row > .elementor-element:first-child { flex-grow: 62; }
  .sbl-enrich-team__row > .e-con:last-child,
  .sbl-enrich-team__row > .elementor-element:last-child { flex-grow: 38; }

  /* The award event row, 52/48, has the identical arithmetic. */
  .sbl-enrich-recognition .e-con > .e-con,
  .sbl-enrich-recognition .e-con > .elementor-element {
    min-width: 0;
  }
}

/* Below the breakpoint everything stacks, and the ratio stops applying. */
@media (max-width: 767px) {
  .sbl-enrich-team__row,
  .sbl-enrich-recognition .e-con-inner { flex-wrap: wrap; }
  .sbl-enrich-team__row > .e-con,
  .sbl-enrich-team__row > .elementor-element {
    flex-basis: 100%;
    width: 100%;
    min-width: 0;
  }
}

/*
 * CONTRAST. "Meet the team" rendered white on cream: measured 1.06:1, which is
 * not a near miss, it is invisible. WCAG AA wants 4.5:1 for body text.
 *
 * The brand accent is already the right answer and already passes, so this
 * takes the token rather than introducing a colour:
 *   teal  on cream  5.07:1  AA
 *   white on teal   5.37:1  AA
 *
 * The inline Jameson Law links were falling through to the theme's default
 * link colour, #cc3366. That happens to pass at 4.68:1, but it is another
 * brand's pink on a page that has an accent of its own, so it reads as a
 * mistake even where it is legible.
 */
.sbl-enrich-team a,
.sbl-enrich-recognition a,
.sbl-enrich-enquiry a {
  color: var(--sbl-copper-fill, #AA573B);
  text-decoration-color: color-mix(in srgb, var(--sbl-copper-fill, #AA573B) 45%, transparent);
}
.sbl-enrich-team a:hover,
.sbl-enrich-recognition a:hover,
.sbl-enrich-enquiry a:hover { text-decoration-color: currentColor; }

.sbl-enrich-team .elementor-button,
.sbl-enrich-team .elementor-button-text {
  color: var(--sbl-copper-fill, #AA573B);
  background-color: transparent;
}
/* Keyboard focus must stay visible against cream. */
.sbl-enrich-team a:focus-visible,
.sbl-enrich-recognition a:focus-visible,
.sbl-enrich-team .elementor-button:focus-visible {
  outline: 2px solid var(--sbl-copper-fill, #AA573B);
  outline-offset: 2px;
}

/*
 * DOUBLE PADDING.
 *
 * Measured live: the team and recognition sections were carrying 72px of
 * section padding from this stylesheet AND the 72/80px the Elementor container
 * already has from the builder, so every band opened with ~150px of blank
 * space. Two sources of truth for one value, and the page looked broken
 * because of it.
 *
 * ONE SOURCE WINS, AND IT IS THE NATIVE ONE. The builder's padding is what a
 * person sees and can change in the Elementor editor; a number in a stylesheet
 * is not. So the outer rule stands down to zero and the container keeps its
 * own. Anyone adjusting the rhythm later does it where they would expect to.
 */
.sbl-enrich-team,
.sbl-enrich-recognition,
.sbl-enrich-feature,
.sbl-enrich-process,
.sbl-enrich-enquiry { padding-block: 0; }

@media (max-width: 767px) {
  .sbl-enrich-team,
  .sbl-enrich-recognition,
  .sbl-enrich-feature,
  .sbl-enrich-process,
  .sbl-enrich-enquiry { padding-block: 0; }
}

/* --------------------------- recognition, rebuilt 23 September 2026 --------
 *
 * The live section was rejected on sight: a giant award strip and the event
 * photograph stacked in one column, with a caption stranded alone in the
 * other. A column containing nothing but a caption is the tell.
 *
 * One balanced row. Awards left in a restrained card, event photograph right,
 * and each caption directly beneath ITS OWN image.
 */
.sbl-enrich-recog-row {
  max-width: 1200px;
  margin-inline: auto;
  align-items: flex-start;
}

@media (min-width: 768px) {
  .sbl-enrich-recog-row { flex-wrap: nowrap; gap: 32px; }
  /* 1.35fr / 1fr, expressed as grow on a zero basis so the gap comes out of
     the shared space instead of overflowing the row. */
  .sbl-enrich-recog-row > .e-con,
  .sbl-enrich-recog-row > .elementor-element { flex-basis: 0; width: auto; min-width: 0; }
  .sbl-enrich-recog-row > :first-child { flex-grow: 1.35; }
  .sbl-enrich-recog-row > :last-child  { flex-grow: 1; }
}

/* The awards card: restrained, white, bordered. It is artwork on a page, not
   a banner. */
.sbl-enrich-recog-card--awards {
  background: #fff;
  border: 1px solid color-mix(in srgb, currentColor 12%, transparent);
  border-radius: 10px;
  padding: 16px;
}
.sbl-enrich-recog-card--awards img {
  /* Whole, never cropped: the distinctions and years are the content. */
  object-fit: contain;
  width: 100%;
  height: auto;
}
/* The event photograph keeps its own ratio. Cropping a photograph of people
   to match a neighbouring graphic is not a layout decision. */
.sbl-enrich-recog-row > :last-child img {
  width: 100%;
  height: auto;
  border-radius: 10px;
}

.sbl-enrich-divider {
  height: 1px;
  max-width: 1200px;
  margin: 40px auto 24px;
  background: color-mix(in srgb, currentColor 14%, transparent);
}

.sbl-enrich-associations { max-width: 760px; margin-inline: auto; }
.sbl-enrich-associations img {
  max-width: 760px;
  max-height: 88px;
  width: 100%;
  height: auto;
  object-fit: contain;
  margin-inline: auto;
}
.sbl-enrich-attrib {
  max-width: 760px;
  margin-inline: auto;
  font-size: 13px;
  opacity: .72;
  text-align: center;
}

@media (max-width: 767px) {
  .sbl-enrich-recog-row { flex-wrap: wrap; gap: 24px; }
  .sbl-enrich-recog-row > .e-con,
  .sbl-enrich-recog-row > .elementor-element {
    flex-basis: 100%; width: 100%; min-width: 0;
  }
  /* The award artwork stays legible by scrolling inside its own card rather
     than shrinking six badges into illegibility or pushing the page sideways.
     The focusable region is added by the script, and only when it overflows. */
  .sbl-enrich-recog-card--awards { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .sbl-enrich-recog-card--awards img { min-width: 0; max-width: 100%; width: 100%; height: auto; object-fit: contain; }
  .sbl-enrich-divider { margin: 28px auto 20px; }
}
