/* ==========================================================================
   Motion layer — entrances, hovers, scroll effects.
   Everything settles to an identity transform, so measured layout is unchanged.
   ========================================================================== */

:root {
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
}

/* --------------------------------------------------------------------------
   1. Masked line reveal for display headings
   JS splits a [data-split] heading on <br> into masked lines.
   -------------------------------------------------------------------------- */

.line {
  display: block;
  overflow: hidden;
  /* Boldonse overshoots its line box; pad the mask and pull it back so the
     clip never crops a glyph and the layout box is unchanged. */
  padding-block: 0.14em;
  margin-block: -0.14em;
}

.line__inner {
  display: block;
  transform: translateY(110%);
  transition: transform 0.9s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 90ms);
  will-change: transform;
}

.is-in .line__inner,
.line.is-in .line__inner {
  transform: translateY(0);
}

/* nowrap headings still need the mask to clip horizontally */
.t-fit .line { overflow: hidden; }

/* --------------------------------------------------------------------------
   2. Image wipe reveal
   -------------------------------------------------------------------------- */

.reveal-img {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.05s var(--ease-out);
  will-change: clip-path;
}

.reveal-img img {
  transform: scale(1.09);
  transition: transform 1.4s var(--ease-out);
}

.reveal-img.is-in {
  clip-path: inset(0 0 0 0);
}

.reveal-img.is-in img {
  transform: scale(1);
}

/* motion.css loads after enhance.css, so the hover lift is restated here
   with enough specificity to beat the reveal's resting transform */
.reveal-img.img-frame:hover img,
.img-frame.reveal-img:hover img {
  transform: scale(1.04);
}

/* --------------------------------------------------------------------------
   3. Parallax + scroll progress
   -------------------------------------------------------------------------- */

[data-parallax] {
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  [data-parallax] { transform: none !important; }
}

.progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: 60;
  background: var(--red);
  transform: scaleX(0);
  transform-origin: 0 50%;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   4. Buttons — a colour sweep from the left
   -------------------------------------------------------------------------- */

.btn-outline {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: color 0.35s var(--ease-out), border-color 0.35s var(--ease-out);
}

.btn-outline::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.45s var(--ease-out);
}

.btn-outline:hover::before,
.btn-outline:focus-visible::before {
  transform: scaleX(1);
}

.btn-outline--red::before { background: var(--red); }
.btn-outline--red:hover,
.btn-outline--red:focus-visible { color: var(--paper); background: transparent; }

.btn-outline--paper::before { background: var(--paper); }
.btn-outline--paper:hover,
.btn-outline--paper:focus-visible { color: var(--ink); background: transparent; }

/* the underlined hero CTA gets a rule that redraws from the left */
.btn-rule {
  position: relative;
  border-bottom-color: rgba(171, 188, 196, 0.35);
}

.btn-rule::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: var(--red);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.5s var(--ease-out);
}

.btn-rule:hover::after,
.btn-rule:focus-visible::after {
  transform: scaleX(1);
}

/* --------------------------------------------------------------------------
   5. Nav links — label swaps upward on hover
   -------------------------------------------------------------------------- */

.nav__link {
  overflow: hidden;
  padding-bottom: 0;
}

.nav__link .swap {
  display: block;
  position: relative;
  transition: transform 0.42s var(--ease-out);
}

.nav__link .swap::after {
  content: attr(data-label);
  position: absolute;
  top: 100%;
  left: 0;
  color: var(--blue);
}

.nav__link:hover .swap,
.nav__link:focus-visible .swap {
  transform: translateY(-100%);
}

/* --------------------------------------------------------------------------
   6. Accordion rows — an index slides in, the title steps right
   -------------------------------------------------------------------------- */

.acc {
  counter-reset: acc;
}

.acc__item {
  counter-increment: acc;
}

.acc__btn {
  position: relative;
  transition: color 0.3s var(--ease-out), transform 0.45s var(--ease-out);
}

.acc__btn::before {
  content: counter(acc, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 50%;
  transform: translate(-16px, -50%);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--red);
  opacity: 0;
  transition: opacity 0.35s var(--ease-out), transform 0.45s var(--ease-out);
  pointer-events: none;
}

.acc__item:hover .acc__btn,
.acc__item.is-open .acc__btn {
  transform: translateX(26px);
}

.acc__item:hover .acc__btn::before,
.acc__item.is-open .acc__btn::before {
  opacity: 1;
  transform: translate(-26px, -50%);
}

/* the whole button shifts, so pull the +/chevron back to keep the icon
   column aligned with the rows that aren't hovered */
.acc__icon {
  transition: transform 0.45s var(--ease-out);
}

.acc__item:hover .acc__icon,
.acc__item.is-open .acc__icon {
  transform: translateX(-26px);
}

.acc__panel > div {
  transition: opacity 0.4s var(--ease-out) 0.05s;
  opacity: 0;
}

.acc__item.is-open .acc__panel > div {
  opacity: 1;
}

/* --------------------------------------------------------------------------
   7. Gallery strip — caption rises on hover
   -------------------------------------------------------------------------- */

.p-strip__cell {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  overflow: hidden;
  transition: flex-grow 0.75s var(--ease-out);
}

.p-strip__cell img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(0.35) brightness(0.86);
  transition: filter 0.55s ease, transform 1.1s var(--ease-out);
}

.p-strip:hover .p-strip__cell img { filter: grayscale(0.65) brightness(0.55); }

.p-strip__cell:hover { flex-grow: 2.1; }

.p-strip__cell:hover img {
  filter: none;
  transform: scale(1.06);
}

.p-strip__cap {
  position: absolute;
  left: 16px;
  bottom: 14px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--paper);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.4s var(--ease-out), transform 0.4s var(--ease-out);
  pointer-events: none;
}

.p-strip__cell:hover .p-strip__cap {
  opacity: 1;
  transform: none;
}

/* --------------------------------------------------------------------------
   8. Cursor spotlight over hero imagery — the brand is a lighting studio
   -------------------------------------------------------------------------- */

.p-hero__bg::before,
.sec__bg--spot::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
  background: radial-gradient(
    240px circle at var(--mx, 50%) var(--my, 50%),
    rgba(240, 240, 240, 0.16),
    rgba(240, 240, 240, 0) 68%
  );
}

.p-hero:hover .p-hero__bg::before,
.sec__bg--spot.is-lit::before {
  opacity: 1;
}

/* --------------------------------------------------------------------------
   9. Stat cards — rule draws across on hover
   -------------------------------------------------------------------------- */

.p-stat {
  position: relative;
  transition: color 0.3s ease;
}

.p-stat::after {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 18px;
  height: 1px;
  background: var(--red);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.55s var(--ease-out);
}

.p-stat:hover::after { transform: scaleX(1); }
.p-stat:hover .p-stat__value { color: var(--blue); }
.p-stat__value { transition: color 0.3s ease; }

/* --------------------------------------------------------------------------
   10. Menu rows — the name steps right, price turns red
   -------------------------------------------------------------------------- */

.p-menu__row { transition: border-color 0.3s ease; }
.p-menu__name,
.p-menu__price { transition: transform 0.45s var(--ease-out), color 0.3s ease; }
.p-menu__row:hover .p-menu__name { transform: translateX(12px); }
.p-menu__row:hover .p-menu__price { color: var(--red); }

/* --------------------------------------------------------------------------
   11. Footer + form focus detail
   -------------------------------------------------------------------------- */

.foot__mail a,
.p-visit__hours a {
  background-image: linear-gradient(var(--red), var(--red));
  background-size: 0% 1px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  transition: background-size 0.45s var(--ease-out);
}

.foot__mail a:hover,
.p-visit__hours a:hover { background-size: 100% 1px; }

/* --------------------------------------------------------------------------
   12. Page transition wipe
   -------------------------------------------------------------------------- */

.wipe {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--ink);
  transform: scaleY(0);
  transform-origin: 50% 100%;
  pointer-events: none;
}

.wipe::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: var(--red);
}

body.is-entering .wipe {
  transform: scaleY(1);
  animation: wipe-out 0.62s var(--ease-in-out) forwards;
}

body.is-leaving .wipe {
  transform-origin: 50% 0;
  animation: wipe-in 0.45s var(--ease-in-out) forwards;
}

@keyframes wipe-in  { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes wipe-out { from { transform: scaleY(1); } to { transform: scaleY(0); } }

/* --------------------------------------------------------------------------
   Reduced motion — everything resolves instantly to its resting state
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .line__inner { transform: none; }
  .reveal-img { clip-path: none; }
  .reveal-img img { transform: none; }
  .wipe { display: none; }
  .p-hero__bg::before,
  .sec__bg--spot::before { display: none; }
  .acc__item:hover .acc__btn,
  .acc__item.is-open .acc__btn { transform: none; }
  .acc__panel > div { opacity: 1; }
}

/* ==========================================================================
   Hero choreography
   Entry is clip-path only — never transform — because the parallax/float loop
   owns `transform` on these elements and an inline transform would win.
   ========================================================================== */

/* ---- word-level reveal for display type -------------------------------- */

.word {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  /* clear Boldonse's overshoot so the mask never crops a glyph */
  padding-block: 0.14em;
  margin-block: -0.14em;
}

.word__inner {
  display: inline-block;
  transform: translateY(108%);
  transition: transform 1s var(--ease-out);
  transition-delay: calc(var(--w, 0) * 85ms);
  will-change: transform;
}

.is-in .word__inner {
  transform: translateY(0);
}

/* ---- collage plates: directional wipes, staggered ---------------------- */

.hero-plate {
  transition: clip-path 1.15s var(--ease-out);
  transition-delay: calc(var(--p, 0) * 130ms);
  will-change: clip-path;
}

.hero-plate--left   { clip-path: inset(0 100% 0 0); }
.hero-plate--right  { clip-path: inset(0 0 0 100%); }
.hero-plate--bottom { clip-path: inset(100% 0 0 0); }
.hero-plate--top    { clip-path: inset(0 0 100% 0); }

.hero-plate.is-in { clip-path: inset(0 0 0 0); }

/* ---- hairline that draws across behind the type ------------------------ */

/* must out-rank `.sec > *:not(.sec__bg)` (0,2,0) from the layout sheet —
   otherwise this stays `relative`, becomes a real grid item and spills into an
   implicit 25th column, squeezing every track in the section. */
.sec > .hero-rule,
.p-sec > .hero-rule,
.hero-rule {
  position: absolute;
  left: var(--pad);
  right: var(--pad);
  height: 1px;
  background: var(--red);
  opacity: 0.32;
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 1.3s var(--ease-out) 0.35s;
  pointer-events: none;
  z-index: 0;
}

.hero-rule.is-in { transform: scaleX(1); }

/* ---- scroll cue: a slow bob -------------------------------------------- */

.cue-bob {
  animation: cue-bob 2.4s var(--ease-in-out) infinite;
}

@keyframes cue-bob {
  0%, 100% { transform: translateY(0); opacity: 0.75; }
  50%      { transform: translateY(6px); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .word__inner { transform: none; }
  .hero-plate  { clip-path: none; }
  .hero-rule   { transform: scaleX(1); }
  .cue-bob     { animation: none; }
}

/* ==========================================================================
   Chromatic focus — the wordmark resolves like a lens pulling focus.
   Red and blue ghost layers sit behind the type, offset by --cx. They start
   split, converge on entry, and separate again as the hero leaves.
   Thematically right for a lighting studio: a mis-registered print snapping in.
   ========================================================================== */

.chroma {
  position: relative;
  --cx: 14px;
}

.chroma::before,
.chroma::after {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  z-index: 0;
  line-height: inherit;
  letter-spacing: inherit;
  text-align: inherit;
  pointer-events: none;
  mix-blend-mode: screen;
  opacity: 0.5;
  transition: transform 0.25s linear;
  white-space: inherit;
}

.chroma::before {
  color: var(--red);
  transform: translate3d(calc(var(--cx) * -1), 0, 0);
}

.chroma::after {
  color: var(--blue);
  transform: translate3d(var(--cx), 0, 0);
}

/* the real type paints above both ghosts */
.chroma .line,
.chroma .word,
.chroma .char {
  position: relative;
  z-index: 1;
}

/* ---- per-character stagger --------------------------------------------- */

.char {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding-block: 0.14em;
  margin-block: -0.14em;
}

.char__inner {
  display: inline-block;
  transform: translateY(108%);
  transition: transform 0.85s var(--ease-out);
  transition-delay: calc(var(--c, 0) * 45ms);
  will-change: transform;
}

.is-in .char__inner {
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .chroma { --cx: 0px; }
  .chroma::before,
  .chroma::after { display: none; }
  .char__inner { transform: none; }
}

/* ==========================================================================
   Cursor — a viewfinder reticle. Focus brackets that snap around whatever you
   point at, with a red centre dot. Reads as a camera focus point, which is the
   business these rooms are in.
   Only for fine pointers; reduced motion falls back to the native cursor.
   ========================================================================== */

.cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 300;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s ease;
}

.cursor.is-active { opacity: 1; }

/* the brackets: difference blending keeps them legible on black rooms and
   blown-out studio windows alike */
.cursor__box {
  position: absolute;
  left: 0;
  top: 0;
  width: 40px;
  height: 40px;
  margin: -20px 0 0 -20px;
  mix-blend-mode: difference;
  transition: width 0.32s var(--ease-out), height 0.32s var(--ease-out),
              margin 0.32s var(--ease-out), opacity 0.25s ease;
}

.cursor__c {
  position: absolute;
  width: 13px;
  height: 13px;
  border: 2px solid #fff;
}

.cursor__c--tl { top: 0; left: 0; border-right: 0; border-bottom: 0; }
.cursor__c--tr { top: 0; right: 0; border-left: 0; border-bottom: 0; }
.cursor__c--bl { bottom: 0; left: 0; border-right: 0; border-top: 0; }
.cursor__c--br { bottom: 0; right: 0; border-left: 0; border-top: 0; }

.cursor__dot {
  position: absolute;
  left: 0;
  top: 0;
  width: 9px;
  height: 9px;
  margin: -4.5px 0 0 -4.5px;
  background: var(--red);
  border-radius: 50%;
  /* white ring + dark halo so the dot holds up on black rooms and on
     blown-out studio windows alike */
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.95), 0 0 10px 2px rgba(14, 13, 12, 0.7);
  /* position comes from JS each frame, so `transform` must stay untransitioned
     or the dot drifts behind the pointer; `scale` animates on its own */
  transition: scale 0.25s var(--ease-out), opacity 0.2s ease;
}

.cursor__label {
  position: absolute;
  left: 0;
  top: 0;
  transform: translate(26px, 12px);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--paper);
  text-shadow: 0 0 8px rgba(14, 13, 12, 0.95);
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.22s ease;
}

/* over something interactive: the reticle opens up and locks on */
.cursor.is-locked .cursor__box {
  width: 68px;
  height: 68px;
  margin: -34px 0 0 -34px;
}

.cursor.is-locked .cursor__dot { scale: 0; }
.cursor.is-locked .cursor__label { opacity: 1; }

.cursor.is-down .cursor__box {
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;
}

/* over text being edited, get out of the way */
.cursor.is-text .cursor__box,
.cursor.is-text .cursor__label { opacity: 0; }

body.has-reticle,
body.has-reticle a,
body.has-reticle button,
body.has-reticle .p-strip__cell {
  cursor: none;
}

/* text entry keeps the real caret */
body.has-reticle input,
body.has-reticle textarea,
body.has-reticle select {
  cursor: auto;
}

@media (prefers-reduced-motion: reduce), (hover: none), (pointer: coarse) {
  .cursor { display: none; }
  body.has-reticle,
  body.has-reticle a,
  body.has-reticle button,
  body.has-reticle .p-strip__cell { cursor: auto; }
}

/* ==========================================================================
   Manifesto legibility
   The statement is set over a blurred photo whose luminance runs 13–200, so
   the white type dropped to ~1.2:1 against the blown-out areas. A soft scrim
   sits behind the text only, keeping the image bright at its edges.
   ========================================================================== */

.h-manifesto__img-main {
  filter: brightness(0.82) contrast(1.04);
}

.h-manifesto__text {
  position: relative;
  isolation: isolate;
}

.h-manifesto__text::before {
  content: "";
  position: absolute;
  inset: -92px -110px;
  z-index: -1;
  pointer-events: none;
  /* `closest-side` so the gradient reaches full transparency exactly at the
     box edges — the default (farthest-corner) is still opaque where it meets
     the top and bottom, which shows up as a hard seam across the photo. */
  background: radial-gradient(
    ellipse closest-side at center,
    rgba(14, 13, 12, 0.9) 0%,
    rgba(14, 13, 12, 0.78) 38%,
    rgba(14, 13, 12, 0.42) 66%,
    rgba(14, 13, 12, 0.12) 85%,
    rgba(14, 13, 12, 0) 100%
  );
}


/* ==========================================================================
   Remaining contrast fixes, found by auditing every text-over-image overlay
   rather than only the spot that was reported.
   Measured worst-case (95th-percentile backdrop) before: 2.0:1 and 2.1:1.
   ========================================================================== */

/* STUDIOS crosses the brightest part of the eye plate. A shadow lifts it
   without darkening the collage; the chroma ghosts opt out so the colour
   fringing stays clean. */
.h-hero__title2 {
  text-shadow:
    0 0 26px rgba(14, 13, 12, 0.95),
    0 0 58px rgba(14, 13, 12, 0.8),
    0 2px 6px rgba(14, 13, 12, 0.7);
}

.chroma::before,
.chroma::after {
  text-shadow: none;
}

/* The about copy sits over the blown-out shoulder of the backdrop photo.
   Darken only the column the text occupies and leave the heading side bright. */
.s-about .sec__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    rgba(14, 13, 12, 0) 40%,
    rgba(14, 13, 12, 0.5) 62%,
    rgba(14, 13, 12, 0.72) 100%
  );
}

/* ==========================================================================
   Mobile
   ========================================================================== */

@media (max-width: 767px) {
  /* The scrim's -110px horizontal inset runs past a 390px viewport. */
  .h-manifesto__text::before { inset: -40px -24px; }

  /* The open accordion's index-shift pushed its row 26px right, past the
     viewport edge. There is no hover on touch, so drop the shift entirely. */
  .acc__item:hover .acc__btn,
  .acc__item.is-open .acc__btn,
  .acc__item:hover .acc__icon,
  .acc__item.is-open .acc__icon {
    transform: none;
  }

  .acc__btn::before { display: none; }

  /* comfortable touch targets (44px minimum) */
  .nav__link {
    display: flex;
    align-items: center;
    min-height: 48px;
    padding-inline: 8px;
  }

  .nav__toggle {
    min-width: 48px;
    justify-content: flex-end;
  }

  .btn-outline {
    min-height: 46px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-inline: 24px;
  }

  .btn-rule {
    min-height: 46px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .foot__mail a,
  .p-visit__hours a {
    display: inline-flex;
    align-items: center;
    min-height: 48px;
    padding-block: 12px;
  }

  /* the marquee is decorative and its own overflow source; clip it hard */
  .marquee { max-width: 100vw; overflow: hidden; }

  /* the reticle is pointer-only — make sure nothing reserves space for it */
  .cursor { display: none; }
}

/* Safari paints a start-playback button over a background video it refuses to
   autoplay. The poster is the intended fallback, not a control the visitor is
   meant to press, so suppress the affordance on decorative video only. */
.bg-video::-webkit-media-controls,
.bg-video::-webkit-media-controls-start-playback-button,
.bg-video::-webkit-media-controls-panel,
.bg-video::-webkit-media-controls-overlay-play-button {
  display: none !important;
  -webkit-appearance: none;
  opacity: 0;
}

.bg-video {
  pointer-events: none;
}

/* The spaces accordion sits on the right, where the video's light panel
   blows out. Darken that side only; the red title on the left stays vivid. */
@media (min-width: 768px) {
  .h-spaces .sec__bg::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(90deg, rgba(14,13,12,0) 38%, rgba(14,13,12,0.5) 62%, rgba(14,13,12,0.62) 100%);
  }
}

/* Fallback play control — only shown when the browser refuses to autoplay. */
.sec > .video-play {
  position: absolute;
  grid-column: 1 / -1;
  grid-row: 1;
  justify-self: end;
  align-self: end;
  right: var(--pad);
  bottom: 28px;
  z-index: 5;
  display: none;
  align-items: center;
  gap: 12px;
  min-height: 46px;
  padding: 0 20px 0 14px;
  border: 1px solid rgba(240, 240, 240, 0.55);
  border-radius: 999px;
  background: rgba(14, 13, 12, 0.72);
  color: var(--paper);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: border-color 0.25s ease, background-color 0.25s ease;
}

.video-blocked > .video-play { display: inline-flex; }

.sec > .video-play:hover,
.sec > .video-play:focus-visible {
  border-color: var(--red);
  background: rgba(187, 17, 34, 0.85);
}

.video-play__icon {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 6px 0 6px 10px;
  border-color: transparent transparent transparent currentColor;
}

@media (max-width: 767px) {
  .sec > .video-play {
    right: auto;
    left: 50%;
    bottom: 22px;
    justify-self: auto;
    transform: translateX(-50%);
  }
}

/* WebKit paints its own start-playback triangle over a refused video, and its
   modern controls live in a shadow root the ::-webkit-media-controls selectors
   no longer reach. So when autoplay is refused, hide the element itself and
   let the poster — set as the layer's background — carry the section. The
   branded "Play reel" control is then the only affordance. */
.h-spaces .sec__bg {
  background: #0e0d0c url("../video/spaces-poster.jpg") center / cover no-repeat;
}

.video-blocked .bg-video {
  opacity: 0;
}

.bg-video {
  transition: opacity 0.5s ease;
}
