/* =============================================================================
   Halden Orthodontics, hero.css: h01, the Opening frame (sections_hero.py), driven by assets/js/hero.js. Tokens only. One breakpoint (1023px). hero.js writes --clip, --open, --x, --c,
   --e on the section and the per-word and per-layer transforms; reduced motion and no script get the still versions below.
   ========================================================================== */

/* ---- the x01 bar stays out of a pinned or zooming stage (nav.js untouched: hero.js sets the html classes) ---- */
html.hero-stage:not(.menu-open):not(.modal-open) .hdr:not(:focus-within) { transform: translateY(-105%); }
html.hero-after:not(.menu-open):not(.modal-open) .hdr { transform: none; }

/* ---- shared stage ---------------------------------------------------------------- */
.s-hero { position: relative; }
.s-hero__stage { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; }
.s-hero__media { position: absolute; inset: 0; background: var(--photo-black); color: var(--ink-invert); }
.s-hero__media img, .s-hero__media video { display: block; width: 100%; height: 100%; object-fit: cover; }
.s-hero__media::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to bottom, var(--scrim-top), transparent 180px), linear-gradient(to top, var(--scrim), transparent 45%), linear-gradient(var(--scrim-hero), var(--scrim-hero)); }
.s-hero__sub { margin: 0; }
.hero-based { display: grid; gap: var(--gap-8); }
.hero-based p { display: grid; margin: 0; }

/* ---- 1. Opening frame -------------------------------------------------------------- */
.s-hero--v1 { height: calc(100vh * 3.5); height: calc(100svh * 3.5); background: var(--ground); --open: 0; --x: 0;
  --clip: inset(0 0 0 50%); }
.s-hero--v1 .s-hero__stage { background: var(--ground); }
.s-hero--v1 .s-hero__light { position: absolute; inset: 0; background: var(--ground); }
.s-hero--v1 .s-hero__light::after { content: ""; position: absolute; inset: 0; background: var(--anchor); opacity: calc(var(--open) * .18); pointer-events: none; }
.s-hero--v1 .s-hero__slot { position: absolute; top: 0; right: 0; bottom: 0; left: 50%; pointer-events: none; }
.s-hero--v1 .s-hero__type { position: absolute; inset: 0; display: grid; place-content: center; padding: 0 var(--pad-x); pointer-events: none;
  opacity: clamp(0, calc(1 - var(--open) * 2.5), 1); transform: translateX(calc(var(--open) * -6vw)); }
.s-hero--v1 .s-hero__type .split-h { color: var(--ink); width: max-content; max-width: calc(100vw - 2 * var(--pad-x)); margin: 0; }
.s-hero--v1 .s-hero__type--inv { z-index: 2; }   /* inside the clip, so its ground reads as the clip */
.s-hero--v1 .s-hero__type--inv .split-h { color: var(--ink); }   /* fix wave 2, C1: the whole headline is ink on both halves, no colour change mid-word */
.s-hero--v1 .s-hero__sub { position: absolute; right: calc(50% + var(--pad-x)); bottom: var(--gap-24); max-width: 13em; text-align: right; color: var(--ink);
  opacity: clamp(0, calc(1 - var(--open) * 2.5), 1); }
.s-hero--v1 .hero-based { position: absolute; left: var(--pad-x); bottom: var(--gap-24); opacity: clamp(0, calc(1 - var(--open) * 2.5), 1); }
.s-hero--v1 .s-hero__media { z-index: 1; clip-path: var(--clip); }
/* fix wave 2, C1: at rest the clip is moved so the subject (the model with braces) sits in the window; hero.js measures --vx, --vy, --vs from
   the window and the subject box, and the move eases to nothing as the frame opens */
.s-hero--v1 .s-hero__media .vid, .s-hero--v1 .s-hero__media > img { transform: translate(calc(var(--vx, 0px) * (1 - var(--open))), calc(var(--vy, 0px) * (1 - var(--open))))
  scale(calc(var(--vs, 1.06) + (1 - var(--vs, 1.06)) * var(--open) - var(--x) * .03)); }
.s-hero--v1 .s-hero__media::before { content: ""; position: absolute; inset: 0; z-index: 1; background: var(--photo-black); opacity: calc(var(--x) * .4); pointer-events: none; }
.s-hero--v1 .s-hero__media::after { z-index: 0; opacity: var(--open);
  background: linear-gradient(to top, rgba(35, 31, 32, .55), rgba(35, 31, 32, 0) 45%), linear-gradient(rgba(35, 31, 32, .5), rgba(35, 31, 32, .5)); }   /* C1: bright at rest, darkens only as it opens, so the white landing line and the links stay readable at full bleed */
.s-hero__note { position: absolute; left: calc(50% + var(--pad-x)); bottom: var(--gap-24); z-index: 2; max-width: 22em; margin: 0; padding: var(--gap-12) var(--gap-16);
  border-radius: 22px; background: var(--ground); color: var(--ink); opacity: clamp(0, calc(1 - var(--open) * 2.5), 1); }   /* C1: a paper chip on the clip */
.s-hero__line { position: absolute; inset: 0; z-index: 2; display: flex; flex-wrap: wrap; align-content: center; justify-content: center;
  column-gap: .22em; margin: 0 auto; padding: 0 var(--pad-x); max-width: calc(100vw - 2 * var(--pad-x)); text-align: center; color: var(--ink-invert); pointer-events: none; }
.hero-w { display: inline-block; overflow: hidden; padding: 0 .04em .1em; vertical-align: top; }
.hero-w > span { display: inline-block; transform: translateY(130%); opacity: 0; will-change: transform; }
.hero-w.is-it > span { font-style: italic; }
.s-hero__items { position: absolute; left: 0; right: 0; bottom: var(--gap-24); z-index: 3; display: flex; justify-content: space-between; gap: var(--gap-24);
  margin: 0; padding: 0 var(--pad-x); list-style: none; opacity: clamp(0, calc(var(--open) * 2 - 1), 1); }
.s-hero__items a { display: inline-flex; min-height: 24px; align-items: center; color: var(--ink-invert); transition: opacity var(--dur-fast) var(--ease-io); }
.s-hero__items a:hover { opacity: .6; }
.s-hero__items a.is-on { font-style: normal; }
/* section two slides up over the stage as it closes into a card: two beats */
.s-hero--v1 + * { margin-top: -100vh; margin-top: -100svh; position: relative; z-index: 2; }

/* ---- phones ---------------------------------------------------------------------- */
@media (max-width: 1023px) {
  .s-hero--v1 .s-hero__light { display: flex; flex-direction: column; gap: var(--gap-24); padding: calc(var(--hdr-h) + var(--gap-16)) var(--pad-x) var(--gap-16); }
  .s-hero--v1 .s-hero__type, .s-hero--v1 .s-hero__sub, .s-hero--v1 .hero-based { position: relative; inset: auto; right: auto; left: auto; bottom: auto; }
  .s-hero--v1 .s-hero__type { display: block; padding: 0; }
  .s-hero--v1 .s-hero__type .split-h > span { text-align: left; }
  .s-hero--v1 .s-hero__type--inv { display: none; }
  .s-hero--v1 .s-hero__sub { max-width: 16em; text-align: left; }
  .s-hero--v1 .s-hero__slot { position: relative; inset: auto; flex: 1 1 0; min-height: var(--gap-64); order: 9; }
  .s-hero__note { display: none; }
  .s-hero__line { max-width: none; }
  .s-hero__items { flex-wrap: wrap; justify-content: flex-start; gap: var(--gap-8) var(--gap-24); }
  .s-hero__items li { flex: 0 0 calc(50% - var(--gap-12)); }
  /* FX8 item 9: under 1024 the design sets Full-Mouth Rehabilitation on two lines; a 7.5em measure keeps that break in BOTH
     states (upright 8.2em, italic 8.8em), and the size cap keeps the next longest name, Cosmetic Dentistry (italic 6.2em),
     on one line, so no row changes height when it turns italic */
}

/* ---- reduced motion and no script: calm still versions --------------------------- */
.reduced .s-hero__stage, html:not(.js) .s-hero__stage { position: relative; }
.reduced .s-hero--v1 + *, html:not(.js) .s-hero--v1 + * { margin-top: 0; }
.reduced .s-hero__line, html:not(.js) .s-hero__line { display: none; }
.reduced .hero-w > span, html:not(.js) .hero-w > span { opacity: 1; transform: none; }
.reduced .s-hero__items, html:not(.js) .s-hero__items { opacity: 1; }
html:not(.js) .s-hero__media .vid { transform: translate(22%, 6%) scale(1.3); }   /* no script: an approximate framing of the subject (hero.js measures it exactly) */
@media (max-width: 1023px) { html:not(.js) .s-hero__media .vid { transform: none; } }
/* FX1: the V1 still (reduced motion, no script). The note keeps its own line above the four services, both inside the photo
   half on wide screens (2 by 2, no overlap); on phones the services sit 24px inside the photo card (D10), one per line. */
@media (min-width: 1024px) {
  .reduced .s-hero--v1 .s-hero__items, html:not(.js) .s-hero--v1 .s-hero__items { left: 50%; display: grid; grid-template-columns: repeat(2, max-content);
    justify-content: start; gap: var(--gap-8) var(--gap-40); }
  .reduced .s-hero--v1 .s-hero__note, html:not(.js) .s-hero--v1 .s-hero__note { bottom: calc(var(--gap-24) * 2 + var(--gap-8) + 48px); }
}
@media (max-width: 1023px) {
  .reduced .s-hero--v1 .s-hero__items, html:not(.js) .s-hero--v1 .s-hero__items { display: grid; gap: var(--gap-8);
    padding: 0 calc(var(--pad-x) + var(--gap-24)); bottom: calc(var(--gap-16) + var(--gap-24)); }
}

/* ---- Halden: the two calls on the light half ---- */
.hero-calls { position: absolute; left: var(--pad-x); bottom: calc(var(--gap-24) * 2 + 5.6em); z-index: 3; display: flex; flex-wrap: wrap; gap: var(--gap-12);
  opacity: clamp(0, calc(1 - var(--open) * 2.5), 1); }
.reduced .s-hero--v1, html:not(.js) .s-hero--v1 { height: auto; }
.s-hero--v1.is-open .hero-calls { visibility: hidden; pointer-events: none; }
@media (max-width: 1023px) {
  .s-hero--v1 .hero-calls { position: relative; left: auto; bottom: auto; }
}
.s-hero--v1 .hero-based { max-width: 15em; }
.s-hero--v1 .s-hero__sub { max-width: 16em; }
@media (min-width: 1024px) {
  /* their mission sentence is 118 characters: it sits in three lines between the "Based in" block and the half's inner edge */
  .s-hero--v1 .hero-based { max-width: 12.5em; }
  .s-hero--v1 .s-hero__sub { font-size: clamp(20px, 1.9vw, 30px); max-width: calc(50vw - 2 * var(--pad-x) - 17vw); }
}

/* ---- fix wave 2, C1: the headline rises into the upper third so both arches of the model sit under it in the right half ---- */
@media (min-width: 1024px) {
  .s-hero--v1 .s-hero__type { place-content: start center; padding-top: calc(var(--hdr-h) + 2.5vh); }
  .s-hero--v1 .s-hero__type .split-h { font-size: min(var(--t-display-size), 11.4vw); }
}

/* ---- C1: the clip is bright at rest. A soft paper veil under the header keeps its ink text legible whatever frame is playing; it fades as the frame opens. The ground behind the clip is paper, not black. ---- */
.s-hero--v1 .s-hero__media { background: var(--ground); }
.s-hero__veil { position: absolute; inset: 0 0 auto 0; height: 26%; z-index: 1; pointer-events: none; opacity: clamp(0, calc(1 - var(--open) * 2.5), 1);
  background: linear-gradient(to bottom, rgba(246, 245, 241, .86), rgba(246, 245, 241, .5) 50%, rgba(246, 245, 241, 0)); }
@media (max-width: 1023px) { .s-hero__veil { display: none; } }
/* the four treatment links over the clip show only once the frame has opened (white on the darkened clip); until then they are not painted
   and not in the tab order. The still versions (reduced motion, no script) sit on the bright clip in ink. */
html.js:not(.reduced) .s-hero--v1:not(.is-open) .s-hero__items { visibility: hidden; }
.reduced .s-hero__items a, html:not(.js) .s-hero__items a { color: var(--ink); }

/* phones: the photo credit chip sits on the bottom edge, so the service names stand clear above it */
@media (max-width: 1023px) {
  .s-hero__items { bottom: calc(var(--gap-24) + 44px); }
}
