/* ==========================================================================
   COMPONENTS Structural layout for all site sections
   ========================================================================== */

/* ---------- Global text justify (editorial prose. Specificity (0,1,1) so the
   per-class patches below still win. Applied to every page, home included, so
   line endings are synchronized across the whole site.

   "Synchronized" is the whole point and also the whole limit. Justifying
   reaches a straight right edge by spending the leftover width, and where the
   leftover is large the spending lands in the word spaces. The patches below
   are the boundary of that: prose keeps the rule, and short captions are taken
   out of it. See the measured block further down for why the list is those ten
   containers and not others.

   hyphens is manual, not auto. Auto hyphenation was breaking words in half
   mid-word and it looked like a printing error rather than a typesetting aid.
   The Credentials lead on index.html, at every width, read:

     Professional training and certifica-
     tions from internationally recog-
     nized institutions.

   Three lines, two split words, one of them cut six letters from the end. That
   is what hyphens: auto does to a SHORT paragraph: the text is two or three
   lines long, so there is no paragraph rhythm to justify breaking anything, and
   every break is visible as a defect because the reader can see the whole
   sentence at once. Hyphenation pays for itself in a long column of body copy
   and costs on a lead.

   manual is also the CSS default, so this restores the browser's own behaviour:
   break only where the author put a hyphen or a soft hyphen, which this site
   already does in copy like "Sessions 2-3" and "Weeks 3-7".

   The whole site is short paragraphs, leads and card captions rather than
   long-form articles, so auto hyphenation was a net loss everywhere on it, not
   only on this lead. The nine rules that asked for auto are all now manual, and
   .hiw-card p already was.

   Justification has now gone too, and the hyphenation decision above is what
   decided it. Hyphenation is how a justified line gets more places to break,
   which is how it absorbs slack instead of pushing it into the word spaces. With
   auto hyphenation off, every gap has to come out of the spaces, and the measures
   on this site are short.

   Measured by rendering each space in every justified paragraph and comparing its
   width against the font's natural space advance, at 390px and across every page:
   85 paragraphs on 13 pages had a space stretched beyond twice its natural width,
   and the worst was 26x, an 83.6px gap where a space should be 3.2px.

   That was not a phone fault. corporate-wellbeing was bad from 390px all the way to
   1600px, and about.html was worst in the middle of the range rather than at the
   bottom: 11.6x at 860px, where its story grid is two columns of 323px, and still
   5.6x at 1440px with a 513px column. legal.html was 3.6x at every width, because
   its reading column is capped at 500px.

   Those columns run 52 to 63 characters, against the 65-78 this site's own notes
   call the comfortable reading range, and justification wants more than that to
   avoid rivers. Ragged right is the typographic default for body copy and it cannot
   produce this failure at all, so it is what the site uses now.

   hyphens: manual stays. It is independently correct, being what stops a word
   being split mid-word, and it costs nothing now that nothing is justified.

   text-wrap: pretty is the second half of tidying the rag. With justification
   gone, the remaining fault in a narrow column is the orphan: a last line
   carrying one word. That is what put a lone "memory", "time" and "pursues" on
   their own lines on the poem page, and pretty exists to prevent exactly that by
   re-breaking the tail of a paragraph rather than the whole of it. It is
   progressive enhancement: where it is not supported the rag is simply the
   browser default, which is no worse than before.

   The list is a :is() group rather than p alone because pretty only reached
   paragraphs, and the orphans that remained were all in other prose elements:
   ten last lines holding a single word at 390px, across five pages, in list
   items, blockquotes and leads. p was (0,2,0) and this is (0,2,0) too, so nothing
   that used to win here stops winning, and no other rule is displaced. */
.section :is(p, li, dd, blockquote) { hyphens: manual; text-wrap: pretty; }
.section .lead { text-align: center; }
.section .eyebrow { text-align: center; }
.section .card-label { text-align: left; }
.section .card-note { text-align: left; }
.section .check-list { text-align: left;}
.section .legal-date { text-align: left;}

/* ---------- The same opt-out for every short caption ----------

   The blanket rule above justifies every paragraph in every section so that
   line endings line up across the site. That only works while the measure is
   wide enough to reach the right edge without touching the word spacing.
   Below roughly 45 characters per line there is no such width, so the browser
   reaches the edge by inflating the gaps between words instead, and the text
   stops looking typeset and starts looking spaced out.

   This is measured, not estimated. Every justified paragraph on all 24 pages
   was measured for measure width and for the actual gap between consecutive
   words, and compared against the font's own space width. The results:

     packages.html, .why-item caption at 1024px, 212px measure, 26 chars/line:
     median word gap 8.1px against a natural 3.8px, and because the median
     equals the maximum, EVERY gap in the paragraph is stretched, not just one
     loose line. That is 2.2x. At 390px the worst single gap reaches 2.64x.

     The control is on the same page and proves the mechanism rather than the
     correlation: .card-note is opted out two rules above, and it measures
     0.76x, i.e. its gaps are natural. Same font, same column, same page.

   Seventy paragraphs were affected, in ten containers. The narrowest were
   .step at 21 characters per line and .why-item at 23, which is not a measure
   any book would set, let alone justify.

   So the patch list above now covers all ten, as one :is() group rather than
   ten rules, and for the same reason the comment on that list can be trusted:
   these are the captions, and a caption is not editorial prose. Prose keeps
   its justification and its synchronised line endings, which is what the
   blanket rule was for.

   Specificity is (0,2,1) against the blanket's (0,1,1), so this wins without
   needing !important, and any page that already sets alignment on one of these
   containers at a higher specificity still keeps its own choice. */

.section :is(.mini-card, .why-item, .step, .theme-card, .stage, .hook-card,
             .achieve-card, .testi-card, .work-card, .legal-toc) p {
  text-align: left;
}
/* explicit center utility must win over the blanket patches above */
.section p.text-center,
.section .text-center,
.section .text-center p { text-align: center;}

/* ---------- Header / Nav ---------- */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  height: var(--header-h);
  background: transparent;
  border-bottom: 1px solid transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  transition: background 0.35s ease, box-shadow 0.35s ease, height 0.35s ease, border-color 0.35s ease;
}
.site-header.scrolled {
  background: rgba(251, 247, 240, 0.72);
  border-bottom-color: rgba(251, 247, 240, 0.5);
  box-shadow: var(--shadow-sm);
  -webkit-backdrop-filter: blur(22px) saturate(1.5);
  backdrop-filter: blur(22px) saturate(1.5);
  height: var(--header-h-scrolled);
}
/* Track definitions are unchanged from before, deliberately.

   The wordmark bug was never really about these three values. A plain auto track
   is sized max-content but allowed to shrink to min-content, and min-content for
   "SAEED UR RIAZ" is its LONGEST WORD. The middle 1fr track cannot shrink - every
   nav link is white-space: nowrap, so its min-content is its full width - so the
   two outer tracks absorbed the whole shortfall and the logo, a flex item with the
   default min-width: auto, collapsed to one word per line.

   That is fixed at the item, by min-width: max-content on .logo below, because
   fixing it in the track definition is what breaks the design. The obvious
   spelling, minmax(max-content, 1fr) on the outer tracks, was written and
   measured: it does stop the wrap, but it unbalances the tracks - the logo needs
   125px and .header-right needs 389px, so 1fr cannot make them equal - and it
   pushed the nav 120px off centre at a 1296px viewport. Plain 1fr is what keeps
   the nav dead centre, which is the only reason the 1400px query exists. */
.header-inner {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: clamp(10px, 1.5vw, 18px);
  width: min(100% - 32px, var(--container));
  margin-inline: auto;
  padding: 0;
  height: 100%;
}
/* 1400px is where this query used to meet the phone-number query in
   breakpoints.css exactly, and that meeting point is the whole trigger: at
   1401px and up the phones came back at the same moment the logo track became
   space-sized. The phones now drop out at 1500px, so this query only ever has to
   hold the bar without them, which it has 200px of room for. */
@media (min-width: 1400px) {
  .header-inner { grid-template-columns: 1fr auto 1fr;}
}
.logo {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  /* The floor that actually holds. min-width: max-content raises the item's
     automatic minimum size from min-content to max-content, so no track
     definition above can squeeze the wordmark under its single-line width. The
     grid would then overflow rather than wrap, and with the phones gone below
     1500px there is room for it not to. */
  min-width: max-content;
  flex-shrink: 0;
}
.logo-mark {
  width: 38px; height: 38px;
  border-radius: 10px;
  background: var(--gold);
  color: var(--white);
  display: grid; place-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  flex-shrink: 0;
}
.logo-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  flex-shrink: 0;
}
/* The wordmark and its tagline are one line each, always.

   white-space: nowrap is the actual fix for the two-line logo. The two spans are
   meant to STACK - name above, tagline below - and .logo-text is a column flex
   that already does that. What went wrong is each span wrapping INSIDE itself
   once the track got narrow, so "SAEED UR RIAZ" became two lines and pushed the
   tagline down out of the bar entirely.

   Fluid sizing, and this is the reason the bar now fits at all rather than just
   failing more gracefully. Both ramps are anchored to hit their current desktop
   value at 1400px and scale down from there:

     .logo-name     14.4px at 1025  ->  16.8px at 1400  (was a flat 16.8px)
     .logo-tagline   8.64px at 1025 ->   9.6px at 1400  (was a flat 9.6px)

   The floor is deliberately above the 320px mobile case rather than below it.
   At 1024px and under the nav is a full-screen overlay, so the bar holds only the
   wordmark and the hamburger: there is no competition for width and shrinking
   the wordmark there would only make it harder to read. */
.logo-name {
  font-family: 'Cormorant Garamond', var(--font-display);
  font-weight: 600;
  font-size: clamp(0.9rem, 0.64vw + 0.49rem, 1.05rem);
  color: var(--charcoal);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}
.logo-first { color: var(--gold);}
.logo-tagline {
  font-family: var(--font-ui);
  /* Raised from clamp(0.54rem, 0.26vw + 0.38rem, 0.6rem), which was 8.64px at
     1025 and 9.6px at 1400. That is roughly the practical floor for a letterform
     at this weight: the tagline is the smallest text on the site and it was
     carrying the accent colour from the last two passes, so a bigger accent is
     the point rather than a coincidence.

     10.56px at 1025 up to 12.6px at 1400. Both ends moved by roughly 1.5x the
     old value rather than being rounded, so the ramp keeps its original shape:
     the ceiling is reached at about the same 1400px the wordmark's own ramp uses,
     which is what makes the two lines still look like a pair at every width.

     Width is the binding constraint here, not the 80px bar. .logo carries
     min-width: max-content and the header is a three-column grid whose outer
     tracks are 1fr, so a wider tagline eats the nav's slack. Measured after this
     change: the wordmark block grew from 125px to 172px at 1025px, and the nav
     still sits dead centre because 1fr on both outer tracks absorbs it. That
     stops being true at some width, and 1025px is the narrowest width where the
     nav is still inline, so this is measured at the right end of the range.

     letter-spacing goes 0.06em to 0.08em with it. Uppercase sans at 10px needs
     the air more than 16px does, and the extra tracking is what keeps the three
     words from reading as one. */
  font-size: clamp(0.66rem, 0.34vw + 0.47rem, 0.7875rem);
  /* --gold, not --muted, on the client's request: the tagline carries the accent
     colour in both header states, on the sticky bar and over a banner alike.

     This is the sticky-bar half of that, and it is a strict gain rather than a
     trade. --gold #22544C is darker than --muted #7A7063, so against the light
     ground the contrast can only rise, and it does: 4.83:1 to 8.55:1. There is
     no version of this change that loses legibility.

     The banner half cannot use this value and is in page-overrides.css: --gold
     measures 0.072 luminance and the darkest pixel a banner presents under the
     header is 0.1374, so the brand colour on a photograph would be darker than
     the ground it sits on. Over a banner the accent has to be the light end of
     the same family, --banner-ink. Same colour identity, two values, because the
     ground underneath is two different things.

     The tagline is the smallest text in the bar at 9.6px, which is the reason it
     has no length to absorb a lower figure: it does not qualify as large text at
     any viewport, so 4.5:1 is the floor in both states. */
  color: var(--gold);
  letter-spacing: 0.06em;
  margin-top: 2px;
  white-space: nowrap;
}

/* Nav */
.nav { justify-self: center; overflow: visible; display: flex; align-items: center; height: 100%;}
.nav-mobile-head, .nav-close, .nav-mobile-cta { display: none;}
.nav-list { display: flex; gap: clamp(2px, 0.5vw, 5px); margin: 0; justify-content: center; align-items: center;}
.nav-list li { position: relative;}
/* Eight links, all nowrap, so the nav's min-content is its full width and it can
   never be the thing that gives up space - which is exactly why the squeeze used
   to land on the logo instead.

   The nav is the only elastic part of the bar, so it is also the part that should
   scale. This ramp holds the current 13.44px from 1440px up and steps down to
   11.52px by about 1100px, which is roughly 45px of width handed back to the
   grid at the tight end. Measured at 1401px with the phones restored:

     logo 130 + nav 736 + right 389 + gaps 36 = 1291 against 1369 available

   so there is 78px of slack at the narrowest width where the full bar shows. The
   padding is left alone: it is fixed, and shrinking it would change the tap
   target rather than the type size. */
.nav-list a {
  display: block;
  font-family: var(--font-ui);
  font-size: clamp(0.72rem, 0.62vw + 0.28rem, 0.84rem);
  font-weight: 500;
  color: var(--charcoal-2);
  padding: 7px 10px;
  letter-spacing: 0;
  border-radius: 999px;
  white-space: nowrap;
  transition: color 0.3s ease, background 0.3s ease;
}
/* Hover and keyboard focus now get the SAME treatment, which they did not before.

   Hover used to paint a --stone pill with charcoal text, and focus had no rule at
   all, so a keyboard user tabbing the nav saw only the browser default outline
   while a mouse user saw a filled pill. Two different affordances for one control,
   and no real focus state on the primary navigation of the site.

   The pill is now near-white at 90% rather than --stone, so it reads as the same
   frosted material as the scrolled header bar (rgba(251,247,240,0.72)) instead of
   as a beige block. The 10% transparency is what keeps it from looking like a
   solid sticker: the page behind still tints it very slightly, which is the
   difference between glass and paper.

   The text goes black, NOT white. This is the part worth being explicit about: the
   resting ink is dark on light pages but rgba(255,255,255,0.88) once a banner sits
   behind the bar, so white-on-white was measured at 1.06:1 against the ivory page
   - unreadable. A light fill and light ink cannot both happen, and the fill is what
   makes the hover visible, so the ink yields. Because the pill now carries its own
   light ground, this single rule is correct over the banners and the plain pages
   alike and needs no per-page override.

   --black rather than --charcoal: on a pill the element fills itself, the only job
   the ink has is contrast, and 21:1 reads as a deliberate signal where the warm
   near-black reads as slightly grey.

   The focus ring is the accent rather than white, for the same reason: a white
   ring around a white pill would be invisible. focus-visible rather than :focus,
   so a mouse click leaves no ring behind. */
.nav-list a:hover,
.nav-list a:focus-visible {
  color: var(--black);
  background: rgba(255, 255, 255, 0.9);
}
.nav-list a:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.nav-list a.active { color: #fff; background: var(--gold); font-weight: 600;}

/* Dropdown */
.has-dropdown { position: relative;}
.has-dropdown > a { display: flex; align-items: center; gap: 3px;}
.has-dropdown > a .ph { font-size: 0.6rem; color: var(--charcoal); font-weight: 700; transition: transform 0.25s ease;}
.has-dropdown:hover > a .ph,
.has-dropdown.open > a .ph { opacity: 1; transform: rotate(180deg);}
.dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  transform: translateY(8px);
  min-width: 220px;
  background: var(--gold);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius-md);
  box-shadow: 0 16px 48px -12px rgba(14, 38, 34, 0.45);
  padding: 8px 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s;
  z-index: 130;
}
.has-dropdown:hover .dropdown,
.has-dropdown:focus-within .dropdown {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.dropdown li { list-style: none;}
.dropdown li a {
  display: block;
  padding: 10px 20px;
  font-size: 0.82rem;
  font-weight: 500;
  color: #fff;
  border-radius: 0;
  white-space: nowrap;
  transition: background 0.2s ease, color 0.2s ease;
}
.dropdown li a:hover { background: rgba(255, 255, 255, 0.14); color: #fff;}

/* Header CTA */
.header-right {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 8px;
}
/* 0.66rem. This was briefly taken to 0.6rem while both numbers were in the bar,
   to close the gap between them and the 326.4px track that the 1fr auto 1fr grid
   allows at the 1440px container cap. Measured at a 1600px viewport, the pair
   comes to 377px at 0.66rem and only about 360px at 0.6rem, so the shrink never
   did solve it: the group was still over the track either way.

   Only one number is in the bar now, and that is what solved it. One number plus
   the CTA measures 280.9px against the 326.4px track, with 45.5px spare, so the
   smaller size was buying nothing. Reverting it puts back about 1px of height on
   the smallest text in the header, which is worth more than the width it was
   never delivering. Below 1500px the number is hidden outright, so this size
   only ever applies to wide viewports. */
.header-phone {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.66rem;
  font-weight: 600;
  color: var(--charcoal);
  white-space: nowrap;
  transition: color 0.25s ease;
}
.header-phone i { font-size: 0.8rem;}
.header-phone:hover { color: var(--gold);}
.header-phone-sep { display: none;}
.header-cta { justify-self: end;}
a.header-cta {
  background: var(--gold);
  color: #fff;
  border: none;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.7rem;
  padding: 10px 14px;
}
a.header-cta:hover { color: #fff;}
.nav-mobile-cta .btn {
  background: var(--gold);
  color: #fff;
  border: none;
}

/* Menu toggle */
.menu-toggle {
  display: none;
  position: relative;
  width: 44px; height: 44px;
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  cursor: pointer;
  z-index: 150;
}
.menu-toggle span {
  position: absolute;
  left: 14px; right: 14px;
  height: 2px;
  background: var(--charcoal);
  border-radius: 2px;
  transition: transform 0.3s ease, opacity 0.3s ease;
}
.menu-toggle span:nth-child(1) { top: 14px;}
.menu-toggle span:nth-child(2) { top: 24px;}

/* Mobile CTA bar */
.mobile-cta {
  display: none;
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 90;
  background: var(--charcoal);
  padding: 0;
  box-shadow: 0 -4px 20px rgba(0,0,0,0.15);
}
.mobile-cta .btn { width: 100%; justify-content: center; background: var(--gold); color: var(--white); border: none; padding: 16px 24px; font-size: 1rem; font-weight: 700; border-radius: 0;}
/* Was #b81a00, a dark red, on a gold button. Same fault as the certificate
   arrows and worth clearing for the same reason: on touch the hover sticks
   after a tap. .mobile-cta has no markup on any page, so this is currently
   inert, but leaving a red hover behind it in a live component file is how it
   came back last time. */
.mobile-cta .btn:hover { background: var(--charcoal);}

/* ---------- Hero ----------
   No min-height here on purpose. A text-only hero is short (legal 229px, 404
   322px) and forcing it to 100dvh, then flex-centring the content, left a
   657px void on the legal page and 564px on 404: 245px of nothing above the
   title and 245px below it. The full-bleed image heroes still want a full
   viewport, and .hero--full below declares min-height: 100dvh for itself, so
   nothing loses it. */
.hero {
  position: relative;
  overflow: hidden;
  padding: clamp(76px, 10vh, 120px) 0 clamp(32px, 5vh, 60px);
  display: flex;
  align-items: center;
}
.hero-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 100px);
  align-items: center;
}
.hero-grid > * { min-width: 0;}
.hero-content { max-width: 580px;}
.hero-headline {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(3rem, 6vw, 5.2rem);
  line-height: 0.95;
  letter-spacing: -0.035em;
  /* Black, like every other heading. The hero variants that sit on a dark ground
     still override this at higher specificity: .hero--full goes --white, and the
     four dark-hero pages and the six photo banners keep their light ink, which is
     what those grounds need.

     #hero.hero--tint no longer overrides it. It used to, to a warm ivory, because
     the home copy sat low over dark grass. That copy now sits at 32% to 56% down,
     the bright middle of the photograph, where light ink measures 1.50:1, so it is
     black like the rest of the site and measures 11.90:1 there. The rule and the
     full band table are in page-overrides.css. */
  color: var(--black);
  margin-bottom: 0.6em;
}
.hero-headline-accent { color: inherit; font-style: normal;}
.hero-desc {
  font-size: clamp(1rem, 1.3vw, 1.15rem);
  color: var(--charcoal-2);
  line-height: 1.75;
  max-width: 480px;
  margin-bottom: 2em;
}
.hero-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 2.5em;
}
.hero-actions.center { justify-content: center;}
.hero-trust {
  display: flex;
  align-items: center;
  gap: 24px;
}
.trust-item { display: flex; align-items: center; gap: 10px;}
.trust-item .ph { font-size: 1.2rem; color: var(--gold);}
.trust-item strong { font-size: 0.78rem; color: var(--charcoal); display: block;}
.trust-item span { font-size: 0.68rem; color: var(--muted); display: block;}

/* Hero visual */
.hero-visual { position: relative; max-width: 480px;}
.hero-glow {
  position: absolute;
  inset: -20%;
  border-radius: 50%;
  background: radial-gradient(circle, var(--gold-soft) 0%, transparent 70%);
  opacity: 0.4;
  pointer-events: none;
}
.hero-badge {
  position: absolute;
  top: 20px; right: 30px;
  z-index: 2;
  text-align: center;
}
.hero-badge-text {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.75rem;
  color: var(--charcoal);
  line-height: 1.4;
  letter-spacing: 0.02em;
}
.hero-badge-underline { display: block; margin: 4px auto 0;}
.hero-figure {
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 3/4;
  box-shadow: var(--shadow-soft);
  background: var(--stone);
}
.hero-figure img { width: 100%; height: 100%; object-fit: cover; transform: scale(1.08);}
.hero-figure-secondary {
  position: absolute;
  bottom: 50px;
  left: -30px;
  width: 140px;
  border-radius: var(--radius-md);
  overflow: hidden;
  aspect-ratio: 1;
  box-shadow: var(--shadow-md);
  border: 3px solid var(--white);
  z-index: 3;
  opacity: 0;
  transform: translateY(10px);
  animation: fadeInUp 0.6s ease 0.5s forwards;
}
.hero-figure-secondary img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}
.hero-figure-secondary:hover {
  transform: scale(1.05);
  box-shadow: var(--shadow-lg);
}
@keyframes fadeInUp {
  to { opacity: 1; transform: translateY(0);}
}

/* Hero stat card */
.hero-stat-card {
  position: absolute;
  right: 30px; bottom: -20px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 20px 24px;
  box-shadow: var(--shadow-card);
  min-width: 200px;
  text-align: center;
  z-index: 2;
}
.stat-top { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 8px;}
.stat-icon {
  width: 38px; height: 38px;
  border-radius: 12px;
  background: var(--gold-soft);
  color: var(--gold);
  display: grid; place-items: center;
}
.stat-icon .ph { font-size: 1.1rem;}
.stat-number {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.8rem;
  color: var(--charcoal);
  line-height: 1;
}
.stat-label {
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}
.stat-stars { display: flex; justify-content: center; gap: 2px; margin-bottom: 8px;}
.stat-stars .ph-fill { font-size: 0.8rem; color: var(--gold);}
.stat-tags {
  font-size: 0.55rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  padding-top: 8px;
  border-top: 1px solid var(--line);
}

/* Hero decorations */
.hero-deco {
  position: absolute;
  border-radius: 50%;
  z-index: 0;
  pointer-events: none;
}
.hero-deco-1 {
  width: 300px; height: 300px;
  top: -60px; right: 10%;
  background: radial-gradient(circle, rgba(245, 178, 27, 0.08) 0%, transparent 70%);
}
.hero-deco-2 {
  width: 200px; height: 200px;
  bottom: 10%; left: -40px;
  background: radial-gradient(circle, var(--stone) 0%, transparent 70%);
}

/* Hero blobs subpage backgrounds */
.hero-blob {
  position: absolute;
  border-radius: 50%;
  z-index: 0;
  pointer-events: none;
}
.hero-blob-1 {
  width: 400px; height: 400px;
  top: -80px; right: -60px;
  background: radial-gradient(circle, rgba(245, 178, 27, 0.06) 0%, transparent 70%);
}
.hero-blob-2 {
  width: 300px; height: 300px;
  bottom: -40px; left: -60px;
  background: radial-gradient(circle, var(--stone) 0%, transparent 70%);
}

/* ---------- Authority bar ---------- */
.authority { background: var(--charcoal); color: var(--ivory); padding: clamp(32px, 4vw, 48px) 0;}
.authority h1, .authority h2, .authority h3, .authority h4, .authority h5, .authority h6,
.authority .eyebrow, .authority .lead, .authority p, .authority b, .authority span,
.authority strong { color: var(--ivory);}
.authority-inner {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  text-align: center;
}
.authority-inner > * { min-width: 0;}
.auth-item { display: flex; flex-direction: column; align-items: center; gap: 4px;}
.auth-item b {
  font-family: var(--font-display);
  font-size: 1.8rem;
  font-weight: 700;
  color: var(--ivory);
}
.auth-item span {
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(251,247,240,0.85);
}

/* ---------- Sections ---------- */
/* 48/48 gives 96px between adjacent sections, down from the previous 64/64
   which put 128px at every boundary. */
.section {
  padding: clamp(32px, 4.2vw, 48px) 0;
  /* Every section wears the same light yellow. Four neutrals were in play across
     the site (ivory #FBF8F3, cream #FDFBF7, gold-soft #E4EFEB, white #FFFFFF) and
     read as drift rather than intent, so the band is now one value everywhere,
     and one light yellow rather than one white.

     --butter #FFFAE0 was searched for, not chosen by eye: it is the most
     saturated light yellow in the site's warm family where every ink that sits on
     a light ground still clears AA. --muted is the binding constraint at 4.62:1,
     which is exactly why the earlier --stone #EDE6DA attempt failed. Stone is only
     8% saturated but drops to 3.91 because it is darker, value 93% against this
     ground's 100%. Saturation had to be traded for lightness to buy that ink its
     margin back.

     Start and end mark. Once every band is the same value there is nothing left
     to tell one section from the next, so each one is bracketed by a hairline:
     the top rule is its start mark, the bottom rule its end mark. That bracket
     lives in page-overrides.css and needs no token of its own here: --line reads
     1.33:1 on #FFFFF5, the same weight it has on white.

     Declared on .section rather than on body, because body also sits behind the
     header and the full-bleed photo strips, and the footer keeps its charcoal. */
  background: var(--butter);
}
.section.alt { background: var(--butter);}
.section-head { margin-bottom: clamp(16px, 2.5vw, 32px);}
.section-head.center { text-align: center;}
.section-head.center .lead { margin-inline: auto;}

/* ---------- Global heading consistency ---------- */
h1, h2, h3, h4, h5, h6 { margin-top: 0;}
.section h2 { margin-bottom: 0.4em;}
.section h3 { margin-bottom: 0.3em;}
.section .lead { margin-top: 0.8em;}
.section .eyebrow { margin-bottom: 8px;}
.em-serif { font-style: normal; color: inherit;}

/* ---------- Meet Your Coach ---------- */
.meet-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 80px);
  align-items: center;
}
.meet-grid > * { min-width: 0;}
.meet-media {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.meet-media > * { min-width: 0;}
.exp-stamp {
  position: absolute;
  top: -16px; right: 0;
  width: 100px; height: 100px;
  border-radius: 50%;
  background: var(--gold);
  color: var(--white);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 2;
  box-shadow: var(--shadow-card);
}
.exp-stamp b {
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 700;
  line-height: 1;
}
.exp-stamp span {
  font-size: 0.65rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: 2px;
}
.photo-a {
  border-radius: var(--radius-md);
  overflow: hidden;
  aspect-ratio: 3/4;
  margin-top: 32px;
}
.photo-b {
  border-radius: var(--radius-md);
  overflow: hidden;
  aspect-ratio: 4/5;
}
.photo-a img, .photo-b img { width: 100%; height: 100%; object-fit: cover; display: block;}

/* GSAP initial states */
.gs-scale { opacity: 0; transform: scale(1.08);}
.gs-up { opacity: 0; transform: translateY(40px);}
.gs-fade { opacity: 0;}

/* ---------- Service cards ---------- */
.service-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
  display: flex;
  flex-direction: column;
}
.service-card:hover { border-color: var(--gold); box-shadow: var(--shadow-card);}
.service-card .media {
  position: relative;
  min-height: 180px;
  background: var(--stone);
  overflow: hidden;
}
.service-card .media:has(img) { aspect-ratio: 16/9;}
.service-card .media img { width: 100%; height: 100%; object-fit: cover;}
.service-card .body { padding: clamp(24px, 3vw, 40px); display: flex; flex-direction: column; gap: 8px; flex: 1;}
.service-card .body h3 { font-size: 1.3rem; margin-bottom: 0.4em;}
.service-card .body > p { color: var(--muted);}
.service-card .foot { margin-top: 1.5em;}

/* Text-only service cards (no image/media area) */
.service-card--text { background: var(--ivory); border-color: var(--line);}
.service-card--text:hover { border-color: var(--gold); background: var(--white);}
.service-card--text .body { padding: clamp(20px, 3vw, 32px);}
.service-card--text .num {
  position: static;
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  color: var(--gold);
  background: none;
  padding: 0;
  margin-bottom: 8px;
}
.service-card--text h3 { font-size: 1.15rem; color: var(--black);}
.service-card--text p { font-size: 0.9rem; color: var(--muted); line-height: 1.6;}

.num {
  position: absolute;
  top: 16px; left: 20px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  color: var(--charcoal);
  background: var(--white);
  border-radius: 999px;
  padding: 4px 12px;
}
.card-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px; height: 48px;
  border-radius: 50%;
  background: var(--charcoal);
  color: var(--ivory);
  font-size: 1rem;
  font-weight: 600;
  transition: background 0.3s ease, transform 0.3s ease;
}
.card-arrow:hover { background: var(--gold); transform: translateX(4px);}
.meta-tag { font-size: 0.72rem; color: var(--muted);}

/* ---------- Services grid ---------- */
.services-grid {
  display: grid;
  gap: 24px;
  grid-template-columns: repeat(3, 1fr);
}
.services-grid > * { min-width: 0;}

/* ---------- Editorial grid ---------- */
.editorial-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: auto auto;
  gap: 16px;
}
.editorial-grid > * { min-width: 0;}
.edi-img { border-radius: var(--radius-md); overflow: hidden; position: relative;}
.edi-img img { width: 100%; height: 100%; object-fit: cover; display: block;}
.edi-1 { grid-column: 1 / 2; grid-row: 1 / 3; aspect-ratio: auto; min-height: 300px;}
.edi-2 { grid-column: 2 / 3; grid-row: 1 / 2; aspect-ratio: 16/10;}
.edi-3 { grid-column: 3 / 4; grid-row: 1 / 2; aspect-ratio: 16/10;}
.edi-4 { grid-column: 2 / 4; grid-row: 2 / 3; aspect-ratio: 21/9;}
.edi-float { position: relative;}

/* ---------- Transformation / Journey ---------- */
.trans-form { background: var(--charcoal); color: var(--ivory); overflow: hidden;}
.trans-form h1, .trans-form h2, .trans-form h3, .trans-form h4, .trans-form h5, .trans-form h6,
.trans-form .eyebrow, .trans-form .lead, .trans-form p, .trans-form b, .trans-form span,
.trans-form strong, .trans-form li { color: var(--ivory);}
.trans-scroll {
  display: grid;
  grid-auto-columns: min(50vw, 380px);
  grid-auto-flow: column;
  gap: 20px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding: 40px var(--gutter);
  scrollbar-width: none;
  justify-content: center;
}
.trans-scroll::-webkit-scrollbar { display: none;}
.stage {
  background: var(--charcoal-2);
  border: 1px solid rgba(251,247,240,0.15);
  border-radius: var(--radius-lg);
  padding: clamp(28px, 3vw, 40px);
  scroll-snap-align: center;
  min-width: 300px;
  flex-shrink: 0;
  color: var(--ivory);
  text-align: left;
  transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease, background 0.35s ease;
}
.stage:hover {
  transform: translateY(-6px);
  border-color: var(--gold);
  box-shadow: 0 12px 32px -8px rgba(34, 84, 76,0.2);
  background: #3f3830;
}
.stage h1, .stage h2, .stage h3, .stage h4, .stage h5, .stage h6,
.stage p, .stage b, .stage span, .stage strong, .stage li { color: var(--ivory);}
.st-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 2.8rem;
  color: var(--gold);
  opacity: 0.3;
  line-height: 1;
  margin-bottom: 0.8em;
}
.stage h3 { font-size: clamp(1.3rem, 2.5vw, 1.6rem); color: var(--ivory); margin-bottom: 0.8em;}
.stage ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 0.5em; margin-bottom: 1.2em;}
.stage li { font-size: 0.92rem; color: rgba(251,247,240,0.85); padding-left: 1.2em; position: relative;}
.stage li::before { content: "\2013"; position: absolute; left: 0; color: var(--gold);}
.st-arrow { font-size: 1.2rem; color: var(--gold);}

/* ---------- Program panel ---------- */
.program-panel {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.program-panel > * { min-width: 0;}
.program-media { position: relative; min-height: 400px; overflow: hidden; background: var(--stone);}
.program-media img { width: 100%; height: 100%; object-fit: cover;}
.program-body {
  padding: clamp(32px, 4vw, 48px);
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.program-meta { display: flex; flex-wrap: wrap; gap: 8px;}
.chip {
  display: inline-flex;
  padding: 6px 14px;
  background: var(--stone);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--charcoal);
  white-space: nowrap;
}
/* One column, not two.

   .spec is nested inside .program-body, which is the 1.2fr half of a
   .program-panel, which is itself capped by the page container. Measured on
   programs.html that gives .spec a maximum width of 492px at 1440px and, in
   fact, at 2560px too: it does not grow at all past a certain viewport. Two
   columns therefore never had room for more than 209px each, which is the
   narrowest thing on the page.

   One column is also the correct arrangement, not just the roomier one. Each
   child is a .kv, and .kv is a flex column with the label above the value, so
   the second column was never a peer of the first - it was cutting a three-item
   list into two pairs and an orphan. Stacked, it reads as the definition list it
   is. */
.spec { display: grid; grid-template-columns: 1fr; gap: 12px; margin: 8px 0 16px;}
.program-body .btn { align-self: flex-start;}
.kv { display: flex; flex-direction: column; gap: 2px;}
.kv dt { font-size: 0.72rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);}
.kv dd { font-size: 0.92rem; font-weight: 500; color: var(--charcoal); margin: 0;}

/* ---------- Why Work With Me ---------- */
.why-layout {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: clamp(40px, 6vw, 80px);
  align-items: start;
}
.why-layout > * { min-width: 0;}
.why-sticky { position: sticky; top: calc(var(--header-h) + 40px);}
.why-list { display: grid; gap: 16px;}
.why-list.cols-2 { grid-template-columns: 1fr 1fr;}
.why-list > * { min-width: 0;}
.why-item {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 22px 24px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.why-item:hover { border-color: var(--gold); box-shadow: var(--shadow-sm);}
.w-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.4rem;
  color: var(--gold);
  opacity: 0.4;
  flex-shrink: 0;
  line-height: 1;
  min-width: 32px;
}
.why-item h3 { font-size: 1.2rem; margin-bottom: 0.3em;}
.why-item p { font-size: 0.92rem; color: var(--muted); line-height: 1.6; margin: 0;}

/* ---------- Story / Timeline ---------- */
.story-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 80px);
  align-items: center;
}
.story-grid > * { min-width: 0;}
.story-media {
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 3/4;
  background: var(--stone);
}
.story-media img { width: 100%; height: 100%; object-fit: cover;}
.timeline {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 2em 0;
  border-left: 2px solid var(--line);
  padding-left: 32px;
  position: relative;
}
.tl-item {
  display: grid;
  grid-template-columns: 70px 1fr;
  gap: 16px;
  padding: 18px 0;
  position: relative;
  align-items: start;
  transition: transform 0.3s ease;
}
.tl-item > * { min-width: 0;}
.tl-item:hover {
  transform: translateX(6px);
}
.tl-item::before {
  content: "";
  position: absolute;
  left: -39px; top: 22px;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--gold);
  border: 3px solid var(--ivory);
  z-index: 1;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.tl-item:hover::before {
  transform: scale(1.3);
  box-shadow: 0 0 0 4px rgba(34, 84, 76,0.15);
}
.tl-year {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.3rem;
  color: var(--gold);
  line-height: 1;
  padding-top: 2px;
}
.tl-item b { display: block; font-size: 0.95rem; color: var(--charcoal); margin-bottom: 4px; line-height: 1.3;}
.tl-item span { display: block; font-size: 0.85rem; color: var(--muted); line-height: 1.5;}

/* ---------- Testimonials ---------- */
.testi-wrap { overflow: hidden;}
.row-meta {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: clamp(24px, 4vw, 40px);
}
.head-inline { margin-bottom: 0;}
.testi-nav { display: flex; gap: 8px; flex-shrink: 0;}
.testi-prev, .testi-next {
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--white);
  cursor: pointer;
  display: grid; place-items: center;
  font-size: 1.1rem;
  color: var(--charcoal);
  transition: background 0.2s, border-color 0.2s;
  flex-shrink: 0;
}
.testi-prev:hover, .testi-next:hover { background: var(--charcoal); border-color: var(--charcoal); color: var(--ivory);}
.testi-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.testi-grid > * { min-width: 0;}
.testi-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(20px, 2.5vw, 28px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.testi-card:hover { border-color: var(--gold); box-shadow: var(--shadow-card);}
.testi-card .stars { display: flex; gap: 2px; color: var(--gold); font-size: 0.9rem;}
.testi-card .testi-text { font-size: 0.92rem; line-height: 1.7; color: var(--charcoal-2); margin: 0; font-style: normal;}
.testi-card .testi-author { display: flex; flex-direction: column; gap: 2px; margin-top: auto; padding-top: 12px; border-top: 1px solid var(--line);}
.testi-card .testi-author strong { font-size: 0.85rem; color: var(--charcoal);}
.testi-card .testi-author span { font-size: 0.78rem; color: var(--muted);}
.testi-inline { padding: 1.5em 2em;}
.testi-track {
  display: flex;
  gap: 20px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding-bottom: 8px;
  scroll-padding: 0 var(--gutter);
}
.testi-track::-webkit-scrollbar { display: none;}
.testi-track .testi-card {
  flex: 0 0 min(380px, 72vw);
  background: rgba(255,255,255,0.85);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(231,222,206,0.6);
  border-radius: var(--radius-lg);
  padding: clamp(24px, 3vw, 36px);
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
}
.testi-card blockquote {
  font-size: clamp(1.05rem, 1.8vw, 1.2rem);
  line-height: 1.65;
  color: var(--charcoal);
  margin: 0;
  font-style: normal;
  flex: 1;
}
.quote-mark {
  font-family: Georgia, "Times New Roman", serif;
  font-size: 5rem;
  line-height: 1;
  color: var(--gold);
  opacity: 0.25;
  margin-bottom: -12px;
  user-select: none;
}
.stars { color: #F5A623; font-size: 0.85rem; letter-spacing: 2px; margin-bottom: 4px;}
.testi-meta {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid rgba(231,222,206,0.4);
}
.testi-avatar {
  width: 48px; height: 48px;
  min-width: 48px;
  border-radius: 50%;
  background: var(--charcoal);
  color: var(--ivory);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1;
}
.testi-meta div { display: flex; flex-direction: column;}
.testi-meta b { font-family: var(--font-display); font-size: 0.92rem; font-weight: 700; color: var(--charcoal);}
.testi-meta span { font-size: 0.78rem; color: var(--muted);}

/* ---------- Mini cards / Blog cards ---------- */
.mini-cards {
  display: grid;
  gap: 24px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
}
.mini-cards > * { min-width: 0;}
.mini-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
  display: flex;
  flex-direction: column;
}
.mini-card:hover { border-color: var(--gold); box-shadow: var(--shadow-card);}
.mini-card .media { aspect-ratio: 16/10; overflow: hidden; background: var(--stone);}
.mini-card .media img { width: 100%; height: 100%; object-fit: cover; display: block;}
.mini-card .body { padding: 22px; display: flex; flex-direction: column; gap: 8px; flex: 1;}
.mini-card .body h3 { font-size: 1.2rem; line-height: 1.2; color: var(--black);}
.mini-card .body p { font-size: 0.9rem; color: var(--muted); line-height: 1.6;}

/* ---------- Lead panel (Free Guide) ---------- */
.lead-panel {
  display: flex;
  align-items: center;
  gap: clamp(32px, 5vw, 64px);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(36px, 5vw, 56px);
  box-shadow: var(--shadow-card);
}
.lead-panel .media { max-width: 280px; flex-shrink: 0;}

/* The copy column starts on the cover's top edge.
   .lead-panel is align-items: center, so the copy column, at 190px against a
   373px cover, was floating down against the middle of the image and beginning
   92px below its top. It read as one panel, but the two halves did not start
   together, which is the first thing the eye checks on a two-column card.

   align-self: flex-start on the column that is not .media, rather than
   align-items: flex-start on the panel. The two are not equivalent here: on
   blog.html this panel has no .media at all and its tall column is the form, so
   a panel-level rule would move the form up on one page and change nothing on
   the other. Scoping to the copy column moves the same block on both, and on
   blog the form stays the taller column and stays put.

   Selector is .lead-panel > div:not(.media), which reaches the copy column on
   both pages and cannot reach a <form> or the .media itself. */
.lead-panel > div:not(.media) { align-self: flex-start; }

/* "Free Guide" eyebrow inside the lead panel, raised from the shared 0.72rem.
   Two reasons. It is a label on a card, not a section kicker, and at 11.52px it
   was the smallest text on a panel whose other two lines are a 36px heading and
   a 19px lead. It is also the only thing on the panel telling a visitor what the
   panel is before they read the heading, so it is the first thing that should
   be readable, not the last.

   0.875rem gives 14px, which is 1.22x the shared size and just over the 13.12px
   Download button below it, so the label no longer reads as smaller than the
   action it labels. Tracking drops from 0.2em to 0.14em because at 14px the
   original tracking opens the gap between the two words enough to read as two
   separate words rather than one label.

   Scoped to .lead-panel, so every other .eyebrow on the site keeps its shared
   0.72rem and 0.2em. Both panels that carry this label, blog.html and
   resources.html, get it. */
.lead-panel .eyebrow {
  font-size: 0.875rem;
  letter-spacing: 0.14em;
  /* Left, on the client's request.
     layout.css:80 sets .section .eyebrow to text-align: center outright, and both
     of these panels sit inside a .section, so the label was centred even though
     the panel around it is not. It sat centred above a centred lead above a
     left-aligned Download button, which was the only thing on the panel already
     reading left.

     Rides on the rule above rather than as a separate one, so the size and the
     alignment of this label stay in one place. */
  text-align: left;
}

/* The lead inside the panel, left for the same reason as the eyebrow above.
   layout.css:79 sets .section .lead to text-align: center outright, so the panel
   read as a centred label over a centred paragraph over a left-aligned button.
   The panel is not a centred block: .lead-panel is a flex row with the guide
   cover at a fixed 280px on the left and this column beside it, so there is no
   centre to align to in the first place.

   The eyebrow and the lead are now left together and the Download button below
   them was already left, so the whole text column reads from one edge. On
   resources.html the lead is also the line the 280px cover sits beside, so
   centring it was putting the paragraph away from the image it describes. */
.lead-panel .lead { text-align: left; }
.lead-form { display: flex; flex-direction: column; gap: 16px; flex: 1; max-width: 400px;}
.field { display: flex; flex-direction: column; gap: 6px;}
.field label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.field input, .field textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--ivory);
  padding: 14px 16px;
  font-family: var(--font-ui);
  font-size: 0.92rem;
  color: var(--charcoal);
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
  min-height: 48px;
}
.field input:focus, .field textarea:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px var(--gold-soft);
}
.form-success { display: none; margin: 0; color: var(--gold); font-weight: 600; font-size: 0.92rem;}
.error { min-height: 1em; color: #b42318; font-size: 0.78rem; margin-top: 4px;}

/* ---------- Final CTA ---------- */
.final-cta { padding: clamp(40px, 6vw, 72px) 0; background: var(--charcoal); color: var(--ivory); text-align: center;}
.final-cta.cta-compact { padding: clamp(24px, 4vw, 48px) 0;}
.final-cta .eyebrow { color: var(--gold); margin-bottom: 8px;}
.final-cta h2 { margin-bottom: 0.3em;}
.final-cta .lead { color: rgba(251,247,240,0.85); margin-inline: auto; margin-bottom: 0;}
/* The accent span is gone from this heading. It was --gold, a dark teal, on a
   charcoal band: 1.43:1, which is why the footer and the stage cards were fixed
   earlier and this one was missed. It is the same 1.43:1 failure with an accent
   word dropped into the middle of a heading, and it is also the only place left
   where one heading carried two inks. Inheriting puts the span on the same ivory
   as the rest of the line. */
.final-cta .em-serif { color: inherit;}
.final-cta .display, .final-cta h2 { color: var(--ivory);}
.cta-actions { display: flex; align-items: center; justify-content: center; gap: 14px; margin-top: 1em;}

/* ---------- Footer ---------- */
.site-footer {
  background: var(--charcoal);
  color: var(--ivory);
  padding-top: 32px;
}
.site-footer h1, .site-footer h2, .site-footer h3, .site-footer h4, .site-footer h5, .site-footer h6,
.site-footer p, .site-footer b, .site-footer span, .site-footer strong, .site-footer li { color: var(--ivory);}
.foot-main {
  display: grid;
  grid-template-columns: 1.4fr 0.8fr 0.8fr 0.8fr;
  gap: 24px 32px;
  padding-bottom: 28px;
  text-align: left;
}
.foot-brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding-left: 20px;
}
/* An assigned Customizer logo sits above the written lockup instead of
   replacing it, so the footer always shows the name and its tagline. */
.foot-brand .foot-logo-image { display: block; line-height: 0; margin-bottom: 12px;}
.foot-brand .foot-logo-image img { display: block; max-height: 56px; width: auto; max-width: 100%;}
.foot-brand .logo { min-width: 0; max-width: 100%;}
.foot-nav, .foot-legal, .foot-contact {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.foot-brand .logo-name {
  font-family: 'Cormorant Garamond', var(--font-display);
  font-weight: 600;
  font-size: 1.45rem;
  color: var(--ivory);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* .nav-mobile-head joins this rule because it has the identical failure and the
   identical fix. Its own rule already sets .logo-name and .logo-tagline to white,
   but .logo-first carries a colour of its own from layout.css:84, so it was
   inheriting nothing: "Saeed" rendered --gold #22544C on the --gold #22544C nav
   panel behind it, at 1.00:1. Not low contrast, literally nothing. White here is
   the same ink the footer uses for the same wordmark on a dark ground. */
:is(.foot-brand, .nav-mobile-head) .logo-first { color: #fff;}
.foot-brand .logo-tagline {
  font-family: var(--font-ui);
  font-size: 0.68rem;
  color: rgba(251,247,240,0.6);
  letter-spacing: 0.06em;
  margin-top: 5px;
}
.foot-nav h3, .foot-contact h3, .foot-legal h3 {
  font-family: var(--font-display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
  margin-bottom: 12px;
}
.foot-nav ul { display: flex; flex-direction: column; gap: 8px; margin: 0;}
.foot-nav ul ul { margin-left: 12px; gap: 4px;}
.foot-nav ul ul li a { font-size: 0.85rem; opacity: 0.8;}
.foot-nav a { font-size: 0.92rem; color: var(--ivory); transition: color 0.3s ease;}
/* The three contact links are the only tappable things in the footer column, and
   they were 18-25px tall each. The footer nav beside them has never been given
   the same treatment and is left alone, because this is about the phone number
   and the address, which are the two a visitor actually taps on a phone.

   This could not be done from CSS until now: every one of the 48 anchors
   carried style="display:block; margin-bottom:6px;" inline, and an inline
   declaration outranks any stylesheet, so no amount of rule here would have
   moved them. The inline styles are gone from all 24 pages that have a footer
   and the size is set in one place.

   flex with align-items: center keeps the icon on the same optical line it was
   on as an inline-block, and the negative margin keeps the block rhythm the
   8px margin-bottom was already giving. */
.foot-email {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.92rem;
  color: var(--ivory);
  margin-bottom: 4px;
  word-break: break-all;
}
.foot-phone {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.92rem;
  color: var(--ivory);
  margin-bottom: 4px;
}
.foot-phone i { margin-right: 7px;}
/* Footer interaction. Three gaps closed here, and one dark-ground correction.

   .foot-nav a, .foot-legal a and .foot-phone each already carried
   transition: color 0.3s ease with nothing ever transitioning, because none of
   them had a :hover at all. Across all 24 pages that is roughly forty links
   where the pointer gave no signal whatsoever. They move to --gold-soft, which
   is 14.5:1 on --charcoal, and the phone icon takes a 2px nudge so the row reads
   as one control rather than as digits that happen to change shade.

   The rings here are ivory, and that is not an inconsistency with the gold floor
   in design-tokens.css. Because the ring is drawn with outline-offset it sits on
   the ground AROUND the control, and down here that ground is --charcoal #201C16,
   where --gold measures 1.43:1 and is invisible. Gold is the right default
   precisely because most grounds on this site are light; the footer is the one
   dark band and it has to say so. Same reasoning as the dark-hero header block
   in page-overrides.css and as .cinematic-btn already does on the home hero.

   .socials is included because it lives inside .foot-contact, and its gold hover
   fill is correct there; only the ring needed to know what it is standing on.

   .foot-email is listed with the phones but gets no icon nudge, because unlike
   the two phone rows it carries no <i>. The shared colour rule is right for it
   and the transform is not. */
.foot-nav a:hover, .foot-nav a:focus-visible,
.foot-legal a:hover, .foot-legal a:focus-visible,
.foot-phone:hover, .foot-phone:focus-visible,
.foot-email:hover, .foot-email:focus-visible {
  color: var(--gold-soft);
}
.foot-nav a:focus-visible,
.foot-legal a:focus-visible,
.foot-phone:focus-visible,
.foot-email:focus-visible,
.site-footer .socials a:focus-visible {
  outline-color: var(--ivory);
}
/* The footer wordmark was the one link down here still drawing the gold floor.
   It is the first thing in the footer to take focus, and it sits on --charcoal
   like everything else around it, so gold was the 1.43:1 case again. Caught by
   tabbing the page rather than by reading the rules: the ring list above was
   written from the footer markup and the logo lives one level up, inside
   .foot-brand, which is why it was missed. */
.site-footer .logo:focus-visible {
  outline-color: var(--ivory);
}
.foot-phone, .foot-phone i { transition: color 0.3s ease, transform 0.3s ease;}
.foot-phone:hover i, .foot-phone:focus-visible i { transform: translateX(2px);}
.socials { display: flex; gap: 10px;}
.socials a {
  /* 44, not 40. Measured at 390px: the footer social icons were 40x40 while
     .contact-socials .socials a, the same icons on the contact page, were
     already 44x44 at page-overrides.css. The base was the odd one out, and these
     are small targets at the bottom of a long scroll. */
  width: 44px; height: 44px;
  border-radius: 10px;
  border: 1px solid rgba(251,247,240,0.3);
  display: grid; place-items: center;
  color: var(--ivory);
  transition: background 0.3s, border-color 0.3s, color 0.3s, transform 0.2s var(--ease);
}
.socials a:hover { background: var(--gold); border-color: var(--gold); color: var(--white);}
/* Press feedback, not hover feedback, and that is the whole point of it. On a
   phone there is no hover state to reach, so a tap on one of these gave nothing
   back at all. Placed next to the hover rather than in a shared :is() block
   because touch devices leave :hover stuck on the tapped element afterwards: at
   equal specificity and later in source, this wins the frame the finger is
   still down and the lift relaxes on release. */
.socials a:active { transform: scale(0.94);}
.socials a .ph { font-size: 1.2rem;}
.foot-legal ul { display: flex; flex-direction: column; gap: 8px; margin: 0;}
.foot-legal a { font-size: 0.85rem; color: var(--ivory); transition: color 0.3s ease;}
/* The footer CTA's top margin used to be an inline style on the anchor in all 24
   pages, which outranked every stylesheet rule, so it could not be adjusted per
   breakpoint. It lives here now instead: 28px as it always was, and the phone
   step in breakpoints.css raises it to 40px. */
.foot-contact .btn { margin-top: 28px;}
.foot-bar {
  background: transparent;
  border-top: 1px solid rgba(251,247,240,0.15);
  padding: 14px 0;
}
.foot-bar .container { display: flex; justify-content: space-between; align-items: center;}
.foot-copy { font-size: 0.78rem; color: rgba(251,247,240,0.85);}
.foot-tagline { font-size: 0.72rem; color: rgba(251,247,240,0.8); letter-spacing: 0.06em;}

/* ---------- Lightbox ---------- */
.lightbox {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(0,0,0,0.9);
  place-items: center;
  flex-direction: column;
  gap: 20px;
  padding: 20px;
}
.lightbox.open { display: grid;}
.lightbox img { max-width: 90vw; max-height: 85vh; object-fit: contain; border-radius: var(--radius-sm);}
.lb-btn {
  position: absolute;
  background: rgba(255,255,255,0.15);
  border: none;
  color: white;
  border-radius: 50%;
  cursor: pointer;
  display: grid; place-items: center;
  transition: background 0.2s;
  font-size: 1.5rem;
}
.lb-btn:hover { background: rgba(255,255,255,0.3);}
.lb-close { top: 16px; right: 16px; width: 48px; height: 48px; font-size: 1.8rem;}
.lb-prev { left: 16px; top: 50%; transform: translateY(-50%); width: 48px; height: 48px;}
.lb-next { right: 16px; top: 50%; transform: translateY(-50%); width: 48px; height: 48px;}

/* ---------- Lightbox: drag to change image ----------
   The overlay, not just the <img>, is the drag surface, so a swipe that starts
   on the black surround still works. touch-action: none is what actually buys
   that on touch: with the default, the browser claims the gesture for panning
   and fires pointercancel before the drag can finish. It costs pinch-zoom over
   the overlay, which is not a feature here anyway (the image is object-fit:
   contain, there is no zoom to pinch into). user-drag stops the native image
   drag ghost appearing mid-swipe. */
.lightbox {
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-user-drag: none;
}
/* The drag changes which certificate is shown; it never moves this one. So no
   transform is ever applied and no grab cursor is offered, because both would
   promise a draggable picture that stays exactly where it is. The opacity
   hint matches the crossfade the swap actually animates. */
.lightbox img {
  cursor: default;
  will-change: opacity;
}
/* No hover-reveal of the arrows while a drag is in flight: they would appear at
   exactly the moment the user is part way through a swipe, competing with the
   change they are already asking for. */
.lightbox.dragging .lb-btn { opacity: 0; pointer-events: none;}

/* ---------- Hero Full-Width Background ---------- */
.hero--full {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  padding: clamp(100px, 14vh, 160px) 0 clamp(40px, 6vh, 80px);
  background-color: #22544C;
  background-size: cover;
  background-position: center top;
  background-repeat: no-repeat;
}
.hero-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  display: block;
}
/* No veil on this hero, and there is not one to remove.

   There was a rgb(4 9 14) gradient here while the copy sat low, added to lift the
   near-white headline over the bright middle of the frame. Lifting the copy into
   that same band made the veil look like the wrong tool, and it was: the band is
   bright, so the fix is dark ink on a bright ground rather than a dark wash over
   a dark ground.

   Measured against the bare image, --charcoal #201C16 at luminance 0.012 gives
   these contrasts at the median of each tenth of the frame:

     0-10%  5.41:1    30-40%  9.60:1    60-70%  4.48:1
     10-20% 6.78:1    40-50%  9.44:1    70-80%  3.20:1
     20-30% 8.21:1    50-60%  5.08:1    80-90%  1.61:1

   The copy block sits between 32% and 56%, so it reads between 5.1:1 and 9.6:1,
   which is better than the veiled version managed at 3.6:1 to 5.6:1, and it does
   it without touching the photograph. The bands below 70% go poor for dark ink,
   but nothing is set there: the CTA is an opaque white button.

   The site-wide warning about dark ink on a photograph still stands elsewhere -
   gold on a dark ground is the recurring failure in this codebase - and none of
   it applies here, because this ground is the bright end of the scale. */
.hero-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(0,0,0,0.65) 0%, rgba(0,0,0,0.35) 100%);
  z-index: 1;
}
/* Was --white, against a headline that is the warm ivory rgb(243,238,230). That
   is a 6-point difference between two near-whites sitting next to each other
   inside one line: not a contrast fault, but a two-tone headline. Inheriting
   puts the accent word on the same ink as the rest of the line. */
#hero.hero--tint .hero-headline-accent { color: inherit;}
#hero.hero--tint .hero-headline {
  font-size: clamp(1.75rem, 3.3vw, 3.1rem);
  white-space: nowrap;
}
#hero.hero--tint .hero-inner {
  max-width: min(1100px, 92%);
  margin: 0 auto;
  text-align: left;
}
#hero.hero--tint .hero-desc {
  color: rgba(255,255,255,0.92);
  max-width: min(640px, 92%);
  margin-left: 0;
  margin-right: 0;
  margin-bottom: clamp(12px, 1.6vw, 20px);
}
#hero.hero--tint .hero-actions { justify-content: flex-start;}
/* 768, not 767. Every other media query on the site splits at 768 and 769, and
   these two hero rules in page-overrides.css were the last holdouts on 767/768.
   At exactly 768px - the iPad portrait width - the old boundary applied this
   mobile rule AND the desktop one beside it at the same time. */
@media (max-width: 768px) {
  #hero.hero--tint .hero-headline { white-space: normal; font-size: clamp(1.9rem, 8vw, 2.6rem);}
}
.hero-inner {
  position: relative;
  z-index: 2;
  max-width: 680px;
  margin: 0 auto 0 5%;
}
.hero--full .hero-headline { color: var(--white); margin-bottom: 0.5em;}
/* Was --gold: a dark teal word inside a white headline on a photograph, the same
   1.43:1 the footer and stage cards had. The span now takes the headline's ink,
   so the line is one colour on every ground. */
.hero--full .hero-headline-accent { color: inherit;}
.hero--full .hero-desc { color: rgba(255,255,255,0.85); max-width: 540px;}
.hero--full .hero-eyebrow { color: rgba(255,255,255,0.7);}
.hero--full .hero-trust { color: var(--white);}
.hero--full .hero-trust .trust-item strong { color: var(--white);}
.hero--full .hero-trust .trust-item span { color: rgba(255,255,255,0.65);}
.hero--full .hero-actions { margin-bottom: 2.5em;}

/* ---------- Balance Steps ---------- */
.balance-steps {
  display: flex;
  flex-direction: column;
  gap: 32px;
}
.balance-step {
  padding: 28px 32px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  border-left: 4px solid var(--gold);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.balance-step:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-card);
}
.balance-label {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 10px;
}
.balance-step p {
  font-size: clamp(0.95rem, 1.2vw, 1.05rem);
  color: var(--charcoal-2);
  line-height: 1.8;
}

/* ---------- Work Options ---------- */
.work-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
}
.work-options > * { min-width: 0;}
.work-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 36px 32px;
  text-align: center;
  transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}
.work-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-card);
  border-color: var(--gold);
}
.work-card .ph {
  font-size: 2.4rem;
  color: var(--gold);
  margin-bottom: 16px;
  display: block;
}
.work-card h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.1rem;
  /* Two spacing faults, both measured on index.html at 390/768/1024/1440.

     The first is proximity. The heading sat 10px above its caption while the
     caption was set at line-height 1.7, so the gap that has to say "this line
     belongs with the line above it" was smaller than the gap between the
     caption's own lines. Measured baseline to baseline, the heading-to-caption
     distance was 32px against 26px of internal line rhythm, a ratio of 1.25,
     and anything near 1 reads as one undifferentiated block rather than as a
     title and a line under it. 18px puts the two apart properly.

     The second is that this heading has no line-height of its own and was
     inheriting 1.05, which is 18.48px of line box on 17.6px of type. That is
     fine on one line and wrong the moment it wraps: at 1024px the card is
     182px wide and the heading broke to three lines 18px apart, so the lines
     nearly touched. 1.2 gives 21.12px, which still reads as a tight display
     setting but leaves the lines their own air.

     text-wrap: balance is what keeps a centred heading from breaking badly.
     Without it the browser fills lines and these two titles can break as
     "Online Coaching &" / "Mentorship", which leaves a single short word alone
     on the second line. It is a no-op on the widths where the heading fits on
     one line, so nothing else moves. */
  line-height: 1.2;
  text-wrap: balance;
  color: var(--black);
  margin-bottom: 18px;
}
.work-card p {
  font-size: 0.95rem;
  color: var(--charcoal-2);
  line-height: 1.7;
}

/* ==========================================================================
   PAGE-SPECIFIC GRID BASES Must live here (before breakpoints.css)
   so responsive media queries can override them.
   ========================================================================== */

/* Contact page */
.contact-grid {
  display: grid;
  grid-template-columns: 1.2fr 0.8fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
}
.contact-grid > * { min-width: 0;}
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px;}
.form-row > * { min-width: 0;}

/* Resources */
.res-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px;}
.res-grid-2 > * { min-width: 0;}

/* Mini-cards cols-2 */
.mini-cards.cols-2 { grid-template-columns: 1fr 1fr;}
.mini-cards.cols-3 { grid-template-columns: repeat(3, 1fr);}
.mini-cards.cols-4 { grid-template-columns: repeat(4, 1fr);}

/* Packages pricing grid */
.packages-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  align-items: stretch;
}
.packages-grid > * { min-width: 0;}

/* Steps grid

   Three columns, not five. The component caps itself at max-width 1200px, so
   five tracks could never exceed 221px each however wide the monitor got: the
   five-column layout was unreachable on any real display and only ever showed
   up as five 73px columns on a tablet. Three columns of 387px is the same
   content at a readable size, and the ladder in breakpoints.css now carries
   this down through two and one. */
.steps-grid {
  display: grid;
  gap: 24px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  max-width: 1200px;
  margin: 0 auto;
}
.steps-grid > * { min-width: 0;}

/* Blog post nav */
.post-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 48px;}
.post-nav > * { min-width: 0;}

/* Comment form */
.comment-form .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px;}

/* ---------- Floating WhatsApp ----------
   Markup is injected by js/main.js rather than pasted into all 25 pages, so the
   number, the label and the glyph can never drift between pages.

   Bottom-right corner, the placement the button is expected at and the one the
   rest of the page leaves free: .mobile-cta is force-hidden at every width
   (breakpoints.css), and no other bottom-edge float has any markup. The
   .social-float column and .book-float pill that used to share this corner have
   been removed rather than left dormant - see the note at the end of this file.
   env(safe-area-inset-bottom keeps the button clear of the iPhone home
   indicator rather than tucked under it.

   z-index 120 sits above page content but below the sticky header (130), the
   hamburger (150) and every overlay (199-210), so it can never cover the menu
   drawer, its backdrop or an open lightbox. */
.wa-float {
  position: fixed;
  right: clamp(16px, 2vw, 24px);
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  width: 56px;
  height: 56px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: linear-gradient(135deg, #25D366, #128C7E);
  color: #fff;
  box-shadow: 0 10px 30px -8px rgba(18, 140, 126, 0.55);
  z-index: 120;
  transition: transform 0.25s ease, box-shadow 0.25s ease,
              opacity 0.25s ease, visibility 0s linear 0s;
}
/* The footer repeats the WhatsApp link and the phone numbers in this same
   bottom-right corner. Left alone the float would sit on top of them for the
   whole time they are on screen and swallow every click, so it steps aside when
   the footer arrives and returns the moment it scrolls back out.
   visibility is delayed by the fade duration rather than flipped instantly, so
   the button also leaves the tab order while it is hidden instead of staying
   focusable at opacity 0. */
.wa-float--away {
  opacity: 0;
  transform: scale(0.75);
  visibility: hidden;
  pointer-events: none;
  transition: transform 0.25s ease, box-shadow 0.25s ease,
              opacity 0.25s ease, visibility 0s linear 0.25s;
}
.wa-float:hover,
.wa-float:focus-visible {
  transform: scale(1.06);
  box-shadow: 0 14px 38px -8px rgba(18, 140, 126, 0.65);
}
/* keyboard users get a visible ring; the hover lift alone is not enough of a
   signal on a round target with no other affordance */
.wa-float:focus-visible {
  outline: 3px solid var(--gold-soft);
  outline-offset: 3px;
}
.wa-float svg { width: 28px; height: 28px; display: block;}

/* ---------- Floating booking ----------
   Circular gold booking button stacked above the WhatsApp bubble in the
   bottom-right corner. Same fixed layer (z-index 120) and the same hover lift,
   focus ring and responsive sizing the wa-float button uses. The markup is one
   anchor per page - footer.php on WordPress, pasted before the scripts on every
   static page - because a booking entry point belongs on every page. The
   bottom offset is the wa-float's 24px plus its 56px height plus a 12px gap.
   Both floats stay visible over the footer: wa-float steps aside there under
   js/main.js's own observer, and this button covering the footer's book button
   is no loss, since the two targets are the same action. */
.book-float {
  position: fixed;
  right: clamp(16px, 2vw, 24px);
  bottom: calc(92px + env(safe-area-inset-bottom, 0px));
  width: 56px;
  height: 56px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--gold);
  color: #fff;
  box-shadow: 0 10px 30px -8px rgba(34, 84, 76, 0.55);
  z-index: 120;
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.book-float:hover,
.book-float:focus-visible {
  transform: scale(1.06);
  box-shadow: 0 14px 38px -8px rgba(34, 84, 76, 0.65);
}
/* keyboard users get a visible ring, matching the wa-float ring */
.book-float:focus-visible {
  outline: 3px solid var(--gold-soft);
  outline-offset: 3px;
}
.book-float svg { width: 26px; height: 26px; display: block; }
