/* The browsing look: a header that sits over the banner and firms up as you scroll, plain text
   navigation, posters in the manner of Plex, hero rows, and one set of easings for every
   movement. Loaded last, so it settles what the component layers before it leave open. Colours,
   fonts and corners still come from the theme. */

:root {
  --ease-out: cubic-bezier(0.22, 0.8, 0.24, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --top-h: 4.5rem;
  /* This device's card size (the slider on library pages), 0.8 to 1.4. */
  --card-scale: 1;
}

/* ---------- Type ---------- */
body { text-rendering: optimizeLegibility; font-kerning: normal; }
h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }
.section > h2 { font-size: calc(var(--heading-size, var(--type-section, 1.25rem)) * var(--type-scale, 1)); line-height: 1.3; margin-bottom: 0.85rem; }
.home-section-description { font-size: 0.92rem; margin: -0.45rem 0 1rem; }
.muted, .help { letter-spacing: 0; }

/* ---------- Header ---------- */
.top {
  position: sticky; top: 0; z-index: 30; isolation: isolate;
  min-height: var(--top-h); padding-block: 0.55rem; gap: 1.75rem;
  background: color-mix(in srgb, var(--bg) 84%, transparent);
  -webkit-backdrop-filter: saturate(1.3) blur(18px); backdrop-filter: saturate(1.3) blur(18px);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 40%, transparent);
  transition: background-color 0.4s var(--ease-out), border-color 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out);
}
.top.scrolled { box-shadow: 0 10px 30px -18px rgb(0 0 0 / 0.55); }
/* Over the homepage banner: clear until the page moves, with a soft shade so the links read. */
.top.over-art:not(.scrolled):not(.nav-open) { background: transparent; border-bottom-color: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; }
.top::before { content: ""; position: absolute; inset: 0 0 -3rem; z-index: -1; pointer-events: none; opacity: 0;
  background: linear-gradient(to bottom, color-mix(in srgb, var(--bg) 72%, transparent), transparent); transition: opacity 0.4s var(--ease-out); }
.top.over-art:not(.scrolled)::before { opacity: 1; }
.top .wordmark { font-size: 1.65rem; font-weight: 700; letter-spacing: -0.035em; }

/* Links as words, with a line that slides in under the current one. */
.top:not(.compact-nav) .nav { gap: 1.6rem; }
.top:not(.compact-nav) .nav a { position: relative; padding: 0.55rem 0; border-radius: 0; background: none;
  color: color-mix(in srgb, var(--text) 70%, transparent); font: 500 0.92rem/1.4 var(--font-body); transition: color 0.2s ease; }
.top:not(.compact-nav) .nav a::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0.15rem; height: 2px; border-radius: 2px;
  background: var(--accent); transform: scaleX(0); transform-origin: left center; transition: transform 0.35s var(--ease-out), opacity 0.2s; }
.top:not(.compact-nav) .nav a:hover { color: var(--text); background: none; }
.top:not(.compact-nav) .nav a:hover::after { transform: scaleX(1); opacity: 0.35; }
.top:not(.compact-nav) .nav a[aria-current="page"] { color: var(--text); background: none; }
.top:not(.compact-nav) .nav a[aria-current="page"]::after { transform: scaleX(1); opacity: 1; }
.top.compact-nav .nav { animation: menu-in 0.2s var(--ease-out); }

.top .search-form { position: relative; flex: 0 1 17rem; }
.top .search { height: var(--control-h); min-height: 0; padding: 0 1rem 0 2.5rem; border: 1px solid transparent; border-radius: 999px;
  background: color-mix(in srgb, var(--text) 9%, transparent); color: var(--text);
  transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease; }
.top .search:hover { background: color-mix(in srgb, var(--text) 13%, transparent); }
.top .search:focus { outline: none; background: color-mix(in srgb, var(--bg) 70%, transparent); border-color: color-mix(in srgb, var(--text) 35%, transparent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 22%, transparent); }
.search-icon { position: absolute; left: 0.9rem; top: 50%; width: 1rem; height: 1rem; margin-top: -0.5rem; color: var(--muted); pointer-events: none; }

.admin-shortcut { width: var(--control-h); height: var(--control-h); min-width: 0; min-height: 0; padding: 0; border-radius: var(--control-radius); color: color-mix(in srgb, var(--text) 75%, transparent); }
/* The header's icons, all one size. */
.admin-shortcut svg, .top-icon svg, .search-close svg { width: 1.375rem; height: 1.375rem; }
.admin-shortcut:hover, .admin-shortcut[aria-current="page"] { background: color-mix(in srgb, var(--text) 12%, transparent); color: var(--text); }

/* The account: a round initial, the name inside the menu. */
.account-menu summary { width: var(--control-h); height: var(--control-h); min-height: 0; max-width: none; padding: 0; justify-content: center; border-radius: 50%;
  background: hsl(var(--avatar-hue, 150) 32% 38%); color: #fff; font: 600 1rem/1 var(--font-body); box-shadow: 0 0 0 2px transparent;
  transition: box-shadow 0.2s ease, transform 0.2s var(--ease-out); }
.account-menu summary:hover, .account-menu[open] summary { box-shadow: 0 0 0 2px color-mix(in srgb, var(--text) 55%, transparent); }
.account-menu summary #me-name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.account-who { margin: 0 0 0.35rem; padding: 0.35rem 0.7rem 0.6rem; border-bottom: 1px solid var(--line); display: grid; gap: 0.1rem; }
.account-who strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Their picture fills the round button, and sits beside their name in the menu (profiles.js). */
.account-menu summary #me-avatar { display: grid; width: 100%; height: 100%; }
.account-menu summary #me-avatar .avatar { width: 100%; height: 100%; font-size: 1rem; }
.account-who:has(.avatar) { display: flex; align-items: center; gap: 0.65rem; }
.account-menu[open] .account-links { animation: menu-in 0.2s var(--ease-out); transform-origin: top right; }
/* More menus open the same way. */
details.more[open] > .more-menu { animation: more-in 0.18s var(--ease-out); }
/* Up and in only: util.js measures the menu as it opens to keep it on the screen. */
@keyframes more-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@keyframes menu-in { from { opacity: 0; transform: translateY(-6px) scale(0.98); } to { opacity: 1; transform: none; } }

/* ---------- Cards ---------- */
.art { background: color-mix(in srgb, var(--text) 6%, var(--surface)); }
.art img[data-fade] { opacity: 0; transition: opacity 0.5s var(--ease-out), filter 0.25s ease; }
.art img[data-fade].loaded { opacity: 1; }
.card .art { transition: transform 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out); }
.card:hover .art, .card:focus-visible .art { transform: translateY(-4px); box-shadow: 0 12px 22px -12px rgb(0 0 0 / 0.7), 0 0 0 2px color-mix(in srgb, var(--text) 75%, transparent); }
.card:focus-visible .art { outline: none; box-shadow: 0 12px 22px -12px rgb(0 0 0 / 0.7), 0 0 0 3px var(--accent); }
.card:hover .art img { filter: brightness(1.06); }
/* Pictures that aren't cards but open like them (Coming soon, a channel in On now) lift the same way. */
:is(.upcoming-open, .live-tune) .art { transition: transform 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out); }
:is(.upcoming-open, .live-tune):hover .art { transform: translateY(-4px); box-shadow: 0 12px 22px -12px rgb(0 0 0 / 0.7), 0 0 0 2px color-mix(in srgb, var(--text) 75%, transparent); }
/* Titles take one line and the line under it is always there, so rows never change height. */
.card h3 { margin: 0.6rem 0 0.1rem; font: 500 0.92rem/1.45 var(--font-body); letter-spacing: -0.005em; }
.card p { min-height: 1.45em; font-size: 0.82rem; line-height: 1.45; }
.card.poster p + p { margin-top: 0; }
.progress { height: 3px; background: rgb(0 0 0 / 0.45); }
.progress span { border-radius: 0 2px 2px 0; background: var(--accent); }
.badge { border-radius: 4px; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.01em; }
/* Continue watching: a play mark over the picture when pointed at. The picture plays; the words
   under it open the episode's or film's page (views.js playCard). */
.card.resume > a { display: block; color: inherit; text-decoration: none; }
.card.resume .art::after { content: ""; position: absolute; inset: 0; background: rgb(0 0 0 / 0.35); opacity: 0; transition: opacity 0.25s ease; }
.card.resume .play-mark { position: absolute; z-index: 1; left: 50%; top: 50%; width: 3rem; height: 3rem; margin: -1.5rem 0 0 -1.5rem; border-radius: 50%;
  background: rgb(255 255 255 / 0.92); opacity: 0; transform: scale(0.85); transition: opacity 0.25s ease, transform 0.3s var(--ease-out); }
.card.resume .play-mark::after { content: ""; position: absolute; left: 1.15rem; top: 0.85rem; border-style: solid; border-width: 0.65rem 0 0.65rem 1rem; border-color: transparent transparent transparent #111; }
.card.resume .card-play:hover .art::after, .card.resume .card-play:focus-visible .art::after { opacity: 1; }
.card.resume .card-play:hover .play-mark, .card.resume .card-play:focus-visible .play-mark { opacity: 1; transform: none; }
.card.resume .card-play:focus-visible { outline: none; }
.card.resume .card-play:focus-visible .art { transform: translateY(-4px); box-shadow: 0 12px 22px -12px rgb(0 0 0 / 0.7), 0 0 0 3px var(--accent); }
.card.resume .card-about:hover h3 { text-decoration: underline; text-underline-offset: 3px; }
.card.resume .card-about:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; border-radius: 4px; }
/* Without a pointer to hover with, the play mark is always there, smaller. */
@media (hover: none) { .card.resume .play-mark { opacity: 0.9; transform: scale(0.75); } }

/* This device's card size. */
.grid { grid-template-columns: repeat(auto-fill, minmax(calc(9.5rem * var(--card-scale)), 1fr)); gap: calc(2.2rem * var(--card-scale)) calc(1.5rem * var(--card-scale)); }
.home-section .row.posters { grid-auto-columns: calc(var(--card-size, clamp(8.5rem, 15cqw, 10.5rem)) * var(--card-scale)); }
.home-section .row.wide { grid-auto-columns: calc(var(--card-size-wide, clamp(14rem, 24cqw, 18.5rem)) * var(--card-scale)); }
.card-size { display: inline-flex; align-items: center; gap: 0.6rem; color: var(--muted); font-size: 0.85rem; }
.toolbar .card-size { margin-left: auto; margin-right: 0.75rem; }
.toolbar .card-size + .sort { margin-left: 0; }
.card-size input { width: 7rem; }
.card-size .cs-small, .card-size .cs-large { flex: none; border: 1.6px solid currentColor; border-radius: 2px; }
.card-size .cs-small { width: 0.55rem; height: 0.8rem; }
.card-size .cs-large { width: 0.8rem; height: 1.15rem; }
@media (max-width: 640px) { .card-size { display: none; } }

/* ---------- Rows ---------- */
/* Room for a card to lift and ring without the row's edge clipping it. */
.home-section .row { padding: 0.55rem 0.35rem 1rem; margin: -0.55rem -0.35rem 0; scroll-padding-inline: 0.35rem; }
.home-section { padding-bottom: var(--section-space, 1.4rem); }
.home-section > h2 a { display: inline-flex; align-items: baseline; gap: 0.35rem; text-decoration: none; }
.home-section > h2 a::after { content: "›"; color: var(--muted); font-weight: 400; transition: transform 0.25s var(--ease-out), color 0.2s; }
.home-section > h2 a:hover { text-decoration: none; }
.home-section > h2 a:hover::after { transform: translateX(4px); color: var(--text); }
.rail-btn { width: var(--control-h); height: var(--control-h); border-radius: var(--control-radius); border: 1px solid color-mix(in srgb, var(--text) 16%, transparent);
  background: color-mix(in srgb, var(--bg) 86%, transparent); -webkit-backdrop-filter: none; backdrop-filter: none; color: var(--text);
  box-shadow: 0 8px 20px -8px rgb(0 0 0 / 0.6); transform: scale(0.88); transition: opacity 0.25s ease, transform 0.3s var(--ease-out), background-color 0.2s ease, color 0.2s ease; }
.rail:hover .rail-btn, .rail-btn:focus-visible { opacity: 1; transform: none; }
.rail-btn:hover { background: var(--text); color: var(--bg); border-color: var(--text); }
.rail-btn:active { transform: scale(0.94); }

/* ---------- Banner ---------- */
/* On the homepage it runs under the header, and the first row tucks up over its foot. */
.home-page > .banner:first-child { margin: calc(-1 * var(--top-h)) 0 0; height: clamp(28rem, 78vh, 52rem); max-height: none; min-height: 0; aspect-ratio: auto; border-radius: 0; }
.home-page > .banner:first-child .banner-text { padding-bottom: clamp(6rem, 13vh, 8.5rem); max-width: 40rem; }
/* The banner fades into the page in the theme's own colours, day or night, and the first row
   tucks up over its foot. */
.home-page > .banner:first-child + .visually-hidden + .home-section { position: relative; z-index: 2; margin-top: -4.25rem; }
.home-page > .banner:first-child .banner-nav { bottom: clamp(5rem, 11vh, 7rem); }
.banner { overflow: hidden; }
/* The new title fades in over the last, which stays put underneath until it's covered. */
.banner-slide { opacity: 0; visibility: hidden; z-index: 0; transition: opacity 1.1s var(--ease-in-out), visibility 0s linear 1.1s; }
.banner-slide.leaving { opacity: 1; visibility: visible; z-index: 1; transition: none; }
.banner-slide.shown { opacity: 1; visibility: visible; z-index: 2; transition: opacity 1.1s var(--ease-in-out), visibility 0s; }
.banner-nav { z-index: 4; }
.banner-art { transform-origin: 60% 40%; will-change: transform; }
.banner-slide.shown .banner-art, .banner-slide.leaving .banner-art { animation: ken-burns 14s linear both; }
@keyframes ken-burns { from { transform: scale(1.02); } to { transform: scale(1.09) translate(-0.6%, -0.4%); } }
.banner-slide::after { background:
  linear-gradient(to right, color-mix(in srgb, var(--bg) 92%, transparent), color-mix(in srgb, var(--bg) 60%, transparent) 28%, transparent 62%),
  linear-gradient(to top, var(--bg) 2%, color-mix(in srgb, var(--bg) 55%, transparent) 22%, transparent 48%); }
.banner-text { gap: 0.7rem; }
.banner-label { text-transform: uppercase; letter-spacing: 0.12em; font-size: 0.72rem; font-weight: 600; }
.banner-title { font-size: calc(clamp(2.2rem, 4.4vw, 3.6rem) * var(--type-scale, 1)); line-height: 1.04; letter-spacing: -0.03em; font-weight: 700; margin: 0; }
.banner-logo { display: block; max-width: min(26rem, 72vw); max-height: clamp(4.5rem, 14vh, 9rem); width: auto; height: auto; object-fit: contain; object-position: left bottom;
  filter: drop-shadow(0 4px 18px rgb(0 0 0 / 0.55)); }
.banner-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 0.65rem; font-size: 0.92rem; color: color-mix(in srgb, var(--text) 82%, transparent); }
.banner-meta > span + span::before { content: "·"; margin-right: 0.65rem; color: var(--muted); }
/* .age-badge is drawn with .rating-box (style.css). */
.banner-meta > .age-badge + span::before, .banner-meta > span + .age-badge::before { content: none; }
.banner-meta .meta-star { display: inline-block; width: 0.85em; height: 0.85em; margin-right: 0.3em; vertical-align: -0.06em; background: var(--accent);
  clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%); }
.banner-overview { font-size: 1rem; max-width: 34rem; color: color-mix(in srgb, var(--text) 86%, transparent); }
.banner .actions { gap: 0.6rem; margin-top: 0.35rem; }
.banner .actions .primary { padding-inline: 1.6rem; }
.banner .actions .primary::before { content: ""; width: 0; height: 0; border-style: solid; border-width: 0.4rem 0 0.4rem 0.62rem; border-color: transparent transparent transparent currentColor; margin-right: 0.15rem; }
.banner .actions .ghost { background-color: color-mix(in srgb, var(--text) 18%, transparent); color: var(--text); }
.banner .actions .ghost:hover { background-color: color-mix(in srgb, var(--text) 26%, transparent); }
/* The owner's own slides (bannerView's ownSlide): their button goes somewhere rather than
   playing, so no play mark; without a picture, a wash of the accent behind the words. */
.banner-own .actions .primary::before { content: none; }
.banner-own.no-art { background: radial-gradient(120% 90% at 85% 15%, color-mix(in srgb, var(--accent) 34%, transparent), transparent 70%); }
.banner-own .banner-title { overflow-wrap: anywhere; }
/* Bars that fill while a title is up; the next one comes when the bar is full. */
.banner-nav { position: absolute; right: var(--gutter); bottom: 1.1rem; display: flex; align-items: center; gap: 0.7rem; }
.banner-nav .banner-dots { position: static; display: flex; gap: 0.4rem; align-items: center; }
.banner-dot { position: relative; width: 1.9rem; height: 0.28rem; border-radius: 99px; border: 0; overflow: hidden; background: color-mix(in srgb, var(--text) 28%, transparent);
  transition: width 0.4s var(--ease-out), background-color 0.2s; }
.banner-dot::before { content: ""; position: absolute; inset: -0.6rem -0.1rem; }
.banner-dot:hover { background: color-mix(in srgb, var(--text) 50%, transparent); }
.banner-dot[aria-current="true"] { width: 3.2rem; background: color-mix(in srgb, var(--text) 28%, transparent); }
.banner-dot::after { content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--text); transform: scaleX(0); transform-origin: left center; }
.banner-dot[aria-current="true"]::after { transform: scaleX(1); }
.banner.playing .banner-dot[aria-current="true"]::after { animation: banner-fill var(--banner-interval, 8s) linear both; }
.banner.paused .banner-dot[aria-current="true"]::after { animation-play-state: paused; }
@keyframes banner-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.banner-arrow { flex: none; width: 2.25rem; height: 2.25rem; display: grid; place-items: center; padding: 0; border-radius: var(--control-radius);
  border: 1px solid color-mix(in srgb, var(--text) 18%, transparent); background: color-mix(in srgb, var(--bg) 62%, transparent); color: var(--text); cursor: pointer;
  opacity: 0.75; transition: opacity 0.25s ease, background-color 0.2s ease, color 0.2s ease; }
.banner:hover .banner-arrow, .banner-arrow:focus-visible { opacity: 1; }
.banner-arrow:hover { background: var(--text); color: var(--bg); }
.banner-arrow .chev { width: 0.5rem; height: 0.5rem; border: solid currentColor; border-width: 0 2.5px 2.5px 0; transform: rotate(-45deg); margin-right: 0.2rem; }
.banner-arrow.prev .chev { transform: rotate(135deg); margin: 0 0 0 0.2rem; }
@media not (any-hover: hover) { .banner-arrow { display: none; } }
/* Pause and play, for a banner that moves on by itself: on touch screens too, which have no
   arrows. */
.banner-pause { opacity: 1; }
@media (hover: none) { .banner-pause { display: grid; } }
/* On a phone the bars run the width of the banner, so its words sit a little higher, clear of
   the pause button beside them. */
@media (max-width: 640px) { html:not(.tv) .banner.playing .banner-text { margin-bottom: 1.75rem; } }
.pause-mark { width: 0.72rem; height: 0.78rem; border-inline: 0.24rem solid currentColor; }
.banner-pause[aria-pressed="true"] .pause-mark { width: 0; height: 0; border-style: solid; border-width: 0.42rem 0 0.42rem 0.66rem; border-color: transparent transparent transparent currentColor; margin-left: 0.18rem; }
/* On a TV (html.tv) the remote steps through the titles with left and right on the banner, and
   the banner waits while it has focus: its arrows and pause aren't stops, so they aren't drawn. */
html.tv .banner-arrow { display: none; }
html.tv .banner :is(a, button):focus-visible { outline: 3px solid var(--text); outline-offset: 3px; }
html.tv .banner-dot { height: 0.4rem; }
.banner-slide.shown .banner-text > * { animation: rise-in 0.7s var(--ease-out) both; }
.banner-slide.shown .banner-text > :nth-child(2) { animation-delay: 0.08s; }
.banner-slide.shown .banner-text > :nth-child(3) { animation-delay: 0.14s; }
.banner-slide.shown .banner-text > :nth-child(n + 4) { animation-delay: 0.2s; }
@media (max-width: 640px) {
  .home-page > .banner:first-child { height: clamp(30rem, 82vh, 40rem); }
  .home-page > .banner:first-child .banner-text { padding-bottom: 6.5rem; }
  .home-page > .banner:first-child .banner-nav { left: var(--gutter); right: auto; bottom: 4.75rem; }
  :root:not([data-scheme="light"]) .home-page > .banner:first-child + .visually-hidden + .home-section { margin-top: -3rem; }
}

/* A title's page: its backdrop runs under the header as well. */
#page > .hero:first-child:not(.plain) { margin-top: calc(-1 * var(--top-h)); min-height: calc(clamp(20rem, 56vh, 36rem) + var(--top-h)); }

/* ---------- Hero rows (Expanded): the chosen title opens out in place ---------- */
.row.expanded { align-items: stretch; }
/* The open title is kept at the row's left edge by script (views.js heroRail), so the row
   doesn't snap, and isn't smooth-scrolled on top of the script's own movement. A swipe across
   it is the script's too, a title at a time; up and down still scroll the page. */
.row.expanded { scroll-snap-type: none; scroll-behavior: auto; touch-action: pan-y; }
.row.expanded > * { scroll-snap-align: none; }
/* Room after the last title, so it too can open at the left edge. */
.row.expanded > .hero-end { flex: 0 0 max(0px, calc(100% - var(--expanded-width) - var(--card-gap, 1.4rem))); }
/* Sized as an open and a closed card are (home.css), but never animated: the script reads where
   a title will come to rest from these while the cards are still moving. */
.row.expanded > .hero-measure { position: absolute; top: 0; left: 0; width: var(--expanded-width); height: 0; visibility: hidden; pointer-events: none; }
.row.expanded > .hero-measure.shut { width: calc(var(--expanded-width) * 0.375); }
.home-expanded-card { position: relative; transition: flex-basis 0.55s var(--ease-in-out); }
.home-expand-pick { position: relative; border-radius: var(--media-radius); overflow: visible; }
.home-expand-pick .art { transition: box-shadow 0.35s var(--ease-out), transform 0.35s var(--ease-out); }
.home-expand-pick:hover .art { transform: translateY(-3px); box-shadow: 0 12px 22px -12px rgb(0 0 0 / 0.7), 0 0 0 2px color-mix(in srgb, var(--text) 70%, transparent); }
.home-expanded-card.selected .home-expand-pick { outline: none; }
.home-expanded-card.selected .home-expand-pick .art { box-shadow: 0 18px 36px -18px rgb(0 0 0 / 0.8); transform: none; }
.home-expand-pick:focus-visible { outline: none; }
.home-expand-pick:focus-visible .art { box-shadow: 0 0 0 3px var(--accent); }
/* The open title is one link to its page (or a trailer row's button), laid over its picture and
   words: its ring and its hover go on the picture. */
.hero-open { position: absolute; inset: 0; z-index: 1; display: block; padding: 0; border: 0; border-radius: var(--media-radius); background: none; cursor: pointer; }
.home-expanded-card:not(.selected) > .hero-open { display: none; }
.hero-open:focus-visible { outline: none; }
.home-expanded-card:has(> .hero-open:focus-visible) .home-expand-pick .art { box-shadow: 0 0 0 3px var(--accent); }
.home-expanded-card:has(> .hero-open:hover) .home-expand-pick .art :is(.tall-art, .wide-art) { filter: brightness(1.06); }
.home-expanded-card:has(> .hero-open:hover) .home-expanded-copy h3 { text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 2px; }
/* The poster and the wide picture sit on each other and cross-fade as the card opens. (Only
   those two: the title's lettering sits in the same box and keeps its own size.) */
.home-expand-pick .art :is(.tall-art, .wide-art) { position: absolute; inset: 0; transition: opacity 0.55s var(--ease-in-out), transform 0.9s var(--ease-out); }
.home-expand-pick .art .wide-art { opacity: 0; transform: scale(1.04); }
.home-expanded-card.selected .home-expand-pick .art .wide-art.loaded { opacity: 1; transform: none; }
.home-expanded-card.selected .home-expand-pick .art .tall-art { opacity: 0; }
/* The lettering fits whole in the bottom-left corner: .art's own rule for pictures (full size,
   cropped to fill) mustn't reach it, so this is written to outrank that. */
.art .hero-logo { position: absolute; left: 1rem; bottom: 0.9rem; z-index: 1; width: auto; height: auto; max-width: 55%; max-height: 38%; object-fit: contain; object-position: left bottom;
  filter: drop-shadow(0 2px 12px rgb(0 0 0 / 0.6)); opacity: 0; transform: translateY(6px); transition: opacity 0.4s ease 0.25s, transform 0.5s var(--ease-out) 0.25s; pointer-events: none; }
.home-expanded-card.selected .hero-logo.loaded { opacity: 1; transform: none; }
.home-expand-pick .art::after { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity 0.5s ease;
  background: linear-gradient(to top, rgb(0 0 0 / 0.55), transparent 55%); }
.home-expanded-card.selected:has(.hero-logo.loaded) .home-expand-pick .art::after { opacity: 1; }
/* Under each card, a fixed height of words: one line for a neighbour, the full block for the chosen one. */
.home-expanded-card > .hero-short, .home-expanded-copy { transition: opacity 0.3s ease; }
.hero-short h3 { margin: 0.65rem 0 0.1rem; font: 500 0.92rem/1.45 var(--font-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hero-short p { margin: 0; min-height: 1.45em; font-size: 0.82rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-expanded-card.selected > .hero-short { display: none; }
.home-expanded-card:not(.selected) > .home-expanded-copy { display: none; }
.home-expanded-copy { padding-top: 0.85rem; min-width: 0; animation: copy-in 0.5s var(--ease-out) 0.12s both; }
.home-expanded-copy > .muted { display: flex; flex-wrap: wrap; gap: 0 0.55rem; margin: 0; height: 1.4rem; overflow: hidden; font-size: 0.84rem; }
.home-expanded-copy > .muted > span + span::before { content: "·"; margin-right: 0.55rem; }
.home-expanded-copy h3 { margin: 0.3rem 0 0; font-size: 1.4rem; line-height: 1.3; height: 1.3em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; letter-spacing: -0.02em; }
.home-expanded-overview { margin: 0.5rem 0 0; font-size: 0.93rem; line-height: 1.6; height: 4.8em; color: var(--muted); }
@keyframes copy-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ---------- Collections: a tile each, as Disney+ has its brands ---------- */
.home-section .row.collections { grid-auto-columns: calc(clamp(15rem, 26cqw, 21rem) * var(--card-scale)); }
.rail:has(.row.collections) .rail-btn { top: calc(50% - 1.375rem); }
.collection-tile .art { aspect-ratio: 16 / 9; }
.collection-back { position: absolute; inset: 0; }
.collection-back img { position: absolute; object-fit: cover; }
.collection-back .cb-wide { inset: 0; width: 100%; height: 100%; filter: brightness(0.6) saturate(1.05); transform: scale(1.02);
  transition: opacity 0.5s var(--ease-out), transform 0.9s var(--ease-out), filter 0.4s ease; }
.collection-back .cb-tall { top: 13%; height: 74%; width: auto; aspect-ratio: 2 / 3; border-radius: 6px; box-shadow: 0 12px 22px -8px rgb(0 0 0 / 0.75);
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out); }
.collection-back .cb-1 { right: 22%; transform: rotate(-5deg); }
.collection-back .cb-2 { right: 7%; transform: rotate(4deg); }
.collection-tile:hover .cb-wide, .collection-tile:focus-visible .cb-wide { transform: scale(1.08); filter: brightness(0.7) saturate(1.1); }
.collection-tile:hover .cb-1, .collection-tile:focus-visible .cb-1 { transform: rotate(-9deg) translate(-10px, -3px); }
.collection-tile:hover .cb-2, .collection-tile:focus-visible .cb-2 { transform: rotate(8deg) translate(6px, -3px); }
.collection-name { position: absolute; inset: auto 0 0 0; z-index: 1; display: grid; gap: 0.15rem; padding: 2.5rem 1rem 0.9rem; color: #fff;
  background: linear-gradient(to top, rgb(0 0 0 / 0.72), transparent); }
.collection-name strong { max-width: 62%; font: 700 1.2rem/1.2 var(--font-display); letter-spacing: -0.02em; text-shadow: 0 2px 10px rgb(0 0 0 / 0.5);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.collection-name span { font-size: 0.8rem; opacity: 0.8; }

/* ---------- Loading ---------- */
.skeleton { pointer-events: none; }
.sk { border-radius: var(--media-radius); background: linear-gradient(100deg, color-mix(in srgb, var(--text) 6%, transparent) 30%, color-mix(in srgb, var(--text) 12%, transparent) 50%, color-mix(in srgb, var(--text) 6%, transparent) 70%);
  background-size: 300% 100%; animation: shimmer 1.4s ease-in-out infinite; }
.sk-banner { height: clamp(24rem, 62vh, 40rem); margin: calc(-1 * var(--top-h)) 0 1.5rem; border-radius: 0; }
.sk-line { height: 1.1rem; width: 12rem; margin: 0 0 1rem; border-radius: 6px; }
.sk-line.short { width: 7rem; height: 0.8rem; margin: 0.6rem 0 0; }
.sk-row { display: flex; gap: 1.4rem; overflow: hidden; }
.sk-poster { flex: 0 0 calc(clamp(8.5rem, 15vw, 10.5rem) * var(--card-scale)); aspect-ratio: 2 / 3; }
.sk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(calc(9.5rem * var(--card-scale)), 1fr)); gap: calc(2.2rem * var(--card-scale)) calc(1.5rem * var(--card-scale)); }
.sk-hero { height: calc(clamp(20rem, 56vh, 36rem) + var(--top-h)); margin: calc(-1 * var(--top-h)) 0 2rem; border-radius: 0; }
.skeleton .sk-title { height: 2rem; width: min(22rem, 70%); margin: 0 0 1.5rem; border-radius: 8px; }
.sk-bar { height: 4.5rem; margin: 0 0 0.75rem; border-radius: var(--radius); }
.skeleton { animation: fade-in 0.4s ease both; }
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }

/* ---------- Pages ---------- */
#page > * { animation: page-in 0.32s var(--ease-out) both; }
#page > *:nth-child(2) { animation-delay: 0.02s; }
#page > *:nth-child(3) { animation-delay: 0.04s; }
#page > *:nth-child(n + 4) { animation-delay: 0.06s; }
@keyframes page-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.home-page > .banner:first-child { animation: fade-in 0.7s ease both !important; }
html { scroll-padding-top: calc(var(--top-h) + 0.5rem); }
@media (prefers-reduced-motion: no-preference) { html:focus-within { scroll-behavior: smooth; } }

/* ---------- The page's scrollbar ---------- */
/* Thin and in the theme's colours on a computer with a mouse, so a laptop without a trackpad can
   still see and drag it, as the admin console has it (web #34). Touch screens and TVs scroll
   without one (admin.css hides it by default). Rows keep theirs hidden. */
@media (hover: hover) and (pointer: fine) {
  html:not(.tv) { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--muted) 50%, transparent) transparent; }
  html:not(.tv)::-webkit-scrollbar { display: block; width: 10px; }
  html:not(.tv)::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--muted) 50%, transparent); background-clip: content-box; border: 3px solid transparent; border-radius: 999px; }
  html:not(.tv)::-webkit-scrollbar-track { background: transparent; }
}

/* ---------- Everywhere ---------- */
a, button { -webkit-tap-highlight-color: transparent; }
.row { scroll-behavior: smooth; }
.hero-bg { transition: opacity 0.6s ease; }

@media (prefers-reduced-motion: reduce) {
  .top, .top::before, .top .nav a::after, .card .art, .art img[data-fade], .rail-btn, .banner-slide, .banner-dot, .banner-arrow, .home-expanded-card,
  .home-expand-pick .art img, .hero-logo { transition: none !important; }
  .collection-back img { transition: none !important; }
  .banner-slide.shown .banner-art, .banner-slide.leaving .banner-art, .banner-slide.shown .banner-text > *, .home-expanded-copy, #page > *, .skeleton, .sk,
  .account-menu[open] .account-links, .top.compact-nav .nav, details.more[open] > .more-menu { animation: none !important; }
  .card:hover .art, .home-expand-pick:hover .art, :is(.upcoming-open, .live-tune):hover .art { transform: none; }
  :is(.upcoming-open, .live-tune) .art { transition: none; }
  .row { scroll-behavior: auto; }
}

@media (max-width: 900px) { .top.compact-nav { gap: 0.9rem; } }
@media (max-width: 640px) {
  .top, .top.compact-nav { gap: 0.55rem; }
  .top .wordmark { font-size: 1.4rem; }
  .top .search { padding-left: 2.2rem; padding-right: 0.6rem; }
  .search-icon { left: 0.75rem; }
}

/* ---------- Phones and touch tablets: a compact header, and tabs along the bottom (tabs.js) ---------- */
/* As Plex's and Netflix's apps have it: the name, then search, casting, My list and the account,
   and Home and the site's links as tabs at the bottom, where a thumb reaches them, clear of the
   home indicator or gesture bar. The same in the Android app, whose frame already keeps clear of
   the system bars. Not on TVs (html.tv), which keep the header their remote moves around.
   A tablet is a touch screen from 641 to 1366 pixels wide (tabs.js TABLET): the same tabs in
   either orientation, so turning it round never moves anything. */
.top-icon, .search-close, .tab-bar { display: none; }
@media (max-width: 640px), (pointer: coarse) and (hover: none) and (max-width: 1366px) {
  html:not(.tv) { --tabs-h: 3.5rem; }
  html:not(.tv) #top > .wordmark { margin-right: auto; }
  html:not(.tv) #top .nav-toggle, html:not(.tv) #top .nav { display: none !important; }
  html:not(.tv) .top-icon:not([hidden]) { display: inline-grid; place-items: center; flex: none; width: var(--control-h); height: var(--control-h); padding: 0; border: 0; border-radius: var(--control-radius);
    background: none; color: var(--text); text-decoration: none; cursor: pointer; }
  html:not(.tv) .top-icon:hover { background: color-mix(in srgb, var(--text) 10%, transparent); }
  html:not(.tv) .top-icon[aria-current="page"] { color: var(--accent); }
  html:not(.tv) .top-icon.cast-slot google-cast-launcher { width: 1.5rem; height: 1.5rem; }


  html:not(.tv) .tab-bar:not([hidden]) { display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
    padding: 0 max(0.25rem, env(safe-area-inset-right, 0px)) env(safe-area-inset-bottom, 0px) max(0.25rem, env(safe-area-inset-left, 0px));
    background: color-mix(in srgb, var(--bg) 92%, transparent); -webkit-backdrop-filter: saturate(1.3) blur(18px); backdrop-filter: saturate(1.3) blur(18px);
    border-top: 1px solid color-mix(in srgb, var(--line) 45%, transparent); }
  /* Only the bar's: the Edit dialog's Details and Poster tabs are .tab too. */
  .tab-bar .tab { flex: 1 1 0; min-width: 0; min-height: var(--tabs-h); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.2rem;
    padding: 0.35rem 0.15rem; border: 0; border-radius: var(--radius); background: none; color: var(--muted); font: 500 0.7rem/1.2 var(--font-body); text-decoration: none; cursor: pointer; }
  .tab-bar .tab svg { flex: none; width: 1.5rem; height: 1.5rem; fill: currentColor; }
  .tab-bar .tab span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tab-bar .tab[aria-current="page"], .tab-bar .tab.is-current { color: var(--accent); }
  .tab-bar .tab:focus-visible { outline: 2px solid var(--ring); outline-offset: -3px; }
  /* Room for the tabs at the end of every page, and above them for messages and save bars. */
  html:not(.tv) body:has(> .tab-bar:not([hidden])) { --tabs: calc(var(--tabs-h) + env(safe-area-inset-bottom, 0px)); }
  html:not(.tv) body:has(> .tab-bar:not([hidden])) > #page { padding-bottom: calc(3rem + var(--tabs-h)); }
  html:not(.tv) body:has(> .tab-bar:not([hidden])) > .toasts { bottom: calc(var(--tabs) + 1rem); }
  html:not(.tv) body:has(> .tab-bar:not([hidden])) .save-bar { bottom: calc(var(--tabs) + 0.75rem); }
}
/* A phone: search is an icon until it's wanted, and admin is in the account menu. */
@media (max-width: 640px) {
  html:not(.tv) #top { gap: 0.15rem; }
  html:not(.tv) #top .admin-shortcut { display: none !important; }
  html:not(.tv) #top:not(.search-open) .search-form { display: none; }
  /* Search opens over the header's row, with Close beside it. */
  html:not(.tv) #top.search-open > :not(.search-form) { visibility: hidden; }
  html:not(.tv) #top.search-open .search-form { position: absolute; inset: 0 var(--gutter); display: flex; align-items: center; gap: 0.35rem; }
  html:not(.tv) #top.search-open .search { flex: 1; min-width: 0; }
  html:not(.tv) #top.search-open .search-close { display: inline-grid; place-items: center; flex: none; width: var(--control-h); height: var(--control-h); padding: 0; border: 0; border-radius: var(--control-radius);
    background: none; color: var(--text); cursor: pointer; }
}

/* ---------- Tablets ---------- */
/* Designed for a hand, not a stretched phone or a squeezed desktop: the search box is always
   there in the header (there's room), and the tabs sit side by side with their names beside
   their icons, as iPad apps have them, in a bar the width of a comfortable reach. Cards, buttons
   and the player's controls are sized for a fingertip (44 px and up). */
@media (pointer: coarse) and (hover: none) and (min-width: 641px) and (max-width: 1366px) {
  html:not(.tv) { --tabs-h: 3.75rem; }
  html:not(.tv) #top { gap: 0.4rem; }
  html:not(.tv) #top .search-form { flex: 0 1 24rem; margin-left: 0; margin-right: 0.35rem; }
  html:not(.tv) #top .search { height: var(--control-h); }
  html:not(.tv) #top #search-open, html:not(.tv) #top .search-close { display: none !important; }
  html:not(.tv) .tab-bar:not([hidden]) { justify-content: center; gap: 0.25rem; padding-inline: max(1rem, env(safe-area-inset-left, 0px)) max(1rem, env(safe-area-inset-right, 0px)); }
  .tab-bar .tab { flex: 0 1 10rem; flex-direction: row; gap: 0.55rem; padding: 0.35rem 0.75rem; font-size: 0.85rem; }
  .tab-bar .tab svg { width: 1.45rem; height: 1.45rem; }
  /* Rows: a card is a comfortable tap, and a few more show on a tablet on its side. */
  .home-section .row.posters { grid-auto-columns: calc(var(--card-size, clamp(9.5rem, 17cqw, 11.5rem)) * var(--card-scale)); }
  .grid { grid-template-columns: repeat(auto-fill, minmax(calc(10rem * var(--card-scale)), 1fr)); }
  /* The pickers on a library's page, and a title's buttons, are big enough to tap. */
  .filter-bar select, .toolbar select { min-height: 2.75rem; }
  .pill-action, .pill-row summary { min-height: 2.75rem; }
  /* The player: bigger buttons, a timeline a finger can hold, and no volume slider (the tablet's
     own buttons do that). */
  html:not(.tv) .ctl:not(.ctl-labelled) { width: 3rem; }
  html:not(.tv) .ctl { height: 3rem; }
  html:not(.tv) .ctl-main { width: 3.5rem; height: 3.5rem; }
  html:not(.tv) .ctl-volume { display: none; }
  html:not(.tv) .timeline { height: 2.25rem; }
  html:not(.tv) .tl-track { height: 6px; }
  html:not(.tv) .tl-thumb { transform: scale(1); width: 1.1rem; height: 1.1rem; margin: -0.55rem 0 0 -0.55rem; }
  html:not(.tv) .ctl-row { gap: 0.5rem; }
}
/* Upright, a tablet has the width for seven tabs only with their names under their icons. */
@media (pointer: coarse) and (hover: none) and (min-width: 641px) and (max-width: 1366px) and (orientation: portrait) {
  .tab-bar .tab { flex: 1 1 0; max-width: 8.5rem; flex-direction: column; gap: 0.25rem; padding-inline: 0.25rem; font-size: 0.75rem; }
}
/* A tablet on its side, or a phone on its side: the tabs take less of the height. */
@media (pointer: coarse) and (hover: none) and (max-height: 500px) and (max-width: 1366px) {
  html:not(.tv) { --tabs-h: 3rem; }
  .tab-bar .tab { flex-direction: row; gap: 0.45rem; }
}
/* More: the rest of the links, in a sheet from the bottom. */
dialog.modal.tab-sheet { width: 100%; max-width: none; margin: auto 0 0; padding: 0.6rem 0.6rem calc(0.6rem + env(safe-area-inset-bottom, 0px));
  border-width: 1px 0 0; border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
.tab-sheet-list { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }
.tab-sheet-list a { display: flex; align-items: center; gap: 0.9rem; min-height: 3rem; padding: 0.5rem 0.8rem; border-radius: var(--radius); color: var(--text); text-decoration: none; }
.tab-sheet-list a:hover { background: color-mix(in srgb, var(--text) 8%, transparent); }
.tab-sheet-list a[aria-current="page"] { color: var(--accent); }
.tab-sheet-list svg { flex: none; width: 1.5rem; height: 1.5rem; fill: currentColor; }

/* ---------- iPhone and iPad: safe areas, the Home Screen app, the keyboard (ios.js, pwa.js) ---------- */
/* The page itself (style.css :root) keeps below the status bar and above the home indicator.
   Here the rest keeps clear of them and of the notch: what's fixed or stuck to an edge, sheets,
   and the page's sides on a phone on its side (--gutter, and design.js's Page margins). In Safari
   the areas are mostly 0; in the Home Screen app the status bar lies over the page (index.html),
   so the top one is its height. */
:root { --gutter: max(clamp(1rem, 3vw, 2.5rem), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)); }
html { -webkit-tap-highlight-color: transparent; scroll-padding-top: calc(var(--top-h) + 0.5rem + env(safe-area-inset-top, 0px)); }
/* The header sticks under the status bar, and a strip of the header's own glass lies under the
   status bar itself, so the page never scrolls behind its writing. */
.top { top: env(safe-area-inset-top, 0px); }
html:not(.tv):has(> body > #top:not([hidden]))::before { content: ""; position: fixed; z-index: 31; top: 0; left: 0; right: 0; height: env(safe-area-inset-top, 0px);
  pointer-events: none; background: color-mix(in srgb, var(--bg) 84%, transparent); -webkit-backdrop-filter: saturate(1.3) blur(18px); backdrop-filter: saturate(1.3) blur(18px);
  transition: background-color 0.4s var(--ease-out); }
/* Over Home's banner and a title's picture, which run up under the status bar too: the strip is
   clear with the header, and the header's shade reaches up behind the status bar's writing. */
html:not(.tv):has(> body > #top.over-art:not(.scrolled):not(.nav-open))::before { background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; }
.top::before { top: calc(-1 * env(safe-area-inset-top, 0px)); }
.home-page > .banner:first-child, .sk-banner { margin-top: calc(-1 * (var(--top-h) + env(safe-area-inset-top, 0px))); }
#page > .hero:first-child:not(.plain), .sk-hero { margin-top: calc(-1 * (var(--top-h) + env(safe-area-inset-top, 0px))); }
/* Pages that fill the screen and scroll inside it: the screen less the status bar and home indicator. */
@media (min-width: 961px) { html body:has(#page > .console) { height: calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px)); } }
@media (min-width: 801px) { html body:has(#page > .settings) { height: calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px)); } }
html body:has(#page > .site-editor) { height: calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px)); }
/* Dialogs stop short of the status bar and home indicator; a sheet the height of the screen (the
   audiobook player on a phone) keeps its buttons clear of them. */
dialog.modal { max-height: calc(100dvh - 2rem - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px)); }
@media (max-width: 640px) {
  html:not(.tv) dialog.modal.listen-full { padding-top: max(0.75rem, env(safe-area-inset-top, 0px)); padding-bottom: max(1.25rem, env(safe-area-inset-bottom, 0px));
    padding-left: max(1rem, env(safe-area-inset-left, 0px)); padding-right: max(1rem, env(safe-area-inset-right, 0px)); }
}
.profiles { padding-top: max(2.5rem, calc(env(safe-area-inset-top, 0px) + 1rem)); padding-bottom: max(2.5rem, calc(env(safe-area-inset-bottom, 0px) + 1rem)); }
/* The mini-player: clear of the notch on a phone on its side, and of the home indicator where
   there are no tabs under it. */
html:not(.tv) .listen-bar:not([hidden]) { margin-left: env(safe-area-inset-left, 0px); margin-right: env(safe-area-inset-right, 0px); }
html:not(.tv) body:not(:has(> .tab-bar:not([hidden]))) > .listen-bar:not([hidden]) { margin-bottom: env(safe-area-inset-bottom, 0px); }
/* The player's menus, clear of the notch on a phone on its side. */
html:not(.tv) .player-menu { right: max(clamp(0.75rem, 3vw, 2rem), env(safe-area-inset-right, 0px)); }
#ctl-airplay.on { color: var(--accent); }

/* No rubber band where nothing scrolls: under the player, behind a dialog, and on the pages that
   fill the screen (their own parts scroll). */
html:has(> body > #player:not([hidden])), html.ios:has(dialog.modal[open]) { overflow: hidden; overscroll-behavior: none; }
html:has(body > #page > :is(.console, .settings, .site-editor)) { overscroll-behavior: none; }
dialog.modal, .player-menu, .account-links { overscroll-behavior: contain; }

/* iOS zooms into a field whose writing is smaller than 16 pixels. -webkit-touch-callout is only on iOS. */
@supports (-webkit-touch-callout: none) {
  input:not([type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"], [type="button"], [type="submit"]), select, textarea { font-size: max(16px, 1em) !important; }
}
/* In the Home Screen app: no link previews or picture menus on a long press, and no selecting
   the words on buttons and bars, as in an app. */
html.ios.standalone :is(a, img) { -webkit-touch-callout: none; }
html.ios.standalone :is(button, .tab-bar, .ctl-row, .listen-bar, .player-bar, .card) { -webkit-user-select: none; user-select: none; }
/* The phone's own buttons set the volume: iOS doesn't let a page. */
html.ios .ctl-volume { display: none; }
/* While the keyboard is up, the tabs and the mini-player step aside (ios.js). */
html.keyboard .tab-bar, html.keyboard .listen-bar { display: none; }

/* Add to Home Screen, in Your settings on an iPhone or iPad (pwa.js). */
.home-screen-hint { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem 1rem; flex-wrap: wrap; }
.home-screen-hint p { margin: 0.2rem 0 0; color: var(--muted); }
