/* Manage channels — mobile first.
   ⚠ Every list here can be tens of thousands of rows, so nothing sizes itself
   from its content and every row is a fixed, scannable height. */

.lib { max-width: 1180px; padding-bottom: 140px; }
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ── breadcrumbs ─────────────────────────────────────────────────────────── */
.lib-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:6px;font-size:14px;
  padding:10px 0 2px}
.lib-crumbs a{color:#1AD6C5;text-decoration:none}
.lib-crumbs a:hover{text-decoration:underline}
.lib-crumbs span{opacity:.45}
.lib-crumbs b{font-weight:600}

.lib-head h1{margin:.15em 0 .1em;font-size:clamp(1.5rem,5vw,2rem)}
.lib-sub{margin:0 0 12px;opacity:.75;max-width:60ch}

/* ── sync status: quiet, persistent, never lies ──────────────────────────── */
.lib-sync{display:flex;align-items:center;gap:9px;padding:10px 14px;margin:0 0 14px;
  border-radius:12px;background:rgba(255,255,255,.04);font-size:14px}
.lib-sync .material-symbols-rounded{font-size:20px;opacity:.8}
.lib-sync.saving{background:rgba(45,212,191,.10)}
.lib-sync.saved{background:rgba(45,212,191,.16)}
.lib-sync.fail{background:rgba(239,68,68,.16)}
.lib-link{background:none;border:0;color:#1AD6C5;font:inherit;cursor:pointer;
  text-decoration:underline;padding:6px}

/* ── toolbar ─────────────────────────────────────────────────────────────── */
.lib-tools{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:10px}
.lib-search{flex:1 1 240px;display:flex;align-items:center;gap:8px;padding:0 12px;
  border-radius:12px;border:1px solid rgba(255,255,255,.14);background:rgba(0,0,0,.25)}
.lib-search .material-symbols-rounded{opacity:.6;font-size:20px}
.lib-search input{flex:1;min-width:0;padding:13px 0;border:0;background:none;color:inherit;
  font:inherit;font-size:16px}           /* 16px stops iOS zooming on focus */
.lib-search input:focus{outline:none}
.lib-search:focus-within{outline:2px solid rgba(45,212,191,.55);outline-offset:1px}

.lib-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-height:48px;padding:0 16px;border-radius:999px;font:inherit;font-size:14px;
  color:inherit;background:transparent;border:1px solid rgba(255,255,255,.18);cursor:pointer}
.lib-btn:hover{background:rgba(255,255,255,.08)}
.lib-btn:disabled{opacity:.45;cursor:default}
.lib-btn.pri{background:#1AD6C5;color:#06281f;border-color:transparent;font-weight:600}
.lib-btn .material-symbols-rounded{font-size:20px}
.lib-iconbtn{display:inline-flex;align-items:center;justify-content:center;
  min-width:48px;min-height:48px;border:0;background:none;color:inherit;cursor:pointer;
  border-radius:12px;opacity:.75}
.lib-iconbtn:hover{opacity:1;background:rgba(255,255,255,.08)}
:focus-visible{outline:2px solid #1AD6C5;outline-offset:2px}

.lib-chips{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px}
.lib-chip{display:inline-flex;align-items:center;gap:6px;padding:7px 12px;border-radius:999px;
  background:rgba(45,212,191,.16);border:0;color:inherit;font:inherit;font-size:13px;cursor:pointer}
.lib-chip .material-symbols-rounded{font-size:16px}

/* ── content type ────────────────────────────────────────────────────────── */
.lib-kinds{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:12px}
.lib-kind{display:flex;flex-direction:column;align-items:center;gap:2px;padding:12px 6px;
  min-height:48px;border-radius:14px;border:1px solid rgba(255,255,255,.12);
  background:rgba(255,255,255,.03);color:inherit;font:inherit;cursor:pointer}
.lib-kind .material-symbols-rounded{font-size:22px;opacity:.85}
.lib-kind b{font-size:14px}
.lib-kind small{opacity:.6;font-size:12px;font-variant-numeric:tabular-nums}
.lib-kind.on{border-color:#1AD6C5;background:rgba(45,212,191,.14)}

.lib-count{font-size:13px;opacity:.7;margin:2px 0 8px;font-variant-numeric:tabular-nums}
.lib-count:focus{outline:none}

/* ── rows ────────────────────────────────────────────────────────────────── */
.lib-list{display:flex;flex-direction:column;gap:2px}
.lib-row{display:flex;align-items:center;gap:8px;min-height:60px;padding:6px 8px;
  border-radius:12px;background:rgba(255,255,255,.03)}
.lib-row:hover{background:rgba(255,255,255,.06)}
.lib-row.off{opacity:.72}
.lib-row.sel{background:rgba(45,212,191,.15)}
.lib-row.lifted{background:rgba(45,212,191,.22);box-shadow:0 8px 24px rgba(0,0,0,.5)}
.lib-all{background:rgba(45,212,191,.10);border:1px solid rgba(45,212,191,.35)}

.lib-main{flex:1;min-width:0;display:flex;align-items:center;gap:10px;padding:8px 4px;
  background:none;border:0;color:inherit;font:inherit;text-align:left;cursor:pointer;
  min-height:48px}
.lib-txt{min-width:0;display:flex;flex-direction:column;gap:2px}
/* Long provider names wrap to two lines rather than being cut mid-word. */
.lib-txt b{font-weight:600;font-size:15px;line-height:1.25;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.lib-txt small{opacity:.62;font-size:12px}
.lib-hidden{color:#fca5a5;opacity:.95}

.lib-dot{flex:0 0 12px;width:12px;height:12px;border-radius:50%}
.lib-ic{flex:0 0 24px;font-size:24px;line-height:1}
.lib-logo{flex:0 0 40px;width:40px;height:28px;object-fit:contain;border-radius:5px;
  background:rgba(255,255,255,.06)}
.lib-logo-none{display:block}
.lib-chev{opacity:.35;font-size:20px}
.lib-check{flex:0 0 40px;display:flex;justify-content:center}
.lib-check input{width:22px;height:22px}
.lib-star.on{opacity:1;color:#E53935}
.lib-handle{flex:0 0 44px;min-width:44px;min-height:48px;display:flex;align-items:center;
  justify-content:center;border:0;background:none;color:inherit;opacity:.7;
  cursor:grab;touch-action:none}   /* touch-action:none so the drag is not a scroll */
.lib-handle:active{cursor:grabbing}

.lib-skel{background:rgba(255,255,255,.04)}
.lib-skel span{display:block;height:14px;width:60%;border-radius:7px;
  background:linear-gradient(90deg,rgba(255,255,255,.06),rgba(255,255,255,.13),rgba(255,255,255,.06));
  background-size:200% 100%;animation:libsk 1.1s linear infinite;margin-left:10px}
@keyframes libsk{0%{background-position:200% 0}100%{background-position:-200% 0}}

.lib-empty{text-align:center;padding:42px 18px;opacity:.9}
.lib-empty .material-symbols-rounded{font-size:40px;opacity:.45}
.lib-empty h3{margin:10px 0 4px}
.lib-empty p{margin:0 0 14px;opacity:.7}
.lib-empty .lib-btn{margin:4px}

/* ── pagination ──────────────────────────────────────────────────────────── */
.lib-pager{display:flex;align-items:center;justify-content:center;gap:10px;
  flex-wrap:wrap;margin:14px 0;font-size:14px}
.lib-jump{display:flex;align-items:center;gap:6px;font-size:13px;opacity:.8}
.lib-jump input{width:78px;padding:11px;border-radius:10px;font-size:16px;
  border:1px solid rgba(255,255,255,.14);background:rgba(0,0,0,.25);color:inherit}

/* ── bottom bars ─────────────────────────────────────────────────────────── */
.lib-bar{position:fixed;left:0;right:0;bottom:0;z-index:40;padding:10px 14px;
  background:rgba(15,23,42,.97);border-top:1px solid rgba(255,255,255,.12);
  box-shadow:0 -8px 24px rgba(0,0,0,.4)}
.lib-bar-order{display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:flex-end}
.lib-bar-order span{flex:1;min-width:160px;font-size:13px;opacity:.8}
.lib-selbar-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:8px}
#lib-sel-n{font-weight:600}
.lib-selbar-acts{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:6px}
.lib-selbar-acts button{display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-height:48px;padding:0 10px;border-radius:12px;font:inherit;font-size:13px;color:inherit;
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);cursor:pointer}
.lib-selbar-acts button:hover{background:rgba(255,255,255,.12)}
.lib-selbar-acts .material-symbols-rounded{font-size:18px}

/* ── sheet / dialog ──────────────────────────────────────────────────────── */
.lib-sheet-wrap{position:fixed;inset:0;z-index:60;background:rgba(0,0,0,.6);
  display:flex;align-items:flex-end;justify-content:center}
.lib-sheet{width:100%;max-height:88vh;overflow:auto;background:#0f172a;
  border:1px solid rgba(255,255,255,.14);border-radius:18px 18px 0 0;padding:6px 16px 20px}
.lib-sheet-head{position:sticky;top:0;background:#0f172a;display:flex;align-items:center;
  justify-content:space-between;gap:10px;padding:10px 0 8px}
.lib-sheet-head h3{margin:0;font-size:1.05rem;min-width:0;overflow:hidden;text-overflow:ellipsis}
.lib-sheet-row{display:flex;align-items:center;justify-content:space-between;gap:10px;
  width:100%;min-height:52px;padding:0 12px;margin-bottom:4px;border-radius:12px;
  background:rgba(255,255,255,.05);border:0;color:inherit;font:inherit;font-size:15px;
  text-align:left;cursor:pointer}
.lib-sheet-row:hover{background:rgba(255,255,255,.1)}
.lib-sheet-row.on{background:rgba(45,212,191,.16)}
.lib-sheet-note{opacity:.7;font-size:13px;margin:2px 0 10px}
/* Per-playlist sync results. A <p> collapses newlines, so the summary has
   to be real markup or every playlist runs into the one before it. */
.lib-syncres{list-style:none;margin:2px 0 4px;padding:0;display:flex;
  flex-direction:column;gap:10px}
.lib-syncres li{display:flex;gap:10px;align-items:flex-start;font-size:13px;
  line-height:1.35}
.lib-syncres li .material-symbols-rounded{font-size:18px;flex:0 0 auto;margin-top:1px}
.lib-syncres li.ok .material-symbols-rounded{color:#4ade80}
.lib-syncres li.skip .material-symbols-rounded{opacity:.5}
.lib-syncres li.fail .material-symbols-rounded{color:#f87171}
.lib-syncres b{display:block;font-weight:600}
.lib-syncres span.d{opacity:.7}
.lib-sheet-btns{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}
.lib-field{display:block;font-size:13px;opacity:.85;margin:6px 0 12px}
.lib-field input{display:block;width:100%;margin-top:6px;padding:13px;border-radius:12px;
  font-size:16px;border:1px solid rgba(255,255,255,.14);background:rgba(0,0,0,.25);color:inherit}
.lib-field-lab{font-size:13px;opacity:.85;margin:14px 0 6px}
#lib-iq{width:100%;padding:12px;border-radius:12px;font-size:16px;margin-bottom:8px;
  border:1px solid rgba(255,255,255,.14);background:rgba(0,0,0,.25);color:inherit}
.lib-cols{display:grid;grid-template-columns:repeat(auto-fill,minmax(116px,1fr));gap:6px}
.lib-col{display:flex;align-items:center;gap:8px;min-height:48px;padding:0 10px;
  border-radius:12px;border:1px solid rgba(255,255,255,.14);background:transparent;
  color:inherit;font:inherit;font-size:13px;cursor:pointer}
.lib-col span{width:18px;height:18px;border-radius:50%;flex:0 0 18px}
.lib-col.on{border-color:#1AD6C5;background:rgba(45,212,191,.16)}
.lib-icons{display:grid;grid-template-columns:repeat(auto-fill,minmax(56px,1fr));gap:6px;
  max-height:260px;overflow:auto;margin-top:4px}
.lib-icon{display:flex;align-items:center;justify-content:center;min-height:52px;
  border-radius:12px;border:1px solid rgba(255,255,255,.12);background:transparent;
  color:inherit;font-size:22px;cursor:pointer}
.lib-icon.on{border-color:#1AD6C5;background:rgba(45,212,191,.16)}

/* ── desktop ─────────────────────────────────────────────────────────────── */
@media (min-width:820px){
  .lib-kinds{grid-template-columns:repeat(3,minmax(0,220px));justify-content:start}
  .lib-row{min-height:56px}
  .lib-sheet-wrap{align-items:center}
  .lib-sheet{max-width:620px;border-radius:18px}
  .lib-bar{left:50%;transform:translateX(-50%);max-width:1180px;border-radius:16px 16px 0 0}
}

/* ⚠ 320px is a real phone, and the bulk bar is where narrow layouts break. */
@media (max-width:360px){
  .lib-kind b{font-size:13px}
  .lib-selbar-acts{grid-template-columns:1fr 1fr}
  .lib-btn{padding:0 12px}
}

@media (prefers-reduced-motion:reduce){
  .lib-skel span{animation:none}
  *{transition:none!important}
}

/* ⚠ THE ONE DESTRUCTIVE CONTROL ON THE PAGE, AND IT HAS TO LOOK LIKE IT.
   Removing a provider takes its favourites, groups and watch history with it on
   every television. Everything else here is reversible with a second tap; this
   is not, so it does not get to wear the same neutral pill as Cancel. */
.lib-btn.danger {
  border-color: rgba(229, 57, 53, .55);
  color: #ff8a85;
}
.lib-btn.danger:hover,
.lib-btn.danger:focus-visible {
  background: rgba(229, 57, 53, .14);
  border-color: rgba(229, 57, 53, .9);
  color: #ffb4b0;
}

/* A pin is an ON/OFF mark, so it has to read as one without a label beside it —
   hollow when it is not pinned, filled and in the accent when it is. */
.lib-pin{opacity:.55}
.lib-pin.on{opacity:1;color:#FDD835}
.lib-pin.on .material-symbols-rounded{font-variation-settings:'FILL' 1}

/* ── destinations ───────────────────────────────────────────────────────────
 * Favourites, groups and hidden items are household-wide, so they read as
 * places rather than filters: a row of pills above the tools, always visible,
 * with the current one carrying the same teal the kind tabs use.
 * Scrolls sideways on a narrow phone rather than wrapping into two ragged
 * lines — four short labels stay recognisable at a glance that way.
 */
.lib-dests{display:flex;gap:8px;margin-bottom:12px;overflow-x:auto;
  scrollbar-width:none;-webkit-overflow-scrolling:touch}
.lib-dests::-webkit-scrollbar{display:none}
.lib-dest{display:inline-flex;align-items:center;gap:7px;flex:0 0 auto;
  min-height:48px;padding:0 16px;border-radius:999px;font:inherit;font-size:14px;
  color:inherit;background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.12);cursor:pointer;white-space:nowrap}
.lib-dest:hover{background:rgba(255,255,255,.08)}
.lib-dest .material-symbols-rounded{font-size:20px;opacity:.85}
.lib-dest.on{border-color:#1AD6C5;background:rgba(45,212,191,.14);font-weight:600}
.lib-dest.on .material-symbols-rounded{opacity:1;color:#1AD6C5}
.lib-dest:focus-visible{outline:2px solid #1AD6C5;outline-offset:2px}

/* The jump menu wears the same shape as the buttons beside it, so the toolbar
   reads as one row of controls rather than a form dropped into it. */
.lib-plsel{display:inline-flex;align-items:center;gap:6px;
  min-height:48px;padding:0 8px 0 14px;border-radius:999px;
  border:1px solid rgba(255,255,255,.18);cursor:pointer}
.lib-plsel:hover{background:rgba(255,255,255,.08)}
.lib-plsel .material-symbols-rounded{font-size:20px;opacity:.8}
.lib-plsel select{font:inherit;font-size:14px;color:inherit;background:transparent;
  border:0;padding:0 4px;max-width:46vw;cursor:pointer}
.lib-plsel select:focus{outline:none}
.lib-plsel:focus-within{outline:2px solid #1AD6C5;outline-offset:2px}
.lib-plsel select option{color:#0b1220;background:#e8eef6}

/* A cross-playlist row is read, not opened — there is nothing below a channel
   to drill into — so its middle cell is a span that lines up with .lib-main
   without pretending to be a button. */
.lib-main-flat{flex:1;min-width:0;display:flex;align-items:center;gap:10px;
  padding:8px 4px;text-align:left}

/* ── back ───────────────────────────────────────────────────────────────────
 * ⚠ ALWAYS IN THE PAGE FLOW. The breadcrumb carried the only way up and sits
 * under the sticky site header on a handset — readable, untappable. This is a
 * real control with a 48px target, and it names its destination because "Back"
 * alone on a six-level page is a guess.
 */
.lib-back{display:inline-flex;align-items:center;gap:8px;
  min-height:48px;padding:0 18px 0 14px;margin-bottom:12px;
  border-radius:999px;font:inherit;font-size:14px;font-weight:600;
  color:inherit;background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.14);cursor:pointer;max-width:100%}
.lib-back:hover{background:rgba(255,255,255,.12)}
.lib-back:focus-visible{outline:2px solid #1AD6C5;outline-offset:2px}
.lib-back .material-symbols-rounded{font-size:20px}
.lib-back span:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ── phones ─────────────────────────────────────────────────────────────────
 * ⚠ THE LIST WAS BELOW THE FOLD ON EVERY PHONE. Title, subtitle, sync bar,
 * back, destinations, search, kind tabs and a count all stacked before a single
 * channel appeared — and the subtitle said the very same sentence as the sync
 * bar directly under it. Owner, on an iPhone: "Need better layout for mobile?".
 *
 * Nothing is removed that carries information; what goes is the duplication and
 * the padding. Tap targets stay at 48px throughout — this is a remote-and-thumb
 * product, not a dense dashboard.
 */
@media (max-width: 640px) {
  /* The sync bar already says this, in stronger words, immediately below. */
  .lib-sub { display: none; }

  .lib { padding-bottom: 120px; }
  .lib-crumbs { padding: 6px 0 0; font-size: 13px; }
  .lib-head h1 { margin: .1em 0 .35em; font-size: 1.45rem; }
  .lib-sync { padding: 9px 12px; margin: 0 0 10px; font-size: 13px; }
  .lib-back { margin-bottom: 10px; }

  /* ⚠ SAY THAT IT SCROLLS. The destinations run off the right edge on a 390px
     screen and looked like a cut-off layout rather than a scrollable row, so
     "Groups" and "Hidden" read as broken. A fade at the edge is the only honest
     affordance that costs no height. */
  .lib-dests {
    margin-bottom: 10px;
    padding-right: 18px;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
  }
  .lib-dest { padding: 0 14px; font-size: 13px; }

  /* Icon beside the words, not above them: same information, half the height. */
  .lib-kinds { gap: 6px; margin-bottom: 10px; }
  .lib-kind {
    flex-direction: row;
    justify-content: center;
    gap: 7px;
    padding: 0 8px;
    min-height: 48px;
    border-radius: 999px;
  }
  .lib-kind b { font-size: 13px; }
  .lib-kind small { font-size: 11px; opacity: .55; }

  .lib-tools { gap: 6px; margin-bottom: 8px; }
  .lib-count { font-size: 12px; }
  .lib-plsel select { max-width: 38vw; }
}

/* Very small phones: the kind tabs lose their counts before they lose their
   labels — the label is what you tap, the count is decoration. */
@media (max-width: 380px) {
  .lib-kind small { display: none; }
  .lib-back { padding: 0 14px 0 10px; }
}

/* ── POSTER WALL for films and series ─────────────────────────────────────
   ⚠ A FILM IS CHOSEN BY ITS ARTWORK, A CHANNEL BY ITS NAME. The channel list
   is a list because you already know the name you are looking up; browsing
   films is the opposite job, and the poster carries what a title cannot.
   Owner: "so people can see clear what the movie / series is ... and decide if
   they wanna watch it or not". Three across on a phone, as in his reference. */
.lib-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; padding: 4px 0 8px; }
@media (min-width: 700px)  { .lib-grid { grid-template-columns: repeat(5, 1fr); gap: 14px; } }
@media (min-width: 1100px) { .lib-grid { grid-template-columns: repeat(7, 1fr); } }

.lib-card { position: relative; border-radius: 10px; overflow: hidden; background: #11293b; }
.lib-card.off { opacity: .55; }

/* ⚠ 2:3, BECAUSE THAT IS THE SHAPE THE ARTWORK ALREADY IS. The catalogue
   stores TMDB w600_and_h900 posters, so any other ratio letterboxes every
   single tile. */
/* ⚠⚠ THE RATIO IS HELD BY PADDING, NOT BY aspect-ratio.
   aspect-ratio is ignored by older mobile browsers, and the image inside is
   sized to 100% of its parent — so on those the parent had no height, the
   image had no height, and every poster rendered as a thin line. Owner: "the
   posters are not showing properly ... they look like lines on my mobile".
   padding-top:150% is 3/2 and has worked in every browser for fifteen years;
   aspect-ratio stays as well for the modern ones, where the two agree. */
.lib-card-art { display: block; width: 100%; padding: 0; border: 0;
  background: #0d1f2d; cursor: pointer; position: relative; overflow: hidden; }
.lib-card-art::before { content: ""; display: block; padding-top: 150%; }
@supports (aspect-ratio: 2 / 3) {
  .lib-card-art { aspect-ratio: 2 / 3; }
  .lib-card-art::before { display: none; }
}
/* Absolute, so it fills whichever of the two is holding the box open. */
.lib-card-art img { position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block; }
/* 0.2% of films have no artwork: a plain tile, never a broken image. */
.lib-card-art.noart::after { content: 'movie'; font-family: 'Material Symbols Rounded';
  font-size: 34px; color: #2c4a60; position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center; }

.lib-card-hidden { position: absolute; left: 6px; top: 6px; z-index: 2;
  background: rgba(0,0,0,.72); color: #fff; font-size: 10px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; padding: 3px 7px; border-radius: 99px; }

/* Both controls sit ON the poster so they cost no height, but keep a 34px
   target and a scrim so they stay hittable and visible over a bright image. */
.lib-card-acts { position: absolute; top: 4px; right: 4px; z-index: 3; display: flex; gap: 2px; }
.lib-card-btn { width: 34px; height: 34px; display: flex; align-items: center;
  justify-content: center; border: 0; border-radius: 50%; background: rgba(0,0,0,.55);
  color: #fff; cursor: pointer; }
.lib-card-btn:hover { background: rgba(0,0,0,.78); }
.lib-card-btn .material-symbols-rounded { font-size: 19px; }
/* ⚠ RED HEART, MATCHING THE TELEVISION. The app draws a favourite as a red
   heart and a pinned category as a yellow pin. The website drew a yellow star
   for favourites — the app's PIN colour, on the wrong thing. Owner: "keep app
   and website consistent". */
.lib-card-btn.lib-star.on { color: #E53935; }

.lib-card-name { font-size: 12.5px; line-height: 1.25; padding: 7px 8px 9px; color: #F5F8FC;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
@media (min-width: 700px) { .lib-card-name { font-size: 13.5px; } }

/* ⚠ A SCROLLING CHIP ROW MUST NOT DRAG THE WHOLE PAGE SIDEWAYS WITH IT.
   .lib-dests is deliberately overflow-x:auto — the destinations are meant to
   scroll within their own strip. But without min-width:0 a flex/grid child
   sizes to its CONTENT, so the strip grew past the viewport and took the page
   with it: the customer got a horizontally scrolling page on a phone, which is
   the one thing a phone layout must never do. Measured at 390px: chips
   reaching 594px, i.e. 200px off the right edge. */
.lib-dests, .lib-kinds, .lib-chips { min-width: 0; max-width: 100%; }

/* ⚠⚠ NOTHING IMPORTANT MAY LIVE OFF THE RIGHT EDGE OF A PHONE.
   Owner: "favourites, hidden, pinned etc.. is all off screen and I need to
   scroll?". The destinations were a sideways-scrolling strip with no hint that
   it scrolled, so on a phone the only ones you could see were the first two —
   the same fault the account page's navigation had. A strip you must discover
   by dragging is a strip most people never find.
   They WRAP now: two short rows, everything reachable, nothing hidden. */
@media (max-width: 700px) {
  .lib-dests { flex-wrap: wrap; overflow-x: visible; }
  .lib-dest { flex: 0 0 auto; }

  /* ⚠ AND THE KIND ROW HAD TO BE ALLOWED TO SHRINK. repeat(3,1fr) looks like
     it fits by definition, but a grid child's default min-width is its
     CONTENT — and these carry counts like "181,713", so the three tiles came
     to 428px inside a 390px screen and pushed the whole page sideways.
     min-width:0 is what lets 1fr actually mean a third. */
  .lib-kinds > * { min-width: 0; }
  .lib-kind { min-width: 0; overflow: hidden; }
  /* ⚠ DROP THE COUNT, KEEP THE WORD. Truncating the label turned "Movies"
     into "M…" beside a perfectly legible "181,713" — the wrong half survived.
     The count is reference; the label is what you are aiming at. It is still
     on screen just below, in "Showing 100 of 181,713 films". */
  .lib-kind small { display: none; }
  .lib-kind b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* The opened poster: artwork, then what it is about. */
.lib-sheet-poster { display: block; width: 132px; aspect-ratio: 2 / 3; object-fit: cover;
  border-radius: 10px; margin: 0 auto 14px; }
.lib-sheet-meta { font-size: 12.5px; color: #B2C3D3; margin: 0 0 10px; line-height: 1.45; }
/* ⚠ Long plots must scroll INSIDE the sheet, not push its buttons off a phone. */
.lib-sheet-plot { font-size: 14px; line-height: 1.55; color: #F5F8FC; margin: 0 0 16px;
  max-height: 42vh; overflow-y: auto; }

/* ── The opened title's three actions ─────────────────────────────────────
   ⚠ flex-start, NOT the inherited space-between. .lib-sheet-row is built for
   label-left / chevron-right; these rows are icon-then-label, and pushed
   apart they read as two unrelated things at opposite ends of a wide row. */
.lib-sheet-acts { margin-top: 4px; }
.lib-sheet-acts .lib-sheet-row { justify-content: flex-start; gap: 12px; }
.lib-sheet-acts .material-symbols-rounded { font-size: 21px; opacity: .9; }
/* The heart is red once it is on, exactly as it is on the card and on the TV. */
.lib-sheet-acts .lib-sheet-row .material-symbols-rounded#lib-ti-fav-ic { color: #E53935; }
.lib-sheet-acts .lib-sheet-row #lib-ti-fav-ic:not(:only-child) { color: inherit; }

/* ── WHICH PROVIDER, on a cross-playlist poster ───────────────────────────
   Favourites and groups span every playlist on the account, and the same film
   can legitimately appear twice from two providers. The row list said so in
   its subtitle; the wall says it here. */
.lib-card-from { margin-top: -5px; padding: 0 8px 8px; font-size: 11px;
  line-height: 1.2; color: #8FA4B6; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }

/* ══ THE PHONE LAYOUT ═══════════════════════════════════════════════════════
   ⚠⚠ THE CONTROLS USED TO FILL THE WHOLE SCREEN BEFORE ANY CONTENT.
   Measured on Strong › Movies › Categories at 390px, the first category row sat
   669px down: a 74px logo header, a breadcrumb, a page heading, a sync banner,
   a Back pill, six destination pills wrapped over three rows, a search box,
   three more wrapped buttons and the kind tabs — then, at last, a category.
   Owner: "The current controls take up an entire phone screen before the first
   category appears."

   ⚠ NOTHING IS MOVED IN THE DOM. The page becomes a flex column here and the
   rows are arranged with `order`, so the desktop layout keeps the source order
   it has always had and this file is the only thing that differs. The desktop
   toolbar is not deleted — it is hidden, still bound, and the phone controls
   press it (see drawMobile).

   ⚠ NO flex-wrap AS A LAYOUT STRATEGY. Wrapping is what produced three rows of
   pills; every row below is an explicit grid or a nowrap flex.        ════════ */
/* ⚠ THE PHONE ROWS DO NOT EXIST ON DESKTOP. Without this they are ordinary
   divs with content in them, so the desktop page grew a second header, a
   second view control and a second list heading above its own toolbar. They
   are switched on inside the query below and nowhere else. */
.lib-mhead, .lib-mview, .lib-mlisth { display: none; }

@media (max-width: 760px) {

  /* 1 — A COMPACT SITE HEADER. Scoped without a page class: channels.css is
     loaded by this page alone, and after app.css, so this override reaches
     nothing else. 74px → 56px. */
  .site-header .wrap { height: 56px; }
  .wordmark img { height: 34px; }
  .wordmark { font-size: 16px; }

  .lib { display: flex; flex-direction: column; }

  /* Replaced by the three rows below — not deleted, so their handlers live on
     and drawMobile can ask them what they would have done. */
  .lib-crumbs, .lib-head, .lib-back, .lib-dests, .lib-count { display: none; }

  .lib-mhead      { order: 1; }
  .lib-kinds      { order: 2; }
  .lib-tools      { order: 3; }
  .lib-chips      { order: 4; }
  .lib-mview      { order: 5; }
  .lib-mlisth     { order: 6; }
  #lib-list       { order: 7; }
  .lib-pager      { order: 8; }
  .lib-sheet-host { order: 9; }

  /* 2 — ONE PAGE-HEADER ROW: back · what you are looking at · more.
     Explicit columns, so a long playlist name can only ever eat the middle. */
  .lib-mhead { display: grid; grid-template-columns: 44px minmax(0, 1fr) 44px;
    align-items: center; gap: 4px; margin: 6px 0 10px; }
  .lib-m-icon { display: flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; border: 0; border-radius: 12px; background: none;
    color: inherit; cursor: pointer; }
  .lib-m-icon .material-symbols-rounded { font-size: 20px; }
  .lib-m-icon:hover { background: rgba(255,255,255,.08); }
  .lib-m-title { display: flex; align-items: center; justify-content: center;
    gap: 2px; min-width: 0; min-height: 44px; padding: 0 6px; border: 0;
    border-radius: 12px; background: none; color: inherit; font: inherit;
    font-size: 17px; font-weight: 600; cursor: pointer; }
  .lib-m-title[disabled] { cursor: default; }
  /* Truncated, never wrapped into a second header row — the full name is on the
     element's title attribute and read out by the accessible name. */
  .lib-m-title-tx { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .lib-m-title .material-symbols-rounded { font-size: 20px; flex: 0 0 auto; opacity: .7; }

  /* 3 — CONTENT TYPE AS ONE SEGMENTED CONTROL. Three equal columns, text only:
     the icons and counts are what made these three tall pills. The count is
     still on screen, in the list heading below. */
  .lib-kinds { grid-template-columns: repeat(3, 1fr); gap: 0; margin: 0 0 10px;
    height: 44px; border-radius: 12px; overflow: hidden;
    background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.10); }
  .lib-kind { flex-direction: row; justify-content: center; gap: 0; padding: 0;
    min-height: 0; height: 100%; border: 0; border-radius: 0; background: transparent; }
  .lib-kind .material-symbols-rounded, .lib-kind small { display: none; }
  .lib-kind b { font-size: 15px; font-weight: 600; }
  .lib-kind.on { background: #1AD6C5; }
  .lib-kind.on b { color: #06281f; }

  /* 4 — ONE SEARCH ROW. nowrap: the filter button sits beside the field or not
     at all, and can never push itself onto a line of its own. */
  .lib-tools { flex-wrap: nowrap; gap: 8px; margin-bottom: 10px; }
  .lib-tools > #lib-select, .lib-tools > #lib-addpl,
  .lib-tools > #lib-plsel-wrap, .lib-tools > #lib-reorder { display: none; }
  .lib-search { flex: 1 1 auto; min-width: 0; }
  .lib-search input { padding: 12px 0; }   /* 46px tall, still 16px text */
  #lib-filters { flex: 0 0 auto; min-height: 46px; padding: 0 14px; border-radius: 12px; }

  /* 5 — ONE VIEW SELECTOR in place of six pills. These are destinations, so it
     navigates; it does not pretend they are filters of one list. */
  .lib-mview { display: block; margin-bottom: 10px; }
  .lib-mview-btn { display: flex; align-items: center; gap: 8px; width: 100%;
    min-height: 44px; padding: 0 14px; border-radius: 12px;
    border: 1px solid rgba(255,255,255,.14); background: rgba(255,255,255,.03);
    color: inherit; font: inherit; font-size: 15px; cursor: pointer; text-align: left; }
  .lib-mview-lab { opacity: .6; flex: 0 0 auto; }
  .lib-mview-val { font-weight: 600; flex: 1 1 auto; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .lib-mview-btn .material-symbols-rounded { font-size: 20px; opacity: .7; flex: 0 0 auto; }

  /* 6 — LIST HEADING: what these rows are, how many, and Select. */
  .lib-mlisth { display: flex; align-items: center; gap: 10px; margin: 2px 0 8px; }
  .lib-m-lt { margin: 0; font-size: 15px; font-weight: 600; flex: 1 1 auto;
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .lib-m-lt span { opacity: .55; font-weight: 400; font-variant-numeric: tabular-nums; }
  .lib-m-lacts { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
  .lib-m-text { min-height: 44px; padding: 0 10px; border: 0; border-radius: 12px;
    background: none; color: #1AD6C5; font: inherit; font-size: 15px;
    font-weight: 600; cursor: pointer; }
  .lib-m-add { display: inline-flex; align-items: center; gap: 6px; min-height: 44px;
    padding: 0 14px; border-radius: 12px; border: 0; background: #1AD6C5;
    color: #06281f; font: inherit; font-size: 15px; font-weight: 600; cursor: pointer; }
  .lib-m-add .material-symbols-rounded { font-size: 19px; }


  /* 7 — THE SYNC LINE IS NOT A BANNER ANY MORE.
     ⚠ It said "Changes sync to all your devices" permanently, at the top, on a
     screen with no room for it — and it said it before anything had been
     changed. It is a transient toast now: nothing at rest, and when there IS
     something to report it is fixed to the bottom so it never shifts the list
     under the thumb that is reading it. Above the bulk bars (z-index 40) so a
     failure's Retry is always reachable. */
  /* ⚠ HIDDEN BY DEFAULT, SHOWN BY STATE — not the other way round. Hiding
     only .idle left it on screen at page load, because the markup ships with
     the bare class and nothing has called sync() yet: the banner this change
     exists to remove was still sitting there until the first save.
     There is no state in which it should appear before you have changed
     something, so the default is gone and each real state opts in. */
  .lib-sync { display: none; position: fixed; left: 12px; right: 12px;
    bottom: 12px; z-index: 45; margin: 0; border-radius: 12px;
    background: #12263a; box-shadow: 0 6px 20px rgba(0,0,0,.45); }
  .lib-sync.saving, .lib-sync.saved, .lib-sync.fail { display: flex; }
}

/* The desktop toolbar reappears above this; nothing below 760px reaches it. */

/* ── PICKING FILMS BY THEIR ARTWORK ───────────────────────────────────────
   ⚠ SELECT USED TO THROW YOU BACK TO THE ROW LIST. That was my call and it was
   wrong: you found these films by their posters, so being handed a list of
   names the moment you press Select takes away the one thing you were reading
   them by. Owner: "if i click select on the movie posters list in account it
   goes to the list view and the posters disapear ?"
   The wall stays; the card carries the tick. Reordering still drops to the
   list, because a drag handle has nowhere to sit on a poster. */
.lib-card-check { position: absolute; left: 6px; top: 6px; z-index: 4;
  width: 26px; height: 26px; border-radius: 6px; display: flex;
  align-items: center; justify-content: center;
  background: rgba(0,0,0,.6); box-shadow: 0 0 0 1px rgba(255,255,255,.35); }
.lib-card-check input { width: 17px; height: 17px; margin: 0; cursor: pointer;
  accent-color: #1AD6C5; }


/* ⚠ THE SELECTED STATE CANNOT BE THE TICK ALONE. A 26px box on a bright
   poster is easy to miss when you are scanning twelve of them, so the card
   itself answers: a turquoise ring and the artwork knocked back, which reads
   at arm's length on a phone. */
.lib-card.sel { box-shadow: 0 0 0 3px #1AD6C5; }
.lib-card.sel .lib-card-art img { opacity: .55; }
.lib-card.sel .lib-card-name { color: #1AD6C5; }
