/* The cinema, for the mobile app's fullscreen.

   Lifted from nilsportstech-athlete-preview.css, which draws the same screen on
   the network: a snap-scrolled reel of full-height clips, each keeping its own
   shape over a blurred copy of itself, with the copy and the transport laid on
   the frame rather than under it.

   Lifted rather than imported. That sheet is one part of a 1,945-line athlete
   panel built around a list of apps, and mobile.html loads none of it -- pulling
   it in would drag the whole panel onto a page that has no use for it. So this
   is the treatment on its own, prefixed .mcin so it cannot collide with the
   mobile app's own classes.

   Two differences from the network's cinema, both asked for:
     - no app button. The byline is the face and the name, nothing on the right.
     - the transport keeps its rewind and forward buttons, which the moments
       fullscreen already had and readers already use. */

.mcin {
  position: fixed; inset: 0; z-index: 2147483000;
  background: #000;
  font-family: 'Barlow', system-ui, -apple-system, sans-serif;
  /* Every colour stated, not inherited, and stated hard.

     This layer is a guest on a page with 117 stylesheets, one of which paints
     text black broadly enough to reach in here -- the headline and the byline
     came out near-black on a black stage, and walking the ancestors showed the
     colour already lost at .mcin itself. Specificity is not a fight worth
     having against a sheet this file cannot see, and nothing on a film screen
     should turn with the page behind it anyway. */
  color: #f4f4f2 !important;
  -webkit-text-fill-color: #f4f4f2 !important;
}
/* Every descendant, stated rather than inherited.

   An earlier pass wrote `color: inherit` here, meaning to propagate the light
   ink down. It did the opposite: `inherit` takes the parent's *computed* value,
   and with something upstream painting black that is what each child inherited
   -- and because the rule matches everything, it also beat .mcin__title's own
   colour further down the sheet. The quiet lines restate their greys after
   this. */
.mcin *:not(input):not(select) {
  color: #f4f4f2 !important;
  -webkit-text-fill-color: #f4f4f2 !important;
}
.mcin[hidden] { display: none; }

/* Close. Its disc is fixed dark glass whatever the page behind it does, so the
   chevron on it is stated light rather than inherited -- taking the page's ink
   put a near-black mark on a near-black disc in daylight. */
.mcin__close {
  position: absolute; top: calc(12px + env(safe-area-inset-top)); right: 14px; z-index: 4;
  width: 36px; height: 36px; display: grid; place-items: center; padding: 0;
  border-radius: 50%; cursor: pointer; color: #f4f4f2;
  background: rgba(8,8,10,.55); border: 1px solid rgba(255,255,255,.16);
}
.mcin__close svg { width: 19px; height: 19px; display: block; }

.mcin__reel {
  height: 100%; overflow-y: auto; overscroll-behavior-y: contain;
  scroll-snap-type: y mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
}
.mcin__reel::-webkit-scrollbar { display: none; }

/* The film fills the screen and the chrome lies on it.

   This is the Bytes TV cinema's screen, brought to the app: nothing is a black
   bar, nothing takes room away from the picture. A page or a track gets a
   column -- there is no picture to lay type over -- but a clip is the one kind
   of byte that fills its own frame, so the caption and the controls ride on the
   footage under a wash soft enough to keep it reading through. */
.mcin__panel {
  position: relative; height: 100%; scroll-snap-align: start; scroll-snap-stop: always;
  display: flex; align-items: center; justify-content: center; background: #000;
}
.mcin__frame { position: absolute; inset: 0; overflow: hidden; }
/* The clip keeps its own shape -- a reel is not cropped to fill a phone -- and
   a blurred, overscaled copy of its own poster fills what is left, so the black
   bands either side become part of the frame rather than a hole in it. */
.mcin__frame::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: var(--clip-wash, none) center / cover no-repeat;
  filter: blur(38px) saturate(140%) brightness(.5);
  transform: scale(1.3);
}
.mcin__frame video:not(.mcin__mirror),
.mcin__frame iframe {
  position: relative; z-index: 1;
  width: 100%; height: 100%; object-fit: contain; display: block; border: 0;
}
/* Upright film fills the screen instead of floating in it.

   `contain` is right for a wide clip -- cropping 16:9 to a portrait screen
   throws most of the picture away. It is wrong for a phone-shaped one: a
   720x1280 clip on a 390x844 screen painted 693px of film and left 151px of
   blurred mirror banding the top and bottom, so the picture sat in the middle
   of the screen with grey above and below it. A 9:16 clip on a 9:19.5 screen
   loses a sliver off the ends and gains the whole frame, which is the trade
   every reel on a phone makes.

   The JS marks the panel once it knows the clip's shape (see mount()); until
   then `contain` holds, so nothing jumps. */
/* Upright film filled the frame back when the frame was the whole screen and
   the two shapes nearly matched -- a 9:16 clip in a 9:19.5 panel lost a sliver
   and gained the picture. The frame is shorter now that the copy and the
   transport sit under it rather than on it, so filling would cut a real amount
   off the top and bottom of every clip. Everything is fitted; the blurred wash
   behind still fills what is left. */
.mcin__panel.is-tall .mcin__frame video:not(.mcin__mirror) {
  object-fit: cover;
}
/* The poster sits OVER the clip, not beside it: sharing position:relative and
   coming first put the still in the flow, so a clip played underneath a frozen
   frame while the blurred mirror behind it moved -- which reads as a video that
   will not play. Faded out once the clip is actually rendering. */
.mcin__still {
  position: absolute; inset: 0; z-index: 2;
  width: 100%; height: 100%; object-fit: contain; display: block; border: 0;
  transition: opacity 220ms ease;
}
/* The still is fitted the same way as the clip beneath it. It was always
   `contain`, which lined up while the video was too -- once upright film began
   filling the screen, the poster stayed letterboxed on top of it and the frame
   showed the same picture twice, offset, with the burnt-in caption doubled. */
.mcin__panel.is-tall .mcin__still {
  object-fit: cover;
}
.mcin__frame.is-playing .mcin__still { opacity: 0; pointer-events: none; }
/* The copy behind it covers rather than fits -- filling the bands is its whole
   job, so it is the one thing here that crops. */
.mcin__mirror {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover; display: block; border: 0;
  filter: blur(34px) saturate(140%) brightness(.52);
  transform: scale(1.2); pointer-events: none;
}

/* --- the copy, laid on the frame ---------------------------------------- */

/* On the film's own foot.

   Warm rather than blue-black and never reaching full strength: a wash that
   ends near-opaque draws a slab across the lower third and the picture appears
   to stop at the caption. Four stops rather than two, because the eye picks up
   the straight line where a two-stop gradient changes rate -- and that line is
   exactly the edge this is trying not to draw. */
.mcin__body {
  position: absolute; inset: auto 0 0 0; z-index: 2;
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 6px; pointer-events: none;
  /* Clear of the transport and the actions row beneath it. */
  padding: 88px 20px calc(104px + env(safe-area-inset-bottom));
  background: linear-gradient(
    to bottom,
    rgba(14, 10, 8, 0) 0%,
    rgba(14, 10, 8, .18) 30%,
    rgba(12, 9, 8, .46) 62%,
    rgba(10, 8, 7, .68) 100%);
}
.mcin__body > * { pointer-events: auto; max-width: 100%; }
/* Which bloc the clip came from. A label rather than a heading -- it sat at 11px
   in near-white directly above the caption, reading as the first line of the
   copy instead of the quiet note about where this is from. */
.mcin__flag {
  font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: .12em;
  color: rgba(244, 244, 242, .52) !important;
  -webkit-text-fill-color: rgba(244, 244, 242, .52) !important;
  text-transform: uppercase;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
/* The headline sizes to how much there is of it.

   Every caption was set at one size, so "Takeoff" and a ninety-five character
   sentence about a full game were drawn at the same weight -- the short one
   read as a headline and the long one as a wall of capitals with its ending
   clamped off. A caption is not a headline; it only looks like one when it is
   short. The JS measures the text and marks the panel, and each step down
   trades size for lines: fewer, bigger words at the top, more, smaller ones as
   the caption grows. */
/* A caption, not a headline.

   It was set as a condensed uppercase display face up to 36px -- a poster
   headline over someone's clip. What is actually in it is whatever the poster
   typed, usually a sentence with handles in it, and at that size two lines of
   it swallowed the lower third of the picture. Sentence case, ordinary weight,
   and small enough to read as a note on the film. */
.mcin__title {
  margin: 0; font-family: inherit; font-weight: 650;
  line-height: 1.3; text-transform: none; color: #f4f4f2;
  font-size: 15px; letter-spacing: -.01em;
  text-shadow: 0 1px 12px rgba(6,6,10,.85); max-width: 100%;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden; overflow-wrap: anywhere;
}
/* Around a line and a half: still a headline, with room for the whole of it. */
.mcin__panel[data-len="mid"] .mcin__title {
  font-size: 14.5px; line-height: 1.32; -webkit-line-clamp: 3;
}
/* A sentence. Sentence case rather than capitals -- ninety characters of
   uppercase is read letter by letter -- and six lines, which is the most that
   fits above the byline without pushing it into the transport. */
.mcin__panel[data-len="long"] .mcin__title {
  font-size: 14px; line-height: 1.34; font-weight: 600; -webkit-line-clamp: 3;
}
.mcin__said {
  font-size: 13px; line-height: 1.45; color: #a4a4ac !important; max-width: 52ch;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
/* Whose clip it is. No button on the right: this is the app already, so a link
   into it is a link to where the reader is standing. */
/* The byline: a small picture, the app's name, then the quiet meta. One line,
   the height of the text in it, rather than the 48px block this used to be. */
.mcin__by { display: flex; align-items: center; gap: 8px; width: 100%; min-width: 0; }
.mcin__by .mcin__name {
  font-family: inherit; font-size: 12px; font-weight: 750; letter-spacing: .02em;
  text-transform: none; line-height: 1; color: #f4f4f2 !important;
  -webkit-text-fill-color: #f4f4f2 !important;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-shadow: 0 1px 8px rgba(6,6,10,.9);
}
.mcin__by .mcin__meta { flex: 0 1 auto; min-width: 0; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.mcin__by .mcin__meta::before { content: "·"; padding-right: 6px; opacity: .7; }
/* The app's picture, at byline size. */
.mcin__face {
  width: 22px; height: 22px; flex: 0 0 auto;
  border-radius: 50%; object-fit: cover; display: block;
  background: #1b1b22;
  box-shadow: 0 1px 8px rgba(6,6,10,.9);
}
.mcin__who { min-width: 0; }
.mcin__name {
  font-family: 'Barlow Condensed', sans-serif; font-size: 19px; font-weight: 700;
  text-transform: uppercase; line-height: 1.05;
}
.mcin__sport {
  font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: .12em;
  color: #a4a4ac !important; text-transform: uppercase; padding-top: 3px;
}

/* --- the transport, on the clip ----------------------------------------- */

/* On the clip, not on a shelf under it.

   The wash ended at .92 of a near-black, which against a lit gym floor read as
   a slab laid across the foot -- the picture appeared to stop and a control
   panel took over. Warmer, softer, and four stops rather than two: the eye
   picks up the straight line where a two-stop gradient changes rate, and that
   line is exactly the edge this is trying not to draw. */
/* No tiles behind the marks.

   A generic rule in the app gives buttons a box-shadow and a
   `backdrop-filter: blur(10px) saturate(1.8)` -- a frosted tile that reads as a
   rounded box behind every icon. On a control panel that is right; on film it
   is exactly the boxiness this screen is trying not to have. The marks carry
   their own shadow and nothing else. */
.mcin .mcin__btn,
.mcin .mcin__act {
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  background: none !important;
  border: 0 !important;
  border-radius: 0 !important;
}

/* The plays and the date, on one quiet line under the caption. */
.mcin__meta {
  font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: .1em;
  color: rgba(244, 244, 242, .56) !important;
  -webkit-text-fill-color: rgba(244, 244, 242, .56) !important;
  text-transform: uppercase;
  text-shadow: 0 1px 8px rgba(6, 6, 10, .9);
}

/* What you can do about the byte: a row across the foot, on the film rather
   than on a shelf under it. Spread rather than packed -- three targets across a
   phone gives each its own space, so a thumb aiming at the chat does not catch
   the like. */
.mcin__acts {
  position: absolute; inset: auto 0 0 0; z-index: 4;
  display: flex; align-items: center; justify-content: space-around;
  padding: 0 20px calc(env(safe-area-inset-bottom) + 4px);
  background: none;
}
.mcin__act {
  flex: 1 1 0; min-width: 0; height: 44px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border: 0; background: none; cursor: pointer;
  color: #f4f4f2; font-family: inherit;
  filter: drop-shadow(0 1px 8px rgba(6, 6, 10, .9));
  transition: color .16s ease, transform .16s ease;
}
.mcin__act svg { width: 21px; height: 21px; display: block; }
.mcin__act:active { transform: scale(.9); }
/* Acted on, in the app's own orange. */
.mcin__act.is-on { color: #ff4a15; }
/* The tally beside the mark, absent at zero. */
.mcin__act-count {
  font-size: 12px; font-weight: 600; letter-spacing: .02em;
  font-variant-numeric: tabular-nums; color: inherit;
}
.mcin__act-count:empty { display: none; }

/* On the film, above the actions row. The wash from .mcin__body already carries
   both, so neither needs a ground of its own. */
.mcin__bar {
  position: absolute; inset: auto 0 calc(48px + env(safe-area-inset-bottom)) 0; z-index: 3;
  display: flex; align-items: center; gap: 12px;
  min-height: 44px;
  padding: 0 20px;
  background: none;
}
/* A mark on the film, not a disc of chrome.

   Five filled circles across the foot of a clip is a control panel; the same
   five marks carried on their own shadows are controls. The target stays the
   size it was -- only the tile behind it goes. */
.mcin__btn {
  flex: 0 0 auto; width: 34px; height: 34px; border: 0; border-radius: 50%;
  background: none; color: #f4f4f2;
  display: grid; place-items: center; cursor: pointer; padding: 0;
  position: relative;
  filter: drop-shadow(0 1px 8px rgba(6, 6, 10, .9));
  transition: transform .16s ease;
}
.mcin__btn:active { transform: scale(.9); }
/* The marks are drawn in the button's own colour.

   These are inline SVGs using fill/stroke, not text, so `color` never reached
   them -- and the app's light theme paints every element black. That was
   invisible while each button sat on a grey disc, but the discs were removed so
   the controls could sit on the film, and on a black bar the icons became black
   on black: present, positioned, and unseeable. currentColor ties them to the
   button, which the rules below already keep light. */
.mcin__btn svg { width: 15px; height: 15px; display: block; }
.mcin__btn svg,
.mcin__btn svg * {
  fill: currentColor !important;
  stroke: currentColor !important;
}
/* Except the paths that are meant to be open shapes rather than solid ones. */
.mcin__btn svg [fill="none"] { fill: none !important; }
/* The 10 rides under the arrow rather than beside it, so a skip button is the
   same disc as play and sound instead of a wider pill in the middle of them. */
.mcin__btn small {
  position: absolute; bottom: 5px; left: 0; right: 0;
  font-family: 'JetBrains Mono', monospace; font-size: 7px; line-height: 1;
  letter-spacing: 0; pointer-events: none;
}
.mcin__btn--skip svg { width: 17px; height: 17px; transform: translateY(-2px); }
.mcin__time {
  flex: 0 0 auto; font-family: 'JetBrains Mono', monospace; font-size: 10px;
  letter-spacing: .06em; color: #a4a4ac !important; min-width: 62px;
}
/* No rail. The unplayed remainder drawn as a light line ruled straight across
   the foot of the picture; only the part that has played is drawn, so the bar
   states progress without laying a line under the clip. */
/* The bar you actually drag.

   Four 34px buttons and a 62px clock left it 92px wide on a 390px screen --
   a quarter of an inch of travel for a minute of film, which is why the clip
   could not be scrubbed. The skips go (the frame is tappable and the bar is
   draggable), and what is left is a real length of track. */
.mcin__track {
  position: relative; flex: 1 1 auto; min-width: 0; height: 3px; cursor: pointer;
  background: rgba(244, 244, 242, .22); border-radius: 999px;
  /* A 3px line is not a touch target; the padding is transparent and only
     widens what a thumb can land on. */
  padding: 14px 0; background-clip: content-box;
  touch-action: none;
}
/* A 3px line is not a thumb target; the hit area reaches past it. */

.mcin__track > span {
  position: absolute; left: 0; top: 14px; height: 3px; width: 0;
  background: #ff4a15; border-radius: 999px; pointer-events: none;
}

/* Nothing behind the cinema scrolls while it is up. */
body.mcin-locked { overflow: hidden; }

/* --- the quiet lines, after the blanket above ---------------------------

   The rule that states every descendant light has to come first so nothing the
   app paints reaches in. These are the lines meant to sit back from the
   headline, so they restate their own grey after it -- same specificity, later
   in the sheet, which is what decides between two !important declarations. */
.mcin .mcin__flag  { color: rgba(244, 244, 242, .52) !important; -webkit-text-fill-color: rgba(244, 244, 242, .52) !important; }
.mcin .mcin__said  { color: #a4a4ac !important; -webkit-text-fill-color: #a4a4ac !important; }
.mcin .mcin__sport { color: #a4a4ac !important; -webkit-text-fill-color: #a4a4ac !important; }
.mcin .mcin__time  { color: #a4a4ac !important; -webkit-text-fill-color: #a4a4ac !important; }

/* --- daylight ------------------------------------------------------------

   The app's light theme carries `[data-theme="light"] * { color: #000
   !important }` -- every element on the page, painted black, in a sheet that
   loads after this one. It is the right rule for a white app and the wrong one
   for a film screen: the headline and the byline came out near-black on a black
   stage, and no amount of specificity below `*` with !important could win,
   because the two were tied and load order decided.

   So the theme is named here too. Same weight, later sheet -- and the cinema is
   the one surface in the app that does not turn with the theme, because the
   thing behind the type is a photograph rather than a page. */
:root[data-theme="light"] .mcin,
:root[data-theme="light"] .mcin *:not(input):not(select) {
  color: #f4f4f2 !important;
  -webkit-text-fill-color: #f4f4f2 !important;
}
:root[data-theme="light"] .mcin .mcin__flag  { color: rgba(244, 244, 242, .52) !important; -webkit-text-fill-color: rgba(244, 244, 242, .52) !important; }
:root[data-theme="light"] .mcin .mcin__said,
:root[data-theme="light"] .mcin .mcin__sport,
:root[data-theme="light"] .mcin .mcin__time  { color: #a4a4ac !important; -webkit-text-fill-color: #a4a4ac !important; }

/* The marks in the transport, for daylight.

   The theme paints `fill` and `stroke` black on every element, not just
   `color` -- and it does it in a sheet that loads after this one, so a plain
   `fill: currentColor` further up was overruled. The buttons used to sit on
   grey discs, which hid it; once the discs came off so the controls could sit
   on the film, the icons went black on a black bar and vanished.

   Named here for the same reason the copy is: same weight, later in the sheet,
   which is what decides between two !important declarations. */
:root[data-theme="light"] .mcin .mcin__act svg,
:root[data-theme="light"] .mcin .mcin__act svg *,
.mcin .mcin__act svg,
.mcin .mcin__act svg * {
  fill: none !important;
  stroke: currentColor !important;
}
:root[data-theme="light"] .mcin .mcin__act,
.mcin .mcin__act { color: #f4f4f2 !important; -webkit-text-fill-color: #f4f4f2 !important; }
:root[data-theme="light"] .mcin .mcin__act.is-on,
.mcin .mcin__act.is-on { color: #ff4a15 !important; -webkit-text-fill-color: #ff4a15 !important; }
:root[data-theme="light"] .mcin .mcin__meta { color: rgba(244,244,242,.56) !important; -webkit-text-fill-color: rgba(244,244,242,.56) !important; }

:root[data-theme="light"] .mcin .mcin__btn svg,
:root[data-theme="light"] .mcin .mcin__btn svg *,
.mcin .mcin__btn svg,
.mcin .mcin__btn svg * {
  fill: currentColor !important;
  stroke: currentColor !important;
}
/* Open shapes stay open -- these are drawn as outlines, not solids. */
:root[data-theme="light"] .mcin .mcin__btn svg [fill="none"],
.mcin .mcin__btn svg [fill="none"] { fill: none !important; }
/* The scrubber is a filled bar, not an icon, and keeps the app's orange. */
:root[data-theme="light"] .mcin .mcin__track > span,
.mcin .mcin__track > span { background: #ff4a15 !important; }

