/* StraightTalk4u: page layout, bands and rhythm.
   ============================================================================
   Ported from the inline styles in "StraightTalk4u Website.dc.html", which is
   the approved design.

   Depends on assets/css/tokens.css and assets/css/components.css. Enqueue in
   that order.

   Two prototype artefacts are deliberately not ported.

   1. The header breakpoint. The prototype watches its own root element with a
      ResizeObserver and swaps the navigation at 1040px. That is a prototype
      artefact. The site's header is Kadence's, built in the header builder and
      rendered on the kadence_header hook, so the collapse is the parent theme's
      own drawer. Section 7 dresses that markup rather than a bespoke header.

   2. The marquee. The prototype animates it with no pause control, no hover
      pause and no reduced motion handling. WCAG 2.2 SC 2.2.2 requires a
      mechanism to pause any movement that starts automatically, lasts more than
      five seconds and runs beside other content. All three are added below.

   One block in this file uses !important: the forced colours rules in section
   1, which say why. Nothing else in the theme does.
   British English throughout. No em dashes and no en dashes.
   ========================================================================= */

/* ==========================================================================
   1. Page base
   ====================================================================== */

body {
  background: var(--canvas);
  color: var(--text-body);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

body a {
  color: var(--accent-strong);
}

body a:hover {
  color: var(--brand);
}

::selection {
  background: var(--accent);
  color: var(--white);
}

/* A visible focus indicator on every focusable thing that has not been given
   one by components.css. WCAG 2.2 AA, 2.4.7 Focus Visible. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}

/* The same ring for a link, at a weight Kadence cannot beat. Kadence takes the
   outline off a link under the pointer and while it is pressed (a:hover,
   a:active { outline: 0 }, 0,1,1), which outweighs the rule above (0,1,0): a
   link reached with the keyboard lost its ring whenever the pointer happened
   to be resting on it, on the menu, the footer, the privacy contents list and
   the enquiry link in the booking panel. This one is (0,1,1) and comes later.
   Every ring drawn in components.css is (0,2,0) or heavier, so no link drawn
   as a button gains a second ring, and Kadence still hides the ring from a
   pointer user until a key is pressed. */
a:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}

/* On the dark green surfaces the ring is white, 7.2 to 1 on --surface-invert.
   The logo green that --focus-ring carries since 1.2.2 (K-22) reads 4.0 to 1 on
   the cream canvas but only 1.7 to 1 here, where the paler tint it replaced
   read 3.5: the footer links on every page, the solid button in the dark band,
   the feelings strip and the enquiry link in the booking panel all lost their
   ring in 1.2.2. Both properties are restated, because --shadow-focus is
   resolved where it is declared and would otherwise inherit the green. Nothing
   light is nested inside these four, so a white ring always has dark behind it.
   The testimonials panel draws its own white ring (section 19). */
.st4u-band--invert,
.st4u-section--invert,
.st4u-booking-panel__aside,
.st4u-footer {
  --focus-ring: var(--white);
  --shadow-focus: 0 0 0 3px var(--focus-ring);
}

/* The one field on the site that the theme does not draw: the search box on
   the not found page and on a search with no results, which is Kadence's.
   Kadence removes the outline from its own text fields on focus
   (input[type=search]:focus, 0,2,1), which beats the one-pseudo-class rule
   above (0,1,0), so that box showed no ring at all. */
.search-form .search-field:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}

/* Windows contrast themes, and any other forced colours mode. There the browser
   paints its own palette and throws box-shadow away, and most of the rings in
   components.css are a box-shadow with the outline switched off (.st4u-btn,
   .st4u-control, the calendar days, the times and the rest), so those controls
   showed no focus at all. In that mode every focused control gets a real
   outline in the system's own highlight colour instead. The !important is
   deliberate, and this block is the only place in the theme that uses it: it
   has to beat each of those "outline: none" rules, and Kadence's, without
   listing them. Checked by emulation in a browser engine, not yet on a real
   contrast theme (test-accessibility.md, B5). */
@media (forced-colors: active) {
  :focus-visible {
    outline: 3px solid Highlight !important;
    outline-offset: 2px !important;
  }

  /* Drawn inside the box where the box fills a parent that clips it: the FAQ
     questions and the scrolling text of the terms window. An outline 2px
     outside them was cut away: all of it on a closed question, the sides of it
     on the terms text. Their ring in normal colours is drawn inside for the
     same reason. */
  .st4u-accordion__btn:focus-visible,
  .st4u-acc__btn:focus-visible,
  .st4u-accordion__item > summary:focus-visible,
  .st4u-terms__body:focus-visible {
    outline-offset: -3px !important;
  }

  /* Not for a section, a form card or a heading that a script focuses on
     arrival. Kadence focuses the target of an address like #st4u-booking and
     hides that focus until a key is pressed (.hide-focus-outline); the first
     rule in this block would otherwise draw a line round the whole booking
     panel after every step, for mouse users too. Anything a visitor works
     keeps its outline and is named: a button, a field of any kind (Kadence
     gives a field tabindex -1 when a link in the error summary is followed),
     a calendar day, bookable or not, and the error summary. Once a key is
     pressed Kadence drops the class and the section is outlined, as it is in
     normal colours. One :not() for each, not a list inside one: a browser that
     does not know the list drops the whole rule. */
  .hide-focus-outline [tabindex="-1"]:focus-visible:not(button):not(input):not(select):not(textarea):not(.st4u-alert):not(.st4u-cal__day) {
    outline: 0 !important;
  }

  /* Two states that fill and tint alone carried, and forced colours repaints
     every fill: the chosen day and time looked like the rest, and a day that
     is not offered looked bookable. The chosen ones take the system's own
     selection colours. forced-color-adjust is needed with them: without it the
     browser puts its own backplate behind the label and the number vanishes.
     Bookable squares only are named: a chosen day that has since filled up
     takes the "not offered" look below, which would be unreadable on this
     fill. */
  .st4u-cal__day.is-available.is-selected,
  .st4u-cal__day.is-available[aria-selected="true"],
  .st4u-time[aria-pressed="true"] {
    forced-color-adjust: none;
    background: Highlight;
    border-color: Highlight;
    color: HighlightText;
    box-shadow: none;
  }

  .st4u-cal__day.is-unavailable,
  .st4u-cal__day.is-full {
    border-color: Canvas;
    color: GrayText;
  }
}

/* The site is one long column with the footer pinned to the bottom on short
   pages. */
.st4u-site {
  min-height: 100vh;
  background: var(--canvas);
  display: flex;
  flex-direction: column;
}

.st4u-site__main {
  flex: 1;
}

/* The skip link, the first thing in the tab order. It is off screen until it
   takes focus. */
.st4u-skip-link {
  position: absolute;
  top: -100px;
  left: var(--space-4);
  z-index: 100;
  background: var(--surface);
  color: var(--text-strong);
  font-weight: var(--fw-bold);
  padding: 12px 18px;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  text-decoration: none;
  transition: top var(--dur-fast) var(--ease-out);
}

.st4u-skip-link:focus {
  top: var(--space-4);
}

/* ==========================================================================
   2. Containers
   Three widths, all tokens. --container mirrors theme.json contentSize and
   wideSize, and the Kadence Customizer container width, so all three must be
   changed together.
   ====================================================================== */

.st4u-container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Reading width: the FAQ, the enquiry form, the fees reassurance note and the
   legal pages. */
.st4u-container--narrow {
  max-width: var(--container-narrow);
}

/* The two booking panels. The prototype hard-codes 980px as a literal in both
   places; --container-form is the token that replaces it. */
.st4u-container--form {
  max-width: var(--container-form);
}

/* ==========================================================================
   3. Bands and section rhythm
   Every full-width band is one <section> with a background and vertical
   padding of --section-y. Alternating bands are what give the pages their
   rhythm, so the classes are named after the surface rather than the content.
   ====================================================================== */

.st4u-section {
  padding-block: var(--section-y);
  /* Every band is a constrained layout group, so the width of its contents comes
     from --wp--style--global--content-size. theme.json sets that to 1180px, but
     Kadence's Customizer container width reaches the page later and overrides it
     with 1242px, which is both wider than the approved design and has no gutter
     inside it, so at a viewport a little over 1242px the copy touches the window
     edge. Restating it here as the container minus its two gutters gives the
     1084px content box the approved design draws, and lines every band up with
     .st4u-page-header__inner and .st4u-cta-band__inner, which already resolve to
     that width. */
  --wp--style--global--content-size: calc(var(--container) - (2 * var(--gutter)));
}

/* Two names for each band. .st4u-band--* is this file's own vocabulary;
   .st4u-section--* is what the shipped patterns emit on the group wrapper. Both
   must resolve, or a pattern carrying st4u-section--invert renders white copy on
   the cream canvas and disappears. */

/* The cream page background. */
.st4u-band--canvas,
.st4u-section--canvas {
  background: var(--canvas);
}

/* White, used for the page header band and every other content band. */
.st4u-band--surface,
.st4u-section--surface {
  background: var(--surface);
}

/* The pale green alternating band. */
.st4u-band--alt,
.st4u-section--alt {
  background: var(--surface-alt);
}

/* Dark sage. Used by the feelings marquee, the call to action band and the
   footer. Text on it is white, so anything placed inside inherits correctly. */
.st4u-band--invert,
.st4u-section--invert {
  background: var(--surface-invert);
  color: var(--white);
}

.st4u-band--invert h1,
.st4u-band--invert h2,
.st4u-band--invert h3,
.st4u-section--invert h1,
.st4u-section--invert h2,
.st4u-section--invert h3 {
  color: var(--white);
}

/* An ordinary link inside a dark band. Without this it keeps the site wide
   --accent-strong navy, which sits at roughly 1.5:1 against --surface-invert:
   a WCAG 2.2 AA failure at 1.4.3 and close to invisible in practice. Buttons
   are excluded so their own variant colours still win. */
.st4u-band--invert a:not(.st4u-btn):not(.wp-block-button__link),
.st4u-section--invert a:not(.st4u-btn):not(.wp-block-button__link) {
  color: var(--white);
}

.st4u-band--bordered {
  border-bottom: var(--border-width) solid var(--border);
}

/* The page header band that opens all six inner pages: a white strip carrying
   the eyebrow, title and intro, with a hairline under it. */
.st4u-page-header {
  background: var(--surface);
  border-bottom: var(--border-width) solid var(--border);
}

.st4u-page-header__inner {
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--space-8) var(--gutter);
}

/* The three confirmation screens: one centred column on the cream canvas. */
.st4u-confirmation {
  display: grid;
  place-items: center;
  padding: var(--section-y) var(--gutter);
  background: var(--canvas);
  text-align: center;
}

.st4u-confirmation__inner {
  max-width: 520px;
}

/* The large tick in a soft navy disc above the confirmation heading. */
.st4u-confirmation__mark {
  width: 76px;
  height: 76px;
  border-radius: 50%;
  margin-inline: auto;
  background: var(--accent-soft);
  color: var(--accent-strong);
  display: grid;
  place-items: center;
}

.st4u-confirmation__mark .st4u-icon {
  width: 36px;
  height: 36px;
}

/* ==========================================================================
   4. Grids
   Every multi-column layout in the design is the same auto-fit pattern with a
   different minimum. The minimum is the only thing that changes, so it is a
   custom property on the grid itself.
   ====================================================================== */

.st4u-grid {
  --_min: 280px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--_min)), 1fr));
  gap: var(--space-5);
}

.st4u-grid--min-160 { --_min: 160px; }
.st4u-grid--min-220 { --_min: 220px; }
.st4u-grid--min-240 { --_min: 240px; }
.st4u-grid--min-280 { --_min: 280px; }
.st4u-grid--min-300 { --_min: 300px; }
.st4u-grid--min-340 { --_min: 340px; }
.st4u-grid--min-400 { --_min: 400px; }

.st4u-grid--gap-lg {
  gap: var(--space-7);
}

/* A rail layout: a main column and a second one that sticks. The columns start
   at the top rather than stretching, which is the part that lets the rail stick
   at all.

   The approved design does not use a narrow rail here. Both screens draw two
   equal columns, which at the 1084px band width is 518px each, so the tracks are
   the same auto-fit pattern as every other grid with a 400px minimum. A fixed
   340px rail made the question list run to a much longer line than approved and
   squeezed the card beside it.

   Used by st4u/why-coaching-split and st4u/wnw-split. Do not put an overflow
   rule on this element or on anything above it: position: sticky then fails
   with no error of any kind. */
.st4u-grid--rails {
  align-items: start;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
  gap: var(--space-7);
}

@media (max-width: 767px) {

  .st4u-grid--rails {
    grid-template-columns: 1fr;
  }
}

/* ==========================================================================
   5. Sticky rails
   Two occurrences: the "Ready to be heard?" card on Why coaching and the "Join
   this Wednesday" card on the women's group page. 96px is the 78px header plus
   18px of clearance, held in --sticky-top.

   WARNING. position: sticky fails silently if ANY ancestor sets
   overflow: hidden, overflow: auto or overflow: clip. Nothing wraps these
   rails in an overflow rule, and nothing may be added later. If a rail stops
   sticking, look up the tree for an overflow before looking at this rule.
   ====================================================================== */

.st4u-sticky-rail {
  position: sticky;
  top: var(--sticky-top);
}

/* On a narrow viewport the grid has collapsed to one column, so sticking would
   pin the card over the content it belongs beside. */
@media (max-width: 767px) {

  .st4u-sticky-rail {
    position: static;
  }
}

/* ==========================================================================
   6. Testimonial masonry
   A multi-column flow rather than a grid, so cards of different heights pack
   without gaps. columns: 320px 3 means "as many columns as fit at 320px, but
   never more than three".

   Caveat worth knowing before anyone reorders the testimonials: a multi-column
   flow runs top to bottom and then across, so the reading order down the page
   is not the source order across the columns.
   ====================================================================== */

/* A gallery grid, three across, every card the same height as its neighbours.

   This replaces the multi-column masonry the prototype used. Two reasons the
   client asked for the change, and both are real. A masonry sizes each card to
   its own text, so six testimonials of different lengths produced six different
   heights and a ragged edge. It also flows top to bottom and then across, so
   the reading order on screen did not match the order the cards were written
   in, which made the section confusing to edit.

   Design Options 1g is the variant this follows, with one deliberate change:
   1g sets align-items:start, which leaves the cards ragged again. Stretch is
   what makes them consistent, which is the point of the change. */
.st4u-masonry {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: var(--space-5);
  align-items: stretch;
  margin-top: var(--space-7);
}

/* The item is a flex column purely so the card inside it can fill the full
   height of the grid row rather than sitting at its natural height. */
.st4u-masonry__item {
  display: flex;
}

.st4u-masonry__item > .st4u-testimonial,
.st4u-masonry__item > .st4u-quote {
  width: 100%;
}

/* The quote takes the slack, so every attribution line sits on the same
   baseline across a row however long or short the quote above it is. */
.st4u-masonry__item .st4u-testimonial__text {
  flex: 1;
}

/* ==========================================================================
   7. Site header
   Sticky, 78px tall, translucent with a blur behind it.

   The selectors are Kadence's, not the theme's own. The child theme ships no
   header template: the header is built by the parent theme's header builder and
   rendered on the kadence_header hook, so nothing on the front end ever carries
   a .st4u-header class. These rules therefore dress the markup the site
   actually has (#masthead, #main-header, .site-container, #primary-menu) rather
   than markup that does not exist.

   The collapse below 1040px is Kadence's own: it swaps in #mobile-header and a
   drawer, which is left as the parent theme draws it. The one thing that has to
   collapse here is the header call to action, which is a menu item.
   ====================================================================== */

/* The header is sticky and covers the top of the window, so the browser is told
   to keep that much clear when it scrolls something into view: a control that
   takes keyboard focus, or the target of an address that names a place on the
   page. Without it, tabbing backwards up a page put the focused control under
   the header, wholly hidden for eight controls at desktop width and ten on a
   phone (WCAG 2.2 AA, 2.4.11 Focus Not Obscured), and a heading reached from
   the browser's own jump started under it. --sticky-top is the header's height
   and 18px of clearance, the figure both sticky rails already sit at. */
html {
  scroll-padding-top: var(--sticky-top);
}

#masthead {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  backdrop-filter: blur(8px) saturate(1.15);
  border-bottom: var(--border-width) solid var(--border);
}

/* Kadence's own container is wider than the design's and carries its own
   padding, so both are restated on the header row only. */
#main-header .site-container {
  max-width: var(--container);
  padding-inline: var(--gutter);
}

#main-header .site-main-header-inner-wrap {
  min-height: var(--header-height);
}

/* The logo artwork is 759 by 506, and Kadence prints those as attributes, so the
   height has to be set here or the header stands 133px tall. */
#masthead .custom-logo {
  height: 54px;
  width: auto;
  display: block;
}

#main-header #primary-menu {
  display: flex;
  align-items: center;
  gap: 24px;
  margin: 0;
  padding: 0;
  list-style: none;
}

#main-header #primary-menu > li > a {
  font-size: 15px;
  font-weight: var(--fw-semibold);
  color: var(--text-body);
  text-decoration: none;
  padding: 6px 0;
  border-bottom: 2px solid transparent;
}

#main-header #primary-menu > li > a:hover {
  color: var(--text-strong);
}

/* The current page. The underline plus the heavier weight means the state is
   not signalled by colour alone. */
#main-header #primary-menu > .current-menu-item > a,
#main-header #primary-menu > li > a[aria-current="page"] {
  font-weight: var(--fw-bold);
  color: var(--text-strong);
  border-bottom-color: var(--accent);
}

/* The header call to action, added to the primary menu by inc/header-cta.php so
   that it survives the parent theme's header builder. It is a menu item, so the
   nav link rules above have to be undone on it. */
.st4u-menu-cta > .st4u-btn {
  font-size: 15px;
  padding: 0.8em 1.6em;
}

#main-header #primary-menu > .st4u-menu-cta > a {
  border-bottom: 0;
  padding: 0.8em 1.6em;
  color: var(--text-on-accent);
}

#main-header #primary-menu > .st4u-menu-cta > a:hover {
  color: var(--text-on-accent);
}

/* The pill is dropped from the horizontal row wherever it will not fit beside
   the logo, because there it wraps onto a second line and the header stands
   103px tall instead of 79. Beside the wordmark logo it needs about 1150px,
   measured in a browser on 22 September 2026, and 1199 leaves it about 48px of
   room at the edge rather than none. This used to stop at 1039, which was
   already too low: at 1040 the menu wrapped even with the old logo.

   Nothing is lost by hiding it. Below 1025 Kadence's drawer takes over and
   carries its own copy of the call to action, styled by the rules below, and
   between 1025 and 1199 the menu's own "Book a call" link does the same job. */
@media (max-width: 1199px) {

  .st4u-menu-cta {
    display: none;
  }
}

/* The call to action inside Kadence's mobile drawer, appended to #mobile-menu by
   inc/header-cta.php. On a phone the pill above is hidden, so this is the only
   copy of the site's main call to action the visitor has. It is drawn as a full
   width button at the end of the list, which means the drawer's own link
   treatment, a hairline divider and the pale link colour, has to come off it, or
   it reads as another menu item. The id selector is what wins against Kadence's
   .mobile-navigation rules and its Customizer output. */
#mobile-menu > .st4u-drawer-cta {
  margin-top: 18px;
  border-bottom: 0;
}

/* K-38. The drawer's link for the page the visitor is on. Kadence colours it
   with its own highlight blue, #2B6CB0, which is 3.6 to 1 on the drawer's
   #090c10 where small text wants 4.5. The pale green the site already uses for
   "this one" on its dark surfaces (the current testimonials dot) is 13.7 to 1.
   It is only 1.4 to 1 away from the other links, which are near white, so the
   weight and the underline carry the state, as they do in the header: it is
   not signalled by colour alone, and it survives forced colours, where every
   link is the same colour. The call to action is left out: it is a button,
   with its own colours below. The id is what wins against Kadence's Customizer
   output, as it does for that button. */
#mobile-menu li.current-menu-item:not(.st4u-drawer-cta) > a {
  color: var(--green-200);
  font-weight: var(--fw-bold);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 6px;
}

#mobile-menu > .st4u-drawer-cta > a {
  /* Kadence sets display: block on a drawer link, which would undo the flex
     centring .st4u-btn--block gives every other block button on the site. */
  display: flex;
  justify-content: center;
  padding: 0.9em 1.4em;
  border-bottom: 0;
  color: var(--text-on-accent);
  text-align: center;
  white-space: normal;
}

#mobile-menu > .st4u-drawer-cta > a:hover,
#mobile-menu > .st4u-drawer-cta > a:focus-visible {
  color: var(--text-on-accent);
}
/* ==========================================================================
   8. Hero
   ====================================================================== */

.st4u-hero__inner {
  max-width: var(--container);
  margin-inline: auto;
  padding: clamp(48px, 7vw, 92px) var(--gutter);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  gap: clamp(36px, 5vw, 64px);
  align-items: center;
}

.st4u-hero__title {
  font-family: var(--font-heading);
  font-weight: var(--fw-bold);
  margin: 20px 0 0;
  font-size: clamp(38px, 4.6vw, 58px);
  line-height: 1.06;
  letter-spacing: var(--heading-spacing);
  color: var(--text-strong);
  text-wrap: balance;
}

.st4u-hero__lead {
  margin: 22px 0 0;
  max-width: 50ch;
  font-size: var(--text-md);
  line-height: var(--lh-relaxed);
  color: var(--text-body);
  text-wrap: pretty;
}

.st4u-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 30px;
}

.st4u-hero__facts {
  display: flex;
  gap: 22px;
  margin-top: 30px;
  flex-wrap: wrap;
}

.st4u-hero__fact {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 14px;
  font-weight: var(--fw-bold);
  color: var(--text-body);
}

.st4u-hero__fact .st4u-icon {
  width: 19px;
  height: 19px;
  color: var(--accent);
}

/* The full logo at the foot of the copy column, FBL-0050. The markup is added to
   the rendered page by inc/hero-lockup.php, not by the pattern, because the hero
   is saved page content. The margin below is declared here and restated in
   section 15, because .single-content zeroes the block margins of everything in
   this column and that restatement is where the design's own spacing is kept.

   300px is taken from the mock-up she chose: measured against the portrait frame
   beside it, which is 440px wide, her logo is a little over 300px. It is capped
   rather than fluid so the wordmark never grows larger than the headline above
   it. */
.st4u-hero__lockup {
  display: block;
  width: min(100%, 300px);
  height: auto;
  margin-top: clamp(20px, 2.5vw, 32px);
  margin-inline-start: auto;
}

/* The hero grid collapses to a single column at about 782px, where two 340px
   tracks and the gap between them no longer fit inside the container less its
   gutters. Above that the logo sits against the right of the copy column, where
   her mock-up puts it, tucked into the corner beside the portrait. Below it the
   column is the full width of the page and there is no portrait to sit beside,
   so it centres instead. 781px rather than 782px because a browser may report a
   fractional width. */
@media (max-width: 781px) {

  .st4u-hero__lockup {
    margin-inline: auto;
  }
}

/* The portrait frame, with the two overlapping floating cards. The frame is
   relative so the cards can hang off its edges, and it must not be given an
   overflow rule or the cards will be clipped. */
.st4u-hero__portrait {
  position: relative;
  width: 100%;
  max-width: 440px;
  margin-inline: auto;
  /* The frame carries its own 4/5 shape, its gradient and its shadow, rather
     than inheriting them from the photograph. Two reasons. The floating cards
     are absolutely positioned against this box, so without a height of its own
     the column collapses to nothing and the cards stack into single character
     columns. And the prototype shows a green gradient panel behind the
     portrait, which must still be there before any photograph is uploaded. */
  aspect-ratio: 4 / 5;
  /* The prototype frames the portrait at --radius-card, 18px, not --radius-xl. */
  border-radius: var(--radius-card);
  background: linear-gradient(160deg, var(--brand) 0%, var(--brand-strong) 100%);
  box-shadow: var(--shadow-lg);
}

/* The photograph fills the frame exactly, so the frame stays the single source
   of the shape. Absolute rather than a plain block, so an image of any ratio is
   cropped to the frame instead of stretching it.

   The radius is named rather than inherited. Inherit takes it from the image's
   own parent, and when the photograph arrives wrapped in a caption that parent
   is the caption, not the frame, so on 22 September 2026 the photograph came out
   square inside a rounded frame. */
.st4u-hero__portrait img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius-card);
}

/* A caption wrapper round the photograph brings a caption of its own, her name,
   which the name card already says. On a wide screen it sat hidden behind the
   photograph; on a phone, once the photograph is in the flow, it would show as a
   stray line of text. The image's alt text still names her. */
.st4u-hero__portrait figcaption {
  display: none;
}

/* Both cards carry a dark blue border, which Miriam asked for on 28 September
   2026 (FBL-0080). */
.st4u-hero__float {
  position: absolute;
  background: var(--surface);
  border: 2px solid var(--accent-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 14px 16px;
}

/* The name card hangs off the left edge by as much as the quote card hangs off
   the right, so the two balance (FBL-0080): 40px here and 16px on a tablet. It
   carries slightly wider side padding than the quote card, matching the
   prototype. */
.st4u-hero__float--name {
  left: -40px;
  bottom: 26px;
  padding: 14px 18px;
}

/* The quote card is pinned across the portrait's top-right corner, rising above
   the frame and hanging past its edge, rather than sitting inside it. FBL-0005
   asked for it bigger, and inside the frame there was no room to grow: its lower
   corner already sat on the top of the coach's hair, and growing it in place
   tripled that. Above and to the right of her is plain wall and page margin, so
   that is where the extra size goes. Measured against the real photograph on 22
   September 2026 at every width from 640 to 1440: nothing over her head or
   shoulder, and no sideways scroll. It mirrors the name card, which hangs off
   the opposite corner. */
.st4u-hero__float--quote {
  right: -40px;
  top: -32px;
  max-width: 272px;
}

.st4u-hero__float--quote p {
  margin: 0;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 17px;
  line-height: var(--lh-normal);
  color: var(--text-body);
}

/* On a tablet the portrait is narrower, so the card is a little smaller and
   rises further, to clear the top of her hair, and hangs less far past the edge,
   because the page margin is narrower too. This comes before the phone rule
   below so that rule still wins beneath 600px, where the card leaves the
   portrait altogether. The 16px text carries on down to phones. */
@media (max-width: 1024px) {

  .st4u-hero__float--quote {
    right: -16px;
    top: -44px;
    max-width: 236px;
  }

  /* Still the quote card's overhang, mirrored (FBL-0080). */
  .st4u-hero__float--name {
    left: -16px;
  }

  .st4u-hero__float--quote p {
    font-size: 16px;
  }
}

/* On a narrow viewport the floating cards would hang off the screen edge, so
   they drop into the flow underneath the portrait.

   For "underneath" to hold, the photograph has to be in the flow as well. The
   frame normally carries the 4/5 shape and the photograph fills it absolutely,
   which on a phone left both cards inside the frame and painted over by the
   photograph: invisible, found on 22 September 2026, the day the photograph went
   up. Before then the cards sat on top of the green panel, so nothing showed it.
   So once there is a photograph, the photograph carries the shape itself, the
   frame steps back, and the cards follow the photograph. With no photograph the
   frame keeps its green panel exactly as before. */
@media (max-width: 599px) {

  .st4u-hero__float {
    position: static;
    margin-top: var(--space-3);
    max-width: none;
  }

  .st4u-hero__portrait:has(img) {
    aspect-ratio: auto;
    background: none;
    box-shadow: none;
  }

  .st4u-hero__portrait:has(img) img {
    position: static;
    height: auto;
    aspect-ratio: 4 / 5;
    box-shadow: var(--shadow-lg);
  }

  /* A caption wrapper brings its own bottom margin, which put 32px under the
     photograph against 12px between the cards. */
  .st4u-hero__portrait figure {
    margin: 0;
  }
}

/* ==========================================================================
   9. Feelings marquee
   A single flex row at width: max-content, holding the nine chips three times
   over. The animation translates it by exactly -33.3333%, which lands a copy
   where the first started, so the loop is seamless. The duplication is what
   makes -33.3333% correct: change the number of copies in the pattern and this
   translation must change with it, to 100% divided by the number of copies.

   Accessibility. The prototype implements none of this and it is not optional:
     - SC 2.2.2 Pause, Stop, Hide requires a mechanism to pause movement that
       starts automatically and runs for more than five seconds. The pause
       button below is that mechanism.
     - The animation also pauses on hover and on keyboard focus within, so a
       visitor reading a chip is not chasing it across the screen.
     - Under prefers-reduced-motion the animation is disabled outright and the
       band stays a single scrollable line, rather than the chips wrapping or
       being merely slowed down. The second and third copies are hidden so every
       phrase appears once, and the control stays on screen with its meaning
       flipped, so movement can still be asked for.
     - The second and third copies of the chips carry aria-hidden in the markup
       so a screen reader reads the nine feelings once, not 27 times.
   ====================================================================== */

@keyframes st4u-scroll {

  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(-33.3333%);
  }
}

.st4u-marquee {
  padding-block: 26px;
  overflow: hidden;
}

.st4u-marquee__head {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
  margin-bottom: 14px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.st4u-marquee__eyebrow {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--green-200);
}

.st4u-marquee__head .st4u-icon {
  width: 18px;
  height: 18px;
  color: var(--green-bright);
}

.st4u-marquee__viewport {
  overflow: hidden;
  width: 100%;
}

.st4u-marquee__track {
  display: flex;
  width: max-content;
  animation: st4u-scroll 38s linear infinite;
}

/* Pause while a visitor is reading, by pointer or by keyboard, and only over the
   moving strip itself. Until 1.1.5 the pointer rule covered the whole band,
   Play button included, so pressing Play left the banner paused for as long as
   the pointer stayed on the button: exactly what FBL-0011 was raised for. The
   keyboard rule was narrowed the same way in 1.0.4; this is its pointer twin. */
.st4u-marquee__viewport:hover .st4u-marquee__track,
.st4u-marquee__viewport:focus-within .st4u-marquee__track {
  animation-play-state: paused;
}

/* Paused by the control.

   Two hooks, because two mechanisms exist and only one of them is guaranteed.

   a) The shipped pattern renders a visually hidden checkbox followed by the
      head and the viewport, with a <label> acting as the visible control. That
      needs no JavaScript at all, which is what makes it the primary route:
      SC 2.2.2 has to be satisfied with scripting off.
   b) assets/js/st4u-marquee.js sets data-st4u-marquee-state on an enhanced
      root. The older data-paused name is kept alongside it so an earlier build
      of that script still works.

   All three selectors are listed rather than one, because none of them can be
   assumed present. */
.st4u-marquee__toggle:checked ~ .st4u-marquee__viewport .st4u-marquee__track,
.st4u-marquee[data-st4u-marquee-state="paused"] .st4u-marquee__track,
.st4u-marquee[data-paused="true"] .st4u-marquee__track {
  animation-play-state: paused;
}

/* The label is not itself focusable, so the visible focus indicator has to be
   driven from the checkbox that is. Without this the pause control can be
   reached by keyboard with nothing on screen to show it, which fails 2.4.7. */
.st4u-marquee__toggle:focus-visible ~ .st4u-marquee__head .st4u-marquee__pause {
  outline: 3px solid var(--white);
  outline-offset: 2px;
}

/* The control shows one glyph and one word at a time: "Pause" while the row is
   moving, "Play" once it has stopped. Both pairs are in the markup so the swap
   costs no script. Order matters here: the base rule has to come first, or it
   would re-show the hidden half at equal specificity. */
.st4u-marquee__pause-glyph {
  display: inline-flex;
  align-items: center;
}

.st4u-marquee__pause-glyph--play,
.st4u-marquee__pause-text--play {
  display: none;
}

.st4u-marquee__toggle:checked ~ .st4u-marquee__head .st4u-marquee__pause-glyph--pause,
.st4u-marquee__toggle:checked ~ .st4u-marquee__head .st4u-marquee__pause-text--pause {
  display: none;
}

.st4u-marquee__toggle:checked ~ .st4u-marquee__head .st4u-marquee__pause-glyph--play {
  display: inline-flex;
}

.st4u-marquee__toggle:checked ~ .st4u-marquee__head .st4u-marquee__pause-text--play {
  display: inline;
}

.st4u-marquee__chip {
  flex: none;
  margin-inline-end: 14px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--white);
  border: var(--border-width) solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius-pill);
  padding: 10px 20px;
  font-weight: var(--fw-bold);
  font-size: 15px;
  white-space: nowrap;
}

/* The pause control. It sits inside the dark band, so it is drawn in white on
   a translucent fill, and it is a real button with a text label, not an icon
   alone. */
.st4u-marquee__pause {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* The head is a nowrap flex row, and on a phone the eyebrow takes most of it. Without
     these two the control is a flex item that shrinks to whatever is left, and the word
     inside it breaks mid-way: measured at 68x56 with "Play" over two lines at 375px, and
     60x97 over four lines at 320px. flex-shrink keeps the control at its natural width and
     white-space stops the word breaking if it is ever squeezed anyway. */
  flex-shrink: 0;
  white-space: nowrap;
  /* Navy rather than another translucent white, so the control reads as a
     control and not as a tenth chip. The border has to be brighter than the
     chips use: navy on this green band is only 1.5:1, well under the 3:1 that
     SC 1.4.11 asks for on the edge of a control, so the boundary is what makes
     it identifiable. At 0.65 the border reaches 3.68:1 against the band. */
  background: var(--navy-700);
  color: var(--white);
  border: var(--border-width) solid rgba(255, 255, 255, 0.65);
  border-radius: var(--radius-pill);
  padding: 6px 14px;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: var(--fw-bold);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out);
}

.st4u-marquee__pause:hover {
  background: var(--navy-600);
}

.st4u-marquee__pause:focus-visible {
  outline: 3px solid var(--white);
  outline-offset: 2px;
}

.st4u-marquee__pause .st4u-icon {
  width: 14px;
  height: 14px;
}

@media (prefers-reduced-motion: reduce) {

  /* Nothing moves until the visitor asks for it.

     The control is NOT hidden here, and the checkbox meaning flips. In the
     default state the checkbox means "pause this". Here it means "play this".
     SC 2.2.2 is about motion that starts on its own, so motion a person
     deliberately switches on is fine, and taking the choice away from somebody
     who has set a system preference is patronising: plenty of people set it to
     stop things moving unbidden, not to be forbidden from ever seeing movement.

     It is also the only way the owner can see the effect on her own machine
     without changing a Windows setting. */
  .st4u-marquee__track {
    animation: none;
    /* The band stays ONE LINE whether it is moving or not. The row simply
       overflows and the visitor scrolls it, which is why the viewport below
       becomes scrollable rather than the chips wrapping onto three rows. */
    padding-inline: var(--gutter);
  }

  /* The copies after the first exist ONLY so the translate loops without
     a visible seam. While nothing is moving it has no purpose, and leaving it
     visible shows every phrase three times, which reads as a mistake rather than as a
     considered fallback. It is already aria-hidden, so a screen reader was never
     affected either way. */
  .st4u-marquee__chip[aria-hidden='true'] {
    display: none;
  }

  /* Static: the row is a single scrollable line, so every phrase is still
     reachable without any movement at all. scroll-padding keeps a chip clear of
     the edge when it is scrolled to by keyboard. */
  .st4u-marquee__viewport {
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: thin;
    scroll-padding-inline: var(--gutter);
    overscroll-behavior-inline: contain;
  }

  /* Opted in: restore exactly the moving state the default preference gets. The
     duplicate has to come back or the loop shows a gap, the padding has to go or
     the -33.3333% no longer lands on the seam, and the viewport clips again. */
  .st4u-marquee__toggle:checked ~ .st4u-marquee__viewport .st4u-marquee__track {
    animation: st4u-scroll 38s linear infinite;
    padding-inline: 0;
  }

  .st4u-marquee__toggle:checked ~ .st4u-marquee__viewport .st4u-marquee__chip[aria-hidden='true'] {
    display: revert;
  }

  .st4u-marquee__toggle:checked ~ .st4u-marquee__viewport {
    overflow: hidden;
  }

  /* Hover and focus must still pause once it is running. The shorthand above
     resets animation-play-state to running, so the pause needs to win on
     specificity rather than order: :hover and :focus-within on the viewport
     give it one more pseudo-class than the rule it overrides.

     Over the moving strip only, as in the rule above the media query. These
     named the whole band until 1.1.5, and clicking Play leaves focus on the
     hidden checkbox inside it, so the banner stayed still after Play until the
     visitor clicked somewhere else. */
  .st4u-marquee__toggle:checked ~ .st4u-marquee__viewport:hover .st4u-marquee__track,
  .st4u-marquee__toggle:checked ~ .st4u-marquee__viewport:focus-within .st4u-marquee__track {
    animation-play-state: paused;
  }

  /* The control reads the opposite way round here, because the checkbox means
     the opposite thing: "Play" while the row is still, "Pause" once it moves. */
  .st4u-marquee__pause-glyph--pause,
  .st4u-marquee__pause-text--pause {
    display: none;
  }

  .st4u-marquee__pause-glyph--play {
    display: inline-flex;
  }

  .st4u-marquee__pause-text--play {
    display: inline;
  }

  .st4u-marquee__toggle:checked ~ .st4u-marquee__head .st4u-marquee__pause-glyph--play,
  .st4u-marquee__toggle:checked ~ .st4u-marquee__head .st4u-marquee__pause-text--play {
    display: none;
  }

  .st4u-marquee__toggle:checked ~ .st4u-marquee__head .st4u-marquee__pause-glyph--pause {
    display: inline-flex;
  }

  .st4u-marquee__toggle:checked ~ .st4u-marquee__head .st4u-marquee__pause-text--pause {
    display: inline;
  }
}

/* ==========================================================================
   10. Booking panels
   One card, split into a dark side panel and the wizard. The two halves wrap
   onto separate rows on a narrow viewport, which is what the flex basis pair
   does: 280px for the panel, 380px for the form, form growing twice as fast.

   The panel carries overflow: hidden so the dark half is clipped to the card
   radius. Nothing sticky may be placed inside it.
   ====================================================================== */

/* st4u-booking-page is added to <body> on the three form templates. It is the
   one hook that tells the page it is a form page, so the panel takes the form
   width without the template having to name it, and any future rule that
   applies to all three has somewhere to hang. */
body.st4u-booking-page .st4u-container:not(.st4u-container--narrow):not(.st4u-container--form) {
  max-width: var(--container-form);
}

.st4u-booking-panel {
  background: var(--surface);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  display: flex;
  flex-wrap: wrap;
}

.st4u-booking-panel__aside {
  flex: 1 1 280px;
  background: var(--surface-invert);
  color: var(--white);
  padding: 34px 30px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

/* assets/img/emblem-bright.png is the full colour emblem, so it is knocked out
   to white here rather than a second artwork being shipped. This is exactly what
   the prototype does. */
.st4u-booking-panel__logo {
  width: 54px;
  height: auto;
  display: block;
  opacity: 0.9;
  filter: brightness(0) invert(1);
}

.st4u-booking-panel__eyebrow {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--green-200);
}

.st4u-booking-panel__title {
  margin: 8px 0 0;
  font-family: var(--font-heading);
  font-size: 26px;
  font-weight: var(--fw-bold);
  color: var(--white);
}

/* A real ul in the wizard, so the list defaults are cleared here. */
.st4u-booking-panel__facts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-size: 14.5px;
  color: rgba(255, 255, 255, 0.85);
}

.st4u-booking-panel__fact {
  display: flex;
  gap: 10px;
  align-items: center;
}

.st4u-booking-panel__fact .st4u-icon {
  width: 18px;
  height: 18px;
  color: var(--green-bright);
}

/* The sentence for a visitor who finds no slot that suits (FBL-0086), in the
   size and colour of the facts, as Miriam asked. It is pushed to the foot of
   the dark panel, below the closing note, where Miriam placed it on 3 October
   2026. The link is underlined because it sits inside a sentence, where colour
   alone would not mark it out. */
.st4u-booking-panel__enquire {
  margin: auto 0 0;
  font-size: 14.5px;
  line-height: var(--lh-normal);
  color: rgba(255, 255, 255, 0.85);
}

.st4u-booking-panel__enquire a {
  color: var(--white);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* The colour is restated: body a:hover (the top of this file) is more specific
   than the rule above and would turn the link --brand, 1.3 to 1 on the panel,
   so the words vanished under the pointer in 1.2.2. */
.st4u-booking-panel__enquire a:hover {
  color: var(--white);
  text-decoration-thickness: 2px;
}

/* A rule of its own, not a second selector on the one above: a browser that
   does not know :focus-visible throws away a whole selector list that names
   it, and the hover colour would go with it. */
.st4u-booking-panel__enquire a:focus-visible {
  color: var(--white);
  text-decoration-thickness: 2px;
}

/* The closing note is pushed to the bottom of the dark panel, unless the
   enquiry sentence follows it: then the sentence takes the bottom and the note
   sits under the facts. */
.st4u-booking-panel__note {
  margin: auto 0 0;
  font-size: 13.5px;
  line-height: var(--lh-normal);
  color: rgba(255, 255, 255, 0.78);
}

.st4u-booking-panel__note--with-enquire {
  margin-top: 0;
}

/* min-width: 0 because a flex item defaults to min-width: auto and so refuses
   to shrink below the widest thing inside it. The calendar was holding the
   form column open at 423px on a 390px phone. */
.st4u-booking-panel__form {
  flex: 2 1 380px;
  min-width: 0;
  padding: clamp(24px, 4vw, 40px);
}

.st4u-booking-panel__month {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 12px;
}

.st4u-booking-panel__month-name {
  font-family: var(--font-heading);
  font-size: 19px;
  font-weight: var(--fw-bold);
  color: var(--text-strong);
}

.st4u-booking-panel__month-note {
  font-size: 12.5px;
  color: var(--text-muted);
}

.st4u-booking-panel__submit {
  margin-top: 26px;
}

/* ==========================================================================
   11. Site footer
   ====================================================================== */

.st4u-footer {
  background: var(--surface-invert);
  color: var(--white);
  margin-top: auto;
}

.st4u-footer__inner {
  max-width: var(--container);
  margin-inline: auto;
  padding: 56px var(--gutter) 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: 36px;
}

.st4u-footer__brand {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* Same artwork as the booking rail, knocked out to white the same way. */
.st4u-footer__brand img {
  width: 44px;
  height: auto;
  opacity: 0.9;
  filter: brightness(0) invert(1);
}

.st4u-footer__name {
  font-family: var(--font-heading);
  font-weight: var(--fw-bold);
  font-size: 20px;
}

/* The strapline is styled markup, not the site description. Binding it to the
   site tagline would tie footer typography to an SEO field the owner will
   legitimately want to change. */
.st4u-footer__strapline {
  font-family: var(--font-display);
  font-size: 10.5px;
  font-weight: var(--fw-bold);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--green-200);
}

/* The blurb sits at 78% white rather than the prototype's 65%. 65% white over
   --surface-invert is about 3.9:1, under the 4.5:1 that 14px body copy needs.
   The same reasoning covers .st4u-footer__base below. */
.st4u-footer__blurb {
  margin: 16px 0 0;
  font-size: 14px;
  line-height: var(--lh-relaxed);
  color: rgba(255, 255, 255, 0.78);
  max-width: 34ch;
}

/* The column headers depend on --ls-caps, as does every other uppercase label
   on the site. */
.st4u-footer__heading {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  /* --green-200, not the prototype's --green-300. #a2bfa8 on --surface-invert
     is 3.6:1, which fails WCAG 2.2 AA at 1.4.3 for a 12px label; #cbdccf is
     5.0:1. Recorded here so nobody restores the prototype value by accident. */
  color: var(--green-200);
  /* The heading is a real h2, so its own top margin has to go or the two columns
     start lower than the brand column beside them. */
  margin: 0 0 14px;
}

/* A real ul, so the browser bullet and its 40px indent are cleared here. */
.st4u-footer__links {
  display: flex;
  flex-direction: column;
  gap: 10px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.st4u-footer__links a,
.st4u-footer__facts a {
  font-size: 14.5px;
  color: rgba(255, 255, 255, 0.75);
  text-decoration: none;
}

.st4u-footer__links a:hover,
.st4u-footer__facts a:hover {
  color: var(--white);
  text-decoration: underline;
}

.st4u-footer__facts {
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-size: 14.5px;
  color: rgba(255, 255, 255, 0.75);
}

.st4u-footer__fact {
  display: flex;
  gap: 10px;
  align-items: center;
}

.st4u-footer__fact .st4u-icon {
  width: 17px;
  height: 17px;
  color: var(--green-bright);
}

/* The client's accreditation badges, FBL-0023, in a row under the facts in the
   "Good to know" column, where her mock-up put them and at about the size she
   drew them. The files are 192px, twice this, so they stay sharp on a high
   density screen. Their corners are transparent, so they sit directly on the
   footer's green rather than in white squares. */
/* Centred in their column, and sized from her own mock-up rather than by eye. In the picture
   she sent on 8 September the badge is 97px tall against a Good to know block of 99px, so she
   has them the full height of that block rather than small marks beside it. On the live footer
   that block is about 118px, so 120px is the same relationship. Two of them and the gap come to
   256px in a 385px column, which leaves room to centre without crowding the edges. */
.st4u-footer__badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 16px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.st4u-footer__badges img {
  display: block;
  width: 120px;
  height: 120px;
}

.st4u-footer__base {
  max-width: var(--container);
  margin: 40px auto 0;
  padding: 22px var(--gutter);
  border-top: var(--border-width) solid rgba(255, 255, 255, 0.12);
  font-size: 13px;
  color: rgba(255, 255, 255, 0.78);
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: space-between;
}

/* ==========================================================================
   12. Small shared blocks
   The bordered fact rows used on the women's group page and the tick list on
   Why coaching. Both are the same shape at two sizes.
   ====================================================================== */

/* A real ul in the shipped pattern, so the browser bullet and the 40px indent
   have to be cleared or they appear beside every tick. */
.st4u-tick-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.st4u-tick-list__item {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  background: var(--surface);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--text-body);
}

.st4u-tick-list__mark {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent-strong);
  display: grid;
  place-items: center;
}

.st4u-tick-list__mark .st4u-icon {
  width: 16px;
  height: 16px;
}

/* A real ul in the shipped pattern. Same reset as the tick list above. */
.st4u-fact-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.st4u-fact-list__item {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  background: var(--surface);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md);
  padding: 16px 18px;
}

.st4u-fact-list__mark {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent-strong);
  display: grid;
  place-items: center;
}

.st4u-fact-list__mark .st4u-icon {
  width: 20px;
  height: 20px;
}

.st4u-fact-list__title {
  font-family: var(--font-heading);
  font-size: 16px;
  font-weight: var(--fw-bold);
  color: var(--text-strong);
}

.st4u-fact-list__text {
  margin-top: 3px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--text-body);
}

/* The numbered GROW steps on the home page. */
.st4u-step {
  display: flex;
  gap: 16px;
}

.st4u-step__num {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--brand);
  color: var(--text-on-brand);
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: var(--fw-extra);
  font-size: 17px;
}

.st4u-step__title {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 18px;
  font-weight: var(--fw-bold);
  color: var(--text-strong);
}

.st4u-step__text {
  margin: 5px 0 0;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--text-body);
}

/* The square icon tile at the top of the three "why coaching" cards. */
.st4u-card__icon {
  width: 52px;
  height: 52px;
  border-radius: var(--radius-md);
  background: var(--accent-soft);
  color: var(--accent-strong);
  display: grid;
  place-items: center;
  margin-bottom: 16px;
}

.st4u-card__icon .st4u-icon {
  width: 26px;
  height: 26px;
}

/* ==========================================================================
   13. Call to action band
   ====================================================================== */

.st4u-cta-band__inner {
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--section-y) var(--gutter);
  text-align: center;
}

.st4u-cta-band__title {
  font-family: var(--font-heading);
  font-weight: var(--fw-bold);
  font-size: var(--text-3xl);
  color: var(--white);
  margin: 0;
  letter-spacing: var(--heading-spacing);
}

/* Two names again: __lead is this file's, __intro is what the shipped
   cta-band-dark pattern emits. */
.st4u-cta-band__lead,
.st4u-cta-band__intro {
  margin: 16px auto 0;
  max-width: 46ch;
  font-size: var(--text-md);
  line-height: var(--lh-relaxed);
  color: rgba(255, 255, 255, 0.8);
}

.st4u-cta-band__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  margin-top: 30px;
}

.st4u-cta-band__note {
  margin-top: 16px;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.78);
}

/* ==========================================================================
   14. Page level pieces the templates emit
   Added by the integration pass. The three page templates, the hero, the
   marquee band, the confirmation screens and the legal body all emitted names
   that no rule in this file or in components.css defined. Where a rule already
   existed the markup was renamed onto it; what follows is the remainder.

   This file is enqueued after components.css, so anything here wins a tie.
   Nothing below uses !important.
   ====================================================================== */

/* --- The three form page templates -------------------------------------- */

/* Kadence draws its own <main>. These are semantic hooks with no look of their
   own beyond making sure the two form pages sit on the cream canvas rather than
   on whatever the parent theme last set. */
.st4u-main--booking,
.st4u-main--enquiry {
  background: var(--canvas);
}

/* Semibold, not bold. This band is the hand written twin of
   .st4u-section-heading--lg, which already drops to --fw-semibold at 46px, and
   the two have to agree. The 12px margins are the same --space-3 the pattern
   heading uses as a flex gap between all three of its lines. */
.st4u-page-header__title {
  margin: var(--space-3) 0 0;
  font-family: var(--font-heading);
  font-size: var(--text-3xl);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: var(--heading-spacing);
  color: var(--text-strong);
}

.st4u-page-header__intro {
  margin: var(--space-3) 0 0;
  max-width: 60ch;
  font-size: var(--text-md);
  line-height: var(--lh-relaxed);
  color: var(--text-body);
}

/* The small uppercase label above a page title. The pattern equivalent is
   .st4u-section-heading__eyebrow; this is the hand written one the three page
   templates use, and the two must look the same, so the size and the colour are
   read straight off that rule: 13px in the navy, not 12px in sage green. */
.st4u-eyebrow {
  margin: 0;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--accent-strong);
}


/* The optional editor content between the page header and the form. */
.st4u-page-body {
  padding-block: var(--space-7);
}

/* --- The booking panel -------------------------------------------------- */

/* The eyebrow and the title are one block inside the dark rail, so the gap
   between them belongs to the pair rather than to the rail's own flex gap. Only
   the first child is reset: the title carries its own 8px top margin, and a
   blanket reset here silently threw that away. */
.st4u-booking-panel__head > :first-child {
  margin: 0;
}

/* --- The confirmation screens ------------------------------------------- */

.st4u-confirmation__title {
  margin: var(--space-5) 0 0;
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  font-weight: var(--fw-bold);
  line-height: var(--lh-snug);
  letter-spacing: var(--heading-spacing);
  color: var(--text-strong);
}

.st4u-confirmation__lede {
  margin: 14px 0 0;
  font-size: var(--text-md);
  line-height: var(--lh-relaxed);
  color: var(--text-body);
}

.st4u-confirmation__note {
  margin: 14px 0 0;
  font-size: 14px;
  line-height: var(--lh-relaxed);
  color: var(--text-muted);
}

.st4u-confirmation__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin: var(--space-6) 0 0;
}

/* --- The hero ----------------------------------------------------------- */

/* The left hand column of the split. It needs no width of its own: the grid in
   .st4u-hero__inner sets the two tracks. This only stops the block editor's own
   default margins collapsing the spacing between the badge, the title, the lead
   and the buttons. */
.st4u-hero__copy > * + * {
  margin-top: var(--space-4);
}

/* The three reassurance icons under the buttons. */
.st4u-hero__fact-svg {
  width: 18px;
  height: 18px;
  color: var(--brand-strong);
}

/* The featured image, drawn inside the portrait frame. The frame itself carries
   the aspect ratio, the radius and the shadow, so this only makes the image
   fill it. */
.st4u-hero__image,
.st4u-hero__image img {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
}

.st4u-hero__image img {
  object-fit: cover;
}

/* The placeholder shown on a page that has no featured image yet. It is
   aria-hidden, so it is a note to the owner and nothing else, and it is removed
   the moment a real image lands in the frame. */
.st4u-hero__empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  margin: 0;
  padding: var(--space-5);
  text-align: center;
  font-size: 14px;
  /* Sits on the frame's green gradient rather than covering it, so the shape the
     client approved is visible before any photograph is uploaded. Light text,
     because the panel behind it is dark. */
  color: rgba(255, 255, 255, 0.72);
  background: none;
  border-radius: inherit;
}

.st4u-hero__portrait:has(img) .st4u-hero__empty {
  display: none;
}

/* The two cards that overhang the portrait frame. .st4u-hero__float positions
   them; these are the lines inside. */
.st4u-hero__float-name {
  font-family: var(--font-heading);
  font-size: 18px;
  font-weight: var(--fw-bold);
  color: var(--text-strong);
}

.st4u-hero__float-role {
  margin-top: 2px;
  font-size: 13px;
  font-weight: var(--fw-bold);
  color: var(--accent-strong);
}

/* No added tracking and no green here. The attribution is a caption under the
   quote, so it recedes; the prototype sets it in the muted grey at the same
   tracking as everything else. */
.st4u-hero__float-cite {
  margin-top: 6px;
  font-size: 13px;
  font-weight: var(--fw-bold);
  color: var(--text-muted);
}

/* --- The feelings marquee ----------------------------------------------- */

/* The band the marquee sits in. Its own vertical padding is smaller than a
   normal section, as the prototype draws it. */
.st4u-marquee-band {
  padding-block: 0;
}

.st4u-marquee__eyebrow-icon {
  display: inline-flex;
  color: var(--green-bright);
}

.st4u-marquee__eyebrow-icon .st4u-icon {
  width: 18px;
  height: 18px;
}

/* The word on the pause control. Both halves are always in the markup so the
   accessible name always contains the visible word; layout.css section 9 swaps
   which half is shown on the checked state. */
.st4u-marquee__pause-text {
  font-size: 13px;
  font-weight: var(--fw-bold);
  color: inherit;
}

/* --- The legal page body ------------------------------------------------ */

.st4u-legal__updated {
  margin: 0;
  font-size: 13px;
  color: var(--text-muted);
}

.st4u-legal__lead {
  margin: var(--space-4) 0 0;
  font-size: var(--text-md);
  line-height: var(--lh-relaxed);
  color: var(--text-body);
}

/* --- Card titles and text ------------------------------------------------ */

/* The two titles are deliberately not the same size. A "why coaching" card is
   one of three headline claims and the approved design sets it at --text-lg,
   22px; a GROW step is one of six short rows and stays at 18px. */
.st4u-why-card__title {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  font-weight: var(--fw-bold);
  color: var(--text-strong);
}

.st4u-step__title {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 18px;
  font-weight: var(--fw-bold);
  color: var(--text-strong);
}

.st4u-why-card__text {
  margin: 8px 0 0;
  font-size: 15px;
  line-height: 1.65;
  color: var(--text-body);
}

/* The GROW step body sits beside the numbered circle, so it takes the rest of
   the row rather than shrinking to its content. */
.st4u-step__body {
  flex: 1 1 auto;
  min-width: 0;
}

/* The wide half of a rail split. min-width: 0 stops a long unbroken string, for
   example an email address in the legal body, forcing the track wider than its
   share and pushing the rail off the page. */
.st4u-split__main {
  min-width: 0;
}

/* ----------------------------------------------------------------------
   Kadence's page title band.

   inc/setup.php removes the callback that fills this section, but Kadence's
   template still prints the empty <section class="entry-hero page-hero-section">
   wrapper, which keeps its 200px minimum height and leaves a blank strip under
   the header on every page. The element carries no content and no landmark
   role once emptied, so hiding it costs nothing.
   ---------------------------------------------------------------------- */
.page .entry-hero.page-hero-section {
  display: none;
}

/* Kadence's boxed content card, neutralised on pages. The body class filter in
   inc/setup.php does the main work; these cover the inline styles Kadence
   prints against the container regardless of the class. */
.page .content-container.site-container {
  max-width: none;
  padding-inline: 0;
}

.page .entry-content-wrap {
  padding: 0;
  background: none;
  box-shadow: none;
}

/* ==========================================================================
   15. Kadence content typography, undone inside the theme's own components
   Added by the fidelity pass.

   Kadence styles the post body through .single-content, which is the second
   class on the block editor's own .entry-content wrapper. Those rules are
   (0,1,1) and (0,2,0):

     .single-content h1 ... h6   margin: 1.5em 0 0.5em
     .single-content p           margin-bottom: var(--global-md-spacing)
     .single-content ul, ol      margin-bottom + padding-left: 2em
     .single-content .wp-block-group, .wp-block-buttons   margin-bottom

   Every component in this theme and in components.css is written at one class,
   so all of them lost, and the result was a section eyebrow sitting 113px above
   its own title, cards of unequal height in a grid, and tick lists indented
   34px past the heading above them.

   The fix is one reset at (0,2,0), scoped to the theme's own component roots so
   that ordinary editor content further down a page keeps Kadence's spacing,
   followed by the handful of margins the design actually wants, restated at the
   same specificity and later in the file so they win the tie.

   Nothing here uses !important, and nothing here is a new value: every number
   below is already stated by the rule it is repeating.
   ====================================================================== */

/* The bands themselves. Each one carries its own --section-y padding, so they
   must abut with nothing between them. */
.entry-content.single-content > * {
  margin-block: 0;
}

/* Inside a component, the spacing belongs to the component's own gap, padding
   or restated margins below, never to the block editor's defaults. */
.single-content :is(
    .st4u-section-heading,
    .st4u-sh,
    .st4u-page-header,
    .st4u-page-header__inner,
    .st4u-section,
    .st4u-container,
    .st4u-grid,
    .st4u-masonry,
    .st4u-split__main,
    .st4u-hero__copy,
    .st4u-card,
    .st4u-price,
    .st4u-price-card,
    .st4u-testimonial,
    .st4u-quote,
    .st4u-step,
    .st4u-step__body,
    .st4u-cta-band__inner,
    .st4u-accordion,
    .st4u-accordion__item,
    .st4u-marquee__head
  ) > * {
  margin-block: 0;
}

/* The four real lists in the patterns. Kadence's `.single-content ul` adds a
   2em indent, which put every tick 34px to the right of the heading above it. */
.single-content :is(
    .st4u-tick-list,
    .st4u-fact-list,
    .st4u-benefit__list,
    .st4u-booking-panel__facts
  ) {
  margin: 0;
  padding: 0;
}

/* --- The margins the design does want, restated ------------------------- */

/* The hero column. */
.single-content .st4u-hero__title {
  margin-top: 20px;
}

.single-content .st4u-hero__lead {
  margin-top: 22px;
}

.single-content .st4u-hero__actions,
.single-content .st4u-hero__facts {
  margin-top: 30px;
}

/* The full logo at the foot of the column, FBL-0050. Section 8 carries the rest
   of it. */
.single-content .st4u-hero__lockup {
  margin-top: clamp(20px, 2.5vw, 32px);
}

/* The icon tile at the top of a why coaching card and a benefit card. */
.single-content .st4u-card__icon {
  margin-bottom: 16px;
}

.single-content .st4u-why-card__text {
  margin-top: 8px;
}

/* The GROW step body. */
.single-content .st4u-step__text {
  margin-top: 5px;
}

/* The testimonial masonry, which has no inline margin of its own the way the
   why coaching and GROW grids do. */
.single-content .st4u-masonry {
  margin-top: var(--space-7);
}

/* The testimonial carousel, for the same reason and then one of its own. A
   core/html block renders raw with no editor wrapper around it, so the dark
   panel is a real direct child of .st4u-section and the reset above matches it,
   which kills theme.json's zero specificity blockGap rule. Every other pattern
   gets its gap back from an inline block spacing style on a group wrapper, and a
   core/html block cannot carry one, so the gap has to be restated here or the
   section heading sits flush against the top edge of the panel at every width.

   .st4u-carousel is deliberately NOT added to the :is() list above while doing
   this. That list would also zero the track's margin-top: -44px, which is load
   bearing: it is the half of a pair with padding-top: 44px that keeps the quote
   mark from being clipped by the scroll container, and the panel would grow 44px
   taller. */
.single-content .st4u-carousel {
  margin-top: var(--space-7);
}

/* The women's group facts heading, which sits closer to its list than a full
   section heading does. */
.single-content .st4u-split__main > .st4u-section-heading {
  margin-bottom: 20px;
}

/* The dark call to action band. */
.single-content .st4u-cta-band__intro {
  margin: 16px auto 0;
}

.single-content .st4u-cta-band__actions {
  margin-top: 30px;
}

.single-content .st4u-cta-band__note {
  margin-top: 16px;
}

/* The two rail cards. */
.single-content .st4u-cta-card__text {
  margin-top: 10px;
}

.single-content .st4u-cta-card__action,
.single-content .st4u-price-cta__action {
  margin-top: 20px;
}

.single-content .st4u-price-cta__amount,
.single-content .st4u-price-cta__text,
.single-content .st4u-price-cta__note {
  margin-top: 12px;
}

/* The two benefit cards on the women's group page. */
.single-content .st4u-benefit__intro {
  margin-top: 8px;
}

.single-content .st4u-benefit__label {
  margin-top: 18px;
}

.single-content .st4u-benefit__list {
  margin-top: 12px;
}

/* ----------------------------------------------------------------------
   The two highlighted words in the hero headline.

   The pattern marks them with the theme.json preset class
   has-accent-strong-color, but no --wp--preset--color--* variables reach the
   front end on this install, so the class is inert and the emphasis the client
   approved was simply not there. The token is named directly instead.
   ---------------------------------------------------------------------- */
.st4u-hero__title .has-accent-strong-color {
  color: var(--accent-strong);
}

/* ----------------------------------------------------------------------
   The band gutter on a viewport narrower than the content box.

   WordPress gives a constrained group's children max-width: content-size and
   auto side margins, and nothing else. Once the viewport is narrower than the
   content box those children simply fill it, so on a phone every grid, card
   and section heading that sits straight inside a band ran edge to edge and
   the copy touched the screen. Capping the same max-width at the viewport
   less its two gutters restores the inset, and resolves to exactly the value
   WordPress already used on any viewport wide enough to hold the content box,
   so nothing above 1180px moves.

   .st4u-container is excluded because it carries the gutter as padding of its
   own, and a full-bleed child is excluded because escaping the gutter is the
   whole point of one.
   ---------------------------------------------------------------------- */
.st4u-section > :not(.st4u-container):not(.alignfull) {
  max-width: min(
    var(--wp--style--global--content-size),
    calc(100% - (2 * var(--gutter)))
  );
}

/* The footer legal row. Quiet, under the copyright line, because it is there to
   be findable rather than prominent. Kept to the same muted tone as the rest of
   the footer base so it does not compete with the navigation above it. */
.st4u-footer__legal {
  max-width: var(--container);
  margin-inline: auto;
  padding: 0 var(--gutter) 22px;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.5);
}

.st4u-footer__legal a {
  color: rgba(255, 255, 255, 0.7);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.st4u-footer__legal a:hover {
  color: var(--white);
}

/* A rule of its own, for the reason given at .st4u-booking-panel__enquire: a
   browser that does not know :focus-visible drops a whole selector list, and
   the hover colour with it, and body a:hover then turned these words dark
   green on the dark green footer. */
.st4u-footer__legal a:focus-visible {
  color: var(--white);
}

/* ==========================================================================
   16. Testimonials carousel
   Six client testimonials as light cards on a dark blue panel: three side by
   side on a desktop, two on a tablet, one on a phone, with the arrows paging a
   whole screenful at a time.

   It is a CSS scroll snap carousel that JavaScript enhances, not a JavaScript
   carousel. .st4u-carousel__track is a horizontally scrollable flex row with
   scroll-snap-type: x mandatory, and every card carries scroll-snap-align:
   start. With no script at all that already gives native swipe on a phone,
   trackpad and wheel scrolling, keyboard scrolling from the track's own
   tabindex, and all six testimonials reachable. The arrows and the dots are
   enhancements layered on top of a thing that already works.

   It does not auto advance, and it never should. Movement that starts on its
   own and runs for more than five seconds needs a pause control under SC 2.2.2
   Pause, Stop, Hide, and a timer takes reading time away from anybody slower
   than whoever set it. A visitor moves this carousel or it does not move.

   Three numbers below carry more weight than they look:

     - the gap, subtracted inside every card's flex basis. Three cards and the
       two gaps between them then come to exactly 100% of the track, and that is
       what makes the paging honest: the furthest the track can scroll lands
       precisely on the fourth card's leading edge, so the second page is a whole
       page rather than a page and a sliver. It is also why
       assets/js/st4u-carousel.js can move by a plain track.clientWidth and needs
       no idea which breakpoint it is in. Change the divisor and change the
       subtraction with it.
     - box-sizing on the card. The 32px of padding and the 1px border that
       .st4u-testimonial gives it have to sit inside that basis, or three cards
       do not fit the width they were handed and every page after the first
       drifts. It is restated here rather than trusted to the parent theme's
       reset, because the arithmetic above stands on it.
     - the single flex line. All six cards sit on one line of the track's flex
       row, and the default align-items: stretch gives each of them the height of
       the tallest, so a two line testimonial and a seven line one still make a
       level row. Setting the track to display: block, or adding flex-wrap, takes
       that away.

   The panel is dark and the cards are light, which is the whole point of the
   design, so the contrast figures are recorded beside the colours that had to
   earn them. Everything measured against the panel is measured against #0b3d72.
   ====================================================================== */

/* The panel. position: relative is what the two arrows are positioned against,
   so it is structural here rather than decorative.

   --navy-700 is named rather than its alias --accent-strong, which resolves to
   the same #0b3d72, because the client asked for the brand navy itself and not
   for whatever the accent colour happens to become. A white card on it is
   10.9:1, so the edge of a card is never in question.

   text-align: center survives from the previous design and still earns its
   place: it is what centres the two arrows on their own line once they drop
   below the track on a phone, so the pair needs no wrapper. Each card sets its
   own words back to the leading edge. */
.st4u-carousel {
  /* The one place the space between two cards is written down. The track spends
     it as its flex gap and every card subtracts it from its own basis, so the
     two cannot drift apart. */
  --st4u-carousel-gap: var(--space-5);

  position: relative;
  background: var(--navy-700);
  padding: 56px 60px;
  text-align: center;
}

/* The scroll container AND the flex row, in one element. There is no separate
   viewport wrapper, so anything added here has to be safe for both jobs.

   The padding and negative margin pair that used to sit here has gone. It
   existed to stop the scroll container clipping one 64px quotation mark that
   overhung the top of the panel, and both marks now sit inside a card whose own
   32px of padding holds them, so there is nothing overhanging left to save. */
.st4u-carousel__track {
  display: flex;
  gap: var(--st4u-carousel-gap);
  overflow-x: auto;
  /* Explicit rather than left to the initial value. Setting overflow on one
     axis forces the other axis to compute to auto, so leaving this out invites
     a stray vertical scrollbar. */
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  /* Keeps a swipe that runs off the last card inside the carousel, rather than
     handing it to the page or to the browser's back gesture. */
  overscroll-behavior-inline: contain;

  /* Hidden, never disabled. The bar is noise under a row of cards and the dots
     below already say where you are, but the element stays a real scroll
     container: wheel, trackpad, touch and keyboard all still move it. Reaching
     for overflow: hidden here would take the carousel away from everybody who
     has no pointer. */
  scrollbar-width: none;
}

.st4u-carousel__track::-webkit-scrollbar {
  display: none;
}

/* Smooth scrolling is opt out, not opt in. Declaring it inside a no-preference
   block means a visitor who has asked for less motion is never given the
   animation in the first place, which is cleaner and more reliable than setting
   it for everybody and then trying to unset it further down the file. */
@media (prefers-reduced-motion: no-preference) {

  .st4u-carousel__track {
    scroll-behavior: smooth;
  }
}

/* The track carries tabindex="0" so the cards can be scrolled by keyboard, and
   anything that takes focus has to show it, which is SC 2.4.7. The offset is
   positive now that the track's box is exactly the row of cards: the ring sits
   in the panel's own padding, where there is 56px of navy for it and nothing to
   collide with. White on the panel is 10.9:1. */
.st4u-carousel__track:focus-visible {
  outline: 3px solid var(--white);
  outline-offset: 3px;
}

/* One card, and a third of the track wide. The subtraction is the whole trick:
   two gaps come out before the division, so three cards and the two gaps
   between them make exactly the width of the track and every page boundary
   falls on a card edge. Read the note at the top of this section before
   changing either number.

   The card itself is dressed by .st4u-testimonial in components.css, which the
   pattern puts on this same element, so this rule only has to make it a slide.
   That is deliberate: the gallery pattern and the carousel then show the same
   card, and a change to the card is made once. */
.st4u-carousel__slide {
  flex: 0 0 calc((100% - (var(--st4u-carousel-gap) * 2)) / 3);
  scroll-snap-align: start;
  /* Load bearing, and not left to the parent theme. The basis above is the
     card's whole width, its padding and border included, which is only true
     under border-box. */
  box-sizing: border-box;
  /* A flex item's automatic minimum size is its content, so one long unbroken
     word could otherwise push a card wider than its share of the track. */
  min-width: 0;
  /* The panel is centred for the sake of the arrows. A testimonial is read
     rather than scanned, so the card sets its own words back to the leading
     edge, which is the left in English and the right in a right to left
     language. */
  text-align: start;
  /* --shadow-sm is a navy shadow, and on a navy panel it draws nothing except
     something for the scroll container to clip. The card is already separated
     from the panel by 10.9:1 of contrast, which is a stronger edge than a
     shadow. */
  box-shadow: none;
}

/* No margin on a card, and it takes two classes to say so.

   A figure carries 1em 40px from the user agent, and Kadence's content.min.css
   replaces that with .single-content figure { margin-bottom: 32px }, which is a
   class and an element and outranks anything with one class in it. Both would
   throw the basis above out and break the snap.

   The 32px was invisible while one quotation filled the whole track. In a row
   of cards it is not, and it fails in a way that takes some finding: a flex line
   is as tall as the tallest item plus that item's own margins, and every card is
   then stretched to the line less its own margins, so five cards came out 32px
   shorter than the sixth and the last card hung below the row. */
.st4u-carousel__track .st4u-carousel__slide {
  margin: 0;
}

/* The attribution, held at the foot of the card.

   components.css already asks for that with margin-top: auto, and section 15 of
   this file takes it away again: the .single-content reset zeroes the block
   margins of every direct child of a card, and auto is a block margin. Without
   this the three names in a row sit wherever their own quotation happens to
   end, which on quotations running from two lines to seven is a ragged line
   nobody would have drawn on purpose.

   Two classes, so it outranks that reset, and further down the file than it, so
   the tie between two equally specific rules is settled here. The gallery
   solves the same problem the other way, at .st4u-masonry__item, by letting the
   quotation take the slack instead. */
.st4u-carousel__slide .st4u-testimonial__foot {
  margin-top: auto;
}

/* The closing quotation mark, which the cards did not have until the client
   asked for one. It shares .st4u-testimonial__mark with the opening mark, so
   the family, the weight, the size and the colour are declared once in
   components.css and the pair cannot fall out of step. Both are decorative and
   both are aria-hidden in the markup: the blockquote already carries the
   quotation, and a screen reader announcing a quotation mark twice would be
   reading punctuation rather than meaning.

   align-self works on the cross axis, which in a column flex container is the
   inline axis, so flex-end puts the mark at the end of the line the language
   reads towards without this file naming left or right.

   The negative margin pulls it back up under the last line of the quotation.
   The card's own 16px gap plus the mark's half line height would otherwise
   leave it floating in the middle of the space below the words. It carries two
   classes for the same reason the rule above does, and not for the look of it:
   a single class loses to section 15 and the pull is silently dropped. */
.st4u-carousel__slide .st4u-carousel__mark-close {
  align-self: flex-end;
  margin-top: -8px;
}

/* --- Two cards, then one ------------------------------------------------ */

/* Two across from 640px and one below it. Only the basis changes: the
   subtraction drops to a single gap for two cards, and to nothing at all for
   one, because a lone card has no gap beside it inside the track. */
@media (max-width: 1023px) {

  .st4u-carousel {
    padding: 48px 56px;
  }

  .st4u-carousel__slide {
    flex-basis: calc((100% - var(--st4u-carousel-gap)) / 2);
  }
}

/* One card below 640px, in a tighter panel. What happens to the arrows at this
   width is at the foot of the section rather than here, and the reason is
   written there. */
@media (max-width: 639px) {

  .st4u-carousel {
    --st4u-carousel-gap: var(--space-4);

    padding: 40px 22px;
  }

  .st4u-carousel__slide {
    flex-basis: 100%;
  }
}

/* --- The two arrows ----------------------------------------------------- */

/* The offset clears the panel's side padding: a 40px arrow at 10px reaches
   50px, and the cards start at 56px or 60px, so the two never overlap. */
.st4u-carousel__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 40px;
  height: 40px;
  padding: 0;
  /* 45% white, not the 25% this carried on the old green panel. The centre of
     the arrow is all but transparent, so the ring is the only thing showing
     where the control is, which puts it under SC 1.4.11 Non-text Contrast and
     its 3:1. 25% composites to #486e95 on the navy and is 2.05:1, which fails.
     45% gives #7994b1 and 3.47:1. It failed on the green panel too, at 1.84:1,
     so this is a fix rather than a consequence of the new colour. */
  border: var(--border-width) solid rgba(255, 255, 255, 0.45);
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.06);
  /* The chevron is 9.2:1 against the arrow's own background. */
  color: var(--white);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out);
}

.st4u-carousel__arrow--prev {
  left: 10px;
}

.st4u-carousel__arrow--next {
  right: 10px;
}

/* The script genuinely disables an arrow that has nowhere left to go, and the
   carousel opens on the first page, so the previous arrow is dead from the
   first frame a visitor sees. Without this it looks exactly like the live arrow
   beside it, which is the same house convention .st4u-btn[disabled],
   .st4u-day[disabled] and .st4u-time[disabled] already follow in components.css.
   The state was reaching assistive technology and nobody else. */
.st4u-carousel__arrow[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Kadence's button rule again (K-37; see .st4u-btn in components.css): on
   hover, focus and press it filled the arrow with its own blue and lifted it on
   a shadow, the dead arrow included. Restated at (0,2,0), before the live
   arrow's own hover below, which is heavier and still wins. */
.st4u-carousel__arrow:hover,
.st4u-carousel__arrow:focus,
.st4u-carousel__arrow:active {
  background: rgba(255, 255, 255, 0.06);
  color: var(--white);
  box-shadow: none;
}

/* :hover is not blocked by :disabled, so without the :not() a dead arrow still
   lit up under the pointer, telling the visitor it was live at the moment it
   was not. */
.st4u-carousel__arrow:not([disabled]):hover {
  background: rgba(255, 255, 255, 0.16);
}

.st4u-carousel__arrow:focus-visible {
  outline: 3px solid var(--white);
  outline-offset: 2px;
}

.st4u-carousel__arrow-glyph {
  display: inline-flex;
}

/* st4u_icon() emits an SVG sized at 1em and stroked in currentColor, so the
   chevron takes the white set above and only needs a size here. */
.st4u-carousel__arrow .st4u-icon {
  width: 18px;
  height: 18px;
}

/* PHP renders the arrows and the dots carrying the hidden attribute, and the
   script removes it once it has taken over, so nothing that does nothing is
   ever shown. That only works if hidden genuinely hides them, and it does not
   on its own: the user agent's [hidden] rule is display: none at the very
   bottom of the cascade, so every display value set above beats it and the
   controls would flash up before any script ran, or sit there inert if the
   script never loaded at all. Restating it against the class puts the rule back
   on top. */
.st4u-carousel__arrow[hidden],
.st4u-carousel__dots[hidden] {
  display: none;
}

/* --- The dots ----------------------------------------------------------- */

/* One dot per page rather than per testimonial, so there are two of them on a
   desktop and six on a phone. PHP ships this element empty and the script fills
   it, because how many pages there are depends on how many cards fit, and only
   the browser can answer that. */
.st4u-carousel__dots {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 22px;
}

/* The dot has a transparent centre, so this 1px ring is the whole of the
   control. That puts it under SC 1.4.11 Non-text Contrast, which asks for 3:1
   against what it sits on. At 55% white the ring composites to #91a8c0 on the
   navy panel, which is 4.5:1. It was raised to 55% for the old green panel,
   where 45% gave 2.8:1 and failed; on the navy, 45% would now pass at 3.5:1,
   and it stays at 55% because a hollow 9px circle is a small thing to find and
   the extra weight costs nothing. */
.st4u-carousel__dot {
  position: relative;
  box-sizing: border-box;
  width: 9px;
  height: 9px;
  padding: 0;
  border: var(--border-width) solid rgba(255, 255, 255, 0.55);
  border-radius: var(--radius-pill);
  background: transparent;
  cursor: pointer;
}

/* The same Kadence rule filled a hollow dot blue under the pointer and on
   focus (K-37). A dot is hollow until it is the current page. Stated before the
   current dot's rule, which has the same weight and so still wins. */
.st4u-carousel__dot:hover,
.st4u-carousel__dot:focus,
.st4u-carousel__dot:active {
  background: transparent;
  box-shadow: none;
}

/* The current page is marked by aria-current in the markup, so that attribute
   is the hook here rather than a class the script would have to keep in step
   with it. One source of truth, and it is the one assistive technology reads.

   It is deliberately not colour alone. Anybody who cannot separate the pale
   green from the translucent white still sees a solid circle among hollow ones
   and a larger circle among smaller ones, which is what SC 1.4.1 Use of Colour
   asks for. The size change is a transform, so it costs no layout and the row
   of dots does not shuffle sideways as the visitor moves through.

   --green-200 rather than --green-bright, and for the same reason as the ring
   above: SC 1.4.11 wants 3:1 for the visuals that identify a control and its
   state, and #4fa94f on the navy panel is 3.7:1 where #cbdccf is 7.6:1. The
   brighter green would scrape a pass and still be the hardest dot on the panel
   to find. Passing SC 1.4.1 with the solid fill and the scale did not settle
   1.4.11, which is a separate criterion. */
.st4u-carousel__dot[aria-current="true"] {
  background: var(--green-200);
  border-color: var(--green-200);
  transform: scale(1.35);
}

.st4u-carousel__dot:focus-visible {
  outline: 3px solid var(--white);
  outline-offset: 3px;
}

/* A 9px circle is a cruel target for a thumb, so the button is given an
   invisible one of roughly 17px by 27px. The inline inset is exactly half the
   8px gap, so neighbouring targets meet and never overlap: overlapping hit
   areas fire the wrong dot, which is a worse fault than a small one.

   That is still under the 24px of SC 2.5.8 Target Size (Minimum), and honestly
   so. The criterion's equivalent control exception is what carries it: every
   page is reachable from the 40px arrows, from a swipe and from the keyboard,
   so nothing at all is available only through a 9px dot. */
.st4u-carousel__dot::before {
  content: "";
  position: absolute;
  inset: -9px -4px;
}

/* --- Narrow viewports, and why this is the last thing in the section ----- */

/* Under 640px the arrows come out of the corners and sit below the card, rather
   than being shrunk in place.

   Shrinking was the other option and it was the wrong one. One card fills
   whatever width is left, so an arrow floating over the panel lands on top of
   the words once the panel is narrow, and a smaller arrow lands on them just as
   squarely while being harder to hit. Below the card it covers nothing and
   stays a 40px target. Little is lost by moving them either, because a phone
   already has the swipe.

   position: static is what releases the left, right and top offsets, and the
   panel's own text-align: center is what puts the pair in the middle of the
   line, so the two buttons need no wrapper around them and the agreed markup
   stands unchanged.

   It sits here, after .st4u-carousel__arrow, and not up with the other two
   widths, because a media query buys no specificity. Both selectors are one
   class, so the later one wins wherever it is written, and this block above the
   arrow rule reads as though it works while quietly doing nothing but the
   margin. */
@media (max-width: 639px) {

  .st4u-carousel__arrow {
    position: static;
    transform: none;
    display: inline-flex;
    margin: 20px 5px 0;
  }
}

/* ==========================================================================
   17. Utilities
   ========================================================================== */

/* A line break that only applies where there is room for it.

   Used where a two sentence intro reads better with the second sentence on its
   own line. Below this width the first sentence already wraps by itself, and a
   forced break there would leave a short line with two or three words on it,
   which looks like a mistake rather than a choice.

   Always put a space before it: "Zoom. <br class="st4u-break-wide">Bring". Hidden,
   the break leaves nothing between the two sentences, so without the space they
   ran together on a phone, "Zoom.Bring" (1 October 2026). Where the break shows,
   the space sits at the end of a line, where browsers drop it, so wider screens
   look exactly as they did. A plugin test checks every use. */
.st4u-break-wide {
  display: none;
}

@media (min-width: 48em) {

  .st4u-break-wide {
    display: inline;
  }
}

/* Issue 21: the three footer columns were equal thirds, which left the Pages
   list sitting hard against the brand text with a wide gap to its right. It read
   as misaligned rather than as three columns. The first column carries a logo
   and a sentence and genuinely needs more room than a list of five links, so the
   widths now reflect the content. Only above this width: below it the columns
   stack and the question does not arise. */
@media (min-width: 62em) {

  /* This read .st4u-footer__grid until 1.0.5, a class the markup has never carried,
     so the rule matched nothing and the columns stayed equal thirds on the live
     site. The element is .st4u-footer__inner.

     Written as fr and not per cent. The row has a 36px gap between columns, and fr
     is sized after the gaps are taken out; three per cent values adding up to a
     hundred would overflow the row by exactly the two gaps, 72px. Kept inside the
     query so the base rule below 62em still stacks the columns on a phone. */
  .st4u-footer__inner {
    grid-template-columns: 38fr 24fr 38fr;
  }
}

/* The pair of buttons under the fee cards, added when the Book now button came
   off each card. The cards' own band closes with zero bottom padding, because a
   reassurance note follows on the fees page, so the spacing has to come from
   here rather than from the band. */
.st4u-fees .st4u-fees__actions {
  justify-content: center;
  gap: var(--space-4);
  /* Two classes deliberately. Section 15 resets margin-block to 0 on children of
     Kadence's content wrappers, at (0,1,1), so a single class rule here is
     silently zeroed and the buttons sit hard against the cards. */
  margin-top: var(--space-6);
  /* Lifted above the band that follows. The buttons end flush with their own
     band, and the next one is positioned with a fill of its own, so it painted
     over the bottom edge of their focus ring and of their hover shadow. */
  position: relative;
  z-index: 1;
}
