/* song-player.css — styles for the shared song/karaoke player
   (includes/song_player_overlay.php + assets/js/song-player.js).

   Two consumers:
   - lesson_player.php: loads this AFTER lesson-player-v3.css. The rules in
     the first section moved here verbatim from that file (its "Song
     overlay" block) and still resolve their vars (--gold/--surface-2/...)
     and modal shell (.passage-modal*) from lesson-player-v3.css, so the
     overlay looks exactly as before.
   - piosenka.php: standalone page with no lesson-player-v3.css. The
     .song-standalone section at the bottom supplies everything the player
     needs there: the var values (lesson player's dark "Midnight" palette --
     the share page is deliberately always-dark/immersive, it doesn't track
     the account theme), the .passage-modal shell, and the .pa-* transport
     controls. */

/* ---------- Song overlay (shared, moved from lesson-player-v3.css) ---------- */
/* Immersive shell: this card always looks like a piece of the song itself,
   never like a light/dark patch of whatever lesson theme (szlak/zmierzch/
   pergamin/kontrast) happens to be active behind it ("the outside is a
   light color" while the inside was hardcoded dark -- Darek). Redefining
   the theme variables locally, scoped to this element, is enough to also
   re-skin every child that already reads --surface/--ink/--muted/--gold/etc
   (chooser pills, switches, vol buttons) without duplicating their rules. */
.song-modal-content {
  --surface: #111a1e;
  --surface-2: rgba(255, 255, 255, .1);
  --ink: #f4f8f7;
  --muted: #b9cac7;
  --line: rgba(255, 255, 255, .2);
  --gold: #E8B44C;
  --gold-soft: rgba(232, 180, 76, .24);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  width: min(880px, 96vw);
  background: linear-gradient(160deg, color-mix(in srgb, var(--gold) 16%, #10181b) 0%, #10181b 70%);
  color: var(--ink);
}
/* The song's own cover art, heavily blurred and darkened, bleeding across
   the WHOLE card -- not just the lyrics tile -- so the controls/switches
   area reads as one continuous scene instead of a dark video pane sitting
   inside a differently-colored card. Set per-song from JS (loadSong). */
.song-modal-content::before {
  content: '';
  position: absolute;
  inset: -12%;
  background-image: var(--song-cover-url, none);
  background-size: cover;
  background-position: center;
  filter: blur(46px) saturate(1.2) brightness(.55);
  transform: scale(1.1);
  z-index: -2;
}
.song-modal-content::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(6, 10, 13, .25) 0%, rgba(6, 10, 13, .55) 55%, rgba(6, 10, 13, .82) 100%);
  z-index: -1;
}
/* Kontrast is the accessibility high-contrast theme -- skip the photo
   backdrop/blur there and stay a flat, maximally legible dark panel. */
html[data-theme="kontrast"] .song-modal-content::before,
html[data-theme="kontrast"] .song-modal-content::after { display: none; }
html[data-theme="kontrast"] .song-modal-content { background: #0c1113; }
/* Beats lesson-player-v3.css's generic .passage-modal-content theme rules
   (data-bg-tint photo backdrop, kontrast flat surface) on specificity --
   this card's background is always the immersive cover-derived one above,
   never the ambient lesson theme's. */
html[data-bg-tint] .song-modal-content.passage-modal-content,
html[data-theme] .song-modal-content.passage-modal-content {
  background: linear-gradient(160deg, color-mix(in srgb, var(--gold) 16%, #10181b) 0%, #10181b 70%);
}
html[data-theme="kontrast"] .song-modal-content.passage-modal-content { background: #0c1113; }
/* Real browser fullscreen (not just a bigger modal) -- the video/lyrics
   zone gets the room, controls stay pinned below it. */
.song-modal-content:fullscreen {
  width: 100vw;
  height: 100vh;
  max-height: 100vh;
  max-width: none;
  border-radius: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 2rem;
}
.song-modal-content:fullscreen .song-media-zone { flex: 1; aspect-ratio: auto; min-height: 0; margin-bottom: 1rem; }
.song-modal-content:fullscreen .song-chooser,
.song-modal-content:fullscreen .song-controls,
.song-modal-content:fullscreen .song-switch-row { flex: none; }
/* Fullscreen is the classroom/projection mode, so the lyrics get +70% over
   the in-card size (Darek) -- 1.15rem -> 1.955rem on desktop, and the
   narrow-phone override further down does the same to its own 1rem base.
   The panel widens to match, otherwise bigger text just means more wrapped
   lines in the same 34rem column. */
.song-modal-content:fullscreen .song-karaoke-view { font-size: 1.955rem; line-height: 1.6; }
.song-modal-content:fullscreen .song-karaoke-panel { max-width: 52rem; padding: 1.8rem 2rem; }
.song-modal-content:fullscreen .song-karaoke-line { padding: .45rem 1rem; }
.song-chooser { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0 0 .8rem; padding-right: 2rem; }
.song-chooser-btn {
  border: 2px solid var(--line);
  background: var(--surface-2);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border-radius: 99px;
  padding: .4rem .9rem;
  font-size: .85rem;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
}
.song-chooser-btn.is-active { border-color: var(--gold); background: var(--gold-soft); color: var(--ink); }
/* Widescreen (tablet-up). This USED to be a two-column grid -- media left,
   controls stacked in a column on the right. That is what made the controls
   read as asymmetrical (Darek): a squeezed half-width transport block beside
   a tall image, with volume and fullscreen orphaned onto their own lines.
   Now it's one column at every width: image, then the full-width transport
   row directly beneath it, then the toggles. The card is capped narrower so
   a single column doesn't stretch into a letterbox on a big display. */
@media (min-width: 760px) {
  .song-modal-content { padding: 1.6rem; }
  .song-modal-content:not(:fullscreen) { width: min(620px, 96vw); }
}
.song-media-zone {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: #10181b;
  margin-bottom: .8rem;
  box-shadow: 0 12px 32px -12px rgba(0, 0, 0, .5);
}
.song-video { width: 100%; height: 100%; object-fit: contain; background: #10181b; display: block; }
/* Scrollable but with no visible scrollbar (Darek) -- applied to the song
   modal's own surfaces only, NOT .passage-modal-content generally (the
   lesson player's other modals keep their scrollbars). */
.song-modal-content,
.song-karaoke-view { scrollbar-width: none; }
.song-modal-content::-webkit-scrollbar,
.song-karaoke-view::-webkit-scrollbar { display: none; }
/* The dark lyrics tile always fits inside the media zone (its bottom edge
   stays visible -- Darek) and the LINES scroll inside it instead of the
   whole tile scrolling out of view. Flex-centering is safe here, unlike
   the earlier block-flow version, because the panel is max-height-capped
   and scrolls internally, so nothing ever sticks out past the center line
   unreachably (the classic flex-center-plus-overflow trap). */
.song-karaoke-view {
  position: absolute;
  inset: 0;
  display: flex;
  overflow: hidden;
  padding: 1.6rem 1.4rem;
  background: linear-gradient(160deg, color-mix(in srgb, var(--gold) 22%, #10181b) 0%, #10181b 100%);
  background-size: cover;
  background-position: center;
  color: #fff;
  font-size: 1.15rem;
  line-height: 1.9;
  text-align: center;
  white-space: pre-line;
}
/* Shared backdrop for every karaoke-view state (synced lines, "processing",
   and the plain-lyrics fallback) -- cover art backgrounds are often busy
   illustrations, so text needs a blurred, darkened surface under it rather
   than sitting directly on the artwork. backdrop-filter blurs the
   .song-karaoke-view background-image showing through; Safari needs the
   -webkit- prefix. */
.song-karaoke-panel {
  margin: auto;
  max-width: 34rem;
  max-height: 100%;
  overflow-y: auto;
  scrollbar-width: none;
  padding: 1.4rem 1.6rem;
  border-radius: 18px;
  background: rgba(8, 10, 14, 0.62);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
}
.song-karaoke-panel::-webkit-scrollbar { display: none; }
/* Word-synced view (song.karaoke_status === 'ready'): one line per <p>,
   the current one highlighted, neighbors dimmed -- same visual language as
   the tutorials/suno-sandbox karaoke-demo.html prototype. */
.song-karaoke-lines { display: flex; flex-direction: column; gap: .5rem; }
.song-karaoke-line {
  margin: 0;
  padding: .5rem .8rem;
  border-radius: 8px;
  opacity: .45;
  font-weight: 600;
  transition: opacity var(--speed), background var(--speed);
  /* Only actually stacks two lines when a translation span is present --
     with just the original span (no translation, or the toggle's off)
     this is a one-child flex column and behaves identically to the plain
     single-line <p> this replaced. */
  display: flex;
  flex-direction: column;
  gap: .15rem;
}
.song-karaoke-line.is-current {
  opacity: 1;
  background: rgba(10, 10, 15, 0.55);
  font-weight: 100;
}
.song-karaoke-line-translation {
  font-weight: 500;
  font-size: .85em;
  opacity: .75;
  font-style: italic;
}
/* "Luki" typing boxes -- inline in the lyric line, sized to the answer. */
.song-gap-input {
  display: inline-block;
  margin: 0 .15rem;
  padding: 0 .25rem;
  border: none;
  border-bottom: 2px solid var(--gold);
  border-radius: 8px 8px 0 0;
  background: rgba(255, 255, 255, .14);
  color: #fff;
  font: inherit;
  text-align: center;
  outline: none;
  vertical-align: baseline;
}
.song-gap-input.is-correct {
  border-bottom-color: #4CC98F;
  background: rgba(76, 201, 143, .22);
  color: #baf3d8;
}
.song-gap-input.is-missed {
  border-bottom-color: var(--gold);
  background: transparent;
  color: var(--gold);
  font-style: italic;
}
/* Swobodny / Trening picker -- only rendered while Luki is on. */
.song-gaps-mode { display: flex; gap: .3rem; align-items: center; }
.song-gaps-mode-btn {
  display: inline-flex; align-items: center; gap: .3rem;
  border: 2px solid var(--line);
  background: var(--surface-2);
  border-radius: 99px;
  padding: .3rem .7rem;
  font-size: .78rem;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
}
.song-gaps-mode-btn.is-active { border-color: var(--gold); background: var(--gold-soft); color: var(--ink); }
/* End-of-song tally ("Trafione X/Y" + explicit reveal button). */
.song-gaps-summary {
  position: absolute;
  left: 50%; bottom: .8rem;
  transform: translateX(-50%);
  display: flex; align-items: center; gap: .6rem;
  background: rgba(8, 10, 14, .8);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  padding: .45rem .55rem .45rem .9rem;
  border-radius: 99px;
  color: #fff;
  font-size: .85rem;
  font-weight: 600;
  white-space: nowrap;
  z-index: 2;
}
.song-gaps-summary button {
  border: none;
  background: var(--gold);
  color: #14343B;
  border-radius: 99px;
  padding: .3rem .7rem;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
.song-controls { display: flex; flex-direction: column; gap: .55rem; }
.song-controls-row { display: flex; align-items: center; gap: .5rem; }
.song-controls-transport .pa-seek { flex: 1; min-width: 0; }
.song-play-btn { flex: none; }
.song-vol-btn {
  flex: none;
  width: 30px; height: 30px;
  border-radius: 50%;
  border: none;
  background: var(--surface-2);
  color: var(--muted);
  display: grid; place-items: center;
  font-size: .9rem;
  cursor: pointer;
}
/* Volume sits at the END of the transport row as just an icon, and the
   slider slides out of it on click -- so the row's width goes to the seek
   bar (the control people actually drag) instead of being permanently
   split with a slider nobody touches on most plays. Animating max-width
   rather than toggling display keeps it a smooth reveal. */
.song-vol { display: flex; align-items: center; gap: .35rem; flex: none; }
.song-vol-slider {
  width: 110px;
  max-width: 0;
  opacity: 0;
  margin: 0;
  padding: 0;
  pointer-events: none;
  transition: max-width var(--speed), opacity var(--speed);
  accent-color: var(--audio-accent-soft);
}
.song-vol.is-open .song-vol-slider { max-width: 110px; opacity: 1; pointer-events: auto; }
/* Card chrome, not a transport control -- pinned opposite the close button.
   In the standalone page there IS no close button, so it simply owns the
   corner alone. */
.song-fs-btn {
  position: absolute;
  top: .8rem;
  right: .8rem;
  z-index: 3;
  width: 34px; height: 34px;
  border-radius: 50%;
  border: none;
  background: rgba(8, 10, 14, .55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: var(--ink);
  display: grid; place-items: center;
  font-size: 1rem;
  cursor: pointer;
}
.song-fs-btn:hover { background: rgba(8, 10, 14, .8); color: var(--gold); }
/* Tu stalo `right: 3.3rem` -- "zamknij" odsuwane w lewo, zeby nie wchodzilo na
   przycisk pelnego ekranu. Odsuniecie bylo za male i za pozne: 6 px przerwy
   miedzy jasnym kolkiem 40 px a ciemnym 34 px czyta sie jak jedna plama, a nie
   dwie kontrolki. Przycisk wyjscia siedzi teraz w PRZECIWLEGLYM rogu (blok
   .is-song-exit nizej, wspolny dla obu trybow), wiec nie ma juz czego odsuwac.
   Reguly usuniete, a nie nadpisane -- inaczej zostaje martwy `right`, ktory
   przy nastepnej zmianie wyglada jak obowiazujacy. */

/* Wyjscie z odtwarzacza: strzalka w GORNYM LEWYM narozniku karty. Powstalo dla
   piosenka.php (2026-08-17, SongPlayer.init -> onExit), od 2026-08-19 obowiazuje
   TAKZE w nakladce w lekcji -- patrz komentarz przy .song-fs-btn wyzej i w
   song-player.js. Klasa nadawana jest bezwarunkowo, roznica miedzy trybami
   siedzi juz tylko w tym, co robi klikniecie (nawigacja wstecz vs zamkniecie
   nakladki).
   `right: auto` zostaje mimo usuniecia tamtych regul, ale NIE jest nosne:
   bazowe .passage-modal-close (lesson-player-v3.css) ustawia `right: .8rem`,
   a przy jednoczesnym `left`, `right` i jawnej `width` przegladarka i tak
   ignoruje `right` (zmierzone: z wyzerowaniem i bez niego przycisk ma te same
   34 px). Zostaje jako deklaracja intencji -- gdyby ktos kiedys zdjal stad
   `width`, bez tego zera przycisk rozciagnalby sie przez cala karte.

   Na piosenka.php ten przycisk nie ma ZADNEGO innego stylu: bazowe
   .passage-modal-close zyje w lesson-player-v3.css, ktorego ta strona
   swiadomie nie laduje -- bez tego bloku wyszedlby domyslny przycisk
   przegladarki w normalnym przeplywie, rozpychajacy zawartosc karty
   (samo `left` nic nie robi bez position:absolute).

   Wymiary i tlo celowo identyczne z .song-fs-btn: to para kontrolek w tych
   samych naroznikach tej samej karty i maja czytac sie jak jedna rodzina. */
.song-modal-content .passage-modal-close.is-song-exit,
.song-standalone .song-modal-content .passage-modal-close.is-song-exit {
  position: absolute;
  top: .8rem;
  left: .8rem;
  right: auto;
  z-index: 3;
  width: 34px; height: 34px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(8, 10, 14, .55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: var(--ink);
  display: grid; place-items: center;
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
}
.song-modal-content .passage-modal-close.is-song-exit:hover { background: rgba(8, 10, 14, .8); color: var(--gold); }
.song-modal-content .passage-modal-close.is-song-exit:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.song-switch-row { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1.4rem; margin-top: .8rem; }
/* Chip "Udostepnij" w rzedzie przelacznikow. Nie jest przelacznikiem, wiec
   wyglada jak przycisk (obwodka, nie suwak), ale mieszka tutaj -- patrz
   komentarz w includes/song_player_overlay.php: narozniki karty sa juz zajete
   i kolejna kontrolka absolutna musialaby znac wszystkie warianty ich obsady.
   Tokeny (--muted/--gold/--line) sa zdefiniowane lokalnie na
   .song-modal-content, wiec rozwiazuja sie tez na piosenka.php, ktora nie
   laduje lesson-player-v3.css. */
.song-share-chip {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .3rem .7rem; border-radius: 99px;
  border: 1px solid var(--line); background: transparent; color: var(--muted);
  font: inherit; font-size: .84rem; font-weight: 600; cursor: pointer;
  margin-left: auto; /* dosuniety do konca rzedu, zeby nie mieszal sie z przelacznikami */
}
.song-share-chip[hidden] { display: none; }
.song-share-chip:hover { border-color: var(--gold); color: var(--gold); }
.song-share-chip:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* Luki + Swobodny/Trening stay glued together on one line. */
.song-gaps-group { display: flex; align-items: center; flex-wrap: nowrap; gap: .7rem; }
/* [hidden] on these loses to their own display rules (a class selector beats
   the UA stylesheet), which is why the Karaoke/Tłumaczenie/Luki switches
   showed up even for songs that had none of it -- toggles that did nothing.
   Restore the intent explicitly. */
.song-karaoke-switch[hidden],
.song-gaps-mode[hidden],
.song-gaps-group[hidden],
.song-fs-btn[hidden] { display: none; }
.song-karaoke-switch {
  display: flex;
  align-items: center;
  gap: .55rem;
  cursor: pointer;
  font-size: .88rem;
  font-weight: 600;
  color: var(--muted);
  width: fit-content;
}
.song-karaoke-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.song-karaoke-track {
  flex: none;
  width: 40px; height: 22px;
  border-radius: 99px;
  background: var(--surface-2);
  border: 2px solid var(--line);
  position: relative;
  transition: background var(--speed), border-color var(--speed);
}
.song-karaoke-track::after {
  content: '';
  position: absolute;
  top: 1px; left: 1px;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--muted);
  transition: transform var(--speed), background var(--speed);
}
.song-karaoke-switch input:checked + .song-karaoke-track { background: var(--gold-soft); border-color: var(--gold); }
.song-karaoke-switch input:checked + .song-karaoke-track::after { transform: translateX(18px); background: var(--gold); }

/* ---------- Mini player (assistant drawer song list) ---------- */
/* Lives in a ~280px drawer column, which is the whole reason it exists:
   the seek bar gets a full row to itself and every other control sits on
   a second row, instead of the native <audio controls> single-row squeeze
   this replaced. Reads the drawer's own theme vars (lesson-player-v3.css),
   so it follows szlak/zmierzch/pergamin/kontrast rather than forcing the
   song card's always-dark palette into a light drawer. */
.song-mini { display: flex; flex-direction: column; gap: .35rem; margin: .2rem 0; }
.song-mini-seek-row { display: flex; align-items: center; gap: .4rem; }
.song-mini-seek { flex: 1; min-width: 0; accent-color: var(--audio-accent, #4684a9); }
.song-mini-time { flex: none; font-size: .7rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.song-mini-btn-row { display: flex; align-items: center; gap: .4rem; }
/* Was a flex:1 .song-mini-spacer pushing the chips right, with each chip a
   direct child of the row. Adding the share chip (2026-08-19) ate the last
   of the slack: MEASURED in the 300px drawer, the row overflowed its card
   by 20px at font-size level 3, 60px at level 4 and 100px at level 5
   (--fs-base 19/22/25px, lesson-player-v3.css:82) -- the reported symptom,
   the expand icon spilling past the card's right edge. Level 2 (the 17px
   default) had exactly 0px left over, so it was one glyph away too.
   Nothing shrinks its way out of that: a chip's min-content IS its icon
   plus padding, so the overflow is unavoidable while all six items must
   share one line. Grouping the chips gives them a line of their own to
   wrap onto -- but wrapping was the fallback, not the look: Darek's first
   sight of it was the expand chip stranded alone on a second line. All
   three chips are icon-only now (the "Tekst" label went, 2026-08-19),
   which buys back ~40px and keeps one line at every font level in the
   300px drawer -- the wrap stays as the safety net for whatever narrows
   this next. margin-left:auto replaces the spacer. */
.song-mini-chips {
  margin-left: auto;
  display: flex; align-items: center;
  flex-wrap: wrap; justify-content: flex-end;
  gap: .4rem;
  min-width: 0;
}
.song-mini-spacer { flex: 1; }
.song-mini-play {
  flex: none;
  width: 32px; height: 32px;
  border-radius: 50%;
  border: none;
  background: var(--audio-accent, #4684a9);
  color: #fff;
  display: grid; place-items: center;
  font-size: .85rem;
  cursor: pointer;
}
.song-mini-chip {
  display: inline-flex; align-items: center; gap: .3rem;
  border: 1px solid var(--line);
  background: var(--surface-2);
  border-radius: 99px;
  padding: .25rem .6rem;
  font-size: .74rem;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
}
.song-mini-chip.is-active { border-color: var(--gold); background: var(--gold-soft); color: var(--ink); }
/* Icon-only chips: the .6rem side padding is sized for a chip with a word
   in it, and on a bare glyph it reads as slack the row cannot afford. */
.song-mini-chip--icon { padding: .25rem .45rem; }
/* Hides the trailing chips (Tekst / expand) while the volume slider is
   open (2026-08-15) -- the row has no shrink budget wide enough to fit a
   growing 110px slider AND every fixed-size chip in a narrow drawer, so
   the row was overflowing its container to the right. The slider now
   temporarily takes the space the chips vacate instead of fighting them
   for it. See the .is-vol-open toggle in song-player.js's mini(). */
.song-mini-btn-row.is-vol-open .song-mini-chip { display: none; }
/* Capped and internally scrolled: an 80-line lyric must not push the rest
   of the drawer (the create-song form, other tracks) off the screen. */
.song-mini-lyrics {
  max-height: 11rem;
  overflow-y: auto;
  scrollbar-width: none;
  margin-top: .1rem;
  padding: .5rem .6rem;
  border-radius: 10px;
  background: var(--surface-2);
  font-size: .8rem;
  line-height: 1.5;
}
.song-mini-lyrics::-webkit-scrollbar { display: none; }
.song-mini-line { margin: 0 0 .15rem; opacity: .55; transition: opacity var(--speed), color var(--speed); }
.song-mini-line.is-current { opacity: 1; color: var(--gold); font-weight: 600; }
.song-mini-line.is-plain { opacity: .8; white-space: pre-line; }

/* ---------- Standalone shell (piosenka.php only) ---------- */
/* Var values are lesson-player-v3.css's Midnight theme block. */
.song-standalone {
  --radius: 20px;
  --radius-sm: 12px;
  --speed: .25s;
  --surface: #182B30;
  --surface-2: #14252A;
  --ink: #E7F2EF;
  --muted: #8FB0AC;
  --line: #24424663;
  --gold: #E8B44C;
  --gold-soft: #3D3419;
  --audio-accent: #4684a9;
  --audio-accent-soft: #4a92bdb0;
  --island-fill: linear-gradient(180deg, color-mix(in srgb, var(--surface) 100%, white 7%) 0%, var(--surface) 55%, color-mix(in srgb, var(--surface) 100%, black 3%) 100%);
  --island-shadow: 0 1px 0 rgba(255,255,255,.07) inset, 0 12px 28px -12px rgba(0,0,0,.55), 0 2px 8px rgba(0,0,0,.35);
}
/* The same cover art that backs the card also fills the WHOLE page around
   it -- far heavier blur and darker, so the card still reads as the one
   sharp object in the room and the page never looks like a dark rectangle
   floating on a flat background. Uses the same --song-cover-url custom
   property the card sets from JS (loadSong); it's set on .song-modal-content,
   so this reaches up to the fixed backdrop via a sibling-free ::before on
   the modal layer itself rather than trying to inherit upward. */
.song-standalone .passage-modal::before {
  content: '';
  position: fixed;
  inset: -10%;
  z-index: -2;
  background-image: var(--song-page-cover, none);
  background-size: cover;
  background-position: center;
  filter: blur(70px) saturate(1.3) brightness(.4);
  transform: scale(1.15);
  pointer-events: none;
}
/* Keeps the lyrics/controls legible over a busy illustration and stops the
   blurred art washing the page out to mid-grey. */
.song-standalone .passage-modal::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  background: radial-gradient(120% 120% at 50% 0%, rgba(16, 30, 34, .55) 0%, rgba(10, 21, 24, .82) 60%, rgba(10, 21, 24, .95) 100%);
  pointer-events: none;
}
html[data-theme="kontrast"] .song-standalone .passage-modal::before,
html[data-theme="kontrast"] .song-standalone .passage-modal::after { display: none; }
/* The modal IS the page here: fixed full-viewport like on lesson_player,
   but transparent (the page body provides the dark backdrop) and padded
   down past the fixed topbar (piosenka.php's own chrome, z-index above
   this so its links stay clickable). */
.song-standalone .passage-modal {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(4.6rem + env(safe-area-inset-top)) calc(1rem + env(safe-area-inset-right)) calc(1.2rem + env(safe-area-inset-bottom)) calc(1rem + env(safe-area-inset-left));
}
/* NEVER scrolls (Darek: "unnecessary space underneath... at the end the
   whole thing moves up to reveal it", taking the fullscreen button off the
   top with it).
   The dead space was NOT layout: the real children add up to exactly the
   card's height. It was this element's own decorative ::before, which sits
   at inset:-12% (~71px past the bottom edge) to bleed the blurred cover
   art beyond the card. That counts as scrollable overflow, so with the old
   overflow-y:auto the card was permanently scrollable by ~108px of pure
   nothing -- and any scroll (the karaoke auto-follow's scrollIntoView, a
   stray wheel, a focus) slid the whole player under its own top edge,
   carrying the absolutely-positioned fullscreen button out of sight.
   overflow:hidden clips the bleed (which is the point of the bleed anyway)
   and makes the card unscrollable. The lyrics still scroll, inside their
   own panel, where the scrolling belongs. */
.song-standalone .passage-modal-content {
  position: relative;
  width: min(640px, 100%);
  max-height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--island-fill);
  border-radius: var(--radius);
  box-shadow: var(--island-shadow);
  padding: 1.2rem;
  color: var(--ink);
}
/* Short-viewport safeguard only -- it does not bind on a normal laptop
   (the 16/10 ratio already lands under it). Without it, a short window
   would give the ratio a height taller than the room available and push
   the controls off the bottom, since an aspect-ratio box does NOT shrink
   just because its flex container overflows: the ratio is a definite
   height that flex-shrink won't override. The subtrahend is everything
   else on the page: topbar padding, card padding, transport and switch
   rows. */
.song-standalone .song-media-zone {
  flex: 0 1 auto;
  max-height: calc(100vh - 16rem);
  min-height: 120px; /* never let the controls squeeze the art to nothing */
}
.song-standalone .song-chooser,
.song-standalone .song-controls,
.song-standalone .song-switch-row { flex: none; }
/* Roomier than the lesson overlay's 520px -- this player is the entire
   page, and in a classroom it's projected. */
.song-standalone .song-modal-content { width: min(760px, 100%); }
.song-standalone .song-media-zone { aspect-ratio: 16 / 10; }
.song-standalone .pa-play {
  flex: none;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: none;
  background: var(--audio-accent);
  color: #fff;
  display: grid; place-items: center;
  font-size: 1.1rem;
  cursor: pointer;
}
.song-standalone .pa-time { flex: none; font-size: .74rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.song-standalone .pa-seek { flex: 1; min-width: 0; accent-color: var(--audio-accent-soft); }

/* ---------- Narrow phones (down to 320px) ---------- */
/* The volume slider goes -- phones have hardware volume keys and it's the
   one control that doesn't fit a 320px controls row (mute stays). Tighter
   paddings keep the lyrics readable without a horizontal scrollbar. */
@media (max-width: 480px) {
  .song-karaoke-view { padding: 1.2rem .6rem; font-size: 1rem; line-height: 1.7; }
  /* Same +70% as desktop fullscreen, off this narrower 1rem base. Must come
     after the .song-karaoke-view rule above or that one wins on order. */
  .song-modal-content:fullscreen .song-karaoke-view { font-size: 1.7rem; line-height: 1.55; }
  .song-modal-content:fullscreen .song-karaoke-panel { max-width: 100%; padding: 1rem .8rem; }
  /* The slider stays (it's collapsed by default now, so it costs no width
     until tapped) but narrows to fit a 320px row when opened. */
  .song-vol.is-open .song-vol-slider { max-width: 80px; }
  .song-karaoke-panel { padding: 1rem .7rem; }
  .song-switch-row { gap: .5rem .9rem; }
  .song-standalone .passage-modal { padding-left: .5rem; padding-right: .5rem; }
  .song-standalone .passage-modal-content { padding: .8rem; }
  .song-standalone .pa-play { width: 38px; height: 38px; font-size: .95rem; }
}
