/*
 * Deliberate divergences from the ported source CSS.
 *
 * layout.css is machine-generated from the original stylesheet and gets
 * regenerated; anything we intentionally change lives HERE so the divergence
 * stays visible and survives a re-port (CLAUDE.md §5).
 */

/*
 * The source gives six pages two <h1>s - one in the banner band, one in the
 * content. The banner now carries the page's single H1 and content headings are
 * demoted to <h2 class="hor-h1"> at import. `.content h1` and `.content h2` are
 * styled differently (20px brown vs 18px sky), so the class restores the h1
 * appearance exactly. Same pixels, correct heading order (§16 item 8).
 */
.content h2.hor-h1 {
  font-family: var(--hor-font);
  font-weight: var(--hor-fw-bold);
  font-size: var(--hor-fs-20);
  line-height: var(--hor-lh-h1);
  color: var(--hor-c-brown-dark);
  /*
   * NO text-transform. The source's .content h1 is `none`; an invented
   * uppercase here widened mixed-case headings enough to wrap them onto a
   * second line, shifting whole pages by 20px. It went unnoticed on FAQs only
   * because that heading is already uppercase in the source text.
   */
  /*
   * margin 0, matching `.content h1` in the source. An invented 10px bottom
   * margin here pushed every page's content down 9px and showed up as a 16%
   * visual diff - text mis-registering line for line.
   */
  margin: 0;
  padding: 0;
}

/*
 * The source drops .content h1 to 15px/20px with a 10px bottom margin below
 * 800px. .hor-h1 has to mirror that or it forces the desktop size at every
 * width - which is exactly what made mobile differ while desktop matched.
 */
@media all and (max-width: 800px) and (min-width: 200px) {
  .content h2.hor-h1 {
    font-size: var(--hor-fs-15);
    line-height: var(--hor-lh-body-sm);
    margin: 0 0 10px 0;
  }
}

/*
 * Nothing styles the mobile nav here any more.
 *
 * jquery.mmenu.all.css is ported into layout.css, so `.mm-menu`, `.mm-panel`,
 * `.mm-list`, `.mm-subopen` and the rest come from the source stylesheet
 * verbatim, and assets/js/nav.js builds the DOM they are written against.
 * `.mm-menu.mm-offcanvas { display: none }` is what hides it until opened -
 * the two rules that used to live here were an approximation of that.
 */
@media all and (max-width: 900px) {
  .hor-nav-desktop {
    display: none;
  }
}

/* The hamburger is one inline SVG in place of the Font Awesome library (§6). */
.mobmenu .menu-icon {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: inherit;
  font: inherit;
  line-height: 1;
}

.mobmenu .menu-icon svg {
  /*
   * Sized to reproduce the line box Font Awesome's glyph produced, so the
   * mobile header keeps the same height as the source.
   */
  /* display:block removes the inline descender gap that grew the bar. */
  display: block;
  width: 1em;
  height: 1em;
}

/*
 * The mobile bar's height comes from .mobmenu's own line box (30.775px) plus
 * its 20px padding. Font Awesome's glyph sat inside that without growing it;
 * an inline <button> with a sized SVG does grow it, which pushed every page
 * below the header down. line-height:0 keeps the control out of the
 * calculation so the bar measures the same as the source.
 */
.mobmenu .menu-icon {
  font-size: var(--hor-fs-30);
  line-height: 0;
  display: inline-block;
  /*
   * `top` keeps the control inside .mobmenu's 30.775px line box. With `middle`
   * it extends above the box and grows the bar by 1px - which shifted every
   * page 1px and, on a text-dense mobile layout, registered as a ~7% pixel
   * difference despite nothing being misplaced.
   */
  vertical-align: top;
}

/*
 * Pop-up stacking - a DELIBERATE divergence from the source.
 *
 * jquery.modal gives `.blocker` z-index 1. The source's own chrome sits far
 * above that: the nav is 99999, the hero slider 9999, the banner band 9998. So
 * on the live site a bio opened near the top of /therapists renders UNDERNEATH
 * all three - the overlay dims the page but the top of the panel is covered by
 * the menu bar and the slider. It is reproducible on live and it is plainly a
 * bug, not a design decision.
 *
 * Ben asked for it fixed here, so this is the one place the rebuild knowingly
 * looks different from the source. 100000 is one above the nav, which is the
 * highest thing in the source's stack; mmenu's own #mm-blocker stays above at
 * 999999, which is correct - an open mobile menu should win.
 *
 * Only the overlay needs raising. `.modal` is z-index 2 INSIDE the overlay's
 * stacking context, so it rides along.
 *
 * Side effect worth knowing: WordPress's admin bar is also 99999, so a
 * logged-in editor's pop-up now covers it. That is how a modal should behave,
 * and the bar comes back the moment it is closed.
 */
.blocker {
  z-index: 100000;
}

/*
 * Pop-up reveal.
 *
 * jquery.modal.min.css is now ported into layout.css, so `.blocker`, `.modal`
 * and `.modal a.close-modal` all come from the source stylesheet verbatim and
 * nothing about the pop-up's appearance is written here any more.
 *
 * The one thing the stylesheet cannot supply is the reveal: the library set
 * `style="display:inline-block"` on the panel from JavaScript, and the
 * Content-Security-Policy refuses inline styles (SECURITY.md §3). Same
 * declaration, carried by a class instead.
 */
.modal.is-open {
  display: inline-block;
}

/*
 * Scroll lock. jquery.modal left the page scrollable behind the overlay on
 * some browsers; the live site ends up with overflow:hidden on <body> either
 * way, so this matches what the source actually does rather than what the
 * library shipped.
 */
body.hor-modal-open {
  overflow: hidden;
}

/*
 * flexslider.css hides every slide ("Hide the slides before the JS is loaded")
 * and the original library revealed the active one with an inline style from
 * jQuery. Our vanilla slider toggles .flex-active-slide instead, so the reveal
 * has to be a real rule (§10).
 */
.flexslider .slides > li.flex-active-slide {
  display: block;
}

/*
 * No-JS fallback: show the first slide rather than an empty band. The source
 * has the same rule via .no-js, which it never actually sets.
 */
.flexslider .slides > li:first-child {
  display: block;
}

.flexslider .slides > li:first-child:not(.flex-active-slide):has(~ li.flex-active-slide) {
  display: none;
}

/*
 * Where we split ONE source section into several, the 40px top + 40px bottom
 * padding gets paid at every join instead of once.
 *
 * Scoped to a following .hor-cols (Two columns) section, because that is the
 * only split we create: a source page's heading and its columns live in one
 * <section class="content"> and we emit two. Collapsing at EVERY join was
 * wrong - News and Blog genuinely have two sections on the source and keep
 * their padding, and the blanket rule made those pages 65px short.
 */
.content + .content.hor-cols > div > .col-12 > article,
.content + .content.hor-cols > div > article {
  padding-top: 0;
}

.content:has(+ .content.hor-cols) {
  padding-bottom: 0;
}

/*
 * The article inside also carries a 10px bottom padding. On the source that
 * sits once at the very end of the page; here it would land at every section
 * join, shifting everything below it down by 10px.
 */
.content:has(+ .content.hor-cols) > div > .col-12 > article,
.content:has(+ .content.hor-cols) > div > article {
  padding-bottom: 0;
}

/*
 * The source put these on an inline style attribute; inline styles are out
 * (CLAUDE.md §12), so the same declarations live here as a class.
 * Values copied exactly: display:flex; gap:10px; flex-wrap:wrap; margin-top:20px
 * on the row, and padding:6px 10px 2px 10px on each button.
 */
.hor-btn-row {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 20px;
}

.hor-btn-row .btn {
  display: inline-block;
  padding: 6px 10px 2px 10px;
}

/*
 * The Useful Links page was 404ing on the source site, so its grid styles were
 * never in main.css - only the markup survived in the archive. Rebuilt to match
 * the archived layout: a logo above a centred link.
 */
.useful-links {
  display: flex;
  flex-wrap: wrap;
  gap: 30px;
  margin-top: 20px;
}

.useful-links__item {
  flex: 0 1 calc(33.333% - 20px);
  text-align: center;
}

.useful-links__img {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 90px;
  margin-bottom: 10px;
}

.useful-links__img img {
  max-width: 100%;
  max-height: 90px;
  width: auto;
  height: auto;
}

@media all and (max-width: 767px) {
  .useful-links__item {
    flex: 0 1 calc(50% - 15px);
  }
}

/*
 * "Want to work with us?" pop-up.
 *
 * The ported stylesheet does all of the showing and hiding - opacity, the
 * slide in from left:150%, the white wash in ::after. The three rules that
 * used to live here (display:none / display:block / a close-icon reset) were
 * an approximation of that, and the reset is what made the close square
 * invisible. Only what the MOVE to body level requires is left
 * (template-parts/recruitment-panel.php explains the move):
 *
 * 1. Out of flow. .brochure is inline-block in the source, which is harmless
 *    inside the nav but at body level would open a line box and add ~20px to
 *    the bottom of the page. Absolute, not fixed: fixed ALWAYS creates a
 *    stacking context, which would trap the pop-up's z-index inside it and
 *    put it straight back underneath the nav.
 */
.brochure {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  margin: 0;
}

/*
 * 2. Above the nav. In the source this pop-up borrows the nav's z-index 99999
 *    by living inside it. At body level it has to carry its own - the same
 *    value as the bio pop-up's .blocker, for the same reason.
 */
.brochure.active .brochure-pop {
  z-index: 100000;
}

/*
 * 3. The close square. The source's close control is a <div>; ours is a
 *    <button> so it can be reached from the keyboard - and the ported rule
 *    `.brochure button { background: none; padding: 0 10px }` (meant for a
 *    different button) then matches it and wipes out the black square. Put
 *    back exactly what the ported .close-icon rule says.
 */
.brochure button.close-icon {
  background: var(--hor-c-black);
  border: 0;
  padding: 0;
  cursor: pointer;
}

.brochure button.close-icon:hover,
.brochure button.close-icon:focus-visible {
  background: var(--hor-c-sky);
}

/*
 * 4. What it used to inherit from the nav.
 *
 * Inside the source's <nav> the panel picks up two things it does not set
 * itself: text-align:center from the nav, and the BODY font, museo-sans, which
 * comes from the Typekit kit and shows nowhere else on the site - every
 * visible element sets Khula explicitly. At body level it would get neither.
 *
 * Typekit is out of scope (Ben, CLAUDE.md §6), so rather than let it fall
 * through to the system sans-serif it uses the site's own face at the same
 * light weight live renders (the kit only carries museo-sans 300). The one
 * visible difference from live, flagged in §16.
 */
.brochure-pop article {
  text-align: center;
  font-family: var(--hor-font);
  font-weight: 300;
}

/*
 * 5. Phones. There is no live behaviour to match here: on live the pop-up is
 * inside a nav that is display:none below 900px, so it never opens. The
 * source's desktop sizing - article 50% of a 75%-wide panel, 50px padding, and
 * 30px/50px on the paragraph - leaves a 146px column at 390px wide, with the
 * text crushed to a word per line. Same look, room to read.
 */
@media all and (max-width: 900px) {
  .brochure .brochure-pop {
    width: 90%;
  }

  .brochure-pop article {
    width: 100%;
    padding: 60px 20px 30px;
  }

  .brochure-pop article p {
    padding: 10px;
  }
}

/*
 * The site notice's close control is a real <button> now rather than a styled
 * <div>, so it is keyboard reachable. Reset the button chrome; .close-icon in
 * the ported stylesheet supplies the appearance.
 *
 * The source CSS pins it to top-LEFT, where it straddles the panel edge and
 * reads as a rendering fault. There is no parity cost in moving it: the source
 * shipped this markup commented out, so it never appeared on the live site and
 * has no established look to match.
 */
.holiday-pop .close-icon {
  border: 0;
  padding: 0;
  cursor: pointer;
  appearance: none;
  left: auto;
  right: 0;
}

.holiday-pop .close-icon:focus-visible {
  outline: 2px solid var(--hor-c-sky);
  outline-offset: 2px;
}

/*
 * Mobile column padding.
 *
 * The source styles stacked columns with :nth-child rules. There the two
 * .col-6 blocks are children 3 and 4 of their <article> (a heading and an <hr>
 * come first), so the second one falls through to `.content .col-6 article`
 * and gets 10px. Here each layout is its own section, so the columns are
 * children 1 and 2 - and the second matches `:nth-child(2)`, picking up
 * 20px top AND 20px bottom instead.
 *
 * That is a 30px discrepancy per split, and it is what made mobile 16%
 * different while desktop was already matching. Restore the source's computed
 * values for our structure.
 */
@media all and (max-width: 800px) and (min-width: 200px) {
  .hor-cols .col-6:nth-child(2) article {
    padding: 10px 0 0 0 !important;
  }
}

/*
 * Two footer items ("Hand Therapy", "Referral Form") are 15px on the source,
 * set with an inline style attribute. Inline styles are out (§12), so the
 * import tags them with this class instead. Without it the footer stands 18px
 * taller than the original.
 */
footer .links li.hor-footer-sm {
  font-size: var(--hor-fs-15);
}

/*
 * Every clinic page ends with <div class="col-12"><article></article></div> -
 * empty markup whose only effect is 50px of space before the footer (40px top
 * + 10px bottom article padding). Reproduced as padding rather than by
 * shipping an empty element.
 */
.content.hor-clinic > div > .col-12 > article {
  padding-bottom: 60px;
}

/*
 * People with no qualifications: the source still renders an empty <h4> there,
 * which occupies about 5px. Reserving it here keeps the heights matching
 * without shipping an empty heading element for a screen reader to trip over.
 *
 * Both the grid card (<article>) and the pop-up (<figure>) need it. They were
 * written as `> article >` only, so every Support Team pop-up came out 5px
 * short - invisible to the page sweep, which never opens one, and worth 8-9%
 * of a 390px-wide pop-up once the panel re-centres around the missing height.
 */
.our-people.hor-missing-1 > article > h4:last-of-type,
.our-people.hor-missing-1 > figure > h4:last-of-type {
  /* One absent <h4>: add the 5px of margin it would have contributed. */
  margin-bottom: 10px;
}

.our-people.hor-missing-2 > article > h3,
.our-people.hor-missing-2 > figure > h3 {
  /* Both absent - no <h4> to hang it on, so it goes on the role. */
  margin-bottom: 15px;
}

/* See rich_text.php - blank columns the source leaves before its footer. */
.content.hor-trailing-space > div > .col-12 > article {
  padding-bottom: 60px;
}

/*
 * Gravity Forms field spacing.
 *
 * The source's hand-rolled form stacked label + input with about 17px between
 * fields. Gravity Forms defaults to roughly double that, which made the Contact
 * page 161px taller at mobile. The form itself is a like-for-like replacement
 * (CLAUDE.md §11), so its spacing should match what it replaced.
 */
.gform_wrapper .gform_fields {
  row-gap: 0;
}

.gform_wrapper .gfield,
.gform_legacy_markup_wrapper ul.gform_fields li.gfield {
  /*
   * No bottom margin: the ported source CSS already gives .form input a 20px
   * bottom margin, and that is exactly how the original form spaced its
   * fields. Adding GF's own margin on top stacked the two.
   */
  margin-bottom: 0;
  padding-right: 0;
}

/*
 * GF stacks a 16px top margin on the field and another 8px between label and
 * input. The source had neither, so each field ran ~24px taller. Its own rules
 * are more specific than a plain class selector, hence !important.
 */
.gform_wrapper .gfield,
.gform_legacy_markup_wrapper ul.gform_fields li.gfield {
  margin-top: 0 !important;
}

.gform_wrapper .ginput_container,
.gform_legacy_markup_wrapper .ginput_container {
  margin-top: 0 !important;
}

.gform_wrapper .gfield_label,
.gform_legacy_markup_wrapper .gfield_label {
  margin-bottom: 0;
  padding-bottom: 0;
}

/*
 * Two inline style attributes, moved into the stylesheet.
 *
 * The Content-Security-Policy refuses inline styles outright - `style-src-attr
 * 'none'` - so a `style="..."` attribute is dead markup, not a fallback. Both
 * of these were load-bearing:
 *
 *   .hor-map          replaces style="border:0" on the clinic map embed. A
 *                     browser's default iframe border is 2px inset, so without
 *                     this the map grows a frame the source site never had.
 *
 *   gform_ajax_frame  replaces Gravity Forms' own
 *                     style="display:none;width:0px;height:0px" on the hidden
 *                     iframe its AJAX submission posts into. Without it the
 *                     iframe renders at its default 300x150 in the middle of
 *                     the contact page. The attribute is stripped server-side
 *                     in inc/security/hardening.php; this is what replaces it.
 */
.hor-map {
	border: 0;
}

iframe[id^="gform_ajax_frame"] {
	display: none;
	width: 0;
	height: 0;
}

/*
 * Screen-reader live regions, hidden from the stylesheet rather than inline.
 *
 * Both WordPress core's @wordpress/a11y and Gravity Forms' own utils bundle
 * create aria-live containers and hide them with setAttribute( 'style', ... ).
 * `style-src-attr 'none'` refuses that, and an unhidden live region is not a
 * silent failure - it prints its announcements as visible text on the page.
 *
 * Core's containers carry a class, so assets/js/csp-fixes.js creates them first
 * and core skips the call. Gravity Forms' carry no id and no class at all, so
 * there is nothing to pre-create and nothing to name - the attribute selector
 * below is the only handle on them. It matches what a live region IS rather
 * than what it is called, which is also why it keeps working if either vendor
 * renames anything.
 */
.a11y-speak-region,
.a11y-speak-intro-text,
[aria-live][aria-relevant="additions text"][aria-atomic="true"] {
	position: absolute;
	margin: -1px;
	padding: 0;
	height: 1px;
	width: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	border: 0;
	word-wrap: normal !important;
}
