/* Czytnik Plast Echo (spec `magazine` §Czytnik numeru). Fonty z repo (`public/fonts/plastecho/`): Lato 2.015 (OFL 1.1,
   npm lato-font@3.0.0; PDF używa wag Lato 2.0, których nie ma w Lato 1.x z public/fonts: Semibold, Medium, Heavy),
   PT Sans + Oswald (numery 1-39), Carlito, PT Sans Narrow, Font Awesome 6 Free. Ten sam arkusz obsługuje statyczny
   podgląd kontroli w próbie (`scripts/magazine-reader-poc/viewer/index.html`). Zmiana = podbij `?N` w reader.html.twig. */
@font-face { font-family: 'PELato'; src: url(/fonts/plastecho/lato-light.woff2) format('woff2'); font-weight: 300; font-style: normal; font-display: block; }
@font-face { font-family: 'PELato'; src: url(/fonts/plastecho/lato-light-italic.woff2) format('woff2'); font-weight: 300; font-style: italic; font-display: block; }
@font-face { font-family: 'PELato'; src: url(/fonts/plastecho/lato-normal.woff2) format('woff2'); font-weight: 400; font-style: normal; font-display: block; }
@font-face { font-family: 'PELato'; src: url(/fonts/plastecho/lato-normal-italic.woff2) format('woff2'); font-weight: 400; font-style: italic; font-display: block; }
@font-face { font-family: 'PELato'; src: url(/fonts/plastecho/lato-medium.woff2) format('woff2'); font-weight: 500; font-style: normal; font-display: block; }
@font-face { font-family: 'PELato'; src: url(/fonts/plastecho/lato-semibold.woff2) format('woff2'); font-weight: 600; font-style: normal; font-display: block; }
@font-face { font-family: 'PELato'; src: url(/fonts/plastecho/lato-bold.woff2) format('woff2'); font-weight: 700; font-style: normal; font-display: block; }
@font-face { font-family: 'PELato'; src: url(/fonts/plastecho/lato-heavy.woff2) format('woff2'); font-weight: 800; font-style: normal; font-display: block; }
@font-face { font-family: 'PELato'; src: url(/fonts/plastecho/lato-black.woff2) format('woff2'); font-weight: 900; font-style: normal; font-display: block; }
/* Starsze numery (np. 22): PT Sans i Oswald, oba OFL 1.1 (google/fonts); Oswald = font zmienny, wagi 200-700. */
@font-face { font-family: 'PEPTSans'; src: url(/fonts/plastecho/PT_Sans-Web-Regular.ttf) format('truetype'); font-weight: 400; font-style: normal; font-display: block; }
@font-face { font-family: 'PEPTSans'; src: url(/fonts/plastecho/PT_Sans-Web-Italic.ttf) format('truetype'); font-weight: 400; font-style: italic; font-display: block; }
@font-face { font-family: 'PEPTSans'; src: url(/fonts/plastecho/PT_Sans-Web-Bold.ttf) format('truetype'); font-weight: 700; font-style: normal; font-display: block; }
@font-face { font-family: 'PEPTSans'; src: url(/fonts/plastecho/PT_Sans-Web-BoldItalic.ttf) format('truetype'); font-weight: 700; font-style: italic; font-display: block; }
@font-face { font-family: 'PEOswald'; src: url(/fonts/plastecho/Oswald-VF.ttf) format('truetype'); font-weight: 200 700; font-style: normal; font-display: block; }
@font-face { font-family: 'PEPTSansNarrow'; src: url(/fonts/plastecho/PT_Sans-Narrow-Web-Regular.ttf) format('truetype'); font-weight: 400; font-style: normal; font-display: block; }
@font-face { font-family: 'PEPTSansNarrow'; src: url(/fonts/plastecho/PT_Sans-Narrow-Web-Bold.ttf) format('truetype'); font-weight: 700; font-style: normal; font-display: block; }
/* Carlito = zamiennik Calibri o identycznych szerokościach (OFL, Google Crosextra). */
@font-face { font-family: 'PECarlito'; src: url(/fonts/plastecho/Carlito-Regular.ttf) format('truetype'); font-weight: 400; font-style: normal; font-display: block; }
@font-face { font-family: 'PECarlito'; src: url(/fonts/plastecho/Carlito-Italic.ttf) format('truetype'); font-weight: 400; font-style: italic; font-display: block; }
@font-face { font-family: 'PECarlito'; src: url(/fonts/plastecho/Carlito-Bold.ttf) format('truetype'); font-weight: 700; font-style: normal; font-display: block; }
@font-face { font-family: 'PECarlito'; src: url(/fonts/plastecho/Carlito-BoldItalic.ttf) format('truetype'); font-weight: 700; font-style: italic; font-display: block; }
/* Font Awesome 6 Free (fonty: OFL 1.1; ikony kontaktowe w listach wystawców). */
@font-face { font-family: 'PEFASolid'; src: url(/fonts/plastecho/fa-solid-900.woff2) format('woff2'); font-weight: 900; font-style: normal; font-display: block; }
@font-face { font-family: 'PEFARegular'; src: url(/fonts/plastecho/fa-regular-400.woff2) format('woff2'); font-weight: 400; font-style: normal; font-display: block; }
@font-face { font-family: 'PEFABrands'; src: url(/fonts/plastecho/fa-brands-400.woff2) format('woff2'); font-weight: 400; font-style: normal; font-display: block; }

html, body { margin: 0; height: 100%; background: #2b2b2d; color: #eee; font-family: system-ui, -apple-system, 'Segoe UI', sans-serif; }
.app { display: flex; flex-direction: column; height: 100vh; height: 100dvh; overflow: hidden; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* Jedna belka u góry (46 px): logo + numer z lewej, kartkowanie, spis, zoom, z prawej pełny ekran, udostępnianie, PDF.
   Dwie belki (nagłówek + pasek na dole) zabierały stronie ~90 px - decyzja usera 14.10; linki „Wszystkie numery /
   Prenumerata / Plastech.pl" wypadły, bo czytnik żyje w iframe karty numeru, a nawigację portalu ma karta. */
.tb { flex: none; display: flex; align-items: center; gap: 6px 14px; flex-wrap: wrap; padding: 6px 12px; background: #1b1b1d; border-bottom: 1px solid #333; }
.tb-brand { margin-right: auto; gap: 12px; min-width: 0; }
.tb-end { margin-left: auto; }
.hd-logo img { display: block; height: 20px; }
.hd-issue { color: #bbb; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hd-issue .short { display: none; }

/* Scena: rozkładówka dopasowana do okna; przy powiększeniu przewijana (i przeciągana myszą). */
.stage { flex: 1; position: relative; overflow: auto; outline: none; overscroll-behavior: contain; touch-action: manipulation; }
.stage.pan { cursor: grab; }
.stage.panning { cursor: grabbing; user-select: none; }
.spread { display: flex; justify-content: center; align-items: center; gap: 2px; padding: 16px; width: max-content; min-width: 100%; min-height: 100%; box-sizing: border-box; }
.pg { position: relative; flex: none; background: #fff; box-shadow: 0 2px 14px rgba(0, 0, 0, .5); }
.pg img.bg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; user-select: none; -webkit-user-drag: none; }
.pg svg.tl { position: absolute; inset: 0; width: 100%; height: 100%; font-family: 'PELato', sans-serif; text-rendering: geometricPrecision; }
/* `pre` MUSI stać na samym <text>/<tspan>: Chrome daje im z arkusza przeglądarki `white-space: nowrap`, który
   wygrywa z dziedziczeniem z <svg> (i z xml:space). Bez tego spacja na początku fragmentu („2026:| jubileuszowa”,
   zmiana koloru po dwukropku) znika, a każda litera dostaje pozycję poprzedniej - nagłówek się rozsypuje. */
.pg svg.tl text, .pg svg.tl tspan { white-space: pre; }
.pg svg.tl-bitmap text { fill-opacity: 0; }
.pg a.lk { position: absolute; display: block; }
.pg a.lk:hover { outline: 2px solid rgba(226, 0, 26, .6); background: rgba(226, 0, 26, .06); }
.edge { position: absolute; top: 0; bottom: 0; width: 56px; border: 0; background: transparent; cursor: pointer; opacity: 0; transition: opacity .15s; }
.edge::after { content: ''; position: absolute; top: 50%; left: 50%; width: 14px; height: 14px; border: solid #fff; border-width: 0 3px 3px 0; }
.edge-prev { left: 0; } .edge-prev::after { transform: translate(-30%, -50%) rotate(135deg); }
.edge-next { right: 0; } .edge-next::after { transform: translate(-70%, -50%) rotate(-45deg); }
.stage:hover .edge { opacity: .55; } .edge:hover { opacity: 1 !important; background: rgba(0, 0, 0, .25); }
.stage.zoomed .edge { display: none; }

/* Przyciski belki. */
.tb-group { display: flex; align-items: center; gap: 4px; }
.tb button, .tb .btn { display: inline-flex; align-items: center; gap: 6px; height: 34px; min-width: 34px; padding: 0 8px; box-sizing: border-box; justify-content: center;
  background: transparent; color: #eee; border: 1px solid transparent; border-radius: 6px; cursor: pointer; font: inherit; font-size: 14px; text-decoration: none; }
.tb button:hover, .tb .btn:hover { background: #333; border-color: #444; }
.tb button:disabled { opacity: .35; cursor: default; background: transparent; border-color: transparent; }
.tb svg, .panel-hd svg { width: 20px; height: 20px; fill: currentColor; flex: none; }
.pagesel { height: 34px; background: #2b2b2d; color: #eee; border: 1px solid #444; border-radius: 6px; padding: 0 6px; font: inherit; font-size: 14px; }

/* Panele: spis treści (z lewej) i udostępnianie (z prawej). */
.panel { position: fixed; top: 46px; bottom: 0; width: min(360px, 92vw); background: #1b1b1d; border: 1px solid #333; z-index: 20; display: flex; flex-direction: column; box-shadow: 0 0 24px rgba(0, 0, 0, .5); }
.panel[hidden] { display: none; }
.panel.toc { left: 0; } .panel.share { right: 0; }
.panel-hd { display: flex; justify-content: space-between; align-items: center; padding: 10px 14px; border-bottom: 1px solid #333; }
.panel-hd button { background: transparent; border: 0; color: #eee; cursor: pointer; }
.toc-list { list-style: none; margin: 0; padding: 6px 0; overflow: auto; }
.toc-list .sec { padding: 10px 14px 4px; color: #e2001a; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
.toc-list a { display: flex; gap: 10px; padding: 6px 14px; color: #ddd; text-decoration: none; font-size: 14px; line-height: 1.3; }
.toc-list a:hover, .toc-list a.on { background: #2e2e30; color: #fff; }
.toc-list .pn { flex: none; width: 2.2em; color: #888; text-align: right; }
.issue-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 14px; padding: 14px; overflow: auto; }
.issue-tile { display: block; color: #ddd; text-decoration: none; font-size: 13px; line-height: 1.3; }
.issue-tile img { display: block; width: 100%; aspect-ratio: 320 / 417; object-fit: cover; background: #333; border-radius: 3px; box-shadow: 0 2px 8px rgba(0, 0, 0, .5); margin-bottom: 6px; }
.issue-tile img.nocover { object-fit: contain; padding: 30% 12%; box-sizing: border-box; background: #2e2e30; }
.issue-tile strong { display: block; color: #fff; font-size: 12px; text-transform: uppercase; letter-spacing: .03em; }
.issue-tile:hover img { outline: 2px solid #e2001a; }
.issues-all { margin: 0 14px 14px; } .issues-all a { color: #ddd; }
/* Karta „czytaj dalej” w wolnym miejscu obok tylnej okładki (rozkładówka). */
.pg-end { flex: none; box-sizing: border-box; padding: 6% 7%; background: #232325; display: flex; flex-direction: column; gap: 16px; overflow: hidden; }
.pg-end h2 { margin: 0; font-size: 18px; color: #fff; }
.pg-end .issue-tiles { padding: 0; overflow: visible; flex: none; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); }
.share-pages { display: flex; gap: 8px; padding: 14px 14px 0; }
.share-pages:empty { display: none; }
.share-pages button { flex: 1; min-width: 0; padding: 8px 10px; border-radius: 6px; background: #2e2e30; color: #ddd; border: 1px solid #444; font: inherit; font-size: 13px; text-align: left; cursor: pointer; }
.share-pages button.on { border-color: #e2001a; background: #3a1c20; color: #fff; }
.share-pages button small { display: block; color: #aaa; font-size: 12px; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.share-img { display: block; width: calc(100% - 28px); margin: 14px; border-radius: 4px; background: #000; aspect-ratio: 1200 / 627; }
.share-title { margin: 0 14px 10px; font-size: 14px; color: #ccc; }
.share-links { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 14px 14px; }
.share-links a, .share-links button { padding: 8px 12px; border-radius: 6px; background: #2e2e30; color: #eee; border: 1px solid #444; text-decoration: none; font: inherit; font-size: 14px; cursor: pointer; }
.share-links a:hover, .share-links button:hover { background: #3a3a3c; }

/* Belka ma zostać w JEDNYM rzędzie (zawinięcie oddaje dwie belki). Zmierzone 14.10: komplet z podpisami = 1260 px,
   iframe karty numeru = ok. 770 px. Poniżej 1280 px podpisy przycisków znikają, a numer skraca się; poniżej 900 px
   wypadają skoki na początek/koniec i maleją odstępy (razem ok. 690 px). */
@media (max-width: 1279px) {
  .tb .wide span { display: none; }
  .hd-issue .long { display: none; }
  .hd-issue .short { display: inline; }
}
@media (max-width: 899px) {
  .tb { gap: 4px 8px; }
  .tb [data-act="first"], .tb [data-act="last"] { display: none; }
}
/* Telefon i wąskie okna: jedna strona, bez logo i numeru (tytuł numeru stoi na karcie nad iframe), bez zoomu
   i pełnego ekranu, panele na całą wysokość. */
@media (max-width: 760px) {
  .tb { gap: 2px 6px; padding: 4px; }
  .tb-brand { display: none; }
  .tb-end { margin-left: 0; }
  .tb-group { gap: 0; }
  .tb button, .tb .btn { min-width: 32px; padding: 0 4px; }
  .pagesel { padding: 0 2px; font-size: 13px; }
  .tb-zoom { display: none; }
  .tb [data-act="fullscreen"] { display: none; }
  .panel { top: 0; }
  .edge { display: none; }
  .spread { padding: 8px; }
}

/* Tryb porównawczy dla skryptów kontroli (shoot.js, qa.js): sama strona o stałej szerokości, bez interfejsu. */
body.diff { background: #fff; }
body.diff .app { height: auto; overflow: visible; }
body.diff .tb, body.diff .edge, body.diff .panel { display: none; }
body.diff .stage { overflow: visible; }
body.diff .spread { padding: 0; justify-content: flex-start; align-items: flex-start; min-height: 0; }
body.diff .pg { box-shadow: none; }
