/* ============================================================
   EN¿GMA — character select
   Rider left, name and links middle, roster right.
   ============================================================ */
:root{
  --bg:#010101; --fg:#f2f3f7; --muted:#8a8c98;
  --line:rgba(255,255,255,.22); --line-strong:rgba(255,255,255,.72);
  --accent:#f3c10b;
  --ease:cubic-bezier(.22,.61,.36,1);
  --spring:cubic-bezier(.16,1.02,.3,1);
  --skew:12%;
  --pad:clamp(16px,2.6vw,34px);
}
*{box-sizing:border-box}
/* .btn sets display:inline-flex, which outranks the UA sheet's [hidden].
   Without this the "New outfit" pill shows on riders who haven't got one. */
[hidden]{display:none !important}
html,body{height:100%}
body{
  margin:0;background:var(--bg);color:var(--fg);
  font:400 15px/1.6 var(--font-body);
  overflow:hidden;overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}
img,video{display:block;max-width:100%}

/* ---------- nav ----------
   Geometry and the underline come from base.css so this page's header
   sits exactly where the puzzle pages' does. Only the Street Skater
   lockup is local — and it is taken out of the flow, because stacking
   it under the mark was what made this header 307px tall and put its
   dead space over the first row of rider tiles. */
.nav .brand{display:block}
/* The Street Skater lockup now lives on the plate — see the markup. */
/* Over the top-left of the rider on desktop, where it reads as a title
   plate on the artwork. It is taken out of the flow so it cannot push the
   grid around, and it never takes a click. */
.select > .ss{
  position:absolute;z-index:3;pointer-events:none;
  top:calc(104px - .5vh);left:var(--pad);
  width:clamp(150px,15vw,230px);
}

/* ============================================================
   LAYOUT — three columns
   ============================================================ */
.select{
  position:relative;
  height:100svh;
  padding:104px var(--pad) clamp(14px,2.4vh,30px);
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,.9fr) minmax(320px,.85fr);
  align-items:stretch;gap:clamp(12px,2vw,34px);
}

/* ---------- the rider ---------- */
/* The rider column is the point of the page — it keeps full height and
   the roster gives way, never the other way round. */
/* ---------- the reel ----------
   Three slots on one track. The middle one is the rider; the other two
   sit a stage-width to either side, scaled back and dimmed, so a drag
   shows you who is next instead of just swapping the picture. --dx is
   set by the pointer handler as a fraction of the stage width, so the
   track follows the finger and the transition only does the snap. */
.stage{
  position:relative;min-height:0;height:100%;
  overflow:hidden;
  touch-action:pan-y;              /* vertical scroll still belongs to the page */
  cursor:grab;
}
.stage:active{cursor:grabbing}
.reel{
  --dx:0;
  position:absolute;inset:0;
  transform:translateX(calc(var(--dx) * 100%));
  transition:transform 460ms var(--spring);
}
.reel.dragging{transition:none}
/* Used for the one frame in which the riders are swapped after the track
   has finished travelling — see step() in team.js. */
.reel.no-anim{transition:none}
.slot{
  position:absolute;inset:0;margin:0;
  display:grid;
}
.slot-prev{transform:translateX(-100%)}
.slot-next{transform:translateX(100%)}
/* The neighbours are context, not the subject. */
.slot-prev,.slot-next{opacity:.3;filter:grayscale(.7) brightness(.6);scale:.82}
.slot-prev img,.slot-next img{pointer-events:none}

/* ---------- the arrows ---------- */
.reel-nav{
  position:absolute;top:50%;translate:0 -50%;z-index:4;
  width:46px;height:46px;border-radius:50%;padding:0;cursor:pointer;
  border:1px solid var(--line);background:rgba(0,0,0,.42);
  backdrop-filter:blur(7px);-webkit-backdrop-filter:blur(7px);
  color:var(--fg);display:grid;place-items:center;
  transition:border-color .22s var(--ease), background .22s var(--ease),
             transform .3s var(--spring), opacity .22s var(--ease);
}
.reel-nav svg{width:20px;height:20px;fill:none;stroke:currentColor;
              stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.reel-nav.prev{left:4px}
.reel-nav.next{right:4px}
.reel-nav:hover{border-color:var(--line-strong);background:rgba(0,0,0,.7)}
.reel-nav.prev:hover{transform:translateY(-50%) translateX(-2px)}
.reel-nav.next:hover{transform:translateY(-50%) translateX(2px)}
.reel-nav[disabled]{opacity:.22;pointer-events:none}

/* The still and the clip occupy the same cell and both fill it. `contain`
   keeps the whole rider at the largest size the box allows, which — since
   the media is 520x936 and the box is never that narrow — always means
   full height. Sizing by `width:auto` instead let a max-width cap steal
   the height back, which is why the clip sat short on a phone. */
.slot > *{
  grid-area:1/1;
  width:100%;height:100%;min-height:0;
  object-fit:contain;object-position:bottom center;
  opacity:0;transform:translateY(10px);
  transition:opacity 280ms var(--ease), transform 520ms var(--spring);
}
.slot > *.on{opacity:1;transform:none}
/* The clip is painted over the still, so the still is never removed —
   if playback is refused the rider is still on screen. */
.slot video{z-index:1}
.slot-cur::after{
  content:'';position:absolute;left:50%;bottom:0;translate:-50% 0;
  width:min(70%,300px);height:22px;border-radius:50%;
  background:radial-gradient(50% 50%, rgba(255,255,255,.1), transparent 70%);
  pointer-events:none;
}

/* ---------- the plate ---------- */
.plate{
  min-height:0;display:flex;flex-direction:column;justify-content:center;
  padding-bottom:6vh;
}
.plate .eyebrow{
  font-size:9.5px;letter-spacing:.32em;text-transform:uppercase;color:var(--muted);margin:0;
}
.who{
  font-family:"Archivo Black","Arial Black",Impact,sans-serif;
  padding:.04em .16em .06em 0;
  font-size:clamp(30px,4.4vw,68px);font-weight:900;line-height:.88;
  letter-spacing:-.02em;margin:10px 0 0;text-transform:uppercase;font-style:italic;
  background:linear-gradient(180deg,#fff 34%,var(--accent) 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  text-shadow:0 0 34px rgba(243,193,11,.2);
}
.wears{
  font-size:13px;color:var(--muted);margin:12px 0 0;letter-spacing:.01em;
  max-width:34ch;line-height:1.55;
}
.wears:empty{display:none}

/* ---------- the name arrives ----------
   Wipes in behind a mask, blown out to white, then settles into the
   gradient. Two animations on one element: the clip does the reveal,
   the filter does the cool-down. */
@keyframes wipe{
  from{ clip-path:inset(0 100% 0 0) }
  to  { clip-path:inset(0 0 0 0) }
}
@keyframes cool{
  0%   { filter:brightness(2.6) saturate(0); text-shadow:0 0 30px rgba(255,255,255,.85) }
  55%  { filter:brightness(1.5) saturate(.6); text-shadow:0 0 26px rgba(243,193,11,.5) }
  100% { filter:none; text-shadow:0 0 34px rgba(243,193,11,.2) }
}
.who.enter{
  /* `backwards`, not `both`. With `both` the final keyframe — clip-path
     inset(0 0 0 0) — stays applied for ever, and an inset clip is taken
     from the border box, so the lean of the italic and the glow around it
     were being sliced off the last letter. `backwards` holds the start
     state during the delay and then hands the element back to its own
     styles, unclipped. The padding gives the lean somewhere to sit. */
  animation:wipe 520ms var(--ease) backwards, cool 1000ms var(--ease) backwards;
}
@keyframes bio-in{
  from{ opacity:0; clip-path:inset(0 100% 0 0) }
  to  { opacity:1; clip-path:inset(0 0 0 0) }
}
.wears.enter{animation:bio-in 620ms var(--ease) 160ms backwards}

.links{display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin-top:22px}
.btn{
  display:inline-flex;align-items:center;gap:11px;text-decoration:none;color:var(--fg);
  border:1px solid var(--line);border-radius:999px;
  padding:12px 22px;font-size:9.5px;letter-spacing:.22em;text-transform:uppercase;font-weight:700;
  background:rgba(0,0,0,.5);cursor:pointer;font-family:inherit;
  transition:background .22s var(--ease), color .22s var(--ease), border-color .22s var(--ease);
}
.btn svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.btn.ghost{color:var(--muted)}
.btn.ghost:hover{color:var(--fg);border-color:var(--line-strong)}

/* the rider in the new drop gets the loud one */
.btn.drop{
  border:0;color:#fff;
  background:linear-gradient(102deg,#cf1f24 0%,#e8620c 48%,#f3c10b 100%);
  background-size:200% 100%;background-position:0 0;
  box-shadow:0 8px 26px rgba(207,31,36,.34);
  transition:background-position 700ms var(--ease), transform 360ms var(--spring);
}
.btn.drop:hover{background-position:100% 0;transform:translateY(-2px)}
.btn.drop .tag{
  font-size:8.5px;letter-spacing:.2em;padding:3px 8px;border-radius:999px;
  background:rgba(0,0,0,.32);
}

/* ---------- the toggle ----------
   A rider who is two riders. Deliberately the quietest thing on the
   plate — a "?" on a dark outline — because it is meant to be found,
   not offered. It spins its arrows on hover so it reads as a switch
   rather than as another link. */
.btn.flip{padding:12px 18px;letter-spacing:.2em}
.btn.flip svg{transition:transform 520ms var(--spring)}
.btn.flip:hover svg{transform:rotate(180deg)}
.btn.flip[aria-pressed="true"]{color:var(--fg);border-color:var(--line-strong)}

/* The alt's own way out. Same loud pill as a drop link, but it arrives
   rather than sitting there, so the eye goes to it the moment it exists. */
@keyframes found-in{
  from{opacity:0;transform:translateY(8px) scale(.96)}
  to{opacity:1;transform:none}
}
.btn.drop.found{animation:found-in 520ms var(--spring) both}
@media (prefers-reduced-motion:reduce){
  .btn.flip svg,.btn.drop.found{animation:none;transition:none}
}

/* ============================================================
   THE ROSTER
   ============================================================ */
.pick{
  position:relative;min-height:0;
  display:flex;flex-direction:column;justify-content:center;
  padding-bottom:clamp(52px,9vh,104px);
}
.hint{
  position:absolute;top:-4px;right:0;margin:0;
  font-size:9px;letter-spacing:.24em;text-transform:uppercase;color:var(--muted);
}
@media (hover:none){ .hint{display:none} }

.roster{display:flex;flex-direction:column;gap:clamp(4px,.8vh,9px)}
.row{
  --lean:22px;
  display:flex;gap:clamp(4px,.5vw,8px);
  padding:clamp(3px,.5vh,7px) calc(var(--lean) + 4px);
  border:1px solid rgba(255,255,255,.16);
  transform:translateX(calc(var(--i) * -8px));
  clip-path:polygon(var(--lean) 0, 100% 0, calc(100% - var(--lean)) 100%, 0 100%);
}
.cell{
  position:relative;flex:1 1 0;min-width:0;aspect-ratio:1/1;
  padding:0;border:0;background:#0a0a0c;cursor:pointer;overflow:hidden;
  clip-path:polygon(var(--skew) 0, 100% 0, calc(100% - var(--skew)) 100%, 0 100%);
  filter:grayscale(.55) brightness(.7);
  transition:transform 300ms var(--spring), filter 240ms var(--ease);
}
.cell img{width:100%;height:100%;object-fit:cover;transition:transform 620ms var(--ease)}

/* hover / keyboard cursor — the tile only. The stage is not touched. */
.cell:hover,.cell.cursor{filter:none;transform:scale(1.07);z-index:2}
.cell:hover img{transform:scale(1.05)}
.cell:focus-visible{outline:none;filter:none;transform:scale(1.07);z-index:3}
.cell:focus-visible::after{
  content:'';position:absolute;inset:0;border:2px solid #fff;
  clip-path:polygon(var(--skew) 0, 100% 0, calc(100% - var(--skew)) 100%, 0 100%);
}

/* the committed pick */
.cell[aria-selected="true"]{filter:none;transform:scale(1.12);z-index:4}
.cell[aria-selected="true"]::after{
  content:'';position:absolute;inset:0;border:2px solid var(--accent);
  clip-path:polygon(var(--skew) 0, 100% 0, calc(100% - var(--skew)) 100%, 0 100%);
  animation:pulse 1.4s var(--ease) infinite;
}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.32}}

.cell .nm{
  position:absolute;left:0;right:0;bottom:0;padding:14px 4px 4px;
  font-size:8px;letter-spacing:.16em;text-transform:uppercase;text-align:center;
  color:#fff;background:linear-gradient(to top,rgba(0,0,0,.85),transparent);
  opacity:0;transition:opacity 220ms var(--ease);
}
.cell:hover .nm,.cell.cursor .nm,.cell[aria-selected="true"] .nm{opacity:1}

/* the rider wearing the new drop */
.cell .flag{
  position:absolute;top:0;left:0;right:0;padding:4px 2px 3px;
  font-size:7px;letter-spacing:.14em;text-transform:uppercase;text-align:center;
  font-weight:700;color:#fff;
  background:linear-gradient(102deg,#cf1f24,#e8620c);
  z-index:2;
}

/* ---------- the mark, bottom right ---------- */
.brandmark{
  position:absolute;right:0;bottom:0;
  width:clamp(150px,17vw,260px);
  opacity:.95;pointer-events:none;
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
/* ------------------------------------------------------------
   PHONE — the rider takes the screen

   Not a narrow column with things stacked under it: the stage goes
   edge to edge and most of the way down, the name sits on top of the
   bottom of it behind a fade, and the roster is the only thing below.
   The stage, the plate and the logo are all placed in row 1 so they
   overlap; the roster is row 2 and is the only thing that scrolls
   into view.
   ------------------------------------------------------------ */
@media (max-width:1000px){
  body{overflow:auto}
  .select{
    height:auto;min-height:100svh;overflow:visible;
    grid-template-columns:minmax(0,1fr);
    /* A definite row, not minmax(...,1fr): the media inside is sized in
       percentages and a percentage height needs a definite ancestor, or
       it silently doesn't resolve and the rider collapses. */
    /* Three rows now: the lockup, the rider, the roster. The logo used to
       share row 1 with the rider and sit on top of him; it has a row of its
       own so it reads as a title above the picture instead. */
    grid-template-rows:auto 72svh auto;
    gap:0;
    /* Full bleed. The horizontal padding comes back on the children that
       still want it, so only the picture reaches the edges. */
    padding:0 0 clamp(16px,3vh,30px);
  }

  .stage{
    grid-area:2 / 1;
    height:100%;min-height:0;width:100%;
  }
  /* The clip and the still fill the width and crop off the top rather
     than letterboxing into a black box either side. `top` keeps his
     head in frame when the crop bites. */
  .stage .still,.stage video{object-fit:cover;object-position:50% 12%}

  .plate{
    grid-area:2 / 1;position:relative;      /* the fade anchors to this */
    align-self:end;z-index:6;pointer-events:none;
    padding:0 var(--pad) clamp(14px,3vh,26px);
    align-items:center;text-align:center;
  }
  .plate a,.plate button{pointer-events:auto}
  /* The fade the name sits on. Tall enough that the type never lands on
     a hard edge, and it stops short of the middle so the rider's face is
     never behind it. */
  .plate::before{
    content:'';position:absolute;left:0;right:0;bottom:0;
    height:min(46svh,340px);
    background:linear-gradient(to top,
      #0a0a0c 0%, rgba(10,10,12,.92) 22%, rgba(10,10,12,.6) 52%, transparent 100%);
    pointer-events:none;z-index:-1;
  }
  .wears{margin-left:auto;margin-right:auto}

  /* Tucked into the sides at mid-height now the plate owns the bottom. */
  .reel-nav{width:42px;height:42px;top:44%;bottom:auto;translate:0 -50%}
  .reel-nav.prev{left:6px}
  .reel-nav.next{right:6px}
  .reel-nav.prev:hover{transform:translateX(-2px)}
  .reel-nav.next:hover{transform:translateX(2px)}
  .slot-prev,.slot-next{scale:.9}

  .pick{grid-area:3 / 1;padding:10px var(--pad) 20px}
  .row{--lean:14px;transform:none}
  .cell .nm{opacity:1;font-size:7.5px}

  /* Its own row above the rider, still left-aligned. The top margin clears
     the fixed header, which the rider is free to run under but a logo in
     the flow is not. */
  .select > .ss{
    grid-area:1 / 1;
    /* The desktop rule takes it out of the flow with top/left offsets. Going
       back to position:relative does NOT drop those — they become a relative
       nudge, which was pushing the logo ~100px down (calc(104px - .5vh)) and
       double-indenting it by --pad. Clear them explicitly. */
    position:relative;top:auto;left:auto;z-index:7;
    justify-self:start;align-self:start;
    width:clamp(112px,30vw,150px);
    /* The header is fixed and has no height of its own — it is padding plus
       content, ~75px here. --nav-h is not set on this page, so the fallback
       below is the value that actually applies; measure before changing it. */
    margin:calc(var(--nav-h,76px) + 12px) 0 clamp(6px,1.4vh,14px) var(--pad);
    pointer-events:none;
  }
  .hint{position:static;text-align:center;margin:0 0 8px}
}
@media (max-width:560px){
  .who{font-size:clamp(26px,9vw,44px)}
}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms !important;transition-duration:.01ms !important}
}

/* ---------- the collaboration's own link ----------
   Sits under the thumbnails, quiet. It is not a rider's drop link and
   should not be dressed as one: the loud gradient pill is reserved for
   a rider's own thing, and two of them on one screen would be a
   competition rather than a hierarchy. */
.ep-link{
  align-self:flex-start;
  display:inline-flex;align-items:center;gap:10px;
  margin-top:clamp(12px,2vh,22px);
  padding:11px 18px;border-radius:999px;
  border:1px solid var(--line);background:rgba(0,0,0,.5);
  color:var(--muted);text-decoration:none;
  font-size:9.5px;letter-spacing:.22em;text-transform:uppercase;font-weight:700;
  transition:color .22s var(--ease), border-color .22s var(--ease),
             background .22s var(--ease);
}
.ep-link svg{
  width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round;
  transition:transform .28s var(--ease);
}
.ep-link:hover{color:var(--fg);border-color:var(--line-strong);background:rgba(0,0,0,.7)}
.ep-link:hover svg{transform:translateX(3px)}
.ep-link:focus-visible{outline:1px solid var(--fg);outline-offset:3px}
@media (prefers-reduced-motion:reduce){ .ep-link svg{transition:none} }
