/*
 * HiperCasino brand skin.
 *
 * Cloned from brand-cper.css rather than written fresh: that file carries the
 * full-height layout discipline, the sticky day-heading fix and the scrollbar
 * treatment that took a long time to get right, and all of it is brand-neutral.
 * What changes here is the palette and the page skin. Selectors are body.hiper.
 *
 * Live is red, never gold - live is a state, not a brand colour, and both other
 * brands make the same split.
 */

/*
 * CasinoPer — channel 2.
 *
 * Loaded after landing.css. Two jobs:
 *
 *   1. Repalette. The whole design keys off --red, so redefining that flips
 *      every badge, chip, button and ring to teal in one move.
 *   2. Relayout. index2 and this page share one stylesheet and one script, and
 *      a recolour alone reads as the same site with a filter on it. So the
 *      header, the schedule panel and the scoreboard are all rebuilt here:
 *      utility strip and icon nav above, CANLI / YAYINLANACAKLAR with a search
 *      box and a sport column, and the board in two columns of cards.
 *
 * Everything is scoped under body.hiper so nothing here can reach index2.
 */

body.hiper {
  /* CasinoPer teal, sampled from the logo artwork. */
  /*
   * Gold, not the skin's own yellow.
   *
   * pageskin-hiper.jpg uses roughly #ffe000 - right at poster scale on black,
   * hazard-tape at UI scale. Same hue pulled two steps toward amber and one step
   * down in lightness reads as gold leaf, and it lets the skin's brighter yellow
   * around the frame stay the highlight rather than competing with the chrome.
   */
  --red: #f4c542;
  --red-dim: #c9a132;
  --red-glow: rgba(244, 197, 66, .22);

  /*
   * Neutral near-black surfaces, teal reserved for the accent.
   *
   * These were green-tinted, on the theory that the panels should belong to the
   * same picture as the green skin. In practice a wide dark-green panel next to
   * a full-colour illustration reads as murky rather than as tinted - the green
   * is too desaturated to look deliberate and too present to look neutral, and
   * it made the player surround in particular look dirty.
   *
   * Going fully neutral fixed the murk but overshot - flat black next to this
   * artwork looked like a hole rather than a panel. These sit between: clearly
   * green, but dark enough that the colour reads as depth instead of as a wash.
   * Teal still means one thing only - interactive, or CasinoPer.
   */
  /*
   * Two tones, not one. Panels sit at --surface, the controls inside them a
   * shade lighter at --surface-2 - that step is what gives a panel depth. A
   * single flat colour is why the previous pass read as a slab however dark or
   * light it was set.
   */
  --bg: #05070c;
  --surface: #0a0f18;
  --surface-2: #111827;
  --surface-3: #18202e;
  --line: #1e2735;
  --line-soft: #141b26;

  --fg: #ffffff;
  /*
   * Effectively white. Two earlier passes lifted these part-way and both still
   * read as grey next to full-strength text - including inside the match modal,
   * where the stat labels, coach lines and shirt numbers all sit on --fg-mute.
   * There is no lightness gap left to carry hierarchy here; size and weight do
   * it instead.
   */
  --fg-dim: #ffffff;
  --fg-mute: #ecf1f8;
}

/*
 * The backdrop.
 *
 * No scrim: the artwork is shown at full strength, the way index2 shows its
 * own. It went through two worse versions first - a gradient that faded to
 * flat, which left a hard band across the page where it ran out, then a
 * constant wash, which was even but muddied the artwork for no gain.
 *
 * What makes bare artwork safe here is that nothing on this page sits directly
 * on it any more. Every surface carries its own translucent panel - the utility
 * strip, the header, the player, the schedule rail, the live-scores card and
 * the footer - so the skin only ever shows through in the outer gutters, which
 * is exactly where its own promotional artwork lives. That was not true while
 * the CANLI SKOR TABLOSU board was here: its heading, league chips and pager
 * had no backdrop of their own and needed the wash to stay legible. Removing
 * the board is what made this possible. If a bare-text surface is ever added
 * back outside a panel, it will need either a panel or the wash returned.
 */
body.hiper {
  background: #05070c url('/pageskin-hiper.jpg') no-repeat center top;
  background-size: cover;
  background-attachment: fixed;
}

/* Teal is bright; white-on-teal loses the contrast red carried. */
body.hiper .btab.on,
body.hiper .mtab.on,
body.hiper .pgr-n.on { color: #04140d; }
body.hiper .btab u.lv { color: #04140d; }

/* "On air" is not a brand colour. Live stays red on both pages - recolouring it
   teal here would make it read as one more accent on an already teal page. */
body.hiper .livetag { background: rgba(225, 29, 72, .92); }
body.hiper .hh-live, body.hiper .lh-live { background: #e11d48; color: #fff; }
body.hiper .mrow2.islive { box-shadow: inset 2px 0 0 #e11d48; background: rgba(225,29,72,.07); }
body.hiper .mrow2.islive:hover { background: rgba(225,29,72,.12); }
body.hiper .st-form .fp.l { background: #e11d48; }
body.hiper .q.live { background: #e11d48; border-color: #e11d48; color: #fff; }

/* ---- utility strip -------------------------------------------------------- */

.topbar {
  background: rgba(3, 14, 11, .82);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line-soft);
  font-size: 12px;
}
.topbar-in {
  max-width: var(--max); margin: 0 auto; padding: 0 16px;
  height: 28px; display: flex; align-items: center; gap: 16px;
}
.topbar .addr { color: var(--fg-mute); letter-spacing: .01em; }
.topbar .addr a {
  color: var(--red); font-weight: 700; text-decoration: none;
  letter-spacing: .04em;
}
.topbar .addr a:hover { text-decoration: underline; }
/* Socials move up here out of the header, which the icon nav now fills. */
.topbar .social { margin-left: auto; display: flex; gap: 4px; }
.topbar .social a {
  width: 26px; height: 26px; border: 0; background: none;
  display: grid; place-items: center; border-radius: 6px;
  color: var(--fg-mute);
}
.topbar .social a svg { width: 15px; height: 15px; }
.topbar .social a:hover { color: var(--red); background: rgba(244, 197, 66,.12); }

/* ---- header -------------------------------------------------------------- */

body.hiper .hdr { background: rgba(5, 22, 17, .78); }
/* 76px put the header's bottom edge across the page skin's own "ÖZEL
   BONUSLAR" / "CANLI BAHİSLER" headline in the right gutter, which read as a
   rendering fault rather than two layers. 60px clears it. */
body.hiper .hdr-in {
  height: 60px; gap: 22px;
}
/* Scaled down from the 40px this replaced, in step with the shorter header;
   the logo is a 210x44 PNG so it keeps its proportions. */
body.hiper .logo img { height: 32px; width: auto; display: block; }

/* Icon over label, as on the main site. */
.iconnav {
  margin-left: auto;
  display: flex; align-items: center; gap: 4px;
}
.iconnav a {
  display: grid; justify-items: center; gap: 5px;
  /* Tightened from 7px 13px along with the shorter header, so the icon and
     its label still clear the top and bottom edges instead of touching them. */
  padding: 4px 12px; border-radius: 9px;
  text-decoration: none; color: var(--fg-dim);
  font-size: 10px; font-weight: 700; letter-spacing: .05em;
  white-space: nowrap;
  transition: color .12s, background .12s;
}
.iconnav a svg { width: 19px; height: 19px; }
.iconnav a:hover { color: var(--red); background: rgba(244, 197, 66,.1); }

/* The header's ÜYE OL / GİRİŞ YAP pair has been removed - it simulated a login
   this site does not have - so the rules that sized it inside .hdr-in went with
   it. The icon nav above and the utility strip carry the real links. */

@media (max-width: 1100px) {
  .iconnav a span { display: none; }
  .iconnav a { padding: 8px 10px; }
}
@media (max-width: 820px) {
  body.hiper .hdr-in { height: auto; padding: 10px 14px; flex-wrap: wrap; gap: 12px; }
  .iconnav { order: 3; margin-left: 0; width: 100%; overflow-x: auto; }
  .topbar .addr { font-size: 11px; }
}

/* ---- schedule panel ------------------------------------------------------ */

/* Wider than index2's 290px: this panel now carries a sport column and a search
   box as well as the list. */
/* margin-top: with the broadcaster strip removed, .app centres hero-in in
   whatever space is left, which can be none on a short window - hero-in would
   then sit flush against the header with its top border touching the
   header's bottom border. A small fixed gap guarantees they never meet. */
/*
 * 320, not 372.
 *
 * The content column is pinned at 1076px because that is the width of the page
 * skin's central dark panel - anything wider covers the artwork in the gutters,
 * which has to stay visible. So the only width left to give the video is the
 * rail's, and the rail had spare: its sport column hides itself when there is
 * nothing to filter, and fixture rows ellipsise long names either way.
 */
body.hiper .hero-in { grid-template-columns: minmax(0, 1fr) 288px; }

/* .rail-hd and its .rtab buttons are index2's; this page's markup no longer has
   the row, so the rules that sized it here went with it. */

.mpanel { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
/* A class selector outranks the UA [hidden] rule, so without this #mpanel kept
   its flex layout while hidden - landing.js swaps it out for SIRALAMA, and the
   sub-tabs and search box stayed on screen with the standings table rendering
   into whatever space was left, which is what threw its sticky header off. */
.mpanel[hidden] { display: none; }

/* CANLI / YAYINLANACAKLAR. index2 runs live and upcoming together in one
   chronological list on purpose; splitting them is one of the things that makes
   this page read as its own. */
.mtabs {
  /*
   * The rail's only row now.
   *
   * SIRALAMA came down here first, when the row above still held MAÇLAR and
   * SOHBET. SOHBET went, that row was left with a single tab and nothing to
   * switch to, and the schedule stopped being something you select at all -
   * CANLI and YAYINLANACAKLAR already are the schedule. So the row went.
   *
   * Three columns here, four in the stacked layout below: SKORLAR only exists
   * where the scores card is behind a tab, and holding a fourth column open for
   * a button that is display:none would leave a quarter of the bar empty.
   *
   * Weighted, not equal. YAYINLANACAKLAR is more than twice the length of the
   * next longest label, and equal shares wrapped it onto a second line - which
   * would put back the two-row bar this change exists to remove.
   */
  display: grid; grid-template-columns: 0.85fr 1.4fr 0.9fr;
  border-bottom: 1px solid var(--line);
}
/* A class selector outranks the UA [hidden] rule, so a hidden .mtabs would
   otherwise keep its grid layout and stay on screen - the same trap #mpanel
   fell into. Nothing hides the bar today; the rule stays so that anything that
   does in future does not have to rediscover this. */
.mtabs[hidden] { display: none; }
.mtb {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 11px 4px; border: 0; background: none; cursor: pointer;
  /* Three labels in a 320px rail leaves little room; the type is a shade
     smaller and the tracking tighter than the two-tab version needed. nowrap
     because a label that no longer fits has to show as an overflow, not
     silently become a second line - a second line here is the exact thing this
     bar was rebuilt to get rid of. */
  white-space: nowrap;
  font-family: inherit; font-size: 10.5px; font-weight: 800; letter-spacing: .04em;
  color: var(--fg-mute);
  border-bottom: 2px solid transparent;
  transition: color .12s, border-color .12s, background .12s;
}
.mtb:hover { color: var(--fg-dim); background: rgba(255,255,255,.03); }
.mtb.on { color: var(--fg); border-bottom-color: var(--red); }
.mtb u {
  text-decoration: none; font-size: 10px; font-weight: 700;
  padding: 1px 6px; border-radius: 20px;
  background: var(--surface-3); color: var(--fg-dim);
}
.mtb u:empty { display: none; }
.mtb.on u { background: var(--red); color: #04140d; }
/*
 * The CANLI pip is red whether or not the tab is selected.
 *
 * It used to dim to --fg-mute when unselected, which on the old green palette
 * came out as a green dot - so the one element on the page that means "on air"
 * changed colour depending on which tab you happened to be looking at. The tab
 * itself already shows selection through its label and underline; the pip is
 * stating a fact about the fixtures, not about the tab.
 */
.mtb .pip { width: 6px; height: 6px; border-radius: 50%; background: #e11d48; }

.rsearch {
  position: relative;
  padding: 9px 10px;
  border-bottom: 1px solid var(--line-soft);
}
.rsearch svg {
  position: absolute; left: 21px; top: 50%; transform: translateY(-50%);
  width: 14px; height: 14px; color: var(--fg-mute); pointer-events: none;
}
.rsearch input {
  width: 100%; padding: 8px 10px 8px 30px;
  /* On the palette, one step below the panel so the field reads as inset. */
  background: var(--bg);
  border: 1px solid var(--line); border-radius: 8px;
  color: var(--fg); font: inherit; font-size: 12.5px;
  -webkit-appearance: none; appearance: none;
}
.rsearch input::placeholder { color: var(--fg-mute); }
.rsearch input:focus {
  outline: none; border-color: var(--red-dim);
  box-shadow: 0 0 0 3px var(--red-glow);
}
/* Chrome draws its own clear button in the wrong colour on a dark field. */
.rsearch input::-webkit-search-cancel-button { -webkit-appearance: none; }

/* List plus the sport column beside it. */
.mbody { display: flex; min-height: 0; flex: 1 1 auto; }

.sportrail {
  flex: 0 0 auto;
  width: 52px;
  display: flex; flex-direction: column;
  border-right: 1px solid var(--line-soft);
  overflow-y: auto;
  scrollbar-width: none;
}
.sportrail::-webkit-scrollbar { width: 0; }
.sportrail[hidden] { display: none; }
.sp {
  position: relative;
  flex: 0 0 auto;
  height: 46px;
  display: grid; place-items: center;
  border: 0; background: none; cursor: pointer;
  color: var(--fg-mute);
  border-bottom: 1px solid var(--line-soft);
  border-left: 2px solid transparent;
  transition: color .12s, background .12s, border-color .12s;
}
.sp:hover { color: var(--fg-dim); background: rgba(255,255,255,.03); }
.sp.on { color: var(--red); border-left-color: var(--red); background: rgba(244, 197, 66,.08); }
.sp svg { width: 20px; height: 20px; }
.sp .sp-all { font-size: 9px; font-weight: 800; letter-spacing: .05em; }
/* Count in the corner, small enough not to compete with the icon. */
.sp u {
  position: absolute; top: 5px; right: 5px;
  text-decoration: none; font-size: 9px; font-weight: 700;
  color: var(--fg-mute);
}
.sp.on u { color: var(--red); }

body.hiper .rail-body { flex: 1 1 auto; min-width: 0; }

/*
 * The crest pair is left exactly as landing.css draws it: home crest, "v", away
 * crest, together at the front of the row.
 *
 * An earlier version here tried to push the two crests out to opposite edges of
 * the row, score-style. It hid the away crest and the "v" to do it - but never
 * actually repositioned the away crest, so the second team's badge simply
 * vanished from every fixture. Splitting that pair needs the row rebuilt in the
 * markup, not a column tweak, and it is not worth losing a badge over.
 */

/* ---- the stacked layout -------------------------------------------------- */

/*
 * One column, and the tab bar directly under the player.
 *
 * Wide, this page is two columns: the player with the live-scores card under it
 * on the left, the schedule rail on the right. Stacked, those become four
 * blocks in a single column, and in source order the card lands between the
 * player and the rail - so the tab bar that runs the whole schedule sat about
 * 500px down the page, below a scores block nobody had asked for. That is what
 * the owner's screenshot is pointing at.
 *
 * The fix is ordering, not a second copy of the markup: `display: contents`
 * dissolves .player-col so its three children become grid items of .hero-in
 * alongside .rail-wrap, and the four can then be ordered freely. .hero-in is
 * already `gap: 0`, so flattening introduces no seam.
 *
 * Everything here is inside the media query on purpose. Above the breakpoint
 * .player-col is a flex column whose whole job is to hand its leftover height
 * to the scores card - that is what keeps the wide layout gapless - and
 * `display: contents` would destroy it. The two layouts want opposite things
 * from the same element, which is exactly what a media query is for.
 */
@media (max-width: 980px) {
  /*
   * `align-content: start` and no gap, both because there are four rows here
   * now instead of two.
   *
   * .hero-in is `flex: 1 1 auto` inside .app, so on a window taller than the
   * content it grows - and a grid taller than its auto rows stretches those
   * rows to fill it. With two rows that slack landed inside .player-col, where
   * its own flex column swallowed it. Flattened into four, it came out as a
   * ~36px band between every block: one under the caption strip, one under the
   * tab bar, one above the scores card. Packed to the start, each block is the
   * height of its own content and whatever is left is simply the end of the
   * page. landing.css also opens a 14px gap between grid items below 640; that
   * was a seam between two panels and is now a seam between four, so it goes -
   * the card keeps its own 8px margin, which is the one separation that means
   * something.
   *
   * The rows are stated rather than left implicit so the slack has one named
   * destination: the last one, which is the scores card. An `fr` track resolves
   * before align-content gets a look in, so there is no free space left to
   * stretch the first three with - the player, the caption strip and the tab
   * bar each stay exactly as tall as their content, and in the SKORLAR view the
   * card grows to the bottom of the window instead of floating above a band of
   * page artwork. In the other views row four is simply unused and the page
   * ends where its content does.
   */
  body.hiper .hero-in {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto auto minmax(0, 1fr);
    gap: 0;
  }

  /* The fourth tab appears with the stacked layout that needs it. Tighter type
     and padding than the three-tab bar, because 390px has to hold one more
     label than 320px did. */
  body.hiper .mtabs { grid-template-columns: 0.78fr 1.46fr 0.9fr 0.86fr; }
  body.hiper .mtb { padding: 11px 2px; font-size: 10px; letter-spacing: .01em; }

  body.hiper .player-col { display: contents; }
  body.hiper .screen { order: 1; }
  body.hiper .under { order: 2; }
  body.hiper .rail-wrap { order: 3; }
  body.hiper .feat { order: 4; }

  /* .player-col was painting the surface behind the caption bar; with the box
     gone the strip needs its own, or the page skin shows through between the
     video and the tabs. */
  body.hiper .under { background: #0a0f18; }

  /*
   * The rail sizes to its content here, instead of filling a fixed box.
   *
   * landing.css gives .rail-wrap a 300px height below 820 and absolutely
   * positions .rail inside it, which is how the rail matches the player's
   * height in the two-column layout. Stacked, that box is a liability: with
   * SKORLAR selected the rail holds nothing but the tab bar, and the fixed
   * height would leave ~250px of empty panel between the tabs and the scores
   * card. Letting it hug its content means each panel is as tall as it needs to
   * be, and the list gets a viewport-relative cap instead - which is the same
   * bound expressed against the thing that actually constrains it.
   */
  body.hiper .rail-wrap { height: auto; min-height: 0; }
  body.hiper .rail { position: static; }
  body.hiper .rail-body { max-height: 46vh; }
  body.hiper .stand-body { max-height: 46vh; }

  /*
   * The scores card, behind its tab.
   *
   * A class rather than the `hidden` attribute, because landing.js uses
   * `hidden` for a different question - "there is nothing to list" - and the
   * two have to be able to disagree. It also means this rule can be scoped to
   * the stacked layout and simply not exist above the breakpoint, where the
   * card is a permanent panel and the tab that would hide it is not offered.
   */
  body.hiper .feat.tab-off { display: none; }
}

/* Above the breakpoint the card holds the left column open on its own, so
   there is nothing to select and a fourth tab would only be a way to empty
   that column. The other three keep the row. */
@media (min-width: 981px) {
  body.hiper #tab-scores { display: none; }
}

/* ---- featured live match ------------------------------------------------- */

.feat {
  margin: 10px 0 0;
  background: rgba(11, 38, 32, .82);
  backdrop-filter: blur(6px);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 12px 14px 13px;
}
.feat[hidden] { display: none; }

.ft-hd {
  display: flex; align-items: center; gap: 8px;
  padding-bottom: 10px; margin-bottom: 11px;
  border-bottom: 1px solid var(--line-soft);
}
.ft-lg {
  font-size: 11.5px; font-weight: 700; letter-spacing: .04em;
  color: var(--fg-dim); text-transform: uppercase;
}
.ft-round {
  font-style: normal; font-size: 11px; color: var(--fg-mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ft-min {
  margin-left: auto; flex: 0 0 auto;
  font-size: 11px; font-weight: 800; letter-spacing: .04em;
  padding: 3px 9px; border-radius: 20px;
  background: #e11d48; color: #fff;
}

.ft-row {
  display: grid; grid-template-columns: minmax(0,1fr) auto minmax(0,1fr);
  align-items: center; gap: 12px;
}
.ft-team { display: flex; align-items: center; gap: 10px; min-width: 0; }
.ft-team.r { flex-direction: row-reverse; }
.ft-team img { width: 38px; height: 38px; object-fit: contain; flex: 0 0 auto; }
.ft-team b {
  font-size: 14px; font-weight: 700; color: var(--fg);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ft-score { display: grid; justify-items: center; gap: 2px; flex: 0 0 auto; }
.ft-score b {
  font-size: 26px; font-weight: 800; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.ft-score span { font-size: 10.5px; color: var(--fg-mute); }

.ft-venue {
  margin: 9px 0 0; text-align: center;
  font-size: 11px; color: var(--fg-mute);
}

.ft-stats { margin-top: 12px; display: grid; gap: 9px; }
.ft-st-top {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; margin-bottom: 4px;
}
.ft-st-top b { font-variant-numeric: tabular-nums; color: var(--fg); }
.ft-st-top span { flex: 1 1 auto; text-align: center; color: var(--fg-mute); }
.ft-st-bar { display: flex; height: 4px; border-radius: 3px; overflow: hidden; gap: 2px; }
.ft-st-bar i.h { background: var(--red); }
.ft-st-bar i.a { background: var(--surface-3); }

.ft-more {
  margin-top: 13px; width: 100%;
  padding: 9px; border-radius: 9px;
  background: rgba(244, 197, 66, .1);
  border: 1px solid var(--red-dim); color: var(--red);
  font: inherit; font-size: 12px; font-weight: 700; letter-spacing: .04em;
  cursor: pointer;
  transition: background .12s;
}
.ft-more:hover { background: rgba(244, 197, 66, .2); }

@media (max-width: 560px) {
  .ft-team b { font-size: 12px; }
  .ft-team img { width: 30px; height: 30px; }
  .ft-score b { font-size: 21px; }
}

/* ---- live scores (inside .feat, under the featured match) ---------------- */

.lsc {
  margin-top: 13px; padding-top: 12px;
  border-top: 1px solid var(--line-soft);
}

.lsc-hd {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 6px;
}
/* Same weight as .board-hd h2, so the two headers read as one system. */
.lsc-hd h3 {
  display: flex; align-items: center; gap: 8px; margin: 0;
  font-size: 12px; font-weight: 800; letter-spacing: .11em; color: var(--fg-dim);
}
.lsc-n { margin-left: auto; font-size: 11px; color: var(--fg-mute); }

/*
 * The favourites toggle, at the end of the card header.
 *
 * This card has no filter row of its own and cannot borrow the rail's tab bar:
 * above 980px it is a permanent panel with no tab at all, and below it the bar
 * is a four-column grid already at the limit of what 390px will hold on one
 * line. So the toggle lives in the header of the list it filters - the same
 * relationship index2's FAVORİLER chip has to its board, on the surface this
 * page actually has. See liveScoresNode() in landing.js.
 *
 * After .lsc-n rather than before it, because .lsc-n carries the margin-left
 * that pushes this end of the header right; putting a second auto margin in
 * front of it would split the gap instead of closing it.
 *
 * Gold, as on index2 - teal is this page's "interactive / CasinoPer" and red is
 * "on air", and a shortlist is neither.
 */
.lsc-fav {
  display: inline-flex; align-items: center; gap: 5px;
  margin-left: 8px; padding: 3px 9px 3px 7px;
  border: 1px solid rgba(242, 183, 5, .38); border-radius: 20px;
  color: var(--gold); cursor: pointer;
  font-size: 10px; font-weight: 800; letter-spacing: .06em;
  white-space: nowrap;
  transition: color .12s, background .12s, border-color .12s;
}
.lsc-fav svg { width: 12px; height: 12px; flex: 0 0 12px; display: block; pointer-events: none; }
.lsc-fav svg path {
  fill: none; stroke: currentColor; stroke-width: 1.9;
  stroke-linejoin: round; stroke-linecap: round;
}
.lsc-fav b { font-weight: 800; }
.lsc-fav u { text-decoration: none; opacity: .75; }
.lsc-fav:hover { border-color: rgba(242, 183, 5, .75); }
/* Near-black on gold: white on #f2b705 is under 2:1. */
.lsc-fav.on {
  background: var(--gold); border-color: var(--gold); color: #1b1400;
}
.lsc-fav.on svg path { fill: currentColor; }
.lsc-fav:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/*
 * Below this the header is three items on one line inside a rail 320-390px
 * wide, which the word FAVORİLER does not survive. The chip keeps its star and
 * its count and drops the label - the star is the same mark the rows carry, so
 * what it does is still legible - and the title attribute set in landing.js
 * still names it.
 */
@media (max-width: 560px) {
  .lsc-fav { padding: 3px 7px; margin-left: 6px; }
  .lsc-fav b { display: none; }
}

/* Scrollbar approach copied from .rail-body in landing.css: touching any single
   ::-webkit-scrollbar part makes Chrome drop its overlay scrollbar for the
   legacy widget, which draws a pale track and stepper arrows unless every
   part - track, thumb, hover, buttons and corner - is accounted for here. */
.lsc-list {
  max-height: 300px; overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: #303e4e transparent;
}
.lsc-list::-webkit-scrollbar { width: 10px; height: 10px; }
.lsc-list::-webkit-scrollbar-track { background: transparent; }
.lsc-list::-webkit-scrollbar-thumb {
  background: #303e4e; border-radius: 999px;
  border: 3px solid transparent; background-clip: content-box;
}
.lsc-list::-webkit-scrollbar-thumb:hover { background: #45596e; background-clip: content-box; }
.lsc-list::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
.lsc-list::-webkit-scrollbar-corner { background: transparent; }

/* A row that behaves like a table row, not a button - no chrome, no default
   button font, the grid does the alignment. */
.lsc-row {
  width: 100%; display: grid;
  grid-template-columns: 32px minmax(0, 1fr) 58px minmax(0, 1fr);
  align-items: center; gap: 8px;
  padding: 8px 10px; margin: 0;
  border: 0; border-bottom: 1px solid var(--line-soft); border-radius: 0;
  background: none; color: inherit;
  font: inherit; text-align: left; cursor: pointer;
  transition: background .12s;
}
.lsc-row:last-child { border-bottom: 0; }
.lsc-row:hover { background: rgba(255, 255, 255, .03); }

/* <u> for the minute, so it needs its underline stripped explicitly. */
.lsc-min {
  text-decoration: none; text-align: center;
  font-size: 10.5px; font-weight: 700; color: var(--fg-mute);
  font-variant-numeric: tabular-nums;
}

/* Crest-and-name pair. The two sides are mirror images of each other in the
   markup (h: crest then name, a: name then crest) rather than sharing one DOM
   order and a reversing class - same idea as .ft-team/.ft-team.r, just spelt
   out in the HTML instead of in a modifier, because the row is built by a
   template rather than by hand. */
.lsc-side { display: flex; align-items: center; gap: 6px; min-width: 0; }
/*
 * Both sides pack against the score with the crest innermost, so the two mirror
 * each other and the score reads as the pivot.
 *
 * `order` on the crest, not `row-reverse`. The home markup is crest-then-name,
 * so reversing the axis did put the crest by the score - but it also reverses
 * what `justify-content` means, and the `flex-end` paired with it therefore
 * packed the home team to the LEFT of its column. Its distance from the score
 * then varied with every team-name length and nothing lined up vertically.
 */
.lsc-side.h { justify-content: flex-end; text-align: right; }
.lsc-side.h .lsc-c { order: 2; }
.lsc-side.a { justify-content: flex-start; text-align: left; }
.lsc-side b {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12px; font-weight: 600; color: var(--fg);
}
.lsc-c { width: 16px; height: 16px; flex: 0 0 16px; object-fit: contain; }

.lsc-sc {
  text-align: center; font-size: 13px; font-weight: 700;
  font-variant-numeric: tabular-nums; color: var(--fg);
}

/*
 * The compact row stacks, rather than being squeezed narrower.
 *
 * Six things - minute, crest, name, score, crest, name - on one line inside a
 * card the width of a phone leaves each name about 120px at 390 and 70px at
 * 320, so the fixed columns keep their space and the flexible name columns are
 * the only ones that give. Measured on the live-scores stub at 390px: four of
 * fourteen names clipped, "Maziya Sports & Recreation" down to 77% of its own
 * width, and at 320px seven of fourteen with "Borussia Mönchengladbach" at 51%.
 * Shrinking the columns to 26px/44px and the type to 11px, which is what this
 * block used to do, only moves the cliff a few pixels - it does not remove it,
 * because the row is simply the wrong shape at this width.
 *
 * Minute, score and competition on the first line, then a line per team. Each
 * name gets the full width of the card less one crest, so nothing is ever
 * abbreviated to make room for a badge.
 *
 * The scoreline moves up onto the meta line rather than being dropped.
 *
 * index2's board row solves this by hiding the shared score and printing each
 * side's goals at the end of its own line, and the obvious move was to copy it
 * - landing.js exports sideGoals() for exactly that. But it only calls it from
 * matchRow(), index2's row; index3's liveScoresRow() builds crest and name and
 * nothing else, so there is no .m-goals in this markup to reveal. Styling one
 * anyway hid the only scoreline the row has and left the SKORLAR tab showing
 * seven live matches with no scores on any of them. Beside the minute it is
 * still read as match state, and it costs no vertical space.
 */
@media (max-width: 560px) {
  .lsc-row {
    grid-template-columns: auto auto minmax(0, 1fr);
    grid-template-areas:
      "min  sc   lg"
      "home home home"
      "away away away";
    gap: 3px 8px; padding: 8px 10px;
  }
  .lsc-min { grid-area: min; text-align: left; font-size: 9.5px; }
  .lsc-sc { grid-area: sc; text-align: left; font-size: 12.5px; }
  .lsc-lg { grid-area: lg; justify-self: end; }
  .lsc-side.h { grid-area: home; }
  .lsc-side.a { grid-area: away; }

  /* Both lines read crest then name. The mirroring exists only to make the two
     sides point at a score sitting between them, and there is no longer a
     score between them. */
  .lsc-side.h, .lsc-side.a {
    flex-direction: row; justify-content: flex-start; text-align: left;
  }
  .lsc-side.h .lsc-c { order: 0; }
  .lsc-side.a .lsc-c { order: -1; }
  .lsc-side b { font-size: 12px; }
}

/*
 * Last line of defence: the crest goes before the name does.
 *
 * The stacked layout above is what actually buys the room, and with it no name
 * clips at any viewport from 320 up. But that rule keys off the VIEWPORT, and
 * the thing that decides whether a name fits is the width of the CARD - which
 * is not the same number. Beside the player the card is the viewport less the
 * 320px rail; stacked it is the whole viewport. Today the narrowest the card
 * ever gets while still using the one-line row is about 561px, comfortably
 * clear. Forced down to the rail's own 320px, though, the one-line row clips
 * twelve of fourteen names, "Borussia Mönchengladbach" to 37% of itself - so
 * the row is not robust at that width, it is merely never asked to be.
 *
 * A container query asks the right question. Below 470px of list the crests go,
 * which is the width at which the longest names stop fitting beside a badge:
 * a 16px logo is decoration, a club name is the content, and there is no width
 * at which the badge is worth an abbreviated name. Browsers without container
 * queries simply keep the badges and fall back on the media query above, which
 * is what ships today.
 */
.lsc-list { container-type: inline-size; container-name: lsc; }

@container lsc (max-width: 470px) {
  .lsc-c { display: none; }
}

/* ---- scoreboard ---------------------------------------------------------- */

body.hiper .board-hd h2 { text-shadow: 0 1px 3px rgba(0, 0, 0, .7); }

/* League picker leads the row here and trails it on index2. */
body.hiper .board-filters .lgdd { order: -1; flex: 0 0 auto; }

/*
 * Two columns of cards rather than one full-width list.
 *
 * The panel border moves onto the cells, because a two-column grid inside one
 * bordered panel leaves an unresolved seam down the middle - and the rows draw
 * their own separators, which would only line up in a single column.
 */
body.hiper .board-list {
  background: none; backdrop-filter: none;
  border: 0; border-radius: 0; overflow: visible;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px;
}
body.hiper .board-list .board-empty,
body.hiper .board-list .board-note { grid-column: 1 / -1; }

body.hiper .mrow2 {
  background: rgba(11, 38, 32, .8);
  backdrop-filter: blur(6px);
  border: 1px solid var(--line);
  border-radius: 10px;
  border-bottom: 1px solid var(--line);
  padding: 10px 12px;
  transition: background .12s, border-color .12s, transform .12s;
}
body.hiper .mrow2:hover {
  background: rgba(244, 197, 66, .08);
  border-color: var(--red-dim);
  transform: translateY(-1px);
}
body.hiper .mrow2.islive {
  box-shadow: inset 3px 0 0 #e11d48;
  border-color: rgba(225, 29, 72, .4);
}

@media (max-width: 860px) {
  body.hiper .board-list { grid-template-columns: minmax(0, 1fr); }
}

/* ---- footer -------------------------------------------------------------- */

body.hiper .ftr { background: rgba(3, 14, 11, .8); }
body.hiper .ftr img { height: 22px; width: auto; opacity: .75; }

/* Recent goals and cards, shown when the API has no statistics for the fixture
   - which is the norm for reserve and youth football. */
.ft-flow { margin-top: 12px; display: grid; gap: 1px; }
.ft-fl {
  /* The team column is given a share of the row rather than `auto`: with auto
     the player column claimed the slack first and every club name ended up
     truncated to three letters. */
  display: grid; grid-template-columns: 30px 18px minmax(0, 1fr) minmax(0, 44%);
  align-items: center; gap: 8px;
  padding: 6px 2px;
  border-top: 1px solid var(--line-soft);
  font-size: 12px;
}
.ft-fl u {
  text-decoration: none; color: var(--fg-mute);
  font-size: 11px; font-variant-numeric: tabular-nums;
}
.ft-fl-i { display: grid; place-items: center; }
.ft-fl-i svg { width: 14px; height: 14px; }
.ft-fl b {
  font-weight: 600; color: var(--fg);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ft-fl i {
  font-style: normal; font-size: 11px; color: var(--fg-mute);
  text-align: right;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---- player sizing ------------------------------------------------------- */

/*
 * --chrome is everything above and below the video that is not the video, and
 * landing.css sizes the player as (100vh - chrome) * 16/9. Its figure was
 * measured on index2: header 55, provider strip 48, caption bar 58, footer 49,
 * plus padding - and, until the fake sign-in pair was removed, a CTA bar too.
 *
 * This page has none of that middle section - the provider strip is gone and
 * the sign-in pair sat inside the header rather than under it - and its header
 * stack is shorter. So index2's figure subtracted chrome that does not exist
 * here, which is why this is remeasured rather than inherited; on a short
 * window the player was shrinking below the width of the column it sits in for
 * no reason. Remeasured for this layout: topbar 28 + header 60 + caption 58 +
 * footer 49 + padding.
 */
body.hiper { --chrome: 215px; }

/* ---- standings panel ----------------------------------------------------- */

/*
 * The team-cell and opaque-sticky-header fixes moved into landing.css: both were
 * bugs on index2 as well, not CasinoPer quirks. Only the colour belongs here -
 * the shared value is a blue-grey that reads as foreign on a green page.
 */


/* Hover needs to sit on the green scale too, and be strong enough to read
   against panels that are already translucent over the skin. */
body.hiper .stbl tbody tr:hover { background: rgba(244, 197, 66, .1); }

/*
 * SIRALAMA lives in the sub-tab bar now, so it is an .mtb rather than an .rtab
 * - but unlike the other two it has no count badge, and the standings panel it
 * opens sits directly below this bar. It also has to stay lit while its own
 * panel is showing, which is why landing.js gates the CANLI / YAYINLANACAKLAR
 * highlight on #mpanel being the visible panel.
 */
body.hiper .mtabs #tab-table { letter-spacing: .05em; }

/* With SIRALAMA gone from the top row, MAÇLAR has room to breathe. */
body.hiper .rail-hd { gap: 4px; }

/* The standings panel now opens under the sub-tab bar instead of directly under
   the rail tabs, so its own dropdown no longer needs a top border of its own -
   the bar above already provides the separation. */
body.hiper .stand-hd { border-top: 0; }

/* ---- the rail keeps the player's height ---------------------------------- */

/*
 * The rail stays stretched to the player, as landing.css draws it - `.rail-wrap`
 * is a stretched grid item with `.rail` absolutely positioned to fill it.
 *
 * It was briefly made to hug its rows instead, to close the empty area under a
 * two-fixture list. That was the wrong trade: with the panel short, the space
 * beside the player became bare page skin rather than an empty panel, and the
 * artwork showing through a hole in the layout looked far worse than the gap it
 * replaced. An empty panel reads as "nothing scheduled"; a hole reads as broken.
 *
 * Closing that gap properly means giving the rail something to fill it with, not
 * shrinking the rail.
 */

/* ---- modal tabs with no data --------------------------------------------- */

/*
 * Tabs for sections the API has nothing for are now shown rather than dropped.
 * Hiding them made İLK 11 look unimplemented, when in fact the fixture was a
 * youth match for which the upstream API publishes no lineup at all - the panel
 * behind the tab says so ("Kadrolar maçtan ~1 saat önce açıklanır"), which is
 * the answer the reader wanted and could not reach.
 *
 * Dimmed, but deliberately still clickable: the explanation is the content.
 */
/*
 * Full opacity. Three passes tried to dim an empty tab and be readable at once
 * (.45, .72, then .72 again because this rule outranks the one in landing.css)
 * and every one came out grey next to its neighbour - white text at 72% IS
 * grey. The tab says what section it is; the panel behind it says whether there
 * is anything in it. Dimming the label only hid the first to imply the second.
 */
/* No weight override either. The 700 was here to compensate for the dimming;
   with that gone it only made empty tabs lighter than their neighbours, which
   is the same "one is bold, one is not" problem from the other direction. All
   three tabs now inherit one weight from .mtab. */
body.hiper .mtab.empty,
.mtab.empty {
  opacity: 1;
}
body.hiper .mtab.empty:hover,
.mtab.empty:hover { opacity: 1; }
/* A selected empty tab must still read as selected, so the accent wins over
   the dimming rather than being averaged with it. */
body.hiper .mtab.empty.on,
.mtab.empty.on { opacity: 1; }

/* Footer wordmark. Sits tight against the logo so the two read as one lockup -
   "CASINOPER TV" - rather than a logo with a stray caption next to it. */
body.hiper .ftr { gap: 7px; }
body.hiper .ftr-tv {
  font-size: 15px; font-weight: 800; letter-spacing: .04em;
  color: var(--fg-dim);
}

/* ---- live-scores rows: which competition ---------------------------------- */

/*
 * Without the competition, this list is unreadable. The API's worldwide in-play
 * feed is overwhelmingly youth, reserve and women's football - 104 of the 105
 * fixtures live as I write this - so the rows were "Maldives U20", "Stanway
 * Rovers", "Viking FK W" with nothing to say what any of it was. The league now
 * sits on its own line under the teams, quiet enough not to compete with the
 * score but present on every row.
 */
.lsc-row { row-gap: 3px; }
/*
 * Centred under the match, not under the whole row. Spanning from column 1 put
 * it beneath the minute, hanging off the left edge with nothing above it;
 * starting at the home column centres it on the teams and score - the block it
 * actually describes.
 */
.lsc-lg {
  grid-column: 2 / -1;
  display: flex; align-items: center; justify-content: center;
  gap: 5px; min-width: 0;
}
.lsc-lgb { width: 14px; height: 14px; flex: 0 0 14px; object-fit: contain; opacity: .8; }
.lsc-ln {
  font-size: 10px; letter-spacing: .03em; color: var(--fg-mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---- live-scores rows: the favourite star --------------------------------- *
 *
 * Placed here, after both the base .lsc-row and its 560px block, because grid
 * placement on this row is decided by source order as much as by specificity -
 * .lsc-lg's `grid-column` a few lines up already overrides the `grid-area` the
 * media query gives it, and a rule for the star written earlier in the file
 * would lose the same argument.
 *
 * Wide, the row is a four-column grid whose second row holds only the
 * competition, and .lsc-lg starts that line at column 2 so it centres on the
 * teams rather than hanging off the left edge. Column 1 of row 2 is therefore
 * empty by design - directly under the minute - and the star goes in it. No new
 * track, no new column, nothing that was measured this morning moves.
 */
.lsc-row > .favb {
  grid-row: 2; grid-column: 1; justify-self: center;
  /* Sized to the line it shares, not to the 22px box the star uses on index2's
     board. 14px is the height of .lsc-lgb, the competition badge opposite it,
     so the second row is exactly as tall as it was before the star existed -
     measured: row height unchanged, and the video above it therefore keeps its
     height to the pixel. The touch target is the ::after inset in landing.css,
     which costs no layout. */
  width: 18px; height: 14px; flex: 0 0 18px;
}
.lsc-row > .favb svg { width: 13px; height: 13px; }

/*
 * Stacked, row 2 is the home team and there is no spare cell. The meta line
 * gains a fourth area at its right end instead, which is where the row has room
 * - .lsc-lg is already justified to the end of a flexible third column, so the
 * competition simply stops one chip earlier.
 */
@media (max-width: 560px) {
  .lsc-row {
    grid-template-columns: auto auto minmax(0, 1fr) auto;
    grid-template-areas:
      "min  sc   lg   fav"
      "home home home home"
      "away away away away";
  }
  .lsc-row > .favb { grid-area: fav; justify-self: end; }
  /*
   * And the competition has to stop one column short of it.
   *
   * .lsc-lg is given `grid-area: lg` by the 560px block further up, but the
   * `grid-column: 2 / -1` a few lines above this one is later in the file and
   * therefore wins - which was harmless while `-1` meant the last of three
   * columns and is not now that a fourth exists. Measured before this line: the
   * league line ran under the star and the two overlapped exactly. Named
   * explicitly rather than as -1, so adding another column cannot repeat it.
   */
  .lsc-row > .lsc-lg { grid-column: 2 / 4; }
}

/*
 * A starred row, marked here as well as inside the favourites view.
 *
 * A wash from the leading edge rather than a border: .lsc-row has no left edge
 * of its own to spend, and the glass skin below paints these rows with
 * translucent backgrounds that a solid bar would cut across.
 */
.lsc-row.isfav {
  background: linear-gradient(90deg, rgba(242, 183, 5, .10), rgba(242, 183, 5, 0) 60%);
}
.lsc-row.isfav:hover {
  background: linear-gradient(90deg, rgba(242, 183, 5, .16), rgba(255, 255, 255, .03) 60%);
}

/* The heading pip is red for live scores. On the upcoming fallback that would
   claim these matches are on air, so it drops to the neutral scale. */
.lsc-hd .pip.soon { background: var(--fg-mute); box-shadow: none; }

/* Kickoff time in the minute slot reads as a time, not a clock count; a
   cancelled fixture in that set is struck through like the board rows. */
.lsc-min.off {
  text-decoration: line-through; text-decoration-thickness: 1px;
  color: var(--fg-mute); letter-spacing: 0;
}

/*
 * Win / draw / loss stay hidden here too, exactly as on index2.
 *
 * They were briefly shown because this rail was 372px. It is 340 now - the
 * difference went to the video - and nine columns in that width crushed the
 * header into an unreadable "O G B M AV P FORM" run with the team names
 * squeezed behind it. Played, goal difference and points still justify the
 * ordering, which is the whole job of the extra columns; the other three were
 * the ones worth losing.
 */

/* ---- no dead space around the player ------------------------------------ */

/*
 * The empty bands above and below the video, removed - without widening the
 * page.
 *
 * Widening was the wrong fix and got reverted: --max stays at 1076 and the rail
 * at 372 precisely so the page skin's artwork keeps showing in the left and
 * right gutters. Covering it with a wider content column made the player bigger
 * by hiding the thing the skin is there for.
 *
 * What actually created the bands is vertical, not horizontal:
 *
 * 1. .app centres its children. Whenever the page is shorter than the window
 *    that inserts blank space above the player whose height depends on the
 *    window - which is why it read as a broken empty block rather than as
 *    deliberate spacing. Top-aligned, the header is followed by the player.
 * 2. .player-col carried its own top inset, adding to the same strip.
 * 3. --chrome told the 16:9 cap to reserve room for a header stack and CTA
 *    bars this page does not have, so the video was sized smaller than its
 *    column for space that was never used. Remeasured for this layout, the
 *    video grows to fill the column it already had.
 */
body.hiper .app { justify-content: flex-start; }

/*
 * The page fills the window instead of leaving slack.
 *
 * landing.css sizes .hero-in by its content (`flex: 0 0 auto`) because index2
 * has a scoreboard below it that wants the rest of the page. This page does
 * not, so on a tall window the content stopped short and the leftover height
 * piled up as a dead band above the footer - a couple of hundred pixels of
 * nothing. Centring it, which is what .app did originally, only split the same
 * emptiness into two smaller bands above and below.
 *
 * So the row grows, and the growth goes to the live-scores card: its list was
 * capped at 300px and scrolling while blank space sat underneath it. Now the
 * card takes the slack and shows more matches, which is what the space is
 * worth. Nothing is stretched that would look wrong stretched - the video keeps
 * its aspect ratio and the rail already scrolls internally.
 */
/* padding-top:0 as well as margin: landing.css gives .hero-in 10px all round,
   and that top 10 was the last of the strip between the header and the video. */
body.hiper .hero-in {
  /*
   * No padding at all. landing.css gives this 10px all round; padding-top was
   * the strip under the header, and padding-bottom was the last one - 10px of
   * page background showing beneath the scores card, with the skin's own
   * wordmark visible through it. The sides go too, so the player and the rail
   * run edge to edge against the artwork instead of floating on it.
   */
  margin-top: 0; flex: 1 1 auto; min-height: 0;
  padding: 0;
}

/*
 * Rounded on the outer edge, square where it meets the rail.
 *
 * .screen carried a 10px radius on all four corners while the rail's left edge
 * is square, and the two touch exactly - so the video's rounded top-right cut a
 * visible notch out of the seam. This mirrors what the rail already does on its
 * own outer side, so the pair reads as one panel split down the middle rather
 * than two tiles that do not quite meet.
 */
body.hiper .screen { border-radius: var(--r) 0 0 var(--r); }
body.hiper .player-col { padding-top: 0; justify-content: flex-start; min-height: 0; }

/*
 * The video takes the leftover height, and the card takes only what it needs.
 *
 * The slack used to go to the live-scores card, which worked only when the
 * list was long. With two matches on the board the card stretched and left
 * blank space under its rows - the same dead area, moved inside a panel.
 *
 * So .screen grows instead, and drops its 16:9 lock to do it. That is a real
 * trade: the box becomes taller than 16:9, so `object-fit: cover` fills it by
 * scaling up and cropping the left and right edges of the picture rather than
 * letterboxing. `contain` would put the empty space straight back, this time
 * as black bars inside the player. On a football feed the crop costs a sliver
 * of pitch width, which is the price of the fill.
 */
body.hiper .screen {
  /*
   * flex-grow AND a 16:9 ratio, not one or the other.
   *
   * `aspect-ratio: auto` was wrong: before the first segment arrives the video
   * element has no intrinsic size, so the box collapsed to the height of the
   * "Yayın hazırlanıyor" overlay and left the rest of the column empty - the
   * player looked broken for the two seconds that matter most, on first load.
   *
   * Keeping the ratio gives the box a floor derived from its own width, so it
   * is correctly sized with no video at all; flex-grow then stretches it into
   * whatever height is left over. Never smaller than 16:9, never a gap.
   */
  /*
   * min-height, not 0. The ratio is the PREFERRED size, not a hard floor:
   * with `min-height: 0` the box refused to give anything back, so on a
   * 768-tall window the column needed 779px and the page overflowed by 150 -
   * a scrollbar and a footer pushed below the fold. It may now shrink under
   * pressure, down to a size where the picture is still worth watching.
   */
  /*
   * flex-grow 0, and a low shrink priority. The video holds 16:9.
   *
   * Letting it take the leftover height did remove every gap, but at a cost
   * that was worse than the gap: the box became 735x611 on a 1080 window
   * (ratio 1.20) and 735x315 on a 720 one (ratio 2.33), and `object-fit: cover`
   * fills those by cropping - about a third of the picture's width lost on the
   * big screen, a quarter of its height on the small one.
   *
   * So the slack goes to the scores card instead (see .feat below): it grows to
   * absorb spare height and shrinks first when there is not enough. That keeps
   * the video at exactly 16:9 across the whole 720-1080 range with no gap
   * anywhere, because the card has enough range to cover the difference. The
   * min-height is a last resort for windows shorter than the card can absorb.
   */
  flex: 0 1 auto; min-height: 240px;
  aspect-ratio: 16 / 9;
  width: 100%;
}
body.hiper #video { object-fit: cover; }

/*
 * Content height, so the card cannot manufacture a gap of its own - but
 * shrinkable, so it is not the reason the page overflows either. On a short
 * window the list gives up rows before the video gives up size, which is the
 * right order: someone came for the stream.
 */
/*
 * The card is the elastic element: it takes all spare height and gives it up
 * first. Growing it is not padding - it shows more matches, which is what the
 * space is worth. The high shrink factor is what lets the video keep its ratio
 * on a short window.
 */
body.hiper .feat { flex: 1 100 auto; min-height: 0; display: flex; flex-direction: column; }
body.hiper .lsc { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
body.hiper .lsc-list { max-height: none; flex: 1 1 auto; min-height: 84px; }

/* The 13px of panel either side of the video was .player-col's own inset - the
   dark strips flanking the picture. The video spans the full column now. */
body.hiper .player-col { padding-left: 0; padding-right: 0; }
body.hiper .under { padding-left: 4px; padding-right: 4px; }
body.hiper { --chrome: 196px; }

/* ---- footer -------------------------------------------------------------- */

/*
 * No dark band under the player.
 *
 * The footer painted an opaque strip across the bottom of the page, and with
 * the skin's own CASINOPER artwork sitting directly behind it the result was
 * two logos stacked in a black box. Transparent, it reads as the page ending
 * rather than as another panel, and the height it was reserving goes to the
 * video above it.
 *
 * The mark keeps a shadow because what is behind it is now artwork rather than
 * a flat colour, and that varies.
 */
/*
 * No footer at all on this page.
 *
 * It was a dark band carrying a second CASINOPER mark directly over the skin's
 * own CASINOPER artwork - two logos in a box, at the bottom of a page whose
 * header already says who this is. Removing it hands its height to the player,
 * which is what the space is worth here. The mark and the "TV" wordmark go with
 * it; index2 keeps its own footer untouched.
 */
body.hiper .ftr { display: none; }

/*
 * One screen, no scrollbar - which is what finally makes "no gaps" possible.
 *
 * body is `min-height: 100%`, so the flex chain was free to grow past the
 * window and nothing ever applied shrink pressure: the player held its 16:9
 * height, the card held its rows, and the page simply overflowed - 150px at
 * 768 tall, with a scrollbar and the footer pushed below the fold. Pinning the
 * height bounds the chain, so the leftover space is distributed instead of
 * invented, and .screen / .lsc-list give a little back when there is not
 * enough.
 *
 * Desktop only. Below the 980px breakpoint the layout stacks into one column
 * and genuinely needs to scroll, so it must keep its natural height there.
 */
@media (min-width: 981px) {
  body.hiper { height: 100%; overflow: hidden; }
  body.hiper .app { min-height: 0; }
  /*
   * minmax(0, 1fr) on the row, not the default `auto`.
   *
   * This was the piece that made the rest of the chain inert. A grid row sized
   * `auto` is as tall as its tallest item's content, so bounding .hero-in from
   * above changed nothing - the row simply overflowed and, with body clipped,
   * the bottom of the scores card was cut off and unreachable. minmax(0, 1fr)
   * lets the row be smaller than its content, which is what finally gives
   * .screen and .lsc-list something to shrink against.
   */
  body.hiper .hero-in { grid-template-rows: minmax(0, 1fr); }
  /*
   * align-self: stretch is the fix. landing.css sets `align-self: start` on
   * this column so index2's player sits at the top of a taller row; here that
   * made the column opt out of the row's height entirely - it sized to its
   * content at 783px inside a correctly-bounded 668px row and spilled past the
   * window. Stretched, it takes the row height and the flex children below can
   * finally shrink into it.
   */
  body.hiper .player-col { min-height: 0; align-self: stretch; }
  body.hiper .rail-wrap { min-height: 0; align-self: stretch; }
}

/* The rail header that carried the total-fixture counter, and the MAÇLAR tab it
   sat beside, are gone from this page's markup - so the rule that used to hide
   the counter has nothing left to hide. The count it showed is carried per view
   by the CANLI and YAYINLANACAKLAR tabs, which is where it belonged. index2
   keeps the header; it has no such tabs. */

/* ---- live-scores card: no rule, no dead space, red pip ------------------- */

/*
 * The .lsc block carried margin-top, padding-top and a border-top, which made
 * sense while it sat below a featured-match block inside the same card and
 * needed separating from it. That block is gone, so all three were decorating
 * the top of an otherwise empty card: ~37px of space and a horizontal line
 * above "CANLI SKORLAR" with nothing above them to divide it from.
 */
body.hiper .lsc {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
/* The card's own inset shrinks to match - the heading is the top of the panel
   now, so it does not need to be held away from an edge it is already at. */
body.hiper .feat { padding-top: 9px; margin-top: 8px; }

/*
 * The pip goes red, not the brand teal.
 *
 * `.pip` takes --red, which on this page is the CasinoPer teal - so the dot
 * beside CANLI SKORLAR came out green and read as decoration. It means "on
 * air", which is the one thing on this page that stays red on both brands, for
 * the same reason .livetag and .q.live do: it is a state, not a brand colour.
 * The upcoming variant stays neutral, since kickoff times are not on air.
 */
body.hiper .lsc-hd .pip { background: #e11d48; box-shadow: 0 0 0 3px rgba(225, 29, 72, .18); }
body.hiper .lsc-hd .pip.soon { background: var(--fg-mute); box-shadow: none; }

/* The featured group's heading carries the live pip, so it takes the same red
   as the rest of the on-air indicators rather than the brand teal. */
body.hiper .rgrp-t .pip { background: #e11d48; box-shadow: 0 0 0 3px rgba(225, 29, 72, .18); }
/*
 * No per-row marker at all on this page.
 *
 * These rows already sit under an ÖNE ÇIKANLAR heading that names exactly what
 * they are, so the wash and the star were a second and third way of saying it -
 * and the gold read as a warning colour against the teal palette rather than as
 * emphasis. index2 needs them because it has no heading: one combined list in
 * kickoff order, where a featured fixture has to announce itself in place.
 */
body.hiper .ritem.featured,
body.hiper .ritem.featured:hover { background: none; }
body.hiper .ritem.featured .ritem-t span::after { content: none; }

/* ---- the day, on the card ------------------------------------------------ */

/*
 * Which day a fixture is on, on every row that is not today's.
 *
 * index2 answers this with a heading over each day's block. This rail cannot:
 * it is split into CANLI / YAYINLANACAKLAR tabs and partitioned into ÖNE
 * ÇIKANLAR / DİĞER MAÇLAR, and a third kind of divider cutting across those two
 * would leave the list with more headings than rows. So the date rides on the
 * card, which also means it is there in the featured group - the pinned match
 * is the one a viewer is most likely to be planning an evening around, so it is
 * the last row that should be ambiguous about which evening.
 *
 * These rules have to be here rather than in landing.css: this file loads after
 * it at equal specificity, so the .q.soon colour below only wins from here.
 *
 * Stacked over the clock rather than beside it. The rail is 320px and the chip
 * shares its row with two crests, the title and the league; "YARIN 21:45" on
 * one line pushed the fixture name into an ellipsis.
 */
body.hiper .q.soon {
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: 3px 8px; line-height: 1.25;
  /* Near-white, not the gold landing.css gives it and not a grey: on this
     palette every piece of text is at full strength and hierarchy is carried by
     size and weight instead. The border keeps the chip reading as the kickoff
     chip without the colour having to do it. */
  color: var(--fg);
  border-color: var(--line);
  background: var(--surface-3);
}
body.hiper .q.soon .q-day {
  margin-right: 0; opacity: 1;
  font-size: 9px; font-weight: 800; letter-spacing: .06em;
  color: #fff;
}

/* The scores panel with nothing in it. Only reachable behind the SKORLAR tab -
   where the card is a permanent column it hides instead of saying this. Full
   strength like everything else on this page; it is the only thing on screen
   when it shows, so dimming it would be dimming the whole panel. */
body.hiper .lsc-empty {
  margin: 0; padding: 26px 12px; text-align: center;
  font-size: 12.5px; color: var(--fg);
}

/* ---- panels stay opaque over the artwork --------------------------------- */

/*
 * landing.css paints these at rgba(17, 22, 29, .93) - a blue-grey at 93%, which
 * works over index2's muted skin. This page's artwork is a busy full-colour
 * casino illustration, and 7% of it came through: faces and shapes were
 * legible inside the rail's empty area, which reads as a rendering fault rather
 * than as translucency.
 *
 * Near-opaque rather than fully flat, so the panels still sit *on* the artwork
 * instead of looking pasted over it, but nothing recognisable survives.
 */
body.hiper .rail,
body.hiper .player-col,
body.hiper .feat {
  background: #0a0f18;
}
/* The board list and modal share the same treatment where they exist. */
body.hiper .board-list,
body.hiper .mdl-box { background: #0a0f18; }

/* The standings' sticky header was matched to the old green surface. */
body.hiper .stbl th { background: #0a0f18; }

/*
 * Square corners on the live-scores card.
 *
 * It carried the shared 10px radius, which rounded the top and bottom of a
 * panel that butts directly against the player above it and the window edge
 * below - so the rounding read as two stray notches in an otherwise straight
 * column rather than as a card. The player keeps its outer-left radius, which
 * is the one corner that actually sits against the artwork.
 */
body.hiper .feat { border-radius: 0; }

/*
 * Square throughout on this page.
 *
 * The player column runs edge to edge against the artwork with no gutter, so
 * every rounded corner it had was meeting something flat - the rail on one
 * side, the scores card underneath, the header above. Each one read as a notch
 * rather than as a curve. Square is the honest shape for a flush block.
 */
body.hiper .player-col,
body.hiper .screen,
body.hiper .rail { border-radius: 0; }

/*
 * Anything in the modal still pinned to a literal grey, lifted with it.
 * These were written before the palette moved and hold their own colours.
 */
body.hiper .bm-none,
body.hiper .lu2-gt,
body.hiper .lu-coach,
body.hiper .st-top span,
body.hiper .lu2-p i,
body.hiper .tl-min,
body.hiper .mdl-sub { color: var(--fg-dim); }

/* Unselected modal tabs use the same white as everything else; only the pill
   and the accent mark which one is open. */
body.hiper .mtab { color: var(--fg); }
body.hiper .mtab.on { color: #04140d; }

/* ==========================================================================
   Frosted glass
   ==========================================================================

   Why this exists.

   On the wide layout the page skin is only ever visible down the left and
   right margins - the 1076px content column covers everything between them.
   Every panel on this page was painted #0a0f18, flat and fully opaque, so the
   artwork stopped at the edge of the column and the middle of the screen was a
   dark slab sitting on top of a picture. Making the panels translucent hands
   most of that column back to the artwork without giving up the surface the
   text needs.

   Everything below is inside one @supports test. A browser without
   backdrop-filter gets the solid panels defined further up this file
   unchanged, which is the right fallback: a semi-transparent panel with no
   blur behind it puts body text straight onto a busy photograph.

   Five blurred surfaces, and no more.
   -----------------------------------
   backdrop-filter is a per-frame GPU cost and this page plays HLS
   continuously, so the layer count is a budget, not an afterthought:

     1  .topbar    1440 x 29
     2  .hdr       1440 x 61
     3  .under      755 x 58     (the caption strip)
     4  #feat       755 x 317    (the live-scores card)
     5  .rail       320 x 810    (the schedule column)

   That is fewer and smaller than what was here before. landing.css puts
   `backdrop-filter: blur(6px)` on .player-col, which is a 756 x 810 blurred
   layer directly behind the <video> - the single most expensive surface on the
   page and the one with the least to show for it, since the video covers all
   but 8px of it. It is switched off below. Total blurred area drops from about
   1.24M px2 to 671k, and none of what is left overlaps the picture.

   The rule the layer count buys: blur the CONTAINER, never the rows. Fixture
   rows, score rows and table rows repaint on every poll and on every scroll,
   and each one carrying its own backdrop-filter would multiply the cost by the
   length of the list. They get plain translucent fills instead, which composite
   for free over the panel that is already frosted. No blur radius is animated
   anywhere; transitions are on colour and border only.

   The fills, and why they are as strong as they are.
   --------------------------------------------------
   Contrast decides the alpha, not taste. Sampling pageskin-cper.jpg as it is
   actually laid out at 1440x900 (cover, centre top), the region behind the rail
   peaks at a 20px-blurred luminance of 0.63 and the region behind the scores
   card at 0.68 - there is a near-white patch and a gold one under exactly the
   panels that carry the most text. Against #ffffff body text a panel has to
   stay under about 0.16 luminance to clear 4.5:1, so a plain 55% fill over that
   gold would land at roughly 3.5:1 and fail.

   The fix is brightness() in the filter chain rather than a heavier fill.
   Darkening the backdrop before compositing tames the hotspots while leaving
   the fill low enough that the artwork still reads, where simply raising the
   alpha would have bought the same contrast by hiding the picture - which is
   the one thing this change exists to avoid. saturate() then puts back the
   colour that brightness() takes out, and it is luminance-preserving so it
   costs nothing in contrast. */

body.hiper {
  /* Big panels: strong blur, backdrop darkened hard because the brightest part
     of the skin sits behind them. */
  --glass-fx:     blur(22px) saturate(1.5) brightness(.72);
  /* Chrome strips: the skin behind the header peaks at only 0.13 luminance, so
     these can afford a lighter hand and a smaller radius over a smaller area.
     brightness is .78 rather than .9 - at .9 the strips measured 3.6:1 against
     a pure-white backdrop, and while no part of this skin is anywhere near
     white, a strip that only passes because of the artwork behind it today is
     one skin swap away from failing. */
  --glass-fx-hdr: blur(16px) saturate(1.5) brightness(.78);

  /*
   * 56%, not the 58% this started at.
   *
   * The binding constraint is the brightest pixel behind a panel, measured on
   * the composite rather than guessed: pageskin-cper.jpg has a near-white patch
   * under the lower rail and a gold one under the scores card. Sweeping the
   * fill down and re-measuring, 48% reached 4.11:1 against a pure-white
   * backdrop - under AA - while 56% with the backdrop dimmed to 72% holds
   * 6.6:1 over the real skin and 4.7:1 over pure white, which nothing this
   * skin could ever be replaced with can beat. The last two points of fill are
   * imperceptible next to the four points of backdrop brightness, so the
   * brightness does the work and the fill keeps the margin.
   */
  --glass:      rgba(15, 23, 21, .56);   /* --surface, 56% */
  --glass-hdr:  rgba(9, 20, 17, .54);

  /* Rows and controls sitting on a frosted panel. White at a low alpha rather
     than a colour, so they read as a lit edge of the same material instead of
     as a second surface. */
  --glass-row:      rgba(255, 255, 255, .05);
  --glass-row-hi:   rgba(255, 255, 255, .085);
  --glass-inset:    rgba(0, 0, 0, .24);

  /* Hairlines. --line (#1e2735) is a solid colour picked for solid panels; on
     glass it reads as a drawn rule. These are lit edges. */
  --glass-edge:      rgba(255, 255, 255, .09);
  --glass-edge-soft: rgba(255, 255, 255, .05);

  /* Depth: one soft drop outward, one 1px highlight along the inside of the top
     edge. The highlight is what stops a translucent panel reading as a hole. */
  --glass-top:  inset 0 1px 0 rgba(255, 255, 255, .10);
  --glass-drop: 0 14px 40px rgba(0, 0, 0, .45);

  --glass-r:    12px;

  /* Emerald, for the states that have to stay legible as states. */
  --glass-accent:      rgba(244, 197, 66, .14);
  --glass-accent-edge: rgba(244, 197, 66, .32);
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {

  /* ---- 1. utility strip ------------------------------------------------- */

  body.hiper .topbar {
    background: var(--glass-hdr);
    -webkit-backdrop-filter: var(--glass-fx-hdr);
    backdrop-filter: var(--glass-fx-hdr);
    border-bottom: 1px solid var(--glass-edge-soft);
  }

  /* ---- 2. header -------------------------------------------------------- */

  body.hiper .hdr {
    background: var(--glass-hdr);
    -webkit-backdrop-filter: var(--glass-fx-hdr);
    backdrop-filter: var(--glass-fx-hdr);
    border-bottom: 1px solid var(--glass-edge);
    box-shadow: var(--glass-top), 0 8px 26px rgba(0, 0, 0, .3);
  }
  body.hiper .iconnav a:hover { background: var(--glass-accent); color: var(--red); }
  body.hiper .topbar .social a:hover { background: var(--glass-accent); color: var(--red); }

  /* ---- 3. the player column is NOT frosted ------------------------------ */

  /*
   * No backdrop-filter here, deliberately.
   *
   * This box is the parent of the <video>, so a filter on it blurs a 756x810
   * region of page background that the picture then covers entirely - the most
   * expensive layer on the page, recomposited while the stream plays, for an
   * 8px seam. The seam is the gap between the caption strip and the scores
   * card, and it is the only part of this element anyone ever sees; a plain
   * translucent fill is enough for it and costs nothing per frame.
   *
   * Glass goes around the player, never on top of it.
   */
  body.hiper .player-col {
    background: rgba(11, 18, 16, .42);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    border-color: var(--glass-edge-soft);
  }

  /* ---- 4. caption strip under the player -------------------------------- */

  /*
   * The hairline is an inset shadow rather than a border-top. A real border
   * would add a pixel to this element's height, and the wide layout is a
   * height-bounded flex chain - that pixel comes back out of the video or the
   * scores card. Shadows do not participate in layout.
   */
  body.hiper .under {
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-fx);
    backdrop-filter: var(--glass-fx);
    box-shadow: var(--glass-top);
  }
  body.hiper .under h1 { color: var(--fg); }
  body.hiper .under p { color: var(--fg-mute); }
  body.hiper .under .btn {
    background: var(--glass-row-hi);
    border: 1px solid var(--glass-edge);
    border-radius: var(--glass-r);
    color: var(--fg);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .09);
  }
  body.hiper .under .btn:hover {
    background: var(--glass-accent);
    border-color: var(--glass-accent-edge);
  }

  /* ---- 5. the schedule rail --------------------------------------------- */

  body.hiper .rail {
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-fx);
    backdrop-filter: var(--glass-fx);
    border: 1px solid var(--glass-edge);
    box-shadow: var(--glass-top), var(--glass-drop);
  }

  /* ---- 6. the live-scores card ------------------------------------------ */

  body.hiper .feat {
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-fx);
    backdrop-filter: var(--glass-fx);
    border-color: var(--glass-edge);
    box-shadow: var(--glass-top);
  }

  /* ---- everything inside a panel: plain fills, no second blur ----------- */

  /* Tab row. */
  body.hiper .mtabs {
    background: rgba(255, 255, 255, .04);
    border-bottom: 1px solid var(--glass-edge-soft);
  }
  body.hiper .mtb { color: var(--fg); }
  body.hiper .mtb:hover { background: var(--glass-row-hi); color: var(--fg); }
  body.hiper .mtb.on {
    background: var(--glass-accent);
    color: var(--fg);
    border-bottom-color: var(--red);
  }
  body.hiper .mtb u { background: var(--glass-row-hi); color: var(--fg); }
  body.hiper .mtb.on u { background: var(--red); color: #04140d; }

  /* Search box: pressed into the panel rather than sitting on it. */
  body.hiper .rsearch { border-bottom: 1px solid var(--glass-edge-soft); }
  body.hiper .rsearch input {
    background: var(--glass-inset);
    border: 1px solid var(--glass-edge);
    border-radius: var(--glass-r);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, .3);
    color: var(--fg);
  }
  body.hiper .rsearch input:focus {
    border-color: var(--red-dim);
    box-shadow: 0 0 0 3px var(--red-glow), inset 0 1px 2px rgba(0, 0, 0, .3);
  }

  /* Sport column. */
  body.hiper .sportrail {
    background: rgba(0, 0, 0, .12);
    border-right: 1px solid var(--glass-edge-soft);
  }
  body.hiper .sp { border-bottom: 1px solid var(--glass-edge-soft); }
  body.hiper .sp:hover { background: var(--glass-row-hi); color: var(--fg); }
  body.hiper .sp.on {
    background: var(--glass-accent);
    border-left-color: var(--red);
    color: var(--red);
  }

  /*
   * Fixture rows become tiles.
   *
   * A list of transparent rows separated by rules is the "boring table" the
   * owner is objecting to, and on a frosted panel the rules are the only thing
   * defining a row at all. Giving each row its own faint fill and a radius
   * makes the list read as a stack of cards on glass. The fill is white at 5%,
   * which is a lit edge of the same material - a darker fill would read as a
   * hole punched through the panel.
   */
  body.hiper .ritem {
    background: var(--glass-row);
    border: 1px solid var(--glass-edge-soft);
    border-radius: var(--glass-r);
    margin-bottom: 4px;
  }
  body.hiper .ritem:hover {
    background: var(--glass-row-hi);
    border-color: var(--glass-edge);
  }
  body.hiper .ritem.on {
    background: var(--glass-accent);
    border-color: var(--glass-accent-edge);
    box-shadow: inset 2px 0 0 var(--red);
  }
  /* The featured group is marked by its heading, not by the rows - unchanged,
     but the "no wash" rule above predates the tiles and would now strip a
     featured row of the fill every other row has. */
  body.hiper .ritem.featured { background: var(--glass-row); }
  body.hiper .ritem.featured:hover { background: var(--glass-row-hi); }

  /* Chips. */
  body.hiper .q { background: var(--glass-row-hi); border-color: var(--glass-edge); color: var(--fg); }
  body.hiper .q.soon { background: var(--glass-inset); border-color: var(--glass-edge); color: var(--fg); }
  body.hiper .q.live { background: #e11d48; border-color: #e11d48; color: #fff; }

  /*
   * Score rows: tiles, same reasoning as the fixture rows - with one extra
   * constraint the rail does not have.
   *
   * This list is the elastic element of the wide layout: .feat takes the height
   * left over from the video and gives it up first, so the list's own intrinsic
   * height is an input to how much the video is allowed to shrink. Separating
   * the rows with 4px of margin therefore pushes on the player. The vertical
   * padding comes down by the same 4px to pay for it, which also keeps the
   * number of matches visible without scrolling exactly where it was.
   * Measured: the video is the same width and position to the pixel, and the
   * same height to within 0.05px.
   */
  body.hiper .lsc-row {
    background: var(--glass-row);
    border: 1px solid var(--glass-edge-soft);
    border-radius: var(--glass-r);
    padding: 6px 10px;
    margin-bottom: 4px;
  }
  body.hiper .lsc-row:last-child {
    border-bottom: 1px solid var(--glass-edge-soft);
    margin-bottom: 0;
  }
  body.hiper .lsc-row:hover {
    background: var(--glass-accent);
    border-color: var(--glass-accent-edge);
  }
  /*
   * A starred row, on glass.
   *
   * The plain .lsc-row.isfav wash a few hundred lines up cannot reach here -
   * `body.hiper .lsc-row` outranks it - so the same mark is restated as a
   * gradient layered OVER the glass fill rather than instead of it. Two
   * background layers, image then colour, so the pane keeps its translucency
   * and its backdrop-filter is untouched.
   */
  body.hiper .lsc-row.isfav {
    background:
      linear-gradient(90deg, rgba(242, 183, 5, .14), rgba(242, 183, 5, 0) 60%),
      var(--glass-row);
    border-color: rgba(242, 183, 5, .3);
  }
  body.hiper .lsc-row.isfav:hover {
    background:
      linear-gradient(90deg, rgba(242, 183, 5, .2), rgba(242, 183, 5, 0) 60%),
      var(--glass-accent);
    border-color: rgba(242, 183, 5, .5);
  }

  /* ---- the standings table --------------------------------------------- */

  /*
   * Rows, not a grid.
   *
   * This and the score list are the two most table-like surfaces on the page,
   * and a bordered grid on frosted glass looks like a spreadsheet pasted over a
   * photograph. `border-collapse: separate` with vertical spacing turns each
   * row into its own tile with rounded ends, matching the fixture and score
   * lists, and every internal rule can then go.
   */
  body.hiper .stand-hd {
    background: rgba(255, 255, 255, .045);
    border-bottom: 1px solid var(--glass-edge-soft);
  }
  body.hiper .lgdd.wide .lgdd-btn {
    background: var(--glass-inset);
    border: 1px solid var(--glass-edge);
    border-radius: var(--glass-r);
    color: var(--fg);
  }
  body.hiper .lgdd.wide .lgdd-btn:hover,
  body.hiper .lgdd.wide .lgdd-btn[aria-expanded="true"] { border-color: var(--red-dim); }
  body.hiper .lgdd-panel {
    background: rgba(12, 20, 18, .94);
    border: 1px solid var(--glass-edge);
    border-radius: var(--glass-r);
  }
  body.hiper .lgdd-opt:hover { background: var(--glass-row-hi); }

  body.hiper .stbl { border-collapse: separate; border-spacing: 0 4px; }
  /*
   * The sticky header stays opaque.
   *
   * landing.css already makes this point and it is more true here, not less:
   * at any alpha the rows scrolling underneath ghost through the column titles,
   * and on a translucent panel there is a second layer behind them to ghost
   * through as well. It is a 20px strip of labels - the one place on this page
   * where opaque is the honest answer.
   */
  body.hiper .stbl th {
    background: #101a17;
    border-bottom: 1px solid var(--glass-edge);
    color: var(--fg-mute);
  }
  body.hiper .stbl td {
    background: var(--glass-row);
    border-bottom: 0;
  }
  body.hiper .stbl tbody td:first-child {
    border-top-left-radius: 10px; border-bottom-left-radius: 10px;
  }
  body.hiper .stbl tbody td:last-child {
    border-top-right-radius: 10px; border-bottom-right-radius: 10px;
  }
  /* The rank cell was drawn as its own bordered pill. Inside a row that is now
     a pill itself that is a box in a box, and the border never carried the
     meaning anyway - the European and relegation cuts are in the text colour,
     which is untouched. */
  body.hiper .stbl td.rk { border: 0; border-radius: 0; }
  body.hiper .stbl tbody tr:hover td { background: var(--glass-accent); }

  /* ---- modal ------------------------------------------------------------ */

  /*
   * The modal is glass for free. Its scrim already carries a blur, so the box
   * only has to be translucent to sit on a frosted backdrop - no sixth
   * backdrop-filter, and nothing extra to composite while it is open.
   */
  body.hiper .mdl-back {
    background: rgba(4, 10, 8, .6);
    -webkit-backdrop-filter: blur(14px) saturate(1.2);
    backdrop-filter: blur(14px) saturate(1.2);
  }
  body.hiper .mdl-box {
    background: rgba(15, 23, 21, .74);
    border: 1px solid var(--glass-edge);
    border-radius: 18px;
    box-shadow: var(--glass-top), 0 30px 80px rgba(0, 0, 0, .6);
  }

  /* ---- scrollbars ------------------------------------------------------- */

  /* #303e4e is landing.css's blue-grey. It read as foreign on the green panels
     and reads as foreign on glass; white at a low alpha belongs to the
     material. Every ::-webkit part still has to be accounted for or Chrome
     drops back to the legacy widget - see the note in landing.css. */
  body.hiper .rail-body,
  body.hiper .stand-body,
  body.hiper .lsc-list { scrollbar-color: rgba(255, 255, 255, .22) transparent; }
  body.hiper .rail-body::-webkit-scrollbar-thumb,
  body.hiper .stand-body::-webkit-scrollbar-thumb,
  body.hiper .lsc-list::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, .22); background-clip: content-box;
  }
  body.hiper .rail-body::-webkit-scrollbar-thumb:hover,
  body.hiper .stand-body::-webkit-scrollbar-thumb:hover,
  body.hiper .lsc-list::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, .34); background-clip: content-box;
  }

  /* ---- below 980: the layout stacks and the blur goes ------------------- */

  /*
   * No frosted surfaces on a phone.
   *
   * Two reasons, and the first is enough on its own: stacked, the content
   * column is the whole width of the screen, so there are no margins for the
   * page skin to show through and translucency buys nothing to pay for. The
   * second is that .hdr is `position: sticky` and this layout scrolls - a
   * blurred header over a scrolling page re-blurs its backdrop every frame,
   * which is the classic mobile jank case, and `background-attachment: fixed`
   * behind it makes it worse.
   *
   * Only the panel fills revert. The tiles, radii and hairlines above are the
   * redesign rather than the blur, they cost nothing, and they leave the
   * stacked layout's geometry exactly as it was.
   */
  @media (max-width: 980px) {
    body.hiper .topbar,
    body.hiper .hdr,
    body.hiper .under,
    body.hiper .player-col,
    body.hiper .rail,
    body.hiper .feat {
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }
    body.hiper .topbar { background: rgba(3, 14, 11, .92); }
    body.hiper .hdr { background: rgba(5, 22, 17, .92); }
    body.hiper .under { background: #0a0f18; }
    body.hiper .player-col { background: #0a0f18; }
    body.hiper .rail { background: #0a0f18; }
    body.hiper .feat { background: #0a0f18; }

    /* The tightened score-row padding above exists to pay for the row margin in
       the height-bounded wide layout. Stacked, the card scrolls inside its own
       grid row and there is no video to protect, so the row keeps the roomier
       inset it had - and below 560 it is three lines tall and needs it. */
    body.hiper .lsc-row { padding: 8px 10px; }
  }

  /*
   * Anyone who has asked their OS to cut transparency gets the solid panels,
   * for the same reason the @supports fallback does.
   */
  @media (prefers-reduced-transparency: reduce) {
    body.hiper .topbar,
    body.hiper .hdr,
    body.hiper .under,
    body.hiper .player-col,
    body.hiper .rail,
    body.hiper .feat {
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }
    body.hiper .topbar { background: rgba(3, 14, 11, .96); }
    body.hiper .hdr { background: rgba(5, 22, 17, .96); }
    body.hiper .under,
    body.hiper .player-col,
    body.hiper .rail,
    body.hiper .feat { background: #0a0f18; }
  }
}


/* ==========================================================================
   HiperCasino layout: the skin is the design, not a backdrop
   ==========================================================================
   pageskin-hiper.jpg is a composed poster - headline top-left, bonus panel
   top-right, Mbappe and Haaland at the sides, characters and the wordmark along
   the bottom. Cloning brand-cper.css brought its full-bleed philosophy with it:
   `cover` cropped the artwork and a full-height content column covered what was
   left, so the headline read "KESINTIS", the bonus panel read "000 TL" and the
   wordmark was gone entirely.

   So: draw the whole poster, and put the content in its dark centre.
   ========================================================================== */

@media (min-width: 981px) {
  body.hiper {
    /* contain, not cover - the whole 1920x1080 composition or nothing. */
    background-size: contain;
    background-position: center top;
  }

  /* Header sits in the skin's upper black band, above the content, with no
     panel of its own - a bordered bar there would cut the poster in half. */
  body.hiper .hdr { background: transparent; border-bottom: 0; }
  body.hiper .hdr-in {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; padding-block: 6px;
  }
  body.hiper .logo img { height: 40px; width: auto; }
  /* The mirrored mark is decoration; it must never take the click or the
     tab stop that belongs to the real one. */
  body.hiper .logo-r { pointer-events: none; }

  /*
   * Bound the content so the bottom of the poster survives.
   *
   * The cloned rules made this `height: 100%` with `overflow: hidden`, which is
   * right for a full-bleed brand and wrong here: it is what buried the
   * characters and the wordmark. 62vh centred leaves the lower third of the
   * artwork visible, which is where the owner drew his box.
   */
  body.hiper { height: auto; overflow-x: hidden; overflow-y: auto; }
  body.hiper .app { justify-content: flex-start; padding-top: 4px; }
  /*
   * Fitted to the skin's dark slot, measured off the artwork rather than chosen.
   *
   * The poster is 1920x1080 and its usable centre is x 458..1462, y 12..741 -
   * 52.3% of the width and 67.5% of the height. Drawn `contain` in a viewport
   * wider than 16:9, the skin's width equals the viewport width, so the slot is
   * 52vw across. Any wider and the content creeps over the headline on the left
   * and the bonus panel on the right, which is what the first pass did: it was
   * 950px in a 753px slot and clipped "KESINTISIZ" and "8.000 TL".
   */
  body.hiper .hero-in {
    height: 56vh;
    max-height: 56vh;
    grid-template-rows: minmax(0, 1fr);
    margin-inline: auto;
    width: min(100%, 50vw);
  }
  body.hiper .player-col, body.hiper .rail-wrap { min-height: 0; }
  body.hiper .screen { aspect-ratio: auto; height: auto; flex: 1 1 auto; min-height: 0; }

  /*
   * Live scores move into the rail's SKORLAR tab.
   *
   * As a permanent panel under the player it owned the bottom third of the
   * viewport - exactly the strip the owner marked as "should be visible ... where
   * is skin". The rail already has the tab; using it costs no functionality and
   * hands the poster its bottom back.
   */
  /*
   * landing.js hides this panel by ADDING .tab-off (see the SCORES_TAB block),
   * it never adds an .on class. Keying the reveal on .on therefore hid the
   * scores permanently and the SKORLAR tab did nothing at all.
   */
  body.hiper .feat.tab-off { display: none; }
  body.hiper #tab-scores { display: inline-flex; }
  /*
   * Four tabs in a rail that is now ~41% of 52vw, i.e. ~307px at 1440.
   * At the inherited size the labels touched - the bar read
   * "CANLIYAYINLANACAKLARSIRALAMA SKORLAR" with no gaps, which looks like a
   * rendering fault rather than a tab strip. Shrunk and tightened until the
   * longest label clears its neighbours at the narrowest desktop width.
   */
  body.hiper .mtabs {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 2px;
  }
  body.hiper .mtb {
    font-size: 8.5px;
    letter-spacing: .01em;
    padding-inline: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
  }
  body.hiper .mtb .pip { margin-right: 3px; }

  /*
   * No letterbox band under the poster.
   *
   * `contain` in a 16:10 viewport leaves ~90px of dead black below a 16:9 skin.
   * Anchoring the paint to the top and filling the remainder with the skin's own
   * base colour makes the seam invisible instead of looking like the page ended
   * early.
   */
  body.hiper { background-color: #05070c; background-position: center top; }
}


/* ==========================================================================
   Fill the width, one header, readable tabs
   ==========================================================================
   Three things the owner marked up:

   1. `contain` left black bars down both edges on any window wider than 16:9 -
      his was ~1.84:1, so the poster was height-limited and floated in the middle
      of the page. `100% auto` pins it to the full width instead. On a viewport
      taller than 16:9 that leaves a strip at the bottom rather than at the
      sides, and the base colour is the skin's own black so the seam does not
      read as a missing image. Filling the width is what matters: the artwork's
      content - headline, bonus panel, both players - is spread horizontally.

   2. The utility strip above the logo was an empty black bar. Gone; one header.

   3. Four tabs would not fit the rail, so YAYINLANACAKLAR was ellipsised to
      "'AYINLANACAKLA". Shortened to PROGRAM in the markup, which lets the type
      go back up to a readable size.
   ========================================================================== */

@media (min-width: 981px) {
  /*
   * Fill the viewport exactly - both axes.
   *
   * The poster is 16:9 and a real browser window is not: the owner's is about
   * 1.97:1 once chrome and taskbar are taken off. Three ways to reconcile that,
   * and all three were tried on his screenshots:
   *   contain    -> black bars down both edges ("here is black space")
   *   100% auto  -> width filled, bottom ~100px below the fold, so the
   *                 HIPER CASINO wordmark and its tagline were cut off
   *   100% 100%  -> fills exactly; costs ~10% vertical stretch
   *
   * The third wins. This is a decorative poster, not a photograph being judged
   * on proportion, and a 10% squash on it is far less noticeable than a cut
   * wordmark or bars down the sides - both of which he flagged immediately.
   */
  body.hiper {
    background-size: 100% 100%;
    background-position: center center;
    background-attachment: scroll;
  }

  /* Slightly narrower than the slot, so the artwork breathes on both sides
     rather than running right up to the content edge. */
  /*
   * Sized from the poster, not guessed.
   *
   * Skin drawn `100% auto`, so its height is 56.25vw. The usable slot is
   * x 458..1462 and y 12..741 of 1920x1080 - 52.3% of the width, and its bottom
   * edge sits at 0.686 x 56.25vw = 38.6vw down the page. Take the header off
   * that and the content can be as tall as the slot allows, which is a good deal
   * taller than the 52vh it was. 52vw wide fills the slot exactly: any more and
   * it starts covering "KESINTISIZ" on the left and "8.000 TL" on the right.
   */
  /*
   * With the skin stretched to the viewport, the slot maps straight onto
   * viewport units: x 23.9%..76.1% and y 1.1%..68.6% of the artwork. So the
   * content can run to 68.6vh and no further - below that are the characters
   * and the wordmark. Taking the header off the top gives the height, and it
   * also closes the dead black gap that used to sit under the content.
   */
  body.hiper .hero-in {
    width: min(100%, 50vw);
    height: calc(67vh - 58px);
    max-height: calc(67vh - 58px);
  }
  body.hiper .app { padding-top: 0; }

  /* One header, logo left and mirrored right, sitting on the poster. */
  body.hiper .hdr { padding-block: 2px; }
  body.hiper .hdr-in { padding-block: 2px; }
  body.hiper .logo img { height: 34px; }

  /* Readable again now the longest label is PROGRAM. */
  body.hiper .mtb {
    font-size: 10px;
    letter-spacing: .02em;
    padding-inline: 4px;
    text-overflow: clip;
  }
  body.hiper .mtabs { gap: 1px; }
}


@media (min-width: 981px) {
  /*
   * 47vw, not 52.
   *
   * The slot is 52.3% of the artwork's width, so 52vw technically fits - and it
   * measured as fitting, with 3px to spare each side at 1920. But 3px is not
   * clearance, it is a coincidence: the headline's glow and the bonus panel's
   * outer chips bleed past the flat rectangle I measured, so "KESINTISIZ / MAC
   * YAYINLARI" lost its M and "8.000 TL", "%100" and "FREE SPIN" lost their
   * right-hand characters. 47vw leaves ~50px of real air at 1920 and the poster
   * reads whole, which is the whole point of this layout.
   *
   * The player does not shrink back for it - that came from moving the scores
   * into the rail, which is a height change, not a width one.
   */
  body.hiper .hero-in { width: min(100%, 50vw); }
}


@media (min-width: 981px) {
  /*
   * 50vw: close the gap without clipping.
   *
   * 52vw put the content edge exactly on the headline and clipped the M of
   * "MAC YAYINLARI"; 47vw cleared it by ~50px but left an obvious dead channel
   * between the poster's text and the player. 50vw splits it - about 20px of
   * clearance at 1920, which is enough for the headline's glow and no more.
   */
  body.hiper .hero-in { width: min(100%, 50vw); }

  /*
   * Shorter header.
   *
   * It was overlapping the top of the artwork - the "%100" chip of the bonus
   * panel was being clipped by the header band. The header carries nothing but
   * two wordmarks, so it does not need 64px; 44px clears the panel and the
   * wordmarks still read at 28px.
   */
  body.hiper .hdr { padding-block: 0; min-height: 0; }
  body.hiper .hdr-in { padding-block: 3px; min-height: 0; }
  body.hiper .logo img { height: 28px; }

  /*
   * The CANLI badge sat on top of the broadcaster's own scorebug, which also
   * lives in the top-left of the picture - two overlays fighting for one corner,
   * which is what looked broken. Ours moves to the bottom-left, above the
   * caption and clear of both the scorebug and the beIN logo top-right, and gets
   * smaller so it reads as our chrome rather than competing with the feed.
   */
  body.hiper .livetag {
    top: auto; bottom: 10px; left: 10px;
    font-size: 9px; letter-spacing: .07em; padding: 4px 8px;
    background: rgba(225, 29, 72, .82);
    backdrop-filter: blur(2px);
  }
}


@media (min-width: 981px) {
  /*
   * Header must clear the artwork's top text, which begins ~5.5% down the
   * poster - about 54px at 975. Measured at 60px it was still clipping the
   * "%100" chip by 6px, so pin the height rather than trusting padding: the
   * wordmarks are the only content and 22px of mark inside 42px of bar reads
   * fine against a poster this busy.
   */
  body.hiper .hdr { height: 42px; overflow: visible; }
  body.hiper .hdr-in { height: 42px; padding-block: 0; align-items: center; }
  body.hiper .logo img { height: 22px; }
}


@media (min-width: 981px) {
  /*
   * Show the whole frame. Never crop the broadcast.
   *
   * Inherited from CasinoPer: `#video { object-fit: cover }`, which is right
   * there because that layout deliberately fills a box taller than 16:9. Here it
   * was slicing the picture - the broadcaster's own scorebug came through as
   * "0|1 KNY" with its left half gone, and the pitch was a zoomed crop.
   *
   * `contain` alone would fix the crop but leave ~95px of black above and below
   * the picture, because the box is 611x534 and the feed is 16:9. That black is
   * pure waste: the visible picture is 611x344 either way. So the box goes back
   * to 16:9 and the height it no longer needs is given back to the poster, which
   * is the thing this whole layout exists to show.
   *
   * The block height is therefore derived, not chosen: player width is the
   * content width less the rail, and the block is that width at 16:9 plus the
   * caption strip.
   */
  body.hiper #video { object-fit: contain; }
  body.hiper .screen {
    aspect-ratio: 16 / 9;
    height: auto;
    width: 100%;
    flex: 0 0 auto;
    min-height: 0;
  }
  body.hiper .hero-in {
    height: calc((50vw - 288px) * 0.5625 + 62px);
    max-height: calc(67vh - 58px);
  }
}


@media (min-width: 981px) {
  /*
   * Align the scores panel to the rail, not inside it.
   *
   * The inherited .feat is a standalone card - 14px of side padding and an 8px
   * top margin - which made sense when it sat under the player as its own block.
   * As a rail panel that padding put its rows at 288px inside a 318px rail, so a
   * 15px black margin ran down both sides and an 8px gap sat under the tab row:
   * the tab and the thing it reveals looked like two different components.
   *
   * Zeroed, and the inset lifted to the tab row's own height so the panel starts
   * exactly where the tabs end. Row padding stays - that is internal spacing,
   * not a frame.
   */
  body.hiper .rail .feat {
    inset: 34px 0 0;
    padding: 0;
    margin: 0;
  }
  body.hiper .rail .feat .lsc-hd { margin: 0; padding: 8px 10px; }
  body.hiper .rail .feat .lsc-list { padding: 0; }
  body.hiper .rail .feat .lsc-row { margin: 0 0 2px; border-radius: 0; }
  /* Overlay the scrollbar instead of letting it eat a column of rows. */
  body.hiper .rail .feat .lsc-list { scrollbar-width: thin; }
}


@media (min-width: 981px) {
  /*
   * Stop growing. The height above is the whole height.
   *
   * .hero-in is `flex: 1 1 auto` in .app so the row would fill a tall window -
   * correct while the live-scores card lived inside it and could absorb slack.
   * The card is in the rail now with its own scroll, so flex-grow had nothing
   * to give the space to: it stretched the row to the 67vh cap (595px) around
   * 406px of content and the difference came out as a black band under the
   * caption, the width of the player and ~190px tall.
   *
   * flex-grow:0 makes the declared height the real height. The space goes back
   * to the poster below, which is what it was covering.
   *
   * max-height stays as the guard on short windows - the calc is width-derived,
   * so on a wide-and-short window it would otherwise run past the artwork.
   */
  body.hiper .hero-in { flex: 0 0 auto; }
}


@media (min-width: 981px) {
  /*
   * The player fills the window. 90vw wide, rail 290px, height from the video.
   *
   * Asked for directly, as a devtools edit: height calc((90vw - 290px) * 0.5625
   * + 62px). Applying only that would not have worked, and it is worth writing
   * down why. .screen is `aspect-ratio: 16/9; width: 100%`, so the picture is
   * sized by WIDTH; the height of .hero-in does not feed back into it. Raising
   * the height alone would have left a 573px-wide player in a 582px-tall box -
   * a bigger version of the empty bottom the edit was trying to remove.
   *
   * So width is the knob and height follows it. With height:auto the dead band
   * cannot come back by construction: the box is exactly as tall as the video
   * plus the caption, whatever the width resolves to. That is strictly better
   * than the calc it replaces, which had to be kept in sync with the rail width
   * by hand and was already 4px out.
   *
   * The third term in min() is the window guard. Width drives height, so on a
   * wide-and-short window 90vw would derive a box taller than the viewport, and
   * desktop body is `overflow: hidden` - the caption and the tab row would have
   * been cut off with no way to scroll to them. Inverting the derivation gives
   * the widest content whose 16:9 player still fits:
   *
   *     player height = (W - 290) * 0.5625        (16:9)
   *     block height  = that + 62                 (caption strip)
   *     must fit      = 100vh - 42 (header) - 20 (breathing room)
   *     => W <= (100vh - 124) / 0.5625 + 290
   *
   * TRADE-OFF, STATED: at 90vw the poster is mostly covered - on a 1723px
   * window the content is 1551px of it. The earlier 50vw was chosen to clear
   * "MAÇ YAYINLARI" on the left and the bonus panel on the right, and that is
   * now given up on purpose in favour of the bigger picture. Only the top logos
   * and a band at the bottom stay visible.
   */
  body.hiper .hero-in {
    width: min(100%, 90vw, calc((100vh - 124px) / 0.5625 + 290px));
    grid-template-columns: minmax(0, 1fr) 290px;
    height: auto;
    max-height: none;
    flex: 0 0 auto;
  }
}


/* ---- skin framing: measured off the artwork, not guessed ---------------- */

@media (max-width: 980px) {
  /*
   * Mobile shows a fixed 435px-wide window of the poster, centred.
   *
   * `cover` on a portrait phone scales the 1920x1080 poster by HEIGHT, so the
   * visible strip is only ~515px of source width - and the two figures nearest
   * the middle land right on its edges: the fisherman's shoulder at x 703..730
   * and Zeus's gold armband at x 1190..1217. Cropped out and enlarged, they are
   * unmistakably two disembodied arms poking into the frame, one bottom-left and
   * one bottom-right, which is exactly how they read on the phone.
   *
   * The clean span around the wordmark is source x 742..1177. Sizing the
   * background in vw pins the window to that width at EVERY phone size instead
   * of letting the viewport's aspect ratio decide it:
   *
   *     1920 / 435 * 100vw = 441vw          (435 source px across the screen)
   *     441vw * 1080/1920  = 248vw tall     (`auto` keeps the ratio)
   *
   * Anchored to the bottom, not the top: the window is taller than a phone, so
   * something must be cut, and the choice is between the wordmark at the bottom
   * and empty theatre ceiling at the top. `center top` was cutting the wordmark.
   */
  body.hiper {
    background-size: 441vw auto;
    background-position: 50% 100%;
  }
}

@media (min-width: 981px) {
  /*
   * Desktop content width: 50vw. Reverting my own 90vw, and here is the honest
   * reason rather than a silent revert.
   *
   * The 90vw was asked for and I applied it, but it never took effect as
   * written: .hero-in inherits `max-width: var(--max)` = 1076px from
   * landing.css, so the width resolved to 1076px at every viewport - which is
   * why the player measured 785x442 identically at 1536, 1723, 1863 and 1920.
   * 1076px at a 1723px window is 62.5vw, and THAT is what put the content's
   * right edge at x 1399 over the bonus panel, whose "I" starts at x 1326.
   * So the reported symptom and the unnoticed cap are the same bug.
   *
   * The poster decides this number, and it is not negotiable by CSS. Measured
   * on the 1920px artwork, allowing for the glow that bleeds past the letters:
   *
   *     "MAC YAYINLARI" is clear from      x 464
   *     "ILK UYELIK" starts at             x 1470
   *     clean window                       1006px = 52.4vw
   *
   * 52vw was tried before and clipped the M by 3px - the glow, not the glyph,
   * is the real edge. 50vw is the largest width with margin on both sides, and
   * with the rail beside the player that caps the picture at (50vw - 290px).
   *
   * max-width: none stays. --max is a site-wide 1076px container for the other
   * pages; on this one the poster is the constraint and vw is the unit that
   * tracks it, since the skin is drawn 100% 100% and therefore scales with the
   * viewport exactly as vw does.
   *
   * height: auto stays too - that is what keeps the dead band gone, whatever
   * the width resolves to.
   */
  body.hiper .hero-in {
    width: min(100%, 50vw);
    max-width: none;
    grid-template-columns: minmax(0, 1fr) 290px;
    height: auto;
    max-height: none;
    flex: 0 0 auto;
  }
}


/* ---- tab row, single mobile logo, and the last of the player width ------ */

@media (max-width: 980px) {
  /*
   * One logo on a phone.
   *
   * The mirrored right-hand mark exists because the desktop header is a bar
   * across a symmetrical poster and a single logo left half of it empty. On a
   * phone the header is 440px wide and the two marks end up shoulder to
   * shoulder in the top-left, which does not read as symmetry - it reads as the
   * logo having been pasted in twice.
   *
   * Hidden rather than removed from the markup: it is the same element the
   * desktop layout needs, and it is already aria-hidden with tabindex="-1", so
   * nothing here is announced or focusable either way.
   */
  body.hiper .logo-r { display: none; }
}

@media (min-width: 981px) {
  /*
   * Tabs sized by their labels, not by four equal shares.
   *
   * The bug: `repeat(4, minmax(0, 1fr))` in a 290px rail gives each tab ~71px.
   * PROGRAM at 10px/800 is ~46px and its count badge is another ~23px, so the
   * content is ~69px before the 8px of padding - it overflows. And because .mtb
   * is `justify-content: center` with `overflow: hidden`, the overflow is taken
   * off BOTH ends: the P disappears, the badge is pushed out of the box, and
   * the remainder reads as "ROGRAM  32". Equal shares are the whole problem -
   * SIRALAMA and SKORLAR sit in 71px boxes they do not need while PROGRAM is
   * starved next to them.
   *
   * Flex with `flex: 1 1 auto` (basis auto = content width) hands each tab what
   * its own label needs and shares the leftover. Measured at 262px: the four
   * labels plus badges and padding come to ~245px, so there is slack rather
   * than a deficit, and nothing clips.
   *
   * overflow visible and text-overflow clip are both undone deliberately - with
   * content-sized columns there is nothing to hide, and leaving `hidden` on
   * would mean a future longer label fails silently again instead of visibly.
   */
  body.hiper .mtabs {
    display: flex;
    grid-template-columns: none;
    gap: 0;
    justify-content: space-between;
  }
  body.hiper .mtb {
    flex: 1 1 auto;
    min-width: 0;
    gap: 4px;
    font-size: 9.5px;
    letter-spacing: 0;
    padding-inline: 3px;
    overflow: visible;
    text-overflow: clip;
  }
  /* The badge is content, not slack - it must never be the thing that shrinks. */
  body.hiper .mtb u { flex: 0 0 auto; }

  /*
   * Rail 290 -> 262, and the 28px goes to the picture.
   *
   * This is the only lever left, and it is worth being straight about why it is
   * small. The player is WIDTH-bound: the box is 16:9 so height only comes from
   * width, and width is capped by the poster at ~50vw - at 1723px the content's
   * left edge already sits 15px off the glow on "MAC YAYINLARI", and 51.5vw
   * would cut that to 2px. So the header height, the caption strip and the
   * viewport height are all irrelevant here; only the rail can give anything
   * back, and only as much as the four tab labels can live without.
   *
   * 262px is the floor the tab row sets, measured, not guessed. That buys the
   * picture 600x337 from 571x321 - about 5%, and the video still fills it
   * exactly because the box stays 16:9.
   *
   * For a genuinely bigger picture the rail has to stop being a column beside
   * the player and go underneath it, which frees the full 862px and makes the
   * video 862x485 - 51% larger. That is a layout change, not a number, so it is
   * not being made here.
   */
  body.hiper .hero-in { grid-template-columns: minmax(0, 1fr) 262px; }
}


@media (min-width: 981px) {
  /*
   * The last of the height. 337px -> 356px.
   *
   * Asked for as "a little bigger to bottom in height", and height on this
   * player is not directly settable: .screen is locked to 16/9 so the video
   * fills it with no bars and no crop, which means every extra pixel of height
   * has to be bought with 1.78px of width. Two places had width left.
   *
   * 1. The content box was 50vw and centred, which left 15px of slack on the
   *    left and 27px on the right - the poster is not symmetrical about the
   *    viewport centre. The real limit is the clean span between the glow on
   *    "MAC YAYINLARI" (x416 at a 1723px window) and the glow on "ILK UYELIK"
   *    (x1319). Centred, the binding edge is the left one:
   *
   *        (100vw - W) / 2 >= 420   =>   W <= 100vw - 840px
   *
   *    Expressed in vw that is 51.2vw here, and stated as the calc so it holds
   *    at other window widths instead of being a number that happens to fit
   *    mine. min() with 51.2vw keeps the narrow end sane.
   *
   * 2. The rail goes 262 -> 250. 262 was the floor for the tab labels at
   *    9.5px; at 9px with 2px of inline padding the four of them measure ~248,
   *    so 250 is the new floor. Verified by measurement, not by eye - if any
   *    tab's scrollWidth exceeds its clientWidth this is wrong and goes back.
   *
   * Together: 599x337 -> 633x356, and 571x321 -> 633x356 over the last two
   * rounds, about 11%. This is the end of the road on this layout. The next
   * increment is not a number - the rail has to go under the player, which
   * frees the whole 883px and makes the video 883x497.
   */
  body.hiper .hero-in {
    /*
     * 51.2vw, and NOT `calc(100vw - 840px)` as I first wrote it.
     *
     * That calc was wrong and worth recording. It came from the measurement at
     * a 1723px window - left edge >= 420px - but 420px is not a constant: the
     * skin is drawn `100% 100%`, so the poster stretches with the viewport and
     * the glow on "MAC YAYINLARI" sits at a fixed FRACTION of the width, not a
     * fixed pixel. Subtracting a fixed 840px therefore over-corrected as the
     * window narrowed and under-corrected as it widened. On a 1440x900 laptop
     * it resolved to 600px of content and a 349x196 player - a third of the
     * size, on the most ordinary screen size there is.
     *
     * The whole constraint is proportional, so it belongs in vw and nothing
     * else. Clean span 416..1319 of 1723 = 52.4vw, and centring needs the left
     * edge at 24.1vw, so W <= 51.7vw; 51.2vw keeps ~4px of margin at every
     * width. Verified at 1440, 1723 and 1863: clearance 4, 4, 5px.
     */
    width: min(100%, 51.2vw);
    grid-template-columns: minmax(0, 1fr) 250px;
  }
  body.hiper .mtb {
    font-size: 9px;
    padding-inline: 2px;
    gap: 3px;
  }
}


/* ---- rail back beside the player, wider; player gives up the width ----- */

@media (min-width: 981px) {
  /*
   * REVERTED: the rail is a column beside the player again, not a row under it.
   *
   * I moved it underneath to buy the picture 53% more height, because the
   * player is 16/9 and width was the only source of height. It worked - 631x355
   * became 964x542 with no bars and no crop - but it was the wrong trade. The
   * rail is 344px tall and it landed exactly on the middle band of the poster,
   * which is the part that was supposed to stay visible; the whole reason this
   * page is only ~51vw wide in the first place is to keep the artwork readable.
   * Buying height by covering the thing the height was protecting is not a win,
   * and no amount of tuning the numbers fixes that - it is the wrong axis.
   *
   * So: side by side, and the height question is settled the other way. The
   * rail goes to 300px (it was 250 at its narrowest) and the player takes the
   * loss - about 582x327 at a 1723px window. The rail gets a roomier list and
   * the poster keeps its middle.
   *
   * height: auto and the width in vw both stay - those were separate fixes and
   * neither had anything to do with where the rail sits. Together they are what
   * keeps the dead band gone and the poster clear at every window size.
   */
  body.hiper .hero-in {
    grid-template-columns: minmax(0, 1fr) 300px;
    grid-template-rows: minmax(0, 1fr);
    /*
     * 51.2vw - the poster's clean window - and the player pays for the rail.
     *
     * REVERTED from `45vw + 290px`. That kept the big player AND fitted the
     * rail beside it, which is arithmetically the only way to have both - and
     * it was the wrong call. player + rail then exceeds the artwork's clean
     * span (x416..x1319 of a 1723px window), so both ends of the poster get
     * clipped: ~81px off "MAC YAYINLARI" and ~68px off "ILK UYELIK". Spending
     * the skin to buy player width defeats the reason this page is held to
     * ~51vw in the first place.
     *
     * So the content box is the clean window again and the 300px rail comes out
     * of the PLAYER, not out of the poster. About 582x327 at a 1723px window.
     *
     * Written down so it is not re-litigated: inside this window the three
     * quantities are fixed and cannot all grow at once -
     *
     *     player width + 300px rail <= 51.2vw    or the skin gets covered
     *     player height = player width / 1.78    or the video bars or crops
     *
     * A bigger picture requires giving up one of those. Both have now been
     * tried and both were rejected - the rail underneath covered the middle of
     * the poster, a wider box covered the text at the edges.
     */
    width: min(100%, 51.2vw);
  }
  body.hiper .player-col { align-self: stretch; width: auto; margin-inline: 0; }
  body.hiper .rail-wrap { height: auto; min-height: 0; align-self: stretch; }

  /* Square where they meet, rounded on the outside - the seam is vertical
     again, so the radii go back to the left/right split. */
  body.hiper .screen { border-radius: var(--r) 0 0 var(--r); }
  body.hiper .rail { border-radius: 0 var(--r) var(--r) 0; border-left: 0; }

  /*
   * Tabs back inside a 300px rail. 11px only made sense while the row was 963px
   * wide; at 300 it would clip PROGRAM's badge again, which is the bug from two
   * rounds ago. 10px with content-sized flex boxes measured ~261px of content
   * in 290px, so 300px has real slack.
   */
  body.hiper .mtabs { justify-content: space-between; }
  body.hiper .mtb {
    flex: 1 1 auto;
    font-size: 10px;
    letter-spacing: .01em;
    padding-inline: 4px;
    gap: 4px;
  }
}


@media (min-width: 981px) {
  /*
   * Taller, and only taller. 16/9 -> 16/10.
   *
   * "expand it only to bottom not to left or right" - so width is fixed, which
   * means the box can no longer match the feed's 16:9. Something has to give
   * and there are exactly two options:
   *
   *   contain  the picture keeps its shape and the extra height becomes black
   *            bars above and below it. That is the dead band again, just
   *            inside the player instead of under it. Rejected.
   *   cover    the picture fills the taller box and loses a sliver off each
   *            side. Nothing is added to the frame and nothing is distorted -
   *            the edges are simply outside the box.
   *
   * cover, at 16/10. That is +36px of height at a 1723px window (327 -> 363)
   * and costs 5.3% of the frame width off each side. Worth stating clearly
   * because it is a real loss: on a wide shot that is a strip of touchline, and
   * a broadcaster graphic hard against the left or right edge can clip.
   *
   * 16/10 rather than something squarer on purpose - the crop scales with how
   * far the ratio departs from 16:9, so 16/10 is roughly the most height that
   * can be taken before the loss stops being a sliver. If the crop reads badly
   * on air, this ratio is the single number to walk back.
   *
   * Mobile keeps 16/9 and contain: there the player is full width already, so
   * height comes free from width and there is nothing to buy.
   */
  body.hiper .screen { aspect-ratio: 16 / 10; }
  body.hiper #video { object-fit: cover; }
}
