.website-deck-section {
  position: relative;
  width: 100%;
  background: var(--dark-bg-color);
  padding: clamp(48px, 9vh, 120px) clamp(16px, 4vw, 56px);
  overflow: hidden;
  isolation: isolate;
}

/* Once the entrance has settled, the cards themselves never leave the
   section box — only their shadows do. Vertical overflow opens up so the
   active card's shadow fades out over the neighbouring section instead of
   slicing at the clip line; x stays clipped so end-card swells can't widen
   the page. During the scatter entrance the full clip stays on, because the
   flights start beyond the viewport and visible overflow there would stretch
   the page's scroll height mid-flight (shadows are ink overflow and never
   affect scrolling; transformed card boxes do). */
.website-deck-section[data-settled="true"] {
  overflow-x: clip;
  overflow-y: visible;
}

/* Grey dot grid behind the content (the glow itself is a shader — see
   DeckGlow). The dots are masked so they fade all the way out to the section
   edges rather than stopping in open space. */
.website-deck-section::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 65%;
  transform: translateX(-50%);
  z-index: -1;
  pointer-events: none;
  background-image: radial-gradient(
    circle,
    hsl(0 0% 86% / 0.13) 1px,
    transparent 1.7px
  );
  background-size: 22px 22px;
  background-position: center;
  -webkit-mask-image: radial-gradient(
    closest-side at 50% 50%,
    #000 0%,
    #000 18%,
    transparent 100%
  );
  mask-image: radial-gradient(
    closest-side at 50% 50%,
    #000 0%,
    #000 18%,
    transparent 100%
  );
}

.website-deck-heading {
  margin: 0 0 clamp(24px, 5vh, 56px);
  font-family: var(--font-display, "Aeonik Pro Regular"), sans-serif;
  font-size: clamp(20px, 3.2vw, 34px);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--dark-text-color);
  text-align: center;
}

.website-deck-stage {
  position: relative;
  width: 100%;
  height: clamp(420px, 58vh, 660px);
  perspective: 3200px;
  perspective-origin: 50% 44%;
  transform-style: preserve-3d;

  /* Deck geometry — tweak these to reshape the fan. --count arrives via
     inline style from PANELS.length; the min() caps keep the full fan inside
     the viewport however many cards are dealt, so cards simply overlap more
     as the deck grows instead of spilling off-screen. */
  --deck-span: calc(100vw - 2 * clamp(16px, 4vw, 56px) - var(--panel-w));
  --panel-w: clamp(150px, 16.5vw, 250px);
  --step-x: min(
    clamp(68px, 9.2vw, 148px),
    calc(var(--deck-span) / max(var(--count, 6) - 1, 1))
  );
  --step-y: min(
    clamp(10px, 1.6vw, 26px),
    calc(140px / max(var(--count, 6) - 1, 1))
  );
  --step-z: 0px;
  --rot: 48deg;
  --shift-x: clamp(0px, 2.5vw, 40px);
  --tilt: 20deg;

  /* Proximity magnification — how much a card swells at prox 1 (pointer dead
     centre), how far forward it comes (real depth, since z-index is ignored
     under preserve-3d), and how much it rises. Per-card --prox / --push are
     written raw by JS; the panel's transform transition supplies the easing. */
  --prox-grow: 0.45;
  --prox-z: 70px;
  --prox-lift: -18px;

  /* How far forward and how large the centred card ends up. Shared by the
     active transform and the pull-forward keyframes so both stay in sync
     (and so the mobile overrides below only need to touch these two vars). */
  --active-z: 240px;
  --active-scale: 2.15;
}

/* Tilted plane the cards live on — this is the "looking down" camera. */
.website-deck-deck {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(calc(var(--tilt) * -1));
  pointer-events: none;
  z-index: 2;
}

.website-deck-panel {
  position: absolute;
  top: 50%;
  left: 50%;
  pointer-events: auto;
  width: var(--panel-w);
  aspect-ratio: 16 / 10;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  overflow: hidden;
  background: hsl(0 0% 7%);
  cursor: pointer;
  transform-style: preserve-3d;
  transform: translate(-50%, -50%)
    translate3d(
      calc(
        (var(--i) - var(--mid)) * var(--step-x) + var(--shift-x, 0px) +
          var(--push, 0px)
      ),
      calc(
        (var(--i) - var(--mid)) * var(--step-y) + var(--lift, 0px) +
          var(--prox, 0) * var(--prox-lift, 0px)
      ),
      calc(var(--i) * var(--step-z) + var(--prox, 0) * var(--prox-z, 0px))
    )
    rotateY(var(--rot))
    scale(calc(1 + var(--prox, 0) * var(--prox-grow, 0)));
  box-shadow:
    0 1px 0 hsl(0 0% 100% / 0.08) inset,
    0 30px 60px -30px hsl(0 0% 0% / 0.85);
  transition:
    transform 640ms cubic-bezier(0.16, 1, 0.3, 1),
    translate 640ms cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 420ms ease,
    opacity 420ms ease,
    filter 420ms ease;
  /* No permanent will-change: it pins a fixed-resolution GPU texture, which
     gets stretched (and pixelated) when the active card scales up. It's added
     only while animating — on hover below, and via JS during the open/close
     tween — then dropped so the card re-rasterises crisp at its final size. */
}

.website-deck-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  user-select: none;
  pointer-events: none;
}

.website-deck-caption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 10px 14px;
  font-family: var(--font-body, "Aeonik Pro Regular"), sans-serif;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: hsl(0 0% 100%);
  text-align: left;
  background: linear-gradient(to top, hsl(0 0% 0% / 0.62), transparent);
  opacity: 0;
  transition: opacity 320ms ease;
}

/* Mid scatter-flight the card crosses the section's clip edge, and a blurred
   shadow slicing off against the neighbouring section reads as a glitch. No
   shadow while flying; the panel's box-shadow transition fades it back in
   when the flight lands and the attribute comes off. */
.website-deck-panel[data-flying="true"] {
  box-shadow: none;
}

/* Hover only matters while we're in deck formation. */
.website-deck-panel[data-state="deck"]:hover {
  --lift: -36px;
  will-change: transform;
  z-index: 60 !important;
  box-shadow:
    0 1px 0 hsl(0 0% 100% / 0.1) inset,
    0 46px 84px -28px hsl(0 0% 0% / 0.9);
  filter: brightness(1.06);
}

.website-deck-panel[data-state="deck"]:hover .website-deck-caption,
.website-deck-panel[data-state="active"] .website-deck-caption {
  opacity: 1;
}

.website-deck-panel:focus-visible {
  outline: 2px solid var(--dark-text-secondary, hsl(0 0% 80%));
  outline-offset: 4px;
}

/* Centralised panel: square to the viewer, pulled well forward so it clears
   the rotated neighbours in 3D (z-index is ignored under preserve-3d), and
   enlarged. */
/* The centred pose (translateZ + scale + rotateX) is driven by the GSAP
   timeline in ProjectDeck.jsx — see --active-z / --active-scale, which it
   reads for the target. Only the non-transform styling lives here. */
.website-deck-panel[data-state="active"] {
  --lift: 0px;
  /* object-fit: contain below shows the full frame uncropped at its native
     aspect ratio (supplied via inline style). */
  cursor: zoom-out;
  /* Box-shadow paints in the card's own space and is then multiplied by the
     GSAP scale, so raw lengths here would balloon with --active-scale (and
     slice at the section's clip edge). Dividing by the scale keeps the
     on-screen shadow at the designed size whatever the scale is tuned to. */
  box-shadow:
    0 calc(1px / var(--active-scale, 1)) 0 hsl(0 0% 100% / 0.12) inset,
    0 calc(64px / var(--active-scale, 1)) calc(130px / var(--active-scale, 1))
      calc(-34px / var(--active-scale, 1)) hsl(0 0% 0% / 0.92);
}

.website-deck-panel[data-state="active"] .website-deck-image {
  object-fit: contain;
}

/* The rest stay in formation but recede further back so they sit clearly
   behind the centred card. */
.website-deck-panel[data-state="dimmed"] {
  opacity: 0.32;
  filter: brightness(0.6) saturate(0.85);
  translate: 0 0 -60px;
}

.website-deck-panel[data-state="dimmed"]:hover {
  opacity: 0.62;
  filter: brightness(0.8) saturate(0.95);
}

.website-deck-backdrop {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
  cursor: zoom-out;
}

@media (max-width: 720px) {
  .website-deck-stage {
    height: clamp(340px, 48vh, 480px);
    --panel-w: clamp(130px, 38vw, 190px);
    --step-x: min(
      clamp(44px, 12vw, 84px),
      calc(var(--deck-span) / max(var(--count, 6) - 1, 1))
    );
    --step-y: min(
      clamp(8px, 2.4vw, 18px),
      calc(90px / max(var(--count, 6) - 1, 1))
    );
    --step-z: 0px;
    --rot: 46deg;
    --shift-x: clamp(10px, 5vw, 40px);
    --tilt: 16deg;
    --active-z: 170px;
    --active-scale: 1.85;
  }

  .website-deck-panel[data-state="deck"]:hover {
    --lift: -24px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .website-deck-panel {
    transition:
      opacity 200ms ease,
      filter 200ms ease;
  }

  .website-deck-panel[data-state="deck"]:hover {
    --lift: 0px;
  }
}

/* Adapt the original deck to the paper portfolio. */
.website-deck-section{container-type:inline-size;background:transparent;padding:48px 0 8px;--dark-text-color:var(--text);--dark-text-secondary:var(--secondary)}
.website-deck-section::before{display:none}
.website-deck-heading{font-family:gramercy,Georgia,serif;font-size:18px;font-weight:inherit;font-variation-settings:'wght' 450,'opsz' 22;letter-spacing:-.006em;text-align:left;margin:0 0 8px}
.website-deck-stage{height:340px;--panel-w:clamp(128px,24cqw,170px);--deck-span:calc(100cqw - var(--panel-w) * .7);--step-x:calc(var(--deck-span) / max(var(--count) - 1,1));--step-y:14px;--shift-x:1cqw;--prox-grow:.22;--active-scale:2.15}
.website-deck-panel{border-radius:3px;box-shadow:0 1px 0 #ffffff30 inset,0 24px 50px -24px #211c2566;transition:transform 350ms var(--deck-ease),translate 350ms var(--deck-ease),box-shadow 200ms ease,opacity 200ms ease,filter 200ms ease}
.website-deck-caption{font-family:diatype,Arial,sans-serif;letter-spacing:0;transition:opacity 150ms ease}
.website-deck-panel[data-state=active]{cursor:pointer;box-shadow:0 1px 0 #ffffff30 inset,0 18px 40px -12px #211c2570}
.website-deck-panel[data-state=dimmed]{filter:saturate(.65);opacity:.28}
.website-deck-panel[data-state=deck]:hover{--lift:0px;filter:none;will-change:auto;box-shadow:0 1px 0 #ffffff30 inset,0 24px 50px -24px #211c2566}
.website-deck-panel[data-state=deck]:hover .website-deck-caption{opacity:0}
.website-deck-panel:focus-visible .website-deck-caption{opacity:1}
.website-deck-panel.is-instant{transition:none}
.website-deck-close{position:absolute;top:12px;right:4px;z-index:10;border:0;background:none;color:var(--secondary);font:inherit;font-size:14px;cursor:pointer;padding:8px}
.website-deck-close[hidden]{display:none}
.home-main{max-width:var(--column);contain:inline-size}
.home .intro{max-width:var(--column)}
.home .contact{position:static;margin-top:48px;padding:0}
@media(hover:hover) and (pointer:fine){.website-deck-panel[data-state=deck]:hover{--lift:-24px;filter:brightness(1.03);box-shadow:0 1px 0 #ffffff30 inset,0 36px 60px -28px #211c2570}.website-deck-panel[data-state=deck]:hover .website-deck-caption{opacity:1}}
@media(max-width:720px){.website-deck-section{padding-top:40px}.website-deck-stage{height:300px;--active-scale:1.85;--step-y:10px;--shift-x:1cqw}.website-deck-heading{font-size:16px}.home .contact{margin-top:40px}}
@media(prefers-reduced-motion:reduce){.website-deck-panel{transition:opacity 150ms ease}.website-deck-panel[data-state=deck]:hover{--lift:0px}}

.website-deck-panel[data-state=active] .website-deck-caption{font-size:calc(13px / var(--active-scale));padding:calc(12px / var(--active-scale)) calc(16px / var(--active-scale))}

/* The resting fan stays in the reading column; selection fills the viewport. */
.website-preview{position:fixed;inset:0;margin:auto;padding:0;border:0;max-width:none;max-height:none;width:min(760px,80vw,calc((100dvh - 160px) * var(--preview-ratio,1.8)));height:fit-content;overflow:visible;background:transparent;color:var(--text)}
.website-preview::backdrop{background:transparent}
.website-preview-dimmer{position:fixed;inset:0;z-index:-1;background:#dddcd6ed;backdrop-filter:blur(3px);opacity:0}
.website-preview-header{display:flex;align-items:center;gap:20px;padding:0 0 14px;font-family:diatype,Arial,sans-serif;font-size:14px;line-height:1.4;letter-spacing:0;word-spacing:normal}
.website-preview-header h3{margin:0;flex:1;font:inherit;color:var(--secondary)}
.website-preview-visit{color:var(--secondary)}
.website-preview-close{border:0;background:none;color:var(--text);font:inherit;padding:5px 0 5px 8px;cursor:pointer}
.website-preview-frame{border-radius:5px;overflow:hidden;background:#111;aspect-ratio:var(--preview-ratio,1.8);box-shadow:0 4px 12px #211c2512,0 28px 80px -20px #211c2540}
.website-preview-frame>.website-preview-video{display:block;width:100%;height:100%;object-fit:contain}
.website-preview [hidden]{display:none}
@media(max-width:600px){.website-preview{width:min(calc(100vw - 40px),calc((100dvh - 144px) * var(--preview-ratio,1.8)))}.website-preview-header{gap:14px;font-size:13px;padding-bottom:10px}}
@media(prefers-reduced-motion:reduce){.website-preview::backdrop,.website-preview.is-closing::backdrop{animation:none}}

.website-deck-panel[data-previewing=true]{visibility:hidden}
.website-preview-frame{transform-origin:0 0}

.website-preview-video{transform-origin:50% 50%}
.website-deck-section[data-preview-restoring] .website-deck-panel[data-state=deck]:hover{--lift:0px;filter:none}
.website-deck-section[data-preview-restoring] .website-deck-panel .website-deck-caption{opacity:0}

.website-preview-frame{mask-size:100% 100%;mask-repeat:no-repeat;-webkit-mask-size:100% 100%;-webkit-mask-repeat:no-repeat}
