@charset "UTF-8";
/* Direct Film — front end */

/* ─────────────────────────────── Fonts ───────────────────────────────
   The display and text faces are Neue Haas Grotesk Display / Text Pro.
   They are picked up from the machine when installed; otherwise the stack
   falls through to the closest widely available grotesques. Drop licensed
   web font files into assets/fonts and add src: url() entries below to serve
   them to every visitor. */

@font-face { font-family: "DF Display"; font-weight: 200; font-style: normal; font-display: swap;
  src: local("HaasGrotDispTrial-25XThin"), local("NeueHaasGroteskDisplayPro-25XThin"), local("NeueHaasDisplayXThin"); }
@font-face { font-family: "DF Display"; font-weight: 300; font-style: normal; font-display: swap;
  src: local("HaasGrotDispTrial-45Light"), local("NeueHaasGroteskDisplayPro-45Light"), local("NeueHaasDisplayLight"); }
@font-face { font-family: "DF Display"; font-weight: 400; font-style: normal; font-display: swap;
  src: local("HaasGrotDispTrial-55Roman"), local("NeueHaasGroteskDisplayPro-55Roman"), local("NeueHaasDisplayRoman"); }
@font-face { font-family: "DF Display"; font-weight: 500; font-style: normal; font-display: swap;
  src: local("HaasGrotDispTrial-65Medium"), local("NeueHaasGroteskDisplayPro-65Medium"), local("NeueHaasDisplayMediu"); }
@font-face { font-family: "DF Display"; font-weight: 700; font-style: normal; font-display: swap;
  src: local("HaasGrotDispTrial-75Bold"), local("NeueHaasGroteskDisplayPro-75Bold"), local("NeueHaasDisplayBold"); }

@font-face { font-family: "DF Text"; font-weight: 400; font-style: normal; font-display: swap;
  src: local("HaasGrotTextTrial-55Roman"), local("NeueHaasGroteskTextPro-55Roman"), local("NeueHaasText"); }
@font-face { font-family: "DF Text"; font-weight: 500; font-style: normal; font-display: swap;
  src: local("HaasGrotTextTrial-65Medium"), local("NeueHaasGroteskTextPro-65Medium"), local("NeueHaasTextMediu"); }
@font-face { font-family: "DF Text"; font-weight: 700; font-style: normal; font-display: swap;
  src: local("HaasGrotTextTrial-75Bold"), local("NeueHaasGroteskTextPro-75Bold"), local("NeueHaasTextBold"); }

/* ─────────────────────────────── Tokens ─────────────────────────────── */

.df {
  --df-bg: #1D2326;
  --df-ink: #FFFFFF;
  --df-ink-dark: #212124;

  /* The shell tracks the viewport rather than stepping between breakpoints:
     it is exactly 1418px on the 1728px artboard and narrows smoothly below. */
  --df-shell: min(1418px, 100vw - clamp(40px, 8vw, 120px));
  --df-shell-header: 1450px;
  --df-shell-footer: 1684px;
  --df-gutter: 24px;

  /* The widest a full-bleed visual band is allowed to become. It is far above
     any normal desktop, so it only takes effect on ultrawide monitors. */
  --df-band: 2200px;
  /* Distance from the edge of a full-bleed band to the content shell. */
  --df-rail-gutter: max(0px, (min(100vw, var(--df-band)) - var(--df-shell)) / 2);

  --df-r-card: 30px;
  --df-r-panel: 20px;
  --df-r-pill: 100px;

  --df-glass: rgba(255, 255, 255, .05);
  --df-glass-mid: rgba(255, 255, 255, .09);
  --df-glass-soft: rgba(255, 255, 255, .1);
  --df-hairline: rgba(255, 255, 255, .15);
  --df-field-border: rgba(255, 255, 255, .5);
  --df-blur: 25px;

  --df-display: "DF Display", "Neue Haas Grotesk Display Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --df-text: "DF Text", "Neue Haas Grotesk Text Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --df-ui: "Instrument Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --df-form: "Outfit", "Instrument Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* Text on an accent fill is always white — a design decision, applied to
     every accent rather than calculated per colour. */
  --df-accent-ink: #fff;

  --df-ease: cubic-bezier(.22, .8, .32, 1);

  /* Entrance motion: how far, how long, and how it settles. */
  --df-rv-ease: cubic-bezier(.22, .68, .24, 1);
  --df-rv-y: 30px;
  --df-rv-y-soft: 14px;
  --df-rv-t: .78s;

  /* Header height is derived from the same two fluid values the header uses,
     so every offset that depends on it stays correct at any width. */
  --df-header-pad: clamp(14px, 1.4vw, 24px);
  --df-header-bar: clamp(60px, 4.5vw, 78px);
  --df-header-h: calc(var(--df-header-pad) + var(--df-header-bar));
}

/* ───────────────────────────── Base ───────────────────────────── */

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

html:has(.df) { scroll-behavior: smooth; scroll-padding-top: clamp(96px, 9vw, 126px); background: #1D2326; }

body.df {
  margin: 0;
  background: var(--df-bg);
  color: var(--df-ink);
  font-family: var(--df-ui);
  font-size: 16px;
  line-height: 30px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

.df :where(img, svg, video) { display: block; max-width: 100%; }
.df :where(img) { height: auto; }
.df :where(a) { color: inherit; text-decoration-thickness: from-font; }
.df :where(button) { font: inherit; color: inherit; }

.df-sr {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

.df-skip {
  position: absolute; left: 16px; top: -60px; z-index: 200;
  background: #fff; color: var(--df-ink-dark); padding: 10px 18px; border-radius: var(--df-r-pill);
  font-family: var(--df-ui); font-weight: 600; text-decoration: none; transition: top .2s var(--df-ease);
}
.df-skip:focus { top: 16px; }

.df :focus-visible { outline: 2px solid var(--df-accent); outline-offset: 3px; border-radius: 4px; }

.df-canvas { position: relative; z-index: 1; }
.df-main { display: block; }

.df-shell { width: var(--df-shell); margin-inline: auto; }

.df-section { position: relative; padding-block: clamp(48px, 5.21vw, 90px); }

/* ─────────────────── Cursor-following ambient glow ─────────────────── */

.df-glow {
  position: fixed;
  top: 0; left: 0;
  width: 1500px; height: 1500px;
  margin: -750px 0 0 -750px;
  pointer-events: none;
  z-index: 0;
  opacity: 0;
  will-change: transform;
  /* Concentrated close to the pointer, then a long, quiet feathered tail.
     The outer stops stay low so the page is lit, not washed. */
  background: radial-gradient(closest-side,
    rgba(var(--df-accent-rgb), .52) 0%,
    rgba(var(--df-accent-rgb), .38) 3.5%,
    rgba(var(--df-accent-rgb), .26) 7%,
    rgba(var(--df-accent-rgb), .175) 12%,
    rgba(var(--df-accent-rgb), .115) 19%,
    rgba(var(--df-accent-rgb), .07) 29%,
    rgba(var(--df-accent-rgb), .035) 44%,
    rgba(var(--df-accent-rgb), .014) 63%,
    rgba(var(--df-accent-rgb), 0) 82%);
  transition: opacity .6s linear;
}
.df-glow.is-live { opacity: 1; }
/* The hero has its own pointer treatment, so the ambient glow steps aside. */
.df-glow.is-muted { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .df-glow { transition: opacity 1.2s linear; }
  .df-glow.is-muted { transition: opacity .45s var(--df-ease); }
}

/* ─────────────────────── Decorative wave band ─────────────────────── */

/* The artwork is drawn half as wide again as the band, deliberately, and runs
   off both sides. The box it is clipped by is the full width of the section,
   not the band, so the only thing that ever crops it is the edge of the
   screen. The graphic keeps exactly the size and placement it has always had:
   it is still measured from the band, only the clip has moved outwards. */
.df-waves {
  position: absolute;
  left: 50%; top: 0;
  width: 100%;
  transform: translateX(-50%);
  overflow: hidden;
  pointer-events: none; z-index: 0;
  opacity: .04; line-height: 0;
}
.df-waves__inner {
  display: block;
  --df-waves-w: min(100%, var(--df-band));
  width: calc(var(--df-waves-w) * 1.383);
  margin-left: calc((100% - var(--df-waves-w)) / 2 - var(--df-waves-w) * .205);
}
.df-waves svg { width: 100%; height: auto; }
.df-waves svg path { fill: #fff; }
.df-waves--top { top: -60px; }

/* ───────────────────── Oversized background words ───────────────────── */

/* A section-wide layer, deliberately outside .df-shell, so the word can run
   the full width of the viewport. Its own clip stops the page overflowing. */
.df-bgword {
  position: absolute;
  top: clamp(40px, 6.94vw, 120px);
  left: 0; right: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
  line-height: 0;
}
.df-bgword__text {
  display: inline-block;
  white-space: nowrap;
  font-family: var(--df-text);
  font-weight: 700;
  font-size: clamp(88px, 17.36vw, 300px);
  line-height: 1;
  letter-spacing: -.01em;
  color: rgba(255, 255, 255, .03);
  will-change: transform;
}
.df-section > .df-shell { position: relative; z-index: 1; }

/* ───────────────────────────── Typography ─────────────────────────────
   One heading scale for the whole front end, keyed to the element rather than
   the class — so a heading is sized by where it sits in the document outline.
   .df-h2 and .df-h3 are visual variants of that step (weight, leading), not
   separate sizes. The only components that override the scale are headings
   doing the job of a small label. */

.df :where(h1) { font-size: clamp(35px, 4.05vw, 80px); }
.df :where(h2) { font-size: clamp(35px, 2vw, 45px); }
.df :where(h3) { font-size: clamp(22px, 1.45vw, 30px); }

.df-h2 {
  margin: 0;
  font-family: var(--df-text);
  font-weight: 400;
  line-height: 1.14;
  letter-spacing: -.01em;
}
.df-h3 {
  margin: 0;
  font-family: var(--df-text);
  font-weight: 400;
  line-height: 1.18;
  letter-spacing: -.01em;
}

.df-prose p { margin: 0 0 30px; }
.df-prose p:last-child { margin-bottom: 0; }
.df-prose a { text-decoration: underline; text-underline-offset: 3px; }
.df-prose ul, .df-prose ol { margin: 0 0 30px; padding-left: 22px; }
.df-prose li { margin-bottom: 8px; }
.df-prose h2, .df-prose h3, .df-prose h4 { font-family: var(--df-text); font-weight: 500; font-size: 18px; line-height: 30px; margin: 30px 0 8px; }
.df-prose strong { font-weight: 600; }

/* ───────────────────────────── Eyebrow pill ───────────────────────────── */

.df-eyebrow { margin: 0 0 20px; line-height: 0; }
.df-eyebrow > span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 159px; height: 44px; padding: 0 24px;
  border-radius: var(--df-r-pill);
  background: var(--df-glass-soft);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  font-family: var(--df-ui); font-size: 16px; font-weight: 400; line-height: 20px;
}

/* ───────────────────────────── Buttons ───────────────────────────── */

.df-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: clamp(150px, 10.88vw, 188px); height: 45px; padding: 0 clamp(18px, 1.5vw, 26px);
  border: 1px solid transparent; border-radius: var(--df-r-pill);
  font-family: var(--df-ui); font-size: 16px; font-weight: 600; line-height: 20px;
  text-decoration: none; cursor: pointer;
  transition: background-color .3s var(--df-ease), color .3s var(--df-ease),
              border-color .3s var(--df-ease), box-shadow .3s var(--df-ease), transform .2s var(--df-ease);
}
.df-btn--lg { height: 52px; }

/* Every button resolves to a solid fill in the live theme colour on hover.
   No glow, no lift — the colour change carries the interaction. */
.df-btn--solid { background: #fff; color: var(--df-ink-dark); }
.df-btn--accent { background: var(--df-accent); color: var(--df-accent-ink); }
.df-btn--outline { background: transparent; border-color: var(--df-accent); color: #fff; }

.df-btn--solid:hover, .df-btn--solid:focus-visible,
.df-btn--accent:hover, .df-btn--accent:focus-visible,
.df-btn--outline:hover, .df-btn--outline:focus-visible {
  background: var(--df-accent);
  border-color: var(--df-accent);
  color: var(--df-accent-ink);
  box-shadow: none;
}

/* The header call to action keeps its approved treatment. */
.df-btn--solid.df-header__cta:hover, .df-btn--solid.df-header__cta:focus-visible {
  background: #fff; color: var(--df-ink-dark); border-color: transparent;
  box-shadow: 0 0 0 1px rgba(var(--df-accent-rgb), .9), 0 10px 34px rgba(var(--df-accent-rgb), .35);
  transform: translateY(-1px);
}

/* ───────────────────────────── Header ───────────────────────────── */

.df-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 60;
  padding-top: var(--df-header-pad);
  transition: transform .5s var(--df-ease), opacity .4s var(--df-ease);
}
.df-header__bar {
  position: relative;
  z-index: 2;
  width: min(var(--df-shell-header), 100% - (var(--df-gutter) * 2));
  margin-inline: auto;
  height: var(--df-header-bar);
  display: flex; align-items: center; gap: clamp(12px, 1.4vw, 24px);
  padding: 0 clamp(10px, 1.6vw, 22px) 0 clamp(18px, 2.2vw, 38px);
  border-radius: var(--df-r-pill);
  border: 1px solid transparent;
  background: transparent;
  transition: background-color .35s var(--df-ease), border-color .35s var(--df-ease), backdrop-filter .35s var(--df-ease);
}
.df-header.is-scrolled .df-header__bar {
  background: rgba(255, 255, 255, .05);
  border-color: rgba(255, 255, 255, .55);
  -webkit-backdrop-filter: blur(11.75px); backdrop-filter: blur(11.75px);
}
.df-header.is-hidden { transform: translateY(-160%); opacity: 0; pointer-events: none; }

.df-header__logo { display: block; flex: none; line-height: 0; }
.df-header__logo-img { display: block; width: clamp(150px, 10.4vw, 180px); height: auto; }
.df-header__logo-img svg { width: 100%; height: auto; display: block; }

.df-header__nav { margin-left: auto; }
.df-header__list { display: flex; align-items: center; gap: clamp(2px, 0.5vw, 8px); margin: 0; padding: 0; list-style: none; }

/* A pill that is always there, only ever coloured in — so nothing beside it
   moves when a neighbour is hovered. It sizes to its own label. */
.df-header__link {
  display: inline-flex; align-items: center;
  padding: 8px clamp(12px, 1.05vw, 18px);
  border: 1px solid transparent;
  border-radius: var(--df-r-pill);
  background: transparent;
  font-family: var(--df-ui); font-size: 16px; font-weight: 600; line-height: 20px;
  text-decoration: none; white-space: nowrap;
  transition: background-color .3s var(--df-ease), border-color .3s var(--df-ease), color .3s var(--df-ease);
}
.df-header__link:hover, .df-header__link:focus-visible {
  background: var(--df-glass-soft);
  border-color: rgba(255, 255, 255, .2);
}

.df-header__cta { min-width: clamp(124px, 8.9vw, 154px); flex: none; }

/* The open/close control is one button in two states — same footprint, same
   pill language as the rest of the header. */
.df-header__toggle {
  display: none; flex: none;
  width: clamp(40px, 6.6vw, 46px); height: clamp(40px, 6.6vw, 46px);
  margin-left: auto; padding: 0;
  align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: 50%;
  background: var(--df-glass); cursor: pointer;
  transition: background-color .3s var(--df-ease), border-color .3s var(--df-ease);
}
.df-header__toggle:hover, .df-header__toggle:focus-visible,
.df-header__toggle[aria-expanded="true"] {
  background: rgba(var(--df-accent-rgb), .16);
  border-color: var(--df-accent);
}
.df-header__toggle-box { display: block; width: 20px; }
.df-header__toggle-box span {
  display: block; height: 1.6px; background: #fff; border-radius: 2px;
  transition: transform .35s var(--df-ease), background-color .3s var(--df-ease);
}
.df-header__toggle-box span + span { margin-top: 6px; }
.df-header__toggle:hover .df-header__toggle-box span,
.df-header__toggle[aria-expanded="true"] .df-header__toggle-box span { background: var(--df-accent); }
.df-header__toggle[aria-expanded="true"] .df-header__toggle-box span:first-child { transform: translateY(3.8px) rotate(45deg); }
.df-header__toggle[aria-expanded="true"] .df-header__toggle-box span:last-child { transform: translateY(-3.8px) rotate(-45deg); }

.df-header__mobile {
  position: fixed; inset: 0; z-index: 1;
  display: flex; flex-direction: column;
  padding: calc(var(--df-header-h) + 12px) var(--df-gutter) max(24px, env(safe-area-inset-bottom));
  pointer-events: none;
}
.df-header__mobile[hidden] { display: none; }

.df-header__mobile-scrim {
  position: absolute; inset: 0;
  background: rgba(19, 24, 26, .82);
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
  opacity: 0; pointer-events: none;
  transition: opacity .38s var(--df-ease);
}
.df-header__mobile-panel {
  position: relative;
  width: min(var(--df-shell-header), 100%);
  margin-inline: auto;
  display: flex; flex-direction: column; gap: 22px;
  padding: 18px 18px 20px;
  border-radius: 28px;
  border: 1px solid var(--df-hairline);
  background: rgba(255, 255, 255, .05);
  -webkit-backdrop-filter: blur(var(--df-blur)); backdrop-filter: blur(var(--df-blur));
  opacity: 0; transform: translateY(-14px);
  transition: opacity .38s var(--df-ease), transform .42s var(--df-ease);
}
.df-header__mobile-nav { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.df-header__mobile-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

.df-header__mobile-item,
.df-header__mobile-foot {
  opacity: 0; transform: translateY(10px);
  transition: opacity .34s var(--df-ease), transform .34s var(--df-ease);
}
.df-header__mobile-link {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 20px;
  border: 1px solid transparent; border-radius: var(--df-r-pill);
  background: transparent; text-decoration: none;
  font-family: var(--df-ui); font-size: 18px; font-weight: 600; line-height: 26px;
  transition: background-color .28s var(--df-ease), border-color .28s var(--df-ease), color .28s var(--df-ease);
}
.df-header__mobile-link:hover, .df-header__mobile-link:focus-visible, .df-header__mobile-link:active {
  background: rgba(var(--df-accent-rgb), .12);
  border-color: var(--df-accent);
}
.df-header__mobile-chev {
  flex: none; width: 8px; height: 8px;
  border-top: 1.6px solid currentColor; border-right: 1.6px solid currentColor;
  transform: rotate(45deg); opacity: .45;
  transition: opacity .28s var(--df-ease), transform .28s var(--df-ease);
}
.df-header__mobile-link:hover .df-header__mobile-chev,
.df-header__mobile-link:focus-visible .df-header__mobile-chev { opacity: 1; transform: rotate(45deg) translate(2px, -2px); color: var(--df-accent); }

.df-header__mobile-foot { padding-top: 4px; border-top: 1px solid var(--df-hairline); margin-top: 2px; }
.df-header__mobile-cta { width: 100%; margin-top: 18px; height: 52px; }

/* Open state — panel first, then the links in sequence. */
.df-header__mobile.is-open { pointer-events: auto; }
.df-header__mobile.is-open .df-header__mobile-scrim { opacity: 1; pointer-events: auto; }
.df-header__mobile.is-open .df-header__mobile-panel { opacity: 1; transform: none; }
.df-header__mobile.is-open .df-header__mobile-item,
.df-header__mobile.is-open .df-header__mobile-foot {
  opacity: 1; transform: none;
  transition-delay: calc(90ms + var(--df-i, 0) * 45ms);
}

/* ───────────────────────────── Hero ───────────────────────────── */

.df-hero { --df-hero-pad: 30px; position: relative; padding: 18px var(--df-hero-pad) 0; }
/* Desktop keeps the artboard proportion (52.72vw is 911px at 1728). Below
   that the height is driven by the viewport instead, so small screens get a
   taller, more cinematic frame with real image above the copy. */
.df-hero__stage {
  position: relative;
  height: min(911px, max(52.72vw, 74svh));
  max-height: calc(100svh - 18px);
  max-width: var(--df-band); margin-inline: auto;
}

.df-hero__media {
  position: absolute; inset: 0 0 38px;
  border-radius: 40px;
  overflow: hidden;
  z-index: 0;
}

/* The dissolve belongs to the picture layer, not to the media container: it is
   what lets the global canvas and the cursor glow read straight through the
   bottom edge with no horizontal seam. */
.df-hero__cover {
  position: absolute; inset: 0;
  overflow: hidden;
  --df-hero-fade-start: max(clamp(90px, 8.97vw, 155px), 14%);
  --df-hero-fade-end: max(clamp(40px, 3.82vw, 66px), 5.5%);
  -webkit-mask-image: linear-gradient(to bottom,
    #000 calc(100% - var(--df-hero-fade-start)),
    transparent calc(100% - var(--df-hero-fade-end)));
  mask-image: linear-gradient(to bottom,
    #000 calc(100% - var(--df-hero-fade-start)),
    transparent calc(100% - var(--df-hero-fade-end)));
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%; mask-size: 100% 100%;
}

/* The flipbox. Every frame is stacked in the same place and sized to cover, so
   the hero never changes shape between two differently proportioned pictures
   and nothing moves as one gives way to the next. The resting opacity is the
   overlay that keeps the headline legible — it belongs to the active frame, so
   a cross-fade never doubles it up in the middle. */
.df-hero__cover-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; object-position: center;
  opacity: 0;
  transform: scale(1.5); transform-origin: 50% 100%;
  transition: opacity 1.2s var(--df-ease);
}
.df-hero__cover-img.is-active { opacity: .25; }

.df-hero__content {
  position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%);
  z-index: 2;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 0 24px;
}
.df-hero__mark { display: block; width: 163px; margin: 0 0 12px; line-height: 0; }
.df-hero__mark svg { width: 100%; height: auto; }
.df-hero__mark svg path { fill: #fff; }

.df-hero__title {
  margin: 0;
  max-width: 1030px;
  font-family: var(--df-display);
  font-weight: 300;
  line-height: 1.09;
  letter-spacing: -.005em;
  text-transform: uppercase;
}
.df-hero__title b { font-weight: 700; }

.df-hero__intro {
  margin: clamp(14px, 1.27vw, 22px) 0 0; max-width: 620px;
  font-family: var(--df-ui); font-size: clamp(15px, 1.16vw, 20px); line-height: 1.55;
}
.df-hero__intro p { margin: 0; }
.df-hero__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: clamp(12px, 0.87vw, 15px); margin-top: clamp(22px, 2.08vw, 36px); }

/* ───────────────────────────── About ───────────────────────────── */

.df-about { padding-top: 24px; padding-bottom: 10px; }
.df-about__grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 502fr) minmax(0, 787fr);
  gap: clamp(32px, 7.47vw, 129px);
  align-items: stretch;
  /* Both tracks are minmax(0, <flex>) in either state, so the browser can
     interpolate straight between them when the video opens. */
  transition: grid-template-columns .8s var(--df-ease), gap .8s var(--df-ease);
}
/* The copy column sets the height of the row and the picture stretches to it,
   so the two always finish level however the client's words wrap. The padding
   is part of that measurement, which is why it lives on the column itself. */
.df-about__text {
  display: flex; flex-direction: column; justify-content: center;
  padding-block: clamp(18px, 3.7vw, 64px);
  transition: opacity .42s var(--df-ease), transform .5s var(--df-ease);
}
.df-about__text .df-eyebrow { margin-bottom: 22px; }
.df-about__text .df-h3 { max-width: 505px; }
.df-about__body { margin-top: 26px; max-width: 502px; }
.df-about__actions { display: flex; flex-wrap: wrap; gap: 13px; margin-top: 32px; }

/* One image at a time, cross-fading in place: the frame never changes size. */
.df-about__media {
  position: relative;
  border-radius: var(--df-r-card); overflow: hidden;
  /* No height of its own beside the copy: it takes the row height. The floor
     only matters when the copy is unusually short. */
  min-height: min(clamp(300px, 32.47vw, 561px), 62vh);
  transition: border-radius .8s var(--df-ease), height .8s var(--df-ease);
}
.df-about__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity .9s var(--df-ease);
}
.df-about__img.is-active { opacity: 1; }

/* ──────────────────── The video inside the picture ────────────────────
   Everything below only exists when a Vimeo video has been supplied. At rest
   the picture is exactly what it was; the three layers here sit on top of it,
   invisible, and are revealed in order — cover, then player — as the visitor
   asks for them. One class on the section drives the whole sequence, so there
   is no half-open state to land in however fast play and pause are pressed. */

.df-about--has-video .df-about__media { cursor: none; }
@media (hover: none), (pointer: coarse) {
  .df-about--has-video .df-about__media { cursor: pointer; }
}

/* The cover holds the frame between the click and the player's first paint,
   so it has to sit above the player rather than behind it. */
.df-about__poster {
  position: absolute; inset: 0; z-index: 4;
  opacity: 0; visibility: hidden;
  transition: opacity .5s var(--df-ease), visibility 0s linear .5s;
}
.df-about__poster-img {
  width: 100%; height: 100%; object-fit: cover;
  /* Held back while it is standing in for the video, both so the loading mark
     reads over it and so the player's own first frame arrives as a lift
     rather than a cut. */
  filter: brightness(.5);
  transition: filter .5s var(--df-ease);
}
.df-about.is-video-loading .df-about__poster { opacity: 1; visibility: visible; transition-delay: 0s, 0s; }

.df-about__spinner {
  position: absolute; left: 50%; top: 50%; z-index: 5;
  width: 34px; height: 34px; margin: -17px 0 0 -17px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .28);
  border-top-color: var(--df-accent);
  opacity: 0; pointer-events: none;
  transition: opacity .3s var(--df-ease);
}
.df-about.is-video-loading .df-about__spinner { opacity: 1; animation: df-spin .85s linear infinite; }
@keyframes df-spin { to { transform: rotate(360deg); } }

.df-about__video {
  position: absolute; inset: 0; z-index: 3;
  opacity: 0; visibility: hidden;
  transition: opacity .55s var(--df-ease), visibility 0s linear .55s;
}
/* The player is one shape and the container is another for as long as the
   transition is running, so the frame is sized to cover and centred. Once the
   container has finished arriving at the video's own proportion the two agree
   and nothing is cropped. */
.df-about__video-el {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 100%; height: 100%; border: 0;
}
@supports (width: 1cqw) {
  .df-about__video { container-type: size; }
  .df-about__video-el {
    width: max(100cqw, calc(100cqh * var(--df-video-ar, 16 / 9)));
    height: max(100cqh, calc(100cqw / var(--df-video-ar, 16 / 9)));
  }
}
.df-about.is-video-playing .df-about__video { opacity: 1; visibility: visible; transition-delay: 0s, 0s; }

/* A transparent target over the playing video. The iframe is cross-origin, so
   this is the only way a click on the picture can reach us. The Pause button
   is stacked above it, and it steps aside entirely while the device is in its
   own fullscreen player. */
.df-about__surface {
  position: absolute; inset: 0; z-index: 6;
  display: none; background: transparent; cursor: pointer;
}
.df-about.is-video-playing .df-about__surface { display: block; }
.df-about.is-video-fullscreen .df-about__surface { display: none; }

/* Keyboard and touch equivalents for the pointer interaction. */
.df-video-btn {
  position: absolute; z-index: 7;
  right: clamp(14px, 1.62vw, 28px); bottom: clamp(14px, 1.62vw, 28px);
  display: inline-flex; align-items: center; gap: 9px;
  height: 45px; padding: 0 22px;
  border-radius: var(--df-r-pill);
  border: 1px solid var(--df-accent);
  background: rgba(var(--df-accent-rgb), .19);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  color: #fff; font-family: var(--df-ui); font-weight: 600; font-size: 15px; cursor: pointer;
}
.df-video-btn svg { flex: none; width: 18px; height: 18px; }
.df-video-btn[hidden] { display: none; }
/* Where there is a pointer the tooltip is the invitation, so the button only
   appears for the keyboard. */
@media (hover: hover) and (pointer: fine) {
  .df-video-btn--play { opacity: 0; pointer-events: none; }
  .df-video-btn--play:focus-visible { opacity: 1; pointer-events: auto; }
}

/* Play-video pointer treatment — only rendered when a video exists. */
.df-video-cursor {
  position: fixed; top: 0; left: 0; z-index: 40;
  pointer-events: none; opacity: 0;
  transition: opacity .3s var(--df-ease);
  will-change: transform;
}
.df-video-cursor.is-live { opacity: 1; }
.df-video-cursor__dot {
  position: absolute; top: -3.4px; left: -3.4px;
  width: 6.8px; height: 6.8px; border-radius: 50%;
  background: var(--df-accent);
  box-shadow: 0 0 12px rgba(var(--df-accent-rgb), .9);
}
.df-video-cursor__pill {
  position: absolute; top: 8px; left: 0;
  display: inline-flex; align-items: center; gap: 8px;
  height: 30px; padding: 0 14px 0 9px;
  border-radius: var(--df-r-pill);
  border: 1px solid var(--df-accent);
  background: rgba(var(--df-accent-rgb), .19);
  -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
  font-family: var(--df-ui); font-size: 14.5px; font-weight: 500; line-height: 1; white-space: nowrap;
  will-change: transform;
}
.df-video-cursor__pill svg { flex: none; width: 16px; height: 16px; color: #fff; }

/* Where the device refuses a fullscreen player — iOS refuses it for iframes —
   the picture takes the video's own proportion in place instead, so the
   fallback is a whole video rather than a cropped one. Only ever set below the
   desktop breakpoint, where the expansion does not apply. */
.df-about.is-video-inline .df-about__media {
  height: auto;
  min-height: 0;
  aspect-ratio: var(--df-video-ar, 16 / 9);
}

/* ── The expansion, desktop only ──
   The copy column is lifted out of the grid and the picture carries on out
   into the space it leaves, arriving at the video's own proportion.

   Lifting rather than collapsing is the whole trick. A grid item with no
   width still wraps its text, and a column of one-word lines is taller than
   any picture — so a copy column left in the flow would drive the row height
   and the video would follow the words instead of its own shape. Taking it
   out of flow removes it from track sizing altogether: the row is then the
   picture and nothing else, whatever the client writes.

   It is pinned to the width and height it measured at rest — by script, not
   by a figure typed here — so it neither re-wraps as the column travels nor
   moves from where it was standing. It simply fades and slides away, and back
   again, in place. The pin is released once the reverse transition has
   finished and the column returns to sizing itself.

   Below the desktop breakpoint none of this applies: the video plays in the
   device's own fullscreen player instead. */
@media (min-width: 1081px) {
  /* Placement is stated rather than inferred, because an out-of-flow copy
     column would otherwise leave the picture as the first in-flow item and
     auto-placement would drop it into column one. */
  .df-about__text  { grid-column: 1; grid-row: 1; }
  .df-about__media { grid-column: 2; grid-row: 1; }

  .df-about.is-video-lifted .df-about__text {
    position: absolute; top: 0; left: 0; z-index: 1;
    width: var(--df-about-text-w); height: var(--df-about-text-h);
    pointer-events: none;
  }
  /* Copy longer than the picture stands taller than the row it has been
     lifted out of, so for the length of the transition the row is what it is
     allowed to show. The copy is fading either way; this only stops the tail
     of a long piece reaching into the section below on the way past. */
  .df-about.is-video-lifted .df-about__grid { overflow: hidden; }

  .df-about.is-video-open .df-about__grid {
    grid-template-columns: minmax(0, 0fr) minmax(0, 1fr);
    gap: 0;
  }
  .df-about.is-video-open .df-about__text {
    opacity: 0; transform: translate3d(-24px, 0, 0);
  }
  .df-about.is-video-open .df-about__media {
    border-radius: var(--df-r-panel);
    min-height: 0;
  }

  /* Re-measuring after a resize has to happen with the section standing still,
     or the frame it is measured in is one that is already moving. */
  .df-about.is-video-still .df-about__grid,
  .df-about.is-video-still .df-about__media,
  .df-about.is-video-still .df-about__text { transition: none; }
}

/* ───────────────────────────── Services ───────────────────────────── */

.df-services__head {
  display: flex; align-items: flex-end; justify-content: space-between; gap: clamp(24px, 2.3vw, 40px);
  margin-bottom: clamp(34px, 4.23vw, 73px);
}
.df-services__heading { max-width: 864px; }

.df-carousel { position: relative; }
.df-carousel__viewport { overflow: hidden; }
.df-carousel__track {
  display: flex; align-items: stretch; margin: 0; padding: 0; list-style: none;
  will-change: transform;
}
.df-carousel__slide { flex: 0 0 auto; display: flex; }

/* The rail is a full-bleed band, centred and capped on very wide screens. The
   track is inset so the first card lines up with the content shell, and cards
   travel off both edges rather than being cut off on the left. */
.df-carousel__viewport { width: min(100%, var(--df-band)); margin-inline: auto; }
.df-carousel__track { padding-left: var(--df-rail-gutter); }

.df-carousel--services .df-carousel__track { gap: clamp(14px, 1.16vw, 20px); }
.df-carousel--services .df-carousel__slide { width: clamp(300px, 26.7vw, 462px); }

.df-carousel__nav { display: flex; gap: 10px; flex: none; }
.df-carousel__btn {
  width: 45px; height: 45px; border-radius: 50%; border: 0; cursor: pointer;
  display: grid; place-items: center;
  transition: background-color .3s var(--df-ease), color .3s var(--df-ease), transform .2s var(--df-ease);
}
.df-carousel__btn svg { width: 20px; height: 17px; }
.df-carousel__btn--prev { background: rgba(255, 255, 255, .25); color: #fff; }
.df-carousel__btn--next { background: #fff; color: var(--df-ink-dark); }
/* The circle takes the theme colour; the arrow itself stays white. */
.df-carousel__btn:hover, .df-carousel__btn:focus-visible { background: var(--df-accent); color: #fff; transform: scale(1.06); }

/* The card carries a picture and a name and nothing else, so the picture is
   given the room the description and the button used to take. Its height comes
   from a ratio rather than a fixed figure: whatever width the rail hands the
   card at, the frame keeps its proportion instead of overflowing it. */
.df-service__card {
  display: flex; flex-direction: column; flex: 1; min-width: 0;
  padding: 6px;
  border-radius: var(--df-r-card);
  background: var(--df-glass);
  border: 1px solid transparent;
  -webkit-backdrop-filter: blur(var(--df-blur)); backdrop-filter: blur(var(--df-blur));
  transition: background-color .4s var(--df-ease), border-color .4s var(--df-ease), box-shadow .4s var(--df-ease);
}
.df-service:hover .df-service__card,
.df-service:focus-within .df-service__card {
  background: rgba(25, 25, 27, .42);
  border-color: var(--df-accent);
  box-shadow: 0 0 90px rgba(var(--df-accent-rgb), .28);
}
.df-service__media { border-radius: 24px; overflow: hidden; flex: none; }
.df-service__img {
  width: 100%; height: auto;
  aspect-ratio: var(--df-service-ratio, 4 / 5);
  object-fit: cover;
}
.df-service__body { padding: clamp(16px, 1.28vw, 22px) clamp(18px, 1.68vw, 29px) clamp(16px, 1.28vw, 22px); }
.df-service__title {
  margin: 0;
  font-family: var(--df-display); font-weight: 500; line-height: 1.25;
}

/* ─────────────────────── Film carousel (plugin) ───────────────────────
   The Sketch 3D Carousel plugin owns the motion; everything here is Direct
   Film dressing the component so it belongs to this page — its own type,
   spacing, poster shape and button. The plugin's stylesheet is already scoped
   to .s3dc-*, so none of this is undoing a global rule: it is only replacing
   the neutral defaults the component ships with. The section takes the page's
   own background, exactly as every other section does. */

.df-films__head { text-align: center; margin: 0 auto clamp(4px, 0.8vw, 14px); }
.df-films__head .df-eyebrow { margin-bottom: 0; }
.df-films__stage { position: relative; }

.df-films .s3dc-carousel {
  --s3dc-poster-width: clamp(122px, 15vw, 262px);
  /* The plugin's posters are 2:3, so the height follows from the width and
     the reflection is the 30% below set on the wrap. Naming both here is what
     lets the stage size itself rather than being a figure kept in step by
     hand — change the width and everything else follows. */
  --s3dc-poster-h: calc(var(--s3dc-poster-width) * 3 / 2);
  --s3dc-reflection: .3;
  --s3dc-orbit-y-origin: clamp(32px, 3.9vw, 68px);
  --s3dc-orbit-y-radius: clamp(36px, 4.4vw, 76px);
  max-width: none;
  margin: 0;
  padding: 0;
}

.df-films .s3dc-carousel__intro { max-width: 794px; margin: clamp(18px, 2vw, 34px) auto clamp(26px, 3.2vw, 54px); }
.df-films .s3dc-carousel__title {
  margin: 0;
  font-family: var(--df-text); font-weight: 400;
  font-size: clamp(35px, 2vw, 45px); line-height: 1.14; letter-spacing: -.01em;
}
.df-films .s3dc-carousel__subtext {
  margin: 23px 0 0;
  font-family: var(--df-ui); font-size: 16px; line-height: 30px;
  opacity: 1;
}

/* Exactly the room the frontmost poster and its reflection need, worked out
   from the poster itself: the orbit puts the front poster at origin + radius,
   and it stands its own height plus its reflection below that. Nothing can
   fall outside the stage at any width, whatever the poster size becomes. */
.df-films .s3dc-carousel__stage {
  height: calc(
    var(--s3dc-orbit-y-origin) + var(--s3dc-orbit-y-radius)
    + var(--s3dc-poster-h) * (1 + var(--s3dc-reflection)) + 6px
  );
}

/* Film posters are square-cornered — the printed thing, not a card. */
.df-films .s3dc-poster,
.df-films .s3dc-poster__img,
.df-films .s3dc-poster__reflection-wrap { border-radius: 0; }
.df-films .s3dc-poster__img { box-shadow: 0 30px 60px rgba(0, 0, 0, .55); }
/* The plugin backs its reflection with white so it reads on a light page.
   On this one the reflection sits straight on the page treatment. */
.df-films .s3dc-poster__reflection-wrap {
  background: transparent;
  height: calc(var(--s3dc-reflection) * 100%);
  -webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, .55), transparent);
  mask-image: linear-gradient(to bottom, rgba(0, 0, 0, .55), transparent);
}
.df-films .s3dc-poster__reflection { opacity: .4; }

/* The site button, not the plugin's. */
.df-films .s3dc-carousel__button {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: clamp(150px, 10.88vw, 188px); height: 45px; padding: 0 clamp(18px, 1.5vw, 26px);
  margin-top: clamp(28px, 2.9vw, 50px);
  border: 1px solid transparent; border-radius: var(--df-r-pill);
  background: #fff; color: var(--df-ink-dark);
  font-family: var(--df-ui); font-size: 16px; font-weight: 600; line-height: 20px;
  letter-spacing: normal; text-transform: none; text-decoration: none;
  transition: background-color .3s var(--df-ease), color .3s var(--df-ease), border-color .3s var(--df-ease);
}
.df-films .s3dc-carousel__button:hover,
.df-films .s3dc-carousel__button:focus,
.df-films .s3dc-carousel__button:focus-visible {
  background: var(--df-accent);
  border-color: var(--df-accent);
  color: var(--df-accent-ink);
  transform: none;
}

/* ───────────────────────────── Our Work ───────────────────────────── */

.df-work__head { text-align: center; max-width: 794px; margin: 0 auto clamp(28px, 2.43vw, 42px); }
.df-work__head .df-eyebrow { margin-bottom: 21px; }
.df-work__lede { margin-top: 23px; font-family: var(--df-ui); font-size: 16px; line-height: 30px; }
.df-work__lede p { margin: 0; }

/* Multi-column would re-balance the whole grid whenever a card grew, which is
   what made the last card jump. Cards are dealt into real columns instead, so
   expanding one only ever changes the height of its own column. */
.df-work__grid { --df-cols: 2; column-count: 2; column-gap: clamp(14px, 1.16vw, 20px); }
.df-work__grid.is-columned {
  column-count: initial;
  display: flex; align-items: flex-start; gap: clamp(14px, 1.16vw, 20px);
}
.df-work__col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: clamp(14px, 1.16vw, 20px); }
.df-project { break-inside: avoid; margin-bottom: clamp(14px, 1.16vw, 20px); display: block; }
.df-work__grid.is-columned .df-project { margin-bottom: 0; }
.df-project[hidden] { display: none; }

.df-project__inner {
  padding: 10px;
  border-radius: var(--df-r-card);
  background: var(--df-glass);
  border: 1px solid transparent;
  -webkit-backdrop-filter: blur(var(--df-blur)); backdrop-filter: blur(var(--df-blur));
  transition: border-color .45s var(--df-ease), box-shadow .45s var(--df-ease), background-color .45s var(--df-ease);
}
.df-project.is-open .df-project__inner {
  border-color: var(--df-accent);
  box-shadow: 0 0 120px rgba(var(--df-accent-rgb), .30), inset 0 0 120px rgba(var(--df-accent-rgb), .10);
}

.df-project__media { position: relative; border-radius: 22px; overflow: hidden; }
.df-project__media-btn { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: pointer; }
.df-project__img { width: 100%; aspect-ratio: 679 / 407; object-fit: cover; transition: transform .7s var(--df-ease); }
.df-project__media-btn:hover .df-project__img { transform: scale(1.03); }
.df-project__dots { position: absolute; left: 49px; bottom: 31px; display: flex; gap: 7px; }
.df-project__dot {
  width: 66px; height: 4px; border-radius: var(--df-r-pill);
  background: rgba(255, 255, 255, .4);
  -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
}
.df-project__dot.is-active { background: #fff; }

.df-project__head {
  display: flex; align-items: center; justify-content: space-between; gap: clamp(12px, 1.16vw, 20px);
  padding: clamp(20px, 1.68vw, 29px) clamp(16px, 1.27vw, 22px) clamp(18px, 1.56vw, 27px) clamp(20px, 2.08vw, 36px);
}
.df-project__title {
  margin: 0;
  font-family: var(--df-display); font-weight: 500; line-height: 1.4;
}
.df-project__toggle {
  background: none; border: 0; padding: 0; cursor: pointer; text-align: left;
  font: inherit; color: inherit;
}
.df-project__toggle::after { content: ""; position: absolute; inset: 0; }
.df-project__head { position: relative; }

.df-status {
  display: inline-flex; align-items: center; gap: 8px; flex: none;
  height: 36px; padding: 0 16px;
  border-radius: var(--df-r-pill);
  background: var(--df-status-tint, rgba(255, 255, 255, .16));
  font-family: var(--df-ui); font-size: 13.5px; line-height: 16px; white-space: nowrap;
}
.df-status__dot { width: 10px; height: 10px; border-radius: 50%; background: var(--df-status-dot, #fff); }

.df-project__panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .5s var(--df-ease); }
.df-project.is-open .df-project__panel { grid-template-rows: 1fr; }
.df-project__panel-inner { overflow: hidden; min-height: 0; }
.df-project.is-open .df-project__panel-inner { overflow: visible; }

.df-project__text { padding: 0 clamp(20px, 2.08vw, 36px); font-family: var(--df-ui); font-size: 16px; line-height: 30px; }
.df-project__services { margin-top: 32px; padding: 26px 0 0; border-top: 1px solid var(--df-hairline); margin-inline: clamp(20px, 2.08vw, 36px); }
.df-project__services-title {
  margin: 0 0 20px;
  font-family: var(--df-display); font-weight: 400; font-size: clamp(17px, 1.16vw, 20px); line-height: 1.6;
}
.df-tags { display: flex; flex-wrap: wrap; gap: 15px; list-style: none; margin: 0; padding: 0; }
.df-tag {
  display: inline-flex; align-items: center; height: 44px; padding: 0 24px;
  border-radius: var(--df-r-pill); background: var(--df-glass-soft);
  font-family: var(--df-ui); font-size: 15px; line-height: 20px;
}
.df-project__actions { display: flex; flex-wrap: wrap; gap: clamp(12px, 1.22vw, 21px); padding: clamp(24px, 1.97vw, 34px) clamp(20px, 2.08vw, 36px) clamp(24px, 2.08vw, 36px); }
.df-project__actions .df-btn { flex: 1 1 260px; min-width: 0; }

.df-work__more { display: flex; justify-content: center; margin-top: 47px; }

/* ───────────────────────────── FAQs ───────────────────────────── */

.df-faqs__head { text-align: center; max-width: 794px; margin: 0 auto clamp(34px, 3.94vw, 68px); }
.df-faqs__head .df-eyebrow { margin-bottom: 21px; }

.df-faqs__list { list-style: none; margin: 0 auto; padding: 0; max-width: 1000px; display: flex; flex-direction: column; gap: 18px; }
.df-faq {
  border-radius: var(--df-r-panel);
  border: 1px solid var(--df-hairline);
  background: var(--df-glass);
  -webkit-backdrop-filter: blur(var(--df-blur)); backdrop-filter: blur(var(--df-blur));
  transition: background-color .35s var(--df-ease), border-color .35s var(--df-ease);
}
/* Answers the same way the service cards do — border only, never a glow. */
.df-faq:hover, .df-faq:focus-within, .df-faq.is-open { border-color: var(--df-accent); }
.df-faq.is-open { background: rgba(255, 255, 255, .07); }
.df-faq__q { margin: 0; font-size: inherit; }
.df-faq__btn {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  width: 100%; min-height: 81px; padding: 20px clamp(20px, 2.66vw, 46px) 20px clamp(20px, 2.37vw, 41px);
  background: none; border: 0; cursor: pointer; text-align: left;
}
.df-faq__label { font-family: var(--df-ui); font-size: 16px; line-height: 30px; font-weight: 400; transition: font-weight .2s; }
.df-faq.is-open .df-faq__label { font-weight: 700; }
.df-faq__icon { position: relative; flex: none; width: 22px; height: 22px; }
.df-faq__icon::before, .df-faq__icon::after {
  content: ""; position: absolute; left: 50%; top: 50%; background: #fff; border-radius: 2px;
  transform: translate(-50%, -50%);
  transition: transform .35s var(--df-ease), opacity .25s var(--df-ease);
}
.df-faq__icon::before { width: 22px; height: 1.6px; }
.df-faq__icon::after { width: 1.6px; height: 22px; }
.df-faq.is-open .df-faq__icon::after { transform: translate(-50%, -50%) scaleY(0); opacity: 0; }

.df-faq__a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .4s var(--df-ease); }
.df-faq__a[hidden] { display: grid; }
.df-faq.is-open .df-faq__a { grid-template-rows: 1fr; }
.df-faq__a-inner { overflow: hidden; min-height: 0; }
.df-faq__a-inner > :first-child { padding-top: 0; }
.df-faq__a-inner { padding: 0 clamp(20px, 3.94vw, 68px) 0 clamp(20px, 2.37vw, 41px); }
.df-faq.is-open .df-faq__a-inner { padding-bottom: 30px; }
.df-faq__a-inner p { margin: 0 0 16px; font-size: 16px; line-height: 30px; }
.df-faq__a-inner p:last-child { margin-bottom: 0; }

/* ───────────────────────────── Reviews ───────────────────────────── */

.df-reviews__head {
  display: flex; align-items: flex-end; justify-content: space-between; gap: clamp(24px, 2.3vw, 40px);
  margin-bottom: clamp(34px, 3.94vw, 68px);
}
.df-reviews__intro { max-width: 620px; }
.df-reviews__intro .df-eyebrow { margin-bottom: 21px; }
.df-reviews__lede { margin-top: 20px; max-width: 384px; font-family: var(--df-ui); font-size: 16px; line-height: 30px; }
.df-reviews__lede p { margin: 0; }
.df-reviews__side { display: flex; flex-direction: column; align-items: flex-end; gap: 20px; flex: none; }
.df-reviews__actions { display: flex; gap: 15px; flex: none; }
.df-reviews__nav { display: flex; justify-content: center; margin-top: clamp(28px, 2.6vw, 45px); }

.df-carousel--reviews .df-carousel__track { gap: clamp(10px, 0.7vw, 12px); }
.df-carousel--reviews .df-carousel__slide { width: clamp(370px, 27.49vw, 475px); }

.df-review__card {
  flex: 1; min-width: 0;
  min-height: clamp(200px, 13.95vw, 241px); padding: 22px clamp(20px, 2.08vw, 36px) 24px clamp(18px, 1.56vw, 27px);
  border-radius: var(--df-r-card);
  background: var(--df-glass-mid);
  -webkit-backdrop-filter: blur(var(--df-blur)); backdrop-filter: blur(var(--df-blur));
  display: flex; flex-direction: column;
  transition: box-shadow .4s var(--df-ease);
}
.df-review:hover .df-review__card { box-shadow: 0 0 70px rgba(var(--df-accent-rgb), .20); }
.df-review__head { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 11px; }
.df-review__card { --df-avatar: clamp(48px, 3.47vw, 60px); }
.df-review__avatar {
  flex: none; width: var(--df-avatar); height: var(--df-avatar);
  border-radius: 50%; overflow: hidden; background: #fff;
}
.df-review__avatar img { width: 100%; height: 100%; object-fit: cover; }
/* No photograph: the author's initials, set in the same circle. */
.df-review__initials {
  display: grid; place-items: center; width: 100%; height: 100%;
  color: var(--df-ink-dark);
  font-family: var(--df-display); font-weight: 500;
  font-size: calc(var(--df-avatar) * .36); line-height: 1; letter-spacing: .01em;
}
/* The name column shrinks first — the role simply wraps — and only once it
   would fall below a readable floor do the stars drop to their own line. */
.df-review__who { display: flex; flex-direction: column; flex: 1 1 0; min-width: min(132px, 100%); }
.df-review__name { font-family: var(--df-text); font-weight: 500; font-size: 16px; line-height: 20px; overflow-wrap: anywhere; }
.df-review__role { font-family: var(--df-text); font-weight: 400; font-size: 14px; line-height: 20px; opacity: .58; overflow-wrap: anywhere; }
.df-stars { display: inline-flex; gap: 3.5px; flex: none; color: #fff; }
.df-stars svg { flex: none; width: 15px; height: 15px; }
.df-review__text {
  margin-top: clamp(14px, 1.27vw, 22px); min-width: 0;
  font-family: var(--df-ui); font-size: 15px; line-height: 22px;
}
.df-review__text p { margin: 0; }

/* ───────────────────────────── Enquiry ───────────────────────────── */

.df-enquiry { padding-top: clamp(90px, 15.05vw, 260px); padding-bottom: clamp(80px, 10.3vw, 178px); }
.df-enquiry .df-bgword { top: 0; }

.df-enquiry__grid {
  display: grid;
  grid-template-columns: minmax(0, 720fr) minmax(0, 502fr);
  gap: clamp(32px, 11.34vw, 196px);
  align-items: start;
}

.df-form {
  position: relative;
  padding: clamp(24px, 2.37vw, 41px) clamp(22px, 2.55vw, 44px) clamp(26px, 2.55vw, 44px);
  border-radius: var(--df-r-panel);
  background: var(--df-glass-mid);
  border: 1px solid var(--df-accent);
  -webkit-backdrop-filter: blur(var(--df-blur)); backdrop-filter: blur(var(--df-blur));
  box-shadow: 0 0 100px rgba(var(--df-accent-rgb), .12);
  transition: border-color .4s var(--df-ease), box-shadow .4s var(--df-ease);
}
.df-form__title { margin: 0 0 8px; }
.df-form__intro { margin: 0 0 34px; font-family: var(--df-ui); font-size: 16px; line-height: 30px; }
.df-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.df-form__alert {
  margin: 0 0 20px; padding: 12px 18px; border-radius: 12px;
  background: rgba(255, 106, 106, .14); border: 1px solid rgba(255, 138, 138, .55);
}
.df-form__alert p { margin: 0; font-size: 15px; line-height: 24px; }

.df-form__field { position: relative; margin-bottom: 15px; }
.df-form__label {
  position: absolute; left: 26px; top: 26px;
  font-family: var(--df-form); font-size: 16px; line-height: 19px; color: #fff;
  pointer-events: none; transform-origin: left top;
  transition: transform .22s var(--df-ease), opacity .22s var(--df-ease);
}
.df-form__field--area .df-form__label { top: 27px; }
.df-form__input {
  width: 100%; height: 74px; padding: 26px 26px 8px;
  border-radius: var(--df-r-panel);
  border: 1px solid var(--df-field-border);
  background: var(--df-glass-mid);
  color: #fff; font-family: var(--df-form); font-size: 16px; line-height: 19px;
  transition: border-color .3s var(--df-ease), box-shadow .3s var(--df-ease);
}
textarea.df-form__input { height: 148px; padding-top: 34px; resize: vertical; line-height: 24px; }
.df-form__input:focus { outline: none; border-color: var(--df-accent); box-shadow: 0 0 0 3px rgba(var(--df-accent-rgb), .18); }
.df-form__field.has-value .df-form__label,
.df-form__field:focus-within .df-form__label { transform: translateY(-13px) scale(.72); opacity: .72; }
.df-form__field.has-error .df-form__input { border-color: rgba(255, 138, 138, .9); }
.df-form__error { margin: 6px 0 0 26px; font-size: 13px; line-height: 20px; color: #ff9a9a; }

.df-form__group { margin: 22px 0 20px; padding: 0; border: 0; }
.df-form__legend { padding: 0 0 12px; font-family: var(--df-form); font-size: 16px; line-height: 19px; }
.df-form__checks { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px 16px; }
.df-check { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font-family: var(--df-form); font-size: 16px; line-height: 20px; }
.df-check input { position: absolute; opacity: 0; width: 20px; height: 20px; margin: 0; cursor: pointer; }
.df-check__box {
  flex: none; width: 20px; height: 20px; border-radius: 5px;
  border: 1px solid var(--df-field-border); background: var(--df-glass-mid);
  display: grid; place-items: center;
  transition: background-color .2s var(--df-ease), border-color .2s var(--df-ease);
}
.df-check__box::after {
  content: ""; width: 10px; height: 6px; border-left: 2px solid var(--df-accent-ink); border-bottom: 2px solid var(--df-accent-ink);
  transform: rotate(-45deg) scale(0); transition: transform .2s var(--df-ease);
}
.df-check input:checked + .df-check__box { background: var(--df-accent); border-color: var(--df-accent); }
.df-check input:checked + .df-check__box::after { transform: rotate(-45deg) scale(1); }
.df-check input:focus-visible + .df-check__box { outline: 2px solid var(--df-accent); outline-offset: 2px; }

.df-form__submit { width: 100%; height: 60px; margin-top: 27px; }

.df-enquiry__aside { padding-top: 41px; }
.df-enquiry__aside .df-h3 { max-width: 340px; }
.df-enquiry__aside .df-eyebrow { margin-bottom: 21px; }
.df-enquiry__body { margin-top: 26px; font-family: var(--df-ui); font-size: 16px; line-height: 30px; }

/* The list sizes itself to its widest pill and no further, so both pills match
   and neither is forced to wrap until the column genuinely runs out of room. */
.df-contact-cards { list-style: none; margin: 30px 0 0; padding: 0; display: flex; flex-direction: column; gap: 13px; width: fit-content; min-width: min(314px, 100%); max-width: 100%; }
.df-contact-cards > li { min-width: 0; }
/* The pill grows with its content and the text column is allowed to shrink,
   so a long address wraps inside the pill rather than escaping it. */
.df-contact-card {
  display: flex; align-items: center; gap: clamp(12px, 0.93vw, 16px);
  width: 100%; max-width: 100%; min-height: 73px;
  padding: 5px clamp(16px, 1.4vw, 24px) 5px 5px;
  border-radius: 40px; background: var(--df-glass-soft);
  text-decoration: none;
  transition: background-color .3s var(--df-ease);
}
.df-contact-card:hover, .df-contact-card:focus-visible { background: rgba(255, 255, 255, .16); }
.df-contact-card__icon {
  flex: none; width: 63px; height: 63px; border-radius: 50%; background: #fff;
  display: grid; place-items: center; color: var(--df-ink-dark);
  transition: background-color .3s var(--df-ease), color .3s var(--df-ease);
}
.df-contact-card:hover .df-contact-card__icon,
.df-contact-card:focus-visible .df-contact-card__icon { background: var(--df-accent); color: #fff; }
.df-contact-card__icon svg { flex: none; width: 24px; height: 24px; }
.df-contact-card__text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; padding: 6px 0; }
.df-contact-card__label { font-family: var(--df-text); font-weight: 500; font-size: 13px; line-height: 18px; }
.df-contact-card__value {
  font-family: var(--df-display); font-weight: 300;
  font-size: clamp(15px, 1.39vw, 24px); line-height: 1.25;
  min-width: 0; overflow-wrap: anywhere; word-break: break-word;
}

.df-social { margin-top: 41px; padding-top: 40px; border-top: 1px solid var(--df-hairline); max-width: 468px; }
.df-social__title { margin: 0 0 14px; font-family: var(--df-text); font-weight: 400; font-size: 18px; line-height: 24px; }
.df-social__list { display: flex; gap: 8px; list-style: none; margin: 0; padding: 0; }
.df-social__list a {
  display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%;
  color: #fff; transition: color .3s var(--df-ease), background-color .3s var(--df-ease);
}
.df-social__list a:hover { color: var(--df-accent); background: rgba(var(--df-accent-rgb), .12); }
.df-social__list svg { flex: none; width: 24px; height: 24px; }

/* ───────────────────────────── Footer ───────────────────────────── */

.df-footer { padding: 0 0 30px; }
.df-footer__panel {
  width: min(var(--df-shell-footer), 100% - (var(--df-gutter) * 2));
  margin-inline: auto;
  padding: clamp(40px, 5.27vw, 91px) clamp(24px, 3.24vw, 56px) clamp(30px, 2.55vw, 44px) clamp(24px, 3.88vw, 67px);
  border-radius: 40px;
  background: rgba(255, 255, 255, .073);
  -webkit-backdrop-filter: blur(var(--df-blur)); backdrop-filter: blur(var(--df-blur));
}
.df-footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 676fr) minmax(0, 232fr) minmax(0, 305fr) minmax(0, 348fr);
  gap: 0;
}
.df-footer__logo { display: block; width: 209px; }
.df-footer__logo svg { width: 100%; height: auto; }
.df-footer__col ul { list-style: none; margin: 0; padding: 0; }
.df-footer__col a {
  display: inline-block; padding: 4px 0;
  text-decoration: none; font-family: var(--df-ui); font-size: 16px; line-height: 27px;
}
.df-footer__col a:hover { color: var(--df-accent); }
.df-footer__col-title { margin: 0 0 14px; font-family: var(--df-display); font-weight: 500; font-size: clamp(17px, 1.16vw, 20px); line-height: 1.4; }
.df-footer__mailing-label { margin: 0 0 14px; font-family: var(--df-ui); font-size: 16px; line-height: 28px; }

.df-mailing { position: relative; display: flex; align-items: center; max-width: 348px; }
.df-mailing__input {
  width: 100%; height: 65px; padding: 0 74px 0 24px;
  border-radius: var(--df-r-pill); border: 1px solid rgba(255, 255, 255, .8);
  background: rgba(255, 255, 255, .11); color: #fff;
  font-family: var(--df-form); font-size: 16px;
}
.df-mailing__input::placeholder { color: rgba(255, 255, 255, .5); }
.df-mailing__input:focus { outline: none; border-color: var(--df-accent); }
.df-mailing__submit {
  position: absolute; right: 5px; top: 50%; transform: translateY(-50%);
  width: 54px; height: 54px; border-radius: 50%; border: 0; cursor: pointer;
  background: #fff; color: var(--df-ink-dark);
  display: grid; place-items: center;
  transition: background-color .3s var(--df-ease), color .3s var(--df-ease);
}
.df-mailing__submit:hover, .df-mailing__submit:focus-visible { background: var(--df-accent); color: #fff; }
.df-mailing__submit svg { width: 20px; height: 17px; }

.df-mailing__note { margin: 10px 0 0; font-size: 14px; line-height: 22px; color: var(--df-accent); }
.df-mailing__note--error { color: #ff9a9a; }

.df-footer__legal { margin: clamp(40px, 6.19vw, 107px) 0 0; font-family: var(--df-ui); font-size: 16px; line-height: 24px; }
.df-footer__legal strong { font-weight: 600; }
.df-footer__credit a { text-decoration: underline; text-underline-offset: 3px; }

/* ───────────────────────────── Legal pages ───────────────────────────── */

.df-legal { padding: calc(var(--df-header-h) + clamp(48px, 6.71vw, 116px)) 0 clamp(70px, 7.52vw, 130px); position: relative; }
.df-legal__head { margin-bottom: clamp(48px, 8.33vw, 144px); }
.df-legal__title {
  margin: 0;
  font-family: var(--df-display); font-weight: 300;
  line-height: 1.16; letter-spacing: -.01em;
}
.df-legal__updated { margin: 12px 0 0; font-family: var(--df-ui); font-size: 16px; line-height: 24px; }

.df-legal__layout { display: grid; grid-template-columns: minmax(0, 860fr) minmax(0, 480fr); gap: clamp(32px, 6.19vw, 107px); align-items: start; }
.df-legal__section { scroll-margin-top: 0; }
.df-legal__section + .df-legal__section { margin-top: 36px; }
.df-legal__section-title { margin: 0 0 22px; line-height: 1.5; }
.df-legal__body .df-prose { font-family: var(--df-ui); font-size: 16px; line-height: 30px; }

.df-legal__aside { position: sticky; top: calc(var(--df-header-h) + 24px); }
.df-legal__index {
  padding: 16px 19px;
  border-radius: var(--df-r-panel);
  background: var(--df-glass);
  -webkit-backdrop-filter: blur(var(--df-blur)); backdrop-filter: blur(var(--df-blur));
  max-height: calc(100vh - var(--df-header-h) - 64px); overflow-y: auto;
}
.df-legal__index ul { list-style: none; margin: 0; padding: 0; }
/* Compact by design: no minimum height, so a row is exactly as tall as the
   words in it. 16px is the navigation size at every width — there is no
   responsive rule anywhere that grows it again. */
.df-legal__index a {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 10px 15px;
  border-radius: var(--df-r-pill);
  border: 1px solid transparent;
  text-decoration: none;
  font-family: var(--df-ui); font-size: 16px; line-height: 1.5;
  transition: background-color .3s var(--df-ease), border-color .3s var(--df-ease);
}
.df-legal__index a:hover { background: rgba(255, 255, 255, .06); }
.df-legal__index a.is-current { background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .23); }
.df-legal__index-label { min-width: 0; }
.df-legal__index-num { flex: none; opacity: .85; }

/* ─────────────────────── Enquiry confirmation ─────────────────────── */

.df-confirm { padding: calc(var(--df-header-h) + clamp(48px, 6.25vw, 108px)) 0 0; }
.df-confirm__inner { display: flex; flex-direction: column; align-items: center; text-align: center; }
.df-confirm__title {
  margin: 0;
  max-width: 900px;
  font-family: var(--df-display); font-weight: 300;
  line-height: 1.16; letter-spacing: -.01em;
}
.df-confirm__body { margin-top: 22px; max-width: 560px; font-family: var(--df-ui); font-size: clamp(15px, 1.16vw, 20px); line-height: 1.6; }
.df-confirm__body p { margin: 0; }
.df-confirm__actions { margin-top: 34px; }
.df-page--confirmation .df-reviews { padding-top: 118px; }

/* ───────────────────────────── Lightbox ───────────────────────────── */

.df-lightbox { position: fixed; inset: 0; z-index: 120; display: grid; place-items: center; }
.df-lightbox[hidden] { display: none; }
.df-lightbox__backdrop {
  position: absolute; inset: 0;
  background: rgba(12, 15, 16, .72);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  animation: df-fade .3s var(--df-ease);
}
.df-lightbox__dialog {
  position: relative;
  width: min(1119px, 100% - 40px);
  animation: df-pop .35s var(--df-ease);
}
@keyframes df-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes df-pop { from { opacity: 0; transform: scale(.97); } to { opacity: 1; transform: none; } }

.df-lightbox__stage { position: relative; border-radius: 8px; overflow: visible; }
.df-lightbox__img {
  width: 100%; max-height: min(660px, 72vh); object-fit: cover;
  border-radius: 8px; background: rgba(255, 255, 255, .05);
}
/* The way out, not a feature of the picture. It keeps the full 52px target it
   always had — only the drawing of it steps back: a dark wash and a hairline
   that read on pale and dark artwork alike, held at low opacity until it is
   wanted. */
.df-lightbox__close {
  position: absolute; top: 12px; right: 12px;
  width: 52px; height: 52px; border-radius: 50%; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .2);
  background: rgba(12, 15, 16, .4);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  color: #fff; opacity: .5;
  display: grid; place-items: center;
  transition: background-color .25s var(--df-ease), border-color .25s var(--df-ease),
              opacity .25s var(--df-ease), color .25s var(--df-ease), transform .2s var(--df-ease);
}
.df-lightbox__close:hover, .df-lightbox__close:focus-visible {
  opacity: 1;
  background: rgba(12, 15, 16, .72);
  border-color: rgba(255, 255, 255, .55);
  color: #fff;
  transform: rotate(90deg);
}
.df-lightbox__close svg { width: 17px; height: 17px; }

.df-lightbox__bar { display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-top: 24px; }
.df-lightbox__controls { display: flex; align-items: center; gap: 14px; }
/* Tabular figures so the count does not shuffle sideways as it passes 9. */
.df-lightbox__count {
  margin: 0; font-family: var(--df-ui); font-size: 16px; line-height: 24px;
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1;
}
.df-lightbox__nav {
  width: 45px; height: 45px; border-radius: 50%; border: 0; cursor: pointer;
  display: grid; place-items: center;
  transition: background-color .3s var(--df-ease), color .3s var(--df-ease), transform .2s var(--df-ease);
}
.df-lightbox__nav svg { width: 20px; height: 17px; }
.df-lightbox__nav--prev { background: rgba(255, 255, 255, .25); color: #fff; }
.df-lightbox__nav--next { background: #fff; color: var(--df-ink-dark); }
.df-lightbox__nav:hover, .df-lightbox__nav:focus-visible { background: var(--df-accent); color: #fff; transform: scale(1.06); }

/* Fitted rather than filled — for a set whose pictures are not the landscape
   shape the projects are, such as the film posters. Everything else about the
   viewer is unchanged: same backdrop, same dialog, same close, same bar. The
   dialog is sized to the picture so the close control still sits on its
   corner and the bar still runs its width. */
.df-lightbox--contain .df-lightbox__dialog {
  width: min(calc(var(--df-lb-max, min(720px, 78vh)) * var(--df-lb-ar, 1)), 100% - 40px);
}
.df-lightbox--contain .df-lightbox__img {
  max-height: var(--df-lb-max, min(720px, 78vh));
  object-fit: contain;
  /* A film poster keeps its square corners here as well as in the carousel —
     it is the same printed thing, seen larger. */
  border-radius: 0;
}

body.df-lightbox-open, body.df-menu-open { overflow: hidden; }

/* ───────────────────────────── Responsive ─────────────────────────────
   Sizing and spacing are fluid (clamp/fr/min-max) throughout, so these rules
   are reserved for the points where the layout itself genuinely changes. */

/* ── Tablet and below ──
   The carousels stop travelling off the edges and show complete cards only,
   sized so a whole number of them fills the shell exactly. */
@media (max-width: 1080px) {
  .df { --df-slides: 2; }

  .df-header__nav, .df-header__cta { display: none; }
  .df-header__toggle { display: flex; }
  .df-header__bar { justify-content: space-between; }
  .df-header.is-scrolled .df-header__bar,
  .df-header.is-menu-open .df-header__bar {
    background: rgba(255, 255, 255, .05);
    border-color: rgba(255, 255, 255, .4);
    -webkit-backdrop-filter: blur(11.75px); backdrop-filter: blur(11.75px);
  }

  .df-hero__content { top: 56%; }

  .df-about__grid { grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 4vw, 44px); }
  .df-about__text .df-h3, .df-about__body { max-width: none; }
  /* Stacked, there is no column to match, so the copy sits at the top of its
     own box and the picture takes a sensible height of its own again. */
  .df-about__text { justify-content: flex-start; padding-block: clamp(4px, 1.6vw, 18px); }
  .df-about__media { min-height: 0; height: clamp(260px, 46vw, 460px); }
  /* No expansion below the desktop breakpoint: the video goes to the device's
     own fullscreen player instead, and the section is left exactly as it is. */
  .df-about__grid, .df-about__media { transition: none; }

  .df-films .s3dc-carousel__intro { margin-bottom: clamp(20px, 3vw, 34px); }
  /* The rail is narrower here, so the posters take a larger share of it. The
     stage keeps sizing itself from the result. */
  .df-films .s3dc-carousel { --s3dc-poster-width: clamp(122px, 20vw, 210px); }

  .df-services__head, .df-reviews__head { flex-direction: column; align-items: flex-start; }

  /* Testimonials read as one centred column above the carousel. */
  .df-reviews__head { align-items: center; text-align: center; }
  .df-reviews__intro { max-width: 100%; }
  .df-reviews__lede { max-width: 52ch; margin-inline: auto; }
  .df-reviews__side { align-items: center; width: 100%; }

  .df-carousel__viewport { width: 100%; }
  .df-carousel__track { padding-left: var(--df-rail-gutter); }
  .df-carousel--services .df-carousel__track,
  .df-carousel--reviews .df-carousel__track { gap: var(--df-rail-gutter); }
  .df-carousel--services .df-carousel__slide,
  .df-carousel--reviews .df-carousel__slide {
    width: calc((var(--df-shell) - (var(--df-slides) - 1) * var(--df-rail-gutter)) / var(--df-slides));
  }
  /* Once the rail is showing one or two whole cards the card is wide enough
     that a 4:5 frame would be taller than the screen it is on. The ceiling
     only bites at those widths; the ratio is untouched everywhere else. */
  .df-service__img { max-height: 620px; }

  .df-work__grid { --df-cols: 1; column-count: 1; }
  .df-enquiry__grid { grid-template-columns: minmax(0, 1fr); gap: clamp(40px, 6vw, 56px); }
  .df-enquiry__aside { padding-top: 0; }
  /* Stacked, the contents belong before the document rather than after it.
     Grid order does the moving so the markup stays as it is; the aside is
     still after the body in the source, which is where the keyboard meets it. */
  .df-legal__layout { grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 4vw, 40px); }
  .df-legal__aside { position: static; order: -1; }
  .df-legal__index { max-height: none; }

  /* Footer reads as one centred composition once it leaves four columns. */
  .df-footer__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(28px, 4vw, 40px) clamp(20px, 3vw, 32px);
    justify-items: center; text-align: center;
  }
  .df-footer__brand { grid-column: 1 / -1; }
  .df-footer__col { width: 100%; }
  /* The sign-up runs the full width so the last row is never half empty. */
  .df-footer__mailing { grid-column: 1 / -1; display: flex; flex-direction: column; align-items: center; }
  .df-mailing { width: 100%; max-width: 348px; margin-inline: auto; }
  .df-footer__legal { text-align: center; }
  .df-footer__legal strong { display: block; }
  .df-footer__credit { display: inline-block; margin-top: 4px; }
}

@media (max-width: 820px) {
  .df { --df-slides: 1; }
}

@media (max-width: 780px) {
  .df { --df-gutter: 20px; }
  .df-hero { --df-hero-pad: 12px; }
  .df-hero__stage { max-height: calc(100svh - 12px); }
  .df-hero__media { inset: 0 0 30px; border-radius: 28px; }
  .df-hero__mark { width: clamp(104px, 26vw, 163px); }
  .df-video-btn { right: 50%; transform: translateX(50%); bottom: 16px; }
  .df-review__card { min-height: 0; }
  .df-service__card { min-height: 0; }
  .df-form__checks { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .df-form__input { height: 68px; padding: 24px 20px 8px; }
  .df-form__label { left: 20px; top: 24px; }
  .df-footer__grid { grid-template-columns: minmax(0, 1fr); }
  .df-footer__panel { border-radius: 28px; }
  .df-lightbox__bar { flex-direction: column; align-items: flex-start; gap: 12px; margin-top: 16px; }
  .df-lightbox__close { width: 44px; height: 44px; top: 8px; right: 8px; }
  .df-project__dots { left: clamp(18px, 5vw, 49px); bottom: clamp(14px, 3.6vw, 31px); }
  .df-project__dot { width: clamp(34px, 9vw, 66px); }
  .df-glow { width: 900px; height: 900px; margin: -450px 0 0 -450px; }
}

@media (max-width: 560px) {
  .df-form__checks { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 480px) {
  .df-btn { min-width: 0; width: 100%; }
  .df-reviews__actions { flex-direction: column; align-self: stretch; width: 100%; }
  .df-reviews__side { width: 100%; }
  .df-about__actions { flex-direction: column; align-items: stretch; }
  .df-project__actions .df-btn { flex: 1 1 100%; }
  .df-header__mobile-cta { width: 100%; }
}

@media (max-width: 420px) {
  .df-hero__actions { flex-direction: column; align-self: stretch; }
}

@media (min-width: 1081px) {
  .df-header__mobile { display: none !important; }
}

/* ──────────────────────── Entrance animations ────────────────────────
   One system for the whole site. The elements below are named once, given a
   paused entrance animation, and released a group at a time by an
   IntersectionObserver. The animation is taken off again when the sequence
   finishes so nothing lingers over the hover, expand and carousel transforms
   that own these elements afterwards.

   The .df-anim gate is set on <html> by a short script in the head — before
   anything paints, and only when the browser can observe and the visitor has
   not asked for reduced motion. Without it every rule here is inert and the
   page renders exactly as it did, which is also what happens if the script or
   the stylesheet never arrives. */

@keyframes df-rv-rise {
  from { opacity: 0; transform: translate3d(0, var(--df-rv-y, 30px), 0); }
  to   { opacity: 1; transform: none; }
}
/* A quieter treatment for large picture panels: barely any travel, a hint of
   scale, so the frame resolves rather than slides. */
@keyframes df-rv-soft {
  from { opacity: 0; transform: translate3d(0, var(--df-rv-y-soft, 14px), 0) scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* :where() keeps this at a single class of specificity so the release and
   clean-up rules below can simply follow it. */
.df-anim :where(
  .df-header__bar,
  .df-eyebrow,
  .df-hero__mark, .df-hero__title, .df-hero__intro, .df-hero__actions,
  .df-about__text > h2, .df-about__body, .df-about__actions, .df-about__media,
  .df-films__stage,
  .df-services__heading, .df-services__head .df-carousel__nav,
  .df-carousel--services .df-carousel__slide,
  .df-work__head > h2, .df-work__lede, .df-project, .df-work__more,
  .df-faqs__head > h2, .df-faq,
  .df-reviews__intro > h2, .df-reviews__lede, .df-reviews__actions,
  .df-carousel--reviews .df-carousel__slide, .df-reviews__nav .df-carousel__nav,
  .df-enquiry__aside > h2, .df-enquiry__body, .df-contact-cards > li, .df-social,
  .df-enquiry__form-wrap,
  .df-footer__grid > *, .df-footer__legal,
  .df-legal__title, .df-legal__updated, .df-legal__section, .df-legal__index,
  .df-confirm__title, .df-confirm__body, .df-confirm__actions
) {
  animation: df-rv-rise var(--df-rv-t, .78s) var(--df-rv-ease) var(--df-rv-d, 0ms) both paused;
}

/* The sequence inside a section: label, heading, copy, buttons, component.
   Tight enough to read as one entrance rather than five. */
.df-anim :is(.df-eyebrow, .df-hero__mark, .df-legal__title, .df-confirm__title, .df-footer__legal) { --df-rv-d: 0ms; }
.df-anim :is(.df-hero__title, .df-about__text > h2, .df-services__heading, .df-work__head > h2,
             .df-faqs__head > h2, .df-reviews__intro > h2, .df-enquiry__aside > h2,
             .df-legal__updated, .df-confirm__body) { --df-rv-d: 90ms; }
.df-anim :is(.df-hero__intro, .df-about__body, .df-work__lede, .df-reviews__lede,
             .df-enquiry__body, .df-confirm__actions) { --df-rv-d: 170ms; }
.df-anim :is(.df-hero__actions, .df-about__actions, .df-reviews__actions) { --df-rv-d: 250ms; }
.df-anim :is(.df-services__head .df-carousel__nav, .df-reviews__nav .df-carousel__nav, .df-social) { --df-rv-d: 300ms; }
.df-anim :is(.df-about__media, .df-enquiry__form-wrap, .df-films__stage) { --df-rv-d: 140ms; }
.df-anim :is(.df-work__more, .df-legal__section, .df-legal__index) { --df-rv-d: 60ms; }

.df-anim .df-about__media { animation-name: df-rv-soft; }

/* Released as the group is reached, then released of the animation altogether
   so nothing is left sitting on top of the hover, expand and carousel
   transforms that own these elements from here on. */
.df-anim .is-rv-in, .df-anim .is-rv-in * { animation-play-state: running; }
.df-anim .is-rv-done, .df-anim .is-rv-done * { animation: none; }

/* The header is already in place when the page loads, so it settles rather
   than travels. */
.df-anim .df-header__bar { --df-rv-y: 14px; --df-rv-t: .6s; }
.df-anim :is(.df-legal__section, .df-enquiry__form-wrap) { --df-rv-y: 22px; }

/* Less travel where there is less room for it. */
@media (max-width: 780px) {
  .df { --df-rv-y: 18px; --df-rv-y-soft: 10px; --df-rv-t: .7s; }
}

/* ───────────────────────── Reduced motion ───────────────────────── */

@media (prefers-reduced-motion: reduce) {
  html:has(.df) { scroll-behavior: auto; }
  .df *, .df *::before, .df *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    /* Nothing may stay parked at the start of an entrance if the preference is
       switched on after the gate in the head has already run. */
    animation-play-state: running !important;
  }
  .df-glow { display: none; }
  .df-bgword { display: none; }
  .df-video-cursor { display: none; }
  .df-about--has-video .df-about__media { cursor: pointer; }
  .df-video-btn--play { opacity: 1 !important; pointer-events: auto !important; }
  .df-header__mobile-item, .df-header__mobile-foot { transition-delay: 0s !important; }
}
