/*
 * 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.cper so nothing here can reach index2.
 */

body.cper {
  /* CasinoPer teal, sampled from the logo artwork. */
  --red: #16d99a;
  --red-dim: #0fae7b;
  --red-glow: rgba(22, 217, 154, .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: #0b1210;
  --surface: #0f1715;
  --surface-2: #162320;
  --surface-3: #1d2e29;
  --line: #223330;
  --line-soft: #17231f;

  --fg: #eef6f3;
  /*
   * 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: #eef6f3;
  --fg-mute: #e2eeea;
}

/*
 * 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.cper {
  background: #0b1210 url('/pageskin-cper.jpg') no-repeat center top;
  background-size: cover;
  background-attachment: fixed;
}

/* Teal is bright; white-on-teal loses the contrast red carried. */
body.cper .btab.on,
body.cper .mtab.on,
body.cper .pgr-n.on { color: #04140d; }
body.cper .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.cper .livetag { background: rgba(225, 29, 72, .92); }
body.cper .hh-live, body.cper .lh-live { background: #e11d48; color: #fff; }
body.cper .mrow2.islive { box-shadow: inset 2px 0 0 #e11d48; background: rgba(225,29,72,.07); }
body.cper .mrow2.islive:hover { background: rgba(225,29,72,.12); }
body.cper .st-form .fp.l { background: #e11d48; }
body.cper .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(22,217,154,.12); }

/* ---- header -------------------------------------------------------------- */

body.cper .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.cper .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.cper .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(22,217,154,.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.cper .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.cper .hero-in { grid-template-columns: minmax(0, 1fr) 320px; }

/* .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(22,217,154,.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.cper .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.cper .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.cper .mtabs { grid-template-columns: 0.78fr 1.46fr 0.9fr 0.86fr; }
  body.cper .mtb { padding: 11px 2px; font-size: 10px; letter-spacing: .01em; }

  body.cper .player-col { display: contents; }
  body.cper .screen { order: 1; }
  body.cper .under { order: 2; }
  body.cper .rail-wrap { order: 3; }
  body.cper .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.cper .under { background: #0f1715; }

  /*
   * 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.cper .rail-wrap { height: auto; min-height: 0; }
  body.cper .rail { position: static; }
  body.cper .rail-body { max-height: 46vh; }
  body.cper .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.cper .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.cper #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(22, 217, 154, .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(22, 217, 154, .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.cper .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.cper .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.cper .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.cper .board-list .board-empty,
body.cper .board-list .board-note { grid-column: 1 / -1; }

body.cper .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.cper .mrow2:hover {
  background: rgba(22, 217, 154, .08);
  border-color: var(--red-dim);
  transform: translateY(-1px);
}
body.cper .mrow2.islive {
  box-shadow: inset 3px 0 0 #e11d48;
  border-color: rgba(225, 29, 72, .4);
}

@media (max-width: 860px) {
  body.cper .board-list { grid-template-columns: minmax(0, 1fr); }
}

/* ---- footer -------------------------------------------------------------- */

body.cper .ftr { background: rgba(3, 14, 11, .8); }
body.cper .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.cper { --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.cper .stbl tbody tr:hover { background: rgba(22, 217, 154, .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.cper .mtabs #tab-table { letter-spacing: .05em; }

/* With SIRALAMA gone from the top row, MAÇLAR has room to breathe. */
body.cper .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.cper .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.cper .mtab.empty,
.mtab.empty {
  opacity: 1;
}
body.cper .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.cper .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.cper .ftr { gap: 7px; }
body.cper .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.cper .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.cper .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.cper .screen { border-radius: var(--r) 0 0 var(--r); }
body.cper .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.cper .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.cper #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.cper .feat { flex: 1 100 auto; min-height: 0; display: flex; flex-direction: column; }
body.cper .lsc { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
body.cper .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.cper .player-col { padding-left: 0; padding-right: 0; }
body.cper .under { padding-left: 4px; padding-right: 4px; }
body.cper { --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.cper .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.cper { height: 100%; overflow: hidden; }
  body.cper .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.cper .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.cper .player-col { min-height: 0; align-self: stretch; }
  body.cper .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.cper .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.cper .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.cper .lsc-hd .pip { background: #e11d48; box-shadow: 0 0 0 3px rgba(225, 29, 72, .18); }
body.cper .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.cper .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.cper .ritem.featured,
body.cper .ritem.featured:hover { background: none; }
body.cper .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.cper .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.cper .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.cper .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.cper .rail,
body.cper .player-col,
body.cper .feat {
  background: #0f1715;
}
/* The board list and modal share the same treatment where they exist. */
body.cper .board-list,
body.cper .mdl-box { background: #0f1715; }

/* The standings' sticky header was matched to the old green surface. */
body.cper .stbl th { background: #0f1715; }

/*
 * 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.cper .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.cper .player-col,
body.cper .screen,
body.cper .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.cper .bm-none,
body.cper .lu2-gt,
body.cper .lu-coach,
body.cper .st-top span,
body.cper .lu2-p i,
body.cper .tl-min,
body.cper .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.cper .mtab { color: var(--fg); }
body.cper .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 #0f1715, 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 #eef6f3 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.cper {
  /* 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 (#223330) 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(22, 217, 154, .14);
  --glass-accent-edge: rgba(22, 217, 154, .32);
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {

  /* ---- 1. utility strip ------------------------------------------------- */

  body.cper .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.cper .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.cper .iconnav a:hover { background: var(--glass-accent); color: var(--red); }
  body.cper .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.cper .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.cper .under {
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-fx);
    backdrop-filter: var(--glass-fx);
    box-shadow: var(--glass-top);
  }
  body.cper .under h1 { color: var(--fg); }
  body.cper .under p { color: var(--fg-mute); }
  body.cper .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.cper .under .btn:hover {
    background: var(--glass-accent);
    border-color: var(--glass-accent-edge);
  }

  /* ---- 5. the schedule rail --------------------------------------------- */

  body.cper .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.cper .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.cper .mtabs {
    background: rgba(255, 255, 255, .04);
    border-bottom: 1px solid var(--glass-edge-soft);
  }
  body.cper .mtb { color: var(--fg); }
  body.cper .mtb:hover { background: var(--glass-row-hi); color: var(--fg); }
  body.cper .mtb.on {
    background: var(--glass-accent);
    color: var(--fg);
    border-bottom-color: var(--red);
  }
  body.cper .mtb u { background: var(--glass-row-hi); color: var(--fg); }
  body.cper .mtb.on u { background: var(--red); color: #04140d; }

  /* Search box: pressed into the panel rather than sitting on it. */
  body.cper .rsearch { border-bottom: 1px solid var(--glass-edge-soft); }
  body.cper .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.cper .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.cper .sportrail {
    background: rgba(0, 0, 0, .12);
    border-right: 1px solid var(--glass-edge-soft);
  }
  body.cper .sp { border-bottom: 1px solid var(--glass-edge-soft); }
  body.cper .sp:hover { background: var(--glass-row-hi); color: var(--fg); }
  body.cper .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.cper .ritem {
    background: var(--glass-row);
    border: 1px solid var(--glass-edge-soft);
    border-radius: var(--glass-r);
    margin-bottom: 4px;
  }
  body.cper .ritem:hover {
    background: var(--glass-row-hi);
    border-color: var(--glass-edge);
  }
  body.cper .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.cper .ritem.featured { background: var(--glass-row); }
  body.cper .ritem.featured:hover { background: var(--glass-row-hi); }

  /* Chips. */
  body.cper .q { background: var(--glass-row-hi); border-color: var(--glass-edge); color: var(--fg); }
  body.cper .q.soon { background: var(--glass-inset); border-color: var(--glass-edge); color: var(--fg); }
  body.cper .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.cper .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.cper .lsc-row:last-child {
    border-bottom: 1px solid var(--glass-edge-soft);
    margin-bottom: 0;
  }
  body.cper .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.cper .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.cper .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.cper .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.cper .stand-hd {
    background: rgba(255, 255, 255, .045);
    border-bottom: 1px solid var(--glass-edge-soft);
  }
  body.cper .lgdd.wide .lgdd-btn {
    background: var(--glass-inset);
    border: 1px solid var(--glass-edge);
    border-radius: var(--glass-r);
    color: var(--fg);
  }
  body.cper .lgdd.wide .lgdd-btn:hover,
  body.cper .lgdd.wide .lgdd-btn[aria-expanded="true"] { border-color: var(--red-dim); }
  body.cper .lgdd-panel {
    background: rgba(12, 20, 18, .94);
    border: 1px solid var(--glass-edge);
    border-radius: var(--glass-r);
  }
  body.cper .lgdd-opt:hover { background: var(--glass-row-hi); }

  body.cper .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.cper .stbl th {
    background: #101a17;
    border-bottom: 1px solid var(--glass-edge);
    color: var(--fg-mute);
  }
  body.cper .stbl td {
    background: var(--glass-row);
    border-bottom: 0;
  }
  body.cper .stbl tbody td:first-child {
    border-top-left-radius: 10px; border-bottom-left-radius: 10px;
  }
  body.cper .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.cper .stbl td.rk { border: 0; border-radius: 0; }
  body.cper .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.cper .mdl-back {
    background: rgba(4, 10, 8, .6);
    -webkit-backdrop-filter: blur(14px) saturate(1.2);
    backdrop-filter: blur(14px) saturate(1.2);
  }
  body.cper .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.cper .rail-body,
  body.cper .stand-body,
  body.cper .lsc-list { scrollbar-color: rgba(255, 255, 255, .22) transparent; }
  body.cper .rail-body::-webkit-scrollbar-thumb,
  body.cper .stand-body::-webkit-scrollbar-thumb,
  body.cper .lsc-list::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, .22); background-clip: content-box;
  }
  body.cper .rail-body::-webkit-scrollbar-thumb:hover,
  body.cper .stand-body::-webkit-scrollbar-thumb:hover,
  body.cper .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.cper .topbar,
    body.cper .hdr,
    body.cper .under,
    body.cper .player-col,
    body.cper .rail,
    body.cper .feat {
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }
    body.cper .topbar { background: rgba(3, 14, 11, .92); }
    body.cper .hdr { background: rgba(5, 22, 17, .92); }
    body.cper .under { background: #0f1715; }
    body.cper .player-col { background: #0f1715; }
    body.cper .rail { background: #0f1715; }
    body.cper .feat { background: #0f1715; }

    /* 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.cper .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.cper .topbar,
    body.cper .hdr,
    body.cper .under,
    body.cper .player-col,
    body.cper .rail,
    body.cper .feat {
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }
    body.cper .topbar { background: rgba(3, 14, 11, .96); }
    body.cper .hdr { background: rgba(5, 22, 17, .96); }
    body.cper .under,
    body.cper .player-col,
    body.cper .rail,
    body.cper .feat { background: #0f1715; }
  }
}
