/* =============================================
   ABOUT — editorial redesign (about-full.php)
   Three chapters: Történetünk (logo panel), Szemléletünk
   (bg-sweep blush band + image slideshow), Csapatunk
   (full-bleed media + team trio). Pairs with
   assets/js/reveal.js and the shared typewriter.js /
   bg-sweep.js. Scoped under .page-about so shared .svc-split
   / .about-team styles are untouched.
   ============================================= */

.page-about {
  /* Near-white surface (--abt-surface) is a global token in base.css so
     chapter cards lift off the parchment page */
  --abt-ease: var(--ease-spring);
  /* Shared page gutter — chapters 1 and 2 keep identical side margins so
     their content edges line up down the page */
  --abt-gutter: clamp(40px, 7vw, 130px);
  /* How far the chapter text columns travel horizontally on reveal */
  --abt-slide-in: clamp(40px, 6vw, 90px);
  /* Contain child margins so the first chapter keeps its gap below the banner */
  display: flow-root;
}

/* ---------------------------------------------
   Scroll reveal — text columns fade + rise
   --------------------------------------------- */
.abt-reveal > * {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity var(--anim-base) var(--abt-ease),
    transform var(--anim-base) var(--abt-ease);
  transition-delay: var(--reveal-delay, 0ms);
  /* Give the block its compositing layer *before* the reveal. Without it,
     iOS Safari creates the layer the moment the transition starts and paints
     it whenever the main thread gets round to it -- during a flick that can
     be hundreds of ms, by which time the spring curve is mostly done and the
     block simply pops in. Pre-promoted, the backing store is already painted
     when the class lands. Text blocks: cheap to keep. */
  will-change: opacity, transform;
}
.abt-reveal.is-visible > * {
  opacity: 1;
  transform: none;
}
.abt-reveal > *:nth-child(1) { --reveal-delay: 0ms; }
.abt-reveal > *:nth-child(2) { --reveal-delay: var(--anim-stagger); }
.abt-reveal > *:nth-child(3) { --reveal-delay: calc(var(--anim-stagger) * 2); }
.abt-reveal > *:nth-child(4) { --reveal-delay: calc(var(--anim-stagger) * 3); }
.abt-reveal > *:nth-child(5) { --reveal-delay: calc(var(--anim-stagger) * 4); }
.abt-reveal > *:nth-child(6) { --reveal-delay: calc(var(--anim-stagger) * 5); }

/* Chapter 1 & 2: title, lead and CTA arrive together as one group,
   sliding horizontally, instead of staggering individually. The script
   sign-off line (typewriter) is excluded — it stays put and is typed
   out afterwards (see .abt-script below).

   Direction mirrors the layout: chapter 1's text column sits on the
   right, so it comes in from the right; chapter 2's sits on the left,
   opposite its image, so it comes in from the left. */
.abt-chapter__body.abt-reveal > .abt-title,
.abt-chapter__body.abt-reveal > .abt-lead,
.abt-chapter__body.abt-reveal > .abt-more-toggle {
  --reveal-delay: 0ms;
  transform: translateX(var(--abt-slide-in, 60px));
}
.abt-band__body.abt-reveal > .abt-title,
.abt-band__body.abt-reveal > .abt-lead,
.abt-band__body.abt-reveal > .abt-more-toggle {
  --reveal-delay: 0ms;
  transform: translateX(calc(-1 * var(--abt-slide-in, 60px)));
}
/* Higher specificity than the overrides above, so the slide actually
   completes instead of staying pinned off-axis once revealed */
.abt-chapter__body.abt-reveal.is-visible > .abt-title,
.abt-chapter__body.abt-reveal.is-visible > .abt-lead,
.abt-chapter__body.abt-reveal.is-visible > .abt-more-toggle,
.abt-band__body.abt-reveal.is-visible > .abt-title,
.abt-band__body.abt-reveal.is-visible > .abt-lead,
.abt-band__body.abt-reveal.is-visible > .abt-more-toggle {
  transform: none;
}
/* The script line is typed, not slid: it must hold its final position from
   the start so the typewriter writes into settled text. It only needs the
   group's opacity fade, which typewriter.css then takes over. */
.abt-chapter__body.abt-reveal > .abt-script,
.abt-band__body.abt-reveal > .abt-script {
  --reveal-delay: 0ms;
  transform: none;
}

/* Media reveal — fade in + settle */
.abt-reveal-media {
  opacity: 0;
  transform: scale(1.04);
  transition:
    opacity var(--anim-base) var(--abt-ease),
    transform var(--anim-slow) var(--abt-ease);
  will-change: opacity, transform; /* see .abt-reveal > * */
}
.abt-reveal-media.is-visible {
  opacity: 1;
  transform: none;
}

/* ---------------------------------------------
   Shared typography
   --------------------------------------------- */
.abt-title {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h2);
  line-height: 1.08;
  color: var(--color-charcoal);
  margin: 0;
}

.abt-lead {
  max-width: 54ch;
}
.abt-lead p {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: var(--fs-body);
  line-height: 1.75;
  color: var(--color-charcoal);
  margin: 0;
  text-align: justify;
  hyphens: manual;
}
.abt-lead p + p {
  margin-top: 14px;
}

/* Bővebben — underline CTA link to the section's subpage */
.abt-more-toggle {
  align-self: flex-start;
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-terracotta);
  text-decoration: none;
  padding: 4px 0;
  cursor: pointer;
  position: relative;
}
.abt-more-toggle::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--color-caramel);
  transform-origin: left;
  transition: transform 0.3s var(--abt-ease);
}
.abt-more-toggle:hover::after {
  transform: scaleX(0.4);
}

/* Script sign-off — typewriter target */
.abt-script {
  font-family: var(--font-script);
  font-weight: 500;
  font-size: var(--fs-script);
  line-height: 1.2;
  color: var(--color-charcoal);
  margin: clamp(6px, 1vh, 14px) 0 0;
}

/* ---------------------------------------------
   Chapter 1 — Történetünk: logo panel + body
   --------------------------------------------- */
/* Section stays full-bleed so the bg-sweep ::before spans the viewport;
   the content sits in a centered 1400px wrapper. */
.abt-chapter {
  position: relative;
  padding-bottom: 50px;
  overflow-x: clip; /* the body copy slides in from the right; never scroll the page */
}
.abt-chapter__inner {
  position: relative;
  max-width: 1400px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 40fr 60fr;
}
/* Near-white card wipes in from the left (bg-sweep ::before) */
.abt-chapter[data-bg-sweep] {
  --bg-sweep-color: var(--abt-surface);
}

.abt-chapter__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(48px, 7vh, 96px) clamp(32px, 4vw, 72px)
    clamp(48px, 7vh, 96px) var(--abt-gutter);
}
.abt-chapter__logo img {
  width: min(320px, 74%);
  height: auto;
  display: block;
}
/* Appearance: zooms in while the blur resolves, instead of the generic
   reveal-media fade + slight scale-down */
.abt-chapter__logo img.abt-reveal-media {
  opacity: 0;
  transform: scale(0.82);
  filter: blur(14px);
  transition:
    opacity var(--anim-slow) var(--abt-ease),
    transform var(--anim-slow) var(--abt-ease),
    filter var(--anim-slow) var(--abt-ease);
}
.abt-chapter__logo img.abt-reveal-media.is-visible {
  opacity: 1;
  transform: scale(1);
  filter: blur(0);
}

.abt-chapter__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(16px, 2.2vh, 26px);
  padding: clamp(56px, 8vh, 104px) var(--abt-gutter)
    clamp(56px, 8vh, 104px) 0;
}

/* ---------------------------------------------
   Chapter 2 — Szemléletünk: blush band + slideshow
   --------------------------------------------- */
.abt-band {
  position: relative;
  z-index: 1;
  overflow-x: clip; /* the media slides in from off-band; never scroll the page */
}

.abt-band__inner {
  position: relative;
  max-width: 1400px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 80fr 60fr;
  align-items: center;
}

.abt-band__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(16px, 2.2vh, 26px);
  padding: clamp(56px, 8vh, 104px) clamp(32px, 4vw, 72px)
    clamp(56px, 8vh, 104px) var(--abt-gutter);
}

/* Narrow portrait, right-aligned to the shared gutter so its right edge
   lines up with the chapter-1 text column above. Overhangs the band top
   and bottom. */
.abt-band__media {
  position: relative;
  align-self: stretch;
  justify-self: end;
  width: min(100%, clamp(270px, 31vw, 460px));
  margin: clamp(-56px, -6vh, -72px) var(--abt-gutter)
    clamp(-56px, -6vh, -72px) 0;
  min-height: clamp(440px, 62vh, 660px);
  overflow: hidden;
  background: linear-gradient(135deg, var(--color-blush), var(--color-sand));
}
/* Appearance: fade in while sliding in from the right */
.abt-band__media.abt-reveal-media {
  transform: translateX(clamp(48px, 7vw, 96px));
  transition:
    opacity var(--anim-slow) var(--abt-ease),
    transform var(--anim-slow) var(--abt-ease);
}
.abt-band__media.abt-reveal-media.is-visible {
  transform: none;
}

.abt-band__media img,
.abt-band__media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ---------------------------------------------
   Chapter 3 — Csapatunk: centered + full-bleed media
   --------------------------------------------- */
.abt-team {
  position: relative;
  padding-top: clamp(48px, 7vh, 88px);
  text-align: center;
}
/* Near-white sweep to match chapter 1 (bg-sweep ::before) */
.abt-team[data-bg-sweep] {
  --bg-sweep-color: var(--abt-surface);
}

.abt-team__head {
  max-width: 1400px;
  margin: 0 auto;
  padding: clamp(48px, 7vh, 88px) var(--abt-gutter) clamp(32px, 4vh, 48px);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: clamp(16px, 2vh, 24px);
}
/* Appearance: the head moves as one block — title, intro and CTA fade in
   together while drifting 20px top→bottom. Transform-only, so the section
   height never shifts during the animation. */
.abt-team__head.abt-reveal {
  opacity: 0;
  transform: translateY(-20px);
  transition:
    opacity var(--anim-base) var(--abt-ease),
    transform var(--anim-base) var(--abt-ease);
}
.abt-team__head.abt-reveal.is-visible {
  opacity: 1;
  transform: none;
}
/* Children ride along with the block instead of staggering individually */
.abt-team__head.abt-reveal > * {
  opacity: 1;
  transform: none;
  transition: none;
}
/* …except the title, which gets its own medium-intensity top→down rise:
   it starts well above its slot and glides down into place over the tail
   of the block's own drift. */
.abt-team__head.abt-reveal > .abt-title {
  opacity: 0;
  transform: translateY(-56px);
  transition:
    opacity var(--anim-base) var(--abt-ease),
    transform var(--anim-slow) var(--abt-ease);
}
.abt-team__head.abt-reveal.is-visible > .abt-title {
  opacity: 1;
  transform: none;
}

.abt-team__intro {
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  line-height: 1.75;
  color: var(--color-charcoal);
  margin: 0;
  max-width: none;
}
/* Runs the full content measure and is justified — the heading above stays
   centred, the copy and the CTA under it read as a left-aligned block. */
.abt-team__intro,
.abt-team .abt-lead p {
  text-align: justify;
  hyphens: manual;
}

.abt-team__media {
  position: relative;
  width: 100%;
  aspect-ratio: 32 / 7;
  overflow: hidden;
  background: linear-gradient(135deg, var(--color-blush), var(--color-clay));
}
.abt-team__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 35%;
  display: block;
}
/* Appearance: the band fades in at its final size while the photo inside
   settles back from a slight enlargement — a zoom-out, cropped by the
   frame's overflow: hidden so the section height never moves. */
.abt-team__media.abt-reveal-media {
  transform: none;
  transition: opacity var(--anim-base) var(--abt-ease);
}
.abt-team__media.abt-reveal-media img {
  transform: scale(1.14);
  transform-origin: center 35%;
  transition: transform var(--anim-slow) var(--abt-ease);
}
.abt-team__media.abt-reveal-media.is-visible img {
  transform: none;
}

.abt-team__script {
  position: relative;
  padding: 40px 0;
  margin: 0;
  bottom: -1px;
  background-color: var(--color-white);
}

/* The Csapatunk "Bővebben" link aligns to the left edge of the copy */
.abt-team__head .abt-more-toggle {
  align-self: flex-start;
}

/* =============================================
   Csapatunk subpage (includes/about/team.php)
   Three full-width member sections on a near-white canvas,
   alternating the portrait side. Each section pairs a tinted
   stage — cut-out portrait standing on its bottom edge, the
   member's name written above the figure in the script face
   at an angle — with a justified bio column. The middle
   section sits on a full-bleed band that wipes open left→right
   once reveal.js marks the row .in-view.
   ============================================= */
.page-team {
  background: var(--abt-surface);
  /* Band tone: parchment nudged toward charcoal — a soft greige
     one step darker than the near-white canvas */
  --team-band: color-mix(in oklch, var(--color-charcoal) 5%, var(--color-parchment));
  /* Panel behind a portrait — warmer, so the cut-out figure has
     something to stand against on the un-banded rows */
  --team-panel: color-mix(in oklch, var(--color-blush) 45%, var(--color-parchment));
  /* Tilt of the script name. One value for all three, so the
     rows read as the same hand. */
  --team-tilt: -6deg;
  /* A tilted name may poke past its stage by a few pixels. Clip,
     never scroll — `clip` rather than `hidden` so no scroll
     container is created. */
  overflow-x: clip;
}

.team-member {
  position: relative;
  /* No bottom padding: the portrait is bottom-aligned and stands on the
     section's lower edge, where the next section begins. The stacked
     breakpoint puts the padding back — see the 880px block. */
  padding: clamp(56px, 9vh, 104px) clamp(24px, 6vw, 96px) 0;
}

.team-member__inner {
  position: relative;
  z-index: 1; /* above the banded row's band */
  max-width: 1400px;
  margin: 0 auto;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: clamp(40px, 5vw, 80px);
}
/* Reversed row: portrait to the right, copy to the left */
.team-member--img-right .team-member__inner {
  flex-direction: row-reverse;
}

/* ---- Stage: panel + name + cut-out portrait ---- */
.team-member__stage {
  position: relative;
  /* The three layers below are ordered against each other and nothing else.
     The figure carries will-change: transform for its reveal, which promotes
     it to its own layer; isolating here means the panel / figure / name
     order holds whatever the compositor does with that promotion, so the
     name cannot end up behind the portrait mid-animation. */
  isolation: isolate;
  flex: 0 1 clamp(340px, 46vw, 660px);
  display: flex;
  flex-direction: column;
  /* The figure fills the width, so the stage width *is* the figure size;
     the name sits in flow above it and adds its own head-height band. */
}
.team-member__panel {
  position: absolute;
  z-index: 0;
  inset: 0;
}

/* Name — script, tilted, in flow above the portrait and painted in
   front of it, so no part of it is ever hidden by the figure. Centred
   over the stage; the tilt is purely visual (transform), so the line
   keeps its box and the figure below never shifts. */
.team-member__name {
  position: relative;
  z-index: 3;
  margin: 0 0 0.35em;
  padding: 0.25em 4% 0;
  text-align: center;
  white-space: nowrap;
  pointer-events: none;
  font-family: var(--font-script);
  font-weight: 500;
  font-size: var(--fs-script-lg);
  line-height: 1.1;
  color: color-mix(in oklch, var(--color-charcoal) 82%, transparent);
  transform: rotate(var(--team-tilt));
  transform-origin: center;
}

.team-member__media {
  position: relative;
  z-index: 1; /* above the panel, below the name */
  margin: 0;
  width: 100%;
}
/* The source is a transparent portrait cut-out that reaches its own
   bottom edge. Size the figure from the image itself (no forced box,
   no percentage height, no object-fit) so its foot lands exactly on
   the stage's — and the section's — lower edge with nothing under it. */
.team-member__media img {
  display: block;
  width: 100%;
  height: auto;
  margin-bottom: -1px;
}

/* ---- Copy column ---- */
.team-member__body {
  flex: 0 1 clamp(300px, 38vw, 560px);
  /* Rides against the middle of the portrait rather than its foot, and
     keeps its own air above the next section when the copy runs longer
     than the stage is tall. */
  align-self: center;
  padding-bottom: clamp(40px, 6vh, 80px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(16px, 2.6vh, 28px);
}
.team-member__lede {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h3);
  line-height: 1.3;
  color: var(--color-charcoal);
  margin: 0;
}
.team-member__bio {
  max-width: 58ch;
}

/* LinkedIn CTA — closes the column, aligned to its right edge */
.team-member__link {
  align-self: flex-end;
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-terracotta);
  text-decoration: none;
  padding-bottom: 3px;
  border-bottom: 1px solid color-mix(in oklch, var(--color-terracotta) 40%, transparent);
  transition: border-color 0.2s ease-out, color 0.2s ease-out;
}
.team-member__link:hover,
.team-member__link:focus-visible {
  border-bottom-color: var(--color-terracotta);
}

/* ---- Banded middle row ---- */
.team-member--banded {
  /* The band already carries the tone; a second rectangle behind
     the portrait would only muddy it */
  --team-panel: transparent;
}
/* Wipes open left→right when reveal.js marks the row .in-view.
   The observer must watch the row, not this span: a fully clipped
   element never intersects, so IO would never fire on it. */
.team-member__band {
  position: absolute;
  z-index: 0;
  inset: 0;
  background: var(--team-band);
  pointer-events: none;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--anim-slow) var(--ease-spring) 0.25s;
}
.team-member--banded.in-view .team-member__band {
  clip-path: inset(0 0 0 0);
}

/* Directional reveal: whatever sits in the left column slides in
   from the left, the right column from the right. The portrait
   side flips per row, so map the translate by row modifier rather
   than by media/text. The .is-visible resets carry higher
   specificity and follow, so the slide completes instead of
   pinning at the offset. */
.team-member--img-left .team-member__media.abt-reveal-media,
.team-member--img-right .team-member__body.abt-reveal > * {
  transform: translateX(-56px);
}
.team-member--img-right .team-member__media.abt-reveal-media,
.team-member--img-left .team-member__body.abt-reveal > * {
  transform: translateX(56px);
}
.team-member--img-left .team-member__media.abt-reveal-media.is-visible,
.team-member--img-right .team-member__media.abt-reveal-media.is-visible,
.team-member--img-left .team-member__body.abt-reveal.is-visible > *,
.team-member--img-right .team-member__body.abt-reveal.is-visible > * {
  transform: none;
}

/* ---------------------------------------------
   Responsive — stack under 880px
   --------------------------------------------- */
@media (max-width: 880px) {
  .team-member {
    padding-bottom: clamp(56px, 9vh, 104px);
  }
  .team-member__inner,
  .team-member--img-right .team-member__inner {
    flex-direction: column;
    align-items: center;
    gap: clamp(24px, 5vw, 36px);
  }
  .team-member__stage,
  .team-member__body {
    flex-basis: auto;
    align-self: center;
    padding-bottom: 0;
    width: 100%;
    max-width: 520px;
  }
  /* Narrow stage: let a long name wrap instead of running off-screen
     (the page clips horizontal overflow, so an unwrapped name would
     simply lose its ends) */
  .team-member__name {
    white-space: normal;
  }
  /* Floor line. Side by side, the portrait's foot stands on the next
     section's top edge; stacked, the copy follows straight under it and
     the cut-out reads as clipped. A single hairline across the stage's
     lower edge gives the figure something to stand on. Team page only:
     the service-detail rows share these classes but carry framed
     photos, not cut-outs. */
  .page-team .team-member__stage {
    border-bottom: 1px solid var(--color-sand);
    margin-bottom: var(--space-xs);
  }
}

@media (prefers-reduced-motion: reduce) {
  .team-member__band {
    transition: none;
    clip-path: none;
  }
  .team-member--img-left .team-member__media.abt-reveal-media,
  .team-member--img-right .team-member__media.abt-reveal-media,
  .team-member--img-left .team-member__body.abt-reveal > *,
  .team-member--img-right .team-member__body.abt-reveal > * {
    transform: none;
  }
}

/* =============================================
   Service detail rows (includes/services/service-detail.php)
   The three alternating portrait/text rows that the marketing,
   design and construction subpages render. This was originally
   the Csapatunk layout, shared by class name; Csapatunk has since
   moved to its own full-width section layout above, so the rows
   keep their old markup under their own page scope
   (.page-service-rows) instead.

   Near-white canvas, flexbox rows that interlock vertically
   (collage rhythm); a full-bleed greige band sweeps in left→right
   behind the middle row, reaching up and down behind the
   neighbouring portraits.
   ============================================= */
.page-service-rows {
  background: var(--abt-surface);
  /* Band tone: parchment nudged toward charcoal — reads as a
     soft greige a step darker than the near-white canvas */
  --team-band: color-mix(in oklch, var(--color-charcoal) 5%, var(--color-parchment));
}

.page-service-rows .team-list {
  max-width: 980px;
  margin: 0 auto;
  padding: clamp(56px, 9vh, 110px) clamp(24px, 6vw, 56px)
    clamp(64px, 10vh, 130px);
  display: flex;
  flex-direction: column;
  /* Rows touch; the collage rhythm comes from the banded
     row's negative margins, not from a list gap */
  gap: 0;
}

/* ---- Row: portrait pinned to one edge, text beside it ---- */
.page-service-rows .team-member {
  position: relative;
  z-index: 1; /* rows paint above the middle row's band */
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: clamp(48px, 8vw, 96px);
}
/* Reversed row: portrait pins to the right edge, text floats left of it */
.page-service-rows .team-member--img-right {
  flex-direction: row-reverse;
}

/* ---- Portrait ---- */
.page-service-rows .team-member__media {
  flex: 0 1 clamp(300px, 30vw, 410px);
  margin: 0;
  aspect-ratio: 7 / 10;
  overflow: hidden;
  background: var(--team-band);
}
.page-service-rows .team-member__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ---- Text column — always left-aligned, justified body ---- */
.page-service-rows .team-member__body {
  flex: 0 1 clamp(280px, 28vw, 380px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(18px, 3.5vh, 34px);
}
/* Collage offsets: the first row's text rides high beside its
   portrait, the last row's settles low; the banded middle row
   stays vertically centered. */
.page-service-rows .team-member:first-child .team-member__body {
  align-self: flex-start;
  padding-top: clamp(24px, 6vh, 56px);
}
.page-service-rows .team-member:last-child .team-member__body {
  align-self: flex-end;
  padding-bottom: clamp(16px, 4vh, 40px);
}

/* Title — script sign-off, soft charcoal (not the terracotta CTA tone) */
.page-service-rows .team-member__name {
  font-family: var(--font-script);
  font-weight: 500;
  font-size: var(--fs-script);
  line-height: 1.1;
  color: color-mix(in oklch, var(--color-charcoal) 80%, transparent);
  margin: 0;
}

.page-service-rows .team-member__bio {
  max-width: 40ch;
}

/* ---- Banded middle row ---- */
.page-service-rows .team-member--banded {
  z-index: 0; /* whole row, band included, sits behind its neighbours */
  /* Interlock: pull the row into the rows above and below so the
     alternating portraits stagger past each other */
  margin-top: clamp(-36px, -3vh, -16px);
  margin-bottom: clamp(-36px, -3vh, -16px);
}

/* Full-bleed band. Breaks out of .team-list to span the viewport
   and reaches past the row so it runs behind the bottom of the
   previous portrait and the top of the next one. Wipes open
   left→right when reveal.js marks the parent row .in-view — the
   observer must watch the row, not the span: a fully clipped
   element never intersects, so IO would never fire on the span
   itself. */
.page-service-rows .team-member__band {
  position: absolute;
  z-index: -1;
  top: clamp(-56px, -5vh, -32px);
  bottom: clamp(-56px, -5vh, -32px);
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  background: var(--color-parchment);
  pointer-events: none;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--anim-slow) var(--ease-spring) 0.25s;
}
.page-service-rows .team-member--banded.in-view .team-member__band {
  clip-path: inset(0 0 0 0);
}

/* Load cascade — row 1 reveals, the band sweeps, then rows 2 and 3
   follow, so the sequence still reads when the whole page fits in
   the first viewport. */
.page-service-rows .team-member:nth-child(2) { --team-delay: 350ms; }
.page-service-rows .team-member:nth-child(3) { --team-delay: 750ms; }
.page-service-rows .abt-reveal-media {
  transition-delay: var(--team-delay, 0ms);
}
.page-service-rows .abt-reveal > * {
  transition-delay: calc(var(--team-delay, 0ms) + var(--reveal-delay, 0ms));
}

/* Directional reveal (mirrors story.php): the element in the left column
   slides in from the left, the element in the right column from the right.
   The portrait side flips per row, so map the translate by row modifier
   rather than by media/text. .is-visible resets carry higher specificity
   and follow the from-states, so the slide completes instead of pinning. */
.page-service-rows .team-member--img-left .team-member__media.abt-reveal-media,
.page-service-rows .team-member--img-right .team-member__body.abt-reveal > * {
  transform: translateX(-64px);
}
.page-service-rows .team-member--img-right .team-member__media.abt-reveal-media,
.page-service-rows .team-member--img-left .team-member__body.abt-reveal > * {
  transform: translateX(64px);
}
.page-service-rows .team-member--img-left .team-member__media.abt-reveal-media.is-visible,
.page-service-rows .team-member--img-right .team-member__media.abt-reveal-media.is-visible,
.page-service-rows .team-member--img-left .team-member__body.abt-reveal.is-visible > *,
.page-service-rows .team-member--img-right .team-member__body.abt-reveal.is-visible > * {
  transform: none;
}

/* ---------------------------------------------
   Responsive — stack under 880px
   --------------------------------------------- */
@media (max-width: 880px) {
  .page-service-rows .team-list {
    gap: clamp(44px, 8vh, 72px);
  }
  .page-service-rows .team-member,
  .page-service-rows .team-member--img-right {
    flex-direction: column;
    align-items: center;
    gap: clamp(20px, 5vw, 32px);
  }
  .page-service-rows .team-member__media {
    flex-basis: auto;
    aspect-ratio: 4 / 5;
    width: 100%;
    max-width: 440px;
  }
  .page-service-rows .team-member__body,
  .page-service-rows .team-member:first-child .team-member__body,
  .page-service-rows .team-member:last-child .team-member__body {
    flex-basis: auto;
    align-self: center;
    padding: 0;
    width: 100%;
    max-width: 440px;
  }
  /* No interlock when stacked — the band simply wraps its row */
  .page-service-rows .team-member--banded {
    margin-top: 0;
    margin-bottom: 0;
  }
  .page-service-rows .team-member__band {
    top: clamp(-40px, -4vh, -24px);
    bottom: clamp(-40px, -4vh, -24px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .page-service-rows .team-member__band {
    transition: none;
    clip-path: none;
  }
  .page-service-rows .abt-reveal-media,
  .page-service-rows .abt-reveal > * {
    transition-delay: 0ms;
  }
}
.page-story {
  background: var(--color-parchment);
}

.story-intro {
  max-width: 1140px;
  margin: 0 auto;
  padding: clamp(64px, 9vh, 104px) clamp(24px, 6vw, 56px)
    clamp(56px, 8vh, 92px);
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  gap: clamp(48px, 7vw, 90px);
}

/* ---- Portrait — 7:10, pinned to the left edge ---- */
.story-intro__media {
  flex: 0 1 clamp(300px, 31vw, 400px);
  margin: 0;
  aspect-ratio: 7 / 10;
  overflow: hidden;
  background: color-mix(in oklch, var(--color-clay) 30%, var(--color-parchment));
}
.story-intro__media img,
.story-intro__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ---- Text column — lede + justified story paragraphs ---- */
.story-intro__body {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(26px, 4.5vh, 44px);
}

/* The subpage title. It is set left, never justified — it used to sit in
   base.css's shared body-copy block, which stretched a two-line title across
   the column. --fs-h3 rather than --fs-h2 for the same brief: at h2 the
   34ch measure came out visibly wider than the 54ch body block beneath it,
   and the title ran to three lines. At h3 the same 34ch is narrower than
   the copy, which is where the client wants it. */
.story-intro__lede {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h3);
  line-height: 1.35;
  color: var(--color-charcoal);
  text-align: left;
  margin: 0;
}

/* Story page only: the portrait matches the text column's height
   instead of its own 7:10 box, so both columns end on the same line.
   Scoped above 880px — stacked, the fixed 4:5 crop is still right. */
@media (min-width: 881px) {
  .page-story .story-intro {
    align-items: stretch;
  }
  .page-story .story-intro__media {
    aspect-ratio: auto;
    align-self: stretch;
    min-height: 0;
  }
}

/* Directional reveal: portrait slides in from the left,
   text column slides in from the right (mirrored pair).
   The .is-visible resets need equal-or-higher specificity than
   the generic .abt-reveal(.is-visible) rules AND must come after
   the from-state below, or the transform stays pinned (no slide). */
.story-intro__media.abt-reveal-media {
  transform: translateX(-64px);
}
.story-intro__media.abt-reveal-media.is-visible {
  transform: none;
}
.story-intro__body.abt-reveal > * {
  transform: translateX(64px);
}
.story-intro__body.abt-reveal.is-visible > * {
  transform: none;
}

/* Reveal order from the reference: text rises first,
   the portrait fades/settles in a beat later */
.page-story .abt-reveal-media {
  transition-delay: 350ms;
}

/* ---------------------------------------------
   Szemléletünk (vision) — reuses the .story-intro layout, but the
   section carries a near-white bg-sweep and the text column swipes in
   right→left as one block while the typewriter types it out.
   --------------------------------------------- */
.page-vision {
  background: var(--color-parchment);
}

/* Full-bleed left→right sweep in the near-white surface tone (matches
   About ch.1/3). The sweep sits on a full-width wrapper — .story-intro
   is a centered max-width box, so sweeping it directly would leave the
   page gutters uncovered. */
.page-vision .story-sweep[data-bg-sweep] {
  --bg-sweep-color: var(--abt-surface);
}

/* The image still slides in from the left (shared rule above); the text
   column swipes in right→left as ONE block while the typewriter types.
   The per-child translate is killed — otherwise each paragraph would slide
   independently under the caret — and the slide moves to the column itself,
   which needs its own transition (the shared one lives on the children). */
.page-vision .story-intro__body.abt-reveal {
  opacity: 0;
  transform: translateX(64px);
  transition:
    opacity var(--anim-base) var(--abt-ease),
    transform var(--anim-base) var(--abt-ease);
}
.page-vision .story-intro__body.abt-reveal.is-visible {
  opacity: 1;
  transform: none;
}
/* Children carry nothing of their own — the shared .abt-reveal > * fade and
   its nth-child stagger would otherwise let the paragraphs arrive one by one
   inside a column that is already moving. */
.page-vision .story-intro__body.abt-reveal > *,
.page-vision .story-intro__body.abt-reveal.is-visible > * {
  opacity: 1;
  transform: none;
  transition: none;
  transition-delay: 0ms;
}

/* Wider portrait than Történetünk, but NOT stretched: five paragraphs of copy
   would drag the image past 1200px tall. It keeps a 4:5 crop capped to the
   viewport and sticks under the fixed nav, so it stays beside the text the
   whole way down instead of leaving a hole under a top-aligned box. */
.page-vision .story-intro {
  max-width: 1320px;
}
/* Scoped above 880px: below it the stacked rules take over, and they are the
   weaker selector — an unscoped .page-vision override would keep the sticky
   side-column sizing on mobile. */
@media (min-width: 881px) {
  .page-vision .story-intro__media {
    flex: 0 1 clamp(340px, 42vw, 560px);
    align-self: flex-start;
    aspect-ratio: 4 / 5;
    max-height: min(74vh, 700px);
    position: sticky;
    top: calc(var(--nav-height) + var(--space-md));
  }
}

/* ---------------------------------------------
   Ingatlan Management (includes/services/management.php) — Szemléletünk's
   sweep and one-block reveal, but a fraction of its copy. The vision
   portrait is a sticky 4:5 crop up to 700px tall, which here towers ~300px
   past the text and leaves a dead block at the bottom of the section.
   Fall back to the Történetünk treatment: a normal-width portrait stretched
   to the text column, so both columns end on the same line.
   --------------------------------------------- */
.page-vision.page-mgmt .story-intro {
  max-width: 1140px;
  /* One row, no sign-off band below it: the shared 56–92px floor left a
     bare strip between the copy and the newsletter block. Keep only enough
     for the sweep edge to clear the text. */
  padding-bottom: clamp(24px, 3vh, 40px);
}
/* The lede is the page's title here, not a pull line — section-title size */
.page-vision.page-mgmt .story-intro__lede {
  font-size: var(--fs-h2);
  line-height: 1.2;
}
/* Scoped above 880px — stacked, the shared responsive rules are right */
@media (min-width: 881px) {
  .page-vision.page-mgmt .story-intro {
    align-items: stretch;
  }
  .page-vision.page-mgmt .story-intro__media {
    flex: 0 1 clamp(300px, 31vw, 400px);
    position: static;
    aspect-ratio: auto;
    align-self: stretch;
    max-height: none;
    min-height: 0;
  }
}

/* ---- Full-bleed white sign-off band ----
   The white surface is what makes the picture-plus-copy row above and this
   line read as two consecutive blocks rather than one long parchment field
   with a sentence adrift at the bottom of it. The padding is roughly half
   what it was: on Szemléletünk the space under the line was reading as the
   end of the page while the newsletter card was still to come. */
.story-band {
  background-color: var(--color-white);
  padding: clamp(28px, 4.5vh, 52px) clamp(24px, 6vw, 56px);
  text-align: center;
}

/* Ink-toned script (not the terracotta CTA tone). --fs-quote, not
   --fs-script: at script size the longer sign-offs ran past the measure
   and broke badly; the balance keeps the last line off an orphan. */
.story-band__script {
  font-size: var(--fs-quote);
  color: color-mix(in oklch, var(--color-charcoal) 85%, transparent);
  max-width: 30ch;
  margin: 0 auto;
  text-wrap: balance;
}

/* About sign-offs (Történetünk + Szemléletünk): one centred line at script
   size. The measure cap and the balance are what forced the smaller
   --fs-quote; with the line held on one row neither applies, so it can take
   --fs-script — the longest motto (65 chars) still clears the gutters at
   every width in this range. Wrapping returns below 880px, where nowrap
   would run off the screen. */
@media (min-width: 881px) {
  .page-about .story-band__script {
    font-size: var(--fs-script);
    max-width: none;
    white-space: nowrap;
    text-wrap: nowrap;
  }
}

/* ---------------------------------------------
   Responsive — stack under 880px
   --------------------------------------------- */
@media (max-width: 880px) {
  .story-intro {
    flex-direction: column;
    align-items: center;
    gap: clamp(28px, 6vw, 40px);
  }
  .story-intro__media {
    flex-basis: auto;
    aspect-ratio: 4 / 5;
    width: 100%;
    max-width: 440px;
  }
  .story-intro__body {
    width: 100%;
    max-width: 440px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .page-story .abt-reveal-media {
    transition-delay: 0ms;
  }
}

/* ---------------------------------------------
   Responsive — About chapters stack under 880px
   --------------------------------------------- */
@media (max-width: 880px) {
  .abt-chapter__inner,
  .abt-band__inner {
    grid-template-columns: 1fr;
    min-height: 0;
  }
  .abt-chapter__logo {
    padding: clamp(40px, 12vw, 72px) clamp(24px, 8vw, 64px) 0;
  }
  .abt-chapter__logo img {
    width: min(240px, 60%);
  }
  .abt-chapter__body,
  .abt-band__body {
    padding: clamp(32px, 6vh, 56px) clamp(24px, 7vw, 48px);
  }
  .abt-team__head {
    padding: clamp(32px, 6vh, 56px) clamp(24px, 7vw, 48px);
  }
  .abt-band__media {
    order: -1;
    width: auto;
    justify-self: stretch;
    margin: 0;
    min-height: 0;
    aspect-ratio: 4 / 3;
  }
  .abt-team__media {
    aspect-ratio: 8 / 3;
  }
}

/* ---------------------------------------------
   Reduced motion
   --------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .abt-reveal > *,
  .abt-reveal-media,
  .abt-band__media.abt-reveal-media,
  .abt-team__head.abt-reveal,
  .abt-team__head.abt-reveal > .abt-title,
  .abt-team__media.abt-reveal-media img,
  .abt-chapter__body.abt-reveal > *,
  .abt-band__body.abt-reveal > *,
  .page-vision .story-intro__body.abt-reveal {
    opacity: 1;
    transform: none;
    filter: none;
    clip-path: none;
    transition: none;
  }
}

/* ---------------------------------------------
   Video frames — the clips are 2:3 portraits (--ratio-video). A frame
   holding one takes the clip's own ratio and stops stretching to the
   text beside it, so nothing is cropped; contain is the safety net for
   the last sub-pixel. Photos in the same frames keep their crops.
   --------------------------------------------- */
.abt-band__media video,
.story-intro__media video {
  object-fit: contain;
}
.abt-band__media:has(> video) {
  align-self: center;
  min-height: 0;
  aspect-ratio: var(--ratio-video);
}
.story-intro__media:has(> video),
.page-story .story-intro__media:has(> video),
.page-vision .story-intro__media:has(> video) {
  align-self: flex-start;
  aspect-ratio: var(--ratio-video);
}
/* Story page: the clip fills the text column's height instead of its own
   2:3 box, so both columns end on the same line — cover, not contain,
   because a stretched frame letterboxes otherwise. The basis stays narrow
   enough that the copy beside it keeps a readable measure. */
@media (min-width: 881px) {
  .page-story .story-intro__media:has(> video) {
    align-self: stretch;
    aspect-ratio: auto;
    min-height: 0;
    flex: 0 1 clamp(320px, 33vw, 420px);
  }
  .page-story .story-intro__media video {
    object-fit: cover;
  }
}

/* Sticky vision portrait: width is whichever is smaller — the column's
   share, or what the viewport-capped height allows at 2:3. */
@media (min-width: 881px) {
  .page-vision .story-intro__media:has(> video) {
    flex-basis: min(clamp(340px, 42vw, 560px), calc(min(74vh, 700px) * 2 / 3));
  }
  /* Management page: its stretched-to-text override outranks the shared
     rule above, so the video frame is pinned to 2:3 here as well. */
  .page-vision.page-mgmt .story-intro__media:has(> video) {
    align-self: flex-start;
    aspect-ratio: var(--ratio-video);
  }
}
@media (max-width: 880px) {
  .abt-band__media:has(> video) {
    justify-self: center;
    width: min(100%, 440px);
    aspect-ratio: var(--ratio-video);
  }
}
