/* ==========================================================================
   Patru.design — interactive components
   --------------------------------------------------------------------------
   Depends on css/tokens.css + css/base.css (load both first; all custom
   properties referenced here are defined in tokens.css). Assembled from the
   U4 builder fragments in order: group A (scroll-in animation, accordion,
   carousel), group B (galleries, lightbox), group C (portfolio hover,
   background video, ambient background). Values measured on the live
   Squarespace site 2026-07-15/16; sources noted per module.
   ========================================================================== */

/* ==========================================================================
   GROUP A — scroll-in animation + accordion + carousel
   --------------------------------------------------------------------------
   Styles js/animate.js, js/accordion.js and js/carousel.js. Measured on the
   live site 2026-07-16 (accordion: home services block; carousel: /ateliere
   testimonials, 1280/1440px).
   ========================================================================== */

/* --------------------------------------------------------------------------
   Scroll-in animation — js/animate.js adds .is-inview once per element.
   Live: global fade 0.65s ease (tweak-global-animations), once, no movement.
   -------------------------------------------------------------------------- */

/* The hidden state is armed only when JS runs: every page includes an inline
   <script>document.documentElement.classList.add('js')</script> in <head>,
   so with JS disabled/blocked nothing stays permanently invisible. */
html.js [data-animate] {
  opacity: 0;
  transition: opacity var(--anim-duration) var(--anim-curve);
}

html.js [data-animate].is-inview {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  /* Everything visible immediately; animate.js never starts its observer. */
  html.js [data-animate] {
    opacity: 1;
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   Accordion — matches the live Squarespace accordion block:
   30px item padding, 1px divider above every item plus a closing one
   (first/last dividers visible), h4-sized title, 24x3px "plus" icon whose
   vertical bar rotates flat (0.25s) when open, dropdown height animated
   250ms cubic-bezier(0.66, 0, 0.34, 1) — reproduced with grid-template-rows
   so no JS measuring is needed. js/accordion.js wraps panel content in
   .accordion__panel-inner (grid-template-rows needs a single child).
   -------------------------------------------------------------------------- */

.accordion {
  border-bottom: 1px solid var(--theme-text);
}

.accordion__item {
  border-top: 1px solid var(--theme-text);
}

.accordion__trigger {
  /* Live title is an h4 (--fluid-scale 1.75); font-size branches below. */
  --fluid-scale: 1.75;
  display: block;
  position: relative;
  width: 100%;
  padding: 30px 0;                 /* live: --accordion-item-padding-y */
  padding-right: calc(24px + 1rem);/* clear the icon */
  border: 0;
  background: none;
  cursor: pointer;
  text-align: left;
  color: var(--theme-heading);
  font-family: var(--font-stack);
  font-weight: var(--heading-weight);
  letter-spacing: var(--heading-letter-spacing);
  /* h4 line-height formula from base.css */
  line-height: calc(var(--heading-line-height) * (1 + (1 - var(--fluid-scale)) / 25));
}

/* Plus icon: two 24x3px bars (live --accordion-icon-size/-thickness); the
   "vertical" bar is a horizontal bar rotated 90deg while closed and lays
   flat when open, leaving a minus — exactly the live transition. */
.accordion__trigger::before,
.accordion__trigger::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 0;
  width: 24px;
  height: 3px;
  margin-top: -1.5px;
  background-color: currentColor;
  transition: transform 0.25s;
}

.accordion__trigger::after {
  transform: rotate(90deg);
}

.accordion__trigger[aria-expanded="true"]::after {
  transform: rotate(0deg);
}

.accordion__panel {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;              /* discrete: flips at the end of closing */
  transition:
    grid-template-rows 250ms cubic-bezier(0.66, 0, 0.34, 1),
    visibility 250ms;
}

.accordion__item.is-open .accordion__panel {
  grid-template-rows: 1fr;
  visibility: visible;
}

.accordion__panel-inner {
  min-height: 0;
  overflow: hidden;
}

.accordion__panel-inner > :last-child {
  padding-bottom: 30px;            /* live: --accordion-description-padding-bottom */
}

.accordion__panel-inner p {
  margin: 0 0 1rem;                /* live: description p margin 0 0 16px */
}

/* --------------------------------------------------------------------------
   Carousel — /ateliere testimonials. Live geometry at 1440px: full-bleed
   band, revealer inset by the page gutter, 2 slides per view with a 60px
   gap, #EDEDED cards padded 10% of their own width, 60px round coral
   arrows vertically centered 3vw from the viewport edges.
   .carousel expects full-bleed placement (direct child of the section, not
   inside .content-wrap) — the gutter lives on .carousel__viewport.
   -------------------------------------------------------------------------- */

.carousel {
  position: relative;
}

/* Section title above the carousel (live .list-section-title p: h2 size,
   bold, body 1.4 line-height, 61px below, left at the gutter). */
.carousel-title {
  --fluid-scale: var(--h2-scale);
  margin: 0 0 61px;
  padding-inline: var(--page-gutter);
  font-size: calc(var(--fluid-scale) * 1rem);
  font-weight: var(--heading-weight);
  letter-spacing: var(--heading-letter-spacing);
  line-height: var(--body-line-height);
}

@media screen and (max-width: 767px) and (orientation: portrait) {
  .carousel-title {
    font-size: calc((var(--fluid-scale) - 1) * 0.012 * min(100vh, 900px) + 1rem);
  }
}

@media screen and (min-width: 768px), screen and (orientation: landscape) {
  .carousel-title {
    font-size: min(
      calc((var(--fluid-scale) - 1) * 1.2vw + 1rem),
      max(
        calc((var(--fluid-scale) - 1) * 0.012 * var(--max-page-width) + 1rem),
        calc(var(--fluid-scale) * 1rem)
      )
    );
  }
}

/* Newsletter signup title — same h3-sized pattern (used on /newsletter). */
.newsletter-title {
  --fluid-scale: var(--h3-scale);
  margin: 0 0 8px;
  font-size: calc(var(--fluid-scale) * 1rem);
}

@media screen and (max-width: 767px) and (orientation: portrait) {
  .newsletter-title {
    font-size: calc((var(--fluid-scale) - 1) * 0.012 * min(100vh, 900px) + 1rem);
  }
}

@media screen and (min-width: 768px), screen and (orientation: landscape) {
  .newsletter-title {
    font-size: min(
      calc((var(--fluid-scale) - 1) * 1.2vw + 1rem),
      max(
        calc((var(--fluid-scale) - 1) * 0.012 * var(--max-page-width) + 1rem),
        calc(var(--fluid-scale) * 1rem)
      )
    );
  }
}

/* Injected by js/carousel.js around .carousel__track */
.carousel__viewport {
  overflow: hidden;
  margin-inline: var(--page-gutter);
  touch-action: pan-y;             /* keep vertical scroll, own horizontal swipes */
}

.carousel__track {
  --carousel-per-view: 1;
  --carousel-gap: 60px;            /* live: space-between-slides 60px */
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc(
    (100% - var(--carousel-gap) * (var(--carousel-per-view) - 1)) /
    var(--carousel-per-view)
  );
  gap: var(--carousel-gap);
  margin: 0;
  padding: 0;
  list-style: none;
  transition: transform var(--anim-duration) var(--anim-curve-flex);
}

.carousel__track.is-dragging {
  transition: none;
}

@media (min-width: 768px) {
  .carousel__track {
    --carousel-per-view: 2;        /* live: max-columns 2 */
  }
}

.carousel__slide {
  background-color: var(--color-light-accent);
  padding: 10%;                    /* of the slide's own width, as live */
}

/* Optional testimonial content helpers (live card anatomy) */
.carousel__media {
  width: 30%;                      /* live: media-width 30% */
  aspect-ratio: 3 / 4;             /* live: media-aspect-ratio 3:4 */
  object-fit: cover;
  margin: 0 0 20%;                 /* live: media margin-bottom 20% */
}

.carousel__quote {
  /* Live: list-item title, custom scale 1.6 with the h2 line-height slot */
  --fluid-scale: 1.6;
  margin: 0;
  font-family: var(--font-stack);
  font-weight: var(--heading-weight);
  letter-spacing: var(--heading-letter-spacing);
  line-height: calc(var(--heading-line-height) * (1 + (1 - 3.5) / 25));
  color: var(--theme-heading);
}

.carousel__author {
  margin: 6% 0 0;                  /* live: description margin-top 6% */
  font-size: 1rem;                 /* live: 16px small text */
}

.carousel__prev,
.carousel__next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: var(--z-raised);
  display: grid;
  place-items: center;
  width: 60px;
  height: 60px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: var(--color-accent);
  color: var(--color-white);
  cursor: pointer;
}

.carousel__prev { left: 3vw; }     /* live: arrow wrapper margin 3vw */
.carousel__next { right: 3vw; }

.carousel__prev svg,
.carousel__next svg {
  width: 36px;                     /* live: 36px icon, white 2px stroke */
  height: auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2px;
}

/* Mobile: arrows drop below the slides (live shows mobile arrows under the
   carousel; smaller tap-friendly circles are a deliberate KTD5 improvement). */
@media (max-width: 767px) {
  .carousel {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 16px;
  }

  .carousel__viewport {
    flex-basis: 100%;
  }

  .carousel__prev,
  .carousel__next {
    position: static;
    transform: none;
    width: 44px;
    height: 44px;
  }

  .carousel__prev svg,
  .carousel__next svg {
    width: 24px;
  }
}

/* Visually-hidden slide announcer (role=status), injected by carousel.js */
.carousel__status {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Fluid font-size for the two custom scales above — same three branches as
   base.css (which only covers its own selectors).
   -------------------------------------------------------------------------- */

.accordion__trigger,
.carousel__quote {
  font-size: calc(var(--fluid-scale) * 1rem);
}

@media screen and (max-width: 767px) and (orientation: portrait) {
  .accordion__trigger,
  .carousel__quote {
    font-size: calc((var(--fluid-scale) - 1) * 0.012 * min(100vh, 900px) + 1rem);
  }
}

@media screen and (min-width: 768px), screen and (orientation: landscape) {
  .accordion__trigger,
  .carousel__quote {
    font-size: min(
      calc((var(--fluid-scale) - 1) * 1.2vw + 1rem),
      max(
        calc((var(--fluid-scale) - 1) * 0.012 * var(--max-page-width) + 1rem),
        calc(var(--fluid-scale) * 1rem)
      )
    );
  }
}

/* ==========================================================================
   GROUP B — galleries + lightbox
   --------------------------------------------------------------------------
   Styles js/gallery.js and js/lightbox.js.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Galleries — .gallery--strips (justified rows) and .gallery--masonry
   js/gallery.js positions each .gallery__item absolutely (left/top/width/
   height) and sets the container height, then adds .is-ready. Without JS
   the items keep flowing normally as a stacked fallback.
   -------------------------------------------------------------------------- */

.gallery {
  position: relative;
}

.gallery__item {
  margin: 0;
}

.gallery--strips.is-ready .gallery__item,
.gallery--masonry.is-ready .gallery__item {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
}

.gallery--strips.is-ready .gallery__item img,
.gallery--masonry.is-ready .gallery__item img {
  width: 100%;
  height: 100%;
  /* Item boxes are rounded to whole pixels; cover absorbs the sub-pixel
     difference from the image's true aspect ratio. */
  object-fit: cover;
}

/* Lightbox link wrapper injected by js/lightbox.js (mirrors the live
   .gallery-strips-lightbox-link structure). */
.gallery__lightbox-link {
  display: block;
  width: 100%;
  height: 100%;
}

/* --------------------------------------------------------------------------
   Lightbox — overlay built by js/lightbox.js, themed black via
   [data-theme="black"] from tokens.css. Closed state uses visibility so
   its buttons drop out of the tab order without display:none killing the
   fade transition.
   -------------------------------------------------------------------------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Live lightbox: section background at 0.9 alpha (glass over the page). */
  background-color: hsla(var(--black-hsl), 0.9);
  visibility: hidden;
  opacity: 0;
  transition:
    opacity 0.25s ease,
    visibility 0s linear 0.25s;
}

.lightbox.is-open {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.25s ease;
}

/* Scroll lock while the lightbox is open (class set on <html>). */
html.has-lightbox-open,
html.has-lightbox-open body {
  overflow: hidden;
}

/* Live image box: width <= 94vw - 40px, height <= viewport - 6vw, centered,
   object-fit contain. 100% of the fixed-position overlay (not 100vh) so the
   stage tracks the *visible* viewport on iOS Safari with the URL bar open. */
.lightbox__stage {
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(94vw - 40px);
  height: calc(100% - 6vw);
}

.lightbox__img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

.lightbox__close,
.lightbox__control {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 10px;
  border: 0;
  background: transparent;
  color: var(--theme-heading);
  cursor: pointer;
}

/* The hidden attribute (set by lightbox.js on single-image galleries) must
   beat the author display:flex above — UA [hidden]{display:none} loses to
   any author display declaration. */
.lightbox [hidden] {
  display: none !important;
}

.lightbox__close {
  top: 12px;
  right: 12px;
}

.lightbox__close svg {
  width: 22px;
  height: 22px;
}

.lightbox__control {
  top: 50%;
  transform: translateY(-50%);
}

.lightbox__control svg {
  width: 13px;
  height: 24px;
}

.lightbox__prev {
  left: 8px;
}

.lightbox__next {
  right: 8px;
}

.lightbox__counter {
  position: absolute;
  bottom: 10px;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  font-size: 0.875rem;
  letter-spacing: var(--body-letter-spacing);
  color: var(--theme-text);
}

/* ==========================================================================
   GROUP C — portfolio hover + background video + ambient background
   --------------------------------------------------------------------------
   Styles js/portfolio-hover.js, js/video.js and js/ambient-bg.js.

   Values measured on the live /portfolio (2026-07-15, geometry re-measured
   2026-07-17): title = h1 fluid size, line-height 1.2, margin .75rem 0,
   rest opacity .85; the image renders aspect-fitted inside a 75vmin square
   centered in the 100vh band below the header; crossfade 0.6s
   cubic-bezier(.2,.6,.3,1) with a scale-up from .95 ("scale-up medium"
   tweak) and a 10% black hard-light overlay; title transition 0.65s
   cubic-bezier(.19,1,.22,1).
   ========================================================================== */

/* --------------------------------------------------------------------------
   Portfolio hover — .portfolio-list (<ul>) of <a data-bg> items, each
   wrapping an <h1 class="portfolio-list__title">. js/portfolio-hover.js
   injects .portfolio-hover-layer into the hosting section and toggles
   .is-active on per-item bg divs / data-active on the hovered item.
   Coarse-pointer devices never get the layer (module returns early) and
   the hover scale is fenced behind (hover: hover).
   -------------------------------------------------------------------------- */

.portfolio-hover-host {
  position: relative;
}

.portfolio-hover-layer {
  position: absolute;
  inset: 0;
  top: var(--header-height, calc(4vw + 73px)); /* center below the header,
                                                  like the live wrapper */
  display: grid;
  place-items: center;
  overflow: hidden;
  pointer-events: none;
}

/* All items stack in the same grid cell so they crossfade in place. */
.portfolio-hover-layer__bg {
  grid-area: 1 / 1;
  position: relative;
  opacity: 0;
  visibility: hidden;
  transform: scale3d(0.95, 0.95, 1);
  transition:
    opacity 0.6s cubic-bezier(0.2, 0.6, 0.3, 1),
    transform 0.6s cubic-bezier(0.2, 0.6, 0.3, 1),
    visibility 0.6s;
}

/* Live: each image aspect-fits a 75vmin square. */
.portfolio-hover-layer__bg img {
  display: block;
  width: auto;
  height: auto;
  max-width: 75vmin;
  max-height: 75vmin;
}

.portfolio-hover-layer__bg.is-active {
  opacity: 1;
  visibility: visible;
  transform: none;
}

/* Live: 10% black hard-light wash over the active image. */
.portfolio-hover-layer__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background-color: #000;
  opacity: 0.1;
  mix-blend-mode: hard-light;
}

.portfolio-list {
  position: relative;
  z-index: var(--z-raised);   /* titles sit over the hover layer */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  list-style: none;
  margin: 0;
  padding: 0;
  min-height: 100vh;          /* live: .portfolio-hover{min-height:100vh} */
}

.portfolio-list a {
  display: block;
  max-width: 100%;
  text-decoration: none;
  background-image: none;     /* cancel base.css `li a` underline gradient */
}

.portfolio-list__title {
  margin: 0.75rem 0;          /* live: hover-static title margin */
  line-height: 1.2;           /* live overrides the heading formula */
  opacity: 0.85;
  transform-origin: center;
  transition:
    transform var(--anim-duration) var(--anim-curve-flex),
    opacity var(--anim-duration) var(--anim-curve-flex);
}

/* Hover/focus = full opacity + scale-up (plan R8). data-active is set by
   the module so keyboard focus and hover share one visual state. */
@media (hover: hover) {
  .portfolio-list a:hover .portfolio-list__title {
    opacity: 1;
    transform: scale(1.06);
  }
}

.portfolio-list a:focus-visible .portfolio-list__title,
.portfolio-list a[data-active="true"] .portfolio-list__title {
  opacity: 1;
  transform: scale(1.06);
}

/* --------------------------------------------------------------------------
   Shared pause/play toggle — .bg-video__toggle and .ambient-bg__toggle.
   Live .background-pause-button: 32px circle, rgba(0,0,0,.5), bottom/right
   14px. The glyph keys off aria-pressed (true = paused, show play icon).
   -------------------------------------------------------------------------- */

.bg-video__toggle,
.ambient-bg__toggle {
  position: absolute;
  right: 14px;
  bottom: 14px;
  z-index: var(--z-raised);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.5);
  color: var(--color-white);
  cursor: pointer;
}

/* Pause glyph: two 3px bars. */
.bg-video__toggle::before,
.ambient-bg__toggle::before {
  content: "";
  box-sizing: border-box;
  width: 9px;
  height: 12px;
  border-left: 3px solid currentColor;
  border-right: 3px solid currentColor;
}

/* Play glyph when paused: solid triangle. */
.bg-video__toggle[aria-pressed="true"]::before,
.ambient-bg__toggle[aria-pressed="true"]::before {
  width: 0;
  height: 0;
  border: none;
  border-left: 10px solid currentColor;
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
  margin-left: 3px;
}

/* --------------------------------------------------------------------------
   Background video — wrapper is sized/positioned by the page (e.g. as a
   section background: position absolute + inset 0); the video always
   covers it.
   -------------------------------------------------------------------------- */

.bg-video {
  position: relative;
  overflow: hidden;
}

.bg-video > video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* --------------------------------------------------------------------------
   Ambient background — canvas fills its positioned parent and sits behind
   the section's content; the low internal resolution set by js/ambient-bg.js
   is stretched here.
   -------------------------------------------------------------------------- */

canvas.ambient-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: var(--z-base);
}

/* ==========================================================================
   SECTION LAYOUT — Squarespace Fluid Engine replica (shared by all pages)
   --------------------------------------------------------------------------
   Decompiled from the live per-section <style> blocks and verified against
   the rendered site (2026-07-16): every section is a grid of 8 (mobile) /
   24 (desktop >=768px) content columns capped at 1500px, centered between
   two gutter tracks; desktop row height = 0.0215 x the content width; gap
   is 24px on most sections (11px on some — override --fe-gap inline).
   Blocks carry their live grid-areas via --gam (mobile) / --gad (desktop).

   Section vertical padding comes from the live section-height tweaks:
   small 3.3vw / medium 6.6vw / large 10vw. The first section of a page
   additionally clears the fixed header (live JS does the same).
   ========================================================================== */

.page-section {
  position: relative;
  display: flex;                     /* live vertical-alignment--middle */
  flex-direction: column;
  justify-content: center;
  --section-pad: 3.3vw;              /* section-height--small default */
  min-height: 33vh;
  padding-block: var(--section-pad);
}

.page-section--medium { --section-pad: 6.6vw; min-height: 66vh; }
.page-section--large  { --section-pad: 10vw;  min-height: 100vh; }

/* Live mobile sections pad with viewport-height units instead. */
@media (max-width: 767px) {
  .page-section          { --section-pad: 3.3vh; }
  .page-section--medium  { --section-pad: 6.6vh; }
  .page-section--large   { --section-pad: 10vh; }
}

/* First section clears the fixed header. --header-height is kept exact by
   js/header.js; the fallback mirrors its geometry (2vmax padding x2 +
   ~19px skip-link line + 54px logo). */
main > .page-section:first-child {
  padding-top: calc(var(--header-height, calc(4vw + 73px)) + var(--section-pad));
}

/* .page-section is a flex column; a .container child's auto margins would
   otherwise beat the default stretch and shrink-wrap absolute content. */
.page-section > .container {
  width: 100%;
}

/* Full-bleed section background (image or video wrapper) under the grid. */
.section-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.section-bg > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.fe {
  --fe-gap: 24px;
  --fe-cw: min(var(--max-page-width), 100vw - 2 * var(--page-gutter));
  position: relative;                /* above any .section-bg */
  display: grid;
  grid-template-rows: repeat(var(--rows-m, 1), minmax(24px, auto));
  grid-template-columns:
    minmax(max(calc(var(--page-gutter) - var(--fe-gap)), 0px), 1fr)
    repeat(8, minmax(0, calc((var(--fe-cw) - 7 * var(--fe-gap)) / 8)))
    minmax(max(calc(var(--page-gutter) - var(--fe-gap)), 0px), 1fr);
  gap: var(--fe-gap);
}

.fe-b {
  grid-area: var(--gam);
  min-width: 0;
}

/* Live text blocks trim the outer margins of their first/last children. */
.fe-b > :first-child { margin-top: 0; }
.fe-b > :last-child  { margin-bottom: 0; }

/* Live button blocks: the button fills its whole grid area, text centered
   (padding comes from the area, not the element). */
.fe-b > .btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 0 var(--btn-padding-x);
  text-align: center;
}

@media (min-width: 768px) {
  .fe {
    grid-template-rows: repeat(var(--rows-d, 1), minmax(calc(var(--fe-cw) * 0.0215), auto));
    grid-template-columns:
      minmax(max(calc(var(--page-gutter) - var(--fe-gap)), 0px), 1fr)
      repeat(24, minmax(0, calc((var(--fe-cw) - 23 * var(--fe-gap)) / 24)))
      minmax(max(calc(var(--page-gutter) - var(--fe-gap)), 0px), 1fr);
  }

  .fe-b {
    grid-area: var(--gad, var(--gam));
  }
}

/* Live per-block vertical alignment (.sqs-block justify-content). */
.fe-b--end,
.fe-b--center {
  display: flex;
  flex-direction: column;
}

.fe-b--end    { justify-content: flex-end; }
.fe-b--center { justify-content: center; }

/* Rich-text niceties used by page content. */
.text-white { color: var(--color-white); }

/* Live sqsrte-text-highlight (underline shape, 0.1em, theme/accent color). */
.text-highlight {
  box-shadow: 0 0.06em 0 0 var(--color-accent);
}

/* --------------------------------------------------------------------------
   Forms — live Squarespace form block (measured /contact 1280): labels at
   text-normal size with 28px below, inputs/textarea 1px solid black on
   #FAFAFA with 10px padding and no radius, name pair split with a 10px gap
   and 12px sub-captions, coral submit with WHITE text. Submission is a
   deferred integration point handled by js/form.js (plan KTD6/R15/R16).
   -------------------------------------------------------------------------- */

.form__item {
  margin: 0 0 12px;
}

.form__label {
  display: block;
  --fluid-scale: var(--text-normal-scale);
  font-size: calc(var(--fluid-scale) * 1rem);
  margin: 0 0 4px;
}

/* The name group's "Numele" legend sits 28px above its inputs (live). */
.form__name .form__label {
  margin-bottom: 28px;
}

.form__item input,
.form__item textarea {
  width: 100%;
  padding: 10px;
  border: 1px solid #000;
  border-radius: 0;
  background-color: #fafafa;
  font-family: var(--font-stack);
  --fluid-scale: var(--text-normal-scale);
  font-size: calc(var(--fluid-scale) * 1rem);
  color: var(--color-black);
}

.form__item textarea {
  min-height: 100px;
  resize: vertical;
}

.form__pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.form__caption {
  display: block;
  margin-top: 6px;
  font-size: 12px;
}

/* Submit reuses the .btn wipe with the live white label. */
.form__submit {
  --theme-btn-text: var(--color-white);
}

.form__notice {
  display: none;
  margin-top: 16px;
}

.form__notice.is-visible {
  display: block;
}

/* Plain social icons (live /contact content block: 20px, no ring). */
.social-links--plain {
  gap: 12px;
}

.social-links--plain a {
  --social-box-pad: 0px;
  box-shadow: none;
}

.social-links--plain svg {
  width: 20px;
  height: 20px;
}

/* Testimonial rules — live horizontalrule-block: 1px, text color. */
.rule {
  border: 0;
  height: 1px;
  background-color: var(--theme-text);
  margin: 0.589em 0;                 /* live: 9.42px at 16px */
}

/* Flush sections — live gallery/heading sections carry no padding and no
   min-height; the content (gallery or a lone heading grid) sets the size. */
.page-section--flush {
  --section-pad: 0px;
  min-height: 0;
}

/* Gallery sections — live .gallery-strips pads one page gutter top/bottom. */
.page-section--gallery {
  --section-pad: var(--page-gutter);
  min-height: 0;
}

/* --------------------------------------------------------------------------
   Project pagination — live .item-pagination (measured casa-aszalos 1280):
   padding 3vw x page gutter, "Previous/Next" label at text-normal size over
   an h3-sized bold title, 9x16 caret at 18px wide beside the text; the next
   link is pushed right. Single-link pages keep the side via --prev/--next.
   -------------------------------------------------------------------------- */

.pagination {
  display: flex;
  align-items: center;
  padding: 3vw var(--page-gutter);
}

.pagination a {
  display: flex;
  align-items: center;
  gap: 24px;
  max-width: 50%;                    /* live: titles wrap inside half the row */
  text-decoration: none;
  color: inherit;
}

.pagination__next {
  margin-left: auto;
  text-align: right;
}

/* Live hides the Previous/Next word at every width; keep it for screen
   readers only. */
.pagination__label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.pagination__title {
  --fluid-scale: var(--h3-scale);
  display: block;
  margin: 0;
  font-size: calc(var(--fluid-scale) * 1rem);
  font-weight: var(--heading-weight);
  letter-spacing: var(--heading-letter-spacing);
  line-height: 1em;                  /* live .item-pagination-title */
}

@media screen and (max-width: 767px) and (orientation: portrait) {
  .pagination__title {
    font-size: calc((var(--fluid-scale) - 1) * 0.012 * min(100vh, 900px) + 1rem);
  }
}

@media screen and (min-width: 768px), screen and (orientation: landscape) {
  .pagination__title {
    font-size: min(
      calc((var(--fluid-scale) - 1) * 1.2vw + 1rem),
      max(
        calc((var(--fluid-scale) - 1) * 0.012 * var(--max-page-width) + 1rem),
        calc(var(--fluid-scale) * 1rem)
      )
    );
  }
}

.pagination svg {
  width: 18px;
  height: 32px;
  stroke: currentColor;
  fill: none;
  stroke-miterlimit: 10;
  flex-shrink: 0;
}
