/* ============================================================================
   Читалка. Общие шкалы и цвета — в webapp/css/base.css, он подключён здесь же.

   Своя пара цветов ниже: стол, на котором лежит страница книги, и сама
   бумага. Они НЕ берутся из общей темы намеренно. Страница учебника всегда
   белая — это скан бумаги, перекрасить её нельзя. Значит и подложка под ней
   должна оставаться тёмной в любой теме: на светлом фоне белая страница
   теряет края и сливается с экраном.
   ========================================================================== */
:root {
  --stage: #3a3f4b;        /* стол под страницей */
  --stage-ink: #c8ccd4;    /* надписи на столе: «Китеп ачылып жатат» */
  --paper: #ffffff;        /* бумага страницы */
  --paper-shadow: 0 4px 24px rgba(0, 0, 0, .35);
  /* Тот же цвет, что и у надписей, но приглушённый — внутренний край
     листа в заставке. Записан числом, а не посчитан из --stage-ink через
     color-mix: тот появился в браузерах весной 2023-го, и на телефоне
     постарше всё правило фона отбросилось бы целиком — лист стал бы
     невидимым, а заставка превратилась бы в неподвижную книгу. */
  --stage-ink-soft: rgba(200, 204, 212, .45);
}

body { background: var(--stage); -webkit-text-size-adjust: 100%; overflow-x: clip; }
    .rbar {
      background: var(--card);
      border-bottom: 1px solid var(--line);
      padding: calc(7px + var(--safe-top)) 10px 7px;
      display: flex;
      align-items: center;
      gap: 8px;
      position: sticky;
      top: 0;
      z-index: 20;
    }
    .rbar .name {
      font-weight: 600;
      font-size: 14px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      flex: 1;
      min-width: 0;
    }
    .iconbtn {
      flex: none;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: 1px solid var(--line);
      background: var(--card);
      color: var(--ink);
      border-radius: var(--radius-md);
      padding: 7px 9px;
      font-size: 15px;
      line-height: 1;
      cursor: pointer;
    }
    /* Внутри кнопки значок стоит сам по себе, без текста рядом, поэтому
       поправка на базовую линию тут только мешает. */
    .iconbtn .icon { vertical-align: 0; }
    /* Закладка стоит на этой странице. Значок ещё и заливается: одного
       фона мало — на маленькой кнопке разница между «есть» и «нет»
       должна читаться самой картинкой, а не подложкой под ней.
       Цвета из общих переменных (webapp/css/base.css), поэтому состояние
       работает и в тёмной теме. */
    .iconbtn.on { background: var(--warn-bg); border-color: var(--warn-line); }
    .iconbtn.on .icon { fill: currentColor; color: var(--warn-ink); }
    /* шаговый переход по совпадениям */
    .hit-nav { display: none; align-items: center; gap: 2px; flex: none; }
    .hit-nav.show { display: inline-flex; }
    .hit-nav .lbl { font-size: 12px; color: var(--muted); min-width: 40px; text-align: center; }
    .hit-nav button { padding: 6px 8px; }
    /* область страниц */
    .stage {
      display: block;
      /* Снизу 76 точек — под панель управления чтением. Она стала выше на
         безопасную зону, значит и запас должен вырасти, иначе последняя
         страница книги уходила бы под панель. */
      padding: 12px 0 calc(76px + var(--safe-bottom));
    }
    .stage.single {
      padding-top: 8px;
      /* 52px — верхняя панель, --banner-h — плашка бесплатного режима,
         если она сейчас висит (задаётся в webapp/css/base.css). */
      min-height: calc(100dvh - 52px - var(--banner-h, 0px));
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
    }
    /* Заставка на время открытия книги. Толстый учебник открывается за
       несколько секунд: читалка успевает сделать три десятка обращений за
       кусками файла. Без заставки человек всё это время видит пустой тёмный
       экран и решает, что сайт сломался.

       Лежит ниже верхней и нижней панелей (у них z-index 20), чтобы уйти со
       страницы можно было, не дожидаясь книги. */
    .loader {
      position: fixed;
      left: 0;
      right: 0;
      bottom: 0;
      top: calc(52px + var(--banner-h, 0px));
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 14px;
      background: var(--stage);
      z-index: 10;
    }
    .loader-text { color: var(--stage-ink); font-size: var(--text-base); }
    /* Картинка первой страницы. Занимает почти всю высоту, как настоящая
       страница, и выглядит так же — чтобы подмена на живую не бросалась
       в глаза. */
    .loader-page {
      max-width: min(100%, 900px);
      max-height: calc(100% - 64px);
      object-fit: contain;
      background: var(--paper);
      border-radius: var(--radius-sm);
      box-shadow: var(--paper-shadow);
    }
    /* Книга, которая листает страницы, — вместо кружка ожидания.
       Кружок ничего не говорит о том, чего ждёшь; здесь же видно, что
       открывается именно книга.

       Рисуется целиком стилями, без картинок: значок пришлось бы грузить
       ровно тогда, когда сеть и так занята самой книгой.

       Размеры одной величиной: половина разворота задаётся в --leaf, всё
       остальное считается от неё. Захочется книгу крупнее — меняется одно
       число, и пропорции не разъезжаются. */
    .loader-book {
      --leaf: 50px;
      position: relative;
      width: calc(var(--leaf) * 2);
      height: calc(var(--leaf) * 1.35);
      /* Перспектива обязательна: без неё лист не поворачивается, а плоско
         сжимается по горизонтали — получается не книга, а жалюзи.

         Но и сильной ей быть нельзя: ближний край листа раздувается, и
         страница вылезает за книгу сверху и снизу — выходит лезвие, а не
         страница. Замерил вылет при разной перспективе (лист 80 точек):
         ×2.5 — 21 точка, ×5 — 9, ×8 — 5, ×12 — 3. Берём ×10: объём виден,
         вылет около двух точек и читается как толщина бумаги. */
      perspective: calc(var(--leaf) * 10);
    }

    /* Раскрытая книга: две неподвижные половины. Они приглушены, потому что
       это фон — движется и притягивает взгляд только лист. */
    .loader-book::before,
    .loader-book::after {
      content: "";
      position: absolute;
      top: 0;
      /* На точку уже половины: между половинами остаётся щель — корешок.
         Без неё две половины сливаются в один серый прямоугольник, и книгу
         в нём не узнать. */
      width: calc(var(--leaf) - 1px);
      height: 100%;
      background: var(--stage-ink);
      opacity: .22;
    }
    .loader-book::before { left: 0; border-radius: 3px 0 0 3px; }
    .loader-book::after { right: 0; border-radius: 0 3px 3px 0; }

    /* Лист поворачивается вокруг корешка — от правой половины к левой. */
    .loader-book .leaf {
      position: absolute;
      top: 0;
      left: 50%;
      width: calc(var(--leaf) - 1px);
      height: 100%;
      /* Ближе к внешнему краю лист светлее: так видно, что он объёмный
         и повёрнут, а не просто перекрашенный прямоугольник. */
      background: linear-gradient(to right,
                  var(--stage-ink-soft), var(--stage-ink));
      border-radius: 0 3px 3px 0;
      transform-origin: left center;
      backface-visibility: hidden;
      animation: leaf-turn 2.4s ease-in-out infinite;
    }
    /* Три листа, каждый следующий вступает на трети круга: движение
       читается непрерывным, а не как одна страница туда-сюда. */
    .loader-book .leaf:nth-child(2) { animation-delay: .8s; }
    .loader-book .leaf:nth-child(3) { animation-delay: 1.6s; }

    /* Лист появляется на правой половине и растворяется на левой. Обе
       границы прозрачны намеренно: без этого в конце круга он прыгал бы
       из перевёрнутого положения обратно в исходное — рывком, на глазах. */
    @keyframes leaf-turn {
      0% { transform: rotateY(0deg); opacity: 0; }
      12% { opacity: .9; }
      82% { opacity: .9; }
      100% { transform: rotateY(-180deg); opacity: 0; }
    }

    /* Кому движение мешает — системная настройка это говорит, уважаем.
       Остаётся раскрытая книга с одной страницей: картинка та же, просто
       неподвижная, и ожидание по-прежнему выглядит осмысленным. */
    @media (prefers-reduced-motion: reduce) {
      .loader-book .leaf { animation: none; opacity: .9; }
      .loader-book .leaf:nth-child(2),
      .loader-book .leaf:nth-child(3) { display: none; }
    }

    .page-wrap {
      position: relative;
      margin: 0 auto 14px;
      background: var(--paper);
      box-shadow: var(--paper-shadow);
      border-radius: var(--radius-sm);
      overflow: hidden;
      max-width: 100%;
    }
    .stage.single .page-wrap { margin-bottom: 0; }
    /* Подложка страницы: номер и кружок ожидания. Видна, пока страница не
       нарисована — например, когда человек прыгнул в середину книги и её
       куски ещё едут из хранилища. Как только страница готова, холст
       накрывает подложку собой. */
    .page-wrap .ph {
      position: absolute;
      inset: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 12px;
      color: var(--stage-ink);
      font-size: 20px;
      z-index: 0;
    }
    .page-wrap .ph .spin {
      width: 24px;
      height: 24px;
      border: 3px solid var(--line);
      border-top-color: var(--muted);
      border-radius: 50%;
      animation: loader-turn .8s linear infinite;
    }
    @media (prefers-reduced-motion: reduce) {
      .page-wrap .ph .spin { animation: none; }
    }
    .page-wrap canvas {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      z-index: 1;
    }
    /* прозрачный текстовый слой PDF.js — выделение/копирование/клик по слову */
    .textLayer {
      position: absolute;
      inset: 0;
      overflow: hidden;
      line-height: 1;
      text-align: initial;
      text-size-adjust: none;
      forced-color-adjust: none;
      z-index: 2;
    }
    .textLayer span {
      color: transparent;
      position: absolute;
      white-space: pre;
      cursor: text;
      transform-origin: 0% 0%;
    }
    /* Совпадения поиска. Как и у шпаргалок, color: transparent обязателен:
       буквы текстового слоя невидимы, их видно с картинки страницы, а <mark>
       по умолчанию красит текст чёрным — вышло бы второе, съехавшее
       начертание поверх первого. */
    .textLayer mark.hl {
      background: rgba(250, 204, 21, .5);
      color: transparent;
      border-radius: 2px;
      padding: 0;
    }
    /* Текущее совпадение — то, на котором стоит счётчик «‹ 3/17 ›». */
    .textLayer mark.hl.cur { background: rgba(249, 115, 22, .65); }
    .textLayer ::selection { background: rgba(37, 99, 235, .35); }
    .navbar {
      position: fixed;
      bottom: 0;
      left: 0;
      right: 0;
      background: var(--card);
      border-top: 1px solid var(--line);
      /* Снизу добавляем безопасную зону: в установленном приложении экран
         занят целиком, и без этого панель управления чтением уехала бы под
         полосу жестов айфона — кнопки листания оказались бы наполовину
         перекрыты. В браузере величина равна нулю и ничего не меняет. */
      padding: 7px 10px calc(7px + var(--safe-bottom));
      padding-left: max(10px, var(--safe-left));
      padding-right: max(10px, var(--safe-right));
      display: flex;
      align-items: center;
      justify-content: center;
      flex-wrap: wrap;
      gap: 8px;
      z-index: 20;
    }
    .seg {
      display: inline-flex;
      border: 1px solid var(--line);
      border-radius: 8px;
      overflow: hidden;
    }
    .seg button {
      border: 0;
      background: var(--card);
      padding: 6px 11px;
      font-size: 13px;
      cursor: pointer;
      color: var(--ink);
    }
    .seg button.on { background: var(--accent); color: var(--accent-ink); }
    .navbar input.pg {
      width: 56px;
      text-align: center;
      border: 1px solid var(--line);
      border-radius: 8px;
      padding: 6px;
      font-size: 14px;
    }
    .navbar .total { font-size: 13px; color: var(--muted); }

    /* На телефоне панель управления чтением обязана уместиться в одну
       строку: перенос отправляет кнопку масштаба на второй ряд, и та
       закрывает низ страницы книги.

       Замер на экране 375: содержимое просило 356 точек при доступных 355 —
       не хватало одной. Поэтому здесь не подгоняем ширину каждой кнопки,
       а забираем запас там, где он ничего не стоит: промежутки и боковые
       отступы. flex-wrap оставляем — он страховка на совсем узких экранах,
       где ужиматься уже некуда. */
    @media (max-width: 430px) {
      /* Отступ снизу обязан сохранить безопасную зону. Сокращение
         «padding: 7px 6px» стирало её как раз там, где она и нужна, —
         на телефоне: панель уезжала под полосу жестов. */
      .navbar { gap: 5px; padding: 7px 6px calc(7px + var(--safe-bottom)); }
      .navbar .iconbtn { padding: 7px; }
      .navbar input.pg { width: 48px; }
    }
    /* закладки — небольшая выпадашка */
    .panel {
      position: fixed;
      top: 50px;
      right: 8px;
      left: 8px;
      max-width: 360px;
      margin-left: auto;
      background: var(--card);
      border: 1px solid var(--line);
      border-radius: 12px;
      padding: 12px;
      max-height: 70vh;
      overflow: auto;
      box-shadow: 0 8px 30px rgba(0,0,0,.3);
      display: none;
      z-index: 30;
    }
    .panel.open { display: block; }
    .panel h3 { margin: 0 0 8px; font-size: 14px; }
    .panel a { display: block; padding: 7px 8px; border-radius: 8px; font-size: 14px; }
    .panel a:hover { background: var(--bg); }
    .panel .empty { color: var(--muted); font-size: 13px; }
    .toc-head { font-weight: 600; font-size: 12px; color: var(--muted); margin: 10px 4px 2px; text-transform: uppercase; letter-spacing: .02em; }
    /* заголовок раздела со своим номером страницы — такая же ссылка, как пункт */
    a.toc-head { display: flex; gap: 8px; justify-content: space-between; text-decoration: none; }
    a.toc-head:hover, a.toc-head:focus-visible { color: inherit; }
    #toc-list a { display: flex; justify-content: space-between; gap: 10px; }
    .toc-pg { color: var(--muted); flex: none; }
    /* Стрелка к настоящей странице «Мазмуну» в книге. display: inline
       обязателен: выше у всех ссылок панели стоит block, и стрелка уезжала
       на вторую строку под заголовок. */
    a.toc-src {
      display: inline;
      color: var(--muted);
      text-decoration: none;
      font-weight: 400;
      padding: 0 4px;
    }
    a.toc-src:hover, a.toc-src:focus-visible { color: inherit; }
    /* панель результатов поиска */
    .search-sidebar {
      position: fixed;
      z-index: 40;
      background: var(--card);
      display: none;
      flex-direction: column;
    }
    .search-sidebar.open { display: flex; }
    .ss-head {
      display: flex;
      gap: 8px;
      align-items: center;
      padding: 10px;
      border-bottom: 1px solid var(--line);
    }
    .ss-head input {
      flex: 1;
      min-width: 0;
      border: 1px solid var(--line);
      border-radius: 8px;
      padding: 8px 10px;
      font-size: 14px;
    }
    .ss-status {
      padding: 7px 12px;
      font-size: 13px;
      color: var(--muted);
      border-bottom: 1px solid var(--line);
    }
    .ss-results { flex: 1; overflow: auto; padding: 4px; }
    .res {
      display: block;
      padding: 9px 10px;
      border-radius: 8px;
      cursor: pointer;
      border-bottom: 1px solid var(--line);
    }
    .res:hover { background: var(--bg); }
    .res.active { background: var(--note-bg); }
    .res-top { display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 3px; }
    .res-top b { font-weight: 600; }
    .res-top span { color: var(--muted); }
    .res-snip { font-size: 13px; color: var(--ink); line-height: 1.4; }
    .res-snip mark { background: rgba(250, 204, 21, .6); border-radius: 2px; padding: 0 1px; }
    @media (max-width: 759px) {
      .search-sidebar {
        left: 0; right: 0; bottom: 0;
        height: 46vh;
        border-top: 1px solid var(--line);
        box-shadow: 0 -8px 30px rgba(0,0,0,.35);
      }
      body.search-open .navbar { display: none; }
      body.search-open .stage { padding-bottom: 48vh; }
    }
    @media (min-width: 760px) {
      .search-sidebar {
        top: 0; bottom: 0; left: 0;
        width: 340px;
        border-right: 1px solid var(--line);
        box-shadow: 2px 0 16px rgba(0,0,0,.25);
      }
      body.search-open .stage { margin-left: 340px; }
      body.search-open .navbar { left: 340px; }
    }
    /* карточка слова (клик по слову → Элсоздук) */
    .word-card {
      position: fixed;
      left: 8px; right: 8px; bottom: 70px;
      max-width: 460px;
      margin: 0 auto;
      background: var(--card);
      border: 1px solid var(--line);
      border-radius: 12px;
      box-shadow: 0 8px 30px rgba(0,0,0,.35);
      padding: 12px 14px;
      max-height: 52vh;
      overflow: auto;
      display: none;
      z-index: 45;
    }
    .word-card.open { display: block; }
    .wc-head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
    #wc-word { font-weight: 600; font-size: 16px; flex: 1; min-width: 0; }
    #wc-link { font-size: 12px; color: var(--accent); flex: none; }
    .wc-entry { padding: 9px 0; border-top: 1px solid var(--line); }
    .wc-entry .src { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .02em; }
    .wc-entry .lemma { font-weight: 600; font-size: 14px; margin: 2px 0; }
    .wc-entry .tr { font-size: 14px; line-height: 1.5; }
    .wc-loading, .wc-empty { color: var(--muted); font-size: 14px; padding: 6px 0; }
    /* Подсвеченное сохранённое место. Красится ровно выделенный отрезок
       символов, а не весь кусок текстового слоя, поэтому это <mark> внутри
       span-а. color: transparent обязателен: буквы текстового слоя невидимы,
       их видно с картинки страницы, а <mark> по умолчанию красит текст
       чёрным — получилось бы второе, съехавшее начертание поверх первого. */
    .textLayer mark.snip-hl {
      background: rgba(34, 197, 94, .32);
      color: transparent;
      border-radius: 2px;
      cursor: pointer;
      padding: 0;
    }

    /* Окошко сохранения: цитата, поле заметки, две кнопки (ТЗ §Э5).
       position: fixed — координаты берём из getBoundingClientRect,
       то есть уже относительно окна, а не документа. */
    .snip-pop, .snip-view {
      position: fixed;
      z-index: 60;
      width: min(320px, calc(100vw - 16px));
      background: var(--card);
      border: 1px solid var(--line);
      border-radius: 12px;
      box-shadow: 0 8px 30px rgba(0, 0, 0, .35);
      padding: 10px;
    }
    .snip-pop-quote {
      font-size: 13px;
      color: var(--muted);
      line-height: 1.4;
      margin-bottom: 8px;
      max-height: 60px;
      overflow: hidden;
    }
    .snip-pop textarea {
      width: 100%;
      border: 1px solid var(--line);
      border-radius: 8px;
      padding: 7px 9px;
      font: inherit;
      font-size: 14px;
      resize: vertical;
    }
    .snip-pop-row { display: flex; gap: 8px; justify-content: flex-end; margin-top: 8px; }
    .iconbtn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
    .iconbtn.danger { color: var(--danger); }

    .snip-view-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      font-size: 13px;
      color: var(--muted);
      margin-bottom: 6px;
    }
    .snip-view-note { margin: 0 0 8px; font-size: 14px; line-height: 1.45; }
    .snip-view-note.muted { color: var(--muted); font-style: italic; }
    .snip-view-text {
      margin: 0 0 10px;
      font-size: 13px;
      color: var(--muted);
      line-height: 1.45;
      max-height: 120px;
      overflow: auto;
      border-left: 3px solid var(--line);
      padding-left: 8px;
    }

    .snip-toast {
      position: fixed;
      z-index: 60;
      left: 50%;
      bottom: 72px;
      transform: translateX(-50%);
      /* Своя тёмная плашка, а не цвет темы: сообщение всплывает поверх
         страницы книги, а та белая при любой теме. */
      background: rgba(17, 24, 39, .92);
      color: #fff;
      font-size: var(--text-sm);
      padding: var(--space-2) var(--space-4);
      border-radius: var(--radius-full);
    }
