/* ------------------------------------------------------------------
   Orbit rings — All In House

   A ring of square footage turns around a centred statement. Nothing
   is pinned: the section sits in normal flow and the page never stops
   moving. The ring's rotation is tied to how far the section has
   travelled across the viewport, so the wheel turns the carousel and
   scrolls the page at the same time.

   One full revolution spans the traverse — from the moment the
   section's top clears the bottom of the screen to the moment its
   bottom clears the top — so every cell passes the mark exactly once
   on the way through.

   rings.js writes a single custom property, --t (0 → 1), on the
   section. Everything below is derived from it, so there is exactly
   one number in flight per ring per frame.

   Each cell counter-rotates by the same amount so the footage and its
   label stay upright while the ring carries them around.
   ------------------------------------------------------------------ */

.orbit {
  --t: 0;                /* how far this section has crossed the screen */
  --count: 7;
  --stage: min(80vw, 68vh, 620px);
  --cell: 23%;

  position: relative;
  overflow: hidden;
  background: var(--ink);
  color: #fff;
  padding: clamp(72px, 12vw, 128px) 24px;
}

.orbit__pin {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(24px, 4vh, 52px);
}

.orbit__eyebrow {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-align: center;
  opacity: 0.55;
}

/* ---- the stage ---- */

.orbit__stage {
  position: relative;
  width: var(--stage);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  flex: none;
}

/* Negative, so scrolling down brings the next cell in source order up
   to the top rather than walking the list backwards. */
.orbit__ring {
  position: absolute;
  inset: 0;
  transform: rotate(calc(var(--t) * -360deg));
}

/* Each cell sits on the circle at its own angle. A percentage translate
   would resolve against the cell's own width, so the radius is carried
   as a length off the stage instead. */
.orbit__cell {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--cell);
  aspect-ratio: 1;
  --r: calc(var(--stage) * 0.39);
  transform:
    translate(-50%, -50%)
    rotate(var(--a))
    translateY(calc(var(--r) * -1))
    rotate(calc(var(--a) * -1));
}

/* undo the ring's rotation so nothing inside the cell tips over */
.orbit__counter {
  position: absolute;
  inset: 0;
  transform: rotate(calc(var(--t) * 360deg));
}

.orbit__media {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: #161616;
}

.orbit__media img,
.orbit__media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: grayscale(0.2) brightness(0.68);
  transition: filter 0.45s ease;
}

.orbit__label {
  position: absolute;
  top: calc(100% + 12px);
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0.3;
  transition: opacity 0.45s ease;
}

/* ---- the cell currently at the top of the ring ----
   rings.js sets this from --t; it is the same arithmetic, kept in one
   place rather than duplicated as CSS keyframes. */

.orbit__cell.is-focus .orbit__media img,
.orbit__cell.is-focus .orbit__media video {
  filter: grayscale(0) brightness(1.04);
}

.orbit__cell.is-focus .orbit__label {
  opacity: 1;
}

/* ---- the statement in the middle ---- */

.orbit__centre {
  position: relative;
  z-index: 2;
  width: min(58%, 340px);
  text-align: center;
}

.orbit__centre::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 190%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side, #0a0a0af2 42%, #0a0a0aad 68%, #0a0a0a00 100%);
  z-index: -1;
  pointer-events: none;
}

.orbit__statement {
  margin: 0;
  font-family: Perandory, Georgia, serif;
  font-weight: 400;
  font-size: clamp(1.8rem, 5.6vw, 2.9rem);
  line-height: 1.04;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-wrap: balance;
}

.orbit__note {
  margin: 1em 0 0;
  font-size: 0.9375rem;
  line-height: 1.5;
  opacity: 0.62;
  text-wrap: balance;
}

/* ---- narrow screens ---- */

@media (max-width: 700px) {
  .orbit { --stage: min(86vw, 62vh, 400px); padding-inline: 16px; }
  .orbit__cell { --r: calc(var(--stage) * 0.40); width: 26%; }
  .orbit__centre { width: min(68%, 250px); }
  .orbit__label { font-size: 0.6875rem; letter-spacing: 0.1em; top: calc(100% + 8px); }
}

/* ---- reduced motion, and any browser rings.js could not drive ----
   The ring holds still and every cell reads at full strength. The
   section already sits in normal flow, so nothing else has to change. */

.orbit--static .orbit__ring,
.orbit--static .orbit__counter {
  transform: none;
}

.orbit--static .orbit__media img,
.orbit--static .orbit__media video {
  filter: grayscale(0.1) brightness(0.9);
}

.orbit--static .orbit__label {
  opacity: 0.85;
}

/* ------------------------------------------------------------------
   A band whose still is a clip instead — scrubbed by the scroll, so it
   runs forward and backward with the wheel and holds its frame the
   moment scrolling stops. rings.js picks the crop and drives the
   position; the poster covers the wait and the reduced-motion case.
   ------------------------------------------------------------------ */

.band--scrub video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--band-pos, center);
  display: block;
}
