<style>

/* ============================================================
   PAGE TRANSITIONS — native View Transitions API
   ------------------------------------------------------------
   Opts every same-origin navigation into a crossfade. Browsers
   without support just navigate normally (graceful fallback).
   No JS and no wrapper library needed. Must be present in the
   <head> CSS of every page (global site code covers this).
   ============================================================ */
@view-transition {
  navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.45s;
  animation-timing-function: ease;
}

/* ============================================================
   FILTER STACK QUERY
   ============================================================ */
input[data-filtered]::placeholder {
  color: currentColor;
  opacity: 1;
}

.filter_checkbox_field:has(.w--redirected-checked) {
  background: var(--_theme---background-2);
  padding-right: 0.5em;
  padding-left: 0.5em;
}

/* ============================================================
   SWIPER CAROUSEL
   ============================================================ */

/* Container */
[data-swiper-wrap] {
  overflow: hidden;
  position: relative;
}

/* Nav buttons */
[data-swiper-prev],
[data-swiper-next] {
  display: flex;
  flex-grow: 2;
  align-items: center;
  justify-content: center;
  width: auto;
  height: 2.5rem;
  color: var(--_theme---text);
  cursor: pointer;
  transition:
    background-color 0.2s ease,
    border-color 0.2s ease;
}

[data-swiper-prev]:hover,
[data-swiper-next]:hover {
  opacity: 0.75;
}

[data-swiper-prev].swiper-button-disabled,
[data-swiper-next].swiper-button-disabled {
  opacity: 0.35;
  pointer-events: none;
}

/* Pagination pill — floating fixed at viewport bottom, centered */
/* width uses !important to beat Swiper's .swiper-pagination-bullets.swiper-pagination-horizontal (0,2,0 specificity) */
[data-swiper-pagination] {
  position: static;
  inset: auto 0 0.5rem;
  width: 5% !important;
  background: transparent;
  padding: var(--_spacing---space--2);
  border-radius: 100vw;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
}

/* Base bullet — solid color, opacity controls the visual hierarchy */
.swiper-pagination-bullet {
  position: relative;
  flex-shrink: 0;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--radius--round);
  background: var(--_theme---text);
  overflow: hidden;
  cursor: pointer;
  margin: 0 !important;
  transition:
    width 0.45s cubic-bezier(0.4, 0, 0.2, 1),
    opacity 0.3s ease;
}

/* 1 step away */
.swiper-pagination-bullet:has(+ .swiper-pagination-bullet-active),
.swiper-pagination-bullet-active+.swiper-pagination-bullet {
  opacity: 0.65;

}

/* 2 steps away */
.swiper-pagination-bullet:has(+ * + .swiper-pagination-bullet-active),
.swiper-pagination-bullet-active+*+.swiper-pagination-bullet {
  opacity: 0.5;

}

/* 3 steps away */
.swiper-pagination-bullet:has(+ * + * + .swiper-pagination-bullet-active),
.swiper-pagination-bullet-active+*+*+.swiper-pagination-bullet {
  opacity: 0.35;

}

/* 4 steps away */
.swiper-pagination-bullet:has(+ * + * + * + .swiper-pagination-bullet-active),
.swiper-pagination-bullet-active+*+*+*+.swiper-pagination-bullet {
  opacity: 0.15;

}

/* Progress Track */
.swiper-pagination-bullet-active {
  width: 3rem;
  background: color-mix(in lab, var(--_theme---text) 20%, transparent);
  backdrop-filter: blur(10px);
}

/* Progress fill */
.swiper-bullet-progress {
  display: block;
  position: absolute;
  inset: 0;
  background: var(--_theme---text);
  transform-origin: left center;
  transform: scaleX(0);
  border-radius: inherit;
}

/* ============================================================
   SWIPER — GENERIC SLIDER COMPONENT
   ------------------------------------------------------------
   Pairs with initGenericSliders() in obel-slater.js. Previously
   duplicated per-instance inside a Webflow embed (along with its
   own Swiper CDN + init script); now lives here so styling loads
   once regardless of how many slider instances are on the page.
   Custom bullet classes (slider_bullet_item / is-active, set in
   the JS pagination config) keep this scoped away from the hero's
   own .swiper-pagination-bullet rules above.

   Scoped under [data-slider="component"] — the generic slider's
   own root marker — rather than bare .slider_list, because the
   hero wrap reuses the .slider_list class too. Unscoped, this
   rule's width/flex sizing was landing on hero slides and fighting
   the fade effect, which needs full-size stacked slides, not
   slide-count-based widths.
   ============================================================ */
html [data-slider="component"] .slider_list> :not(.u-display-contents, .w-dyn-list),
[data-slider="component"] .slider_list>.w-dyn-list>*>*>*,
[data-slider="component"] .slider_list>.u-display-contents>*,
[data-slider="component"] .slider_list>.u-display-contents>.u-display-contents>*,
[data-slider="component"] .slider_list>.u-display-contents>.w-dyn-list>*>*>*,
[data-slider="component"] .slider_list>.u-display-contents>.u-display-contents>.w-dyn-list>*>*>* {
  padding-inline: calc(var(--_gap---size) / 2);
  flex: 0 0 auto;
  width: calc(100% / var(--slide-count));
}

/* ============================================================
   CARD PRIMARY — "Past Winners" variant height fix
   ------------------------------------------------------------
   The slider-generic height:auto carve-out below fixed the outer
   slide (.card_primary_wrap) correctly filling its row height, but
   didn't fix the actual collapse: confirmed live on
   /programmes/programme/obel-award that this specific Card Primary
   component variant (w-variant-51efa20c-c7be-48fe-973a-11367f19d622,
   used for the "Past winners" slider) is missing the height:100%
   that the working variant (w-variant-b0b5a6d5-8477-61e5-f611-
   74d937df47a5) has on .card_primary_group/.card_primary_element.
   Without it, those elements — despite being flex/display:flex —
   size to their own text content instead of stretching to fill
   .card_primary_wrap, so .card_primary_visual (position:absolute,
   inset 0 in this variant) has nothing to fill and the background
   image never appears. This can't be set via the Designer's
   component-variant style API from here, so it's patched with a
   combo-class override targeting Webflow's own w-variant-* class
   that's already rendered in the DOM for this variant. Verified
   live via temporary style injection before adding here — the
   default aspect-ratio wrap for the card should still work
   correctly across breakpoints, and the fill technique matches
   what the working variant already relies on.
   ============================================================ */
.card_primary_group.w-variant-51efa20c-c7be-48fe-973a-11367f19d622,
.card_primary_element.w-variant-51efa20c-c7be-48fe-973a-11367f19d622 {
  height: 100% !important;
}

/* height:auto is only correct for slide content that should size to its own
   content (e.g. text-based cards) rather than stretch to match Swiper's
   row height. Full-bleed image cards — anything built on .card_primary_visual
   (position:relative wrapper around an absolute-positioned, height:100% image,
   used by Card Primary / the Past Winners & Award Winners slider cards) —
   need that height:100% to flow all the way down from .swiper-slide, or the
   image collapses to 0 and the card renders as a thin text-only band. This
   was the cause of the Past Winners cards collapsing: the generic rule above
   used to force height:auto !important on every slide's content regardless
   of card type, cutting off the height chain a .card_primary_visual depends
   on. Carved out here instead of on the shared rule above so non-fill cards
   keep their original auto-height behavior. */
html [data-slider="component"] .slider_list> :not(.u-display-contents, .w-dyn-list):not(:has(.card_primary_visual)),
[data-slider="component"] .slider_list>.w-dyn-list>*>*>*:not(:has(.card_primary_visual)),
[data-slider="component"] .slider_list>.u-display-contents>*:not(:has(.card_primary_visual)),
[data-slider="component"] .slider_list>.u-display-contents>.u-display-contents>*:not(:has(.card_primary_visual)),
[data-slider="component"] .slider_list>.u-display-contents>.w-dyn-list>*>*>*:not(:has(.card_primary_visual)),
[data-slider="component"] .slider_list>.u-display-contents>.u-display-contents>.w-dyn-list>*>*>*:not(:has(.card_primary_visual)) {
  height: auto !important;
}

[data-slider="component"] .slider_button_layout:not(:has(button:not(:disabled))) {
  display: none;
}

/* ============================================================
   GRID Inner border
   ============================================================ */
/* > 991px */
@media (min-width: 992px) {
  .u-grid-wrapper.u-border-children .u-grid>*:not(:first-child) {
    border-left: var(--border-width--main) solid var(--_theme---border);
    padding-left: var(--_gap---size);
  }
}

/* ≤ 991px */
@media (max-width: 991px) {
  .u-grid-wrapper.u-border-children .u-grid>*:not(:first-child) {
    border-bottom: var(--border-width--main) solid var(--_theme---border);
    padding-bottom: var(--_gap---size);
  }
}

/* ============================================================
   RICH TEXT — Figure styles
   ============================================================ */

/* --- Shared figure base --- */
.u-rich-text figure {
  margin: 0;
}

/* Default (unaligned) figure — a Webflow image inserted without picking an
   explicit alignment. The float/center/fullwidth variants below each set
   their own margin; this is the case the reset above otherwise leaves at
   zero, since headings/paragraphs in this design carry margin-bottom only
   (no margin-top), so nothing else fills the gap below the image. Matches
   the center variant's spacing for visual consistency. */
.u-rich-text figure:not([class*="w-richtext-align-"]) {
  margin-bottom: 2rem;
}

.u-rich-text figure figcaption {
  font-size: var(--_typography---font-size--text-small);
  color: var(--_theme---text-faded);
  margin-top: 0.25rem;
  text-align: center;
}

/* ============================================================
   RTE MEDIA FLOAT LEFT
   ============================================================ */

.u-rich-text .w-richtext-align-floatleft {
  float: left;
  margin-right: 4rem;
  margin-bottom: 100%;
  width: 45%;
}

/* Image */
.u-rich-text .w-richtext-align-floatleft.w-richtext-figure-type-image div img {
  width: 100%;
  height: auto;
  display: block;
}

/* Video */
.u-rich-text .w-richtext-align-floatleft.w-richtext-figure-type-video {
  width: 50%;
}

.u-rich-text .w-richtext-align-floatleft.w-richtext-figure-type-video div {
  position: relative;
  padding-bottom: 56.25%;
  /* 16:9 */
  height: 0;
  overflow: hidden;
}

.u-rich-text .w-richtext-align-floatleft.w-richtext-figure-type-video div iframe,
.u-rich-text .w-richtext-align-floatleft.w-richtext-figure-type-video div video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

/* ============================================================
   RTE MEDIA FLOAT RIGHT
   ============================================================ */

.u-rich-text .w-richtext-align-floatright {
  float: right;
  margin-left: 2rem;
  margin-bottom: 1rem;
  width: 45%;
}

/* Image */
.u-rich-text .w-richtext-align-floatright.w-richtext-figure-type-image div img {
  width: 100%;
  height: auto;
  display: block;
}

/* Video */
.u-rich-text .w-richtext-align-floatright.w-richtext-figure-type-video {
  width: 50%;
}

.u-rich-text .w-richtext-align-floatright.w-richtext-figure-type-video div {
  position: relative;
  padding-bottom: 56.25%;
  height: 0;
  overflow: hidden;
}

.u-rich-text .w-richtext-align-floatright.w-richtext-figure-type-video div iframe,
.u-rich-text .w-richtext-align-floatright.w-richtext-figure-type-video div video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

/* ============================================================
   CENTER
   ============================================================ */

.u-rich-text .w-richtext-align-center {
  float: none;
  clear: both;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 2rem 0;
}

/* Image */
.u-rich-text .w-richtext-align-center.w-richtext-figure-type-image div img {
  max-width: 100%;
  height: auto;
  display: block;
}

/* Video */
.u-rich-text .w-richtext-align-center.w-richtext-figure-type-video div {
  position: relative;
  width: 100%;
  padding-bottom: 56.25%;
  height: 0;
  overflow: hidden;
}

.u-rich-text .w-richtext-align-center.w-richtext-figure-type-video div iframe,
.u-rich-text .w-richtext-align-center.w-richtext-figure-type-video div video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

/* ============================================================
   FULL WIDTH
   ============================================================ */

.u-rich-text .w-richtext-align-fullwidth {
  float: none;
  clear: both;
  width: 100%;
  margin: 0rem 0 !important;

}

/* Image */
.u-rich-text .w-richtext-align-fullwidth.w-richtext-figure-type-image div img {
  width: 100% !important;
  height: auto;
  display: block;

}

/* Video */
.u-rich-text .w-richtext-align-fullwidth.w-richtext-figure-type-video div {
  position: relative;
  width: 100%;
  padding-bottom: 56.25%;
  height: 0;
  overflow: hidden;
}

.u-rich-text .w-richtext-align-fullwidth.w-richtext-figure-type-video div iframe,
.u-rich-text .w-richtext-align-fullwidth.w-richtext-figure-type-video div video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

/* ============================================================
   IMAGES — ALWAYS FLUSH & FULL WIDTH, REGARDLESS OF ALIGNMENT
   ------------------------------------------------------------
   Product decision: whatever alignment the editor picks in the
   RTE toolbar (float left/right, center, fullwidth) — or no
   alignment at all — every IMAGE figure renders edge-to-edge
   like the fullwidth variant above. This block sits after all
   the per-alignment rules so it wins ties in the cascade, and
   uses !important because it has to cancel layout side-effects
   those rules depend on once float is gone (floatleft's
   margin-bottom: 100% clearfix hack, floatright's side margins,
   center's flex centering, fullwidth's own !important width).
   Video figures are untouched and keep their per-alignment
   sizing above — this only targets w-richtext-figure-type-image.
   ============================================================ */
.u-rich-text figure.w-richtext-figure-type-image {
  float: none !important;
  clear: both !important;
  display: block !important;
  width: 100% !important;
  max-width: 100% !important;
  margin: 0 0 2rem !important;
}

.u-rich-text figure.w-richtext-figure-type-image div img {
  width: 100% !important;
  max-width: 100% !important;
  height: auto;
  display: block;
}

/* ============================================================
   FOOTNOTES — inline reference + aside note markers
   ------------------------------------------------------------
   Pairs with initRichTextFootnotes() in obel-slater.js. Both
   markers are circles of the same shape so the pairing reads at
   a glance, with inverted fill to distinguish where you are:
     - inline (in the article body): faint outline, dark number
     - aside (in the footnotes list): solid dark fill, white number
   ============================================================ */

/* --- Inline marker, inside the article body --- */
/* An <a>, not <sup> — see initRichTextFootnotes() for why. It's the anchor
   itself (not a wrapper around a smaller nested <a>) so the full circle is
   the click target, not just the number glyph. vertical-align: middle keeps
   it sitting on the same line as the surrounding text instead of floating
   above it like a true superscript. */
.u-rich-text .footnote-ref {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4em;
  height: 1.4em;
  margin-left: 0.15em;
  border: 1px solid var(--_theme---button-primary--border);
  color: var(--_theme---button-primary--text);
  background: var(--_theme---button-primary--background);
  border-radius: var(--radius--round, 100vw);
  padding: 0;
  font-family: var(--_typography---font--secondary-family);
  font-size: 0.55em;
  font-weight: 600;
  line-height: 1;
  text-decoration: none !important;
  vertical-align: middle;
  cursor: pointer;
  scroll-margin-top: var(--nav--height-total, 5.25rem);
}

/* --- Aside marker, inside the footnotes sidebar --- */
/* Not a real <a> — the note text can contain its own inline link, and
   nesting <a> tags is invalid HTML. The whole row (index + text) is made
   clickable via the delegated listener in initRichTextFootnotes() instead;
   role="link" + tabindex on the element keep it keyboard-reachable, and the
   focus-visible ring below gives that keyboard path a visible target. */
.aside-note {
  display: flex;
  align-items: baseline;
  gap: 0.6em;
  font-size: var(--_typography---font-size--text-small);
  font-family: var(--_typography---font--secondary-family);
  margin-bottom: 0.5rem;
  cursor: pointer;
  scroll-margin-top: var(--nav--height-total, 5.25rem);
}

.aside-note:focus-visible {
  outline: 2px solid var(--_theme---button-primary--background, currentColor);
  outline-offset: 3px;
  border-radius: var(--radius--main, 4px);
}

.aside-note__index {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 1.5em;
  height: 1.5em;
  border: 1px solid var(--_theme---button-primary--border);
  color: var(--_theme---button-primary--text);
  background: var(--_theme---button-primary--background);
  border-radius: var(--radius--round, 100vw);
  padding: 0;
  font-size: 0.7rem;
  font-weight: 600;
  line-height: 1;
  font-family: var(--_typography---font--secondary-family);
  text-decoration: none !important;
}

a:not([class]) {
  text-decoration: none;
}

/* ============================================================
   CLEARFIX — prevent float collapse on the RT element
   ============================================================ */
.u-rich-text::after {
  content: "";
  display: table;
  clear: both;
}

/* ============================================================
   GALLERY GRID — irregular editorial mosaic (opt-in)
   ------------------------------------------------------------
   Lives here rather than in page custom code: API writes to a
   page's custom code get clobbered by an open Designer session.

   Attributes set in the Designer:
     [data-gallery-list]            Collection List. Always gets the
                                     lightbox (see below) — on its own
                                     it does NOT touch layout, so the
                                     list keeps whatever the Designer
                                     already set (native Webflow grid,
                                     flex, whatever).
     [data-gallery-list="mosaic"]   Opt in to the irregular editorial
                                     mosaic grid defined in this block.
     [data-gallery-item]            Collection Item (the repeating slot)
     [data-gallery-media]           Image wrapper

   Every rule below that shapes layout (grid, spans, forced image
   sizing) is scoped under the "mosaic" value on purpose. Only the
   lightbox-adjacent bits — cursor affordance, drag prevention, caption
   type — stay unscoped, since a plain [data-gallery-list] still wants
   those.

   Slot positions repeat every 9 items, so any number of CMS
   images fills the mosaic without the rhythm breaking down.
   ============================================================ */

[data-gallery-list="mosaic"] {
  /* Single place to retune. Maps to existing Lumos site tokens so
     the gallery tracks the site scale rather than a parallel one. */
  --gallery-col-gap: var(--site--gutter);

  /* Heights are row spans over a deliberately small row unit. That
     is what lets slots stagger against each other instead of
     snapping to a shared baseline per band. Row gap stays 0 for the
     same reason — vertical room is baked into each span, not the gap. */
  --gallery-row-unit: 1vw;

  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gallery-col-gap);
  row-gap: 0;
  grid-auto-rows: var(--gallery-row-unit);

  /* Non-dense on purpose: dense would pull later small images back
     into earlier gaps and scramble the curated reading order. */
  grid-auto-flow: row;
}

/* align-self: start is load-bearing. Each item's grid area is taller
   than its image; the leftover rows below become the vertical gap. */
[data-gallery-list="mosaic"] [data-gallery-item] {
  align-self: start;
  min-width: 0;
}

/* Fill whatever wrapper sits between the item and the image
   (link block, div, figure) so aspect-ratio below governs.
   The caption is excluded — it must size to its own text. */
[data-gallery-list="mosaic"] [data-gallery-item]> :not([data-gallery-caption]) {
  display: block;
  width: 100%;
  height: 100%;
}

[data-gallery-list="mosaic"] [data-gallery-item] :is([data-gallery-media], img) {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Blocks the native drag ghost and the iOS long-press save sheet.
   Deliberately not pointer-events: none — that would take the image out
   of hit testing and break click-to-open. Captions stay selectable
   because this targets the media only. Unscoped: any gallery, mosaic
   or plain, opens in the same lightbox and wants this. */
[data-gallery-item] :is([data-gallery-media], img),
[data-lightbox-image] {
  -webkit-user-drag: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* Caption is injected by initGalleryCaptions() from the image's alt
   text — no alt, no element. In the mosaic it sits in the gap rows
   already reserved below each slot, so it costs the layout nothing;
   in a plain list it's just normal margin. Unscoped for the same
   reason as the drag-prevention rule above. */
[data-gallery-caption] {
  margin-top: var(--_spacing---space--2);
  font-size: var(--_typography---font-size--text-small);
  color: var(--_theme---text-faded);
  text-wrap: pretty;
}

/* --- The 9-slot cycle -------------------------------------------
   Columns set the composition; row span sets height plus trailing
   gap. Auto-placement only moves forward, so each slot lands in the
   first row where its columns are free — that produces the stagger
   without any explicit row numbers. */

/* 1 — tall portrait, flush left. Anchors the band. */
[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 1) {
  grid-column: 1 / span 5;
  grid-row: span 64;
}

[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 1) :is([data-gallery-media], img) {
  aspect-ratio: 3 / 4;
}

/* 2 — wide landscape, top right. */
[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 2) {
  grid-column: 9 / span 4;
  grid-row: span 26;
}

[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 2) :is([data-gallery-media], img) {
  aspect-ratio: 7 / 4;
}

/* 3 — square, pushed left of slot 2 and dropped below it. */
[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 3) {
  grid-column: 7 / span 3;
  grid-row: span 29;
}

[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 3) :is([data-gallery-media], img) {
  aspect-ratio: 1 / 1;
}

/* 4 — small landscape. Margin, not row span, does the drop: it
   offsets against slot 3 rather than reserving extra grid space. */
[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 4) {
  grid-column: 10 / span 3;
  grid-row: span 21;
  margin-top: calc(var(--gallery-row-unit) * 10);
}

[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 4) :is([data-gallery-media], img) {
  aspect-ratio: 3 / 2;
}

/* 5 — near-square, flush left. Opens the paired band. */
[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 5) {
  grid-column: 1 / span 4;
  grid-row: span 41;
}

[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 5) :is([data-gallery-media], img) {
  aspect-ratio: 8 / 9;
}

/* 6 — wide, right. Shares a baseline with slot 5. */
[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 6) {
  grid-column: 7 / span 6;
  grid-row: span 42;
}

[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 6) :is([data-gallery-media], img) {
  aspect-ratio: 3 / 2;
}

/* 7 — the hero. Inset from both edges so it reads as a pause. */
[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 7) {
  grid-column: 3 / span 9;
  grid-row: span 57;
}

[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 7) :is([data-gallery-media], img) {
  aspect-ratio: 3 / 2;
}

/* 8 — landscape, flush left. */
[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 8) {
  grid-column: 1 / span 4;
  grid-row: span 28;
}

[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 8) :is([data-gallery-media], img) {
  aspect-ratio: 10 / 7;
}

/* 9 — widescreen, right. Closes the cycle before it restarts. */
[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 9) {
  grid-column: 8 / span 5;
  grid-row: span 31;
}

[data-gallery-list="mosaic"] [data-gallery-item]:nth-child(9n + 9) :is([data-gallery-media], img) {
  aspect-ratio: 16 / 9;
}

/* --- Narrow viewports --------------------------------------------
   The mosaic collapses to a single full-width column. Switching to
   flex drops all grid placement automatically — grid-column and
   grid-row are simply inert on flex children, so none of the slot
   rules above need unwinding. */
@media (max-width: 47.9375em) {
  [data-gallery-list="mosaic"] {
    display: flex;
    flex-direction: column;
    gap: var(--_spacing---space--6);
  }

  [data-gallery-list="mosaic"] [data-gallery-item] {
    /* In a column flex container the cross axis is horizontal, so the
       align-self: start above would shrink items to content width. */
    align-self: stretch;

    /* margin-top is the one slot rule flex does NOT neutralise. */
    margin-top: 0;
  }

  /* At full width the per-slot ratios read as arbitrary crops. */
  [data-gallery-list="mosaic"] [data-gallery-item],
  [data-gallery-list="mosaic"] [data-gallery-item]>* {
    height: auto;
  }

  [data-gallery-list="mosaic"] [data-gallery-item] :is([data-gallery-media], img) {
    aspect-ratio: auto;
    height: auto;
  }
}

/* ============================================================
   GALLERY LIGHTBOX
   ------------------------------------------------------------
   Overlay DOM is injected by initGalleryLightbox() — nothing to
   add in the Designer. The image runs fullbleed edge-to-edge at
   full viewport width with no padding; all UI (controls + caption)
   floats on top of it as fixed-position chrome, coloured from the
   Lumos secondary-button theme tokens so it inverts correctly on
   dark sections without a second rule set. The scrim still derives
   from --_theme---text. If the image's natural height (at 100%
   width) exceeds the viewport, the root scrolls vertically instead
   of shrinking or cropping the image.
   ============================================================ */

[data-gallery-item] :is([data-gallery-media], img) {
  cursor: zoom-in;
}

/* Lock lives on <html>, not <body> — Webflow writes to body styles */
html[data-lightbox-open] {
  overflow: hidden;
}

[data-lightbox] {
  --lightbox-scrim: color-mix(in lab, var(--_theme---text) 94%, transparent);
  --lightbox-ui-bg: var(--_theme---button-secondary--background);
  --lightbox-ui-bg-hover: var(--_theme---button-secondary--background-hover);
  --lightbox-ui-text: var(--_theme---button-secondary--text);
  --lightbox-ui-text-hover: var(--_theme---button-secondary--text-hover);
  --lightbox-inset: var(--_spacing---space--5);

  position: fixed;
  inset: 0;
  /* Above the nav (100) but below the filter progress bar (9999) */
  z-index: 9998;
  /* No padding — the image is meant to run edge-to-edge. Vertical
     scroll is what handles images taller than the viewport. */
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
}

[data-lightbox][hidden] {
  display: none;
}

/* Fixed (not absolute) so it stays pinned to the viewport rather than
   scrolling away with the figure when a tall image is being scrolled. */
[data-lightbox-backdrop] {
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--lightbox-scrim);
  backdrop-filter: blur(8px);
}

[data-lightbox-figure] {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  /* min-height (not height) so a short/landscape image still centers
     vertically, while a tall image is free to grow past the viewport
     and drive the scroll on [data-lightbox]. */
  min-height: 100%;
  margin: 0;
  width: 100%;
}

[data-lightbox-image] {
  display: block;
  width: 100%;
  height: auto;
  /* Natural aspect ratio at full width — never cropped, never capped.
     A tall result just extends the figure and scrolls. */
  border-radius: 0;
}

/* Caption is UI chrome, not part of the image flow — pinned over the
   bottom of the image like the button controls. */
[data-lightbox-caption] {
  position: fixed;
  left: 50%;
  bottom: var(--lightbox-inset);
  translate: -50% 0;
  z-index: 1;
  max-width: min(80%, 60ch);
  padding: 0.6em 1.2em;
  border-radius: var(--radius--round);
  background: var(--lightbox-ui-bg);
  color: var(--lightbox-ui-text);
  font-size: var(--_typography---font-size--text-small);
  text-align: center;
  text-wrap: pretty;
}

/* No alt text — render() leaves it empty and it collapses entirely */
[data-lightbox-caption]:empty {
  display: none;
}

/* --- Controls --- */
[data-lightbox] button {
  position: fixed;
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius--round);
  background: var(--lightbox-ui-bg);
  color: var(--lightbox-ui-text);
  cursor: pointer;
  transition: background-color 0.2s ease, color 0.2s ease;
}

[data-lightbox] button:hover {
  background: var(--lightbox-ui-bg-hover);
  color: var(--lightbox-ui-text-hover);
}

[data-lightbox] button:focus-visible {
  outline: 2px solid var(--lightbox-ui-text);
  outline-offset: 3px;
}

[data-lightbox] button svg {
  width: 1.25rem;
  height: 1.25rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

[data-lightbox-prev] {
  left: var(--lightbox-inset);
  top: 50%;
  translate: 0 -50%;
}

[data-lightbox-next] {
  right: var(--lightbox-inset);
  top: 50%;
  translate: 0 -50%;
}

[data-lightbox-close] {
  top: var(--lightbox-inset);
  right: var(--lightbox-inset);
}

/* Single image — navigation would be a dead control */
[data-lightbox][data-lightbox-single] :is([data-lightbox-prev], [data-lightbox-next]) {
  display: none;
}

@media (max-width: 47.9375em) {
  [data-lightbox] {
    --lightbox-inset: var(--_spacing---space--3);
  }

  [data-lightbox] button {
    width: 2.5rem;
    height: 2.5rem;
  }

  /* Arrows move to the bottom edge: at this width, side-centered arrows
     sit on top of the image rather than beside it. */
  [data-lightbox-prev],
  [data-lightbox-next] {
    top: auto;
    bottom: var(--lightbox-inset);
    translate: none;
  }

  /* Clear the arrow row now sitting at the bottom edge */
  [data-lightbox-caption] {
    bottom: calc(var(--lightbox-inset) * 2 + 2.5rem);
    max-width: calc(100% - (2.5rem + var(--lightbox-inset)) * 2 - 1rem);
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-lightbox-backdrop] {
    backdrop-filter: none;
  }
}

/* ============================================================
   FORM VALIDATION — ERROR STATES
   ------------------------------------------------------------
   Pairs with initFormValidation() in obel-slater.js. Uses
   --_theme---error if it exists as a Webflow variable, falling
   back to a static red — swap in the real token once confirmed
   in Designer (Variables couldn't be read from this session).
   ============================================================ */
input.is-error {
  border-color: var(--_theme---error, #c0392b);
}

.form_field-error {
  display: none;
  margin-top: 0.375em;
  color: var(--_theme---error, #c0392b);
  font-size: 0.85em;
}

.form_field-error.is-active {
  display: block;
}

/* ============================================================
   SUBPAGE ANCHOR SUBNAV
   ------------------------------------------------------------
   Behaviour only. The pills are Button Anchor instances and keep
   their Designer styling; the strip's own position belongs to
   mega-nav.css ([data-subpage-toolbar]). See initSubnavAnchors()
   in obel-slater.js for the full markup contract.
   ============================================================ */

/* One line, at every width, always. The row scrolls sideways
   rather than wrapping: the strip is pinned to the top of the
   viewport while the user scrolls (mega-nav.js), so a second or
   third row of stacked pills would eat the phone screen at
   exactly the moment the page content matters most. */
[data-subnav-list] {
  display: flex;
  flex-flow: row nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  /* Firefox */
  -webkit-overflow-scrolling: touch;
  /* momentum scrolling on iOS */
  /* Stops a horizontal fling that has run out of row from being
     handed on to the page, where it reads as swipe-to-go-back. */
  overscroll-behavior-x: contain;
}

[data-subnav-list]::-webkit-scrollbar {
  display: none;
}

/* Pills keep their natural width instead of being squeezed to fit.
   Without this, flex shrinks them to fit the container and there is
   nothing left to scroll. */
[data-subnav-list]>* {
  flex: 0 0 auto;
}

/* Anchor jumps land below the fixed nav rather than under it - the
   same token as the footnote targets above.

   --nav--height-total is the Designer variable for exactly this:
   calc(var(--nav--height) + var(--nav--spacing-inner-vertical)),
   i.e. the nav plus its own inner padding, 84px at present. It
   replaced a hand-written calc() here that summed --nav--height and
   --_spacing---space--4 - which resolves to the identical number,
   because --nav--spacing-inner-vertical carries the same clamp as
   space--4. Same result, one token, and it keeps tracking the nav if
   that inner spacing is ever retuned.

   Done in CSS rather than with JS scroll maths so it also holds for a
   URL opened with a #hash, before any script has run. */
[data-subnav] {
  scroll-margin-top: var(--nav--height-total, 5.25rem);
}

/* Current-section state: initSubnavAnchors() puts `is-active` on the
   pill whose section is on screen. Deliberately unstyled here.

   A fallback lived at this spot and was quietly doing nothing.
   .button_anchor_wrap sets its own background-color, so any rule that
   is easy for the Designer to override is also outranked by the pill's
   own base class - it would have had to win against the Designer to be
   visible at all. Style the active state where the rest of the button
   is styled: add `is-active` as a combo on button_anchor_wrap. */

</style>
