* { box-sizing: border-box; }
body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    color: #1b1b18;
    background: #eef1f6;
}

.block-label {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: #97a0ad;
}

.layout {
    min-height: 100vh;
}

/* VK Mini App (games/__vk_puzzlum, см. docs/INTEGRATIONS.md) грузит страницу в iframe
   ФИКСИРОВАННОЙ высоты и не пробрасывает скролл документа дальше самого iframe — обычная схема
   этой вёрстки (скролл всей страницы через body/html) внутри VK не работает: контент просто
   обрезается по границе iframe. Класс .vk-embed (ставится на <html>, см.
   PuzzlumRoute::isVkContext() в каждой вьюхе Пазлум) превращает раскладку в классический "app
   shell": html/body сами не скроллятся, .layout становится колонкой на всю высоту iframe, а
   единственная скроллящаяся область — сам .app-main (шапка и бургер-панель остаются на месте,
   т.к. лежат вне этой прокручиваемой зоны). На обычном сайте (без класса) поведение не меняется —
   там по-прежнему скроллится обычный document. */
html.vk-embed,
html.vk-embed body {
    height: 100%;
    overflow: hidden;
}

html.vk-embed .layout {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

html.vk-embed .layout-body {
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

html.vk-embed .app-main {
    height: 100%;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.app-header {
    position: sticky;
    top: 0;
    z-index: 20;
    height: 64px;
    display: flex;
    align-items: center;
    padding: 0 20px;
    background: #fff;
    box-shadow: 0 1px 0 rgba(20, 30, 50, 0.08), 0 4px 10px rgba(20, 30, 50, 0.04);
}

/* Три части шапки в строку (см. docs/MENUS.md): лево (бургер + опциональные кнопки быстрого
   управления приложения) / центр (лого) / право (пользователь). Левая и правая часть — по
   равной доле оставшегося места и прижаты каждая к своему краю, тогда центр остаётся ровно по
   центру независимо от того, насколько левая и правая части отличаются по ширине. */
.app-header-left,
.app-header-right {
    display: flex;
    align-items: center;
    flex: 1 1 0;
    min-width: 0;
}

.app-header-left {
    justify-content: flex-start;
    gap: 10px;
}

.app-header-right {
    justify-content: flex-end;
}

.app-header-center {
    flex: 0 0 auto;
}

.header-user-widget {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 36px;
    padding: 0 16px;
    border-radius: 8px;
    background: #e4e8ef;
    color: #6b7280;
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
}

.sidebar-burger {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    margin-right: 6px;
    padding: 0;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: #1b1b18;
    cursor: pointer;
}

.sidebar-burger:hover {
    background: #f0f2f6;
}

.sidebar-burger svg {
    width: 22px;
    height: 22px;
}

.sidebar-overlay {
    display: none;
    position: fixed;
    inset: 64px 0 0 0;
    z-index: 25;
    background: rgba(15, 20, 30, 0.45);
    opacity: 0;
    transition: opacity 0.2s ease;
}

.sidebar-overlay.is-open {
    display: block;
    opacity: 1;
}

.app-logo {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    text-decoration: none;
    color: inherit;
}

.app-logo-icon {
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.15));
    transition: transform 0.2s ease;
}

.app-logo:hover .app-logo-icon {
    transform: rotate(-8deg) scale(1.08);
}

.app-logo-text {
    font-size: 26px;
    font-weight: 800;
    letter-spacing: -0.01em;
    background: linear-gradient(135deg, #ff6b6b, #ffa94d 45%, #4dabf7 75%, #9775fa);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.layout-body {
    display: flex;
    align-items: flex-start;
    min-height: calc(100vh - 64px);
}

/* Панель, которую открывает бургер в шапке (см. docs/MENUS.md) — единый для ЛЮБОЙ ширины экрана
   элемент интерфейса приложения: всегда выезжающая слева панель поверх контента, скрытая по
   умолчанию (закрыта — за пределами экрана слева), открывается классом .is-open. Не зависит от
   ширины окна — в этом и есть "единый вид меню для конечных приложений", о котором договорились:
   на десктопе бургер и эта панель ведут себя точно так же, как на телефоне. Отдельно от неё —
   .app-desktop-sidebar ниже: самостоятельный, специфичный для Пазлум элемент (полный список
   категорий, всегда виден на широких экранах), к бургеру отношения не имеющий.
   max-width:300px делает width:82vw практических неотличимым от фиксированных 300px на любом
   экране шире ~366px — то есть на десктопе ширина панели такая же, как на мобильном. */
.app-sidebar {
    position: fixed;
    top: 64px;
    left: 0;
    bottom: 0;
    z-index: 26;
    width: 82vw;
    max-width: 300px;
    padding: 20px;
    background: #f3f5f9;
    box-shadow: 2px 0 12px rgba(20, 30, 50, 0.2);
    overflow-y: auto;
    transform: translateX(-100%);
    transition: transform 0.25s ease;
}

.app-sidebar.is-open {
    transform: translateX(0);
}

/* Самостоятельный десктопный сайдбар Пазлум с полным списком категорий — виден только на широких
   экранах (см. @media ниже), не связан с бургер-панелью выше и живёт рядом с ней одновременно. */
.app-desktop-sidebar {
    flex-shrink: 0;
    width: 240px;
    padding: 20px;
    background: #f3f5f9;
    box-shadow: 1px 0 0 rgba(20, 30, 50, 0.06);
    /* Липкий сайдбар: остаётся на месте при длинном скролле страницы (см. .app-header — тот же
       64px, под которым он "прилипает"), а если список категорий сам выше экрана — не ломает
       раскладку и не обрезается, а скроллится внутри собственных границ. */
    position: sticky;
    top: 64px;
    max-height: calc(100vh - 64px);
    overflow-y: auto;
}

.sidebar-categories {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 12px;
}

.sidebar-block-label-spaced {
    display: block;
    margin-top: 24px;
}

.sidebar-category-link {
    display: block;
    padding: 9px 12px;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 600;
    color: #4b5563;
    text-decoration: none;
    transition: background 0.15s ease, color 0.15s ease;
}

.sidebar-category-adult-badge {
    display: inline-block;
    margin-left: 4px;
    padding: 1px 5px;
    border-radius: 4px;
    background: #c0392b;
    color: #fff;
    font-size: 10px;
    font-weight: 800;
    vertical-align: middle;
}

.sidebar-category-link:hover {
    background: #e9ecf2;
}

.sidebar-category-link.is-active {
    background: #fff;
    color: #1b1b18;
    box-shadow: 0 1px 4px rgba(20, 30, 50, 0.1);
}

.sidebar-nav-spaced {
    margin-top: 24px;
}

/* "Все категории" — та же ссылка визуально, но это <button> (открывает попап, а не переходит по
   ссылке) — сбрасываем стандартные для <button> рамку/фон/шрифт до вида .sidebar-category-link. */
.sidebar-all-categories-btn {
    width: 100%;
    border: none;
    background: transparent;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.categories-modal {
    position: fixed;
    inset: 0;
    z-index: 250;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(10, 12, 16, 0.5);
    opacity: 1;
    transition: opacity 0.3s ease;
}

.categories-modal[hidden] {
    display: none;
}

.categories-modal--closing {
    opacity: 0;
}

.categories-modal-box {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 14px;
    width: 100%;
    max-width: 360px;
    max-height: 80vh;
    padding: 28px 24px 24px;
    background: #fff;
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
    overflow: hidden;
}

.categories-modal-title {
    margin: 0;
    font-size: 18px;
    font-weight: 800;
}

.categories-modal-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    overflow-y: auto;
}

.categories-modal-close {
    position: absolute;
    top: 10px;
    right: 10px;
}

.app-main {
    flex: 1;
    min-width: 0;
    /* Заполняет всю оставшуюся высоту экрана под шапкой, даже если пазлов в разделе мало —
       иначе фон .app-main обрывался бы раньше конца видимой области (см. .layout-body:
       align-items: flex-start у сайдбара не даёт колонкам тянуться по умолчанию). */
    min-height: calc(100vh - 64px);
    padding: 24px;
    background: #e4e8ef;
}

.puzzle-catalog {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
    gap: 20px;
}

/* Узкие экраны: десктопный сайдбар с полным списком категорий (.app-desktop-sidebar) прячется —
   на таких экранах навигация только через бургер-панель (.app-sidebar, теперь одинаковую на любой
   ширине, см. её описание выше), сама шапка теряет отступ под логотип, а сетка карточек ужимается
   вплоть до одной колонки. */
@media (max-width: 860px) {
    .app-desktop-sidebar {
        display: none;
    }

    .app-main {
        padding: 14px;
    }

    .puzzle-catalog {
        grid-template-columns: 1fr;
        gap: 14px;
    }

    /* Шапка на узких экранах (см. docs/MENUS.md, "Адаптация шапки на узких экранах"): части не
       растягиваются по трети ширины каждая — бургер и лого прижимаются друг к другу слева (левая и
       центральная часть перестают расти, всё оставшееся место забирает центр, а не делится поровну
       между левой и правой частью), правая часть (пользователь/гость) остаётся у правого края. */
    .app-header-left {
        flex: 0 0 auto;
    }

    .app-header-center {
        flex: 1 1 auto;
        min-width: 0;
    }

    .app-header-right {
        flex: 0 0 auto;
    }
}

@media (max-width: 420px) {
    .app-logo-text {
        font-size: 21px;
    }
}

.puzzle-creator-header {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 20px;
}

.puzzle-creator-header-avatar {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.puzzle-creator-header-title {
    margin: 0;
    font-size: 20px;
}

.puzzle-catalog-title {
    margin: 0 0 20px;
    font-size: 20px;
    font-weight: 800;
}

.puzzle-creator-header-name {
    font-weight: 800;
}

.puzzle-creator-header-suffix {
    font-weight: 500;
    color: #6b7280;
}

.puzzle-catalog-empty {
    margin: 40px 0;
    text-align: center;
    color: #6b7280;
    font-size: 15px;
}

.puzzle-load-more-wrap {
    display: flex;
    justify-content: center;
    margin-top: 28px;
}

.puzzle-load-more-btn {
    padding: 11px 28px;
    border: none;
    border-radius: 999px;
    background: #fff;
    color: #1b1b18;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(20, 30, 50, 0.1);
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.puzzle-load-more-btn:hover {
    box-shadow: 0 6px 16px rgba(20, 30, 50, 0.16);
    transform: translateY(-1px);
}

.puzzle-card {
    position: relative;
    background: #fff;
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 2px 8px rgba(20, 30, 50, 0.08);
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.puzzle-card:hover {
    box-shadow: 0 10px 24px rgba(20, 30, 50, 0.16);
}

.puzzle-card-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 12px 14px;
}

.puzzle-card-title {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
}

.puzzle-card-title-link {
    color: inherit;
    text-decoration: none;
}

.puzzle-card-title-link:hover {
    text-decoration: underline;
}

.puzzle-card-title-link::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
}

.puzzle-card-rating {
    font-size: 15.4px;
    letter-spacing: 1px;
    white-space: nowrap;
}

.stars-filled { color: #ffa94d; }
.stars-empty { color: #d8dce3; }

.puzzle-card-thumb {
    position: relative;
    aspect-ratio: 21 / 9;
    background: #f0f2f6;
    overflow: hidden;
}

.puzzle-card-thumb img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.puzzle-card-new-badge {
    position: absolute;
    top: 10px;
    left: 10px;
    padding: 4px 10px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: #fff;
    background: linear-gradient(135deg, #ff6b6b, #ffa94d 45%, #4dabf7 75%, #9775fa);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}

.puzzle-card-visibility-badge {
    position: absolute;
    top: 10px;
    right: 10px;
    padding: 4px 10px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: #fff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}

.puzzle-card-visibility-badge--private {
    background: #4b5563;
}

.puzzle-card-visibility-badge--pending {
    background: #d97706;
}

.puzzle-card-visibility-badge--rejected {
    background: #c0392b;
}

.puzzle-card-video-badge {
    position: absolute;
    bottom: 10px;
    right: 10px;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    border: 2px solid #fff;
    color: #fff;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
}

.puzzle-card-video-badge svg {
    width: 16px;
    height: 16px;
}

.puzzle-card-bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 14px;
    border-top: 1px solid #eef0f4;
}

.puzzle-card-plays {
    font-size: 13px;
    color: #6b7280;
    white-space: nowrap;
}

.puzzle-card-creator {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: center;
    min-width: 0;
}

.puzzle-card-creator-link {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    text-decoration: none;
    color: inherit;
}

.puzzle-card-creator-avatar {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.puzzle-card-creator-name {
    font-size: 13px;
    font-weight: 600;
    color: #4b5563;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.puzzle-card-creator-link:hover .puzzle-card-creator-name {
    color: #1f2937;
    text-decoration: underline;
}

.puzzle-card-creator-name--system {
    color: #9ca3af;
    font-weight: 500;
}

.puzzle-create {
    max-width: 900px;
    margin: 0 auto;
}

.puzzle-create-title {
    margin: 0 0 20px;
    font-size: 24px;
    font-weight: 800;
}

.puzzle-create-errors {
    margin-bottom: 20px;
    padding: 14px 18px;
    background: #fdecec;
    border: 1px solid #f3b9b9;
    border-radius: 10px;
    color: #9c2b2b;
}

.puzzle-create-errors ul {
    margin: 0;
    padding-left: 18px;
}

/* Ошибка отправки формы через fetch внутри VK (создание пазла/жалоба, см. vk-nav.js) — тот же
   визуальный язык, что и .puzzle-create-errors выше, но как отдельный класс, т.к. вставляется
   JS'ом в разные формы (в т.ч. в попап жалобы, где своего блока под ошибку нет). */
.puzzlum-form-error {
    margin-bottom: 16px;
    padding: 12px 16px;
    background: #fdecec;
    border: 1px solid #f3b9b9;
    border-radius: 10px;
    color: #9c2b2b;
    font-size: 14px;
}

/* Не удалось загрузить страницу при SPA-переходе внутри VK (см. vk-nav.js) — сеть подвела, но мы
   осознанно не откатываемся на настоящую перезагрузку (см. её же комментарий), поэтому нужна
   заметная кнопка "Повторить" прямо в области контента. */
.puzzlum-nav-error {
    margin-bottom: 20px;
    padding: 16px 18px;
    background: #fff4e5;
    border: 1px solid #ffd699;
    border-radius: 10px;
    color: #7a4a00;
}

.puzzlum-nav-error p {
    margin: 0 0 10px;
}

.puzzlum-nav-retry-btn {
    padding: 8px 16px;
    border: none;
    border-radius: 8px;
    background: #ffa94d;
    color: #fff;
    font-weight: 600;
    cursor: pointer;
}

.puzzle-create-columns {
    display: grid;
    grid-template-columns: minmax(260px, 380px) 1fr;
    gap: 32px;
    align-items: start;
}

@media (max-width: 720px) {
    .puzzle-create-columns {
        grid-template-columns: 1fr;
    }
}

.puzzle-create-dropzone {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1 / 1;
    border: 2px dashed #c7cdd8;
    border-radius: 16px;
    background: #f7f8fb;
    cursor: pointer;
    overflow: hidden;
    transition: border-color 0.2s ease, background 0.2s ease;
}

.puzzle-create-dropzone.is-dragover {
    border-color: #4dabf7;
    background: #eaf4ff;
}

/* Видео (в отличие от картинки) не показывается прямо в этой зоне после выбора файла — плеер с
   ним отдельным блоком ниже (см. .puzzle-create-video-player), сама зона после выбора остаётся
   просто пустым прямоугольником-кнопкой "выбрать другой файл". Вдвое ниже картиночной, чтобы не
   занимать зря место, которое всё равно не используется под превью. */
.puzzle-create-dropzone--video {
    aspect-ratio: 2 / 1;
}

.puzzle-create-dropzone-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 24px;
    color: #6b7280;
    text-align: center;
}

/* [hidden] в браузере — просто display:none, но у .puzzle-create-dropzone-empty своя более
   специфичная display:flex, которая иначе выигрывает — из-за этого при выбранной картинке текст
   оставался поверх неё. Явно возвращаем hidden его силу здесь же, по образцу .categories-modal[hidden]
   выше в этом файле. */
.puzzle-create-dropzone-empty[hidden] {
    display: none;
}

.puzzle-create-dropzone-empty svg {
    width: 40px;
    height: 40px;
    color: #9aa3b2;
}

.puzzle-create-dropzone-text {
    font-size: 14px;
    font-weight: 600;
    color: #4b5563;
}

.puzzle-create-hint {
    font-size: 12px;
    color: #9aa3b2;
}

.puzzle-create-preview-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.puzzle-create-dropzone-hint {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    text-align: center;
    background: rgba(20, 24, 32, 0.55);
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    opacity: 0;
    transition: opacity 0.2s ease;
    pointer-events: none;
}

.puzzle-create-dropzone:has(.puzzle-create-preview-img:not([hidden])):hover .puzzle-create-dropzone-hint {
    opacity: 1;
}

.puzzle-create-file-input {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    opacity: 0;
}

.puzzle-create-file-error {
    margin-top: 10px;
    font-size: 13px;
    color: #c0392b;
    font-weight: 600;
}

.puzzle-create-fields {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.puzzle-create-label {
    margin-top: 14px;
    font-size: 13px;
    font-weight: 700;
    color: #4b5563;
}

.puzzle-create-input {
    padding: 10px 14px;
    border: 1px solid #dde1e8;
    border-radius: 10px;
    font: inherit;
    font-size: 14px;
    background: #fff;
    color: #1b1b18;
}

.puzzle-create-input:focus {
    outline: none;
    border-color: #4dabf7;
}

.puzzle-create-toggle {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 16px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
}

.puzzle-create-toggle input {
    width: 18px;
    height: 18px;
    accent-color: #4dabf7;
    cursor: pointer;
}

.puzzle-create-note {
    margin: 8px 0 0;
    padding: 12px 14px;
    background: #f3f5f9;
    border-radius: 10px;
    font-size: 13px;
    line-height: 1.5;
    color: #6b7280;
}

.puzzle-create-note--warning {
    background: #fdf3e0;
    color: #92660a;
    font-weight: 600;
}

.puzzle-create-note--success {
    background: #e3f6ea;
    color: #1f7a45;
    font-weight: 600;
}

.puzzle-create-cooldown-timer,
.puzzle-create-unlimited-timer {
    font-variant-numeric: tabular-nums;
    font-weight: 800;
}

/* Баннер холда/безлимита стоит между табами и формой (не внутри общего потока полей, где верхний
   отступ .puzzle-create-note уже отделяет его от label/select над ним) — снизу нужен свой отступ,
   иначе он вплотную упирается в зону загрузки файла (или в кнопки покупки — см. ниже). */
#puzzle-create-cooldown,
#puzzle-create-unlimited {
    margin-bottom: 20px;
}

/* Кнопки покупки безлимита — видны только пока действует холд (см.
   PuzzleCreateController::create()), поэтому сидят сразу под его баннером. */
.puzzle-create-unlimited-offers {
    display: flex;
    gap: 10px;
    margin: -8px 0 20px;
}

.puzzle-create-unlimited-btn {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 10px 14px;
    border-radius: 999px;
    border: none;
    cursor: pointer;
    font: inherit;
}

.puzzle-create-unlimited-btn--outline {
    background: #fff;
    border: 1.5px solid #d8dce3;
    color: #1f2937;
}

.puzzle-create-unlimited-btn--outline:hover {
    border-color: #b7bec9;
}

.puzzle-create-unlimited-btn--accent {
    background: linear-gradient(135deg, #ff6b6b, #ffa94d 45%, #4dabf7 75%, #9775fa);
    color: #fff;
}

.puzzle-create-unlimited-btn--accent:hover {
    filter: brightness(1.05);
}

.puzzle-create-unlimited-btn-title {
    font-size: 13px;
    font-weight: 600;
}

.puzzle-create-unlimited-btn-price {
    font-size: 12px;
    opacity: 0.8;
}

/* Информационные подсказки "после создания — холд N часов" над зонами загрузки — тоже первый
   элемент в своём блоке (см. .puzzle-create-note margin-top:8px без нижнего отступа), нужен свой
   отступ снизу, чтобы не упираться в дропзону. */
#puzzle-create-info-image,
#puzzle-create-info-video {
    margin: 0 0 12px;
}

.puzzle-create-tabs {
    display: flex;
    gap: 8px;
    margin-bottom: 20px;
}

.puzzle-create-tab {
    padding: 8px 20px;
    border: 1px solid #dde1e8;
    border-radius: 999px;
    background: #fff;
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    color: #6b7280;
    cursor: pointer;
}

.puzzle-create-tab.is-active {
    background: #1b1b18;
    border-color: #1b1b18;
    color: #fff;
}

.puzzle-create-video-player {
    margin-top: 12px;
}

.puzzle-create-video-player video {
    display: block;
    width: 100%;
    max-height: 360px;
    border-radius: 12px;
    background: #000;
}

.puzzle-create-grab-frame-btn {
    display: block;
    width: 100%;
    margin-top: 10px;
    padding: 10px;
    border: none;
    border-radius: 10px;
    background: #4dabf7;
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
}

.puzzle-create-grab-frame-btn:hover {
    background: #339af0;
}

.puzzle-create-preview-label {
    margin-top: 24px;
}

.puzzle-create-crop-hint {
    margin: 4px 0 0;
    font-size: 12px;
    color: #9aa3b2;
    max-width: 340px;
}

.puzzle-create-preview-card {
    max-width: 340px;
    cursor: default;
    pointer-events: none;
}

.puzzle-create-preview-thumb-empty {
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, #eef1f6, #e4e8ef);
}

/* Кадрирование превью-карточки: единственная интерактивная часть иначе некликабельной
   .puzzle-create-preview-card (см. pointer-events:none выше) — включаем события обратно только
   здесь, дальше сама картинка позиционируется/масштабируется вручную из create.js (не через
   object-fit), поэтому overflow общего .puzzle-card-thumb (см. выше) обрезает лишнее. */
.puzzle-create-preview-thumb-wrap {
    pointer-events: auto;
    cursor: grab;
    touch-action: none;
    user-select: none;
}

.puzzle-create-preview-thumb-wrap.is-dragging {
    cursor: grabbing;
}

.puzzle-create-preview-thumb-wrap img {
    position: absolute;
    top: 0;
    left: 0;
    max-width: none;
    max-height: none;
    width: auto;
    height: auto;
    -webkit-user-drag: none;
}

.puzzle-create-preview-img {
    -webkit-user-drag: none;
}

.puzzle-create-submit {
    align-self: flex-start;
    margin-top: 24px;
    padding: 12px 28px;
    border: none;
    border-radius: 10px;
    background: #1b1b18;
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
}

.puzzle-create-submit:hover {
    background: #333330;
}

.puzzle-create-submit:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.puzzle-detail {
    max-width: 720px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.puzzle-detail-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.puzzle-detail-links-sep {
    color: #c6cbd4;
}

.puzzle-detail-back {
    color: #4b5563;
    text-decoration: none;
    font-size: 14px;
    font-weight: 600;
}

.puzzle-detail-back:hover {
    color: #1b1b18;
}

.puzzle-detail-thumb {
    position: relative;
    display: flex;
    justify-content: center;
    border-radius: 16px;
    overflow: hidden;
    background: #f0f2f6;
    box-shadow: 0 2px 8px rgba(20, 30, 50, 0.08);
}

/* Реальные пропорции, без обрезки: ширина не больше контейнера, высота — по пропорциям картинки/
   видео. Узкие картинки не тянутся на всю ширину (width: auto вместо 100%) — просто центрируются
   благодаря justify-content выше. */
.puzzle-detail-thumb img,
.puzzle-detail-thumb video {
    display: block;
    max-width: 100%;
    width: auto;
    height: auto;
}

.puzzle-detail-video-status {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 12px 16px;
    background: rgba(20, 24, 32, 0.75);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    text-align: center;
}

.puzzle-detail-video-status--error {
    background: rgba(192, 57, 43, 0.85);
}

.puzzle-detail-info {
    display: flex;
    align-items: center;
    gap: 16px;
}

.puzzle-detail-creator {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 2px;
}

.puzzle-detail-creator-label {
    font-size: 13px;
    color: #9aa3b2;
}

/* Видна только авторизованному администратору сайта (guard tetrum_admin, см. docs/ADMIN.md) —
   та же операция мягкого удаления, что и в __admin (см. PuzzleManageController::destroy()), но
   доступная прямо со страницы любого пазла. */
.puzzle-detail-admin-delete-form {
    margin-top: 10px;
}

.puzzle-detail-admin-delete-btn {
    padding: 7px 14px;
    border: none;
    border-radius: 8px;
    background: #c0392b;
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
}

.puzzle-detail-admin-delete-btn:hover {
    background: #a5301f;
}

.puzzle-detail-creator-sep {
    color: #c7cdd8;
}

/* Кнопка "Пожаловаться" (см. show.blade.php, PuzzleReportController) — намеренно маленькая и
   тихая, простой текст в одну строку с автором, а не заметная кнопка с фоном: раньше стояла
   отдельным блоком в flex-колонке .puzzle-detail (align-items: stretch по умолчанию) и
   растягивалась на всю ширину, выглядя как призыв нажать; вдобавок цвет при наведении (#e4e8ef)
   совпадал с фоном .app-main, из-за чего кнопка визуально пропадала. */
.puzzle-detail-report-btn {
    padding: 0;
    border: none;
    background: none;
    color: #9aa3b2;
    font-size: 13px;
    cursor: pointer;
}

.puzzle-detail-report-btn:hover {
    color: #c0392b;
}

/* Кнопка "Поделиться" (только внутри VK/OK — см. show-content.blade.php) — в отличие от
   "Пожаловаться" выше, это призывное действие, а не тихая служебная ссылка, поэтому со своим
   фоном и заметнее. margin-left: auto прижимает её к правому краю строки .puzzle-detail-info
   (title/рейтинг/сборки), не мешая им расти естественно. */
.puzzle-detail-share-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
    flex-shrink: 0;
    padding: 7px 14px;
    border: none;
    border-radius: 999px;
    background: #f3f5f9;
    color: #495468;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}

.puzzle-detail-share-btn:hover {
    background: #e9ecf2;
}

.puzzle-detail-share-btn svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.report-modal {
    position: fixed;
    inset: 0;
    z-index: 260;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(10, 12, 16, 0.5);
}

.report-modal[hidden] {
    display: none;
}

.report-modal-box {
    position: relative;
    width: 100%;
    max-width: 420px;
    padding: 28px 24px 24px;
    background: #fff;
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}

.report-modal-title {
    margin: 0 0 16px;
    padding-right: 30px;
    font-size: 18px;
    font-weight: 800;
}

.report-modal-close {
    position: absolute;
    top: 10px;
    right: 10px;
}

.report-reasons {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 14px;
}

.report-reason-option {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    color: #1b1b18;
    cursor: pointer;
}

.report-comment-label {
    display: block;
    font-size: 13px;
    font-weight: 700;
    color: #706f6c;
    margin-bottom: 6px;
}

.report-comment-input {
    display: block;
    width: 100%;
    padding: 10px 12px;
    margin-bottom: 16px;
    font-size: 14px;
    font-family: inherit;
    border: 1px solid #d8dce3;
    border-radius: 8px;
    resize: vertical;
}

.report-submit-btn {
    width: 100%;
    padding: 11px;
    border: none;
    border-radius: 8px;
    background: #c0392b;
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
}

.report-submit-btn:hover {
    background: #a5301f;
}

.puzzle-detail-title {
    margin: 0;
    font-size: 24px;
    font-weight: 800;
    flex: 1;
}

.puzzle-difficulty-label {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #97a0ad;
    margin-bottom: 10px;
}

.puzzle-difficulty-options {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
}

.puzzle-difficulty-option {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    font-family: inherit;
    background: #fff;
    border: 2px solid #e3e6ec;
    border-radius: 12px;
    padding: 12px 22px;
    cursor: pointer;
    transition: border-color 0.15s ease, transform 0.15s ease;
}

.puzzle-difficulty-option:hover {
    border-color: #9775fa;
    transform: translateY(-2px);
}

.puzzle-difficulty-name {
    font-size: 16px;
    font-weight: 700;
    color: #1b1b18;
}

.puzzle-difficulty-meta {
    font-size: 13px;
    color: #97a0ad;
}

.puzzle-difficulty-continue {
    font-size: 12px;
    font-weight: 700;
    color: #4dabf7;
}

.puzzle-difficulty-continue[hidden] {
    display: none;
}

.puzzle-article {
    background: #fff;
    border-radius: 16px;
    padding: 20px 24px;
    box-shadow: 0 2px 8px rgba(20, 30, 50, 0.08);
}

.puzzle-article-title {
    margin: 0 0 12px;
    font-size: 18px;
    font-weight: 800;
    color: #1b1b18;
}

.puzzle-article-body {
    font-size: 15px;
    line-height: 1.6;
    color: #1b1b18;
}

.puzzle-article-body p {
    margin: 0 0 12px;
}

.puzzle-article-body p:last-child {
    margin-bottom: 0;
}

.puzzle-article-body a {
    color: #4dabf7;
    text-decoration: underline;
}

.puzzle-article-body a:hover {
    color: #1c7ed6;
}

.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    flex-shrink: 0;
    border: none;
    background: #f3f5f9;
    border-radius: 8px;
    cursor: pointer;
    color: #1b1b18;
    padding: 0;
}

.icon-btn svg {
    width: 20px;
    height: 20px;
}

.icon-btn:hover {
    background: #e9ecf2;
}

.icon-btn:disabled {
    opacity: 0.35;
    cursor: not-allowed;
}

.icon-btn:disabled:hover {
    background: #f3f5f9;
}

.puzzle-game-overlay {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    flex-direction: column;
    background: #eef1f6;
    /* На мобильных браузерах (в первую очередь iOS Safari) непотреблённый остаток жеста
       перетаскивания детали на .canvas-stack (там нечего скроллить по горизонтали) поднимается
       выше по цепочке и превращается в системный "потяни — перейди назад/вперёд" — это не
       свайп именно от края экрана, а связка с упругой прокруткой (overscroll/rubber-banding),
       поэтому одного touch-action:none на канвасе недостаточно. overscroll-behavior гасит
       остаток жеста здесь, не давая ему уйти выше на уровень браузера. */
    overscroll-behavior: none;
}

.puzzle-game-overlay.puzzle-game-bg-dark {
    background: #14161b;
}

.puzzle-game-overlay[hidden] {
    display: none;
}

.puzzle-game-topbar {
    position: relative;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    background: #fff;
}

/* Адаптация шапки под узкие экраны — три ступени по приоритету, включаются по одной
   (см. updateTopbarLayout в show.js), когда всё содержимое перестаёт помещаться в одну строку:
   1) скрыть название пазла и число деталей, 2) убрать подпись у кнопки "Показать картинку/
   видео" (оставить только иконку), 3) перенести все кнопки, кроме полноэкранного режима и цвета
   фона, во вторую строку (см. .puzzle-game-topbar-row2 — реальный отдельный контейнер, в него JS
   физически переносит кнопки, а не просто визуально прячет). */
.puzzle-game-topbar--hide-heading .puzzle-game-heading {
    display: none;
}

.puzzle-game-topbar--icon-source .show-source-btn-label {
    display: none;
}

.puzzle-game-topbar--icon-source .show-source-btn {
    padding: 9px;
}

.puzzle-game-topbar-row2 {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 16px 12px;
    background: #fff;
}

.puzzle-game-topbar-row2[hidden] {
    display: none;
}

.show-source-btn {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    color: #1b1b18;
    background: #f3f5f9;
    border: none;
    border-radius: 999px;
    padding: 9px 18px;
    cursor: pointer;
    white-space: nowrap;
}

.show-source-btn svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}

.show-source-btn:hover {
    background: #e9ecf2;
}

.puzzle-game-topbar-left {
    display: flex;
    align-items: center;
    gap: 8px;
}

.puzzle-game-topbar-right {
    display: flex;
    align-items: center;
    gap: 16px;
}

.puzzle-game-heading {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
}

.puzzle-game-title {
    font-size: 16px;
    font-weight: 700;
}

.puzzle-game-piece-count {
    font-size: 13px;
    color: #97a0ad;
}

.puzzle-game-timer {
    font-size: 16px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum';
}

.puzzle-game-field {
    flex: 1;
    min-height: 0;
}

.canvas-stack {
    position: relative;
    width: 100%;
    height: 100%;
    touch-action: none;
    overscroll-behavior: none;
}

.canvas-stack canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}

#pieces-canvas-drag {
    pointer-events: none;
}

.puzzle-source-preview {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px;
    background: rgba(10, 12, 16, 0.88);
    cursor: zoom-out;
}

.puzzle-source-preview[hidden] {
    display: none;
}

.puzzle-source-preview-media {
    max-width: 100%;
    max-height: 100%;
    display: block;
    border-radius: 10px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
    cursor: default;
}

.puzzle-rating-modal {
    position: fixed;
    inset: 0;
    z-index: 250;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(10, 12, 16, 0.5);
    opacity: 1;
    transition: opacity 0.3s ease;
}

.puzzle-rating-modal[hidden] {
    display: none;
}

.puzzle-rating-modal--closing {
    opacity: 0;
}

.puzzle-rating-box {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    padding: 32px 40px;
    background: #fff;
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}

.puzzle-rating-close {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 30px;
    height: 30px;
}

.puzzle-rating-close svg {
    width: 16px;
    height: 16px;
}

.puzzle-rating-question {
    margin: 0;
    font-size: 17px;
    font-weight: 700;
    color: #1b1b18;
    text-align: center;
}

.puzzle-rating-stars {
    display: flex;
    gap: 6px;
}

.puzzle-rating-star {
    padding: 0;
    border: none;
    background: none;
    font-size: 36px;
    line-height: 1;
    color: #d8dce3;
    cursor: pointer;
}

.puzzle-rating-star.is-filled {
    color: #ffa94d;
}

/* Кнопка попапа "Рассказать друзьям" (см. #puzzle-tell-friends-modal, тот же
   .puzzle-rating-modal/.puzzle-rating-box, что и у попапа оценки, — своя только сама кнопка) —
   призывное действие, поэтому с фирменным градиентом сайта (см. .app-logo-icon в шапке), а не
   нейтральный серый фон, как у большинства второстепенных кнопок. */
.puzzle-tell-friends-btn {
    padding: 12px 28px;
    border: none;
    border-radius: 999px;
    background: linear-gradient(135deg, #ff6b6b, #ffa94d 45%, #4dabf7 75%, #9775fa);
    color: #fff;
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
}

.puzzle-tell-friends-btn:hover {
    filter: brightness(1.05);
}

/* Текст правил публикации (games.puzzlum.publication-rules) — общий для отдельной страницы и
   попапа на странице создания пазла, см. partials/publication-rules-content.blade.php. */
.rules-content h2 {
    margin: 24px 0 10px;
    font-size: 16px;
    font-weight: 800;
    color: #1b1b18;
}

.rules-content h2:first-of-type {
    margin-top: 0;
}

.rules-content p {
    margin: 0 0 12px;
    font-size: 14px;
    line-height: 1.6;
    color: #4b5563;
}

.rules-content ul {
    margin: 0 0 12px;
    padding-left: 20px;
}

.rules-content li {
    margin-bottom: 8px;
    font-size: 14px;
    line-height: 1.6;
    color: #4b5563;
}

.rules-content a {
    color: #4dabf7;
    text-decoration: underline;
}

.rules-content a:hover {
    color: #1c7ed6;
}

.rules-page {
    max-width: 720px;
    background: #fff;
    border-radius: 16px;
    padding: 24px 28px;
    box-shadow: 0 2px 8px rgba(20, 30, 50, 0.08);
}

.rules-page-title {
    margin: 0 0 16px;
    font-size: 22px;
    font-weight: 800;
}

.age-gate {
    max-width: 480px;
    margin: 40px auto 0;
    background: #fff;
    border-radius: 16px;
    padding: 32px 28px;
    text-align: center;
    box-shadow: 0 2px 8px rgba(20, 30, 50, 0.08);
}

.age-gate-title {
    margin: 0 0 12px;
    font-size: 22px;
    font-weight: 800;
}

.age-gate-text {
    margin: 0 0 24px;
    color: #706f6c;
    font-size: 14px;
    line-height: 1.5;
}

.age-gate-actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.age-gate-confirm-btn {
    width: 100%;
    padding: 12px;
    border: none;
    border-radius: 10px;
    background: #1b1b18;
    color: #fff;
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
}

.age-gate-confirm-btn:hover {
    background: #3a3a35;
}

.age-gate-decline-btn {
    display: block;
    padding: 12px;
    border-radius: 10px;
    background: #f0f2f6;
    color: #4b5563;
    font-size: 15px;
    font-weight: 700;
    text-decoration: none;
    text-align: center;
}

.age-gate-decline-btn:hover {
    background: #e4e8ef;
}

/* Страницы ошибок Пазлум (404/419/429/403/500) — см. games/puzzle/errors/show.blade.php,
   bootstrap/app.php. Значок — та же иконка-пазл, что и в шапке (.app-logo-icon), рядом с кодом
   ответа тем же градиентным текстом, что и название "Пазлум" в шапке (.app-logo-text) — единый
   визуальный язык, не отдельная тема оформления только для ошибок. */
.error-page {
    max-width: 480px;
    margin: 40px auto 0;
    background: #fff;
    border-radius: 16px;
    padding: 36px 28px;
    text-align: center;
    box-shadow: 0 2px 8px rgba(20, 30, 50, 0.08);
}

.error-header {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    margin-bottom: 20px;
}

.error-icon {
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.15));
}

.error-status {
    font-size: 48px;
    font-weight: 800;
    letter-spacing: -0.02em;
    background: linear-gradient(135deg, #ff6b6b, #ffa94d 45%, #4dabf7 75%, #9775fa);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.error-title {
    margin: 0 0 12px;
    font-size: 22px;
    font-weight: 800;
}

.error-text {
    margin: 0 0 24px;
    color: #706f6c;
    font-size: 14px;
    line-height: 1.5;
}

.error-links {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

.error-link {
    display: block;
    padding: 12px;
    border-radius: 10px;
    background: #f0f2f6;
    color: #1b1b18;
    font-size: 14px;
    font-weight: 700;
    text-decoration: none;
    text-align: center;
}

.error-link:hover {
    background: #e4e8ef;
}

.error-link--single {
    grid-column: 1 / -1;
}

/* Согласие с правилами на форме создания пазла — сама ссылка открывает попап ниже, а не уводит со
   страницы (не хотим терять уже введённые данные формы). */
.puzzle-create-agreement {
    margin: 12px 0;
    font-size: 13px;
    color: #706f6c;
}

.puzzle-create-rules-link {
    padding: 0;
    border: none;
    background: none;
    color: #4dabf7;
    font-size: 13px;
    text-decoration: underline;
    cursor: pointer;
}

.puzzle-create-rules-link:hover {
    color: #1c7ed6;
}

.rules-modal {
    position: fixed;
    inset: 0;
    z-index: 260;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(10, 12, 16, 0.5);
}

.rules-modal[hidden] {
    display: none;
}

.rules-modal-box {
    position: relative;
    width: 100%;
    max-width: 640px;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    padding: 28px 24px 24px;
    background: #fff;
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
    overflow: hidden;
}

.rules-modal-title {
    margin: 0 0 14px;
    padding-right: 30px;
    font-size: 18px;
    font-weight: 800;
}

.rules-modal-body {
    overflow-y: auto;
}

.rules-modal-close {
    position: absolute;
    top: 10px;
    right: 10px;
}
