/* Gate opener: soft hinge open, gentle walk-in */

.opener-gate {
  --gate-focus-x: 50%;
  --gate-focus-y: 44%;
  --gate-swing: 70deg;
  position: relative;
  overflow: hidden;
  border-radius: 14px;
  background: #0a0705;
}

.gate-scene {
  position: absolute;
  inset: 0;
  transform-origin: var(--gate-focus-x) var(--gate-focus-y);
  /* Flat on purpose: with preserve-3d the scene depth-sorts the rotated door
     leaves against the facade and drops the right one entirely. */
  transform-style: flat;
  transform: scale(1);
  will-change: transform;
}

.envelope-pack.is-opening .gate-scene {
  /* One continuous zoom — later class changes must not restart this */
  animation: gateZoomIn 6.6s cubic-bezier(0.4, 0, 0.55, 1) forwards;
}

@keyframes gateZoomIn {
  from { transform: scale(1); }
  to { transform: scale(2.05); }
}

.gate-beyond {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  pointer-events: none;
  user-select: none;
  z-index: 0;
}

/* Depth vignette only — the interior photo behind must stay readable */
.gate-inner {
  position: absolute;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(
      ellipse 70% 74% at 50% 44%,
      rgba(20, 12, 8, 0) 0%,
      rgba(12, 8, 5, 0.28) 62%,
      rgba(7, 5, 4, 0.62) 100%
    );
}

.gate-plate {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  pointer-events: none;
  user-select: none;
  z-index: 2;
}

.envelope-pack.is-opening .has-gate-arch .gate-plate,
.envelope-pack.is-open .has-gate-arch .gate-plate {
  -webkit-mask-image: var(--gate-plate-mask);
  mask-image: var(--gate-plate-mask);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-mode: alpha;
  mask-mode: alpha;
}

.envelope-pack.is-opening .has-gate-flat .gate-plate,
.envelope-pack.is-open .has-gate-flat .gate-plate {
  -webkit-mask-image:
    linear-gradient(#000, #000),
    linear-gradient(#000, #000),
    linear-gradient(#000, #000),
    linear-gradient(#000, #000);
  mask-image:
    linear-gradient(#000, #000),
    linear-gradient(#000, #000),
    linear-gradient(#000, #000),
    linear-gradient(#000, #000);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: left top, left bottom, left top, right top;
  mask-position: left top, left bottom, left top, right top;
  -webkit-mask-size:
    100% var(--cut-t, 0px),
    100% var(--cut-b, 0px),
    var(--cut-l, 0px) 100%,
    var(--cut-r, 0px) 100%;
  mask-size:
    100% var(--cut-t, 0px),
    100% var(--cut-b, 0px),
    var(--cut-l, 0px) 100%,
    var(--cut-r, 0px) 100%;
  -webkit-mask-composite: source-over;
  mask-composite: add;
}

/* Below the plate: leaves swinging inwards get clipped by the facade,
   showing only through the punched-out doorway. */
.gate-stage {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  perspective: 1100px;
  perspective-origin: var(--gate-focus-x) var(--gate-focus-y);
  transform-style: preserve-3d;
}

.gate-door {
  position: absolute;
  overflow: visible;
  transform-style: preserve-3d;
  opacity: 0;
  filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.28));
  transition:
    transform 0.55s cubic-bezier(0.33, 0.1, 0.25, 1),
    filter 0.55s ease;
  will-change: transform;
}

/* The leaves must swap in during the same frame the facade is masked open,
   otherwise the interior shines through them for a frame and it reads as a cut. */

.envelope-pack.is-opening .gate-door,
.envelope-pack.is-open .gate-door {
  opacity: 1;
}

.gate-door-l {
  transform-origin: left center;
}

.gate-door-r {
  transform-origin: right center;
  transition-delay: 0.05s;
}

.gate-leaf {
  position: absolute;
  inset: 0;
}

.gate-leaf-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: fill;
  display: block;
  pointer-events: none;
  user-select: none;
  backface-visibility: hidden;
}

/* Positive on the left leaf / negative on the right pushes the free edge
   away from the viewer, so both leaves open inwards into the room. */
.envelope-pack.is-opening:not(.is-open) .gate-door-l {
  transform: rotateY(6deg);
}

.envelope-pack.is-opening:not(.is-open) .gate-door-r {
  transform: rotateY(-6deg);
}

.envelope-pack.is-open .gate-door {
  transition:
    transform 2.35s cubic-bezier(0.22, 0.61, 0.18, 1),
    filter 2s ease;
}

.envelope-pack.is-open .gate-door-l {
  transform: rotateY(var(--gate-swing));
  filter:
    brightness(0.62)
    drop-shadow(6px 10px 22px rgba(0, 0, 0, 0.4));
}

.envelope-pack.is-open .gate-door-r {
  transform: rotateY(calc(-1 * var(--gate-swing)));
  filter:
    brightness(0.62)
    drop-shadow(-6px 10px 22px rgba(0, 0, 0, 0.4));
}

.gate-glow {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: soft-light;
  background:
    radial-gradient(
      ellipse 28% 34% at var(--gate-focus-x) var(--gate-focus-y),
      rgba(255, 220, 170, 0.35) 0%,
      transparent 70%
    );
  transition: opacity 1.6s ease;
}

.envelope-pack.is-opening .gate-glow {
  opacity: 0.2;
}

.envelope-pack.is-open .gate-glow {
  opacity: 0.38;
}

/* Doors and facade stay on screen for the whole walk-in; the zoom carries
   them out of frame instead of fading them away. */

.gate-veil {
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  opacity: 0;
  background:
    radial-gradient(
      ellipse 42% 38% at var(--gate-focus-x) var(--gate-focus-y),
      rgba(10, 7, 5, 0),
      rgba(6, 4, 3, 0.35) 58%,
      #0a0705 100%
    );
  transition: opacity 2.2s ease;
}

.envelope-pack.is-entering .gate-veil {
  opacity: 0.6;
}

.envelope-overlay.is-revealing .gate-veil {
  opacity: 1;
  background: #0a0705;
  transition: opacity 0.7s ease, background 0.7s ease;
}

/* Sits outside .gate-scene so the walk-in zoom never scales or crops it */
.opener-gate .gate-card {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 7;
  width: min(72%, 220px);
  max-height: 76%;
  opacity: 0;
  transform: translate(-50%, -46%) scale(0.92);
  pointer-events: none;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.28);
  transition:
    opacity 0.8s ease 0.25s,
    transform 0.95s cubic-bezier(0.22, 0.7, 0.2, 1) 0.25s;
}

.envelope-pack.is-drawn .opener-gate .gate-card {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

.envelope-overlay.is-kind-gate .opener-gate .gate-card {
  display: none;
}

.envelope-overlay.is-kind-gate {
  justify-content: space-between;
  background: #0a0705;
  padding: 0;
}

.envelope-overlay.is-kind-gate .envelope-hint,
.envelope-overlay.is-kind-gate .envelope-skip {
  position: relative;
  z-index: 8;
  transition: opacity 0.45s ease;
}

.envelope-overlay.is-kind-gate.is-opening .envelope-hint,
.envelope-overlay.is-kind-gate.is-opening .envelope-skip,
.envelope-overlay.is-kind-gate.is-revealing .envelope-hint,
.envelope-overlay.is-kind-gate.is-revealing .envelope-skip {
  opacity: 0;
  animation: none;
}

.envelope-overlay.is-kind-gate .envelope-hint {
  margin-top: max(28px, env(safe-area-inset-top, 0px) + 16px);
  color: #f2e6d0;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.55);
}

.envelope-overlay.is-kind-gate .envelope-skip {
  margin-bottom: max(24px, env(safe-area-inset-bottom, 0px) + 12px);
  color: rgba(242, 230, 208, 0.8);
}

.envelope-overlay.is-kind-gate .envelope-pack {
  position: absolute;
  inset: 0;
  width: auto;
  height: auto;
  padding: 0;
  display: block;
  pointer-events: auto;
}

.envelope-overlay.is-kind-gate .opener-gate {
  position: absolute;
  inset: 0;
  width: auto;
  height: auto;
  border-radius: 0;
  overflow: hidden;
  --gate-swing: 72deg;
}

.envelope-overlay.is-revealing.is-kind-gate .opener-gate,
.envelope-pack.is-revealed .opener-gate {
  transform: scale(1);
  opacity: 0;
  filter: blur(8px);
  transition:
    opacity 0.9s ease,
    filter 0.9s ease;
}

/* Cross-fade into the invitation instead of holding on a black screen */
.envelope-overlay.is-kind-gate.is-revealing {
  background: #0a0705;
  transition: opacity 1.1s ease, visibility 1.1s ease;
}

.is-style-gate {
  --env-paper: #8b5a2b;
  --env-paper-2: #5a3418;
  --env-ink: #f2e6d0;
  --env-lining: #3d2412;
  --env-scene: #1a1612;
}

.envelope-colors.is-gate-styles .env-swatch:not(.is-gate-style) {
  display: none;
}

.envelope-colors.is-gate-styles .env-swatch-chip {
  width: 44px;
  height: 44px;
  box-shadow: 0 0 0 1px #c4b5a0;
  background-size: cover;
  background-position: center;
}

.envelope-colors.is-gate-styles .env-swatch:has(input:checked) .env-swatch-chip {
  box-shadow: 0 0 0 2px var(--accent);
}

.env-swatch.is-gate-style .env-swatch-chip {
  box-shadow: 0 0 0 1px #c4b5a0, inset 0 0 0 7px rgba(0, 0, 0, 0.12);
}

/* Smooth invitation entrance after walking through the gate.
   Only an entrance animation — never hide the page up front, so the
   invitation stays readable even if the opener script never runs. */
body.page-invite.invite-from-opener .hero-invite {
  animation: gateInviteIn 1.3s cubic-bezier(0.22, 0.6, 0.2, 1) both;
}

@keyframes gateInviteIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .envelope-pack.is-opening .gate-scene {
    animation: none;
    transform: scale(1.35);
  }

  body.page-invite.invite-from-opener .hero-invite {
    animation: none;
    opacity: 1;
    transform: none;
    filter: none;
  }
}
