/*
 * Fagora Piscinas — shared stylesheet
 *
 * Organisation:
 * 1. Font, design tokens and document defaults
 * 2. Shared layout and interactive components
 * 3. Global navigation and menu
 * 4. Home-page sections
 * 5. Shared footer and interior-page layouts
 * 6. Gallery and contact page
 * 7. Motion effects and responsive overrides
 */

@font-face {
  font-family: Instrument Sans;
  src: url("fonts/instrument-sans.woff2") format("woff2");
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
}
:root {
  --ink: #0b314a;
  --secondary: #35515f;
  --teal: #005765;
  --aqua: #3cc3c6;
  --pale: #ddf4f4;
  --mist: #f3f7f8;
  --white: #fff;
  --border: #708691;
  --rule: #d7e1e6;
  --gutter: clamp(1.25rem, 4.45vw, 4rem);
  --max: 90rem;
  --header: 6.25rem;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  color-scheme: light;
  font-family:
    Instrument Sans,
    Arial,
    sans-serif;
  color: var(--ink);
  background: var(--white);
  font-synthesis: none;
}
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header) + 1.5rem);
}
body {
  margin: 0;
  padding-top: var(--header);
  font-size: 1.125rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
html[data-page="home"] body {
  padding-top: 0;
}
body.modal-open {
  overflow: hidden;
}
::selection {
  background: var(--pale);
  color: var(--ink);
}
a {
  color: inherit;
  text-underline-offset: 0.25em;
  text-decoration-thickness: 1px;
}
button,
input,
textarea {
  font: inherit;
}
button,
a {
  -webkit-tap-highlight-color: transparent;
}
button {
  color: inherit;
  cursor: pointer;
}
.motion-consent {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 40;
  width: min(32rem, calc(100% - 2rem));
  display: grid;
  gap: 1rem;
  padding: 1.25rem;
  color: var(--white);
  background: rgba(11, 49, 74, 0.96);
  box-shadow: 0 0.75rem 2rem rgba(11, 49, 74, 0.2);
}
.motion-consent strong {
  display: block;
  margin-bottom: 0.35rem;
}
.motion-consent p {
  color: #d8edf0;
  font-size: 0.9rem;
  line-height: 1.45;
}
.motion-consent-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.motion-consent .button {
  min-height: 2.75rem;
}
.motion-consent .text-link {
  color: var(--white);
}
button:disabled {
  cursor: default;
}
button {
  border: 0;
  background: none;
}
img,
svg,
video {
  display: block;
  max-width: 100%;
}
img {
  height: auto;
}
h1,
h2,
h3,
p,
figure,
blockquote {
  margin: 0;
}
h1,
h2,
h3 {
  font-weight: 500;
  line-height: 1.08;
  letter-spacing: -0.04em;
  text-wrap: balance;
}
h1 {
  font-size: clamp(3rem, 7.4vw, 7rem);
}
h2 {
  font-size: clamp(2.1rem, 4.5vw, 4.5rem);
}
h3 {
  font-size: clamp(1.4rem, 2.2vw, 2rem);
  letter-spacing: -0.025em;
}
p {
  max-width: 65ch;
}
ul,
ol {
  padding: 0;
  margin: 0;
}
fieldset {
  padding: 0;
  border: 0;
  margin: 0;
  min-width: 0;
}
summary {
  cursor: pointer;
}
:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 5px;
  box-shadow: 0 0 0 2px var(--white);
}
[hidden] {
  display: none !important;
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.no-js .js-only {
  display: none !important;
}
/* --------------------------------------------------------------------------
 * Shared layout and UI primitives
 * -------------------------------------------------------------------------- */
.container {
  width: min(calc(100% - var(--gutter) * 2), var(--max));
  margin-inline: auto;
}
.section {
  padding-block: clamp(4rem, 8vw, 8rem);
}
.eyebrow {
  font-size: 1rem;
  line-height: 1.4;
  letter-spacing: 0.045em;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin-bottom: 1.5rem;
}
.eyebrow::before {
  display: none;
  content: "";
  width: 1.5rem;
  height: 1px;
  background: currentColor;
  flex: none;
}
.section-number {
  font-size: 1rem;
  line-height: 1;
  letter-spacing: 0.06em;
  font-weight: 500;
}
.section-heading {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: end;
  gap: 3rem;
  margin-bottom: 3.5rem;
}
.section-heading p {
  color: var(--secondary);
  max-width: 37rem;
}
.section-heading .text-link {
  justify-self: end;
}
.line-break {
  display: block;
}
.icon {
  width: 1.25rem;
  height: 1.25rem;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.button {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  min-height: 3.25rem;
  padding: 0.85rem 1.25rem;
  border: 1px solid currentColor;
  border-radius: 2rem;
  font-size: 1rem;
  font-weight: 500;
  text-decoration: none;
  line-height: 1.3;
  transition:
    background 0.18s,
    color 0.18s,
    border-color 0.18s;
}
.button .icon {
  transition: transform 0.18s var(--ease);
}
.button:hover .icon {
  transform: translate(2px, -2px);
}
.button-primary {
  background: var(--ink);
  border-color: var(--ink);
  color: white;
}
.button-primary:hover {
  background: var(--teal);
  border-color: var(--teal);
}
.button-light {
  background: white;
  border-color: white;
  color: var(--ink);
}
.button-light:hover {
  background: var(--pale);
  border-color: var(--pale);
}
.button-outline:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: white;
}
.text-link {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  min-height: 2.75rem;
  font-size: 1rem;
  font-weight: 500;
  text-decoration: underline;
}
.text-link .icon {
  transition: transform 0.18s var(--ease);
}
.text-link:hover .icon {
  transform: translate(2px, -2px);
}
.icon-button {
  display: inline-grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border: 1px solid var(--border);
  border-radius: 50%;
  flex: none;
  transition:
    background 0.18s,
    color 0.18s;
}
.icon-button:hover {
  background: var(--ink);
  color: white;
  border-color: var(--ink);
  --wave-fill: var(--teal);
}
.skip-link {
  position: fixed;
  top: 1rem;
  left: 1rem;
  padding: 0.8rem 1rem;
  z-index: 1000;
  background: white;
  color: var(--ink);
  transform: translateY(-200%);
}
.skip-link:focus {
  transform: translateY(0);
}
/* --------------------------------------------------------------------------
 * Global header and navigation
 * -------------------------------------------------------------------------- */
/* The hero continues behind the fixed header; all desktop navigation is visible. */
.site-header {
  height: var(--header);
  position: fixed;
  inset: 0 0 auto;
  z-index: 30;
  /* Solid white: the logo's navy and aqua may not be recoloured, and any
     translucency lets the dark hero photo grey the bar out behind them. */
  background: var(--white);
  color: var(--ink);
  border-bottom: 1px solid var(--rule);
  transition:
    height 0.35s var(--ease),
    background 0.4s,
    box-shadow 0.4s;
}
/* Once the page moves, the header compacts and the logo scales with it.
   Only the fixed header changes height - body padding keeps using
   --header - so nothing on the page shifts. */
.site-header.is-scrolled {
  height: 4.75rem;
  box-shadow: 0 4px 25px rgba(11, 49, 74, 0.1);
}
.header-inner {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}
.brand {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  text-decoration: none;
  flex: none;
}
/*
 * fagora-logo.png is used exactly as supplied. Its artwork only fills the
 * middle of the 1471 x 1069 canvas (x 80-1402, y 152-926), so --logo sets
 * the height of the artwork itself: the image is drawn taller by the
 * canvas/artwork ratio, and negative margins cancel the empty border on
 * every side, so the link's box hugs the visible logo.
 */
.brand {
  --logo: 3.5rem;
}
.brand img {
  width: auto;
  height: calc(var(--logo) * 1.3811);
  aspect-ratio: 1471 / 1069;
  margin: calc(var(--logo) * -0.1964) calc(var(--logo) * -0.0891)
    calc(var(--logo) * -0.1848) calc(var(--logo) * -0.1034);
  transition:
    height 0.35s var(--ease),
    margin 0.35s var(--ease);
}
.site-header.is-scrolled .brand {
  --logo: 2.75rem;
}
.desktop-nav {
  margin-left: auto;
}
.desktop-nav ul {
  list-style: none;
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2vw, 2rem);
}
.desktop-nav a {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 3rem;
  text-decoration: none;
  font-size: 0.9375rem;
  font-weight: 500;
  white-space: nowrap;
}
.desktop-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 3px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s var(--ease);
}
.desktop-nav a:is(:hover, [aria-current="page"])::after {
  transform: scaleX(1);
}
.header-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.language-switch {
  display: flex;
  align-items: center;
  gap: 0;
  font-size: 0.9375rem;
  font-weight: 500;
}
.language-switch a {
  display: grid;
  place-items: center;
  min-width: 2.75rem;
  min-height: 2.75rem;
  text-decoration: none;
  position: relative;
}
.language-switch a[aria-current="true"]::after {
  content: "";
  position: absolute;
  bottom: 3px;
  width: 1.2rem;
  height: 2px;
  background: currentColor;
}
.language-switch span {
  font-weight: 400;
}
.menu-toggle {
  display: none;
  gap: 0.8rem;
  align-items: center;
  min-height: 3rem;
  padding: 0;
  font-size: 1rem;
}
.menu-mark {
  display: grid;
  align-content: center;
  gap: 5px;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid currentColor;
  border-radius: 50%;
  padding: 12px;
}
.menu-mark::before,
.menu-mark::after {
  content: "";
  height: 1px;
  width: 100%;
  background: currentColor;
}
.page-progress {
  position: absolute;
  bottom: -1px;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--aqua);
  transform-origin: left;
  transform: scaleX(var(--page-progress, 0));
}
.native-nav {
  padding: 1rem var(--gutter);
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  background: white;
}
.menu-dialog {
  position: fixed;
  inset: 0;
  margin: 0;
  width: 100%;
  height: 100dvh;
  max-width: none;
  max-height: none;
  padding: 0;
  border: 0;
  background: var(--white);
  color: var(--ink);
  overflow: auto;
}
dialog::backdrop {
  background: rgba(8, 30, 46, 0.72);
  backdrop-filter: blur(10px);
}
.menu-layout {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  padding: 1rem 1.5rem 2rem;
}
.menu-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 2.5rem;
  gap: 1rem;
}
.close-button {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 3rem;
  font-size: 1rem;
}
.menu-nav {
  flex: 1;
  padding-bottom: 3rem;
}
.menu-nav ul {
  list-style: none;
}
.menu-nav a {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 1rem 0;
  text-decoration: none;
  font-size: clamp(1.75rem, 6vw, 3rem);
  line-height: 1.15;
  letter-spacing: -0.035em;
  border-bottom: 1px solid var(--rule);
}
.menu-nav a span:first-child {
  font-size: 0.9375rem;
  letter-spacing: 0;
  min-width: 1.5rem;
}
.menu-nav a[aria-current="page"] {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.menu-bottom {
  border-top: 1px solid var(--rule);
  padding-top: 2rem;
  display: grid;
  gap: 1.5rem;
}
.menu-bottom p {
  font-size: 1rem;
  margin-bottom: 0.4rem;
}
.menu-dialog[open] {
  animation: menu-enter 0.45s var(--ease);
}
@keyframes menu-enter {
  from {
    clip-path: inset(0 0 100%);
  }
  to {
    clip-path: inset(0);
  }
}
/* --------------------------------------------------------------------------
 * Home: hero
 * -------------------------------------------------------------------------- */
.hero {
  position: relative;
  background: var(--ink);
  color: white;
  min-height: max(46rem, 100svh);
  max-height: 70rem;
  isolation: isolate;
  display: flex;
  align-items: center;
  overflow: hidden;
}
.hero-image,
.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: -2;
  overflow: hidden;
}
.hero-image picture {
  display: block;
  height: 100%;
}
.hero-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 53%;
  animation: hero-arrive 1.8s var(--ease) both;
}
/* Landscape screens load the wide hero crop (see templates.py
   hero_picture()); frame it high so the pool's far edge stays in view. */
@media (min-aspect-ratio: 5/4) {
  .hero-image img {
    object-position: center 30%;
  }
}
.hero-scrim {
  z-index: -1;
  background:
    linear-gradient(
      180deg,
      rgba(11, 49, 74, 0.62) 0,
      rgba(11, 49, 74, 0.5) var(--header),
      rgba(11, 49, 74, 0.04) calc(var(--header) + 8rem),
      transparent calc(var(--header) + 12rem)
    ),
    linear-gradient(
      90deg,
      rgba(11, 49, 74, 0.78),
      rgba(11, 49, 74, 0.52) 30%,
      rgba(11, 49, 74, 0.12) 58%,
      rgba(11, 49, 74, 0.02) 100%
    );
}
.hero-content {
  padding-block: calc(var(--header) + 3.5rem) 7rem;
  position: relative;
  max-width: calc(var(--max) * 0.92);
  margin-inline: auto;
}
.hero h1 {
  font-size: clamp(3.75rem, 6.5vw, 6.8rem);
  font-weight: 400;
  line-height: 1.025;
}
/* The H1 is the keyword line ("Piscinas de obra en la Comunidad de
   Madrid") set small above the slogan, which keeps its own measure. The
   admin panel's headline edit replaces only the slogan. */
.hero-title-text {
  display: block;
  max-width: 8.5ch;
}
.hero-title-text > span {
  display: block;
  animation: text-arrive 0.9s var(--ease) both;
}
.hero-title-text > span:nth-child(2) {
  animation-delay: 0.12s;
}
.hero-title-text > span:nth-child(3) {
  animation-delay: 0.24s;
}
.hero-kicker {
  display: block;
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.045em;
  line-height: 1.4;
  max-width: 24rem;
  margin-bottom: 1.25rem;
  text-wrap: balance;
  animation: text-arrive 0.8s var(--ease) both;
}
.faq-section .eyebrow {
  text-wrap: balance;
}
.hero-copy {
  font-size: 1.125rem;
  max-width: 27rem;
  margin-block: 1.75rem 2rem;
  animation: text-arrive 1s 0.3s var(--ease) both;
}
.hero .button {
  animation: text-arrive 1s 0.4s var(--ease) both;
}
.hero-bottom {
  position: absolute;
  inset: auto var(--gutter) 1.75rem;
  display: flex;
  justify-content: flex-end;
  /* Leaves the bottom-right corner to the floating phone bubble. */
  padding-right: max(0px, calc(1.25rem + 3.75rem + 1rem - var(--gutter)));
  max-width: var(--max);
  margin-inline: auto;
}
.hero-scroll {
  display: flex;
  align-items: center;
  gap: 1rem;
  text-decoration: none;
  min-height: 3rem;
  background: rgba(11, 49, 74, 0.9);
  padding: 0.4rem 1rem;
  border-radius: 2rem;
  font-size: 0.9375rem;
}
.hero-scroll .icon {
  transform: rotate(135deg);
}
@keyframes hero-arrive {
  from {
    transform: scale(1.065);
  }
  to {
    transform: scale(1);
  }
}
@keyframes text-arrive {
  from {
    opacity: 0;
    transform: translateY(1.4rem);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
/* --------------------------------------------------------------------------
 * Home: introduction and benefits
 * -------------------------------------------------------------------------- */
/* Photography and expandable details replace the text-heavy introduction. */
.intro-section {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.intro-feature {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(3rem, 7vw, 7rem);
  align-items: center;
}
.intro-photographs {
  position: relative;
  padding: 0 3rem 4rem 0;
  align-self: stretch;
  min-height: 36rem;
  height: clamp(38rem, 57vw, 52rem);
  align-self: center;
}
.intro-main-image {
  height: 100%;
  overflow: hidden;
}
.intro-main-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 60%;
  min-height: 36rem;
}
.intro-detail-image {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 42%;
  aspect-ratio: 1;
  border: 10px solid white;
  overflow: hidden;
  box-shadow: 0 20px 60px rgba(11, 49, 74, 0.12);
}
.intro-detail-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.intro-story h2 {
  font-weight: 400;
  font-size: clamp(2.5rem, 3.7vw, 3.8rem);
  max-width: 19ch;
}
.intro-description {
  margin-top: 1.5rem;
  color: var(--secondary);
  font-size: 1.0625rem;
}
.intro-description p + p {
  margin-top: 0.5rem;
}
.intro-advantages {
  margin-top: 2.25rem;
}
.intro-advantages h3 {
  font-size: 1.25rem;
  letter-spacing: -0.02em;
  line-height: 1.4;
  margin-bottom: 1rem;
}
.benefit-detail {
  border-bottom: 1px solid var(--rule);
}
.benefit-detail summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  list-style: none;
  min-height: 3.4rem;
  padding: 0.8rem 0;
  font-size: 1rem;
  font-weight: 500;
}
summary::-webkit-details-marker {
  display: none;
}
.benefit-detail p {
  padding: 0 2rem 1rem 0;
  color: var(--secondary);
  font-size: 1rem;
  animation: text-arrive 0.3s var(--ease);
}
.benefit-detail .icon {
  width: 1rem;
  height: 1rem;
  transition: transform 0.35s var(--ease);
}
.benefit-detail[open] .icon {
  transform: rotate(45deg);
}
.benefit-list {
  display: grid;
  grid-template-columns: 1fr;
  list-style: none;
}
.benefit-list li {
  padding: 1.25rem 0;
  border-top: 1px solid var(--rule);
}
.benefit-list h4 {
  font-size: 1.125rem;
  line-height: 1.4;
  font-weight: 500;
  margin: 0 0 0.4rem;
}
.benefit-list p {
  font-size: 1rem;
  color: var(--secondary);
}
/* --------------------------------------------------------------------------
 * Home: selected work, process and services
 * -------------------------------------------------------------------------- */
.works-section {
  background: var(--mist);
}
.video-strip {
  background: var(--ink);
  color: var(--white);
  /* The carousel's silhouettes reach past the edges on small screens. */
  overflow: hidden;
}
.video-strip .section-heading {
  margin-bottom: 2rem;
}
/* Project video carousel (app.js). One card plays in the middle; the
   previous and next ones sit behind it as dimmed silhouettes. Cards are
   stacked in one grid cell and moved into place by their data-slot, so
   the stage keeps the active card's size whatever the others do. */
.video-carousel {
  --card: min(22rem, 64vw);
  max-width: 60rem;
  margin-inline: auto;
}
.video-carousel-stage {
  position: relative;
  display: flex;
  justify-content: center;
  touch-action: pan-y;
}
.video-carousel-track {
  display: grid;
  width: var(--card);
}
.video-card {
  grid-area: 1 / 1;
  min-width: 0;
  transition:
    transform 0.6s var(--ease),
    opacity 0.6s var(--ease),
    filter 0.6s var(--ease);
}
.video-card-media {
  position: relative;
  overflow: hidden;
  aspect-ratio: 9 / 14;
  border-radius: 1rem;
  background: #07243a;
}
.video-card-media img,
.video-card-media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The video fades in over its poster once it is actually playing, so a
   slow start never shows a black box. */
.video-card-media video {
  opacity: 0;
  transition: opacity 0.4s;
}
.video-card.is-playing video {
  opacity: 1;
}
.video-card figcaption {
  padding-top: 0.75rem;
  color: #d8edf0;
  font-size: 0.95rem;
  transition: opacity 0.3s;
}
.video-card[data-slot="active"] {
  z-index: 3;
}
.video-card[data-slot="prev"],
.video-card[data-slot="next"] {
  z-index: 2;
  cursor: pointer;
  opacity: 0.5;
  filter: brightness(0.55) saturate(0.7) blur(1px);
}
.video-card[data-slot="prev"] {
  transform: translateX(-62%) scale(0.78);
}
.video-card[data-slot="next"] {
  transform: translateX(62%) scale(0.78);
}
.video-card[data-slot="prev"]:hover,
.video-card[data-slot="next"]:hover {
  opacity: 0.7;
}
.video-card:is([data-slot="prev"], [data-slot="next"], [data-slot="off"]) figcaption {
  opacity: 0;
}
.video-card[data-slot="off"] {
  z-index: 1;
  opacity: 0;
  visibility: hidden;
  transform: scale(0.6);
}
/* Without JavaScript every card has no slot: show only the first. */
.video-card:not([data-slot]) + .video-card:not([data-slot]) {
  display: none;
}
.video-carousel-progress {
  width: var(--card);
  height: 3px;
  margin: 0.9rem auto 0;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.18);
  overflow: hidden;
}
.video-carousel-progress span {
  display: block;
  width: 0;
  height: 100%;
  background: var(--aqua);
}
.video-carousel-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding-top: 0.9rem;
}
.video-carousel-count {
  min-width: 3.5rem;
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.video-carousel-toggle {
  display: inline-grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 50%;
  color: var(--white);
}
.video-carousel-toggle .icon:last-child,
.video-carousel-toggle[aria-pressed="true"] .icon:first-of-type {
  display: none;
}
.video-carousel-toggle[aria-pressed="true"] .icon:last-child {
  display: block;
}
.video-carousel-arrow {
  position: absolute;
  top: calc(50% - 1rem);
  z-index: 4;
  width: 2.75rem;
  height: 2.75rem;
  display: inline-grid;
  place-items: center;
  border: 1px solid currentColor;
  border-radius: 50%;
  background: rgba(11, 49, 74, 0.55);
  color: var(--white);
  transform: translateY(-50%);
}
.video-carousel-previous {
  left: max(0rem, calc(50% - var(--card) / 2 - 8rem));
}
.video-carousel-next {
  right: max(0rem, calc(50% - var(--card) / 2 - 8rem));
}
.video-carousel-arrow[hidden],
.video-carousel-toggle[hidden] {
  display: none;
}
.work-grid {
  display: grid;
  grid-template-columns: 1fr 1.35fr 1fr;
  gap: 1.5rem;
  align-items: start;
}
.work-card:nth-child(2) {
  padding-top: 4rem;
}
.work-card:nth-child(3) {
  padding-top: 8rem;
}
.work-media {
  display: block;
  position: relative;
  overflow: hidden;
  text-decoration: none;
  aspect-ratio: 3/4;
  background: #dfe8ec;
}
.work-media img {
  height: 100%;
  width: 100%;
  object-fit: cover;
  transition: transform 0.4s var(--ease);
}
.work-card:nth-child(2) .work-media {
  aspect-ratio: 1/1.1;
}
.work-media:hover img {
  transform: scale(1.02);
}
.work-caption {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1rem;
  font-size: 1rem;
}
.work-caption span:first-child {
  color: var(--secondary);
}
.process-section {
  position: relative;
  border-bottom: 1px solid var(--rule);
}
/* While the drawing builds, the layout stays pinned, centred in the space
   below the header (app.js measures --process-height). The section is
   that height plus 130svh of scrolling: the build runs over the middle of
   it (see updateFromScroll). */
.process-section.process-scroll {
  min-height: calc(var(--process-height, 36rem) + 2 * clamp(4rem, 8vw, 8rem) + 130svh);
}
.process-layout {
  display: grid;
  grid-template-columns: 1fr 1.55fr;
  gap: 1rem;
  position: sticky;
  top: max(
    calc(var(--header) + 1rem),
    calc(50svh + var(--header) / 2 - var(--process-height, 36rem) / 2)
  );
  align-items: start;
}
.process-intro {
  padding-top: 2rem;
  padding-right: 1rem;
}
.process-intro h2 {
  font-size: clamp(2.25rem, 4vw, 4rem);
  margin-bottom: 1.5rem;
}
.process-intro > p:not(.eyebrow) {
  color: var(--secondary);
  max-width: 31rem;
}
.process-figure {
  position: relative;
  padding: 1rem 0 0;
  min-width: 0;
}
.pool-diagram {
  width: 100%;
  height: auto;
  overflow: visible;
  aspect-ratio: 1.4;
  max-height: 36rem;
}
.drawing-grid {
  opacity: 0.48;
}
.drawing-surface {
  fill: var(--white);
  stroke: var(--ink);
  stroke-width: 1.3;
  vector-effect: non-scaling-stroke;
}
.drawing-line {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.25;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.drawing-fine {
  fill: none;
  stroke: #708691;
  stroke-width: 0.8;
  vector-effect: non-scaling-stroke;
}
.drawing-hidden {
  stroke-dasharray: 4 6;
}
.sketch-ready .sketch-stage {
  opacity: var(--stage-opacity, 1);
  transform: translateY(var(--stage-rise, 0));
  transition:
    opacity 0.1s linear,
    transform 0.1s linear;
}
.sketch-ready .draw-trace {
  stroke-dasharray: 1;
  stroke-dashoffset: var(--stage-offset, 0);
}
.stage-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 2rem;
  list-style: none;
}
.stage-button {
  min-width: 3rem;
  min-height: 3rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: 50%;
  font-size: 1rem;
  transition:
    color 0.15s,
    background 0.15s;
}
.stage-button[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: white;
}

.stage-detail {
  min-height: 6rem;
  margin-top: 1.5rem;
}
.stage-detail strong {
  display: block;
  font-size: 1.25rem;
  font-weight: 500;
  margin-bottom: 0.3rem;
}
.stage-detail p {
  font-size: 1rem;
  color: var(--secondary);
}
.process-actions {
  display: flex;
  gap: 1rem;
  align-items: center;
  margin-top: 0.5rem;
  flex-wrap: wrap;
}
.process-actions .text-link {
  font-size: 1rem;
}
.service-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3rem;
}
.service-image {
  position: relative;
  display: block;
  overflow: hidden;
  aspect-ratio: 1.25;
  background: var(--mist);
}
.service-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s var(--ease);
}
.service-image:hover img {
  transform: scale(1.02);
}
.service-caption {
  display: flex;
  gap: 1rem;
  justify-content: space-between;
  align-items: start;
  padding: 1.5rem 0;
  border-bottom: 1px solid var(--rule);
}
.service-caption h3 {
  font-size: clamp(1.8rem, 2.7vw, 2.5rem);
}
.service-body {
  padding-top: 1.5rem;
  color: var(--secondary);
  font-size: 1.0625rem;
}
.service-body .text-link {
  color: var(--ink);
  margin-top: 1.5rem;
}
.review-section {
  background: var(--mist);
}
.review-layout,
.faq-layout {
  display: grid;
  grid-template-columns: 1fr 1.3fr;
  gap: 6rem;
}
.faq-intro {
  color: var(--secondary);
  max-width: 24rem;
  margin-top: 1.5rem;
}
.faq-list {
  border-top: 1px solid var(--rule);
}
.faq-item summary {
  font-size: 1.125rem;
  min-height: 4rem;
  padding-block: 1rem;
  cursor: pointer;
}
.faq-item p {
  max-width: 40rem;
}
/* 404 page: the main pages as large rows, each with a line on what it is. */
.notfound-section {
  padding-top: 0;
}
.notfound-links {
  list-style: none;
  border-top: 1px solid var(--rule);
}
.notfound-links li {
  border-bottom: 1px solid var(--rule);
}
.notfound-link {
  display: grid;
  grid-template-columns: minmax(12rem, 1fr) 2fr auto;
  align-items: center;
  gap: 0.5rem 2rem;
  padding: 1.5rem 0;
  text-decoration: none;
  transition: padding 0.35s var(--ease), color 0.2s;
}
.notfound-link-name {
  font-size: clamp(1.4rem, 2.2vw, 2rem);
  letter-spacing: -0.02em;
  line-height: 1.2;
}
.notfound-link-copy {
  color: var(--secondary);
}
.notfound-link .icon {
  width: 1.4rem;
  height: 1.4rem;
  transition: transform 0.35s var(--ease);
}
.notfound-link:hover,
.notfound-link:focus-visible {
  color: var(--teal);
  padding-inline: 0.75rem;
}
.notfound-link:hover .icon,
.notfound-link:focus-visible .icon {
  transform: translate(0.2rem, -0.2rem);
}
@media (max-width: 767px) {
  .notfound-link {
    grid-template-columns: 1fr auto;
    padding: 1.15rem 0;
  }
  .notfound-link-copy {
    grid-column: 1;
    font-size: 0.9375rem;
  }
  .notfound-link .icon {
    grid-row: 1 / span 2;
    grid-column: 2;
  }
}
html[data-motion="reduced"] .notfound-link {
  transition: none;
}
.featured-review {
  padding-top: 1rem;
  position: relative;
}
.quote-mark {
  font-size: 6rem;
  line-height: 0.7;
  letter-spacing: -0.1em;
  color: var(--teal);
  margin-bottom: 1rem;
  font-family: inherit;
}
.featured-review blockquote {
  font-size: clamp(1.4rem, 2.1vw, 2rem);
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: -0.02em;
}
.review-byline {
  display: flex;
  gap: 1.2rem;
  align-items: center;
  margin-top: 1.5rem;
  font-size: 1rem;
}
.review-byline time {
  color: var(--secondary);
}
.all-reviews {
  grid-column: 1/-1;
  border-top: 1px solid var(--rule);
  margin-top: 1rem;
}
.all-reviews summary {
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1.5rem 0;
  font-size: 1rem;
  font-weight: 500;
  min-height: 3rem;
}
.all-reviews summary::-webkit-details-marker {
  display: none;
}
.all-reviews[open] summary .icon {
  transform: rotate(45deg);
}
/* The open review list under the featured quote. Reviews written on this
   website sit on white; reviews imported from Google sit on the pale
   pool-water tint with teal stars and label, so the source reads at a
   glance. app.js shows two rows and adds two more with "show more". */
.review-feed {
  grid-column: 1 / -1;
  border-top: 1px solid var(--rule);
  padding-top: 2.5rem;
  margin-top: 1rem;
}
.review-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.25rem;
  list-style: none;
}
.review-entry {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.75rem 1.75rem 1.5rem;
  border-radius: 14px;
  background: var(--white);
}
.review-entry[data-source="google"] {
  background: var(--pale);
}
/* Cards in one batch arrive a beat apart (see app.js). */
.review-entry.reveal-pending {
  transition-delay: calc(var(--arrive, 0) * 90ms);
}
.review-entry:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 3px;
}
.review-source {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.65rem;
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  line-height: 1.4;
  color: var(--secondary);
}
.review-entry[data-source="google"] .review-source {
  color: var(--teal);
}
.review-stars {
  display: inline-flex;
  gap: 0.15rem;
}
.review-stars svg {
  width: 1rem;
  height: 1rem;
  fill: currentColor;
}
.review-stars svg.is-empty {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linejoin: round;
}
.review-entry blockquote {
  flex: 1;
  font-size: 1.0625rem;
  line-height: 1.6;
}
/* Reviews keep their writers' own paragraph breaks. */
.review-entry blockquote p {
  white-space: pre-line;
}
.review-entry .review-byline {
  margin-top: 0;
  font-size: 0.9375rem;
}
.review-more {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
  margin-top: 2rem;
}
.review-more .text-link {
  font-size: 1rem;
}
.review-count {
  font-size: 0.9375rem;
  color: var(--secondary);
}
/* "Write a review" and the moderation note follow the list in its column,
   rather than as rows of the section grid with its wide gaps. */
.review-feed .review-write {
  margin-top: 2.5rem;
}
/* "Write a review": a second disclosure under the list. Submissions wait
   for the admin's approval, so the form only ever says it was received. */
.review-write {
  margin-top: 0;
}
.review-form {
  max-width: 44rem;
  padding-bottom: 2rem;
}
.review-form .form-grid {
  grid-template-columns: minmax(0, 1fr);
}
.review-form #review-name {
  max-width: 22rem;
}
.review-form-intro {
  color: var(--secondary);
  margin-bottom: 1.25rem;
}
.review-consent label {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  font-size: 0.9375rem;
  line-height: 1.5;
  cursor: pointer;
}
.review-consent input[aria-invalid="true"] {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
.review-consent input {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 0.1rem;
  accent-color: var(--teal);
}
.review-submit {
  margin-top: 1.5rem;
}
.review-submit[aria-busy="true"] {
  opacity: 0.7;
  pointer-events: none;
}
/* Cloudflare Turnstile bot check (turnstile.js): room reserved for the
   widget so the form does not jump when it appears. */
.turnstile-slot {
  min-height: 65px;
  margin-top: 1rem;
}
/* Short privacy notice beside each form (templates.py privacy_note()). */
.form-privacy {
  margin-top: 0.8rem;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--secondary);
}
.form-privacy a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.15em;
}
/* How reviews are moderated, under the review list. */
.review-policy {
  grid-column: 1 / -1;
  max-width: 48rem;
  margin-top: 1.25rem;
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--secondary);
}
/* Trap field for spam bots (see templates.py honeypot()): off-screen,
   hidden from assistive technology and out of the Tab order. */
.honeypot {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.enquiry-section {
  isolation: isolate;
  background: var(--ink);
  color: white;
  position: relative;
  overflow: hidden;
}
.enquiry-section .container {
  position: relative;
  z-index: 1;
}
.enquiry-layout {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 5rem;
  align-items: end;
}
.enquiry-section h2 {
  font-size: clamp(2.7rem, 5.5vw, 5.5rem);
  font-weight: 400;
}
.enquiry-copy > p {
  margin-bottom: 2rem;
  max-width: 31rem;
}
.enquiry-links {
  display: flex;
  align-items: center;
  gap: 2rem;
  flex-wrap: wrap;
  margin-top: 1.5rem;
}
.enquiry-links a {
  font-size: 1rem;
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
}
/* --------------------------------------------------------------------------
 * Shared footer
 * -------------------------------------------------------------------------- */
.site-footer {
  padding-top: 4rem;
  background: white;
}
.footer-top {
  display: grid;
  grid-template-columns: 1.2fr 1fr 1fr;
  gap: 4rem;
  padding-bottom: 4rem;
}
.footer-top p {
  font-size: 1rem;
  color: var(--secondary);
  max-width: 19rem;
  margin-top: 1rem;
}
/* Name, services and area, worded exactly as on the Google profile. */
.footer-top .footer-summary {
  font-size: 0.875rem;
  line-height: 1.55;
  max-width: 22rem;
  margin-top: 0.75rem;
}
.footer-nav {
  list-style: none;
  display: grid;
  gap: 0.1rem;
}
.footer-nav a {
  font-size: 1rem;
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  text-decoration: none;
}
.footer-nav a:hover {
  text-decoration: underline;
}
.footer-contact .footer-phone {
  font-size: clamp(1.2rem, 2vw, 1.75rem);
  text-decoration: none;
  display: inline-block;
  margin-top: 1rem;
  letter-spacing: -0.02em;
}
.footer-contact .text-link {
  display: flex;
  width: fit-content;
}
.footer-bottom {
  border-top: 1px solid var(--rule);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 1.25rem 0;
  font-size: 1rem;
}
.footer-utilities {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.motion-toggle {
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0;
  font-size: 1rem;
  text-decoration: underline;
  text-underline-offset: 0.25em;
}
.footer-signature {
  font-size: clamp(5rem, 20vw, 22rem);
  font-weight: 500;
  line-height: 0.95;
  letter-spacing: -0.065em;
  color: #dce7ec;
  margin-left: -0.045em;
  overflow: hidden;
  user-select: none;
  white-space: nowrap;
}
/* The word is drawn by CSS, so this pale watermark is pure decoration and
   is not read or contrast-checked as text (the page's real text is). */
.footer-signature::before {
  content: attr(data-word);
}
/* Studio credit: the last line of the page, under the FAGORA signature. */
.footer-credit {
  /* A paragraph, but it spans the footer like the rule above it. */
  max-width: none;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.35rem 0.6rem;
  padding: 1rem 0 1.5rem;
  border-top: 1px solid var(--rule);
  font-size: 0.875rem;
  color: var(--secondary);
}
.footer-credit-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  color: var(--ink);
}
.footer-credit-brand strong {
  font-weight: 600;
  letter-spacing: 0.01em;
}
.footer-credit-mark {
  width: 1.05rem;
  height: 1.05rem;
  flex: none;
}
/* --------------------------------------------------------------------------
 * Interior service pages
 * -------------------------------------------------------------------------- */
/* Fitted image compositions and alternating stories on the service pages. */
.page-intro {
  padding-top: clamp(3rem, 5vw, 5rem);
  padding-bottom: 3rem;
}
.page-intro .intro-row {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 5rem;
  align-items: end;
}
.page-intro h1 {
  font-size: clamp(2.8rem, 5.5vw, 5.5rem);
  font-weight: 400;
}
.page-intro .lead {
  color: var(--secondary);
  font-size: 1.125rem;
  line-height: 1.7;
}
.service-mosaic {
  display: grid;
  grid-template-columns: 1.2fr 0.85fr 0.85fr;
  gap: 1rem;
  height: clamp(26rem, 40vw, 40rem);
}
.service-mosaic figure {
  position: relative;
  overflow: hidden;
  background: var(--mist);
}
.service-mosaic img {
  height: 100%;
  width: 100%;
  object-fit: cover;
  transition: transform 1s var(--ease);
}
.service-mosaic figure:hover img {
  transform: scale(1.04);
}
.service-mosaic figcaption {
  position: absolute;
  inset: auto 1rem 1rem;
  width: fit-content;
  padding: 0.4rem 0.8rem;
  background: rgba(11, 49, 74, 0.94);
  color: white;
  font-size: 0.9375rem;
  border-radius: 1.5rem;
  max-width: calc(100% - 2rem);
}
.renovation-mosaic figure:nth-child(2) {
  margin-top: 2.5rem;
}
.renovation-mosaic figure:nth-child(3) {
  margin-bottom: 2.5rem;
}
.concrete-mosaic {
  grid-template-columns: 1.5fr 0.75fr;
  grid-template-rows: 1fr 1fr;
}
.concrete-mosaic figure:first-child {
  grid-row: 1/3;
}
.concrete-mosaic figure:nth-child(2) img {
  object-position: center 65%;
}
.service-stories {
  display: grid;
  gap: 5rem;
}
.service-story {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: clamp(3rem, 6vw, 6rem);
  align-items: center;
}
.service-story:nth-child(even) > figure {
  order: 2;
}
.service-story > div {
  max-width: 32rem;
}
.service-story h2 {
  font-size: clamp(2rem, 3.2vw, 3.2rem);
  margin-bottom: 1.5rem;
}
.service-story p {
  color: var(--secondary);
}
.story-media,
.detail-media {
  display: block;
  position: relative;
  overflow: hidden;
  background: var(--mist);
  aspect-ratio: 4/3;
}
.story-media img,
.detail-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.8s var(--ease);
}
.story-media:hover img,
.detail-media:hover img {
  transform: scale(1.04);
}
.service-story:nth-child(2) .story-media {
  aspect-ratio: 1.2;
  max-height: 35rem;
}
.service-story:nth-child(2) img {
  object-position: center 65%;
}
.statement-layout {
  display: flex;
  justify-content: space-between;
  gap: 4rem;
  align-items: end;
}
.statement {
  font-size: clamp(2rem, 4vw, 4rem);
  font-weight: 400;
  line-height: 1.15;
  max-width: 24ch;
}
.statement-layout > .text-link {
  flex: none;
}
.statement-section {
  background: var(--mist);
}
.detail-images {
  display: grid;
  gap: 2rem;
  margin-top: 3rem;
}
.detail-pair {
  grid-template-columns: 1fr 1fr;
}
.detail-media {
  aspect-ratio: 1.3;
}
.detail-images figcaption {
  font-size: 1rem;
  margin-top: 1rem;
  color: var(--secondary);
}
.detail-pair img {
  object-position: center 55%;
}
.concrete-benefits {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: clamp(3rem, 6vw, 6rem);
  align-items: center;
}
.concrete-feature figure {
  margin-bottom: 2rem;
  overflow: hidden;
}
.concrete-feature img {
  width: 100%;
  aspect-ratio: 1.45;
  object-fit: cover;
}
.concrete-feature h2 {
  font-weight: 400;
}
.concrete-benefits h3 {
  font-size: 1.5rem;
  margin-bottom: 1.5rem;
}
.surface-details {
  grid-template-columns: 1.25fr 1fr;
}
.surface-details figure:nth-child(2) {
  padding-top: 4rem;
}
.surface-details figure:nth-child(3) {
  padding-right: 4rem;
}
.surface-details figure:nth-child(4) {
  padding-top: 4rem;
}
.surface-details .detail-media {
  aspect-ratio: 1.6;
}
.surface-details figure:nth-child(n + 3) .detail-media {
  aspect-ratio: 1.2;
}
.surface-cta {
  margin-top: 2.5rem;
}
/* --------------------------------------------------------------------------
 * Gallery
 * -------------------------------------------------------------------------- */
/* Masonry photographs and film previews; hovering plays a silent preview clip. */
.gallery-section {
  padding-top: 0;
}
.gallery-opening {
  padding-block: clamp(3rem, 5vw, 5rem) clamp(2rem, 4vw, 4rem);
}
.gallery-opening-layout {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 6vw, 6rem);
  align-items: end;
}
.gallery-opening-copy {
  padding-bottom: 1rem;
}
.gallery-opening h1 {
  max-width: 8ch;
  font-size: clamp(3rem, 6vw, 6rem);
  font-weight: 400;
}
.gallery-opening .lead {
  max-width: 34rem;
  margin-top: 1.5rem;
  color: var(--secondary);
  font-size: 1.125rem;
  line-height: 1.7;
}
.gallery-opening-image {
  margin: 0;
  overflow: hidden;
  background: var(--mist);
}
.gallery-opening-image img {
  width: 100%;
  aspect-ratio: 1.35;
  object-fit: cover;
}
.gallery-opening-image figcaption {
  padding-top: 0.65rem;
  color: var(--secondary);
  font-size: 0.875rem;
}
.gallery-controls {
  display: flex;
  gap: 1rem;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 1.5rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--rule);
}
.filter-list {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
  list-style: none;
}
.filter-button {
  border: 1px solid transparent;
  min-height: 2.75rem;
  padding: 0.55rem 1rem;
  border-radius: 2rem;
  font-size: 1rem;
  line-height: 1.4;
}
.filter-button[aria-pressed="true"] {
  color: white;
  background: var(--ink);
  border-color: var(--ink);
  --wave-fill: var(--teal);
}
.gallery-count {
  font-size: 0.9375rem;
  color: var(--secondary);
  white-space: nowrap;
}
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.25rem;
  list-style: none;
  align-items: start;
}
.gallery-grid.masonry-ready {
  grid-auto-rows: 8px;
  row-gap: 16px;
  align-items: start;
  /* Back-fill the gap a wide photo would leave (e.g. after a lone tile on
     phones) with the next photo that fits. */
  grid-auto-flow: row dense;
}
.gallery-item {
  min-width: 0;
  break-inside: avoid;
}
.gallery-item.is-landscape {
  grid-column: span 2;
}
.gallery-item figure {
  margin: 0;
}
.gallery-media {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--mist);
  aspect-ratio: var(--media-ratio, 1);
  isolation: isolate;
  border-radius: 4px;
}
.gallery-media img {
  height: 100%;
  width: 100%;
  object-fit: cover;
  transition: transform 0.8s var(--ease);
}
.gallery-media:hover img {
  transform: scale(1.04);
}
/* Each photo's description, with its category as a quiet tag. */
.gallery-item figcaption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.25rem 0.9rem;
  font-size: 0.9375rem;
  line-height: 1.4;
  padding: 0.75rem 0.2rem 0.2rem;
  color: var(--secondary);
}
.gallery-caption {
  flex: 1 1 14rem;
  min-width: 0;
  color: var(--ink);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}
.gallery-tag {
  flex: none;
  font-size: 0.8125rem;
  letter-spacing: 0.01em;
  color: var(--teal);
}
/* "View larger": a real button over the photo; its icon shows on hover
   and keyboard focus. The cursor says what a click does. */
.media-open {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: block;
  width: 100%;
  border: 0;
  background: transparent;
  cursor: zoom-in;
}
.media-open:focus-visible {
  outline: 2px solid var(--aqua);
  outline-offset: -4px;
}
.media-open-icon {
  position: absolute;
  top: 0.8rem;
  right: 0.8rem;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  color: var(--ink);
  box-shadow: 0 6px 18px -8px rgba(11, 49, 74, 0.55);
  opacity: 0;
  transform: scale(0.85);
  transition:
    opacity 0.3s var(--ease),
    transform 0.3s var(--ease);
}
.media-open-icon .icon {
  width: 1.1rem;
  height: 1.1rem;
}
.media-open:hover .media-open-icon,
.media-open:focus-visible .media-open-icon {
  opacity: 1;
  transform: none;
}
.gallery-opening-image {
  position: relative;
}

/* Full-screen photo viewer (templates.py viewer(), app.js). The photo is
   never enlarged past its own size; its average colour fills the frame
   while it loads, and it slides in from the side it came from. */
.viewer {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: #06202f;
  color: var(--white);
  overflow: hidden;
}
.viewer[open] {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  animation: viewer-in 0.35s var(--ease) both;
}
.viewer::backdrop {
  background: #06202f;
}
@keyframes viewer-in {
  from {
    opacity: 0;
  }
}
.viewer-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem var(--gutter);
}
.viewer-count {
  font-size: 0.9375rem;
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, 0.78);
}
.viewer-close,
.viewer-nav {
  display: inline-grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.04);
  color: var(--white);
  transition:
    background 0.2s,
    border-color 0.2s;
}
.viewer-close:hover,
.viewer-nav:hover {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.7);
}
.viewer-close:focus-visible,
.viewer-nav:focus-visible {
  outline: 2px solid var(--aqua);
  outline-offset: 3px;
}
.viewer-stage {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 1.5rem;
  min-height: 0;
  padding: 0 var(--gutter) 2rem;
  touch-action: pan-y pinch-zoom;
}
.viewer-figure {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 1rem;
  min-height: 0;
  height: 100%;
  margin: 0;
}
.viewer-image {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: calc(100dvh - 11rem);
  border-radius: 4px;
  object-fit: contain;
  transition:
    opacity 0.35s var(--ease),
    transform 0.45s var(--ease);
}
.viewer-image.is-changing {
  opacity: 0;
  transform: translateX(calc(var(--viewer-direction, 1) * 1.5rem));
}
.viewer-caption {
  max-width: 60ch;
  min-height: 1.5em;
  text-align: center;
  font-size: 1rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.86);
}
.video-badge {
  position: absolute;
  left: 1rem;
  top: 1rem;
  background: rgba(11, 49, 74, 0.94);
  color: white;
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.3rem 0.7rem;
  font-size: 0.9375rem;
  border-radius: 2rem;
  z-index: 3;
}
.video-badge .icon {
  width: 1rem;
  height: 1rem;
}
.video-preview {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.35s;
  pointer-events: none;
}
.gallery-media.is-previewing .video-preview {
  opacity: 1;
}
.gallery-more-wrap {
  display: flex;
  justify-content: center;
  padding: 3rem 0 0;
}
.no-script-notice {
  padding: 1rem;
  background: var(--pale);
  font-size: 1rem;
}
/* --------------------------------------------------------------------------
 * Contact form
 * -------------------------------------------------------------------------- */
.contact-main {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: 4rem 6rem;
  background: var(--mist);
}
.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.1rem 1rem;
}
.field-full {
  grid-column: 1/-1;
}
.form-field label {
  display: block;
  font-size: 0.9375rem;
  font-weight: 500;
  margin-bottom: 0.45rem;
}
.form-field label span {
  font-weight: 400;
  color: var(--secondary);
  font-size: 0.875rem;
}
.form-field input,
.form-field textarea {
  display: block;
  width: 100%;
  min-width: 0;
  min-height: 3rem;
  border: 1px solid var(--border);
  border-radius: 0.6rem;
  padding: 0.65rem 0.8rem;
  background: white;
  color: var(--ink);
  font-size: 1rem;
  line-height: 1.5;
  transition:
    border-color 0.25s,
    box-shadow 0.25s;
}
.form-field textarea {
  min-height: 7rem;
  resize: vertical;
}
.form-field input::placeholder,
.form-field textarea::placeholder {
  color: var(--secondary);
  opacity: 1;
}
.form-field [aria-invalid="true"] {
  border-width: 2px;
  border-color: var(--ink);
}
.field-error {
  font-size: 0.9375rem;
  color: var(--ink);
  margin-top: 0.5rem;
  font-weight: 500;
}
.form-submit {
  margin-top: 1.5rem;
}
.form-submit .button {
  width: 100%;
  gap: 1rem;
}
.form-handoff-note {
  font-size: 0.875rem;
  color: var(--secondary);
  margin-top: 0.8rem;
  line-height: 1.5;
}
.form-feedback {
  margin-top: 1rem;
  font-size: 1rem;
  padding: 1rem;
  border: 1px solid var(--border);
  background: var(--pale);
  color: var(--ink);
  border-radius: 0.6rem;
}
.form-feedback .text-link {
  margin-top: 0.5rem;
}
/* The enquiry went through (app.js): the confirmation replaces the send
   button, with the reference in large tabular figures so it is easy to
   read out or copy. */
.contact-form.is-sent [data-form-submit],
.contact-form.is-sent .form-handoff-note,
.contact-form.is-sent .flash-change {
  display: none;
}
.form-feedback:has(.form-sent) {
  padding: 1.1rem 1.15rem 1rem;
  border-color: transparent;
}
.form-sent {
  display: grid;
  gap: 0.45rem;
  font-size: 0.9375rem;
  line-height: 1.5;
}
.form-sent-title {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 1.0625rem;
  font-weight: 600;
}
.form-sent-title svg {
  flex: none;
  width: 1.6rem;
  height: 1.6rem;
  padding: 0.3rem;
  border-radius: 50%;
  background: var(--teal);
  fill: none;
  stroke: var(--white);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.form-sent-reference {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.25rem 0.6rem;
  margin-block: 0.15rem 0.2rem;
  color: var(--secondary);
}
.form-sent-reference strong {
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  user-select: all;
}
.asset-credit {
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--secondary);
  margin-top: 1rem;
  text-align: center;
}
/* Liquid fill is shared by every primary button and gallery/stage control. */
.button,
.icon-button,
.stage-button,
.filter-button {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  transition:
    color 0.3s,
    background 0.3s,
    border-color 0.3s,
    transform 0.3s var(--ease);
}
:is(.button, .icon-button, .stage-button, .filter-button)::before {
  content: "";
  position: absolute;
  z-index: -1;
  pointer-events: none;
  width: 230%;
  height: 350%;
  left: -65%;
  top: 115%;
  border-radius: 43% 46% 42% 45%;
  background: var(--wave-fill, var(--pale));
  transition:
    top 0.65s var(--ease),
    transform 1s var(--ease);
  transform: rotate(-12deg);
}
:is(.button, .icon-button, .stage-button, .filter-button):is(
    :hover,
    :focus-visible
  )::before {
  top: -85%;
  transform: rotate(35deg);
}
.button-primary,
.stage-button[aria-pressed="true"] {
  --wave-fill: var(--teal);
}
.button-outline {
  --wave-fill: var(--ink);
}
.button-outline:focus-visible {
  color: white;
  background: var(--ink);
}
.button-ripple {
  position: absolute;
  z-index: 2;
  width: 12px;
  height: 12px;
  border: 1px solid currentColor;
  border-radius: 50%;
  pointer-events: none;
  transform: translate(-50%, -50%);
  animation: button-ripple 0.65s ease-out forwards;
}
@keyframes button-ripple {
  to {
    width: 420px;
    height: 420px;
    opacity: 0;
  }
}
.enquiry-line,
.intro-section::before {
  content: "";
  position: absolute;
  inset: -20%;
  pointer-events: none;
  z-index: -1;
  opacity: 0.32;
  background: repeating-radial-gradient(
    ellipse at 80% 20%,
    transparent 0 45px,
    rgba(60, 195, 198, 0.18) 46px 47px,
    transparent 49px 94px
  );
  animation: water-drift 18s ease-in-out infinite alternate;
  transform-origin: center;
}
.enquiry-line {
  z-index: 0;
  opacity: 0.55;
}
.intro-section::before {
  opacity: 0.13;
}
@keyframes water-drift {
  from {
    transform: translate3d(-2%, -1%, 0) rotate(-5deg) scale(1);
  }
  to {
    transform: translate3d(2%, 2%, 0) rotate(5deg) scale(1.06);
  }
}
.reveal-pending {
  opacity: 0;
  transform: translateY(1.5rem);
  transition:
    opacity 0.8s var(--ease),
    transform 0.8s var(--ease);
}
.reveal-pending.is-visible,
.reveal-pending:focus-within {
  opacity: 1;
  transform: none;
}

/* --------------------------------------------------------------------------
 * Responsive layout overrides
 * -------------------------------------------------------------------------- */
@media (min-width: 768px) and (max-width: 1050px) {
  :root {
    --header: 8rem;
  }
  .header-inner {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-rows: 4.4rem 3.6rem;
    gap: 0 1rem;
  }
  .desktop-nav {
    grid-column: 1/-1;
    grid-row: 2;
    margin: 0;
  }
  .desktop-nav ul {
    justify-content: space-between;
    gap: 1rem;
  }
  .header-actions {
    grid-column: 2;
    grid-row: 1;
  }
  .site-header.is-scrolled {
    height: var(--header);
  }
  .brand,
  .site-header.is-scrolled .brand {
    --logo: 3rem;
  }
  .desktop-nav a {
    font-size: 0.9375rem;
  }
}
@media (max-width: 1199px) {
  .intro-feature {
    gap: 3rem;
  }
  .intro-photographs {
    padding-right: 2rem;
  }
  .intro-story h2 {
    font-size: 3rem;
  }
  .process-layout {
    grid-template-columns: 1fr 1.3fr;
  }
  .process-intro h2 {
    font-size: 3rem;
  }
  .review-layout,
  .faq-layout,
  .enquiry-layout,
  .footer-top,
  .page-intro .intro-row {
    gap: 3rem;
  }
  .service-grid {
    gap: 2rem;
  }
}
@media (max-width: 900px) {
  .intro-feature {
    gap: 2rem;
  }
  .intro-photographs {
    padding: 0 1rem 3rem 0;
  }
  .intro-story h2 {
    font-size: 2.6rem;
  }
  .process-layout {
    grid-template-columns: 1fr 1.15fr;
  }
  .process-intro h2 {
    font-size: 2.7rem;
  }
  .process-intro {
    padding-right: 0;
  }
  .gallery-controls {
    align-items: start;
    flex-direction: column;
  }
  .gallery-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .gallery-item.is-landscape {
    grid-column: span 1;
  }
  .review-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .footer-top {
    grid-template-columns: 1fr 1fr;
  }
  .footer-contact {
    grid-column: 1/-1;
  }
}
/* Short laptop windows: a tighter pool-construction layout, so the whole
   drawing and its stage text fit on screen while it builds. Below 540px
   tall, app.js shows it finished, with the play button, instead. */
@media (min-width: 768px) and (max-height: 760px) {
  .process-intro {
    padding-top: 0;
  }
  .process-intro .eyebrow {
    margin-bottom: 1rem;
  }
  .process-intro h2 {
    font-size: clamp(2rem, 3.2vw, 2.75rem);
    margin-bottom: 1rem;
  }
  .stage-buttons {
    margin-top: 1.25rem;
  }
  .stage-button {
    min-width: 2.75rem;
    min-height: 2.75rem;
  }
  .stage-detail {
    min-height: 5rem;
    margin-top: 1rem;
  }
  .process-figure {
    padding-top: 0;
  }
  .pool-diagram {
    max-height: calc(100svh - var(--header) - 2.5rem);
  }
}
@media (max-width: 767px) {
  :root {
    --gutter: 1.25rem;
    --header: 4.75rem;
  }
  /* Phones: the silhouettes peek in from the edges, arrows over them. */
  .video-card[data-slot="prev"] {
    transform: translateX(-48%) scale(0.72);
  }
  .video-card[data-slot="next"] {
    transform: translateX(48%) scale(0.72);
  }
  .video-carousel-previous {
    left: 0;
  }
  .video-carousel-next {
    right: 0;
  }
  body {
    font-size: 1.0625rem;
  }
  .brand {
    --logo: 2.9rem;
  }
  .site-header.is-scrolled {
    height: 4.25rem;
  }
  .site-header.is-scrolled .brand {
    --logo: 2.5rem;
  }
  .header-inner {
    gap: 1rem;
  }
  .header-actions {
    gap: 0.7rem;
  }
  .desktop-nav {
    display: none;
  }
  .menu-toggle {
    display: flex;
  }
  .menu-toggle > span:first-child {
    display: none;
  }
  .hero {
    min-height: max(42rem, 92svh);
    max-height: none;
  }
  /* Phones stack the hero instead of covering the photo: the pool photo
     fills a band under the header and stays clear, fading into ink over
     its last few rem, and the headline always starts inside that fade -
     so no overlay ever has to darken the pool to keep white text legible. */
  .hero {
    --hero-photo: 52svh;
    min-height: 0;
    align-items: flex-start;
  }
  .hero-image,
  .hero-scrim {
    inset: var(--header) 0 auto;
    height: var(--hero-photo);
  }
  .hero-image img {
    object-position: 50% 62%;
  }
  .hero-scrim {
    background: linear-gradient(
      180deg,
      rgba(11, 49, 74, 0) 0,
      rgba(11, 49, 74, 0) 72%,
      rgba(11, 49, 74, 0.7) 88%,
      var(--ink) 100%
    );
  }
  .hero-content {
    max-width: none;
    width: min(calc(100% - var(--gutter) * 2), var(--max));
    margin-inline: auto;
    padding: calc(var(--header) + var(--hero-photo) - 2.5rem) 0 6.5rem;
  }
  .hero h1 {
    font-size: clamp(2.75rem, 11vw, 4.5rem);
  }
  .hero-title-text {
    max-width: 11ch;
  }
  .hero-copy {
    font-size: 1.0625rem;
    max-width: 28rem;
    margin-block: 1.5rem 2rem;
  }
  .hero-bottom {
    bottom: 1.25rem;
  }
  .hero-scroll {
    font-size: 0.9375rem;
  }
  .section {
    padding-block: 3.75rem;
  }
  .section-heading {
    grid-template-columns: 1fr;
    gap: 1.5rem;
    margin-bottom: 2rem;
  }
  .section-heading .text-link {
    justify-self: start;
  }
  .section-heading h2 {
    font-size: 2.6rem;
  }
  .eyebrow {
    margin-bottom: 1.25rem;
  }
  .intro-feature {
    grid-template-columns: 1fr;
    gap: 2.5rem;
  }
  .intro-photographs {
    min-height: 0;
    height: 27rem;
    padding: 0 2rem 2rem 0;
  }
  .intro-main-image img {
    min-height: 0;
    object-position: center 60%;
  }
  .intro-detail-image {
    width: 36%;
    border-width: 7px;
  }
  .intro-story h2 {
    font-size: 2.75rem;
    max-width: 22ch;
  }
  .intro-advantages {
    margin-top: 2rem;
  }
  .intro-advantages h3 {
    font-size: 1.4rem;
  }
  .benefit-detail summary {
    font-size: 1.0625rem;
  }
  .work-grid {
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
  }
  .work-card:nth-child(2) {
    padding-top: 2.5rem;
  }
  .work-card:nth-child(3) {
    padding: 0;
    grid-column: 1/-1;
    max-width: 75%;
    justify-self: center;
    margin-top: 1rem;
  }
  .work-caption {
    font-size: 0.9375rem;
    gap: 0.5rem;
  }
  .work-caption span:first-child {
    display: none;
  }
  .process-section.process-scroll {
    min-height: 0;
  }
  .process-layout {
    display: flex;
    flex-direction: column;
    position: static;
    gap: 0;
  }
  .process-intro {
    padding: 0;
    width: 100%;
  }
  .process-intro h2 {
    font-size: 2.65rem;
  }
  .process-figure {
    width: 100%;
    padding-top: 1rem;
  }
  .pool-diagram {
    min-height: 15rem;
  }
  .stage-detail {
    min-height: 5.5rem;
  }
  .stage-buttons {
    margin-top: 1.5rem;
  }
  .service-grid {
    grid-template-columns: 1fr;
    gap: 3rem;
  }
  .service-caption h3 {
    font-size: 2rem;
  }
  .review-layout,
  .faq-layout {
    grid-template-columns: 1fr;
    gap: 2.5rem;
  }
  .featured-review blockquote {
    font-size: 1.55rem;
  }
  .all-reviews {
    margin: 0;
  }
  .review-list {
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
  }
  .review-feed {
    padding-top: 2rem;
  }
  .review-entry {
    padding: 1.5rem 1.35rem 1.35rem;
  }
  .enquiry-layout {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  .enquiry-section h2 {
    font-size: 3rem;
  }
  .enquiry-copy > p {
    margin-bottom: 1.5rem;
  }
  .enquiry-links {
    gap: 1.5rem;
  }
  .footer-top {
    gap: 2rem;
    padding-bottom: 2.5rem;
  }
  .footer-top > div:first-child {
    grid-column: 1/-1;
  }
  .footer-contact .footer-phone {
    margin-top: 0.75rem;
  }
  .footer-bottom {
    padding-block: 1.5rem;
    align-items: start;
    flex-direction: column;
  }
  .footer-utilities {
    gap: 1rem;
  }
  .footer-signature {
    margin-top: 1.5rem;
    font-size: 22vw;
  }
  .page-intro {
    padding-top: 3rem;
    padding-bottom: 2rem;
  }
  .gallery-opening {
    padding-block: 3rem 2rem;
  }
  .gallery-opening-layout {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
  .gallery-opening-copy {
    padding-bottom: 0;
  }
  .gallery-opening h1 {
    font-size: clamp(2.75rem, 8.5vw, 4.5rem);
  }
  .gallery-opening .lead {
    font-size: 1.0625rem;
  }
  .gallery-opening-image img {
    aspect-ratio: 1.35;
  }
  .page-intro .intro-row {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
  .page-intro h1 {
    font-size: clamp(2.75rem, 8.5vw, 4.5rem);
  }
  .page-intro .lead {
    font-size: 1.0625rem;
  }
  .service-mosaic {
    grid-template-columns: 1fr 1fr;
    height: auto;
    gap: 0.75rem;
  }
  .service-mosaic figure:first-child {
    grid-column: 1/-1;
    aspect-ratio: 1.35;
  }
  .service-mosaic figure:nth-child(n + 2) {
    margin: 0;
    aspect-ratio: 0.9;
  }
  .service-mosaic figcaption {
    inset: auto 0.7rem 0.7rem;
    max-width: calc(100% - 1.4rem);
    font-size: 0.875rem;
  }
  .renovation-mosaic figure:first-child img {
    object-position: center 50%;
  }
  .concrete-mosaic {
    grid-template-rows: auto;
  }
  .concrete-mosaic figure:first-child {
    grid-row: auto;
  }
  .concrete-mosaic figure:nth-child(n + 2) {
    aspect-ratio: 1;
  }
  .service-stories {
    gap: 3rem;
  }
  .service-story {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
  .service-story:nth-child(even) > figure {
    order: 0;
  }
  .service-story h2 {
    font-size: 2.25rem;
    margin-bottom: 1rem;
  }
  .service-story > div {
    max-width: none;
  }
  .story-media {
    aspect-ratio: 1.3;
  }
  .statement-layout {
    flex-direction: column;
    align-items: start;
    gap: 1.5rem;
  }
  .statement {
    font-size: 2.6rem;
  }
  .detail-images {
    gap: 1.5rem 1rem;
    margin-top: 2rem;
  }
  .detail-pair .detail-media {
    aspect-ratio: 0.8;
  }
  .detail-images figcaption {
    font-size: 0.9375rem;
  }
  .concrete-benefits {
    grid-template-columns: 1fr;
    gap: 2.5rem;
  }
  .concrete-feature h2 {
    font-size: 2.65rem;
  }
  .surface-details {
    grid-template-columns: 1fr 1fr;
  }
  .surface-details figure:nth-child(n) {
    padding: 0;
  }
  .surface-details .detail-media {
    aspect-ratio: 1.1;
  }
  .gallery-grid {
    gap: 1rem;
  }
  .gallery-grid.masonry-ready {
    row-gap: 12px;
  }
  .filter-list {
    gap: 0.25rem;
  }
  .filter-button {
    padding: 0.5rem 0.8rem;
  }
  .gallery-media {
    border-radius: 3px;
  }
  .gallery-item figcaption {
    font-size: 0.875rem;
  }
  .gallery-tag {
    font-size: 0.75rem;
  }
  .viewer-stage {
    grid-template-columns: minmax(0, 1fr);
    padding-bottom: 5.5rem;
  }
  .viewer-nav {
    position: absolute;
    bottom: 1.25rem;
  }
  .viewer-prev {
    left: var(--gutter);
  }
  .viewer-next {
    right: var(--gutter);
  }
  .viewer-image {
    max-height: calc(100dvh - 15rem);
  }
  .video-badge {
    left: 0.7rem;
    top: 0.7rem;
    padding: 0.25rem 0.5rem;
  }
  .form-field textarea {
    min-height: 6rem;
  }
}
@media (max-width: 479px) {
  .work-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  .work-card:nth-child(n) {
    padding: 0;
    margin: 0;
    max-width: none;
    width: 100%;
    grid-column: auto;
  }
  .work-media,
  .work-card:nth-child(2) .work-media {
    aspect-ratio: 1.1;
  }
  .work-caption span:first-child {
    display: block;
  }
  .intro-photographs {
    height: 23rem;
  }
  .intro-story h2 {
    font-size: 2.5rem;
  }
  .gallery-item.is-landscape {
    grid-column: 1/-1;
  }
  .gallery-item.is-landscape .gallery-media {
    aspect-ratio: 1.55;
  }
  .gallery-item figcaption {
    padding-top: 0.5rem;
  }
  .filter-button {
    font-size: 0.9375rem;
    padding: 0.45rem 0.65rem;
  }
  .footer-top {
    grid-template-columns: 1fr;
  }
  .footer-top > div:first-child,
  .footer-contact {
    grid-column: auto;
  }
  .form-submit .button {
    font-size: 0.9375rem;
    padding: 0.9rem 1rem;
  }
  .detail-pair,
  .surface-details {
    grid-template-columns: 1fr;
  }
  /* One column: each detail photo keeps its own shape (--photo-ratio,
     set per photo in templates.py) instead of a square crop that would
     cut a wide shot in half and enlarge it. */
  .detail-images .detail-media,
  .surface-details .detail-media,
  .surface-details figure:nth-child(n + 3) .detail-media {
    aspect-ratio: var(--photo-ratio, 1.1);
  }
  .detail-pair .detail-media {
    aspect-ratio: 1.2;
  }
}

/* The ring is the central contact composition; the actual form stays upright. */
.contact-main {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: 4rem 6rem;
  background: var(--mist);
}
.contact-layout {
  display: grid;
  gap: 2rem;
  align-items: center;
}
.contact-copy {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 5rem;
  align-items: end;
}
.contact-copy h1 {
  font-size: clamp(3rem, 4.5vw, 4.75rem);
  font-weight: 400;
  margin-bottom: 1.5rem;
}
.contact-copy p {
  color: var(--secondary);
  max-width: 35rem;
}
.contact-copy p + p {
  margin-top: 0.8rem;
}
.contact-copy .eyebrow {
  color: var(--ink);
}
.contact-methods {
  border-top: 1px solid var(--rule);
  padding-top: 1.5rem;
  margin-bottom: 1rem;
}
.contact-methods .eyebrow {
  margin-bottom: 0.75rem;
}
.contact-methods .contact-area-label {
  margin-top: 1.5rem;
}
.contact-area {
  font-size: 1.125rem;
}
.contact-number {
  font-size: clamp(1.9rem, 3vw, 3rem);
  letter-spacing: -0.04em;
  text-decoration: none;
  line-height: 1.2;
  display: inline-block;
  margin-bottom: 1.2rem;
  white-space: nowrap;
}
.contact-art {
  min-width: 0;
  display: flex;
  justify-content: center;
}
/*
 * The flash-card deck floats on a small pool, seen from above: aqua water
 * that deepens towards the far edge, a faint grid of mosaic tiles on the
 * floor, drifting light caustics, and a pale coping stone around the rim.
 * Like the deck, it sizes itself around the form ("fit-content" plus this
 * padding), so it fits both languages and every breakpoint. Pure CSS plus
 * one small SVG tile - nothing to load or fall back from.
 */
.contact-pool {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
  padding: 3.5rem 3rem 3rem;
  border-radius: 4.5rem;
  background:
    linear-gradient(rgba(255, 255, 255, 0.08) 1px, transparent 1px) 0 0 / 1.5rem 1.5rem,
    linear-gradient(90deg, rgba(255, 255, 255, 0.08) 1px, transparent 1px) 0 0 / 1.5rem 1.5rem,
    radial-gradient(130% 95% at 28% 18%, #86dedf 0%, var(--aqua) 42%, #138f9a 100%);
  box-shadow: 0 40px 70px -40px rgba(11, 49, 74, 0.55);
}
/* Moving caustics, larger than the pool so its edges never show. */
.contact-pool::before {
  content: "";
  position: absolute;
  inset: -40%;
  z-index: -1;
  background: url("images/pool-caustics.svg") 0 0 / 40rem 40rem;
  opacity: 0.6;
  pointer-events: none;
  animation: caustic-drift 26s ease-in-out infinite alternate;
}
/* Coping stone and the shadow it casts onto the water just inside it. */
.contact-pool::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  box-shadow:
    inset 0 0 0 0.55rem #f4fbfb,
    inset 0 0 0 0.6rem rgba(11, 49, 74, 0.12),
    inset 0 1rem 1.5rem -0.5rem rgba(0, 60, 72, 0.4);
  pointer-events: none;
}
.contact-pool .contact-form {
  position: relative;
  z-index: 2;
}
.contact-pool .flash-ready .flash-card[data-pos="0"] {
  box-shadow: 0 28px 40px -18px rgba(0, 52, 64, 0.55);
}
@keyframes caustic-drift {
  from {
    transform: translate(0, 0) rotate(0deg);
  }
  to {
    transform: translate(5rem, 3rem) rotate(4deg);
  }
}
/*
 * The enquiry form is a deck of flash cards, one question per card. Without
 * JavaScript the cards simply stack in order. Once app.js adds .flash-ready,
 * every card shares one grid cell, so the deck - and the pool sized around
 * it - always has the height of its tallest card (the review card) and never
 * jumps between steps. Each card's data-pos (set by app.js) places it: 0 on
 * top, 1 and 2 peeking out of the deck below, negative already dealt off to
 * the left.
 */
.contact-form {
  width: 22rem;
  max-width: 100%;
}
.flash-deck {
  display: grid;
  gap: 1rem;
}
.flash-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 2rem 1.75rem 1.75rem;
  border-radius: 3rem;
  background: var(--white);
  box-shadow: 0 12px 50px rgba(11, 49, 74, 0.1);
}
.flash-form:not(.flash-ready) :is(.flash-head, .flash-actions, .flash-review) {
  display: none;
}
.flash-form noscript p {
  margin-top: 1rem;
  padding: 1.25rem 1.75rem;
  border-radius: 1.5rem;
  background: var(--white);
  font-size: 0.9375rem;
}
.flash-ready .flash-deck {
  gap: 0;
  padding-bottom: 1.5rem;
}
.flash-ready .flash-card {
  grid-area: 1 / 1;
  transform-origin: 50% 100%;
  transform: translateY(1.5rem) scale(0.88);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    transform 0.55s var(--ease),
    opacity 0.4s var(--ease),
    background-color 0.4s,
    visibility 0s linear 0.55s;
}
.flash-ready .flash-card > * {
  transition: opacity 0.2s;
}
.flash-ready .flash-card:not([data-pos="0"]) > * {
  opacity: 0;
}
.flash-ready .flash-card[data-pos="0"] {
  z-index: 3;
  transform: none;
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s;
}
.flash-ready .flash-card[data-pos="0"] > * {
  transition: opacity 0.3s 0.12s;
}
.flash-ready .flash-card[data-pos="1"] {
  z-index: 2;
  transform: translateY(0.75rem) scale(0.94);
  opacity: 1;
  visibility: visible;
  background: #eef8f8;
  box-shadow: 0 8px 30px rgba(11, 49, 74, 0.08);
  transition-delay: 0s;
}
.flash-ready .flash-card[data-pos="2"] {
  z-index: 1;
  opacity: 1;
  visibility: visible;
  background: var(--pale);
  box-shadow: 0 6px 20px rgba(11, 49, 74, 0.06);
  transition-delay: 0s;
}
.flash-ready .flash-card[data-pos^="-"] {
  transform: translate(-115%, -1.5rem) rotate(-9deg);
}

/* Progress: one mark per question, filled once answered, hollow once
   skipped, and a wider aqua mark for the card on top. */
.flash-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.flash-count {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--secondary);
}
.flash-dots {
  display: flex;
  gap: 0.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.flash-dots li {
  width: 1rem;
  height: 0.3rem;
  border-radius: 1rem;
  background: var(--rule);
  transition:
    width 0.3s var(--ease),
    background-color 0.3s;
}
.flash-dots [data-state="current"] {
  width: 1.75rem;
  background: var(--aqua);
}
.flash-dots [data-state="done"] {
  background: var(--ink);
}
.flash-dots [data-state="skipped"] {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--border);
}

/* Every card is as tall as the tallest one, so the question and its
   answer sit centred in the space between the progress and the actions
   rather than leaving a void under a short question. */
.flash-body {
  margin-block: auto;
  padding-block: 1.75rem 1.5rem;
}
.flash-question {
  display: block;
  width: 100%;
  padding: 0;
  margin: 0 0 0.5rem;
  font-size: 1.5rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.flash-question:focus {
  outline: none;
}
.flash-hint {
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--secondary);
}
.flash-body .form-field {
  margin-top: 1.25rem;
}
/* No resize handle: a taller textarea would grow the deck and the pool. */
.flash-body :is(input, textarea) {
  caret-color: var(--teal);
}
.flash-body textarea {
  min-height: 7.5rem;
  resize: none;
}

/* Project type: four small cards to tap. The real radio sits invisibly on
   top of each one, so it keeps native keyboard and screen-reader support. */
.flash-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
  margin-top: 1.25rem;
}
.flash-option {
  position: relative;
  display: block;
}
.flash-option input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.flash-option span {
  display: flex;
  align-items: flex-end;
  min-height: 4.75rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--rule);
  border-radius: 1.25rem;
  background: var(--mist);
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.25;
  transition:
    background-color 0.2s,
    border-color 0.2s,
    color 0.2s;
}
.flash-option:hover span {
  border-color: var(--aqua);
}
.flash-option input:checked + span {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--white);
}
.flash-option input:focus-visible + span {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

.flash-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
}
.flash-back {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  flex: none;
  margin-right: auto;
  border: 1px solid var(--rule);
  border-radius: 50%;
  color: var(--ink);
  transition: border-color 0.18s;
}
.flash-back:hover {
  border-color: var(--ink);
}
.flash-skip,
.flash-change {
  padding: 0.75rem 0.25rem;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--secondary);
  text-decoration: underline;
  text-decoration-color: var(--rule);
  text-underline-offset: 0.25em;
}
.flash-skip:hover,
.flash-change:hover {
  color: var(--ink);
  text-decoration-color: currentColor;
}
.flash-next {
  min-height: 3rem;
  gap: 0.75rem;
  padding: 0.7rem 1.1rem;
  font-size: 0.9375rem;
}
.flash-back .icon,
.flash-next .icon {
  width: 1.1rem;
  height: 1.1rem;
}

/* Review card: every answer with a way back to change it. */
.flash-review .flash-body {
  margin-block: 0 auto;
  padding-block: 1.25rem 0;
}
.flash-summary {
  margin: 0.75rem 0 0;
}
.flash-summary-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 0.75rem;
  padding: 0.4rem 0;
  border-top: 1px solid var(--rule);
}
.flash-summary dt {
  font-size: 0.75rem;
  color: var(--secondary);
}
.flash-summary dd {
  margin: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.9375rem;
}
.flash-summary dd.is-empty {
  color: var(--secondary);
}
.flash-summary dd:last-child {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  overflow: visible;
}
.flash-change {
  padding-inline: 0.5rem 0;
  font-size: 0.875rem;
}
.flash-review .form-submit {
  margin-top: auto;
  padding-top: 1.25rem;
}
.flash-review .button {
  min-height: 3rem;
  padding: 0.75rem 1rem;
  font-size: 0.9375rem;
}
/* The success message takes the note's place, in a slot tall enough for
   either, so the card (and the pool) keep their size after the handoff. */
.flash-review :is(.form-handoff-note, .form-feedback) {
  min-height: 2.9em;
  margin-top: 0.8rem;
  padding: 0;
  border: 0;
  background: none;
  font-size: 0.875rem;
  line-height: 1.45;
}
.flash-review .form-feedback .text-link {
  display: inline;
  min-height: 0;
  margin-top: 0;
  font-size: inherit;
}
.contact-main::before {
  content: "";
  position: absolute;
  inset: -20%;
  pointer-events: none;
  z-index: -1;
  opacity: 0.2;
  background: repeating-radial-gradient(
    ellipse at 80% 20%,
    transparent 0 45px,
    rgba(60, 195, 198, 0.18) 46px 47px,
    transparent 49px 94px
  );
  animation: water-drift 18s ease-in-out infinite alternate;
}
@media (min-width: 1440px) {
  .contact-layout {
    grid-template-columns: 0.75fr 1.5fr;
    gap: 2rem;
  }
  .contact-copy {
    display: block;
  }
  .contact-methods {
    margin-top: 2rem;
  }
  .contact-copy p {
    max-width: 25rem;
  }
}
@media (max-width: 767px) {
  .contact-main {
    padding-block: 3rem 4rem;
  }
  .contact-layout {
    gap: 1rem;
  }
  .contact-copy {
    display: block;
  }
  .contact-copy h1 {
    font-size: 3rem;
  }
  .contact-methods {
    margin-top: 2rem;
  }
  .contact-form {
    width: min(22rem, calc(100vw - 4rem));
  }
  .contact-pool {
    padding: 2.25rem 2rem 2rem;
    border-radius: 3.75rem;
  }
}
@media (max-width: 479px) {
  .contact-form {
    width: calc(100vw - 5.5rem);
  }
  .contact-pool {
    padding: 1.6rem 1.4rem;
    border-radius: 3.5rem;
  }
  .flash-review :is(.form-handoff-note, .form-feedback) {
    min-height: 4.35em;
  }
  .flash-card {
    padding: 1.75rem 1.4rem 1.5rem;
    border-radius: 2.5rem;
  }
  .flash-question {
    font-size: 1.3125rem;
  }
  .contact-number {
    font-size: 2.4rem;
  }
}

@media (hover: none) {
  .media-open-icon {
    opacity: 0.85;
    transform: none;
    width: 2.1rem;
    height: 2.1rem;
    top: 0.55rem;
    right: 0.55rem;
  }
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
  .reveal-pending {
    opacity: 1;
    transform: none;
  }
  :is(
      .work-media,
      .gallery-media,
      .service-image,
      .story-media,
      .detail-media
    ):hover
    img {
    transform: none;
  }
}
html[data-motion="reduced"] {
  scroll-behavior: auto;
}
html[data-motion="reduced"] *,
html[data-motion="reduced"] *::before,
html[data-motion="reduced"] *::after {
  animation: none !important;
  transition: none !important;
}
html[data-motion="reduced"] .reveal-pending {
  opacity: 1;
  transform: none;
}
html[data-motion="reduced"]
  :is(
    .work-media,
    .gallery-media,
    .service-image,
    .story-media,
    .detail-media
  ):hover
  img {
  transform: none;
}
body.document-hidden *,
body.document-hidden *::before,
body.document-hidden *::after {
  animation-play-state: paused !important;
}
@media (forced-colors: active) {
  .button,
  .stage-button,
  .filter-button,
  .menu-mark {
    border: 1px solid ButtonText;
  }
  .hero-scrim {
    background: Canvas;
  }
  .hero,
  .site-header {
    color: CanvasText;
    background: Canvas;
  }
  .drawing-line,
  .drawing-surface {
    stroke: CanvasText;
  }
  .drawing-surface {
    fill: Canvas;
  }
  .stage-button[aria-pressed="true"],
  .filter-button[aria-pressed="true"] {
    border-width: 3px;
  }
  .hero-image {
    opacity: 0.2;
  }
  .button::before,
  .filter-button::before {
    display: none;
  }
}
@media print {
  body {
    padding: 0;
  }
  .site-header,
  .site-footer,
  .hero-bottom,
  .stage-buttons,
  .process-actions,
  .gallery-controls,
  .gallery-more-wrap,
  .js-only,
  .enquiry-section {
    display: none !important;
  }
  .hero {
    color: var(--ink);
    background: white;
    display: block;
    min-height: 0;
  }
  .hero-image,
  .hero-scrim {
    display: none;
  }
  .hero-content {
    padding: 1rem 0;
  }
  .hero .button {
    display: none;
  }
  .section {
    padding-block: 2rem;
  }
  .process-section.process-scroll {
    min-height: 0;
  }
  .process-layout {
    position: static;
  }
  .sketch-stage {
    opacity: 1 !important;
    transform: none !important;
  }
  .draw-trace {
    stroke-dashoffset: 0 !important;
  }
  .reveal-pending {
    opacity: 1;
    transform: none;
  }
  .gallery-grid {
    display: block;
  }
  .gallery-item {
    display: block !important;
    break-inside: avoid;
  }
  h1 {
    font-size: 3rem;
  }
  h2 {
    font-size: 2rem;
  }
  a {
    text-decoration: none;
  }
}
