/* ==========================================================================
   HAPPY ROOM — Design Factory
   Design tokens
   ========================================================================== */

:root {
  /* Palette — taken from the logo: black, white, one yellow.
     The yellow is a *surface* colour, never small text on light: at
     #F2F20D it fails contrast against the page background. */
  --bone: #f7f7f5;
  --bone-deep: #eeeeea;
  --sand: #e3e3dd;
  --yellow: #f2f20d;
  --yellow-deep: #d9d900;
  --clay: var(--yellow);
  --ink: #111111;
  --ink-soft: #2b2b2b;
  --graphite: #6b6b66;
  --graphite-light: #9a9a94;
  --white: #ffffff;
  --line: rgba(17, 17, 17, 0.13);
  --line-soft: rgba(17, 17, 17, 0.07);
  --line-invert: rgba(247, 247, 245, 0.18);

  /* Type */
  --display: "Inter Tight", "Inter", -apple-system, BlinkMacSystemFont,
    "Helvetica Neue", Arial, sans-serif;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;

  /* Scale */
  --step--1: clamp(0.75rem, 0.72rem + 0.15vw, 0.82rem);
  --step-0: clamp(0.94rem, 0.9rem + 0.2vw, 1.05rem);
  --step-1: clamp(1.1rem, 1rem + 0.5vw, 1.35rem);
  --step-2: clamp(1.5rem, 1.25rem + 1.2vw, 2.25rem);
  --step-3: clamp(1.5rem, 0.9rem + 1.9vw, 2.6rem);
  --step-4: clamp(1.6rem, 0.8rem + 2.4vw, 3.1rem);
  --step-5: clamp(1.75rem, 0.85rem + 2.9vw, 3.8rem);

  /* Space */
  --gutter: clamp(1.25rem, 4vw, 4.5rem);
  --section: clamp(5.5rem, 11vw, 12rem);
  --maxw: 1560px;

  /* Motion */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
}

/* ==========================================================================
   Reset & base
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bone);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--step-0);
  line-height: 1.65;
  font-weight: 400;
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

img, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; border: 0; background: none; cursor: pointer; }
h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

::selection { background: var(--ink); color: var(--bone); }

/* ==========================================================================
   Typography helpers
   ========================================================================== */

.display {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.035em;
}

/* Emphasis stays in the same weight and upright — the grotesque reads as one
   solid block of type, which is the whole point of this treatment. */
.display em {
  font-style: normal;
  font-weight: 700;
}

.h-hero { font-size: var(--step-5); }
.h-xl { font-size: var(--step-4); }
.h-lg { font-size: var(--step-3); }
.h-md { font-size: var(--step-2); }

.eyebrow {
  font-size: var(--step--1);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--graphite);
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.eyebrow::before {
  content: "";
  width: clamp(1.5rem, 3vw, 2.75rem);
  height: 1px;
  background: currentColor;
  opacity: 0.5;
}

.lead {
  font-size: var(--step-1);
  line-height: 1.5;
  color: var(--ink-soft);
  letter-spacing: -0.015em;
}

.muted { color: var(--graphite); }

/* ==========================================================================
   Layout
   ========================================================================== */

.shell {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--section); }
.section--tight { padding-block: clamp(3.5rem, 7vw, 7rem); }

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(1.25rem, 2.4vw, 2.5rem);
}

.section-head {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(1.5rem, 2.4vw, 2.5rem);
  align-items: end;
  margin-bottom: clamp(2.75rem, 6vw, 5.5rem);
}

.section-head__label { grid-column: 1 / span 3; }
.section-head__title { grid-column: 4 / span 6; }
.section-head__aside { grid-column: 10 / span 3; align-self: end; }

@media (max-width: 900px) {
  .section-head { grid-template-columns: 1fr; gap: 1.25rem; }
  .section-head__label,
  .section-head__title,
  .section-head__aside { grid-column: 1 / -1; }
}

.rule { height: 1px; background: var(--line); border: 0; margin: 0; }

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  --btn-bg: var(--ink);
  --btn-fg: var(--bone);
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  padding: 1.05em 1.9em;
  border-radius: 100px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 500;
  overflow: hidden;
  isolation: isolate;
  transition: color 0.45s var(--ease), border-color 0.45s var(--ease);
}

.btn::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--clay);
  transform: translateY(101%);
  transition: transform 0.55s var(--ease);
}

.btn:hover::after { transform: translateY(0); }
.btn:hover { color: var(--ink); }

.btn__arrow {
  width: 0.65em;
  height: 0.65em;
  border-top: 1.5px solid currentColor;
  border-right: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.4s var(--ease);
}

.btn:hover .btn__arrow { transform: rotate(45deg) translate(2px, -2px); }

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  border: 1px solid var(--line);
}

.btn--light {
  --btn-bg: var(--bone);
  --btn-fg: var(--ink);
}

.btn--light::after { background: var(--clay); }

/* Underline link */
.link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 500;
  padding-bottom: 0.35em;
}

.link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform-origin: right;
  transform: scaleX(1);
  transition: transform 0.5s var(--ease);
}

.link:hover::after {
  transform-origin: left;
  animation: link-sweep 0.6s var(--ease);
}

@keyframes link-sweep {
  0% { transform: scaleX(1); transform-origin: right; }
  49% { transform: scaleX(0); transform-origin: right; }
  50% { transform: scaleX(0); transform-origin: left; }
  100% { transform: scaleX(1); transform-origin: left; }
}

/* ==========================================================================
   Navigation
   ========================================================================== */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  padding-block: clamp(1rem, 2vw, 1.6rem);
  transition: transform 0.5s var(--ease), background-color 0.5s var(--ease),
    backdrop-filter 0.5s var(--ease), border-color 0.5s var(--ease);
  border-bottom: 1px solid transparent;
  mix-blend-mode: normal;
}

.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}

.nav.is-solid {
  background: rgba(245, 242, 237, 0.82);
  backdrop-filter: blur(18px) saturate(1.4);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  border-bottom-color: var(--line-soft);
}

.nav.is-hidden { transform: translateY(-101%); }

.nav.is-inverted { color: var(--bone); }
.nav.is-inverted .brand__mark { border-color: var(--line-invert); }

.brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--display);
  font-size: clamp(1.05rem, 1.4vw, 1.3rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  z-index: 2;
}

.brand__mark {
  width: 1.75em;
  height: 1.75em;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--sans);
  font-size: 0.42em;
  letter-spacing: 0.06em;
  font-weight: 600;
  transition: border-color 0.5s var(--ease);
}

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 2.6vw, 2.6rem);
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 500;
}

.nav__links a { position: relative; padding-block: 0.3em; }

.nav__links a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.45s var(--ease);
}

.nav__links a:hover::after { transform: scaleX(1); transform-origin: left; }

.nav__cta { display: inline-flex; }

/* Language switch — a segmented control with a sliding indicator.
   Was plain "UA / EN" text: it read as a caption rather than something
   you could press, and the inactive item sat at 45% opacity. */
.lang {
  --lang-on: var(--bone);
  position: relative;
  display: inline-grid;
  grid-template-columns: 1fr 1fr;
  align-items: stretch;
  padding: 3px;
  border: 1px solid currentColor;
  border-radius: 100px;
  isolation: isolate;
}

/* The bar is light over the hero, so the fill follows the text colour and
   the active label flips to the opposite value. */
.nav.is-inverted .lang { --lang-on: var(--ink); }
.lang { border-color: color-mix(in srgb, currentColor 28%, transparent); }

.lang__thumb {
  position: absolute;
  z-index: -1;
  top: 3px;
  bottom: 3px;
  left: 3px;
  width: calc(50% - 3px);
  border-radius: 100px;
  background: currentColor;
  transition: transform 0.4s var(--ease);
}

.lang[data-active="en"] .lang__thumb { transform: translateX(100%); }

.lang__btn {
  position: relative;
  padding: 0.42em 0.95em;
  min-width: 3.2em;
  text-align: center;
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  font-weight: 600;
  color: currentColor;
  opacity: 0.62;
  transition: opacity 0.3s var(--ease), color 0.3s var(--ease);
}

.lang__btn:hover { opacity: 1; }
.lang__btn.is-active { opacity: 1; color: var(--lang-on); }

.nav__lang { margin-left: auto; }

@media (max-width: 980px) {
  .nav__lang { margin-left: 0; margin-right: 0.35rem; }
}

.menu__foot .lang { font-size: var(--step--1); }

.nav__toggle {
  position: relative;
  display: none;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  border: 1px solid var(--line);
  place-items: center;
  z-index: 2;
}

/* Over the hero the bar is inverted (light on dark). The open menu paints a
   light panel underneath it, so the inverted colour must be dropped or the
   brand and the close cross become white-on-white. */
body.menu-open .nav.is-inverted { color: var(--ink); }
body.menu-open .nav.is-inverted .brand__mark { border-color: var(--line); }
body.menu-open .nav.is-inverted .nav__toggle { border-color: var(--line); }

/* Bars are absolutely positioned rather than stacked in the grid: as grid rows
   they were spread 15px apart, so the "close" rotation (which moves them only
   a few px) left two parallel diagonals instead of a cross. */
.nav__toggle span {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 1.05rem;
  height: 1.5px;
  background: currentColor;
  transform: translate(-50%, -50%) translateY(var(--y, 0));
  transition: transform 0.4s var(--ease), opacity 0.25s var(--ease);
}

.nav__toggle span:nth-child(1) { --y: -5px; }
.nav__toggle span:nth-child(3) { --y: 5px; }

body.menu-open .nav__toggle span:nth-child(1) { transform: translate(-50%, -50%) rotate(45deg); }
body.menu-open .nav__toggle span:nth-child(2) { opacity: 0; }
body.menu-open .nav__toggle span:nth-child(3) { transform: translate(-50%, -50%) rotate(-45deg); }

@media (max-width: 980px) {
  .nav__links, .nav__cta { display: none; }
  .nav__toggle { display: grid; }
}

/* Mobile overlay menu */
.menu {
  position: fixed;
  inset: 0;
  z-index: 99;
  background: var(--bone);
  padding: clamp(6rem, 16vw, 8rem) var(--gutter) var(--gutter);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  clip-path: inset(0 0 100% 0);
  transition: clip-path 0.75s var(--ease);
  pointer-events: none;
}

body.menu-open .menu { clip-path: inset(0 0 0 0); pointer-events: auto; }

.menu__list li {
  overflow: hidden;
  border-bottom: 1px solid var(--line-soft);
}

.menu__list a {
  display: block;
  font-family: var(--display);
  font-size: clamp(2rem, 9vw, 3.25rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.32;
  transform: translateY(110%);
  transition: transform 0.7s var(--ease);
}

body.menu-open .menu__list a { transform: translateY(0); }
body.menu-open .menu__list li:nth-child(2) a { transition-delay: 0.05s; }
body.menu-open .menu__list li:nth-child(3) a { transition-delay: 0.1s; }
body.menu-open .menu__list li:nth-child(4) a { transition-delay: 0.15s; }
body.menu-open .menu__list li:nth-child(5) a { transition-delay: 0.2s; }
body.menu-open .menu__list li:nth-child(6) a { transition-delay: 0.25s; }

.menu__foot {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  justify-content: space-between;
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--graphite);
}

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--ink);
  color: var(--bone);
}

.hero__media {
  position: absolute;
  inset: -8% 0 -8% 0;
  z-index: 0;
  will-change: transform;
}

.hero__media img,
.hero__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.06);
  animation: hero-in 2.4s var(--ease) forwards;
}

@keyframes hero-in {
  to { transform: scale(1); }
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(180deg, rgba(15, 14, 11, 0.5) 0%, rgba(15, 14, 11, 0) 30%),
    linear-gradient(0deg, rgba(15, 14, 11, 0.92) 0%, rgba(15, 14, 11, 0.72) 38%,
      rgba(15, 14, 11, 0.34) 66%, rgba(15, 14, 11, 0) 88%);
}

.hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-bottom: clamp(2.5rem, 4vw, 3.5rem);
  padding-top: clamp(7rem, 13vw, 9rem);
}

.hero__inner > .eyebrow { margin-bottom: clamp(1rem, 2vw, 1.5rem); }

/* No max-width: the headline's line breaks are authored with <br>, and any
   extra wrapping would both overflow the hero and break the line-mask reveal. */
.hero__title {
  max-width: none;
  text-wrap: balance;
  margin-bottom: clamp(1.25rem, 2.4vw, 2rem);
}

/* The headline is cut out of the same photo sitting behind it — the letters
   are a window onto the room, not a flat color. A faint dark wash is layered
   under the photo so bold strokes still read clearly against a busy hero
   image, and the crop drifts slowly via --mx/--my (set in JS) rather than
   sitting static. Falls back to plain bone-colored text wherever
   background-clip: text isn't supported. */
.hero__title--masked {
  /* The hero photo behind the title is already darkened by .hero__scrim, so
     the fill needs to read as light against dark — a warm, bright crop, not
     a second darkened copy of the same dim photo (that just disappeared). */
  background-image: linear-gradient(rgba(255, 250, 240, 0.14), rgba(255, 250, 240, 0.14)),
    url("img/oak-01-lg.jpg");
  background-size: 200% auto;
  background-position: var(--mx, 18%) var(--my, 55%);
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .hero__title--masked {
    background-image: none;
    color: var(--bone);
    -webkit-text-fill-color: var(--bone);
  }
}

.hero__row {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: end;
}

.hero__sub {
  grid-column: 1 / span 5;
  font-size: var(--step-1);
  line-height: 1.5;
  color: rgba(245, 242, 237, 0.82);
}

.hero__actions {
  grid-column: 8 / span 5;
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  justify-content: flex-end;
}

.hero__actions .btn--ghost {
  --btn-fg: var(--bone);
  border-color: var(--line-invert);
}

@media (max-width: 900px) {
  .hero__sub { grid-column: 1 / -1; }
  .hero__actions { grid-column: 1 / -1; justify-content: flex-start; }
}

.hero__scroll {
  position: absolute;
  right: var(--gutter);
  top: 55%;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(245, 242, 237, 0.7);
  writing-mode: vertical-rl;
}

.hero__scroll::after {
  content: "";
  width: 1px;
  height: 4rem;
  background: linear-gradient(to bottom, rgba(245, 242, 237, 0.7), transparent);
  animation: scroll-pulse 2.2s var(--ease-soft) infinite;
}

@keyframes scroll-pulse {
  0%, 100% { transform: scaleY(0.35); transform-origin: top; opacity: 0.4; }
  50% { transform: scaleY(1); transform-origin: top; opacity: 1; }
}

@media (max-width: 900px) { .hero__scroll { display: none; } }

@media (max-width: 620px) {
}

/* Short viewports (laptops in landscape, split screens): let the hero breathe
   by dropping the stat row and easing the top padding rather than overflowing. */
@media (max-height: 720px) and (min-width: 700px) {
  .hero__inner { padding-top: clamp(6rem, 11vh, 7.5rem); }
}

@media (max-height: 560px) {
  .hero { min-height: auto; }
  .hero__inner { padding-top: 6rem; }
}

/* ==========================================================================
   About
   ========================================================================== */

.about__grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
}

.about__media {
  grid-column: 1 / span 5;
  position: relative;
}

.about__media figure { position: relative; overflow: hidden; }

.about__media img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }

.about__badge {
  position: absolute;
  right: clamp(-1rem, -1vw, 0rem);
  bottom: clamp(-1.5rem, -2vw, -1rem);
  width: clamp(7rem, 11vw, 10rem);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--ink);
  color: var(--bone);
  display: grid;
  place-items: center;
  text-align: center;
  line-height: 1.25;
  padding: 1rem;
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.about__badge strong {
  display: block;
  font-family: var(--display);
  font-size: 2.2em;
  font-weight: 700;
  letter-spacing: -0.04em;
  text-transform: none;
}

.about__body { grid-column: 7 / span 6; }

.about__statement {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.035em;
  margin-block: clamp(1.5rem, 3vw, 2.25rem);
}

.about__text p + p { margin-top: 1.15em; }

.about__stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 2vw, 2rem);
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
  padding-top: clamp(1.5rem, 3vw, 2.25rem);
  border-top: 1px solid var(--line);
}

.about__stats strong {
  display: block;
  font-family: var(--display);
  font-size: clamp(1.75rem, 2.9vw, 2.5rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  margin-bottom: 0.3rem;
}

.about__stats span {
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--graphite);
}

@media (max-width: 980px) {
  .about__media, .about__body { grid-column: 1 / -1; }
  .about__media { max-width: 30rem; }
}

/* ==========================================================================
   Services
   ========================================================================== */

.services {
  background: var(--ink);
  color: var(--bone);
}

.services .eyebrow { color: var(--clay); }
.services .muted { color: rgba(245, 242, 237, 0.6); }

.services__banner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1.25rem;
  padding: clamp(1.25rem, 2.5vw, 1.75rem) 0;
  margin-bottom: clamp(2rem, 4vw, 3rem);
  border-block: 1px solid var(--line-invert);
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--clay);
}

.services__list { border-top: 1px solid var(--line-invert); }

.svc {
  position: relative;
  display: grid;
  grid-template-columns: 5rem 1fr minmax(0, 26rem);
  gap: clamp(1rem, 3vw, 2.5rem);
  align-items: center;
  padding-block: clamp(1.5rem, 2.6vw, 2.15rem);
  border-bottom: 1px solid var(--line-invert);
}

.svc > * { position: relative; }

.svc__num {
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  color: var(--clay);
}

.svc__name {
  font-family: var(--display);
  font-size: clamp(1.3rem, 2.5vw, 2.05rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.035em;
}

.svc__desc {
  font-size: var(--step-0);
  color: rgba(245, 242, 237, 0.62);
  line-height: 1.55;
}

@media (max-width: 900px) {
  .svc {
    grid-template-columns: 3rem 1fr;
    align-items: start;
    row-gap: 0.5rem;
  }
  .svc__num { grid-row: 1; }
  .svc__name { grid-row: 1; }
  .svc__desc { grid-column: 2 / span 1; grid-row: 2; }
}

.services__foot {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 2.5rem;
  align-items: center;
  justify-content: space-between;
  margin-top: clamp(2.5rem, 5vw, 4rem);
}

.services__foot p { max-width: 46ch; color: rgba(245, 242, 237, 0.66); }

/* ==========================================================================
   Process
   ========================================================================== */

.process__layout {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
}

.process__sticky {
  grid-column: 1 / span 4;
  position: sticky;
  top: clamp(6rem, 12vw, 9rem);
}

.process__sticky-img {
  margin-top: 2rem;
  overflow: hidden;
  aspect-ratio: 4 / 5;
  position: relative;
  background: var(--sand);
}

.process__sticky-img img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.06);
  transition: opacity 0.9s var(--ease), transform 1.2s var(--ease);
}

.process__sticky-img img.is-active { opacity: 1; transform: scale(1); }

.process__steps { grid-column: 6 / span 7; }

.step {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(1.25rem, 3vw, 2.5rem);
  padding-block: clamp(1.75rem, 3vw, 2.75rem);
  border-top: 1px solid var(--line);
  transition: opacity 0.6s var(--ease);
}

.step:last-child { border-bottom: 1px solid var(--line); }

.step__marker {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
}

.step__dot {
  width: 2.9rem;
  height: 2.9rem;
  border-radius: 50%;
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
  font-size: var(--step--1);
  letter-spacing: 0.05em;
  color: var(--graphite);
  background: var(--bone);
  transition: background-color 0.5s var(--ease), color 0.5s var(--ease),
    border-color 0.5s var(--ease);
}

.step.is-active .step__dot {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--bone);
}

.step__icon { width: 1.5rem; height: 1.5rem; color: var(--graphite-light); }
.step__icon svg { width: 100%; height: 100%; }

.step__title {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.035em;
  margin-bottom: 0.55rem;
}

.step__body { color: var(--graphite); max-width: 52ch; }

.step__tag {
  display: inline-block;
  margin-top: 1rem;
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--graphite);
}

@media (max-width: 980px) {
  .process__sticky { grid-column: 1 / -1; position: static; }
  .process__sticky-img { display: none; }
  .process__steps { grid-column: 1 / -1; }
}

/* ==========================================================================
   Projects
   ========================================================================== */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

.filters button {
  padding: 0.65em 1.35em;
  border-radius: 100px;
  border: 1px solid var(--line);
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--graphite);
  transition: color 0.4s var(--ease), background-color 0.4s var(--ease),
    border-color 0.4s var(--ease);
}

.filters button:hover { color: var(--ink); border-color: var(--ink); }

.filters button.is-active {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--bone);
}

.projects__grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(1.5rem, 3vw, 3.25rem) clamp(1.25rem, 2.4vw, 2.5rem);
}

/* The photography is phone-shot and almost entirely vertical, so the cards
   are portrait: landscape crops would slice most of each room away. */
.project { grid-column: span 6; }
.project--third { grid-column: span 4; }

.project.is-hidden {
  display: none;
}

.project__media {
  position: relative;
  overflow: hidden;
  background: var(--sand);
  aspect-ratio: 4 / 5;
}

.project--third .project__media { aspect-ratio: 3 / 4; }

.project__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.1s var(--ease), filter 0.8s var(--ease);
}

.project:hover .project__media img { transform: scale(1.055); }

.project__badge {
  position: absolute;
  left: 1.1rem;
  top: 1.1rem;
  z-index: 2;
  padding: 0.5em 1em;
  border-radius: 100px;
  background: rgba(245, 242, 237, 0.9);
  backdrop-filter: blur(10px);
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
}

.project__open {
  position: absolute;
  right: 1.1rem;
  bottom: 1.1rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.75em 1.3em;
  border-radius: 100px;
  background: var(--bone);
  color: var(--ink);
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  opacity: 0;
  transform: translateY(0.75rem);
  transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
}

.project:hover .project__open { opacity: 1; transform: translateY(0); }

.project__meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  margin-top: 1.1rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--line-soft);
}

.project__title {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.1;
}

.project__place {
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--graphite);
  white-space: nowrap;
}

.project__scope {
  margin-top: 0.85rem;
  font-size: var(--step--1);
  letter-spacing: 0.06em;
  color: var(--graphite);
}

@media (max-width: 860px) {
  .project,
  .project--third { grid-column: span 12; }
  .project__media,
  .project--third .project__media { aspect-ratio: 4 / 5; }
  .project__open { opacity: 1; transform: none; }
}

/* ==========================================================================
   Why choose us
   ========================================================================== */

.why { background: var(--bone-deep); }

.why__grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(1.25rem, 2.4vw, 2rem);
}

.why__hero {
  grid-column: span 6;
  grid-row: span 2;
  background: var(--ink);
  color: var(--bone);
  padding: clamp(1.75rem, 3.4vw, 3rem);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: clamp(2.5rem, 6vw, 5rem);
  min-height: 22rem;
}

.why__hero .eyebrow { color: var(--clay); }

.why__hero h3 {
  font-family: var(--display);
  font-size: var(--step-3);
  line-height: 1.06;
  letter-spacing: -0.04em;
  font-weight: 700;
  margin-block: 1.25rem 1rem;
}

.why__hero p { color: rgba(245, 242, 237, 0.68); max-width: 40ch; }

.why__card {
  grid-column: span 3;
  background: var(--bone);
  padding: clamp(1.5rem, 2.6vw, 2.25rem);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  min-height: 10.5rem;
  transition: transform 0.6s var(--ease), background-color 0.5s var(--ease);
}

.why__card:hover { transform: translateY(-6px); background: var(--white); }

.why__card-icon {
  width: 1.75rem;
  height: 1.75rem;
  color: var(--ink);
}

.why__card h4 {
  font-family: var(--display);
  font-size: var(--step-1);
  font-weight: 700;
  letter-spacing: -0.03em;
}

.why__card p { font-size: var(--step-0); color: var(--graphite); line-height: 1.55; }

@media (max-width: 980px) {
  .why__hero { grid-column: span 12; grid-row: auto; }
  .why__card { grid-column: span 6; }
}

@media (max-width: 620px) {
  .why__card { grid-column: span 12; }
}

/* ==========================================================================
   Testimonials
   ========================================================================== */

.quotes {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(1.5rem, 3vw, 2.5rem);
}

.quote {
  grid-column: span 4;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--line);
}

.quote blockquote {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1.16;
  letter-spacing: -0.035em;
}

.quote figcaption {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 0.9rem;
}

.quote figcaption img {
  width: 2.9rem;
  height: 2.9rem;
  border-radius: 50%;
  object-fit: cover;
  filter: grayscale(1);
}

.quote__who { display: flex; flex-direction: column; line-height: 1.35; }
.quote__who strong { font-weight: 500; }
.quote__who span {
  font-size: var(--step--1);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--graphite);
}

@media (max-width: 980px) { .quote { grid-column: span 12; } }

/* ==========================================================================
   Reel — Instagram-style swipeable carousel
   ========================================================================== */

.reel { position: relative; }

.reel__track {
  display: flex;
  gap: clamp(0.6rem, 1.2vw, 1.1rem);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  /* `start` rather than `center`: with centred snap points a mandatory
     scroller fights programmatic scrollTo and yanks it back to the origin. */
  scroll-snap-type: x mandatory;
  scroll-padding-left: var(--gutter);
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-inline: var(--gutter);
  cursor: grab;
}

.reel__track::-webkit-scrollbar { display: none; }

/* While dragging, snapping and smooth scrolling would fight the pointer. */
.reel__track.is-dragging {
  cursor: grabbing;
  scroll-snap-type: none;
  scroll-behavior: auto;
  user-select: none;
}

.reel__item {
  flex: 0 0 clamp(14rem, 24vw, 22rem);
  scroll-snap-align: start;
  position: relative;
  overflow: hidden;
  background: var(--sand);
  aspect-ratio: 4 / 5;
}

.reel__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  -webkit-user-drag: none;
  user-select: none;
  transition: transform 1.1s var(--ease);
}

.reel__item:hover img { transform: scale(1.04); }

.reel__cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 2.5rem 1rem 0.9rem;
  font-size: var(--step--1);
  letter-spacing: 0.06em;
  color: var(--bone);
  background: linear-gradient(0deg, rgba(15, 14, 11, 0.72), transparent);
  opacity: 0;
  transform: translateY(0.4rem);
  transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
}

.reel__item:hover .reel__cap { opacity: 1; transform: none; }

/* Controls */
.reel__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(1rem, 2.5vw, 2rem);
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
}

.reel__arrow {
  width: 2.9rem;
  height: 2.9rem;
  flex: none;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: grid;
  place-items: center;
  transition: background-color 0.4s var(--ease), color 0.4s var(--ease),
    border-color 0.4s var(--ease), opacity 0.3s var(--ease);
}

.reel__arrow svg { width: 0.85rem; height: 0.85rem; }
.reel__arrow:hover { background: var(--ink); border-color: var(--ink); color: var(--bone); }
.reel__arrow[disabled] { opacity: 0.25; pointer-events: none; }

.reel__dots { display: flex; align-items: center; gap: 0.45rem; }

.reel__dot {
  width: 6px;
  height: 6px;
  border-radius: 100px;
  background: var(--sand);
  padding: 0;
  transition: width 0.45s var(--ease), background-color 0.45s var(--ease);
}

.reel__dot.is-active { width: 24px; background: var(--ink); }

.reel__count {
  font-size: var(--step--1);
  letter-spacing: 0.12em;
  color: var(--graphite);
  font-variant-numeric: tabular-nums;
  min-width: 4.5ch;
  text-align: center;
}

@media (max-width: 620px) {
  .reel__item { flex-basis: 78vw; }
  .reel__dots { display: none; }
}

/* ==========================================================================
   CTA
   ========================================================================== */

.cta {
  position: relative;
  overflow: hidden;
  background: var(--ink);
  color: var(--bone);
  isolation: isolate;
}

.cta__bg {
  position: absolute;
  inset: -10% 0;
  z-index: -1;
  opacity: 0.32;
  will-change: transform;
}

.cta__bg img { width: 100%; height: 100%; object-fit: cover; }

.cta__inner {
  padding-block: clamp(6rem, 13vw, 12rem);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1.5rem, 3vw, 2.25rem);
}

.cta__title { max-width: 18ch; }
.cta__sub { max-width: 52ch; color: rgba(245, 242, 237, 0.72); }

.cta__actions { display: flex; flex-wrap: wrap; gap: 0.85rem; justify-content: center; }
.cta__actions .btn--ghost { --btn-fg: var(--bone); border-color: var(--line-invert); }

/* ==========================================================================
   Contact
   ========================================================================== */

.contact__grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(2rem, 4vw, 4.5rem);
}

.contact__aside { grid-column: 1 / span 4; }
.contact__form { grid-column: 6 / span 7; }

.contact__channels { margin-top: clamp(2rem, 4vw, 3rem); display: grid; gap: 1px; background: var(--line); border-block: 1px solid var(--line); }

.channel {
  background: var(--bone);
  padding: clamp(1rem, 2vw, 1.4rem) 0;
  display: flex;
  align-items: center;
  gap: 0.9rem;
  transition: padding-inline 0.5s var(--ease);
}

.channel:hover { padding-inline: 0.9rem; }

.channel__icon {
  flex: none;
  width: 2.2rem;
  height: 2.2rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--ink);
  transition: background-color 0.4s var(--ease), border-color 0.4s var(--ease);
}

.channel__icon svg { width: 1.1rem; height: 1.1rem; }

.channel:hover .channel__icon { background: var(--yellow); border-color: var(--yellow); }

.channel__text {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.channel__label {
  font-size: var(--step--1);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--graphite);
}

.channel__value { font-size: var(--step-1); letter-spacing: -0.015em; }

.map {
  margin-top: clamp(2rem, 4vw, 3rem);
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--sand);
}

.map img { width: 100%; height: 100%; object-fit: cover; filter: grayscale(1) contrast(1.05); }

.map__pin {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
}

.map__pin::before,
.map__pin::after {
  content: "";
  position: absolute;
  border-radius: 50%;
}

.map__pin::before { width: 0.6rem; height: 0.6rem; background: var(--ink); }

.map__pin::after {
  width: 3rem;
  height: 3rem;
  border: 1px solid var(--ink);
  opacity: 0;
  animation: ping 2.6s var(--ease-soft) infinite;
}

@keyframes ping {
  0% { transform: scale(0.35); opacity: 0.7; }
  100% { transform: scale(1); opacity: 0; }
}

.form { display: grid; gap: clamp(1.1rem, 2.2vw, 1.5rem); }

.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.1rem, 2.2vw, 1.5rem); }

.field { position: relative; display: flex; flex-direction: column; }

.field label {
  font-size: var(--step--1);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--graphite);
  margin-bottom: 0.5rem;
}

/* Real fields rather than bare underlines: a boxed control reads as
   something you type into, and on the glass modal panel an underline
   gave the input no edge at all. */
.field input,
.field textarea,
.field select {
  font: inherit;
  font-size: var(--step-0);
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.85rem 1rem;
  min-height: 3.1rem;
  width: 100%;
  appearance: none;
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease),
    background-color 0.3s var(--ease);
}

.field textarea {
  resize: vertical;
  min-height: 6.5rem;
  line-height: 1.55;
}

.field select {
  cursor: pointer;
  padding-right: 2.6rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%236b6b66' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
}

.field input:hover,
.field textarea:hover,
.field select:hover { border-color: var(--graphite-light); }

.field input:focus,
.field textarea:focus,
.field select:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(17, 17, 17, 0.08);
}

/* Only after the visitor has actually engaged with the field — :invalid
   alone would paint every required field red on first paint. */
.field input:user-invalid,
.field textarea:user-invalid {
  border-color: #c0392b;
  box-shadow: 0 0 0 3px rgba(192, 57, 43, 0.1);
}

.field input::placeholder,
.field textarea::placeholder { color: var(--graphite-light); }

.field input[type="file"] {
  padding: 0.6rem 1rem;
  font-size: var(--step--1);
  color: var(--graphite);
  cursor: pointer;
}

.field input[type="file"]::file-selector-button {
  font: inherit;
  font-size: var(--step--1);
  color: var(--ink);
  background: var(--bone-deep);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.4rem 0.8rem;
  margin-right: 0.8rem;
  cursor: pointer;
  transition: background-color 0.3s var(--ease);
}

.field input[type="file"]::file-selector-button:hover { background: var(--line); }

.field__hint {
  margin-top: 0.4rem;
  font-size: 0.72rem;
  color: var(--graphite-light);
}

.form__consent {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  font-size: var(--step--1);
  color: var(--graphite);
  line-height: 1.5;
}

.form__consent input {
  appearance: none;
  width: 1.05rem;
  height: 1.05rem;
  flex: none;
  margin-top: 0.15rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--white);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: background-color 0.3s var(--ease), border-color 0.3s var(--ease);
}

.form__consent input:checked { background: var(--ink); border-color: var(--ink); }

.form__consent input:checked::after {
  content: "";
  width: 0.28rem;
  height: 0.55rem;
  border: solid var(--bone);
  border-width: 0 1.5px 1.5px 0;
  transform: translateY(-1px) rotate(45deg);
}

.form__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem; }

.form__note { font-size: var(--step--1); color: var(--graphite); }

.form__status {
  font-size: var(--step--1);
  letter-spacing: 0.06em;
  color: var(--ink);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}

.form__status.is-visible { opacity: 1; transform: none; }

@media (max-width: 980px) {
  .contact__aside, .contact__form { grid-column: 1 / -1; }
}

@media (max-width: 620px) {
  .form__row { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Footer
   ========================================================================== */

.footer {
  background: var(--ink);
  color: var(--bone);
  padding-top: clamp(3.5rem, 7vw, 6rem);
  padding-bottom: clamp(1.5rem, 3vw, 2.25rem);
}

.footer__top {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(2rem, 4vw, 3rem);
  padding-bottom: clamp(3rem, 6vw, 5rem);
  border-bottom: 1px solid var(--line-invert);
}

.footer__brand { grid-column: span 5; }

.footer__brand p {
  margin-top: 1.25rem;
  max-width: 34ch;
  color: rgba(245, 242, 237, 0.62);
}

.footer__col { grid-column: span 2; }
.footer__col:first-of-type { grid-column: 7 / span 2; }

.footer__col h5 {
  font-size: var(--step--1);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--clay);
  font-weight: 500;
  margin: 0 0 1.1rem;
}

/* The link text is short, so its own box was only ~18px tall with dead gaps
   between — too small to hit with a thumb. The padding moves inside the link
   so the whole row is tappable and no gap goes to waste. */
.footer__col a {
  color: rgba(245, 242, 237, 0.75);
  transition: color 0.35s var(--ease);
  display: block;
  padding-block: 0.55rem;
}
.footer__col a:hover { color: var(--bone); }

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  justify-content: space-between;
  padding-top: clamp(1.25rem, 2.5vw, 2rem);
  font-size: var(--step--1);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: rgba(245, 242, 237, 0.5);
}

.footer__bottom a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid rgba(245, 242, 237, 0.3);
  transition: color 0.3s var(--ease), border-color 0.3s var(--ease);
}

.footer__bottom a:hover {
  color: var(--bone);
  border-color: var(--bone);
}

/* The icon column stays put while a long address wraps beside it, so the
   four rows read as one list rather than four ragged lines. */
.footer__contacts a { display: flex; align-items: flex-start; gap: 0.6rem; }
.footer__contacts svg { width: 0.95rem; height: 0.95rem; flex: none; margin-top: 0.28em; }
.footer__contacts span { min-width: 0; overflow-wrap: break-word; }

.footer__social { display: flex; align-items: center; gap: 1.5rem; }

/* The icon already marks these as links, so the underline that the other
   footer links carry would only add noise. */
.footer__social a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border-bottom: 0;
  padding-block: 0.35rem;
}

.footer__social svg { width: 1rem; height: 1rem; flex: none; }

.footer__wordmark {
  font-family: var(--display);
  font-size: clamp(3rem, 15vw, 15rem);
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: -0.05em;
  color: rgba(245, 242, 237, 0.09);
  padding-block: clamp(1.5rem, 4vw, 3rem) 0;
  text-align: center;
  user-select: none;
}

@media (max-width: 900px) {
  .footer__brand { grid-column: span 12; }
  .footer__col { grid-column: span 6 !important; }
}

/* ==========================================================================
   Scroll reveal
   ========================================================================== */

[data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 1s var(--ease), transform 1.1s var(--ease);
  transition-delay: var(--d, 0s);
}

[data-reveal].is-in { opacity: 1; transform: none; }

/* The clip lives on the inner media, never on the observed element itself:
   an element clipped to zero height reports an intersection ratio of 0 and
   would never trigger its own reveal. */
[data-reveal="mask"] { opacity: 1; transform: none; }

[data-reveal="mask"] > figure,
[data-reveal="mask"] > img {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.2s var(--ease);
  transition-delay: var(--d, 0s);
}

[data-reveal="mask"].is-in > figure,
[data-reveal="mask"].is-in > img { clip-path: inset(0 0 0 0); }

[data-reveal="scale"] { opacity: 0; transform: scale(1.04); }
[data-reveal="scale"].is-in { opacity: 1; transform: scale(1); }

/* Line-by-line heading reveal.
   The padding/margin pair gives descenders room inside the overflow clip. */
.split-line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.split-line > span {
  display: block;
  transform: translateY(110%);
  transition: transform 1.05s var(--ease);
  transition-delay: var(--d, 0s);
}
.is-in .split-line > span,
.split-line.is-in > span { transform: translateY(0); }

/* Progress bar */
.progress {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 101;
  height: 2px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left;
  background: var(--clay);
  pointer-events: none;
}

/* Page loader */
.loader {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--ink);
  color: var(--bone);
  display: grid;
  place-items: center;
  transition: clip-path 1s var(--ease) 0.15s;
  clip-path: inset(0 0 0 0);
}

body.loaded .loader { clip-path: inset(0 0 100% 0); pointer-events: none; }

.loader__lockup {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(0.9rem, 2vw, 1.3rem);
}

.loader__mark {
  width: clamp(3.25rem, 8vw, 5rem);
  height: auto;
  color: var(--bone);
  opacity: 0;
  animation: loader-mark-in 0.55s var(--ease) 0.02s forwards;
}

/* The lamp switches on: the cone opens downward from the shade. */
.loader__mark .mark-cone {
  transform-box: fill-box;
  transform-origin: top center;
  opacity: 0;
  animation: loader-light-on 0.5s var(--ease) 0.22s forwards;
}

@keyframes loader-mark-in {
  from { opacity: 0; transform: translateY(12px) scale(0.94); }
  to { opacity: 1; transform: none; }
}

@keyframes loader-light-on {
  from { opacity: 0; transform: scaleY(0.25); }
  to { opacity: 1; transform: scaleY(1); }
}

.loader__word {
  font-family: var(--display);
  font-size: clamp(1.5rem, 4vw, 2.75rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  overflow: hidden;
  padding-bottom: 0.08em;
}

.loader__word span {
  display: inline-block;
  animation: loader-rise 0.7s var(--ease) 0.18s forwards;
  transform: translateY(110%);
}

.loader__tag {
  font-size: var(--step--1);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: rgba(247, 247, 245, 0.55);
  opacity: 0;
  animation: loader-fade 0.5s var(--ease) 0.4s forwards;
}

@keyframes loader-rise { to { transform: translateY(0); } }
@keyframes loader-fade { to { opacity: 1; } }

/* ==========================================================================
   Case study page
   ========================================================================== */

.case-hero {
  position: relative;
  min-height: 82svh;
  display: flex;
  align-items: flex-end;
  background: var(--ink);
  color: var(--bone);
  overflow: hidden;
}

.case-hero__media { position: absolute; inset: -6% 0; }
.case-hero__media img { width: 100%; height: 100%; object-fit: cover; }

.case-hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-block: clamp(8rem, 16vw, 11rem) clamp(2.5rem, 5vw, 4rem);
}

.case-hero__title { max-width: 14ch; margin-block: 1.25rem 2rem; }

.case-facts {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1rem, 3vw, 2.5rem);
  padding-top: clamp(1.25rem, 2.5vw, 2rem);
  border-top: 1px solid var(--line-invert);
}

.case-facts div { display: flex; flex-direction: column; gap: 0.35rem; }

.case-facts span {
  font-size: var(--step--1);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: rgba(245, 242, 237, 0.55);
}

.case-facts strong { font-weight: 400; font-size: var(--step-1); }

@media (max-width: 720px) { .case-facts { grid-template-columns: repeat(2, 1fr); } }

.case-intro { display: grid; grid-template-columns: repeat(12, 1fr); gap: clamp(2rem, 4vw, 4rem); }
.case-intro__label { grid-column: 1 / span 3; }
.case-intro__body { grid-column: 5 / span 7; }
.case-intro__body p + p { margin-top: 1.15em; }

@media (max-width: 900px) {
  .case-intro__label, .case-intro__body { grid-column: 1 / -1; }
}

.gallery { display: grid; grid-template-columns: repeat(12, 1fr); gap: clamp(1.25rem, 2.4vw, 2.5rem); }
.gallery figure { overflow: hidden; background: var(--sand); }
.gallery img { width: 100%; height: 100%; object-fit: cover; }
.gallery figcaption {
  margin-top: 0.85rem;
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--graphite);
}
/* Portrait-first gallery tiles, for the same reason as the project cards. */
.g-half { grid-column: span 6; aspect-ratio: 4 / 5; }
.g-third { grid-column: span 4; aspect-ratio: 3 / 4; }
.g-tall { grid-column: span 5; aspect-ratio: 3 / 4; }
.g-wide { grid-column: span 7; aspect-ratio: 4 / 5; }

@media (max-width: 860px) {
  .g-half, .g-third, .g-tall, .g-wide { grid-column: span 12; aspect-ratio: 4 / 5; }
}

.case-next {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: clamp(2.5rem, 5vw, 4rem);
  border-top: 1px solid var(--line);
}

/* ==========================================================================
   Reduced motion
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; clip-path: none !important; }
  .split-line > span { transform: none !important; }
}

/* Monogram stands in for a client portrait: the quotes are placeholder copy,
   and a stock face would attach a real person to words they never said. */
.quote__avatar {
  width: 2.9rem;
  height: 2.9rem;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
  font-size: var(--step--1);
  letter-spacing: 0.06em;
  color: var(--graphite);
  background: var(--bone-deep);
}

/* ==========================================================================
   Brand lockup
   ========================================================================== */

.brand__mark {
  width: 2.15em;
  height: 2.15em;
  flex: none;
  border: 0;
  border-radius: 0;
  display: block;
  overflow: visible;
}

/* The house and lamp inherit the surrounding colour so the mark stays legible
   on the dark hero and the light page alike; only the light cone is fixed.
   Scoped to the classes, not the parent, so the loader reuses the same mark. */
.mark-line { stroke: currentColor; fill: none; }
.mark-solid { fill: currentColor; }
.mark-cone { fill: var(--yellow); }

.brand__text { display: flex; flex-direction: column; line-height: 1; gap: 0.28em; }

.brand__name {
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: 1em;
}

.brand__tag {
  font-family: var(--sans);
  font-size: 0.42em;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--graphite);
}

.nav.is-inverted .brand__tag,
.footer .brand__tag { color: inherit; opacity: 0.6; }

/* ==========================================================================
   Focus
   ========================================================================== */

/* Browsers otherwise draw the system focus ring, which on macOS picks up the
   user's accent colour — that is where the stray gold circle around the
   burger came from. currentColor keeps it legible on light and dark alike. */
:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
  border-radius: 3px;
}

.nav__toggle:focus-visible,
.lang__btn:focus-visible,
.reel__arrow:focus-visible { outline-offset: 4px; }

/* Pointer interaction should not leave a ring behind. */
:focus:not(:focus-visible) { outline: none; }

/* ==========================================================================
   Responsive leading

   Tight leading is a display-type device: it reads as confident at 70–80px,
   but the same ratio on a phone applies to 20–33px type, where Cyrillic
   ascenders (й, і) and descenders (у, р, ц) end up nearly touching. Leading
   therefore opens up as the type gets smaller.
   ========================================================================== */

@media (max-width: 900px) {
  .display { line-height: 1.14; }
  .about__statement { line-height: 1.2; }
  .svc__name,
  .step__title,
  .project__title { line-height: 1.18; }
  .why__hero h3 { line-height: 1.14; }
  .quote blockquote { line-height: 1.24; }
  .why__card h4 { line-height: 1.3; }
  .reel__cap { line-height: 1.4; }
}

@media (max-width: 620px) {
  .display { line-height: 1.2; }
  .about__statement { line-height: 1.26; }
  .svc__name,
  .step__title,
  .project__title { line-height: 1.24; }
  .why__hero h3 { line-height: 1.18; }
  .quote blockquote { line-height: 1.3; }

  /* Body copy gains a little too — long measures on a narrow column. */
  body { line-height: 1.7; }
  .lead, .hero__sub { line-height: 1.55; }
  .svc__desc, .step__body, .why__card p, .project__scope { line-height: 1.6; }

  /* The menu items sat hard against their divider rules. */
  .menu__list a { line-height: 1.22; padding-block: 0.16em 0.3em; }
}

/* The badge deliberately overhangs the photo, but on a narrow screen that
   overhang lands outside the viewport and widens the document. */
@media (max-width: 620px) {
  .about__badge { right: 0.5rem; bottom: -1rem; }
}

/* ==========================================================================
   Testimonials — cards on a continuously moving belt
   ========================================================================== */

.tbelt {
  overflow: hidden;
  padding-block: 0.5rem;
  /* Fade the edges so cards enter and leave instead of being chopped off. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.tbelt__track {
  display: flex;
  width: max-content;
  animation: tbelt-run var(--belt-speed, 52s) linear infinite;
}

/* Stop for anyone reading, whether with a mouse or a keyboard. */
.tbelt:hover .tbelt__track,
.tbelt:focus-within .tbelt__track { animation-play-state: paused; }

.tbelt__group {
  display: flex;
  align-items: stretch;
  gap: clamp(1rem, 2vw, 1.75rem);
  padding-right: clamp(1rem, 2vw, 1.75rem);
}

@keyframes tbelt-run { to { transform: translateX(-50%); } }

.tcard {
  flex: 0 0 clamp(16.5rem, 30vw, 25rem);
  display: flex;
  flex-direction: column;
  gap: clamp(1.1rem, 2vw, 1.6rem);
  padding: clamp(1.4rem, 2.4vw, 2.1rem);
  background: var(--white);
  border: 1px solid var(--line-soft);
}

.tcard::before {
  content: "";
  width: 2rem;
  height: 3px;
  background: var(--yellow);
  flex: none;
}

/* Quotes read as speech, not as a headline: body face, regular weight. */
.tcard blockquote {
  font-family: var(--sans);
  font-weight: 400;
  font-size: var(--step-1);
  line-height: 1.55;
  letter-spacing: -0.01em;
  color: var(--ink-soft);
}

.tcard figcaption {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding-top: clamp(0.9rem, 1.6vw, 1.25rem);
  border-top: 1px solid var(--line-soft);
}

@media (max-width: 620px) {
  .tbelt { --belt-speed: 34s; }
  .tcard blockquote { line-height: 1.6; }
}

/* Same clobbering applies to the "why" cards: [data-reveal] is declared later
   and would drop background-color from the transition, so the hover fill
   snapped while the lift animated. Declared here, after it, to win. */
.why__card {
  transition: opacity 0.8s var(--ease), transform 0.6s var(--ease),
    background-color 0.5s var(--ease);
}

/* ==========================================================================
   Consultation modal
   Built on <dialog>: focus trapping, Esc and inertness come from the
   platform rather than from hand-rolled JS.
   ========================================================================== */

.modal {
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--ink);
  width: min(42rem, 100%);
  max-height: 100dvh;
}

.modal::backdrop {
  background: rgba(17, 17, 17, 0.66);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

.modal__panel {
  position: relative;
  background: var(--bone);
  padding: clamp(1.6rem, 4vw, 3rem);
  max-height: 92dvh;
  overflow-y: auto;
  /* Floating layers are rounded, in-page surfaces stay flush — the panel
     was the odd one out, square around inputs that are already rounded. */
  border-radius: var(--radius-panel);
}

.modal__close {
  position: absolute;
  top: clamp(0.8rem, 1.6vw, 1.2rem);
  right: clamp(0.8rem, 1.6vw, 1.2rem);
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
  transition: background-color 0.35s var(--ease), color 0.35s var(--ease),
    border-color 0.35s var(--ease);
}

.modal__close:hover { background: var(--ink); border-color: var(--ink); color: var(--bone); }
.modal__close svg { width: 0.85rem; height: 0.85rem; }

.modal__title { margin-block: 0.9rem 0.6rem; }
.modal__sub { max-width: 40ch; }
.modal__form { margin-top: clamp(1.5rem, 3vw, 2.25rem); }

.field__opt {
  text-transform: none;
  letter-spacing: 0;
  color: var(--graphite-light);
}

.modal__note {
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--graphite);
  margin-top: 0.25rem;
}

.modal[open] { animation: modal-in 0.4s var(--ease); }
.modal[open]::backdrop { animation: modal-fade 0.4s var(--ease); }

@keyframes modal-in {
  from { opacity: 0; transform: translateY(14px) scale(0.985); }
  to { opacity: 1; transform: none; }
}

@keyframes modal-fade { from { opacity: 0; } to { opacity: 1; } }

/* Reachable on phones, where the header CTA is hidden behind the burger. */
.menu__cta { margin-top: clamp(1.5rem, 4vw, 2.5rem); align-self: flex-start; }

@media (max-width: 620px) {
  .modal { width: 100%; }
  .modal__panel { padding-top: clamp(2.4rem, 8vw, 3rem); }
}

/* ==========================================================================
   Count-up figures
   ========================================================================== */

/* Tabular figures keep every digit the same width, so the number does not
   twitch as it counts. The JS additionally pins the final width, because
   going from one digit to three would still reflow the row. */
.about__stats strong {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.count-ready { display: inline-block; }

/* ==========================================================================
   Shot detail — a reel frame opened up
   ========================================================================== */

.shot { width: min(62rem, 100%); }

.shot__panel {
  padding: 0;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  align-items: stretch;
}

.shot__media { background: var(--sand); overflow: hidden; }

.shot__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  min-height: 22rem;
}

.shot__info {
  padding: clamp(1.5rem, 3vw, 2.5rem);
  padding-right: clamp(3.2rem, 5vw, 4rem);
  display: flex;
  flex-direction: column;
  gap: clamp(0.9rem, 1.8vw, 1.25rem);
}

.shot__title { margin: 0; }
.shot__desc { color: var(--graphite); }

.shot__facts {
  margin: 0;
  display: grid;
  gap: 1px;
  background: var(--line-soft);
  border-block: 1px solid var(--line-soft);
}

.shot__facts > div {
  background: var(--bone);
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr);
  gap: 1rem;
  padding-block: 0.7rem;
}

.shot__facts dt {
  font-size: var(--step--1);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--graphite);
}

.shot__facts dd { margin: 0; font-size: var(--step-0); }

.shot__foot {
  margin-top: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 0.5rem;
}

.shot__nav { display: flex; align-items: center; gap: 0.6rem; }

.shot__arrow {
  width: 2.4rem;
  height: 2.4rem;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: grid;
  place-items: center;
  transition: background-color 0.35s var(--ease), color 0.35s var(--ease),
    border-color 0.35s var(--ease);
}

.shot__arrow:hover { background: var(--ink); border-color: var(--ink); color: var(--bone); }
.shot__arrow svg { width: 0.8rem; height: 0.8rem; }

.shot__count {
  font-size: var(--step--1);
  letter-spacing: 0.12em;
  color: var(--graphite);
  font-variant-numeric: tabular-nums;
  min-width: 4.5ch;
  text-align: center;
}

/* ==========================================================================
   Case panel — a project card opened up
   ========================================================================== */

.case { width: min(64rem, 100%); }

.case__panel { padding: clamp(1.6rem, 4vw, 3rem); }

.case__head { max-width: 58ch; }
.case__title { margin-block: 0.7rem 0.4rem; }
.case__place { font-size: var(--step-0); }
.case__desc { margin-top: clamp(1rem, 2vw, 1.4rem); color: var(--graphite); line-height: 1.65; }

.case__facts {
  margin-top: clamp(1.25rem, 2.5vw, 1.75rem);
  display: grid;
  gap: 0.75rem;
}

.case__facts > div {
  display: grid;
  grid-template-columns: minmax(7rem, 9rem) minmax(0, 1fr);
  gap: 1rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--line);
}

.case__facts dt {
  font-size: var(--step--1);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--graphite);
}

.case__facts dd { color: var(--ink); }

.case__gallery {
  margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.4vw, 1rem);
}

.case__gallery figure,
.case__shot {
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  background: var(--sand);
  aspect-ratio: 4 / 5;
  border-radius: 4px;
  position: relative;
  display: block;
  width: 100%;
  cursor: zoom-in;
}

.case__gallery img { width: 100%; height: 100%; object-fit: cover; display: block; }
.case__shot img { transition: transform 0.6s var(--ease); }
.case__shot:hover img { transform: scale(1.04); }

/* A quiet affordance: the frame says nothing until you approach it. */
.case__shot::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(17, 17, 17, 0.18)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.4' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M16 16l5 5M11 8v6M8 11h6'/%3E%3C/svg%3E")
    center / 1.75rem no-repeat;
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}

.case__shot:hover::after,
.case__shot:focus-visible::after { opacity: 1; }

.case__foot {
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.75rem;
}

/* Pushed to the far end so the arrows read as navigation for the panel
   rather than as part of the call to action next to them. */
.case__nav {
  margin-inline-start: auto;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.case__arrow {
  width: 2.6rem;
  height: 2.6rem;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: grid;
  place-items: center;
  transition: background-color 0.35s var(--ease), color 0.35s var(--ease),
    border-color 0.35s var(--ease);
}

.case__arrow:hover { background: var(--ink); border-color: var(--ink); color: var(--bone); }
.case__arrow svg { width: 0.8rem; height: 0.8rem; }

.case__count {
  font-size: var(--step--1);
  letter-spacing: 0.12em;
  color: var(--graphite);
  font-variant-numeric: tabular-nums;
  min-width: 4.5ch;
  text-align: center;
}

@media (max-width: 620px) {
  .case__gallery { grid-template-columns: 1fr; }
  .case__facts > div { display: block; }
  .case__facts dd { margin-inline-start: 0; margin-top: 0.3rem; }
  /* On one column the auto margin would strand the arrows on their own row
     edge; centring them keeps the footer balanced. */
  .case__nav { margin-inline-start: 0; width: 100%; justify-content: center; }
}

@media (pointer: coarse) {
  .case__arrow { width: 44px; height: 44px; }
}

/* The project card is now a control, so it needs to shed the button chrome. */
.project[data-project] {
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
  color: inherit;
  font: inherit;
  background: none;
  width: 100%;
  display: block;
}

/* The reel frame is now a control, so it needs an affordance. */
.reel__item {
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
  color: inherit;
  font: inherit;
  display: block;
}

.reel__plus {
  position: absolute;
  top: 0.9rem;
  right: 0.9rem;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  background: rgba(247, 247, 245, 0.9);
  color: var(--ink);
  display: grid;
  place-items: center;
  opacity: 0;
  transform: scale(0.85);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}

.reel__item:hover .reel__plus,
.reel__item:focus-visible .reel__plus { opacity: 1; transform: none; }
.reel__plus svg { width: 0.8rem; height: 0.8rem; }

@media (max-width: 820px) {
  .shot__panel { grid-template-columns: 1fr; }
  .shot__media img { min-height: 0; aspect-ratio: 4 / 3; height: auto; }
  .shot__info { padding-right: clamp(1.5rem, 3vw, 2.5rem); }
  .shot__facts > div { grid-template-columns: 7rem minmax(0, 1fr); }
  .reel__plus { opacity: 1; transform: none; }
}

/* ==========================================================================
   Calculator
   ========================================================================== */

.calc {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: start;
}

.calc__controls { display: flex; flex-direction: column; gap: clamp(1.5rem, 3vw, 2.25rem); }

.calc__group { border: 0; padding: 0; margin: 0; }

.calc__legend {
  font-size: var(--step--1);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--graphite);
  margin-bottom: 0.9rem;
  padding: 0;
}

.calc__areaRow { display: flex; align-items: baseline; gap: 0.75rem; }

.calc__areaRow input[type="number"] {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(2rem, 4vw, 3rem);
  letter-spacing: -0.04em;
  width: 4.5ch;
  border: 0;
  border-bottom: 2px solid var(--ink);
  background: transparent;
  color: var(--ink);
  padding: 0 0 0.1em;
  -moz-appearance: textfield;
}

.calc__areaRow input[type="number"]::-webkit-outer-spin-button,
.calc__areaRow input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.calc__unit { font-size: var(--step-1); color: var(--graphite); }

/* The element itself is the drag area, so a 2px-tall input gave the thumb a
   2px band to be grabbed in — unusable on a touch screen. The input is now a
   tall transparent strip and the hairline is drawn by the track pseudo. */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 2.75rem;
  margin-top: 0.1rem;
  background: transparent;
}

input[type="range"]::-webkit-slider-runnable-track {
  height: 2px;
  background: var(--line);
  border-radius: 2px;
}

input[type="range"]::-moz-range-track {
  height: 2px;
  background: var(--line);
  border-radius: 2px;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 1.35rem;
  height: 1.35rem;
  border-radius: 50%;
  background: var(--ink);
  border: 3px solid var(--yellow);
  cursor: grab;
  /* Webkit aligns the thumb to the track's top edge, so it is pulled back up
     by half its own height to sit centred on the hairline. */
  margin-top: calc((2px - 1.35rem) / 2);
}

input[type="range"]::-moz-range-thumb {
  width: 1.35rem;
  height: 1.35rem;
  border-radius: 50%;
  background: var(--ink);
  border: 3px solid var(--yellow);
  cursor: grab;
  box-sizing: border-box;
}

.seg { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.seg button {
  padding: 0.7em 1.2em;
  border: 1px solid var(--line);
  border-radius: 100px;
  font-size: var(--step--1);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--graphite);
  transition: color 0.35s var(--ease), background-color 0.35s var(--ease),
    border-color 0.35s var(--ease);
}

.seg button:hover { color: var(--ink); border-color: var(--ink); }
.seg button[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--bone); }

.calc__result {
  background: var(--ink);
  color: var(--bone);
  padding: clamp(1.5rem, 3vw, 2.25rem);
  display: flex;
  flex-direction: column;
  gap: 1rem;
  position: sticky;
  top: clamp(6rem, 12vw, 8rem);
}

.calc__result .eyebrow { color: var(--yellow); }

.calc__sum {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.6rem, 3.2vw, 2.5rem);
  letter-spacing: -0.04em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.calc__rate,
.calc__inc { font-size: var(--step-0); color: rgba(247, 247, 245, 0.66); line-height: 1.55; }
.calc__inc { padding-top: 0.9rem; border-top: 1px solid var(--line-invert); }

.calc__deposit {
  font-size: var(--step--1);
  color: var(--yellow);
  font-weight: 600;
  letter-spacing: 0.01em;
}

.calc__note {
  font-size: var(--step--1);
  line-height: 1.5;
  color: rgba(247, 247, 245, 0.45);
}

.calc__result .btn { margin-top: 0.4rem; align-self: flex-start; }

@media (max-width: 900px) {
  .calc { grid-template-columns: 1fr; }
  .calc__result { position: static; }
}

/* The menu panel is bone, and so is .btn--light — the CTA was a white pill on
   a white sheet with no border, reading as plain text rather than a button.
   In the menu it takes the dark fill and a full-width tap target. */
.menu__cta {
  align-self: stretch;
  justify-content: center;
  padding-block: 1.15em;
}

@media (min-width: 621px) {
  .menu__cta { align-self: flex-start; justify-content: flex-start; padding-inline: 2.4em; }
}

/* ==========================================================================
   Glass surfaces

   Applied only where something sits behind the panel — over photography or
   over the dimmed page. On a flat background a blur costs compositing work
   and returns nothing visible, so those surfaces stay solid.
   ========================================================================== */

:root {
  --radius-panel: 14px;
  --glass-blur: 20px;
  --glass-light: rgba(247, 247, 245, 0.72);
  --glass-light-strong: rgba(247, 247, 245, 0.86);
  --glass-dark: rgba(17, 17, 17, 0.38);
  --glass-edge: rgba(255, 255, 255, 0.5);
  --glass-edge-dark: rgba(255, 255, 255, 0.16);
}

@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {

  /* --- bar over the hero photograph ---------------------------------- */
  .nav.is-solid {
    background: var(--glass-light);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.6);
    backdrop-filter: blur(var(--glass-blur)) saturate(1.6);
    border-bottom-color: var(--glass-edge);
  }

  /* --- full-screen menu over the page -------------------------------- */
  .menu {
    background: var(--glass-light-strong);
    -webkit-backdrop-filter: blur(26px) saturate(1.4);
    backdrop-filter: blur(26px) saturate(1.4);
  }

  /* --- dialogs over the dimmed page ---------------------------------- */
  .modal__panel {
    background: var(--glass-light-strong);
    -webkit-backdrop-filter: blur(28px) saturate(1.5);
    backdrop-filter: blur(28px) saturate(1.5);
    border: 1px solid var(--glass-edge);
  }

  .modal::backdrop {
    background: rgba(17, 17, 17, 0.5);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
  }

  .shot__facts > div {
    background: rgba(247, 247, 245, 0.35);
  }

  /* --- controls sitting on top of images ----------------------------- */
  /* Denser than the other glass: light text over a bright patch of photo
     drops to ~2.3:1 through a 38% veil, well under the 4.5:1 small text needs. */
  .hero__actions .btn--ghost,
  .cta__actions .btn--ghost {
    background: rgba(17, 17, 17, 0.58);
    -webkit-backdrop-filter: blur(12px) saturate(1.3);
    backdrop-filter: blur(12px) saturate(1.3);
    border-color: var(--glass-edge-dark);
  }

  .project__badge,
  .project__open,
  .reel__plus,
  .reel__cap {
    background: var(--glass-light);
    -webkit-backdrop-filter: blur(14px) saturate(1.4);
    backdrop-filter: blur(14px) saturate(1.4);
  }

  /* Keeps the original bottom-up gradient — a flat veil would have thrown
     away the contrast that makes the caption readable over any photo. */
  .reel__cap {
    background: linear-gradient(0deg, rgba(17, 17, 17, 0.88), rgba(17, 17, 17, 0.28));
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
  }

  /* --- facts strip on the case hero ---------------------------------- */
  .case-facts {
    background: rgba(17, 17, 17, 0.46);
    -webkit-backdrop-filter: blur(16px) saturate(1.3);
    backdrop-filter: blur(16px) saturate(1.3);
    border: 1px solid var(--glass-edge-dark);
    border-radius: 2px;
    padding: clamp(1.1rem, 2.2vw, 1.6rem) clamp(1.1rem, 2.4vw, 1.8rem);
  }
}

/* The blur is what makes these legible over busy photography. Where it is
   unavailable the same surfaces fall back to opaque fills. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nav.is-solid { background: var(--bone); }
  .menu { background: var(--bone); }
  .modal__panel { background: var(--bone); }
  .project__badge, .project__open, .reel__plus { background: var(--bone); }
  .reel__cap { background: rgba(17, 17, 17, 0.8); }
  .case-facts { background: rgba(17, 17, 17, 0.62); }
}


/* ==========================================================================
   Cycle strip — the seven stages, in order

   Replaces a looping marquee: an endless scroll shows the stages from a
   random point, so the one thing that matters here — the sequence — was
   never legible.
   ========================================================================== */

.cycle {
  background: var(--bone-deep);
  border-block: 1px solid var(--line-soft);
  padding-block: clamp(2rem, 4vw, 3.25rem);
}

.cycle__eyebrow { margin-bottom: clamp(1.5rem, 3vw, 2.25rem); }

.cycle__list {
  position: relative;
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: clamp(1rem, 2vw, 1.75rem);
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: none;
}

/* Hairline threading the icons together, drawn only while all seven sit on
   one line — once the list wraps a single rule would cut across the gap. */
.cycle__list::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 3.55rem;
  height: 1px;
  background: var(--line);
  z-index: 0;
}

.cycle__item {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.cycle__num {
  font-size: var(--step--1);
  letter-spacing: 0.12em;
  color: var(--graphite-light);
  font-variant-numeric: tabular-nums;
}

.cycle__icon {
  width: 2.9rem;
  height: 2.9rem;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--bone-deep);
  display: grid;
  place-items: center;
  color: var(--ink);
  transition: background-color 0.4s var(--ease), border-color 0.4s var(--ease),
    color 0.4s var(--ease);
}

.cycle__icon svg { width: 1.3rem; height: 1.3rem; }

.cycle__item:hover .cycle__icon {
  background: var(--yellow);
  border-color: var(--yellow);
  color: var(--ink);
}

.cycle__label {
  font-size: var(--step-0);
  line-height: 1.35;
  letter-spacing: -0.01em;
  max-width: 16ch;
}

@media (max-width: 1180px) {
  .cycle__list { grid-template-columns: repeat(4, minmax(0, 1fr)); row-gap: 2rem; }
  .cycle__list::before { display: none; }
}

@media (max-width: 680px) {
  .cycle__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cycle__icon { width: 2.5rem; height: 2.5rem; }
  .cycle__icon svg { width: 1.15rem; height: 1.15rem; }
}

/* The switch lives in the bar on desktop and inside the menu on smaller
   screens: three controls crowd a phone's top bar, and the menu is where
   someone goes looking for settings anyway. */
.menu__lang { display: none; }

@media (max-width: 980px) {
  .nav__lang { display: none; }
  /* The menu is a flex column, so without this the control stretches
     edge to edge instead of sitting at its natural width. */
  .menu__lang {
    display: inline-grid;
    align-self: flex-start;
    margin-top: clamp(1.5rem, 4vw, 2.25rem);
  }
}

/* ==========================================================================
   Hero card — the team, inside the first screen
   ========================================================================== */

.hero__card {
  width: min(23rem, 100%);
  margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
  padding: clamp(1.1rem, 2vw, 1.5rem);
  background: var(--glass-light-strong, rgba(247, 247, 245, 0.94));
  border-radius: var(--radius-panel);
  color: var(--ink);
  display: flex;
  flex-direction: column;
  gap: clamp(0.9rem, 1.8vw, 1.25rem);
}

@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero__card {
    -webkit-backdrop-filter: blur(24px) saturate(1.5);
    backdrop-filter: blur(24px) saturate(1.5);
  }
}

.hero__card-top { display: flex; align-items: flex-start; gap: clamp(0.8rem, 1.6vw, 1.1rem); }

.hero__card-photo {
  width: clamp(4rem, 6vw, 5.25rem);
  height: clamp(4rem, 6vw, 5.25rem);
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  background: var(--sand);
}

.hero__card-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

.hero__card-info { display: flex; flex-direction: column; gap: 0.35rem; min-width: 0; }

.hero__card-name {
  font-family: var(--display);
  font-weight: 700;
  font-size: var(--step-1);
  letter-spacing: -0.03em;
  line-height: 1.15;
}

.hero__card-text {
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--graphite);
}

/* Full-width call to action, as on the reference — but a pill, like every
   other button here. */
.hero__card-cta { justify-content: center; width: 100%; }

/* --- placement inside the hero ------------------------------------------ */
@media (min-width: 981px) {
  /* The card sits to the right of the headline, so the text column is capped
     to keep the two from colliding. */
  .hero__inner {
    display: grid;
    /* Fixed track, not `auto`: an auto column sizes to its content's
       max-content width and swallowed two thirds of the row, squeezing the
       headline until it wrapped past its authored line breaks. */
    grid-template-columns: minmax(0, 1fr) clamp(17rem, 24vw, 22rem);
    grid-template-areas: "eyebrow card" "title card" "row card" ;
    align-items: end;
    column-gap: clamp(2rem, 5vw, 4.5rem);
  }
  .hero__inner > .eyebrow { grid-area: eyebrow; align-self: end; }
  .hero__title { grid-area: title; }
  .hero__row { grid-area: row; }
  .hero__card { grid-area: card; align-self: end; margin-top: 0; width: 100%; }
  .hero__sub { grid-column: auto; }
  .hero__row { grid-template-columns: 1fr; gap: 1.25rem; }
  .hero__actions { grid-column: auto; justify-content: flex-start; }
}

@media (max-width: 980px) {
  .hero__card { width: min(23rem, 100%); }
}

/* ==========================================================================
   Types — what the studio designs
   ========================================================================== */

.types__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.6vw, 2.5rem);
}

.type {
  display: flex;
  flex-direction: column;
  gap: clamp(0.7rem, 1.4vw, 1rem);
  padding-top: clamp(1.1rem, 2vw, 1.5rem);
  border-top: 1px solid var(--line);
}

.type__icon {
  width: 2.9rem;
  height: 2.9rem;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: var(--ink);
  transition: background-color 0.4s var(--ease), border-color 0.4s var(--ease);
}

.type__icon svg { width: 1.35rem; height: 1.35rem; }
.type:hover .type__icon { background: var(--yellow); border-color: var(--yellow); }

.type__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: var(--step-2);
  letter-spacing: -0.035em;
  line-height: 1.12;
}

.type__text { color: var(--graphite); max-width: 34ch; }

@media (max-width: 760px) {
  .types__grid { grid-template-columns: 1fr; gap: 1.75rem; }
}

/* The enquiry form lives in the modal now, so the contact section is just
   the channels — one column, with the ways to reach the studio side by side. */
.contact__grid { grid-template-columns: 1fr; }
.contact__aside { grid-column: 1 / -1; }
.contact__cta { margin-top: clamp(1.5rem, 3vw, 2.25rem); align-self: flex-start; }

@media (min-width: 761px) {
  /* Two columns before four: at tablet width a quarter of the row is not wide
     enough for the email address, which then pushed the whole page wider than
     the viewport. */
  .contact__channels { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; }
  .channel {
    align-items: flex-start;
    padding-inline: clamp(1rem, 2vw, 1.5rem);
  }
  /* The address is one unbroken token. `break-word` lets it wrap without
     overflowing, and the <wbr> before the @ gives it a sensible place to do
     so — otherwise it splits mid-domain. */
  .channel__value { overflow-wrap: break-word; }
  .channel:hover { padding-inline: clamp(1rem, 2vw, 1.5rem); }
  .contact__aside .lead { max-width: 46ch; }
}

/* All four side by side only once a quarter-row can actually hold the
   address without wrapping it into a stack. */
@media (min-width: 1100px) {
  .contact__channels { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ==========================================================================
   Touch targets
   On a touch screen the pill controls sat at 38–39px, under the 44px that a
   thumb reliably hits. Gated on a coarse pointer so the desktop sizing —
   which is driven by the type scale — is left exactly as it was.
   ========================================================================== */

@media (pointer: coarse) {
  .filters button,
  .seg button,
  .lang__btn {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

/* ==========================================================================
   Lightbox — a gallery frame at full size
   Sits above the case panel, which stays open underneath, so closing the
   photo returns the visitor to the project they were reading.
   ========================================================================== */

.lightbox {
  border: 0;
  padding: 0;
  /* The dialog's own box covers the full viewport, so ::backdrop (which only
     paints the area outside the dialog) never shows — the dialog itself must
     carry the dark background, not rely on it. Without this the panel
     underneath showed through everywhere except the photo and buttons. */
  background: rgba(8, 8, 8, 0.98);
  width: 100%;
  max-width: 100%;
  height: 100dvh;
  max-height: 100dvh;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "prev stage next";
  align-items: center;
  gap: clamp(0.5rem, 2vw, 1.5rem);
  padding-inline: clamp(0.75rem, 3vw, 2.5rem);
  overflow: hidden;
}

.lightbox__prev { grid-area: prev; }
.lightbox__stage { grid-area: stage; }
.lightbox__next { grid-area: next; }

.lightbox:not([open]) { display: none; }

.lightbox::backdrop {
  background: rgba(10, 10, 10, 0.92);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.lightbox__stage {
  margin: 0;
  display: grid;
  place-items: center;
  /* Leaves room for the counter below and the close button above, so a tall
     photo never slides under either. */
  max-height: calc(100dvh - 7rem);
}

.lightbox__stage img {
  max-width: 100%;
  max-height: calc(100dvh - 7rem);
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 4px;
  cursor: default;
  opacity: 1;
  transition: opacity 0.28s var(--ease);
}

/* Set in JS while the next frame decodes off-screen, so the crossfade never
   uncovers a half-painted photo — only the final swap is visible. */
.lightbox__stage img.is-swapping { opacity: 0; }

.lightbox__arrow,
.lightbox__close {
  width: 2.9rem;
  height: 2.9rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: var(--bone);
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.22);
  transition: background-color 0.35s var(--ease), border-color 0.35s var(--ease),
    color 0.35s var(--ease);
}

.lightbox__arrow:hover,
.lightbox__close:hover {
  background: var(--bone);
  border-color: var(--bone);
  color: var(--ink);
}

.lightbox__arrow svg { width: 0.9rem; height: 0.9rem; }
.lightbox__close svg { width: 0.85rem; height: 0.85rem; }

.lightbox__close {
  position: absolute;
  top: clamp(0.75rem, 2.5vw, 1.75rem);
  right: clamp(0.75rem, 3vw, 2.5rem);
  z-index: 2;
}

.lightbox__count {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: clamp(1rem, 3vw, 2rem);
  font-size: var(--step--1);
  letter-spacing: 0.12em;
  color: rgba(245, 242, 237, 0.7);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 620px) {
  /* No room for side arrows next to the photo on a phone, so the controls
     move into their own row beneath it, where a thumb reaches them. The
     counter joins that row rather than staying pinned to the bottom edge,
     where it collided with the arrows. */
  .lightbox {
    grid-template-columns: 1fr auto 1fr;
    grid-template-rows: minmax(0, 1fr) auto;
    grid-template-areas:
      "stage stage stage"
      "prev  count next";
    column-gap: 1.25rem;
    row-gap: 1rem;
    padding-bottom: 1.5rem;
  }
  .lightbox__stage,
  .lightbox__stage img { max-height: calc(100dvh - 9rem); }
  .lightbox__prev { justify-self: end; }
  .lightbox__next { justify-self: start; }
  .lightbox__count {
    grid-area: count;
    position: static;
    transform: none;
    justify-self: center;
    align-self: center;
  }
}

@media (pointer: coarse) {
  .lightbox__arrow,
  .lightbox__close { width: 44px; height: 44px; }
}
