/* ===================================================================
   The cups ladder — four trophies standing on lit blocks.

   ONE coordinate space. The background, each trophy, each block face
   and each plate are all percentages of .tr-stage-frame, measured off
   tour-platforms.webp: plinth top edges at 57.08/51.44/45.91/41.08%
   and block faces at 13.9-33.0 / 33.8-51.2 / 52.1-72.4 / 73.1-93.1%.
   Nothing here is estimated, and nothing may be.

   ONE SCREEN. The section is the frame plus its padding, nothing else,
   because the frame alone is 0.48 x width and there is no room for a
   copy band above it. The copy is overlaid on the empty sky at the top
   left and must stay clear of the Warriors trophy.

   Never put a height cap on .tr-stage. One used to exist and it
   collapsed the section to a left-aligned remnant on short screens.
   =================================================================== */

.tr-cups {
  background: #03182b;
  padding-block: clamp(8px, 1.2svh, 18px);
  overflow: hidden;
}
.tr-stage { position: relative; width: 100%; }
.tr-stage-frame {
  position: relative;
  aspect-ratio: 1810 / 869;
  width: 100%;
  isolation: isolate;
}
.tr-stage-bg {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: fill;
}

/* ---------------------------- the copy ---------------------------- */
/* A sibling of the frame, not a child. Absolutely positioned it covers
   the frame's box; stacked on mobile it flows above the frame instead.
   Inside the frame it could not do the second thing — the frame is
   ratio-locked, so the copy landed on top of the photograph. */
.tr-cups-copy {
  position: absolute; z-index: 4;
  /* The whole block has to finish above the Warriors trophy's VISIBLE
     top, which is its box top plus the 12.37% transparent margin its
     cutout carries — about 36.5% of the frame. Everything below is
     sized to land inside that at 1366 upward, which is the tightest
     case: the column narrows with the viewport, so the paragraph gains
     a line exactly where there is least room. */
  left: var(--pad-x); top: 2%;
  width: min(430px, 30%);
}
.tr-cups-copy .eyebrow { margin-bottom: 6px; font-size:var(--ds-eyebrow); }
.tr-cups-copy h2 { font-size:var(--ds-title); line-height:1.1; }
/* core.css sets `.section-copy > p:not(.eyebrow)` at --text-body, which
   is 0,2,1 and outranks a plain `.tr-cups-copy p`. That is why this
   paragraph was rendering at 16px however small the clamp here said,
   and why the block kept overrunning the Warriors trophy however much
   the type was tightened. Match the specificity rather than shrink
   further. */
.tr-cups-copy.section-copy > p:not(.eyebrow) {
  font-size:var(--ds-eyebrow); line-height:1.25;
  color: #cfe0f3; margin: 7px 0 0;
}
.tr-cups-copy.section-copy > p.note {
  margin-top: 7px; padding-left: 10px;
  border-left: 2px solid var(--cyan);
  font-size: clamp(12px, 0.78vw, 13.5px); line-height: 1.38; color: #bfe2f5;
}

/* ---------------------------- the tiers --------------------------- */
/* The wrapper spans the frame so its children can be placed against the
   frame's coordinates. It must not take pointer events: at this size it
   would be a transparent lid over everything. The block and the trophy
   take them back, and :hover still reaches this element because hover
   propagates up from whichever child the pointer is actually over. */
.tr-tiers {
  /* inset:0 on .tr-stage, whose only in-flow child is the frame, so
     this covers exactly the frame's box and the blocks land on the
     plinths. It must not take pointer events at that size — it would be
     a transparent lid over every trophy. The tiers take them back. */
  position: absolute; inset: 0; z-index: 3;
  pointer-events: none;
  margin: 0; padding: 0; list-style: none;
}
/* A tier IS the plinth's front face in the photograph — all four
   edges of it, not three.

   `bottom: 0` used to run the box to the bottom of the FRAME. The
   floor line is at 83.54%, so every tier was 16.5% of the frame too
   tall, and since the plate lays out inside this box the copy opened
   past the bottom of the stone and printed onto the water. --bb is
   that floor line, measured off the image. */
.tr-tier {
  position: absolute;
  /* --fl/--fr, not --bl/--br: the outer edges include the dark side
     face turning away from the camera, and laying the wording against
     those put it on the side of the block instead of its front. */
  left: var(--fl); right: calc(100% - var(--fr));
  top: var(--bt); bottom: calc(100% - var(--bb));
  pointer-events: auto;
  cursor: pointer;
}
.tr-tier:focus-visible { outline: 2px solid var(--cyan); outline-offset: -2px; }

/* The block's own front face, lit on hover. Its rect is the plinth in
   the photograph, so what lights up IS the block the trophy stands on. */
.tr-block {
  /* The glow now covers the whole stone face, because the tier box is
     finally the stone face. It fills top to bottom and fades out at
     each edge rather than ending on a drawn line.

     The edges stay soft deliberately. Each top face is a parallelogram
     in perspective — the Lords face drops about 43px from its right
     corner to its left — so a hard horizontal edge would sit visibly
     off the block however carefully it were placed. Tracing the rim
     was tried and abandoned: measured column by column the lit edge
     scatters +/-1.5% against its own recorded top, which is wider than
     the error being chased. A gradient that has faded to nothing
     before it reaches the boundary cannot be misaligned, and still
     reads as the block itself lighting up. */
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: 2px;
  background:
    /* the lit rim, hugging the top edge */
    radial-gradient(ellipse 82% 26% at 50% 0%, rgba(150, 240, 255, 0.72), transparent 72%),
    /* the face itself catching the light, falling off toward the floor */
    linear-gradient(180deg,
      rgba(40, 205, 255, 0.40) 0%,
      rgba(0, 120, 255, 0.20) 34%,
      rgba(0, 86, 200, 0.10) 66%,
      transparent 96%),
    /* a cool bounce coming back up off the wet floor */
    radial-gradient(ellipse 70% 20% at 50% 100%, rgba(25, 170, 255, 0.26), transparent 74%);
  /* Feather both axes so no side, top or bottom lands on a hard line. */
  -webkit-mask-image:
    linear-gradient(90deg, transparent, #000 13%, #000 87%, transparent),
    linear-gradient(180deg, #000 0%, #000 88%, transparent);
  mask-image:
    linear-gradient(90deg, transparent, #000 13%, #000 87%, transparent),
    linear-gradient(180deg, #000 0%, #000 88%, transparent);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
  opacity: 0;
  transition: opacity 360ms var(--surface-ease, ease);
}
/* The bloom the stone throws into the air around it. Separate from the
   face so it can spill past the block's edges without the mask above
   clipping it back. */
.tr-block::after {
  content: "";
  position: absolute;
  inset: -6% -8% -10%;
  border-radius: 8px;
  background: radial-gradient(ellipse 60% 52% at 50% 18%, rgba(35, 190, 255, 0.30), transparent 70%);
  filter: blur(10px);
}

/* ---------------------------- the cups ---------------------------- */
/* Base meets the platform top. --foot is the transparent margin under
   the trophy inside its cutout. js/section-cups.js rewrites this
   transform on scroll and must reproduce it exactly, --foot included. */
.tr-cup {
  position: absolute; z-index: 2;
  left: var(--cx); top: var(--top);
  width: 14.5%;
  transform: translate(-50%, calc(-100% + var(--foot, 0%))) scale(var(--scale));
  transform-origin: 50% 100%;
  pointer-events: auto;
  cursor: pointer;
  will-change: transform;
}
.tr-cup img {
  width: 100%; height: auto; display: block;
  filter: drop-shadow(0 18px 26px rgba(0, 0, 0, 0.62));
  transform-origin: 50% 100%;
}
.tr-cup-glow {
  position: absolute;
  left: 50%; bottom: calc(var(--foot, 0%) * -1);
  width: 168%; height: 22%;
  transform: translate(-50%, 45%);
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(25, 200, 255, 0.55), rgba(0, 98, 255, 0.22) 45%, transparent 72%);
  opacity: 0.34;
  filter: blur(2px);
  pointer-events: none;
  z-index: -1;
}

/* --------------------------- the plates --------------------------- */
/* Painted onto the block face — no card, no border, no panel, so it
   reads as part of the block rather than a tile sitting on top of it.
   The level and the name are always legible; the cup's own line from
   the copy document opens underneath on hover. */
/* Inset from the face's own edges so the lettering sits ON the stone
   with a margin of stone around it, the way a cast plate would — not
   running to the corners as if it were a caption laid over the photo.
   Bounded bottom as well as top: whatever the body opens to, it cannot
   leave the block. */
.tr-plate {
  position: absolute; z-index: 1;
  left: 0; right: 0; top: 7%; bottom: 6%;
  padding-inline: clamp(10px, 1.1vw, 20px);
  display: grid; align-content: start; justify-items: start;
  pointer-events: none;
  /* Cut into the surface rather than floating above it: a dark bed
     below the glyph, a faint lit edge above it. */
  text-shadow:
    0 1px 0 rgba(0, 0, 0, 0.55),
    0 -1px 0 rgba(168, 226, 255, 0.16),
    0 2px 12px rgba(0, 12, 28, 0.9);
}
.tr-plate-level {
  font-family: var(--body); font-weight: 700;
  font-size: clamp(12px, 0.76vw, 13px); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--cyan);
}
.tr-plate-name {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(15px, 1.35vw, 23px); line-height: 1.12;
  color: #fff; margin-top: 2px;
}
/* max-height rather than a 0fr->1fr grid: fr units are not valid inside
   calc(), and --lit drives every other part of this hover. It is inside
   an absolutely positioned plate, so opening it moves nothing on the
   page. */
.tr-plate-body {
  display: block; overflow: hidden;
  max-height: calc(var(--lit, 0) * 9em);
  opacity: var(--lit, 0);
  transition: max-height 380ms ease, opacity 300ms ease;
}
.tr-plate-body > span {
  display: block;
  font-size: clamp(12px, 0.84vw, 14px); line-height: 1.45;
  color: #e7f0ff; padding-top: 6px;
}

/* ---------------------------- wall text --------------------------- */
.tr-stage-wall {
  position: absolute; right: 2%; top: 14%; z-index: 4;
  color: rgba(66, 160, 235, 0.72);
  font-family: var(--display); font-weight: 800;
  letter-spacing: 0.01em; text-transform: uppercase;
  font-size: clamp(13px, 1.95vw, 36px); line-height: 0.95;
}

/* ============================== hover ============================= */
/* Pointer-only: a touch device cannot hover, so on touch the plate
   bodies are shown permanently further down rather than being
   unreachable. Hovering the trophy or the block lights the same tier. */
@media (hover: hover) and (pointer: fine) {
  /* Hovering the trophy or its block lights the same tier. They sit in
     different subtrees — the trophy is placed against the frame, the
     block against its own rect — so :has() on their shared ancestor is
     what couples them. Each pair is written out rather than derived,
     because a wrong pairing would light the wrong block. */
  .tr-stage:has(.tr-tier[data-tier="0"]:hover) .tr-tier[data-tier="0"],
  .tr-stage:has(.tr-cup[data-cup="0"]:hover) .tr-tier[data-tier="0"],
  .tr-tier[data-tier="0"]:focus-visible { --lit: 1; }
  .tr-stage:has(.tr-tier[data-tier="0"]:hover) .tr-cup[data-cup="0"],
  .tr-stage:has(.tr-tier[data-tier="0"]:focus-visible) .tr-cup[data-cup="0"],
  .tr-stage:has(.tr-cup[data-cup="0"]:hover) .tr-cup[data-cup="0"] { --lit: 1; }
  .tr-stage:has(.tr-tier[data-tier="1"]:hover) .tr-tier[data-tier="1"],
  .tr-stage:has(.tr-cup[data-cup="1"]:hover) .tr-tier[data-tier="1"],
  .tr-tier[data-tier="1"]:focus-visible { --lit: 1; }
  .tr-stage:has(.tr-tier[data-tier="1"]:hover) .tr-cup[data-cup="1"],
  .tr-stage:has(.tr-tier[data-tier="1"]:focus-visible) .tr-cup[data-cup="1"],
  .tr-stage:has(.tr-cup[data-cup="1"]:hover) .tr-cup[data-cup="1"] { --lit: 1; }
  .tr-stage:has(.tr-tier[data-tier="2"]:hover) .tr-tier[data-tier="2"],
  .tr-stage:has(.tr-cup[data-cup="2"]:hover) .tr-tier[data-tier="2"],
  .tr-tier[data-tier="2"]:focus-visible { --lit: 1; }
  .tr-stage:has(.tr-tier[data-tier="2"]:hover) .tr-cup[data-cup="2"],
  .tr-stage:has(.tr-tier[data-tier="2"]:focus-visible) .tr-cup[data-cup="2"],
  .tr-stage:has(.tr-cup[data-cup="2"]:hover) .tr-cup[data-cup="2"] { --lit: 1; }
  .tr-stage:has(.tr-tier[data-tier="3"]:hover) .tr-tier[data-tier="3"],
  .tr-stage:has(.tr-cup[data-cup="3"]:hover) .tr-tier[data-tier="3"],
  .tr-tier[data-tier="3"]:focus-visible { --lit: 1; }
  .tr-stage:has(.tr-tier[data-tier="3"]:hover) .tr-cup[data-cup="3"],
  .tr-stage:has(.tr-tier[data-tier="3"]:focus-visible) .tr-cup[data-cup="3"],
  .tr-stage:has(.tr-cup[data-cup="3"]:hover) .tr-cup[data-cup="3"] { --lit: 1; }

  .tr-cup img, .tr-cup-glow, .tr-block {
    transition: transform 420ms ease, opacity 420ms ease, filter 420ms ease, box-shadow 320ms ease;
  }
  .tr-tier .tr-block { opacity: var(--lit, 0); }
  .tr-cup img {
    transform: scale(calc(1 + 0.08 * var(--lit, 0))) translateY(calc(-8px * var(--lit, 0)));
    filter: drop-shadow(0 18px 26px rgba(0, 0, 0, 0.62))
            drop-shadow(0 0 calc(30px * var(--lit, 0)) rgba(25, 200, 255, 0.55))
            brightness(calc(1 + 0.1 * var(--lit, 0)));
  }
  .tr-cup-glow {
    opacity: calc(0.34 + 0.66 * var(--lit, 0));
    transform: translate(-50%, 45%) scale(calc(1 + 0.2 * var(--lit, 0)));
  }
}

/* ============================ entrance ============================ */
/* Applied only once .is-running is set, never declared paused on a
   from-state: paused, it held every cup off its plinth until the
   observer fired, and left them there for anyone without the script. */
@media (prefers-reduced-motion: no-preference) {
  [data-stage].is-running .tr-cup {
    animation: tr-cup-in 760ms cubic-bezier(.2,.75,.3,1) both;
    animation-delay: calc(var(--i, 0) * 120ms);
  }
  [data-stage].is-running .tr-plate {
    animation: tr-plate-in 560ms ease both;
    animation-delay: calc(300ms + var(--i) * 120ms);
  }
  @keyframes tr-cup-in {
    from { opacity: 0; transform: translate(-50%, calc(-100% + var(--foot, 0%) + 26px)) scale(var(--scale)); }
    to   { opacity: 1; transform: translate(-50%, calc(-100% + var(--foot, 0%))) scale(var(--scale)); }
  }
  @keyframes tr-plate-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
}
@media (prefers-reduced-motion: reduce) {
  .tr-cup img, .tr-cup-glow, .tr-block, .tr-plate-body { transition: none; }
}

/* =========================== responsive =========================== */
@media (max-width: 1100px) {
  .tr-cups-copy { width: min(360px, 34%); }
  .tr-cups-copy p { display: none; }   /* the note carries the point at this width */
}
/* Below 900px the overlay has no room and there is no hover, so the
   section stacks: copy, the stage, then every cup's line as a list.
   Nothing is hidden — the bodies that hover would reveal are shown. */
@media (max-width: 900px) {
  .tr-cups { padding-block: clamp(24px, 4svh, 44px); }
  .tr-stage { display: grid; gap: 16px; }
  .tr-cups-copy {
    position: static; width: auto;
    padding-inline: var(--pad-x); margin-bottom: 4px;
  }
  .tr-cups-copy p { display: block; }
  .tr-stage-wall { display: none; }
  .tr-tiers { position: static; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding-inline: var(--pad-x); }
  .tr-tier { position: static; cursor: default; }
  .tr-block { display: none; }
  .tr-plate {
    position: static;
    padding: 12px 14px;
    margin-inline: var(--pad-x);
    border-top: 2px solid rgba(25, 200, 255, 0.6);
    border-radius: 0 0 8px 8px;
    background: linear-gradient(180deg, rgba(7, 32, 60, 0.9), rgba(4, 20, 40, 0.84));
    text-shadow: none;
  }
  .tr-plate-body { max-height: none; opacity: 1; }
  /* The trophies stay on their platforms inside the frame. */
  .tr-stage-frame { grid-row: 2; }
  .tr-cup { position: absolute; }
}
