/* wp-content/plugins/notts-osteo-elements/assets/css/page-hero.css
 *
 * Inner page hero: title and sub text on the left, the anatomical figure on the right.
 * No raw colours — everything resolves against tokens.css.
 *
 * ON THE SITE GRID: full-width background, content on the same 1440 / 72 as everything else,
 * from the same two tokens.
 *
 * Author: Sean Burn
 */

.nosteo-hero {
  --nosteo-hero-bg: var(--nosteo-tint);

  position: relative;
  background:
    radial-gradient(62% 120% at 78% 40%, var(--nosteo-white) 0%, transparent 62%),
    var(--nosteo-hero-bg);
  font-family: var(--nosteo-font);
  color: var(--nosteo-ink);
  overflow: hidden;
}

.nosteo-hero__inner {
  max-width: var(--nosteo-site-max);
  margin: 0 auto;
  /* Vertical padding is deliberately smaller than the horizontal gutter. At 5vw this was 72px top
     AND bottom on a desktop, which on top of a 593px figure made the hero 737px tall — the copy
     floated in the middle of it and the bottom padding read as a gap under the illustration.
     The 72px gutter still governs left and right, which is the site grid.
     Held in a custom property because the figure has to pull back out by exactly this much to
     reach the hero's top and bottom edges — see the side-by-side block. */
  --nosteo-hero-pad-y: clamp(20px, 2.6vw, 40px);
  padding: var(--nosteo-hero-pad-y) var(--nosteo-site-pad);
  /* Measures itself, not the window: the hero can sit in any container, and a viewport query
     would put the figure beside the copy inside a box too narrow for both. */
  container-type: inline-size;
  container-name: nosteo-hero;
}

/* Stacked by default. Copy first in the source AND first on screen, so the words are what a
   visitor meets on a phone rather than a decorative figure they must scroll past. */
.nosteo-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(16px, 4vw, 48px);
  align-items: center;
}

/* ---------- copy ---------- */

.nosteo-hero__eyebrow {
  margin: 0 0 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--nosteo-hair);
  font-family: var(--nosteo-mono);
  font-size: 11px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--nosteo-resolve-ink);
}

.nosteo-hero__title {
  margin: 0 0 14px;
  font-size: clamp(30px, 6vw, 68px);
  line-height: 1;
  letter-spacing: -0.035em;
  font-weight: var(--nosteo-weight-strong);
  text-transform: uppercase;
  text-wrap: balance;
}

.nosteo-hero__text {
  margin: 0;
  max-width: 46ch;
  font-size: clamp(15px, 1.6vw, 18px);
  line-height: 1.6;
  color: var(--nosteo-ink);
}

/* The two things you can do from here, on one row. The illustration toggle is secondary to
   booking, so it is an icon beside the button rather than a second full-width control. */
.nosteo-hero__actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 22px;
}

.nosteo-hero__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 28px;
  border-radius: var(--nosteo-cta-radius, 999px);
  background-color: var(--nosteo-accent);
  /* Same wipe as the header's Book Now: background-size on a flat gradient needs no
     pseudo-element to stack against the button's own fill. */
  background-image: linear-gradient(var(--nosteo-white), var(--nosteo-white));
  background-repeat: no-repeat;
  background-position: left center;
  background-size: 0% 100%;
  box-shadow: inset 0 0 0 1px var(--nosteo-accent);
  color: var(--nosteo-white);
  font-weight: var(--nosteo-weight-strong);
  text-decoration: none;
  transition: background-size 320ms var(--nosteo-ease), color 200ms var(--nosteo-ease);
}
/* Colour restated on every state: the theme reset's `a:active, a:hover { color: #336 }` is
   (0,1,1) and outranks a single-class rule. */
.nosteo-hero__cta:hover,
.nosteo-hero__cta:focus-visible,
.nosteo-hero__cta:active {
  background-size: 100% 100%;
  color: var(--nosteo-accent);
}
.nosteo-hero__cta:focus-visible {
  outline: 2px solid var(--nosteo-ink);
  outline-offset: 3px;
}

/* ---------- illustration toggle ---------- */

.nosteo-hero__reveal {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 48px;          /* matches the booking button, and is the tap target floor */
  padding: 0 20px;
  border: 1px solid var(--nosteo-hair);
  border-radius: 999px;
  background: none;
  color: var(--nosteo-resolve-ink);
  font: inherit;
  font-size: 15px;
  font-weight: var(--nosteo-weight-medium);
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 180ms var(--nosteo-ease), color 180ms var(--nosteo-ease);
}
.nosteo-hero__reveal svg { width: 12px; height: 14px; flex: none; }
/* Two classes to clear Hello Elementor's reset, which paints every button
   `background-color: #c36; color: #fff` on hover AND focus at (0,2,0) via [type=button]. */
.nosteo-hero .nosteo-hero__reveal:hover,
.nosteo-hero .nosteo-hero__reveal:focus {
  background: none;
  border-color: var(--nosteo-accent);
  color: var(--nosteo-accent);
}
.nosteo-hero .nosteo-hero__reveal:focus-visible {
  outline: 2px solid var(--nosteo-accent);
  outline-offset: 2px;
}
/* The arrow is the whole glyph now, so it can simply turn. */
.nosteo-hero__reveal-arrow {
  transform-origin: center;
  transition: transform 240ms var(--nosteo-ease);
}
.nosteo-hero__reveal[aria-expanded="true"] .nosteo-hero__reveal-arrow { transform: rotate(180deg); }

/* ---------- figure ---------- */

.nosteo-hero__figure {
  position: relative;
  /* The aspect ratio lives HERE, on the in-flow element, and is what gives the figure a height
     at all. It was briefly moved onto the canvas — which is absolutely positioned, so it
     contributes no height, and the panel opened to a box with nothing in it. An out-of-flow
     child cannot size its parent. */
  aspect-ratio: 4 / 3;
  /* Collapsed. max-height rather than display:none so it can be transitioned and the script
     has a box to measure the moment it opens. */
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height 340ms var(--nosteo-ease), opacity 260ms var(--nosteo-ease),
              margin-top 340ms var(--nosteo-ease);
}
/* Two independent states, deliberately not merged: `is-ready` means the model has arrived,
   `is-figure-open` means the visitor asked to see it. Both are required, or opening the panel
   before the model loads reveals an empty box. */
.nosteo-hero.is-figure-open .nosteo-hero__figure {
  max-height: 30vh;
  margin-top: 18px;
}
.nosteo-hero.is-figure-open .nosteo-hero__figure.is-ready { opacity: 1; }

/* If the model never arrives the copy stands on its own, and the toggle goes with it — a
   control that reveals nothing is worse than no control. */
.nosteo-hero__figure.is-failed { display: none; }
.nosteo-hero:has(.nosteo-hero__figure.is-failed) .nosteo-hero__reveal { display: none; }

.nosteo-hero__canvas {
  /* ABSOLUTE, not just 100%/100%. renderer.setSize(w, h, false) writes the canvas's width and
     height ATTRIBUTES at device pixel ratio and deliberately leaves its CSS alone; a
     percentage height against a derived parent height does not resolve reliably, and where it
     falls back the canvas lays out at that intrinsic size instead. Out of flow, it cannot —
     and its size comes entirely from the figure. */
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}

/* ---------- name and button on one row ----------
   Phones only. On a staff page there is no sub text between the title and the button, so the button
   was taking a whole row of its own above the portrait and pushing the photograph down the screen.
   Pairing them recovers that row.

   A grid rather than flex on the copy block: the eyebrow has to span both columns and stay above,
   which flex-wrap cannot express without extra markup. */
@media (max-width: 767px) {
  .nosteo-hero--tight .nosteo-hero__copy {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 14px;
  }

  /* The button shares the EYEBROW's row, not the title's.
     Beside the title it forced "MEET HARRY" onto two lines, and the two ways out of that were both
     wrong: shrinking the button cuts the page's primary action below a comfortable tap target, and
     letting the h1 wrap squeezes the one piece of text that should never be squeezed. The eyebrow
     row was nearly empty, so the button goes there and the title gets the full width back. */
  .nosteo-hero--tight .nosteo-hero__eyebrow {
    grid-row: 1;
    grid-column: 1;
    /* The rule moves to the title below, where it can span the whole row. */
    margin: 0;
    padding: 0;
    border-bottom: 0;
  }
  .nosteo-hero--tight .nosteo-hero__actions {
    grid-row: 1;
    grid-column: 2;
    margin-top: 0;
    justify-self: end;
    /* One row: nothing here may wrap onto a second. */
    flex-wrap: nowrap;
  }

  /* Sized to the label it sits beside rather than to a full-width button's proportions. At 48px it
     towered over an 11px eyebrow and set the row height on its own, which is what pushed it hard
     against the rule below. 36px still clears the 24px minimum for a target this size, and the row
     it belongs to is a header strip, not the page's main call to action — that one is the booking
     button further down, at full size. */
  .nosteo-hero--tight .nosteo-hero__cta {
    min-height: 36px;
    padding: 0 18px;
    font-size: 14px;
  }

  .nosteo-hero--tight .nosteo-hero__title {
    grid-row: 2;
    grid-column: 1 / -1;
    /* Full width, so the longest name still sets on one line. */
    margin-bottom: 0;
    /* MARGIN, not padding: it sits outside the border, so it opens a gap between the button's row
       and the rule. Padding would only move the text further below a rule still touching the
       button. */
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid var(--nosteo-hair);
  }
}

/* Below ~330px the eyebrow and the button cannot share a row either. Back to stacked, which is
   still readable — just taller. */
@media (max-width: 329px) {
  .nosteo-hero--tight .nosteo-hero__copy { display: block; }
  .nosteo-hero--tight .nosteo-hero__eyebrow {
    margin: 0 0 12px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--nosteo-hair);
  }
  .nosteo-hero--tight .nosteo-hero__title {
    margin-bottom: 14px;
    padding-top: 0;
    border-top: 0;
  }
  .nosteo-hero--tight .nosteo-hero__actions { margin-top: 22px; }
}

/* ---------- an uploaded image instead of the render ----------
   Prices, FAQ and About have no body area to show. The picture is in flow from the start — no
   collapsing panel, no reveal button, nothing to wait for — so it needs none of the machinery the
   scene does. */
.nosteo-hero__figure--image {
  margin: 18px 0 0;
  /* Overrides the collapsed state the scene's figure starts in. */
  max-height: none;
  aspect-ratio: auto;
  opacity: 1;
  overflow: hidden;
}
.nosteo-hero__figure--image img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---------- an uploaded portrait is a portrait, not a backdrop ----------
   Left to fill its column the way the anatomy render does, a 2:3 staff photograph made the hero
   enormous: full column width on desktop, and on a phone `height: 100%` against an auto-height
   figure fell back to the natural ratio, so a 335px-wide screen got a ~500px-tall photograph and a
   banner you had to scroll past. Capped on both. */
.nosteo-hero__figure--image {
  /* Phone: a landscape crop of a set height, rather than a full-length portrait. */
  aspect-ratio: 4 / 3;
  max-height: 38vh;
}
.nosteo-hero__figure--image img {
  /* Heads are near the top of these shots. */
  object-position: 50% 18%;
}

@container nosteo-hero (min-width: 760px) {
  /* Beside the copy it stays a portrait — full height of the banner, but only as wide as a person
     needs to be. */
  .nosteo-hero__figure--image {
    aspect-ratio: auto;
    max-height: none;
    max-width: 340px;
    margin-inline: auto;
  }
  /* Shorter than the 400px the render gets: there is no scene to frame here, and the copy on these
     pages is a name and a button. */
  .nosteo-hero--image .nosteo-hero__grid { min-height: 360px; }
}

/* ---------- copy only ----------
   With nothing beside it the copy would otherwise sit in a half-width column with dead space to its
   right. It takes the full width and keeps a readable measure instead. */
.nosteo-hero--none .nosteo-hero__grid { grid-template-columns: minmax(0, 1fr); }
.nosteo-hero--none .nosteo-hero__copy { max-width: 72ch; }

/* ---------- side by side ---------- */

@container nosteo-hero (min-width: 760px) {
  .nosteo-hero__grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); }
  /* The toggle is a small-screen affordance only. */
  .nosteo-hero__reveal { display: none; }
  /* The banner's own height, so it does not depend on how long a given page's copy happens to
     be — otherwise the illustration would be short on terse pages and tall on wordy ones. */
  .nosteo-hero__grid { min-height: 400px; }

  .nosteo-hero__figure {
    /* Full height, edge to edge: the figure stretches to the grid row and then pulls back out
       through the inner's vertical padding, so it meets the hero's top and bottom. .nosteo-hero
       has overflow:hidden, so it is clipped exactly there.
       No aspect-ratio and no max-width here — the box is now driven by the row's height, and
       constraining either would reintroduce the gap above and below. */
    align-self: stretch;
    aspect-ratio: auto;
    max-height: none;
    min-height: 0;
    margin-block: calc(-1 * var(--nosteo-hero-pad-y));
    overflow: hidden;
  }
  .nosteo-hero__figure.is-ready { opacity: 1; }
}

@supports not (container-type: inline-size) {
  @media (min-width: 920px) {
    .nosteo-hero__grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); }
    .nosteo-hero__reveal { display: none; }
    .nosteo-hero__grid { min-height: 400px; }
    .nosteo-hero__figure { align-self: stretch; aspect-ratio: auto; max-height: none; min-height: 0; margin-block: calc(-1 * var(--nosteo-hero-pad-y)); overflow: hidden; }
    .nosteo-hero__figure.is-ready { opacity: 1; }
  }
}

@media (prefers-reduced-motion: reduce) {
  .nosteo-hero__cta,
  .nosteo-hero__reveal,
  .nosteo-hero__reveal-arrow,
  .nosteo-hero__figure { transition: none !important; }
}
