/* Sphere home: images on a slowly rotating sphere, CSS 3D only.
   The focal rail becomes the camera lens: perspective, zoom and depth of field. */

@property --p { syntax: "<length>"; inherits: true; initial-value: 1200px; }
@property --s { syntax: "<number>"; inherits: true; initial-value: 1; }

body.home { overflow: hidden; height: 100dvh; }
body.home main { zoom: 1; max-width: none; padding: 0; height: calc(100dvh - var(--hdr)); position: relative; }
body.home .ftr { display: none; }
body.home .hdr, body.home .focal { transition: opacity .8s; }
body.home.loading .hdr, body.home.loading .focal { opacity: 0; pointer-events: none; }

/* lens presets: --p perspective, --s sphere scale, --dof blur strength (read by JS) */
body.home { --p: 1200px; --s: 1; --dof: .6; }
:root[data-focal="14"]  body.home { --p: 550px;  --s: .72; --dof: 0; }
:root[data-focal="24"]  body.home { --p: 750px;  --s: .84; --dof: .35; }
:root[data-focal="35"]  body.home { --p: 950px;  --s: .93; --dof: .65; }
:root[data-focal="85"]  body.home { --p: 1700px; --s: 1.22; --dof: 1.4; }
:root[data-focal="135"] body.home { --p: 2400px; --s: 1.45; --dof: 2.4; }

.stage {
  position: absolute; inset: 0;
  perspective: var(--p); perspective-origin: 50% 50%;
  transition: perspective .9s cubic-bezier(.3,.8,.2,1);
  cursor: grab; user-select: none; -webkit-user-select: none; touch-action: none;
}
.stage.dragging { cursor: grabbing; }
.zoom {
  position: absolute; left: 50%; top: 50%; width: 0; height: 0;
  transform-style: preserve-3d;
  transform: scale(var(--s)); transition: transform .9s cubic-bezier(.3,.8,.2,1);
}
.sphere {
  position: absolute; left: 0; top: 0; width: 0; height: 0;
  transform-style: preserve-3d;
  transform: rotateX(var(--rx, 0rad)) rotateY(var(--ry, 0rad));
}
.card {
  position: absolute; left: 0; top: 0; display: block;
  width: var(--w); height: var(--h); margin: calc(var(--h) / -2) 0 0 calc(var(--w) / -2);
  transform-style: preserve-3d; backface-visibility: hidden;
  /* billboard: undo the sphere rotation so every card faces the camera */
  transform: translate3d(var(--x), var(--y), var(--z)) rotateY(calc(-1 * var(--ry, 0rad))) rotateX(calc(-1 * var(--rx, 0rad)));
  will-change: transform, filter;
}
.card img { width: 100%; height: 100%; object-fit: cover; display: block; background: var(--bg-2); pointer-events: none; box-shadow: 0 1px 2px rgba(0,0,0,.08); }
.card:hover { text-decoration: none; }
.card:hover img { outline: 1px solid var(--fg); }

/* intro phases: cards start in the centre, form a ring, then the sphere */
.stage.anim .card { transition: transform 1.6s cubic-bezier(.6,0,.2,1), opacity .6s; transition-delay: var(--d, 0s); }
.stage.phase-2 .card { transition-property: transform; }
.stage.phase-0 .card, .stage.phase-1 .card { transform: translate3d(var(--rx1), var(--ry1), 0); }
.stage.phase-0 .card { opacity: 0; transition: none; }
.stage.phase-1 .card.late { transform: translate3d(0,0,0) scale(.2); opacity: 0; }

.intro-text {
  position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; z-index: 5;
  transition: opacity .8s;
}
.intro-text .name { font-size: clamp(20px, 2.4vw, 34px); letter-spacing: -0.02em; text-align: center; line-height: 1.1; }
.intro-text .credit { position: absolute; left: 50%; bottom: var(--gutter); transform: translateX(-50%); font-family: var(--mono); font-size: 10px; letter-spacing: .04em; color: var(--fg-2); white-space: nowrap; }
.intro-text .credit a { pointer-events: auto; color: var(--fg); }
body.home:not(.loading) .intro-text .credit { opacity: 0; transition: opacity .8s; pointer-events: none; }
.intro-text .count { position: absolute; right: var(--gutter); bottom: var(--gutter); font-family: var(--mono); font-size: 12px; color: var(--fg-2); font-variant-numeric: tabular-nums; }
.intro-text .side { position: absolute; top: 50%; transform: translateY(-50%); font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--fg-2); opacity: 0; transition: opacity .8s .4s; }
.intro-text .side.l { left: max(var(--gutter), 80px); }
.intro-text .side.r { right: var(--gutter); text-align: right; }
.stage.phase-1 ~ .intro-text .side, .stage.phase-2 ~ .intro-text .side { opacity: 1; }
body.home:not(.loading) .intro-text .name, body.home:not(.loading) .intro-text .count { opacity: 0; }

.label {
  position: absolute; left: 50%; bottom: var(--gutter); transform: translateX(-50%);
  font-family: var(--mono); font-size: 12px; text-transform: uppercase; letter-spacing: .04em;
  white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity .25s; z-index: 5;
}
.label.on { opacity: 1; }
.label span { color: var(--fg-2); margin-left: 1em; }
.hint { position: absolute; left: 50%; top: calc(var(--gutter) + 4px); transform: translateX(-50%); font-family: var(--mono); font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--fg-2); opacity: 0; transition: opacity 1s 1s; pointer-events: none; }
body.home:not(.loading) .hint { opacity: 1; }
.stage.moved ~ .hint { opacity: 0; transition-delay: 0s; }

@media (max-width: 900px) {
  body.home main { zoom: 1; padding: 0; }
  .intro-text .side, .hint { display: none; }
  body.home { --p: 1200px !important; --s: 1 !important; --dof: 0 !important; } /* no lens effect on phones */
}
@media (prefers-reduced-motion: reduce) {
  .stage.anim .card, .stage.lens .sphere, .stage { transition: none; }
}
