@import url('fonts.css');

/* ============================================================
   Design tokens — lifted from the original Squarespace theme
   ============================================================ */
:root {
  --font-body:    'Space Grotesk', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-heading: 'Space Grotesk', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  /* the secondary face, which the original uses for the footer's small print */
  --font-alt:     'Raleway', 'Helvetica Neue', Helvetica, Arial, sans-serif;

  /* The original eases its block motions with a spring, and stores how much it
     bounces. These are that spring sampled: bounce 0.3 for the cards that grow
     under the pointer, bounce 0.2 for the pictures that drop into place. */
  --spring-3: linear(0, 0.0465, 0.158, 0.3009, 0.4514, 0.5935, 0.7182, 0.821,
                     0.9013, 0.9605, 1.0011, 1.0267, 1.0405, 1.0457, 1.045,
                     1.0407, 1.0345, 1.0276, 1.0209, 1.0148, 1.0097, 1.0057,
                     1.0027, 1.0005, 0.9991, 0.9983, 1);
  --spring-2: linear(0, 0.0356, 0.1219, 0.2344, 0.356, 0.4753, 0.5852, 0.6819,
                     0.764, 0.8313, 0.8849, 0.9263, 0.9573, 0.9796, 0.9951,
                     1.0051, 1.0111, 1.0142, 1.0151, 1.0148, 1.0135, 1.0119,
                     1.01, 1.0082, 1.0065, 1.005, 1);
  --font-meta:    'Raleway', 'Helvetica Neue', Helvetica, Arial, sans-serif;

  --c-white:  #fafafa;
  --c-pure:   #ffffff;
  --c-black:  #000000;
  --c-dark:   #1c1c1c;
  --c-grey:   #dcdcdc;
  --c-green:  hsl(141.6, 32.5%, 15.1%);

  --fg: var(--c-black);
  --bg: var(--c-pure);
  --muted: color-mix(in srgb, var(--fg) 62%, transparent);
  --line:  color-mix(in srgb, var(--fg) 14%, transparent);

  /* Type scale measured off the original: every role is 16px + K vmax,
     capped at a 1500px vmax. It is vmax, not vw — which is why a phone held
     upright still gets generous type: the tall side drives the size. */
  --sq-16:  16px;                                          /* buttons   */
  --sq-024: min(calc(16px + 0.24vmax), 19.6px);   /* body, nav */
  --sq-048: min(calc(16px + 0.48vmax), 23.2px);   /* lead      */
  --sq-060: min(calc(16px + 0.60vmax), 25px);     /* strip     */
  --sq-120: min(calc(16px + 1.20vmax), 34px);     /* h4        */
  --sq-192: min(calc(16px + 1.92vmax), 44.8px);   /* h3        */
  --sq-432: min(calc(16px + 4.32vmax), 80.8px);   /* display   */
  --sq-252: min(calc(16px + 2.52vmax), 53.8px);   /* h2        */
  --sq-360: min(calc(16px + 3.60vmax), 70px);     /* pull      */
  --sq-840: min(calc(16px + 8.40vmax), 142px);    /* banner    */

  --step--1: var(--sq-16);
  --step-0:  var(--sq-024);
  --step-1:  var(--sq-048);
  --step-2:  var(--sq-120);
  --step-3:  var(--sq-192);
  --step-4:  var(--sq-432);

  --gutter: 4vw;
  --maxw: 1500px;
  --radius: 14px;

  --pad-sm: 3.3vw;
  --pad-md: 6vw;
  --pad-lg: 9.3vw;

  --header-h: calc(5.2vw + 35px);
}

/* ============================================================
   Reset
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}
body {
  margin: 0;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--step-0);
  line-height: 1.5;
  color: var(--fg);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img, svg, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: 500; line-height: 1.05; letter-spacing: -0.02em; margin: 0; text-wrap: balance; }
p { margin: 0 0 1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }
button { font: inherit; }
:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

/* ============================================================
   Layout primitives
   ============================================================ */
.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.wrap--narrow { max-width: 760px; }
.wrap--wide { max-width: 1180px; }

.blk { position: relative; }
/* a section given a minimum height still starts its content at the top */
.blk--minh { display: flex; flex-direction: column; justify-content: flex-start; }
.blk--minh > * { width: 100%; }
/* Section padding comes from two places that add up: a named step, and an exact
   value the section carries itself. The first section also clears the header. */
.blk {
  padding-top:    calc(var(--pt-step, 0px) + var(--pt, 0px));
  padding-bottom: calc(var(--pb-step, 0px) + var(--pb, 0px));
}
.pt--sm { --pt-step: var(--pad-sm); }  .pb--sm { --pb-step: var(--pad-sm); }
.pt--md { --pt-step: var(--pad-md); }  .pb--md { --pb-step: var(--pad-md); }
.pt--lg { --pt-step: var(--pad-lg); }  .pb--lg { --pb-step: var(--pad-lg); }
.pt--none { --pt-step: 0px; }          .pb--none { --pb-step: 0px; }
main > .blk:first-child {
  padding-top: calc(var(--header-h) + var(--pt-step, 0px) + var(--pt, 0px));
}

/* Each theme names its own colour as well as painting it, because the scrim
   over a backdrop picture is that same colour — not black. A white section
   washes its picture paler; a dark one washes it darker. */
.bg--white { background: var(--c-pure);  --theme-bg: var(--c-pure); }
.bg--offwhite { background: var(--c-white); --theme-bg: var(--c-white); }
.bg--black { background: var(--c-black); --theme-bg: var(--c-black); --fg: var(--c-white); color: var(--c-white); }
.bg--light { background: var(--c-grey);  --theme-bg: var(--c-grey); }
.bg--dark  { background: var(--c-dark);  --theme-bg: var(--c-dark);  --fg: var(--c-white); color: var(--c-white); }
.bg--green { background: var(--c-green); --theme-bg: var(--c-green); --fg: var(--c-black); color: var(--c-black); }
/* The original keeps two dark themes apart: one sets its type in off-white,
   the other — the one the footer and the closing sections use — in #dcdcdc. */
.bg--inverse { background: var(--c-black); --theme-bg: var(--c-black); --fg: var(--c-grey); color: var(--c-grey); }

.rounded { border-radius: var(--radius); overflow: hidden; }

/* ============================================================
   Header
   ============================================================ */
.site-header {
  /* Solid white on every page, as the original's is: it sits over the first
     section, and that section's top padding is what keeps content clear of it.
     A transparent bar left the logo unreadable over dark project covers. */
  position: absolute; top: 0; left: 0; right: 0; z-index: 50;
  background: var(--c-pure);
}
.site-header__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding-block: 2.6vw; height: var(--header-h);
}
@media (max-width: 767px) {
  /* the phone header is taller and sits on a 6vw margin, as the original's does */
  /* the site margin widens on a phone, as the original's does */
  :root { --header-h: calc(12vw + 37px); --gutter: 6vw; }
  .site-header__inner { padding-block: 6vw; }
}
.site-logo { font-size: var(--step-1); text-decoration: none; letter-spacing: -0.03em; display: flex; }
.site-logo img { height: 35px; width: auto; display: block; }
@media (max-width: 767px) { .site-logo img { height: 30px; } }

.nav { display: flex; align-items: center; gap: 2vw; }
.nav a {
  text-decoration: none; font-size: var(--sq-024); letter-spacing: .01em;
  padding-block: .1em;
}
/* The rule under the section you are in: a 1px line the original draws as a
   repeating gradient, sitting .1em above the bottom of the link. It marks the
   current section only — hovering another one draws nothing. */
.nav a[aria-current="page"] {
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 1px 1px;
  background-position: 0 calc(100% - .1em);
  background-repeat: repeat-x;
}

.nav-toggle {
  display: none; background: none; border: 0; cursor: pointer;
  width: 44px; height: 44px; padding: 10px; margin-inline-end: -10px;
}
.nav-toggle span { display: block; height: 2px; background: currentColor; margin: 5px 0; transition: transform .25s, opacity .2s; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 780px) {
  .nav-toggle { display: block; }
  .nav {
    position: fixed; inset: var(--header-h) 0 auto 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--c-white);
    padding: 0 var(--gutter) var(--pad-sm);
    border-bottom: 1px solid var(--line);
    transform: translateY(-8px); opacity: 0; pointer-events: none;
    transition: opacity .2s, transform .2s;
    max-height: calc(100dvh - var(--header-h)); overflow-y: auto;
  }
  .nav[data-open="true"] { opacity: 1; transform: none; pointer-events: auto; }
  .nav a { font-size: var(--step-1); padding-block: 0.9rem; border-bottom: 1px solid var(--line); }
  .nav a:hover, .nav a[aria-current="page"] { border-bottom-color: var(--line); opacity: .6; }
}

/* ============================================================
   Blocks
   ============================================================ */
.b-heading { display: grid; gap: 0.6rem; }
.b-heading[data-align="center"] { text-align: center; justify-items: center; }
.b-heading[data-align="end"]    { text-align: end;    justify-items: end; }
.b-heading__eyebrow { font-size: var(--step-1); color: var(--muted); letter-spacing: -0.01em; }
.b-heading__title { white-space: pre-wrap; }
.b-heading[data-size="xl"] .b-heading__title { font-size: var(--step-4); }
.b-heading[data-size="lg"] .b-heading__title { font-size: var(--step-3); }
.b-heading[data-size="md"] .b-heading__title { font-size: var(--step-2); }

.b-text { font-size: var(--step-0); }
.b-text[data-align="center"] { text-align: center; }

.b-image figcaption, .b-pair figcaption, .b-grid figcaption {
  margin-top: 0.6rem; font-family: var(--font-meta);
  font-size: var(--step--1); color: var(--muted);
}
.b-image { margin: 0; }
.b-image--full { padding-inline: 0; max-width: none; }
.b-image--full img { width: 100%; border-radius: 0; }

.b-pair { display: grid; gap: clamp(0.75rem, 2vw, 1.5rem); grid-template-columns: 1fr; }
@media (min-width: 700px) {
  .b-pair { grid-template-columns: 1fr 1fr; align-items: start; }
  .b-pair[data-offset="1"] > :nth-child(2) { margin-top: clamp(2rem, 6vw, 5rem); }
}

.b-grid { display: grid; gap: clamp(0.75rem, 2vw, 1.5rem); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 640px)  { .b-grid[data-cols="3"], .b-grid[data-cols="4"] { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .b-grid[data-cols="3"] { grid-template-columns: repeat(3, 1fr); }
                             .b-grid[data-cols="4"] { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1180px) { .b-grid[data-cols="4"] { grid-template-columns: repeat(4, 1fr); } }
.b-grid img { width: 100%; }

/* Collage: overlapping scattered cards on desktop, a calm 2-col grid on phones */
.b-collage { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.75rem; }
.b-collage figure { margin: 0; }
.b-collage img { width: 100%; border-radius: var(--radius); }
@media (min-width: 860px) {
  .b-collage {
    grid-template-columns: repeat(12, 1fr);
    grid-auto-rows: clamp(40px, 5vw, 72px);
    gap: 0 clamp(0.5rem, 1.4vw, 1.25rem);
    align-items: start;
  }
  .b-collage figure:nth-child(1) { grid-column: 2 / span 3; grid-row: 2 / span 4; }
  .b-collage figure:nth-child(2) { grid-column: 4 / span 3; grid-row: 1 / span 3; z-index: 2; }
  .b-collage figure:nth-child(3) { grid-column: 6 / span 3; grid-row: 3 / span 4; z-index: 3; }
  .b-collage figure:nth-child(4) { grid-column: 8 / span 3; grid-row: 2 / span 4; z-index: 2; }
  .b-collage figure:nth-child(5) { grid-column: 10 / span 3; grid-row: 1 / span 3; }
  .b-collage figure:nth-child(6) { grid-column: 5 / span 3; grid-row: 5 / span 3; z-index: 4; }
  .b-collage img { height: 100%; object-fit: cover; }
}

.b-marquee { overflow: hidden; white-space: nowrap; user-select: none; }
.b-marquee__track { display: inline-flex; gap: 0; will-change: transform; animation: marquee var(--speed, 32s) linear infinite; }
.b-marquee span { font-size: var(--step-2); padding-inline-end: 0.6em; }
@keyframes marquee { to { transform: translateX(-50%); } }
.b-marquee[data-speed="slow"]   { --speed: 55s; }
.b-marquee[data-speed="normal"] { --speed: 32s; }
.b-marquee[data-speed="fast"]   { --speed: 18s; }

.b-button { display: flex; }
.b-button[data-align="center"] { justify-content: center; }
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  text-decoration: none; text-align: center;
  font-size: var(--sq-16); font-weight: 500; letter-spacing: .04em; text-transform: uppercase;
  line-height: normal;
  padding: 1.1em 1.3em; border-radius: 300px; border: 1px solid currentColor;
  transition: background-color .2s, color .2s, border-color .2s;
}
.btn:hover { background: var(--fg); color: var(--bg); }
.btn--solid {
  background: var(--c-black); color: var(--c-white); border-color: var(--c-white);
}
.btn--solid:hover { background: var(--c-white); color: var(--c-black); border-color: var(--c-black); }
.btn--light { background: var(--c-grey); color: var(--c-black); border-color: var(--c-black); }
.btn--light:hover { background: transparent; color: var(--c-grey); border-color: var(--c-grey); }
/* On a dark section the filled button turns over, as the original's does. */
.bg--black .btn--solid, .bg--dark .btn--solid, .bg--green .btn--solid, .bg--inverse .btn--solid {
  background: var(--c-grey); color: var(--c-black); border-color: var(--c-grey);
}
.bg--black .btn--solid:hover, .bg--dark .btn--solid:hover, .bg--green .btn--solid:hover, .bg--inverse .btn--solid:hover {
  background: transparent; color: var(--c-grey);
}

/* The project grid, matched to the original: three across on the 24-column
   content width, square covers that crop to fill, and the caption 13px under. */
.b-projects { display: grid; grid-template-columns: 1fr; gap: 28px 13px; }
@media (min-width: 620px) { .b-projects { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .b-projects { grid-template-columns: repeat(3, 1fr); } }
.p-card { text-decoration: none; display: block; color: inherit; }
.p-card__img { overflow: hidden; background: var(--c-grey); aspect-ratio: 1 / 1; }
.p-card__img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.p-card__cap { margin-top: 13px; }
.p-card__title {
  font-size: var(--sq-120); font-weight: 500; line-height: 1.2;
  letter-spacing: -.05em; margin-bottom: .5em;
}
.p-card__meta { font-size: var(--sq-024); line-height: 1.5; letter-spacing: .01em; color: var(--muted); }
}

.b-meta { display: grid; gap: 1.25rem; grid-template-columns: 1fr; }
@media (min-width: 620px) { .b-meta { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); } }
.b-meta dt { font-family: var(--font-meta); font-size: var(--step--1); color: var(--muted); margin-bottom: 0.3rem; }
.b-meta dd { margin: 0; font-size: var(--step-0); }

.b-quote { text-align: center; }
.b-quote blockquote { margin: 0; font-size: var(--step-2); line-height: 1.25; letter-spacing: -0.02em; text-wrap: balance; }
.b-quote cite { display: block; margin-top: 1rem; font-family: var(--font-meta); font-size: var(--step--1); font-style: normal; color: var(--muted); }

.b-video__frame { position: relative; aspect-ratio: 16 / 9; border-radius: var(--radius); overflow: hidden; background: var(--c-dark); }
.b-video__frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.b-spacer[data-h="sm"] { height: var(--pad-sm); }
.b-spacer[data-h="md"] { height: var(--pad-md); }
.b-spacer[data-h="lg"] { height: var(--pad-lg); }

/* ============================================================
   Footer
   ============================================================ */
.skip-link { position: absolute; left: -9999px; }
.skip-link:focus { left: var(--gutter); top: 0.5rem; z-index: 100; background: var(--c-black); color: #fff; padding: 0.6rem 1rem; border-radius: 6px; }

/* ============================================================
   Previous / next project
   ============================================================ */
/* The pager carries the theme of the section it follows — white after a white
   page, black after a dark one — which is how the original themes its own. */
.pager {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 2vw;
  padding: 3vw 4vw;
}
.pager__link {
  display: flex; align-items: center; gap: 8px;
  color: inherit; text-decoration: none; min-width: 0;
}
.pager__link--next { margin-inline-start: auto; text-align: end; }
.pager__icon { flex: 0 0 auto; width: 43px; display: flex; justify-content: center; }
.pager__icon svg { width: 18px; height: 32px; }
.pager__t {
  font-size: var(--sq-192); font-weight: 500; line-height: 1; letter-spacing: -.05em;
  min-width: 0;
}
.pager__link:hover .pager__t { text-decoration: underline; text-underline-offset: .12em; }
@media (max-width: 767px) {
  /* Still two columns on a phone — the titles wrap instead of the pair stacking. */
  .pager { padding: 3vw 6vw; gap: 4vw; }
  .pager__link { align-items: flex-start; flex: 1 1 0; }
  .pager__icon { width: 24px; }
  .pager__icon svg { width: 12px; height: 22px; }
}

/* ============================================================
   Site footer — the original's closing section, cell for cell
   ============================================================ */
.site-footer { background: var(--c-black); color: var(--c-grey); --fg: var(--c-grey); }
.ft {
  display: grid; container-type: inline-size;
  column-gap: 11px; row-gap: 11px;
  grid-template-columns: minmax(calc(6cqw - 11px), 1fr)
                         repeat(8, minmax(0, calc((1500px - 11px * 7) / 8)))
                         minmax(calc(6cqw - 11px), 1fr);
  grid-template-rows: repeat(12, minmax(24px, auto));
}
.ft > * { margin: 0; min-width: 0; }
.ft__logo   { grid-area: 3 / 2 / 5 / 6; }
.ft__tag    { grid-area: 5 / 2 / 7 / 10; }
.ft__mail   { grid-area: 7 / 2 / 9 / 9; }
.ft__social { grid-area: 9 / 2 / 11 / 10; }
.ft__legal  { grid-area: 11 / 2 / 13 / 10; }

.ft__logo img { width: 100%; height: 100%; object-fit: contain; object-position: left center; display: block; }
.ft__tag    { font-size: var(--sq-024); line-height: 1.5; letter-spacing: .01em; }
.ft__mail   { font-size: var(--sq-048); line-height: 1.5; letter-spacing: calc(var(--sq-024) * .01);
              display: flex; align-items: center; }
.ft__mail a { color: inherit; text-decoration: none; }
.ft__mail a:hover { text-decoration: underline; }
.ft__legal  { font-family: var(--font-alt);
              font-size: 12.8px; line-height: 1; letter-spacing: normal; }
.ft__social { display: flex; align-items: center; gap: 15px; }
.ft__social a { color: inherit; display: inline-flex; }
.ft__social svg { width: 28px; height: 28px; fill: currentColor; }

@media (min-width: 768px) {
  .ft {
    grid-template-columns: minmax(calc(4cqw - 11px), 1fr)
                           repeat(24, minmax(0, calc((1500px - 11px * 23) / 24)))
                           minmax(calc(4cqw - 11px), 1fr);
    grid-template-rows: repeat(9, minmax(calc(min(1500px, 92cqw) * 0.0215), auto));
  }
  .ft__logo   { grid-area: 1 / 2 / 7 / 7; }
  .ft__tag    { grid-area: 5 / 2 / 6 / 10; }
  .ft__mail   { grid-area: 4 / 17 / 6 / 25; justify-content: flex-end; }
  .ft__social { grid-area: 7 / 22 / 8 / 26; justify-content: center; }
  /* One row tall, like the original: the second line spills into the gap
     below rather than pushing the whole footer down. */
  .ft__legal  { grid-area: 7 / 2 / 8 / 10; height: 1.5em; }
}

/* ============================================================
   Free-placement (fluid grid) sections
   ============================================================ */
/* The canvas is full-bleed and is its own containment context, so the grid's
   gutters and row height can be expressed as a share of its width — which is
   how the original derives them, and what makes the two line up pixel for
   pixel no matter how wide the window is. */
.wrap--bleed { max-width: none; margin-inline: 0; padding-inline: 0; container-type: inline-size; }
.fe { width: 100%; }
.fe-item { min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.fe-al-start  { justify-content: flex-start; }
.fe-al-center { justify-content: center; }
.fe-al-end    { justify-content: flex-end; }

.fe-text { min-width: 0; }
.fe-item--text.is-hcenter .fe-text { text-align: center; }
.fe-item--text.is-hend .fe-text    { text-align: end; }

/* Each size carries the leading and tracking measured alongside it, so the two
   scale together and the line box matches at any viewport. */
.fe-text--sm  { font-size: var(--sq-024); line-height: 1.5;    letter-spacing: .01em; }
.fe-text--md  { font-size: var(--sq-048); line-height: 1.5;    letter-spacing: .01em; }
.fe-text--mq  { font-size: var(--sq-060); line-height: 1.4;    letter-spacing: -.05em; }
.fe-text--lg  { font-size: var(--sq-120); line-height: 1.152;  letter-spacing: -.05em; }
.fe-text--xl  { font-size: var(--sq-192); line-height: 1.1232; letter-spacing: -.05em; }
.fe-text--xxl { font-size: var(--sq-432); line-height: 1.0272; letter-spacing: -.05em; }
.fe-text--x2  { font-size: var(--sq-252); line-height: 1.0992; letter-spacing: -.05em; }
.fe-text--x3  { font-size: var(--sq-360); line-height: 1.0272; letter-spacing: -.05em; }
.fe-text--ban { font-size: var(--sq-840); line-height: 1.0272; letter-spacing: -.05em; }
.fe-text h1, .fe-text h2, .fe-text h3, .fe-text h4,
.fe-text p, .fe-text ul, .fe-text ol {
  font-size: inherit; line-height: inherit; letter-spacing: inherit;
  font-weight: 500; margin: 0;
}
.fe-h-sm  :is(h1,h2,h3,h4) { font-size: var(--sq-024); line-height: 1.5;    letter-spacing: .01em; }
.fe-h-md  :is(h1,h2,h3,h4) { font-size: var(--sq-048); line-height: 1.5;    letter-spacing: .01em; }
.fe-h-mq  :is(h1,h2,h3,h4) { font-size: var(--sq-060); line-height: 1.4;    letter-spacing: -.05em; }
.fe-h-lg  :is(h1,h2,h3,h4) { font-size: var(--sq-120); line-height: 1.152;  letter-spacing: -.05em; }
.fe-h-xl  :is(h1,h2,h3,h4) { font-size: var(--sq-192); line-height: 1.1232; letter-spacing: -.05em; }
.fe-h-x2  :is(h1,h2,h3,h4) { font-size: var(--sq-252); line-height: 1.0992; letter-spacing: -.05em; }
.fe-h-x3  :is(h1,h2,h3,h4) { font-size: var(--sq-360); line-height: 1.0272; letter-spacing: -.05em; }
.fe-h-xxl :is(h1,h2,h3,h4) { font-size: var(--sq-432); line-height: 1.0272; letter-spacing: -.05em; }
/* The one palette colour the original's copy reaches for: a pure white that
   overrides whatever the section theme would otherwise give the text. */
.tc-light { color: #fff; }
/* A block can let each heading level take its own size, which is what a
   project write-up needs: a title, a role line, then body copy. */
.fe-h-auto h1 { font-size: var(--sq-432); line-height: 1.0272; letter-spacing: -.05em; }
.fe-h-auto h2 { font-size: var(--sq-252); line-height: 1.0992; letter-spacing: -.05em; }
.fe-h-auto h3 { font-size: var(--sq-192); line-height: 1.1232; letter-spacing: -.05em; }
.fe-h-auto h4 { font-size: var(--sq-120); line-height: 1.152;  letter-spacing: -.05em; }
.fe-text :is(h1,h2,h3,h4) + * { margin-top: 32px; }
.fe-text p + p { margin-top: 16px; }
.fe-text > * + * { margin-top: .6em; }
.fe-text p:last-child { margin-bottom: 0; }

/* A band that runs off both edges of its cell on one line, the way the
   original's does: the text starts left of the cell and is clipped to it. */
.fe-strip { overflow: hidden; }
.fe-strip__in { white-space: nowrap; width: max-content; margin-left: -526px; }

/* The wave banner. Height and baseline are in em so they track the type,
   while the curve itself keeps the original's fixed 60px rise and fall. */
.fe-wave { overflow: hidden; }
.fe-wave__svg {
  display: block; width: 100%; height: calc(1.401em + var(--amp, 60px));
  overflow: visible; fill: currentColor; transform: translateY(.14em);
}
.fe-wave__svg text { font: inherit; letter-spacing: inherit; }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* A picture is always bounded by the cell it was placed in — it fits inside
   or fills it, but never stretches the grid. Only a stack of pictures grows.
   One that fits shrinks to its own proportions and sits centred, so a corner
   radius rounds the picture itself rather than an empty box around it. */
.fe-item--image { position: relative; }
.fe-img {
  position: absolute; inset: 0; margin: 0;
  display: flex; align-items: center; justify-content: center;
}
.fe-img__el {
  max-width: 100%; max-height: 100%; width: auto; height: auto;
  border-radius: var(--img-r, 0px);
}
.fe-img--cover .fe-img__el {
  width: 100%; height: 100%; object-fit: cover;
  object-position: var(--img-pos, 50% 50%);
}
.fe-stack { display: flex; flex-direction: column; gap: var(--stack-gap, 20px); width: 100%; }
.fe-stack__fig { margin: 0; }
.fe-stack__img { width: 100%; height: auto; display: block; object-fit: contain; }
.fe-video { width: 100%; height: 100%; object-fit: contain; display: block; background: #000; }
.fe-item--button { align-items: stretch; }
.fe-item--button .btn { height: 100%; }
.fe-al-center.fe-item--button { align-items: center; }
.fe-al-end.fe-item--button { align-items: flex-end; }

/* ============================================================
   Contact form
   ============================================================ */
.fm__title { font-size: var(--sq-192); margin-bottom: .4rem; }
.fm__intro { color: var(--muted); margin-bottom: clamp(1.5rem, 4vw, 2.5rem); }
.fm-wrap { width: 100%; }

/* Pill fields on a hairline outline, matching the original's enquiry form. */
.fm { display: grid; gap: 20px; }
.fm__set { border: 0; padding: 0; margin: 0; min-width: 0; }
.fm__lab { display: block; font-size: var(--sq-024); font-weight: 500;
           line-height: 1.5; letter-spacing: .01em; padding-bottom: 4px; }
.fm__lab i { font-style: normal; }
.fm__row { display: grid; gap: 10px; grid-template-columns: 1fr; margin-bottom: 20px; }
@media (min-width: 640px) { .fm__row { grid-template-columns: 1fr 1fr; } }

.fm__f { display: block; min-width: 0; }
.fm__f > span { display: block; font-size: var(--sq-16); font-weight: 500;
                line-height: 1.5; letter-spacing: .01em; padding-bottom: 6px; }
.fm__f > span i { font-style: normal; line-height: 1; }
.fm__f > span.fm__lab { font-size: var(--sq-024); }
/* the line of guidance the original puts under a field's caption */
.fm__desc { display: block; font-size: var(--sq-16); font-weight: 500;
            line-height: 1.5; letter-spacing: .01em; padding-bottom: 6px; }
.fm input[type="text"], .fm input[type="email"], .fm input[type="tel"],
.fm input[type="date"], .fm textarea {
  width: 100%; font-family: inherit; font-weight: 500; font-size: var(--sq-024);
  line-height: 1.5; letter-spacing: .01em;
  color: inherit; background: transparent; border: 1px solid currentColor;
  border-radius: 26.88px; padding: 8px 15px; min-height: 47px;
}
.fm textarea { border-radius: 26.88px; min-height: 100px; resize: vertical; line-height: 1.5; }
.fm__f--date input { max-width: 200px; }
.fm input:focus-visible, .fm textarea:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

.fm__opts { display: flex; flex-wrap: wrap; gap: 8px 24px; }
.fm__opt { display: inline-flex; align-items: center; gap: 9px;
           font-size: var(--sq-16); line-height: 1.5; letter-spacing: .01em; }
.fm__opt input { width: 20px; height: 20px; margin: 0; accent-color: currentColor; }

.fm__send { justify-self: start; padding: 16px 20.8px; cursor: pointer; }
.fm__trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.fm__ok { font-size: var(--sq-048); }
.fm__errs { margin-bottom: 1rem; color: #b3261e; }
.fm__errs p { margin: 0 0 .3rem; }
.fm__errs p:last-child { margin: 0; }
.bg--dark .fm__errs, .bg--black .fm__errs { color: #ffd9d5; }

/* ============================================================
   Staggered gallery
   ============================================================ */
/* The column count holds at every width; only the margins and the gaps
   shrink, which is how the original's staggered galleries behave. */
.gal {
  display: grid; grid-template-columns: repeat(var(--gal-cols, 2), 1fr);
  gap: var(--gal-gx, 10px);
  padding: var(--gal-pad, 4vw);
}
.gal__col { display: grid; gap: var(--gal-gy, 12px); align-content: start; min-width: 0; }
@media (max-width: 767px) {
  /* the phone margin is the site's 6vw, unless the gallery bleeds */
  .gal:not([data-bleed]) { padding: 6vw; }
}
.gal__fig { margin: 0; }
.gal__img { width: 100%; height: auto; display: block; }

/* Hover motion on a block, as the original gives a few of its cards: the cell
   grows, and some of them tilt, springing out and snapping back. The easing is
   a damped spring sampled from the original's own setting (bounce 0.3, so a
   damping ratio of 0.7) — which is why it overshoots by about 4.6% before it
   settles. Touch screens get no hover, so nothing moves there. */
@media (hover: hover) and (pointer: fine) {
  .fe-item.has-motion {
    transition: transform var(--a-dur, .5s) var(--spring-3);
    will-change: transform;
  }
  .fe-item.has-motion:hover {
    transform: rotate(var(--a-rot, 0deg)) scale(var(--a-scale, 1));
  }
}

/* A picture that drops into place as the page reaches it: in from 200% of its
   own height above, turned, small and invisible, springing to rest. The start
   state is only applied when scripts run, so without them the pictures simply
   sit where they belong. Its spring is a shade tighter than the cards' —
   bounce 0.2, a damping ratio of 0.8 — hence the smaller overshoot. */
.js .fe-item.has-appear > * {
  opacity: var(--a-op, 0);
  transform: translateY(var(--a-y, -200%)) rotate(var(--a-rot, 0deg)) scale(var(--a-scale, 1));
  transform-origin: var(--a-ox, 50%) var(--a-oy, 50%);
  will-change: transform, opacity;
}
.js .fe-item.has-appear.is-in > * {
  opacity: 1;
  transform: none;
  transition: transform var(--a-dur, .7s) var(--spring-2),
              opacity   var(--a-dur, .7s) var(--spring-2);
}

@media (prefers-reduced-motion: reduce) {
  .fe-item.has-motion { transition: none; }
  .fe-item.has-motion:hover { transform: none; }
  .js .fe-item.has-appear > * { opacity: 1; transform: none; }
}

/* section backdrop image, as the original uses for the hero gradient */
.blk.has-bg-image {
  background-image: var(--bg-img);
  background-size: cover; background-position: center; background-repeat: no-repeat;
}
/* a phone gets a file sized for a phone, not the one a wide screen needs */
@media (max-width: 767px) {
  .blk.has-bg-image { background-image: var(--bg-img-sm, var(--bg-img)); }
}
/* The scrim the original lays over a backdrop picture is the section's own
   theme colour, so a pale section washes its picture pale rather than grey. */
.blk.has-overlay::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: var(--theme-bg, #000); opacity: var(--overlay, 0);
}

/* A moving effect over the backdrop. The picture is repainted by a canvas
   running the original's own shader (assets/js/image-fx.js); the CSS backdrop
   below it is what shows until that loads, and what stays if WebGL is off or
   less motion was asked for. The scrim is painted over it, as the original
   stacks it. */
.blk__fx {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: block; pointer-events: none; z-index: 0;
}
.blk.has-overlay::before { z-index: 1; }

/* whatever the section holds stays above every backdrop layer */
.blk.has-overlay > :not(.blk__fx),
.blk.has-bg-image > :not(.blk__fx) { position: relative; z-index: 2; }
