/* =========================================================================
   DreamPack Studio — the room you land in
   -------------------------------------------------------------------------
   The first screen is a design studio photographed at eye level, and the
   pointer looks around it. Not a parallax slide: a small translation plus a
   small perspective tilt, so the walls shear against each other the way they
   would if you leaned. The amount is deliberately tiny — enough to feel
   alive, never enough to notice as an effect.

   Objects in the room light up when you point at them, and each one is a
   link to the section of the page that explains it. A hotspot that only
   glows is decoration; one that takes you somewhere is the room working as
   navigation.
   ========================================================================= */

/* --px / --py are the eased pointer, -1 → 1 from the centre of the viewport.
   site.js writes them on .hero. They default to 0 so the room sits square
   before the pointer has moved, on touch, and under reduced motion. */
.hero{--px:0;--py:0;}

/* The lens needs depth to tilt into. Set on the parent, so both layers
   inside share one projection and cannot drift apart. */
.hero__scene{perspective:1600px;perspective-origin:50% 45%;}

/* The zoom is anchored on the dress form, not on the middle of the picture —
   the mannequin sits at about 50% across and 40% down, and pushing in on the
   frame's centre instead would drift off the one object the next section is
   about to pick up. */
.lens{
  position:absolute;
  /* Overscan, and it is deliberately LOPSIDED.

     The room needs margin to travel into or the edge of the render walks
     into frame when it pans. An even -7% inset gave it that and cost the
     ceiling: the render is 21:9 inside a ~16:9 hero, so it fits by height
     with nothing to spare, and everything the overscan pushed past the top
     was simply clipped. The pendant bulbs sit in the top 7-13% of the frame
     and ~10% was being cut — the lights that light the room were the one
     thing you could not see.

     So the travel room is taken from the BOTTOM, where the floor is and
     nobody is looking, and the top keeps just enough to cover the upward
     pan. Vertical travel is halved for the same reason; the effect reads
     mostly horizontally anyway. */
  inset:-3% -8% -11% -8%;
  transform-origin:50% 40%;
  transform:
    rotateY(calc(var(--px) * 1.6deg))
    rotateX(calc(var(--py) * -1.1deg))
    translate3d(calc(var(--px) * -22px),calc(var(--py) * -10px),0)
    scale(calc(1.045 + var(--exit,0) * .62));
  will-change:transform;
}
.lens img{width:100%;height:100%;object-fit:cover;object-position:center 46%;}

/* =========================================================================
   The handoff
   -------------------------------------------------------------------------
   The room does not simply scroll away. As you leave it, the camera pushes
   in on the shirt on the dress form until that shirt is most of the frame —
   and the section underneath opens on a shirt of exactly the same kind, made
   of code, in the same place. The scroll reads as one garment carrying
   through rather than two sections meeting.

   The room dims as it pushes in, so the two are briefly the same picture at
   different brightnesses and the swap has nowhere to show a seam. The
   hotspots go first and fastest: a label you can no longer reach must not
   still be inviting you to try.
   ========================================================================= */
.lens{opacity:calc(1 - var(--exit,0) * .92);}
.lens--spots{opacity:calc(1 - var(--exit,0) * 3);}

/* An invisible link still takes clicks, so the fade alone would leave three
   dead targets floating over the top of the page. `is-leaving` is set by
   site.js from the same number that drives the fade. */
.hero.is-leaving .lens--spots{pointer-events:none;}

/* The hotspot layer rides the same transform and sits above the scrim, so
   the objects stay pointable through it. */
.lens--spots{z-index:2;}

/* =========================================================================
   Hotspots
   ========================================================================= */
/* The hotspot is a real, sized circle centred on its object — NOT a 0×0
   point with a pseudo-element for a hit area, which is what it was first.
   A zero-area link is dropped from the accessibility tree entirely: all
   three were missing from it, so the room was mouse-only and no keyboard or
   screen reader could reach a single one of them. The size comes from --r,
   which studio.js scales with the render, so the target tracks the object
   rather than being a fixed blob that fits at one window size. */
.spot{
  position:absolute;                     /* placed in px by studio.js */
  display:block;
  width:calc(var(--r) * 1px);height:calc(var(--r) * 1px);
  margin:calc(var(--r) * -.5px) 0 0 calc(var(--r) * -.5px);
  border-radius:50%;
  z-index:1;
}
.spot:hover,.spot:focus-visible{z-index:3;}

/* The light. A soft pool over the object that fades up on hover — which is
   what makes a flat photograph read as an object being lit rather than an
   overlay being switched on. Screen blend so it brightens what is under it
   instead of painting over it. */
.spot__glow{
  position:absolute;top:50%;left:50%;
  width:calc(var(--r) * 2px);height:calc(var(--r) * 2px);
  margin:calc(var(--r) * -1px) 0 0 calc(var(--r) * -1px);
  border-radius:50%;
  background:radial-gradient(circle,rgba(255,175,140,.5),rgba(255,120,90,.16) 45%,transparent 70%);
  mix-blend-mode:screen;
  opacity:0;transform:scale(.86);
  transition:opacity .45s var(--ease),transform .55s var(--ease);
  pointer-events:none;
}

/* The ring is the affordance: it says "this one is pointable" before you
   point at it. Faint at rest, vermilion once you are on it. */
.spot__ring{
  position:absolute;top:50%;left:50%;
  width:11px;height:11px;margin:-5.5px 0 0 -5.5px;
  border-radius:50%;
  border:1px solid rgba(226,238,248,.5);
  background:rgba(7,11,16,.34);
  backdrop-filter:blur(3px);
  transition:transform .4s var(--ease),border-color .4s,background .4s;
}
.spot__ring::after{
  content:"";position:absolute;inset:3px;border-radius:50%;
  background:var(--ink);opacity:.85;
  transition:background .4s;
}
/* A slow pulse, so a still page still says the room is interactive. */
.spot::before{
  content:"";position:absolute;top:50%;left:50%;
  width:11px;height:11px;margin:-5.5px 0 0 -5.5px;border-radius:50%;
  border:1px solid var(--red);
  animation:spotPulse 3.4s var(--ease) infinite;
  pointer-events:none;
}
@keyframes spotPulse{
  0%   {transform:scale(1);opacity:.55;}
  70%  {transform:scale(3.1);opacity:0;}
  100% {transform:scale(3.1);opacity:0;}
}

/* The hit area. Bigger than the dot, sized to the object, because asking
   someone to hit an 11px target to discover the room is asking them not to. */
.spot::after{
  content:"";position:absolute;top:50%;left:50%;
  width:calc(var(--r) * 1.7px);height:calc(var(--r) * 1.7px);
  margin:calc(var(--r) * -.85px) 0 0 calc(var(--r) * -.85px);
  border-radius:50%;
}

.spot:hover .spot__glow,
.spot:focus-visible .spot__glow{opacity:1;transform:scale(1);}

.spot:hover .spot__ring,
.spot:focus-visible .spot__ring{
  transform:scale(1.5);
  border-color:var(--red);
  background:rgba(214,59,47,.16);
}
.spot:hover .spot__ring::after,
.spot:focus-visible .spot__ring::after{background:var(--red);}

/* The label. Rises from under the dot rather than appearing beside it, so
   two hotspots near each other never argue about which side to open on. */
.spot__tag{
  position:absolute;top:calc(50% + 18px);left:50%;
  transform:translate(-50%,6px);
  width:max-content;max-width:230px;
  padding:11px 15px 12px;
  border:1px solid var(--line);
  border-radius:var(--r);
  background:rgba(9,14,20,.82);
  backdrop-filter:blur(14px) saturate(120%);
  box-shadow:0 18px 40px -18px rgba(0,0,0,.9);
  font-size:12.5px;line-height:1.45;color:var(--ink-soft);
  opacity:0;pointer-events:none;
  transition:opacity .34s var(--ease),transform .34s var(--ease);
}
.spot__tag b{
  display:block;margin-bottom:3px;
  font-family:var(--display);font-weight:700;font-size:14.5px;
  letter-spacing:-.012em;color:var(--ink);
  font-variation-settings:"wdth" 96;
}
.spot:hover .spot__tag,
.spot:focus-visible .spot__tag{opacity:1;transform:translate(-50%,0);}

/* Edge-anchored variants, set by studio.js when a centred tag would run off
   the window. The transform has to be respecified for both states or the
   hover rule above snaps it back to centred. */
.spot.is-rightward .spot__tag{left:0;transform:translate(-14px,6px);}
.spot.is-rightward:hover .spot__tag,
.spot.is-rightward:focus-visible .spot__tag{transform:translate(-14px,0);}

.spot.is-leftward .spot__tag{left:auto;right:0;transform:translate(14px,6px);}
.spot.is-leftward:hover .spot__tag,
.spot.is-leftward:focus-visible .spot__tag{transform:translate(14px,0);}

.spot:focus-visible .spot__ring{outline:2px solid var(--red);outline-offset:4px;}

/* =========================================================================
   Where the room does not apply
   -------------------------------------------------------------------------
   No hover on a touch screen, so a hotspot there is a dot that does nothing
   but sit on top of the picture. And the room is cover-fitted: on a narrow
   viewport most of its width is cropped away and two of the three objects
   are no longer on screen to point at. Both reasons say the same thing.
   ========================================================================= */
@media (max-width:860px),(pointer:coarse){
  .lens--spots{display:none;}
}

@media (prefers-reduced-motion:reduce){
  .lens{transform:none;}
  .spot::before{animation:none;}
  .spot__glow,.spot__tag{transition:none;}
}
