/* Watch, full screen.

   Opening a clip gives it the whole viewport: the masthead, the nav and the
   search bar go, and the stage stops being a frame inside a page. Everything
   about the clip -- its title, whose it is, what is queued behind it -- is
   still there, one scroll down.

   Its own file because it is a mode rather than a component. The rules here
   only ever apply while a clip is open, and keeping them apart means the view
   they suppress does not have to know about them.

   Loaded after nilsportstech-network-v2.css, so these win on order where the
   two describe the same element. */

/* The page's own chrome, while a clip has the screen. Display rather than
   visibility: the header holds 100px of grid, and hiding it any other way
   leaves the stage starting a header's height down the page. */
body.nst-cinema .nst-head,
body.nst-cinema .nst-nav,
body.nst-cinema .nst-ticker,
body.nst-cinema .nst-watchview__topics { display: none; }

/* svh rather than vh. On a phone vh is the tallest the viewport ever gets --
   the address bar retracted -- so a 100vh stage sits a bar's height taller
   than the screen at rest, and the clip's own controls fall under the chin. */


/* A reel keeps its own shape. Cropping a 9:16 clip to fill a landscape screen
   throws away most of the frame and takes the athlete's head with it -- the
   whole clip stays, at its own ratio, and the blurred overscaled copy heroMedia
   puts behind it fills the space either side.

   The mirror still covers, because its whole job is to fill. */
.nst-wpanel__frame > video:not(.nst-hero__mirror),
.nst-wpanel__frame > iframe,
.nst-wpanel__frame > img:not(.nst-hero__mirror) {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; border: 0; z-index: 1;
}
.nst-wpanel__frame > .nst-hero__mirror {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0;
}

/* The feed. Every clip a screen of its own, one scrolled into the next.

   Its own scroller rather than the document's: a feed that owns its scrolling
   can snap without the page's own length -- the footer, the grid it replaced --
   having any say in where a clip lands. */
.nst-watchfeed {
  position: fixed; inset: 0; z-index: 30;
  overflow-y: auto; overscroll-behavior: contain;
  scroll-snap-type: y mandatory;
  background: #000;
}
.nst-watchfeed[hidden] { display: none; }

/* One clip, one screen. stop: always means a flick moves exactly one -- without
   it a hard swipe skates past three and lands between two. */
.nst-wpanel {
  position: relative; width: 100%; height: 100svh;
  scroll-snap-align: start; scroll-snap-stop: always;
  overflow: hidden; background: #000;
}
.nst-wpanel__frame { position: absolute; inset: 0; }

/* The hero's media player, on the clip. It runs the full width under the hero
   on the front page; here the panel is the full width, so it takes the foot of
   the screen and the wash above it keeps the type off the footage. */
/* Glass, not a shelf. The gradient ran to 97% at the foot, which is opaque --
   the clip stopped dead at the transport and the bar read as a grey strip laid
   over the film rather than part of it. Carrying less ink and blurring what is
   behind instead keeps the type legible while the footage still reads through,
   which is what the rest of the page's chrome does. */
.nst-wpanel .nst-playing {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 8;
  background: linear-gradient(#0000, rgba(6, 6, 10, .42) 40%, rgba(6, 6, 10, .62));
  backdrop-filter: blur(20px) saturate(130%);
  -webkit-backdrop-filter: blur(20px) saturate(130%);
  border: 0;
}
/* Nothing to blur behind, so the ink goes back up to stay readable. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nst-wpanel .nst-playing {
    background: linear-gradient(#0000, rgba(6, 6, 10, .86) 40%, rgba(6, 6, 10, .97));
  }
}

/* The conversation, in the panel rather than in the hero it came from. It runs
   up the right-hand side so it never crosses the title and byline on the left,
   and stops above the player at the foot.

   The hero's own rules place it against a 620px centre column that does not
   exist here, so those are restated rather than inherited. */
.nst-wpanel .nst-hero__chat {
  position: absolute; right: var(--gutter, 32px); left: auto;
  bottom: 148px; z-index: 7;
  display: flex; flex-direction: column; justify-content: flex-end;
  gap: 8px; width: min(340px, 46vw); max-height: 46vh; pointer-events: none;
}
.nst-wpanel .nst-hero__chat[hidden] { display: none; }

@media (max-width: 700px) {
  /* No room beside a phone-width clip: the remarks would sit on the athlete. */
  .nst-wpanel .nst-hero__chat { display: none; }
  /* Clear of the home indicator. Without the inset the player's own controls
     sit in the swipe-up strip, where a tap on the sound button is as likely to
     dismiss the browser as to unmute the clip. */
  .nst-wpanel .nst-playing { padding-bottom: env(safe-area-inset-bottom); }
  .nst-wpanel__over {
    padding: 96px var(--gutter, 20px) calc(124px + env(safe-area-inset-bottom));
  }
  /* Clear of the notch on the other end. */
  .nst-watchback { top: max(14px, env(safe-area-inset-top)); }
  .nst-watchrun { top: max(14px, env(safe-area-inset-top)); max-width: calc(100% - 130px); }
}

/* What the clip is, on its own foot rather than in a bar beneath it. The panel
   is the whole screen, so anything under it is on the next clip. */
.nst-wpanel__over {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 5;
  display: flex; flex-direction: column; align-items: flex-start; gap: 9px;
  /* Clear of the transport, which sits at the foot of the frame. */
  /* Clear of the player below it, which is taller than the bare transport
     this room was left for. */
  padding: 120px var(--gutter, 32px) 132px;
  background: linear-gradient(#0000, rgba(6, 6, 10, .55) 38%, rgba(6, 6, 10, .93));
  pointer-events: none;
}
/* The controls in it still work -- only the wash is see-through to the cursor. */
.nst-wpanel__over > * { pointer-events: auto; }
.nst-wpanel__title {
  margin: 0; font-family: var(--cond); font-weight: 700; line-height: 1;
  text-transform: uppercase; font-size: clamp(26px, 4.2vw, 52px);
  text-shadow: 0 2px 24px rgba(6, 6, 10, .8); max-width: 22ch;
}
.nst-wpanel__meta {
  font-family: var(--mono); font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; color: #c8c8d0;
}
/* The row spans the overlay so the pill has an edge to sit against. The
   overlay lays its children out flex-start, so this row was only as wide as
   its own contents and the pill ended up pressed against the athlete's name --
   two things of equal weight touching, and the eye could not tell whether the
   button belonged to the name or was the next thing along. */
.nst-wpanel__by { display: flex; align-items: center; gap: 14px; width: 100%; }
.nst-wpanel__who { min-width: 0; }
.nst-wpanel__name { font-family: var(--cond); font-size: 19px; font-weight: 700; text-transform: uppercase; }
.nst-wpanel__line { font-family: var(--mono); font-size: 10px; letter-spacing: .12em; color: #a4a4ac; }
/* Pushed to the far end: who it is on the left, what to do about it on the
   right. Costs no height -- the row was already there. */
/* Smaller than the page's own call to action. The orange button is sized for
   the bottom of a section -- 15px type in 15/28 padding -- and on a clip it
   read as a banner laid over somebody's film rather than a way into their app.
   Same colour, a third less of it. */
.nst-wpanel__app {
  flex: 0 0 auto; margin-left: auto;
  padding: 10px 18px; font-size: 12px; letter-spacing: .12em;
  border-radius: 999px;
  /* Its own layer. The panel arrives as a full-screen composite over video,
     and Safari painted the pill but not the words inside it until a scroll
     invalidated the tile -- so the button read as a blank orange lozenge on
     first sight. Promoting it makes the label part of a layer that is drawn
     when the panel is. */
  transform: translateZ(0);
}

/* The page still scrolls. This is a mode, not a modal: locking the body would
   cut off the queue underneath, which is what makes Watch a run of clips
   rather than one video with nowhere to go. */

/* The way out. A chevron in the corner and nothing else -- with the nav gone
   there is no chrome for a labelled button to belong to, and a pill reading
   ALL CLIPS over a full-screen clip is a caption on somebody's film.

   Fixed, so it survives the scroll down to the queue and back. */
/* The card that closes a run.

   A panel like any other, so the scroll that arrives at it is the same swipe
   that moved between clips -- and its parts come in a beat after it lands
   rather than being there when it does. The run has an ending; this is what
   the ending looks like. */
.nst-wend {
  position: relative; width: 100%; height: 100svh;
  scroll-snap-align: start; scroll-snap-stop: always;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 0 var(--gutter, 20px); text-align: center;
  background: radial-gradient(120% 90% at 50% 40%, #16161c 0%, #08080a 62%);
}
/* Each part a step behind the one above it: the label, then the count, then
   the line, then the way out. Slow enough to read as arriving. */
@keyframes nst-wend-rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
.nst-wend > * { animation: nst-wend-rise .55s cubic-bezier(.16,.84,.44,1) both; }
.nst-wend__kicker { animation-delay: .05s; }
.nst-wend__count  { animation-delay: .18s; }
.nst-wend__line   { animation-delay: .31s; }
.nst-wend__row    { animation-delay: .46s; }

.nst-wend__kicker {
  font-family: var(--mono); font-size: 10px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--orange, #ff4a15);
}
.nst-wend__count {
  font-family: var(--cond); font-weight: 700; line-height: .95;
  text-transform: uppercase; font-size: clamp(38px, 11vw, 84px);
}
.nst-wend__line {
  font-size: 15px; color: var(--muted, #a4a4ac); max-width: 26ch;
}
.nst-wend__row { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; padding-top: 10px; }
.nst-wend__btn {
  font-family: var(--cond); font-size: 13px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  background: var(--orange, #ff4a15); color: #0a0a0a;
  border: 0; border-radius: 999px; padding: 13px 22px; cursor: pointer;
}
/* The second way out is quieter than the first: watching it again is the
   thing the run just earned. */
.nst-wend__btn--ghost {
  background: none; color: var(--text, #f4f4f2);
  border: 1px solid rgba(244, 244, 242, .22);
}

/* Nothing moves for a reader who has asked for that. */
@media (prefers-reduced-motion: reduce) {
  .nst-wend > * { animation: none; }
}

/* What the run is, centred on the chevron's own line so it costs no height.

   Only drawn when a section handed its own run over -- the network's feed is
   not a countdown and has nothing to number. */
.nst-watchrun {
  position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 60;
  display: flex; align-items: baseline; gap: 10px; height: 44px;
  align-items: center;
  /* Clear of the chevron at either end, and never wrapping: it is one line
     with a 44px target beside it. */
  max-width: calc(100% - 160px); white-space: nowrap;
  pointer-events: none;
}
.nst-watchrun[hidden] { display: none; }
.nst-watchrun__label {
  font-family: var(--mono); font-size: 10px; letter-spacing: .16em;
  text-transform: uppercase; color: rgba(244, 244, 242, .72);
  overflow: hidden; text-overflow: ellipsis;
  text-shadow: 0 1px 10px rgba(6, 6, 10, .95);
}
/* The place it takes, in the section's own orange. */
.nst-watchrun__rank {
  font-family: var(--cond); font-size: 17px; font-weight: 700; line-height: 1;
  color: var(--orange, #ff4a15);
  text-shadow: 0 1px 10px rgba(6, 6, 10, .95);
}

.nst-watchback {
  position: fixed; top: 20px; right: var(--gutter, 32px); z-index: 60;
  display: inline-flex; align-items: center; justify-content: center;
  /* The target stays 44px for a thumb; the mark inside it is small. A bordered
     disc with a fat rounded chevron in it read as a toy button -- the frame
     was doing the work the mark should. */
  width: 44px; height: 44px; padding: 0;
  color: rgba(244, 244, 242, .82);
  background: none; border: 0; border-radius: 0; cursor: pointer;
  /* Legible over a lit gym floor without a disc behind it. */
  filter: drop-shadow(0 1px 10px rgba(6, 6, 10, .95));
  transition: color .18s ease, transform .18s ease;
}
/* Wide and shallow, drawn thin. The old one was 11px of 1.9 stroke with round
   joins, which at that size is a crayon stroke. */
.nst-watchback svg { width: 26px; height: 26px; }
.nst-watchback:hover { color: #fff; transform: translateY(2px); }
.nst-watchback:active { transform: translateY(3px); }
.nst-watchback:focus { outline: none; }
.nst-watchback:focus-visible { outline: 2px solid var(--orange, #ff4a15); outline-offset: 3px; }
.nst-watchback[hidden] { display: none; }

@media (max-width: 700px) {
  .nst-watchback { top: 12px; }
  .nst-watchrun { top: 12px; max-width: calc(100% - 120px); }
  .nst-watchrun__label { font-size: 9px; letter-spacing: .12em; }
  .nst-watchrun__rank { font-size: 15px; }
  .nst-watchback svg { width: 24px; height: 24px; }

  /* Room for the transport, and not much more.

     The block above this one sets the same padding, but it sits *before* the
     base rule in the sheet, so the base 132px won on source order and the
     phone value never applied. This block is after it.

     124px was left for a bar that starts 64px off the bottom and is 64px
     tall, so the caption finished at 712 on an 844 screen with a hand's
     width of black under it -- the words read as floating in the middle of
     the clip rather than sitting on its foot. */
  .nst-wpanel__over {
    padding-bottom: calc(76px + env(safe-area-inset-bottom));
  }
}

/* A post on X, framed where a clip would play.

   X sets its own width and grows to whatever the post needs, so the frame is
   centred at a readable measure rather than stretched across a desktop stage,
   and scrolls inside itself when a thread runs long. */
.nst-watch__post,
.nst-hero__video--post {
  position: absolute; z-index: 2;
  /* X sizes the frame to the post and leaves the rest of the height empty, so
     a top-aligned frame hangs a short post off the top of a tall screen with
     black under it. Centred on the stage instead -- the post sits where a clip
     would be. */
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 100%; max-width: 550px;
  /* Not the full stage height. X pins its card to the top of the frame it is
     handed, so a 100%-tall frame left a short post at the top of the screen
     over a field of black. Sized to the post and centred as a block. */
  height: auto; max-height: 92%;
  border: 0; display: block;
  background: transparent;
}

/* The full screen is always dark, whatever the page is.

   It is a black room with film in it -- there is no light version of that, and
   the copy sits directly on the footage. Everything here took the page's
   tokens, so in daylight the title, the athlete's name and the avatar initial
   turned near-black over a dark frame and vanished; the screenshot showed a
   headline you could only find by knowing it was there.

   The tokens are restated for this layer rather than each rule being chased,
   so anything added later is light by default too. */
:root[data-theme="light"] .nst-preview__cinema {
  --ink: #08080a;
  --panel: #0b0b0e;
  --card: #0e0e12;
  --pane: #14141a;
  --pane-lead: #191920;
  --line: #1c1c20;
  --line-strong: #26262c;
  --text: #f4f4f2;
  --muted: #a4a4ac;
  --dim: #6d6d76;
  --faint: #4a4a52;
  --edge: #2a2a30;
  --edge-strong: #2f2f36;
  --label: #8b8b93;
  --label-dim: #5c5c64;
  --well: #0a0a0a;
  --well-raised: #101014;
  --line-glass: rgba(255,255,255,.12);
  --line-glass-strong: rgba(255,255,255,.20);
  /* Over film, so the accent goes back to the bright one. */
  --orange: #ff4a15;
  color: #f4f4f2;
}
/* The few that name a colour rather than take the token. */
:root[data-theme="light"] .nst-preview__cinema
  :is(.nst-wpanel__title, .nst-wpanel__name, .nst-avatar__initial,
      .nst-preview__clip-title) {
  color: #f4f4f2;
}

/* The panel is film wherever it mounts, not only inside the preview.

   Everything above is scoped to .nst-preview__cinema -- the athlete preview's
   overlay. The network page builds the same .nst-wpanel markup into its own
   feed, which is not inside that container, so none of it applied there: the
   headline and the athlete's name name no colour of their own and took the
   page's near-black ink straight onto the clip. Opening a moment from the
   hero's WATCH button gave a title you could only read by knowing it was
   there.

   Scoped to the panel's own overlay instead, so it holds in both places and
   in whatever mounts it next. */
:root[data-theme="light"] .nst-wpanel__over {
  color: #f4f4f2;
  --text: #f4f4f2;
  --muted: #d8d8d4;
  --dim: #b4b4b0;
  --label: #c8c8c4;
  --orange: #ff4a15;
}
:root[data-theme="light"] .nst-wpanel__over
  :is(.nst-wpanel__title, .nst-wpanel__name, .nst-avatar__initial) {
  color: #f4f4f2;
}
:root[data-theme="light"] .nst-wpanel__over .nst-wpanel__meta { color: #d8d8d4; }
:root[data-theme="light"] .nst-wpanel__over .nst-wpanel__line { color: #c8c8c4; }

