/* =============================================
   SECTIONS
   About, Properties, Services, News, Contact.
   Each section is self-contained.
   ============================================= */

/* =============================================
   PROPERTIES CATALOGUE
   Listing page: 3-column grid, no cards.
   ============================================= */

.prop-catalogue__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: clamp(32px, 4vw, 64px);
  row-gap: clamp(64px, 8vh, 100px);
  padding: clamp(48px, 6vh, 80px) clamp(48px, 6vw, 96px) clamp(80px, 10vh, 120px);
  background-color: var(--color-parchment);
}

/* ---- Single property entry ---- */
.prop-entry__link {
  display: flex;
  flex-direction: column;
  gap: 0;
  text-decoration: none;
  color: inherit;
}

.prop-entry__photo-wrap {
  aspect-ratio: 4 / 5;
  overflow: hidden;
  width: 100%;
  margin-bottom: clamp(16px, 2.5vh, 24px);
}

.prop-entry__photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  transform: scale(1);
  transition: transform 0.6s var(--ease-spring);
}

.prop-entry__link:hover .prop-entry__photo {
  transform: scale(1.03);
}

.prop-entry__meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.prop-entry__title {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h3);
  line-height: 1.15;
  color: var(--color-charcoal);
}

.prop-entry__address {
  font-family: var(--font-sans);
  font-size: var(--fs-label-sm);
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-charcoal);
  margin-top: 2px;
}

.prop-entry__specs {
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 300;
  letter-spacing: 0.05em;
  color: var(--color-charcoal);
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
}

.prop-entry__dot {
  color: var(--color-clay);
}

.prop-entry__icons {
  list-style: none;
  margin: clamp(4px, 0.6vh, 8px) 0 0;
  padding: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: clamp(12px, 1.8vw, 20px);
  border-top: 1px solid color-mix(in oklch, var(--color-clay) 22%, transparent);
  padding-top: clamp(10px, 1.4vh, 14px);
}

.prop-entry__icons li {
  display: flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 400;
  color: var(--color-charcoal);
  white-space: nowrap;
}

.prop-entry__icons li i {
  font-size: 20px;
  color: var(--color-terracotta);
  flex-shrink: 0;
  position: relative;
  top: -1px;
}

.prop-entry__price {
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 300;
  color: var(--color-clay);
}

.prop-entry__link:hover .prop-entry__cta {
  opacity: 0.65;
}

/* =============================================
   ABOUT
   ============================================= */

.about-section {
  padding: clamp(56px, 8vh, 96px) 0;
  background-color: var(--color-parchment);
}

.about-story {
  position: relative;
  width: min(1200px, 96%);
  margin: 0 auto;
}

.about-story__visual {
  width: 100%;
  min-height: clamp(520px, 68vh, 760px);
  background-image: url('../images/web04.jpg');
  background-size: cover;
  background-position: center;
}

.about-story__panel {
  position: absolute;
  right: clamp(-40px, -3vw, -16px);
  bottom: 90px;
  width: min(440px, 40%);
  background-color: rgba(33, 33, 33, 0.72);
  -webkit-backdrop-filter: blur(14px) saturate(1.15);
  backdrop-filter: blur(2px) saturate(1.15);
  padding: clamp(28px, 3.5vw, 48px);
}

.about-story__rule {
  border: none;
  opacity: 0.45;
  margin: 0 0 clamp(14px, 2vh, 22px);
}

.about-story__heading {
  font-family: var(--font-serif);
  font-weight: 500;
  font-style: italic;
  font-size: var(--fs-h2);
  line-height: 1.12;
  color: white;
  margin-bottom: clamp(12px, 1.8vh, 20px);
}

.about-story__body {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.65;
  color: white;
  max-width: 52ch;
  text-align: justify;
  hyphens: manual;
}

.about-story__body p + p {
  margin-top: 1.25em;
}

.about-story__cta {
  margin-top: clamp(20px, 3vh, 30px);
}

.about-story__cta.cta-link--light {
  color: var(--color-terracotta);
  border-bottom-color: var(--color-terracotta);
}

/* ---- About Philosophy — Homepage Block 2 ---- */

.about-philosophy {
  background-color: var(--color-parchment);
  padding: clamp(80px, 11vh, 130px) clamp(24px, 6vw, 96px);
}

.about-philosophy__inner {
  display: grid;
  grid-template-columns: 6fr 5fr;
  column-gap: clamp(48px, 6vw, 96px);
  align-items: center;
  max-width: 1400px;
  margin: 0 auto;
}

/* The measure lives here, not on the children: `ch` resolves against the
   element's own font, so 52ch on the script signature is nearly twice the
   52ch of the sans paragraph and the right-aligned line ran out past it.
   Capping the shared parent (sans, 1rem) gives both the same right edge. */
.about-philosophy__text {
  text-align: left;
  max-width: 52ch;
}

.about-philosophy__heading {
  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-bottom: clamp(20px, 3vh, 32px);
}

.about-philosophy__body {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.75;
  color: var(--color-charcoal);
  max-width: 100%;
  text-align: justify;
  hyphens: manual;
}

/* Flush right, under the body copy. The parent in the selector is needed:
   .cta-link is defined later at the same specificity and its inline-block
   would otherwise cancel the auto margin. */
.about-philosophy__reveal .about-philosophy__cta {
  display: block;
  width: fit-content;
  margin: clamp(20px, 3vh, 30px) 0 0 auto;
}

/* Right edge is the parent's measure, so the script line closes flush with
   the paragraph above it. */
.about-philosophy__signature {
  font-family: var(--font-script);
  font-weight: 500;
  font-size: var(--fs-script);
  color: var(--color-charcoal);
  text-align: right;
  max-width: 100%;
  margin: clamp(32px, 5vh, 56px) 0 0;
}

/* ---- Reveal wrapper: body + CTA sweep together, heading slides in ---- */
.about-philosophy__text.animate-pending .about-philosophy__heading {
  opacity: 0;
  transform: translateX(-48px);
}

.about-philosophy__text.in-view .about-philosophy__heading {
  animation: slide-from-left var(--anim-base) var(--ease-spring) both;
}

.about-philosophy__reveal {
  position: relative;
  overflow: hidden;
}

.about-philosophy__sweep {
  position: absolute;
  inset: 0;
  z-index: 3;
  background-color: var(--color-parchment);
  pointer-events: none;
  transform: translateX(101%);
}

.about-philosophy__text.animate-pending .about-philosophy__sweep {
  transform: translateX(0);
}

.about-philosophy__text.in-view .about-philosophy__sweep {
  animation: sweep-reveal-local var(--anim-slow) var(--ease-spring) 350ms both;
}

@keyframes sweep-reveal-local {
  from { transform: translateX(0); }
  to   { transform: translateX(101%); }
}

@media (prefers-reduced-motion: reduce) {
  .about-philosophy__text.animate-pending .about-philosophy__heading {
    opacity: 1;
    transform: none;
  }
  .about-philosophy__text.in-view .about-philosophy__heading {
    animation: none;
  }
  .about-philosophy__sweep {
    display: none;
  }
}

.about-philosophy__media {
  width: 100%;
  overflow: hidden;
}

/* The portrait arrives from the right as the text slides in from the left. */
.about-philosophy__media.animate-pending {
  opacity: 0;
  transform: translateX(48px);
}

.about-philosophy__media.in-view {
  animation: slide-from-right var(--anim-slow) var(--ease-spring) var(--anim-stagger) both;
}

@media (prefers-reduced-motion: reduce) {
  .about-philosophy__media.animate-pending {
    opacity: 1;
    transform: none;
  }
  .about-philosophy__media.in-view {
    animation: none;
  }
}

/* Full photo, never cropped: the image sets its own height. */
.about-philosophy__img {
  display: block;
  width: 100%;
  height: auto;
}

/* ---- About full page (about.php) ---- */

.about-full {
  padding: clamp(72px, 10vh, 120px) 0 clamp(96px, 14vh, 160px);
}

.about-pair {
  display: grid;
  grid-template-columns: 3fr 2fr;
  margin: 0 auto;
  padding: 0 clamp(24px, 5vw, 80px);
}

.about-pair + .about-pair {
  margin-top: clamp(80px, 12vh, 140px);
}

.about-pair__photo {
  margin: 0;
  padding-right: clamp(32px, 4vw, 64px);
}

.about-pair__photo img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}

.about-pair__text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-left: clamp(8px, 2vw, 24px);
}

.about-pair__label {
  font-family: var(--font-sans);
  font-size: var(--fs-label-sm);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-terracotta);
  margin: 0 0 clamp(10px, 1.5vh, 18px);
}

.about-pair__heading {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h2);
  color: var(--color-charcoal);
  line-height: 1.05;
  margin: 0 0 clamp(20px, 3vh, 36px);
}

.about-pair__body {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.75;
  color: var(--color-charcoal);
  max-width: 100%;
  text-align: justify;
  hyphens: manual;
}

.about-pair__body p + p {
  margin-top: 1.2em;
}

/* =============================================
   PROPERTIES HIGHLIGHT
   ============================================= */

.prop-highlight {
  padding: clamp(56px, 8vh, 96px) 0 80px;
  background-color: var(--color-white);
}

/* Header and footer share the grid's gutter so the label lines up with the
   first tile's left edge. */
.prop-highlight__header {
  padding: 0 24px clamp(18px, 2vh, 30px);
}

.prop-highlight__label {
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-charcoal);
}

/* ---- Tile row ----
   Every tile is sized for a full row of --tile-cols (6 across on desktop,
   fewer on narrower screens -- see responsive.css), whatever the admin has
   selected. A shorter selection keeps the same tile size and is centred,
   instead of stretching one or two tiles across the whole width. */
.prop-highlight__grid {
  --tile-cols: 6;
  --tile-gap: clamp(6px, 0.8vw, 12px);
  position: relative;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--tile-gap);
  padding: 0 24px;
  /* Contains the curtain once it has been pulled past the right edge. */
  overflow: hidden;
}

/* A shorter row is centred, so the label follows it. */
.prop-highlight--partial .prop-highlight__header {
  text-align: center;
}

/* ---- Left-to-right curtain ----
   One opaque panel covers the whole row and is pulled off to the right, so
   the tiles and their names are uncovered by a single front. Per-tile
   staggering was tried first and never read as synchronised -- neighbouring
   tiles were visibly at different stages of their own reveal. The tiles
   themselves are not animated: whatever the curtain has passed is simply
   there. */
.prop-highlight__grid.animate-pending::after,
.prop-highlight__grid.in-view::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  background-color: var(--color-white);
  pointer-events: none;
}

.prop-highlight__grid.animate-pending::after {
  transform: translateX(0);
}

.prop-highlight__grid.in-view::after {
  animation: prop-curtain-right var(--anim-slow) var(--ease-spring) both;
}

@keyframes prop-curtain-right {
  from { transform: translateX(0); }
  to   { transform: translateX(101%); }
}

@media (prefers-reduced-motion: reduce) {
  .prop-highlight__grid.animate-pending::after,
  .prop-highlight__grid.in-view::after {
    display: none;
  }
}

.prop-tile {
  position: relative;
  flex: 0 0 calc((100% - (var(--tile-cols) - 1) * var(--tile-gap)) / var(--tile-cols));
  aspect-ratio: 1 / 1;
  overflow: hidden;
  display: block;
  container-type: inline-size;
}

/* The uploader burns the WK Doma mark into the bottom-right corner of every
   cover photo (admin/src/services/watermark.js), and it reads as clutter under
   the script name. These tiles are square crops of a much larger file, so the
   mark is simply cropped away rather than covered: the image box is pinned to
   the tile's top-left and --tile-zoom enlarges it past the mark where the
   source is too close to square to lose the corner by cropping alone. All
   three values are measured per image in properties-highlight.php.
   transform-origin must stay `top left` -- a centred hover scale would walk
   the visible window down and right, back onto the logo. */
.prop-tile__img {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(100% * var(--tile-zoom, 1));
  height: calc(100% * var(--tile-zoom, 1));
  object-fit: cover;
  object-position: var(--tile-pos-x, 0%) var(--tile-pos-y, 50%);
  transform-origin: top left;
  transition: transform 0.6s var(--ease-spring);
}

.prop-tile__veil {
  position: absolute;
  inset: 0;
  background-color: color-mix(in oklch, var(--color-obsidian) 52%, transparent);
  transition: background-color 0.35s ease-out;
}

.prop-tile:hover .prop-tile__veil {
  background-color: color-mix(in oklch, var(--color-obsidian) 24%, transparent);
}

.prop-tile:hover .prop-tile__img {
  transform: scale(1.03);
}

/* Centred with flex, not translate(-50%,-50%): the fade-up reveal below
   animates `transform`, and a translate used for centring would be wiped out
   by the keyframes (fill-mode both) -- the name then hangs off the tile's
   centre and is clipped by the tile's overflow. */
.prop-tile__label {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 4%;
  font-family: var(--font-script);
  /* --fs-script is the ceiling; in a six-across row a tile is only ~215px
     wide, and the full token size wraps a name into three ragged lines. */
  font-size: min(var(--fs-script), 15cqi);
  font-weight: 500;
  color: var(--color-white);
  text-align: center;
  pointer-events: none;
  line-height: 1.15;
}


/* ---- View All CTA ---- */
.prop-highlight__footer {
  text-align: center;
  padding-top: clamp(28px, 4vh, 48px);
}

.prop-highlight__cta {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-charcoal);
  border-bottom: 1px solid color-mix(in oklch, var(--color-caramel) 55%, transparent);
  padding-bottom: 2px;
  transition: opacity 0.2s ease-out;
}

.prop-highlight__cta:hover {
  opacity: 0.6;
}

/* ---- About entrance animations (triggered by .in-view on parent) ---- */
/* .animate-pending pre-hides children so there is no visible→hidden flash when .in-view fires */
.about-story.animate-pending .about-story__visual {
  opacity: 0;
  transform: translateX(-48px);
}
.about-story.animate-pending .about-story__panel {
  opacity: 0;
  transform: translateX(48px);
}

@keyframes slide-from-left {
  from { opacity: 0; transform: translateX(-48px); }
  to   { opacity: 1; transform: translateX(0); }
}

@keyframes slide-from-right {
  from { opacity: 0; transform: translateX(48px); }
  to   { opacity: 1; transform: translateX(0); }
}

.about-story.in-view .about-story__visual {
  animation: slide-from-left var(--anim-slow) var(--ease-spring) both;
}

.about-story.in-view .about-story__panel {
  animation: slide-from-right var(--anim-slow) var(--ease-spring) var(--anim-stagger) both;
}

/* ---- Shared keyframes ---- */
@keyframes fade-up {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---- News: heading zoom-out reveal ---- */
.news-section__header.animate-pending .news-section__label {
  opacity: 0;
  transform: scale(1.8);
}

@keyframes zoom-out-reveal {
  from { opacity: 0; transform: scale(1.8); }
  to   { opacity: 1; transform: scale(1); }
}

.news-section__header.in-view .news-section__label {
  animation: zoom-out-reveal var(--anim-slow) var(--ease-spring) both;
}

.news-section__header.animate-pending .news-section__intro {
  opacity: 0;
  transform: translateY(22px);
}

.news-section__header.in-view .news-section__intro {
  animation: fade-up var(--anim-base) var(--ease-spring) calc(var(--anim-stagger) * 2) both;
}

/* ---- News: per-item reveal ---- */
.news-card.animate-pending {
  opacity: 0;
  transform: translateY(22px);
}

.news-card.in-view {
  animation: fade-up var(--anim-base) var(--ease-spring) both;
}

/* No breakpoint on purpose: the cards stack on mobile, where arriving one
   after another reads even more clearly than it does in a row. */
.news-card:nth-child(2).in-view { animation-delay: var(--anim-stagger); }
.news-card:nth-child(3).in-view { animation-delay: calc(var(--anim-stagger) * 2); }
.news-card:nth-child(n+4).in-view { animation-delay: calc(var(--anim-stagger) * 3); }

/* "További cikkeink" — lands on the tail of the third card. */
.news-section__footer {
  text-align: center;
  padding-top: clamp(8px, 1.5vh, 20px);
}

.news-section__footer.animate-pending {
  opacity: 0;
  transform: translateY(22px);
}

.news-section__footer.in-view {
  animation: fade-up var(--anim-base) var(--ease-spring) calc(var(--anim-stagger) * 3) both;
}

/* ---- Properties catalogue: per-card lazy reveal, line by line ---- */
.prop-highlight__item.animate-pending {
  opacity: 0;
  transform: translateY(22px);
}

.prop-highlight__item.in-view {
  animation: fade-up var(--anim-base) var(--ease-spring) both;
}

.prop-highlight__item:nth-child(3n+2).in-view { animation-delay: var(--anim-stagger); }
.prop-highlight__item:nth-child(3n).in-view { animation-delay: calc(var(--anim-stagger) * 2); }

@media (prefers-reduced-motion: reduce) {
  .about-story.animate-pending .about-story__visual,
  .about-story.animate-pending .about-story__panel,
  .news-section__header.animate-pending .news-section__label,
  .news-section__header.animate-pending .news-section__intro,
  .news-card.animate-pending,
  .news-section__footer.animate-pending,
  .prop-highlight__item.animate-pending,
  .client-voices__panel.animate-pending .client-voices__item,
  .contact-left__heading.animate-pending {
    opacity: 1;
    transform: none;
  }
  .about-story.in-view .about-story__visual,
  .about-story.in-view .about-story__panel,
  .news-section__header.in-view .news-section__label,
  .news-section__header.in-view .news-section__intro,
  .news-card.in-view,
  .news-section__footer.in-view,
  .prop-highlight__item.in-view,
  .client-voices__panel.in-view .client-voices__item,
  .contact-left__heading.in-view {
    animation: none;
  }
}


.prop-rail-card {
  display: block;
  text-decoration: none;
}

.prop-rail-card__thumb-wrap {
  overflow: hidden;
  width: 100%;
}

.prop-rail-card__photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  transform: scale(1);
  transition: transform 0.6s var(--ease-spring);
}

.prop-rail-card:hover .prop-rail-card__photo {
  transform: scale(1.03);
}

.prop-rail-card__meta {
  padding-top: clamp(14px, 2vh, 22px);
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.2vh, 12px);
}

.prop-rail-card__location {
  font-family: var(--font-sans);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-terracotta);
  font-size: var(--fs-label-sm);
  margin: 0;
}

.prop-rail-card__name {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  color: var(--color-charcoal);
  font-size: var(--fs-h3);
  line-height: 1.15;
  margin: 0;
}

.prop-rail-card__excerpt {
  text-align: justify;
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 400;
  line-height: 1.65;
  color: var(--color-charcoal);
  max-width: 90%;
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.prop-rail-card__specs {
  list-style: none;
  margin: clamp(4px, 0.6vh, 8px) 0 0;
  padding: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: clamp(10px, 1.6vw, 22px);
  border-top: 1px solid color-mix(in oklch, var(--color-clay) 22%, transparent);
  padding-top: clamp(10px, 1.4vh, 14px);
}

.prop-rail-card__spec {
  display: flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 400;
  color: var(--color-charcoal);
  white-space: nowrap;
}

.prop-rail-card__spec i {
  font-size: 20px;
  color: var(--color-terracotta);
  flex-shrink: 0;
  position: relative;
  top: -1px;
}

.prop-rail-card__price {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--color-charcoal);
  margin: 0;
}

/* =============================================
   SERVICES — photo left, editorial list right
   ============================================= */

.services-section {
  background-color: var(--color-parchment);
  width: 100%;
}

.services-inner {
  padding: clamp(80px, 11vh, 130px) clamp(24px, 6vw, 96px);
  max-width: 1400px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 5fr 7fr;
  column-gap: clamp(48px, 6vw, 96px);
  align-items: center;
}

.services-media {
  width: 100%;
  aspect-ratio: 5 / 6;
  overflow: hidden;
}

.services-media__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* The video leads the section, sliding in from the left while the curtain
   on the right starts uncovering the copy. --anim-slow: large media. */
.services-media.animate-pending {
  opacity: 0;
  transform: translateX(-48px);
}

.services-media.in-view {
  animation: slide-from-left var(--anim-slow) var(--ease-spring) both;
}

.services-content {
  display: flex;
  flex-direction: column;
}

.services__label {
  font-family: var(--font-serif);
  font-weight: 500;
  font-style: italic;
  font-size: var(--fs-h2);
  line-height: 1.12;
  color: var(--color-charcoal);
  margin-bottom: clamp(12px, 1.8vh, 20px);
}

.services-intro {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.75;
  color: var(--color-charcoal);
  max-width: 58ch;
  text-align: justify;
  hyphens: manual;
}

/* ---- Curtain reveal: title + body uncover top-to-bottom together ---- */
.services-curtain-wrap {
  position: relative;
  overflow: hidden;
}

.services-curtain {
  position: absolute;
  inset: 0;
  z-index: 3;
  background-color: var(--color-parchment);
  pointer-events: none;
  transform: translateY(0);
}

.services-curtain-wrap.animate-pending .services-curtain {
  transform: translateY(0);
}

/* --anim-base, not --anim-slow: the client asked for the service list to
   start the moment the intro is readable, and the list is staggered off
   the same beat as this curtain. */
.services-curtain-wrap.in-view .services-curtain {
  animation: curtain-reveal-down var(--anim-base) var(--ease-spring) 200ms both;
}

@keyframes curtain-reveal-down {
  from { transform: translateY(0); }
  to   { transform: translateY(101%); }
}

/* ---- List: plain italic-serif items, slide-from-left one after another ---- */
.services-list {
  list-style: none;
  margin: clamp(32px, 5vh, 56px) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.6vh, 18px);
}

.services-list__item {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h3);
  line-height: 1.3;
  color: var(--color-charcoal);
}

.services-list__link {
  color: inherit;
  text-decoration: none;
  transition: color 0.2s ease-out;
}

.services-list__link:hover,
.services-list__link:focus-visible {
  color: var(--color-terracotta);
}

.services-list__item.animate-pending {
  opacity: 0;
  transform: translateX(-32px);
}

.services-list__item.in-view {
  animation: slide-from-left var(--anim-quick) var(--ease-spring) both;
  /* The bullets follow the intro immediately -- one stagger step behind the
     curtain, not a full --anim-quick after it. The (--i + 1) offset is what
     puts the first bullet just past the copy rather than under it. */
  animation-delay: calc((var(--i, 0) + 1) * var(--anim-stagger));
}

.services-cta {
  margin-top: clamp(28px, 4vh, 44px);
}

/* The CTA arrives on the tail of the last list item -- --i is the item
   count, so the delay lands just as the final bullet settles. */
.services-cta.animate-pending {
  opacity: 0;
  transform: translateY(16px);
}

.services-cta.in-view {
  animation: fade-up var(--anim-quick) var(--ease-spring) both;
  animation-delay: calc((var(--i, 0) + 1) * var(--anim-stagger));
}

@media (max-width: 860px) {
  .services-inner {
    grid-template-columns: 1fr;
  }
  .services-media {
    aspect-ratio: 16 / 10;
  }
}

@media (prefers-reduced-motion: reduce) {
  .services-curtain {
    display: none;
  }
  .services-media.animate-pending {
    opacity: 1;
    transform: none;
  }
  .services-media.in-view {
    animation: none;
  }
  .services-list__item.animate-pending {
    opacity: 1;
    transform: none;
  }
  .services-list__item.in-view {
    animation: none;
  }
  .services-cta.animate-pending {
    opacity: 1;
    transform: none;
  }
  .services-cta.in-view {
    animation: none;
  }
}

/* =============================================
   SLOGAN BAND (parallax)
   ============================================= */

/* ---- Slogan band wrapper (sticky underlay) ---- */
/* ---- Slogan band: fixed-background window effect ---- */
/* background-attachment:fixed keeps the image stationary while
   the page scrolls over it like a window into the scene. */
.slogan-band {
  position: relative;
  height: clamp(320px, 50vh, 560px);
  display: flex;
  align-items: center;
  justify-content: center;
  background-image: url('../images/web08.jpg');
  background-size: cover;
  background-position: center;
  background-attachment: fixed;
}

.slogan-band__veil {
  position: absolute;
  inset: 0;
  background-color: color-mix(in oklch, var(--color-bark) 68%, transparent);
}

.slogan-band__content {
  position: relative;
  z-index: 1;
  text-align: center;
  padding: 0 clamp(24px, 4vw, 64px);
  max-width: none;
}

.slogan-band__heading {
  font-family: var(--font-script);
  font-weight: 500;
  font-size: var(--fs-script-lg);
  line-height: 1.05;
  color: var(--color-parchment);
  letter-spacing: -0.01em;
  margin: 0 0 clamp(20px, 3vh, 36px);
}

/* The slogan stays on one line from tablet up. At full --fs-script-lg it is
   ~16.6em wide (~1200px); the 5vw cap only bites where the viewport is too
   narrow to hold it, so wide screens keep the full size. Phones wrap. */
@media (min-width: 768px) {
  .slogan-band__heading {
    white-space: nowrap;
    font-size: min(var(--fs-script-lg), 5vw);
  }
}

/* =============================================
   NEWS
   ============================================= */

/* ---- News section: 3-column row ---- */
/* z-index + background slide over the sticky slogan band */
.news-section {
  position: relative;
  z-index: 2;
  background-color: var(--color-parchment);
  width: 100%;
}

.news-section__inner {
  padding: 72px 50px;
  max-width: 1400px;
  margin: 0 auto;
}

.news-section__header {
  text-align: center;
}

.news-section__label {
  font-family: var(--font-serif);
  font-weight: 500;
  font-style: italic;
  font-size: var(--fs-h2);
  line-height: 1.12;
  color: var(--color-charcoal);
  margin-bottom: clamp(12px, 1.8vh, 20px);
}

.news-section__intro {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.75;
  color: var(--color-charcoal);
  text-align: justify;
  hyphens: manual;
}

.news-section__all {
  font-family: var(--font-sans);
  font-size: var(--fs-label-sm);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-terracotta);
  text-decoration: none;
  transition: opacity 0.2s ease-out;
}

.news-section__all:hover {
  opacity: 0.7;
}

.news-row {
  list-style: none;
  margin: 0;
  margin-top: 60px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0 clamp(32px, 4vw, 72px);
}

.news-card {
  padding-top: clamp(24px, 3.5vh, 36px);
}

.news-card__link {
  display: flex;
  flex-direction: column;
  text-decoration: none;
}

/* Preview image */
.news-card__figure {
  margin: 0 0 clamp(20px, 3vh, 30px);
  overflow: hidden;
  aspect-ratio: 4 / 3;
}

.news-card__figure img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1);
  transition: transform 0.7s var(--ease-spring);
}

.news-card__link:hover .news-card__figure img {
  transform: scale(1.04);
}

.news-card__body {
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.4vh, 16px);
  padding-bottom: clamp(32px, 5vh, 56px);
}

.news-card__headline {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h3);
  line-height: 1.18;
  color: var(--color-charcoal);
  margin: 0;
  transition: color 0.2s ease-out;
}

.news-card__link:hover .news-card__headline {
  color: var(--color-terracotta);
}

.news-card__excerpt {
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 400;
  line-height: 1.65;
  color: var(--color-charcoal);
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* =============================================
   CONTACT
   ============================================= */

.contact-section {
  background-color: var(--color-parchment);
  width: 100%;
}

.contact-inner {
  display: grid;
  grid-template-columns: 5fr 7fr;
  column-gap: clamp(48px, 8vw, 120px);
  align-items: stretch;
  padding: clamp(80px, 12vh, 140px) clamp(48px, 8vw, 120px) clamp(88px, 13vh, 150px);
  max-width: 1400px;
  margin: 0 auto;
}

/* ---- Left column ---- */
.contact-left {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(28px, 4vh, 44px);
  position: sticky;
  top: 80px;
  align-self: flex-start;
}

.contact-left__heading {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h1);
  line-height: 1.0;
  letter-spacing: -0.015em;
  color: var(--color-charcoal);
  margin: 0;
}

.contact-left__heading.animate-pending {
  opacity: 0;
  transform: translateX(-32px);
}

@keyframes contact-slide-in {
  from { opacity: 0; transform: translateX(-32px); }
  to   { opacity: 1; transform: translateX(0); }
}

.contact-left__heading.in-view {
  animation: contact-slide-in var(--anim-base) var(--ease-spring) both;
}

/* Contact facts: phone, email, address, hours */
.contact-facts {
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.6vh, 18px);
  border-top: 1px solid color-mix(in oklch, var(--color-clay) 18%, transparent);
  padding-top: clamp(20px, 3vh, 30px);
}

.contact-facts__item {
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 400;
  color: var(--color-charcoal);
  text-decoration: none;
  transition: color 0.2s ease-out;
}

.contact-facts__item:hover {
  color: var(--color-terracotta);
}

.contact-facts__address {
  font-style: normal;
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 400;
  line-height: 1.65;
  color: var(--color-charcoal);
  margin: 0;
}

.contact-facts__hours {
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 400;
  line-height: 1.6;
  color: var(--color-charcoal);
  margin: 0;
}

/* Social icons row */
.contact-social {
  display: flex;
  gap: clamp(16px, 2.5vw, 24px);
  align-items: center;
}

.contact-social__link {
  display: flex;
  align-items: center;
  justify-content: center;
  color: black;
  opacity: 0.55;
  transition: opacity 0.2s ease-out;
  text-decoration: none;
  font-size: 22px;
}

.contact-social__link:hover {
  opacity: 1;
}

/* ---- Right column: form ---- */
.contact-form-wrap {
  padding-top: 0.2em;
}

.contact-form {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 3vh, 28px);
}

.contact-form__row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.contact-form__label {
  font-family: var(--font-sans);
  font-size: var(--fs-label-sm);
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-charcoal);
}

.contact-form__label span {
  color: var(--color-terracotta);
}

.contact-form__field {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 300;
  color: var(--color-charcoal);
  background: #f4f4f4;
  border: none;
  border-bottom: 1px solid color-mix(in oklch, var(--color-charcoal) 28%, transparent);
  border-radius: 0;
  padding: clamp(10px, 1.4vh, 14px) 20px;
  width: 100%;
  outline: none;
  transition: border-color 0.2s ease-out;
  -webkit-appearance: none;
  appearance: none;
}

.contact-form__field:focus {
  border-bottom-color: var(--color-terracotta);
}

.contact-form__field::placeholder {
  color: var(--color-clay);
}

.contact-form__field--textarea {
  resize: vertical;
  min-height: 120px;
}

/* Purpose dropdown */
.contact-form__select-wrap {
  position: relative;
}

.contact-form__field--select {
  cursor: pointer;
  padding: 12px 20px;
}

.contact-form__field--select:invalid {
  color: var(--color-clay);
}

.contact-form__select-icon {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  font-size: 18px;
  color: var(--color-terracotta);
  pointer-events: none;
}

/* GDPR consent checkbox */
.contact-form__consent {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.contact-form__checkbox {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  border: 1px solid color-mix(in oklch, var(--color-charcoal) 40%, transparent);
  border-radius: 0;
  background: #f4f4f4;
  cursor: pointer;
  position: relative;
  transition: border-color 0.2s ease-out, background-color 0.2s ease-out;
}

.contact-form__checkbox:checked {
  background: var(--color-terracotta);
  border-color: var(--color-terracotta);
}

.contact-form__checkbox:checked::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 1px;
  width: 5px;
  height: 9px;
  border: solid var(--color-parchment);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.contact-form__checkbox:focus-visible {
  outline: 2px solid var(--color-terracotta);
  outline-offset: 2px;
}

.contact-form__consent-label {
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 400;
  line-height: 1.7;
  color: var(--color-charcoal);
  cursor: pointer;
}

.contact-form__consent-label span {
  color: var(--color-terracotta);
}

.contact-form__consent-link {
  color: var(--color-terracotta);
  text-decoration: underline;
}

.contact-form__footer {
  padding-top: clamp(8px, 1.2vh, 14px);
}

/* Outcome of contact-send.php — same tones as the newsletter status */
.contact-form__status {
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 400;
  line-height: 1.6;
  margin: 0;
}

.contact-form__status:empty {
  display: none;
}

.contact-form__status.is-success {
  color: var(--color-sage);
}

.contact-form__status.is-error {
  color: var(--color-caramel);
}

/* Both forms set display: flex, which beats the hidden attribute. */
[data-contact-form][hidden],
.form-thanks[hidden] {
  display: none;
}

.contact-form button:disabled,
.pd-contact__submit:disabled {
  opacity: 0.6;
  cursor: progress;
}

/* ---- Thank-you panel (includes/shared/form-thanks.php) ----
   Takes the form's place after a send, at the form's height (set by
   contact-form.js), so the page does not move under the visitor. */
.form-thanks {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  padding: var(--space-lg) var(--space-md);
  text-align: center;
  background: color-mix(in oklch, var(--color-blush) 40%, transparent);
  border: 1px solid color-mix(in oklch, var(--color-clay) 30%, transparent);
  outline: none;
}

.form-thanks > * {
  animation: fade-up var(--anim-quick) var(--ease-spring) both;
  animation-delay: calc(var(--i, 0) * var(--anim-stagger));
}

.form-thanks__icon {
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-terracotta);
  color: var(--color-terracotta);
  font-size: 24px;
}

.form-thanks__heading {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h3);
  line-height: 1.2;
  color: var(--color-charcoal);
  margin: 0;
  text-wrap: balance;
}

.form-thanks__text {
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 300;
  line-height: 1.7;
  color: var(--color-charcoal);
  max-width: 40ch;
  margin: 0;
  text-wrap: balance;
}

/* Underline CTA, matching .rd-back / .pd-video-link */
.form-thanks__again {
  position: relative;
  margin-top: var(--space-xs);
  padding: 4px 0;
  background: none;
  border: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-terracotta);
  cursor: pointer;
}

.form-thanks__again::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--color-caramel);
  transform-origin: right;
  transition: transform 0.3s var(--ease-spring);
}

.form-thanks__again:hover::after {
  transform: scaleX(0.4);
}

@media (prefers-reduced-motion: reduce) {
  .form-thanks > * { animation: none; }
  .form-thanks__again::after { transition: none; }
}

/* =============================================
   NEWSLETTER
   ============================================= */

/* The blush band runs edge to edge; the parchment padding above and below
   keeps it off the footer, so the page ends with air rather than a hard edge. */
.newsletter-section {
  background-color: var(--color-parchment);
  padding: clamp(48px, 7vh, 80px) 0 clamp(80px, 12vh, 140px);
  padding-top: 0;
}

.newsletter-inner {
  background-color: var(--color-blush);
  margin: 0 auto;
  padding: 30px clamp(40px, 6vw, 72px);
  text-align: center;
  position: relative;
  overflow: hidden;
}

/* ---- Curtain-down reveal ----
   JS injects .newsletter-curtain and arms the section (so no-JS users
   see the content). The overlay covers the card, then slides down out of
   view when scrolled into view, uncovering content from top to bottom. */
.newsletter-curtain {
  display: none;
}

.newsletter-section--armed .newsletter-curtain {
  display: block;
  position: absolute;
  inset: 0;
  z-index: 2;
  background-color: var(--color-parchment);
  border-top: 1px solid color-mix(in oklch, var(--color-sand) 60%, transparent);
  transform: translateY(0);
  will-change: transform;
  pointer-events: none;
}

.newsletter-section--armed.is-revealed .newsletter-curtain {
  transform: translateY(101%);
  transition: transform 1500ms var(--ease-spring);
}

@media (prefers-reduced-motion: reduce) {
  .newsletter-curtain {
    display: none !important;
  }
}

.newsletter-heading {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h1);
  line-height: 1.1;
  color: var(--color-charcoal);
  margin: 0 0 clamp(12px, 1.8vh, 20px);
}

.newsletter-sub {
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 400;
  line-height: 1.65;
  color: var(--color-charcoal);
  text-wrap: balance;
  margin: 0 auto clamp(28px, 4vh, 44px);
}

.newsletter-form {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 2vh, 20px);
  max-width: 680px;
  margin: auto;
}

/* Input and CTA share one row; the hairline runs under the input only,
   the filled button sits flush to its right. One control height governs
   both, so the hairline lands exactly on the button's bottom edge instead
   of near it. */
.newsletter-form__group {
  --nl-control-h: 48px;
  display: flex;
  align-items: stretch;
  gap: clamp(12px, 2vw, 24px);
}

.newsletter-form__input {
  flex: 1;
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 300;
  color: var(--color-charcoal);
  background: transparent;
  border: none;
  border-radius: 0;
  /* Centred by the line box, not by padding. `appearance: none` drops the
     UA's own vertical centring on a text input, so the old symmetric padding
     inside a stretched flex row left the address sitting on the field's top
     edge with all the slack below it. A line box as tall as the field (less
     the hairline) puts it in the middle at any control height. */
  height: var(--nl-control-h);
  padding: 0;
  line-height: calc(var(--nl-control-h) - 1px);
  border-bottom: 1px solid color-mix(in oklch, var(--color-charcoal) 30%, transparent);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  min-width: 0;
}

.newsletter-form__input::placeholder {
  color: var(--color-charcoal);
}

/* Visual styling comes from the shared .generic__cta block; this only keeps
   the button on the input's row at the input's height.
   The group selector is not decoration: .generic__cta is defined LATER in this
   file at the same specificity, so a bare .newsletter-form__btn loses to its
   margin-top and padding-block and the button drops below the input's row. */
.newsletter-form__group .newsletter-form__btn {
  flex-shrink: 0;
  white-space: nowrap;
  margin-top: 0;
  min-height: var(--nl-control-h);
  padding-block: 0;
}

/* Centred under the input/button row, matching the card's centred heading and
   sub. The label is inline-flex so the row shrinks to its text and the
   paragraph's text-align can centre it. */
.newsletter-form__consent {
  margin: 0;
  text-align: center;
}

.newsletter-form__check-label {
  display: inline-flex;
  align-items: flex-start;
  gap: 10px;
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 400;
  line-height: 1.55;
  color: var(--color-charcoal);
  cursor: pointer;
  text-align: left;
}

.newsletter-form__checkbox {
  flex-shrink: 0;
  margin-top: 3px;
  width: 14px;
  height: 14px;
  accent-color: var(--color-terracotta);
  cursor: pointer;
}

/* Honeypot. Moved off-screen rather than display:none — a bot that skips
   hidden inputs would walk straight past the trap. */
.newsletter-form__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Sign-up outcome. Sage for success, caramel for a problem — the palette has
   no red or green, and this is not the place to introduce one. The slot is
   always reserved (one small line, invisible while empty), so the card does
   not grow when a message arrives. */
.newsletter-form__status {
  text-align: center;
  font-family: var(--font-sans);
  font-size: var(--fs-label-sm);
  font-weight: 400;
  line-height: 1.5;
  min-height: 1.5em;
  margin: calc(clamp(14px, 2vh, 20px) * -0.5) 0 0;
  text-wrap: balance;
}

.newsletter-form__status.is-success {
  color: var(--color-sage);
}

.newsletter-form__status.is-error {
  color: var(--color-caramel);
}

/* The button is disabled while the request is in flight; it keeps its shape so
   the row does not shift, and drops its hover cues so it reads as inert. */
.newsletter-form__btn:disabled {
  opacity: 0.6;
  cursor: progress;
}

.newsletter-form__btn:disabled::before {
  transform: scaleX(0);
}

/* =============================================
   CLIENT VOICES (Testimonials)
   Homepage split: parchment title left | charcoal panel right.
   Right panel is content-driven; left stretches to match.
   ============================================= */

.client-voices {
  padding: 40px 0;
}

.client-voices__inner {
  display: grid;
  grid-template-columns: 5fr 5fr;
  border-top: 1px solid #dbdbdb;
  border-bottom: 1px solid #dbdbdb;
}

/* ---- Left: title column (video background) ---- */
.client-voices__title {
  position: relative;
  overflow: hidden;
  display: flex;
  text-align: center;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  padding: clamp(64px, 10vh, 120px) clamp(48px, 6vw, 96px);
}

.client-voices__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  z-index: 0;
}

.client-voices__veil {
  position: absolute;
  inset: 0;
  background: color-mix(in oklch, var(--color-obsidian) 32%, transparent);
  z-index: 1;
}

.client-voices__heading {
  position: relative;
  z-index: 2;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h1);
  line-height: 1.05;
  color: var(--color-parchment);
  margin: 0;
}

/* ---- Right: charcoal panel ---- */
.client-voices__panel {
  background-color: var(--color-charcoal);
  padding: clamp(56px, 8vh, 96px) clamp(48px, 6vw, 80px);
  display: flex;
  flex-direction: column;
}

/* ---- Testimonial item ---- */
.client-voices__item {
  display: flex;
  flex-direction: column;
  padding: clamp(36px, 5vh, 56px) 0;
}

.client-voices__item:first-child {
  padding-top: 0;
}

.client-voices__item:last-child {
  padding-bottom: 0;
}

/* ---- Testimonial entrance: fly in from top, one by one ---- */
.client-voices__panel.animate-pending .client-voices__item {
  opacity: 0;
  transform: translateY(-40px);
}

@keyframes fall-from-top {
  from { opacity: 0; transform: translateY(-40px); }
  to   { opacity: 1; transform: translateY(0); }
}

.client-voices__panel.in-view .client-voices__item {
  animation: fall-from-top var(--anim-base) var(--ease-spring) both;
}

.client-voices__panel.in-view .client-voices__item:nth-child(2) {
  animation-delay: calc(var(--anim-stagger) * 2);
}

.client-voices__excerpt {
  margin: 0;
}

.client-voices__excerpt p {
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: var(--fs-body);
  color: var(--color-parchment);
  text-align: justify;
  hyphens: manual;
  max-width: 55ch;
  margin: 0;
}

.client-voices__footer {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: clamp(16px, 2.5vh, 24px);
}

.client-voices__cta {
  display: inline-block;
  align-self: flex-start;
  margin-top: 4px;
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-parchment);
  text-decoration: none;
  border-bottom: 1px solid var(--color-parchment);
  padding-bottom: 2px;
  transition: opacity 0.2s ease-out;
}

.client-voices__cta:hover {
  opacity: 0.65;
}


.newsletter-form__policy-link {
  color: var(--color-terracotta);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}

.newsletter-form__policy-link:hover {
  opacity: 0.7;
}

/* =============================================
   NEWS PAGE — LISTING
   news.php: listing below shared page-banner
   ============================================= */

/* Listing container */
.news-page__listing {
  background-color: var(--color-parchment);
  padding: clamp(40px, 5vh, 64px) clamp(48px, 6vw, 96px) clamp(80px, 10vh, 120px);
  max-width: 1100px;
  margin: 0 auto;
}

/* ---- Journal intro (same copy as the homepage news lede) ---- */
.news-listing__intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(20px, 3vh, 28px);
  margin-bottom: clamp(40px, 6vh, 64px);
}

.news-listing__intro-text {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: var(--fs-body);
  line-height: 1.75;
  color: var(--color-charcoal);
  text-align: justify;
  hyphens: manual;
  text-wrap: pretty;
  max-width: none;
  width: 100%;
  margin: 0;
}

.news-listing__intro-rule {
  display: block;
  width: 56px;
  height: 1px;
  background-color: var(--color-terracotta);
}

/* ---- Lead article ---- */
.news-listing__lead {
  border-bottom: 1px solid color-mix(in oklch, var(--color-clay) 25%, transparent);
  padding-bottom: clamp(32px, 4vh, 48px);
  margin-bottom: clamp(24px, 3vh, 40px);
}

/* Horizontal 2-col: thumb left, text right */
.news-listing__lead-link {
  display: grid;
  grid-template-columns: 45fr 55fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
  text-decoration: none;
  color: inherit;
}

/* Lead thumbnail: 4:3, contained left column */
.news-listing__lead-thumb {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  width: 100%;
}

.news-listing__lead-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  transform: scale(1);
  transition: transform 0.7s var(--ease-spring);
}

.news-listing__lead-link:hover .news-listing__lead-img {
  transform: scale(1.025);
}

.news-listing__lead-body {
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.5vh, 16px);
  /* The measure lives here, so headline and excerpt share one width */
  max-width: 60ch;
}

/* Category + date on one row */
.news-listing__lead-meta {
  display: flex;
  align-items: center;
  gap: clamp(10px, 2vw, 20px);
}

.news-listing__dateslug {
  font-family: var(--font-sans);
  font-size: var(--fs-label-sm);
  font-weight: 400;
  letter-spacing: 0.05em;
  color: var(--color-charcoal);
  white-space: nowrap;
}

.news-listing__category {
  font-family: var(--font-sans);
  font-size: var(--fs-label-sm);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-terracotta);
}

.news-listing__lead-headline {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h2-sm);
  line-height: 1.1;
  color: var(--color-charcoal);
  max-width: none;
  transition: color 0.15s ease-out;
}

.news-listing__lead-link:hover .news-listing__lead-headline {
  color: var(--color-terracotta);
}

.news-listing__excerpt {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 300;
  line-height: 1.7;
  color: var(--color-charcoal);
  max-width: none;
}

.news-listing__cta {
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-terracotta);
  transition: opacity 0.15s ease-out;
}

.news-listing__lead-link:hover .news-listing__cta,
.news-listing__item-link:hover .news-listing__cta {
  opacity: 0.6;
}

/* ---- Secondary articles ---- */
.news-listing__item {
  border-bottom: 1px solid color-mix(in oklch, var(--color-clay) 25%, transparent);
  padding: clamp(20px, 3vh, 32px) 0;
}

/* Secondary: text left, portrait thumbnail right */
.news-listing__item-link {
  display: grid;
  grid-template-columns: 1fr clamp(140px, 20vw, 240px);
  column-gap: clamp(28px, 4vw, 56px);
  align-items: start;
  text-decoration: none;
  color: inherit;
}

/* Body wrapper: keeps all text in column 1 */
.news-listing__item-body {
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.2vh, 14px);
  /* The measure lives here, so headline and excerpt share one width */
  max-width: 52ch;
}

.news-listing__item-meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.news-listing__item-date {
  font-family: var(--font-sans);
  font-size: var(--fs-label-sm);
  font-weight: 400;
  letter-spacing: 0.05em;
  color: var(--color-charcoal);
}

.news-listing__item-headline {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h3);
  line-height: 1.15;
  color: var(--color-charcoal);
  max-width: none;
  transition: color 0.15s ease-out;
}

.news-listing__item-link:hover .news-listing__item-headline {
  color: var(--color-terracotta);
}

.news-listing__item-excerpt {
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 300;
  line-height: 1.65;
  color: var(--color-charcoal);
  max-width: none;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Same 4:3 frame as the lead — covers are cropped to 4:3 in the admin, so any
   other ratio here re-crops them and cuts the watermark off. */
.news-listing__item-thumb {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  width: 100%;
  align-self: start;
}

.news-listing__item-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  transform: scale(1);
  transition: transform 0.7s var(--ease-spring);
}

.news-listing__item-link:hover .news-listing__item-img {
  transform: scale(1.03);
}

/* ---- News listing: scroll-triggered reveals ---- */
/* Lead image bounces in; secondary items slide in, alternating
   right / left (direction set per-item in news.php). */
@keyframes news-bounce-in {
  0%   { opacity: 0; transform: scale(0.8); }
  55%  { opacity: 1; transform: scale(1.045); }
  100% { opacity: 1; transform: scale(1); }
}

.news-anim--bounce.animate-pending {
  opacity: 0;
  transform: scale(0.8);
}

.news-anim--bounce.in-view {
  animation: news-bounce-in var(--anim-slow) var(--ease-spring) both;
}

.news-anim--fade.animate-pending {
  opacity: 0;
  transform: translateY(22px);
}

.news-anim--fade.in-view {
  animation: fade-up var(--anim-base) var(--ease-spring) both;
}

.news-anim--slide.animate-pending {
  opacity: 0;
}

.news-anim--from-right.animate-pending {
  transform: translateX(48px);
}

.news-anim--from-left.animate-pending {
  transform: translateX(-48px);
}

.news-anim--from-right.in-view {
  animation: slide-from-right var(--anim-base) var(--ease-spring) both;
}

.news-anim--from-left.in-view {
  animation: slide-from-left var(--anim-base) var(--ease-spring) both;
}

@media (prefers-reduced-motion: reduce) {
  .news-anim.animate-pending { opacity: 1; transform: none; }
  .news-anim.in-view { animation: none; }
}

/* =============================================
   NEWS DETAIL
   news-detail.php: shared banner + parchment article
   ============================================= */

.news-detail__back {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: var(--fs-label-sm);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-clay);
  text-decoration: none;
  margin-bottom: clamp(28px, 4vh, 44px);
  transition: color 0.15s ease-out;
}

.news-detail__back:hover {
  color: var(--color-terracotta);
}

/* Article body.
   One column: headline, lede, image and text all share the same left and
   right edge, so the justified copy lines up with the image above it. The
   text therefore runs to the column (~80ch) instead of the site's 65ch cap —
   the client asked for a wider body here. */
.news-detail__body {
  background-color: var(--color-parchment);
  padding: clamp(56px, 8vh, 96px) clamp(48px, 6vw, 96px) clamp(80px, 12vh, 140px);
  max-width: 920px;
  margin: 0 auto;
}

/* Section-title size rather than --fs-h1, and no ch cap: long Hungarian
   titles fit more words per line and fill the column like the text below. */
.news-detail__headline {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-h2);
  line-height: 1.15;
  color: var(--color-charcoal);
  letter-spacing: -0.01em;
  max-width: none;
  text-wrap: pretty;
  margin-bottom: clamp(20px, 3vh, 32px);
}

.news-detail__byline {
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-clay);
  margin-bottom: clamp(20px, 3vh, 32px);
}

.news-detail__rule {
  width: 40px;
  height: 1px;
  background-color: var(--color-terracotta);
  margin-bottom: clamp(28px, 4vh, 44px);
}

/* Same type as the body paragraphs — the summary reads as the article's
   opening paragraph, not as a second typeface. */
.news-detail__lede {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 300;
  line-height: 1.8;
  color: var(--color-charcoal);
  max-width: none;
  margin-bottom: clamp(28px, 4vh, 44px);
  text-align: justify;
  hyphens: manual;
}

.news-detail__paragraph {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 300;
  line-height: 1.8;
  color: var(--color-charcoal);
  max-width: 65ch;
  margin-bottom: clamp(20px, 3vh, 32px);
  text-align: justify;
  hyphens: manual;
}

.news-detail__pullquote {
  margin: clamp(32px, 5vh, 56px) 0;
  padding: 0;
  border: none;
}

.news-detail__pullquote-text {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--fs-quote);
  line-height: 1.35;
  color: var(--color-sage); /* sage */
  display: block;
  max-width: 42ch;
}

.news-detail__content p {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 300;
  line-height: 1.8;
  color: var(--color-charcoal);
  max-width: none;
  margin-bottom: clamp(20px, 3vh, 32px);
  text-align: justify;
  hyphens: manual;
}

.news-detail__content h2,
.news-detail__content h3 {
  max-width: none;
}

.news-detail__end-rule {
  width: 40px;
  height: 1px;
  background-color: color-mix(in oklch, var(--color-clay) 40%, transparent);
  margin: clamp(40px, 6vh, 64px) 0 clamp(24px, 3vh, 36px);
}

.news-detail__more-link {
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-terracotta);
  text-decoration: none;
  transition: opacity 0.15s ease-out;
}

.news-detail__more-link:hover {
  opacity: 0.6;
}

/* Editorial article image — full column width, placed between lede and body */
.news-detail__figure {
  margin: 0 0 clamp(32px, 5vh, 52px);
  overflow: hidden;
  width: 100%;
  aspect-ratio: 16 / 9;
}

.news-detail__figure-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* GENERIC ------------------*/

/* ---- CTA link: uppercase underline text link (about-story, about-philosophy, etc.) ---- */
.cta-link {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-terracotta);
  border-bottom: 1px solid var(--color-terracotta);
  padding-bottom: 2px;
  transition: opacity 0.2s ease-out;
}

.cta-link:hover {
  opacity: 0.65;
}

/* On dark/photo backgrounds */
.cta-link--light {
  color: white;
  border-bottom-color: color-mix(in oklch, var(--color-parchment) 45%, transparent);
}

/* Shared filled CTA — the contact form's "Üzenet küldése" and the newsletter
   section's "Feliratkozás". Three layers stack inside one stacking context:
   the charcoal background, a terracotta wipe (::before) that fills on hover,
   and a one-pass sheen (::after) that draws the eye when the button arrives. */
.generic__cta {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: 0.75em;
  margin-top: clamp(20px, 3vh, 30px);
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-white);
  background-color: var(--color-charcoal);
  border: 0;
  padding: 14px 30px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* z-index:-1 inside the isolated context sits above the background-color but
   below the label, so no extra wrapper element is needed for the text. */
.generic__cta::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--color-terracotta);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.6s var(--ease-spring);
}

.generic__cta:hover::before,
.generic__cta:focus-visible::before {
  transform: scaleX(1);
}

.generic__cta-arrow {
  display: inline-block;
  transition: transform 0.6s var(--ease-spring);
}

/* Hover wins over the idle drift below: killing the animation lets the
   declared transform apply, and the transition carries it. Restarting at 0%
   on mouse-out matches translateX(0), so there is no snap back. */
.generic__cta:hover .generic__cta-arrow,
.generic__cta:focus-visible .generic__cta-arrow {
  animation: none;
  transform: translateX(6px);
}

.generic__cta:focus-visible {
  outline: 1px solid color-mix(in oklch, var(--color-charcoal) 45%, transparent);
  outline-offset: 3px;
}

/* Emphasis sheen — a pale band crossing the button. Held at opacity 0 until a
   reveal class arms it (see below), so a button that never scrolls into view
   never flashes. Once armed it loops on a long idle cycle: the sweep occupies
   only the first quarter of the 9s cycle, the rest is deliberate silence, so
   the button keeps drawing the eye without ever reading as a blinking ad. */
.generic__cta::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: -55%;
  width: 45%;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(
    100deg,
    transparent,
    color-mix(in oklch, var(--color-white) 24%, transparent),
    transparent
  );
  transform: translateX(0) skewX(-18deg);
}

/* Sweep runs 0%→26% (~2.3s of the 9s cycle), then parks off the right edge at
   opacity 0 for the remaining ~6.7s. */
@keyframes cta-sheen {
  0%   { opacity: 0; transform: translateX(0) skewX(-18deg); }
  4%   { opacity: 1; }
  22%  { opacity: 1; }
  26%  { opacity: 0; transform: translateX(420%) skewX(-18deg); }
  100% { opacity: 0; transform: translateX(420%) skewX(-18deg); }
}

/* Idle arrow drift — a slow nudge right and back, phased to the tail of the
   cycle so it never coincides with the sheen. Two quiet cues, alternating. */
@keyframes cta-arrow-drift {
  0%, 68%, 100% { transform: translateX(0); }
  80%           { transform: translateX(5px); }
}

/* Contact form: reveals on its own intersection via [data-animate]. */
.generic__cta.animate-pending {
  opacity: 0;
  transform: translateY(14px);
}

.generic__cta.in-view {
  animation: cta-rise var(--anim-base) var(--ease-spring) both;
}

.generic__cta.in-view::after {
  animation: cta-sheen 9000ms var(--ease-spring) 700ms infinite;
}

.generic__cta.in-view .generic__cta-arrow {
  animation: cta-arrow-drift 9000ms var(--ease-spring) 700ms infinite;
}

@keyframes cta-rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Newsletter: the curtain already uncovers the button, so it only needs the
   idle cues — delayed past the 1500ms curtain slide so the first sweep is not
   wiped over by the curtain still sliding down. */
.newsletter-section.is-revealed .generic__cta::after {
  animation: cta-sheen 9000ms var(--ease-spring) 1400ms infinite;
}

.newsletter-section.is-revealed .generic__cta-arrow {
  animation: cta-arrow-drift 9000ms var(--ease-spring) 1400ms infinite;
}

@media (prefers-reduced-motion: reduce) {
  .generic__cta.animate-pending { opacity: 1; transform: none; }
  .generic__cta.in-view { animation: none; }
  .generic__cta::before,
  .generic__cta-arrow { transition: none; }
  .generic__cta.in-view::after,
  .generic__cta.in-view .generic__cta-arrow,
  .newsletter-section.is-revealed .generic__cta::after,
  .newsletter-section.is-revealed .generic__cta-arrow { animation: none; }
}