/* Mobile-first responsive overrides for Bootstrap 2 layout */

/* =========================================================
   NAVBAR — long-email truncation (all viewports)
   When a user's displayName collides with a nav-link label
   (PM-D2 case — e.g. an admin whose displayName is literally
   "Admin"), main.html falls back to rendering the full email
   in the navbar. A long email (e.g. "very.long.address@
   provider.example") then pushes the Admin nav-link and
   logout off-screen on desktop, and on mobile blows the
   right .nav row past the viewport so the Admin tab is
   unreachable. Truncate with ellipsis; the full email is
   still in the anchor's title= attribute on hover.

   Admin user-listing table cells also carry .user-email,
   but the truncation rule below is scoped to .navbar so the
   admin /admin/users page is untouched.
   ========================================================= */
.navbar .user-email {
    display: inline-block;
    max-width: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

/* On phones the navbar wraps to 3 stacked rows; the email
   gets its own line and 220 px is fine — but tighten to
   180 px for safety on the narrowest devices. */
@media (max-width: 480px) {
    .navbar .user-email {
        max-width: 180px;
    }
}

/* Admin sub-tabs (Stats/Nodes/Users/Plans/Jobs) must keep
   wrapping if the row gets squeezed by a long page header
   or anything else — never overflow off-screen. */
.nav-tabs {
    flex-wrap: wrap;
}

/* =========================================================
   NAVBAR
   ========================================================= */
@media (max-width: 767px) {
    /* Fixed navbar wraps to 3 stacked rows on phones (brand, left .nav,
       right .nav.pull-right) which adds up to ~130 CSS px tall. The
       hardcoded `<body style="padding-top:50px">` in main.html does NOT
       account for that — the CTA banner ("Need more space? Try a new plan")
       and the page heading sit underneath the fixed navbar and cannot be
       tapped: the user scrolls, content slides under the navbar, navbar
       intercepts the touch. !important overrides the inline body style. */
    body {
        padding-top: 140px !important;
    }

    /* робимо контейнер гумовим, щоб не було горизонтального скролу */
    .container {
        width: 100% !important;
        max-width: 100% !important;
        padding-left: 10px;
        padding-right: 10px;
        box-sizing: border-box;
    }

    #logo img {
        max-width: 100%;
        height: auto;
    }

    .navbar-fixed-top .navbar-inner {
        padding: 0 10px;
    }

    /* Stack nav links vertically on small screens */
    .navbar .nav,
    .navbar .nav.pull-right {
        float: none !important;
        display: block;
    }

    .navbar .nav > li {
        display: inline-block;
    }

    #avatar {
        height: 28px !important;
        margin-top: -4px !important;
    }
}

/* =========================================================
   MAIN CLIENT LAYOUT: sidebar + torrent list
   ========================================================= */

/* Tablet + desktop (>=768px): hide the mobile group picker so only the
   `<ul id="torrent-groups">` sidebar shows. This project does NOT ship
   bootstrap-responsive.css, so `.hidden-desktop` on the picker is a
   no-op — this media rule is the only thing keeping it off non-phone
   viewports. */
@media (min-width: 768px) {
    .mobile-group-picker { display: none; }
}

@media (max-width: 767px) {
    /* PMUX-B1: BS2 .row uses margin-left:-20px to balance the +20px margin
       on .span*. With the reset below, .span* margins are 0, so .row's -20
       leaks 10px past the .container's 10px padding-left and pushes every
       descendant 10px off the viewport's left edge — surfaces as
       #quick-add-url-input rendering at left=-10 on a 390px viewport. */
    .row {
        margin-left: 0 !important;
    }

    /* Bootstrap 2 span* don't stack — force it */
    .row .span2,
    .row .span10,
    .row .span10.offset2 {
        float: none !important;
        width: 100% !important;
        margin-left: 0 !important;
    }

    /* Hide the desktop sidebar list on phones — `.mobile-group-picker`
       (rendered by tags/groups-sidebar.html ahead of the <ul>) takes
       over both group navigation (via <select onchange>) and group
       creation (via the +button data-toggle to #add-group-dialog).
       Earlier revisions tried to repurpose `#torrent-groups` as a
       horizontal scroll strip — dead code since the <ul> is hidden
       anyway. */
    #torrent-groups {
        display: none !important;
    }

    /* Mobile group picker: <select> + 44x44 "+" button. 44px = WCAG
       2.5.5 tap target. Font-size 16px on the select prevents iOS
       Safari auto-zoom on focus. */
    .mobile-group-picker {
        display: flex;
        align-items: stretch;
        gap: 6px;
        margin: 0 0 10px 0;
    }
    .mobile-group-picker #torrent-groups-mobile {
        flex: 1 1 auto;
        min-width: 0;
        height: 44px;
        font-size: 16px;
        margin: 0;
    }
    .mobile-group-picker #add-group-mobile {
        flex: 0 0 44px;
        width: 44px;
        height: 44px;
        padding: 0;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-size: 18px;
        line-height: 1;
    }
    .mobile-group-picker #add-group-mobile [class^="icon-"] {
        margin: 0;
    }

    /* список загрузок не вылезает за экран по ширине */
    #torrent-list table {
        width: 100% !important;
        table-layout: fixed;
    }

    #torrent-list th,
    #torrent-list td {
        word-wrap: break-word;
        white-space: normal;
    }

    /* Torrent row inner layout: title + progress bar on the left,
       action buttons on the right. We KEEP the single-line flex layout
       on phones too — three btn-mini icons (~100 CSS px total) fit next
       to the title even on a 390 px viewport once the title is allowed
       to wrap. Allow title text to wrap so it doesn't overflow and push
       the action block off-screen. */
    .torrent-row-layout .torrent-title {
        white-space: normal;
        word-break: break-word;
        font-size: 13px;
        line-height: 1.4;
    }

    /* Tighten row padding on phones (rule kept from the previous layout). */
    .torrent-row td {
        padding: 4px 6px !important;
    }

    /* більш виразне підсвічування при наведенні/виділенні */
    .torrent-row:hover td {
        background-color: #d0ebff !important;
        box-shadow: inset 0 0 0 1px #2d6cdf;
    }

    .torrent-row.info td {
        background-color: #bcdfff !important;
        box-shadow: inset 0 0 0 1px #1a55c4;
    }

    /* ── Хедер: Switch User форма під назвою групи ── */
    .row .span10.offset2 {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 6px;
    }

    .row .span10.offset2 h3 {
        flex: 1 1 100%;
        margin: 0 0 4px 0;
        font-size: 18px;
    }

    .row .span10.offset2 .form-inline {
        float: none !important;
        display: flex;
        gap: 6px;
        align-items: center;
    }

    .row .span10.offset2 select {
        font-size: 13px;
        padding: 2px 4px;
    }

    /* ── Статистика внизу: переносимо текст ── */
    #torrent-list .torrent-stats {
        font-size: 11px;
        display: block;
        white-space: normal;
        word-break: break-all;
    }

    /* pull-left/pull-right в статистиці — в стовпчик */
    #torrent-list .pull-left,
    #torrent-list .pull-right {
        float: none !important;
        display: block;
    }
}

/* =========================================================
   TORRENT LIST
   ========================================================= */
@media (max-width: 767px) {
    /* "With Selected" and "Add Torrent" buttons */
    .btn-group.pull-left,
    .btn-group.pull-right {
        float: none !important;
        display: inline-block;
        margin-bottom: 6px;
    }

    /* Torrent name — allow wrapping, no hard truncation */
    .torrent-title {
        white-space: normal !important;
        word-break: break-word;
    }

    /* Speed info — always visible on mobile (no hover) */
    .torrent-progress.hide,
    .torrent-speed.hide {
        display: block !important;
    }

    /* Action buttons column: don't shrink below minimum (keep buttons
       on one line, never wrap individual icons). */
    .torrent-row-layout .torrent-row-actions {
        white-space: nowrap;
    }
}

/* =========================================================
   HLS PLAYER MODAL — QuickTime-style chrome (UX spec 2026-05-13)
   Replaces the cramped Bootstrap-2 default (full-width header
   with <h3>, body that floated the iframe in a 5/10/10 padding
   rectangle) with a dark frame that is ~70% of the viewport,
   centered, and topped with a compact 36px title strip + close
   button. Markup contract: #hls-player-modal carries the new
   .gt-player-modal class; title bar is .gt-player-chrome with
   .gt-player-title (containing static "Now Playing" + dynamic
   .hls-title span) and .gt-player-close. The .modal-body keeps
   its class so existing body.hls-audio-menu-open rules below
   continue to select it.

   Source-order note: the new mobile .gt-player-modal rules at
   the bottom of this block MUST stay above the existing
   @media (max-width: 767px) block that defines the
   body.hls-audio-menu-open overrides — those !important rules
   need to win when the iframe-hosted audio menu is open.
   ========================================================= */
.gt-player-modal {
    background: #000 !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: 0 10px 40px rgba(0,0,0,0.5) !important;
    width: min(70vw, 1280px) !important;
    margin-left: 0 !important;
    left: 50% !important;
    transform: translateX(-50%) !important;
    top: 6vh !important;
    padding: 0;
    outline: none;
}
.gt-player-modal.fade.in {
    top: 6vh !important;
}
.gt-player-chrome {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 36px;
    padding: 0 8px 0 12px;
    background: #1a1a1a;
    color: #e8e8e8;
    font: 500 12px/36px -apple-system, "Segoe UI", Roboto, sans-serif;
}
.gt-player-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    min-width: 0;
}
.gt-player-close {
    background: transparent;
    border: 0;
    color: #aaa;
    font: 300 22px/1 sans-serif;
    width: 44px;
    height: 36px;
    padding: 0;
    opacity: 1;
    text-shadow: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}
.gt-player-close:hover, .gt-player-close:focus {
    color: #fff;
    outline: none;
}
/* Mobile: bigger touch target + bigger glyph. User reported the × is
   hard to hit on a 390 px iPhone — WCAG 2.5.5 minimum is 44×44 but
   on a video-modal title bar that's at the very top edge of the
   screen (status-bar adjacent), 48×48 with a 28 px glyph feels much
   more deliberate. Bump the title bar height to match. */
@media (max-width: 767px) {
    .gt-player-modal .gt-player-chrome {
        height: 48px !important;
    }
    .gt-player-modal .gt-player-title {
        line-height: 48px !important;
        font-size: 13px !important;
    }
    .gt-player-modal .gt-player-close {
        width: 48px !important;
        height: 48px !important;
        font-size: 28px !important;
        font-weight: 400 !important;
    }
}
.gt-player-body {
    padding: 0 !important;
    max-height: none !important;
    overflow: hidden;
    background: #000;
}
.gt-player-modal #hls-player-frame {
    display: block;
    width: 100%;
    aspect-ratio: 16/9;
    height: auto;
    min-height: 0;
    border: 0;
}

/* Audio-only mode: the iframe (/client/play) collapses its <video> tile
   to zero and reports the audio-only state to the parent via
   postMessage{type:'gtPlayer.audioOnly'}. The parent flips
   `body.hls-audio-only`, and these rules collapse the iframe to a strip
   so the modal chrome (title bar + control bar inside the iframe) reads
   like a compact audio player rather than a tall black box.

   Desktop: 240 px ceiling — accommodates the P0-2 audiobook card (3 rows:
   parsed chapter title + transport controls + "Up next" tile). Bumped from
   120 px on 2026-05-26; the prior cap clipped everything below the
   transport row, which is why the audit screenshots showed a bare strip
   with no chapter title, no track-count signal, and no path to the next
   chapter. The card itself self-caps at ~240 px inside the iframe (see
   .is-audio-only #audiobook-card height rules in play.html), so an
   overshoot tag still lands clean. Mobile rule below stays at 204 px —
   tighter envelope inside the 240 px modal cap. */
body.hls-audio-only .gt-player-modal #hls-player-frame {
    aspect-ratio: auto !important;
    /* Iframes don't auto-resize to fit content — the previous `height: auto;
       max-height: 240px` left the frame at the <video> tag's intrinsic height
       (~150px on desktop Chrome), clipping the audiobook card's row 1
       (poster + title) off the bottom. Set a fixed height so the card always
       fits inside the visible iframe rectangle. The card itself self-caps at
       ~240 px (see .is-audio-only #audiobook-card max-height in play.html). */
    height: 240px !important;
    min-height: 240px !important;
    max-height: 240px !important;
}
/* Lighter backdrop matches the reference; page chrome shows through. */
.modal-backdrop, .modal-backdrop.in { opacity: 0.55 !important; }

/* =========================================================
   HLS PLAYER MODAL — touch-device fullscreen.

   Applies on every page that renders #hls-player-modal (/client and
   /client/torrent/<hash>). Without this block the detail page collapses
   the modal to iframe-natural-height (~360x238 on a phone) because the
   inline rule that used to define mobile-fullscreen was page-scoped.

   Critical:
     - 100dvh (dynamic viewport) + env(safe-area-inset-bottom). Static
       100vh does NOT shrink when Safari shows its bottom toolbar, so
       the video.js control bar ends up hidden behind it.
     - !important on the positioning declarations because the generic
       `.modal { top: 5%; left: 2%; right: 2%; ... }` rule in the 767px
       modal block below carries !important and would otherwise win on
       specificity ties.

   Breakpoint 1024px (not 767px) covers iPad portrait + phones;
   landscape iPad keeps the centered-modal layout.
   ========================================================= */
@media (max-width: 1024px) {
    #hls-player-modal {
        width: 100% !important;
        margin: 0 !important;
        left: 0 !important;
        right: 0 !important;
        top: 0 !important;
        bottom: 0 !important;
        height: 100dvh !important;
        max-height: 100dvh !important;
        border-radius: 0;
        border: 0;
        box-shadow: none;
        padding-bottom: env(safe-area-inset-bottom);
        transform: none !important;
    }
    #hls-player-modal .modal-header {
        padding: 8px 12px;
    }
    #hls-player-modal .modal-header h3 {
        font-size: 14px;
        line-height: 1.2;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    #hls-player-modal .modal-body {
        max-height: calc(100dvh - 46px - env(safe-area-inset-bottom)) !important;
    }
    #hls-player-frame {
        height: calc(100dvh - 46px - env(safe-area-inset-bottom)) !important;
        max-height: calc(100dvh - 46px - env(safe-area-inset-bottom)) !important;
    }
}

/* =========================================================
   MODALS — fix fixed px widths
   ========================================================= */
@media (max-width: 767px) {
    .modal {
        position: fixed !important;
        top: 5% !important;
        left: 2% !important;
        right: 2% !important;
        width: auto !important;
        margin: 0 !important;
        max-height: 90vh;
        overflow-y: auto;
    }

    /* Override inline styles on specific modals */
    #torrent-info-modal,
    #torrent-download-modal {
        width: auto !important;
        margin-left: 0 !important;
    }

    /* (#hls-player-modal sizing for VIDEO lives in the 1024px
       fullscreen block above — do NOT re-declare width / height /
       .modal-body max-height / #hls-player-frame height here for the
       video case, or the modal collapses to iframe-natural-height
       instead of going fullscreen.) */

    /* =========================================================
       Audio-only on phones — bottom-pinned "now-playing bar"
       (UX spec 2026-05-25, P0 fix).

       Why the modal container — not just the iframe — must be
       re-sized: the 1024px fullscreen block above forces
       #hls-player-modal to height/max-height 100dvh, top:0,
       bottom:0. Capping just #hls-player-frame to 120px left the
       iframe at the TOP of an otherwise-empty 100dvh black void —
       which is exactly the "giant black box, no controls visible"
       symptom from the audit screenshot.

       The fix collapses BOTH the modal container and the iframe to
       a fixed 240 px strip pinned to the bottom of the viewport,
       leaving the file-list page visible above it. Mental model:
       Spotify / podcast bottom-bar mini-player.

       Source-order note: these selectors are MORE specific than
       the 1024px block's bare `#hls-player-modal { ... }` (we add
       `body.hls-audio-only` on top), so they win cleanly on
       specificity — !important is retained on positioning props
       only as defence-in-depth against the legacy `.modal`
       inline-style sweeps Bootstrap-2 still emits.
       ========================================================= */
    body.hls-audio-only .gt-player-modal#hls-player-modal {
        height: auto !important;
        max-height: 240px !important;
        top: auto !important;
        bottom: 0 !important;
        left: 0 !important;
        right: 0 !important;
        width: 100vw !important;
        margin: 0 !important;
        border-radius: 12px 12px 0 0 !important;
        padding-bottom: env(safe-area-inset-bottom) !important;
        transform: none !important;
    }
    body.hls-audio-only .gt-player-modal#hls-player-modal .modal-body {
        max-height: 204px !important;
    }
    /* Specificity note: the desktop rule at line 378 already targets
       `body.hls-audio-only .gt-player-modal #hls-player-frame`, so a
       bare `body.hls-audio-only #hls-player-frame` here loses on
       specificity and the iframe ends up at the desktop's 120px cap
       instead of our 204px mobile target. Mirror the desktop rule's
       selector pattern (with `.gt-player-modal` in the middle) to
       tie specificity, and since we're inside an @media block more
       specific than the desktop rule's home (no media wrapper there),
       source-order resolves the tie in our favour. */
    body.hls-audio-only .gt-player-modal #hls-player-frame {
        height: 204px !important;
        max-height: 204px !important;
        min-height: 0 !important;
        aspect-ratio: auto !important;
    }
    /* Drop the backdrop dim on mobile audio-only: the file list
       above the bottom-bar should remain readable AND tappable —
       a user can pick a different chapter without first closing
       the player. The close (×) inside .gt-player-chrome stays as
       the explicit dismiss affordance. */
    body.hls-audio-only .modal-backdrop,
    body.hls-audio-only .modal-backdrop.in {
        display: none !important;
    }

    /* URL/Magnet textarea */
    .modal textarea {
        width: 100% !important;
        box-sizing: border-box;
    }
}

/* =========================================================
   ACCOUNT PAGES (mobile)
   /account/* used to keep the desktop span3 + span9 grid on
   phones, so the sidebar sat next to the content cell and
   everything overflowed by ~340 px on a 390-wide viewport.
   ========================================================= */
@media (max-width: 767px) {
    /* Stack the /account row exactly like /client already does. */
    .row .span3,
    .row .span9 {
        float: none !important;
        width: 100% !important;
        margin-left: 0 !important;
    }

    /* Compact account sidebar: kill the 50px top margin, render the
       tabs as a single horizontal row so they don't eat the first
       fold; each tab is iOS-HIG-min 44 px tall, chevron arrow is
       dead weight on phone — drop it. Items share width equally
       and the longest label wraps instead of overflowing. */
    .nav-tabs.nav-stacked {
        margin-top: 10px !important;
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;
        gap: 4px;
    }
    .nav-tabs.nav-stacked > li {
        flex: 1 1 0;
        min-width: 0;
    }
    .nav-tabs.nav-stacked > li > a {
        min-height: 44px;
        display: flex;
        align-items: center;
        justify-content: center;
        text-align: center;
        padding: 8px 6px;
        font-size: 12px;
        line-height: 1.2;
        white-space: normal;
        overflow-wrap: anywhere;
    }
    .nav-tabs.nav-stacked .icon-chevron-right {
        display: none;
    }

    /* iOS Safari auto-zooms when a focused input is below 16 px font.
       Force 16 px on every text-ish input so the page doesn't pan
       under the navbar on focus. */
    input[type="text"],
    input[type="email"],
    input[type="password"],
    input:not([type]),
    select,
    textarea {
        font-size: 16px !important;
    }

    /* Plan cards and form-horizontal layouts must respect the
       viewport width once the grid is stacked. */
    .plan-card,
    .form-horizontal .controls,
    .form-horizontal .control-group {
        max-width: 100%;
        box-sizing: border-box;
    }
}

/* =========================================================
   AUTH PAGES
   ========================================================= */
@media (max-width: 480px) {
    .auth-container,
    .password-form {
        padding: 10px;
    }

    .auth-section {
        padding: 14px;
    }

    .auth-container .btn,
    .password-form .btn {
        display: block;
        width: 100%;
        margin-left: 0 !important;
        margin-bottom: 8px;
        text-align: center;
        box-sizing: border-box;
    }
}

/* =========================================================
   ACCOUNT SECTION
   ========================================================= */
@media (max-width: 767px) {
    /* Sidebar nav in account section */
    .account-nav,
    .nav-pills.nav-stacked {
        display: flex !important;
        flex-direction: row !important;
        flex-wrap: wrap !important;
        gap: 4px;
        margin-bottom: 16px !important;
    }

    .account-nav li,
    .nav-pills.nav-stacked li {
        flex: 1 1 auto;
        text-align: center;
    }
}

/* =========================================================
   ONBOARDING PAGE
   ========================================================= */
@media (max-width: 480px) {
    .onboarding {
        padding: 0 10px;
    }

    .step {
        flex-direction: column;
        gap: 10px;
    }

    .onboarding-cta .btn-start {
        display: block;
        width: 100%;
        box-sizing: border-box;
    }
}

/* =========================================================
   ERROR PAGES
   ========================================================= */
@media (max-width: 480px) {
    .error-code {
        font-size: 80px !important;
    }

    .error-title {
        font-size: 22px !important;
    }

    .error-actions a {
        display: block;
        margin: 0 0 8px 0 !important;
    }
}

/* =========================================================
   QUICK-ADD URL INPUT (PMUX-Q1, PMUX-B1)
   - PMUX-Q1: font-size must be >= 16px on mobile to suppress
     iOS Safari focus-zoom.
   - PMUX-B1: input was rendered with bounding-rect.left ≈ -40px
     on a 390px viewport because the wrapper kept its desktop
     `float:right` + inline `width:240px`, and Bootstrap 2's
     `.input-append` puts the input next to a button so the
     input itself can never reach `viewportW - 32`. On phones
     we stack: input on its own row at full width, the `+`
     button drops onto the next line.
   ========================================================= */
@media (max-width: 767px) {
    /* The toolbar wrapper is inline-styled
       `<div style="float:right; display:flex; gap:8px;">`
       in app/views/client/index.html — neutralise the float and
       stretch full-width with column wrap so children stack. */
    .span10 > div[style*="float:right"] {
        float: none !important;
        display: flex !important;
        flex-direction: column !important;
        width: 100% !important;
        gap: 8px;
        align-items: stretch;
        margin-top: 6px;
    }

    /* Form fills the wrapper width. */
    #quick-add-url-form {
        float: none !important;
        width: 100% !important;
        margin: 0 !important;
        box-sizing: border-box;
    }

    /* Bootstrap 2's `.input-append` is inline-block by default and
       puts input + button on one line. Switch to wrapping flex so
       the input takes the whole row (PMUX-B1 needs `width >=
       viewportW - 32`) and the `+` button drops onto the next line. */
    #quick-add-url-form .input-append {
        display: flex !important;
        flex-wrap: wrap;
        width: 100% !important;
        box-sizing: border-box;
        margin: 0 !important;
    }

    #quick-add-url-input {
        /* PMUX-Q1: 16px disables iOS Safari focus-zoom. */
        font-size: 16px !important;
        /* PMUX-B1: drop the inline 240px, fill the row. */
        width: 100% !important;
        min-width: 0;
        margin: 0 !important;
        box-sizing: border-box;
    }

    #quick-add-url-btn {
        flex: 0 0 auto;
        margin: 4px 0 0 0 !important;
        font-size: 16px !important;
        align-self: flex-start;
    }
}

/* Trial banner on /client (evolution 37). Three severity variants share
 * the same flex skeleton; the alert-info/-warning/-danger color comes
 * from Bootstrap which is already loaded by main.html. The banner is
 * rendered as a sibling of #user-messages (NOT inside the loop) so the
 * AJAX-refresh that re-renders user-messages every cursor change does
 * not stomp the trial banner on every tick. */
.trial-banner {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
	margin: 0 0 16px 0;
	padding: 12px 16px;
}
.trial-banner .trial-cta {
	margin-left: auto;
	flex: 0 0 auto;
}
.trial-banner .close.trial-banner-dismiss {
	position: absolute;
	right: 10px;
	top: 6px;
	font-size: 20px;
	line-height: 1;
	text-decoration: none;
	color: inherit;
	opacity: 0.5;
}
.trial-banner .close.trial-banner-dismiss:hover { opacity: 1; }
.trial-banner small {
	color: inherit;
	opacity: 0.8;
	font-size: 12px;
}

/* Mobile: stack the CTA below the copy. Avoids the affordance getting
 * pushed off-screen by long absolute-timestamp strings. */
@media (max-width: 767px) {
	.trial-banner {
		flex-direction: column;
		align-items: flex-start;
	}
	.trial-banner .trial-cta {
		margin-left: 0;
		margin-top: 8px;
		width: 100%;
		text-align: center;
	}
	.trial-banner small {
		/* Truncate the absolute timestamp on narrow screens — the user
		 * still has the relative "N days left" inline. */
		display: block;
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;
		max-width: 100%;
	}
}

/* =========================================================
   TORRENT THUMBS + DETAIL-PAGE HERO
   ---------------------------------------------------------
   Per-row 64x96 thumb on /client and the 120x180 poster
   hero on /client/torrent/<hash>. Markup lives in:
     - app/views/tags/torrent-thumb.html (the glyph + img + badge)
     - app/views/client/torrent-list.html (.torrent-row-thumb wrapper)
     - app/views/client/torrentPage.html (.torrent-hero block)

   Schema for posterUrl / metadataKind / metadataStatus is landing
   in a separate evolution; until it merges, every torrent renders
   the kind-placeholder. After the resolver lands, the same DOM
   auto-lights-up — no template change needed.

   Section deliberately placed at the END of the file so it never
   collides with the audiobook mobile bottom-bar block (lines
   ~460+) or the trial-banner block (lines ~750+).
   ========================================================= */

/* Per-kind accent — drives the SVG stroke colour via currentColor.
   Background stays a neutral cool-grey so the thumb does not
   visually compete with the row's progress bar. */
.torrent-thumb {
	position: relative;
	display: inline-block;
	width: 64px;
	height: 96px;
	flex: 0 0 auto;
	box-sizing: border-box;
	border-radius: 4px;
	background: #e7eaee;
	overflow: hidden;
	/* Default text colour — overridden per-kind below. */
	color: #4a5560;
	/* Subtle inset border so the box reads as a card on white rows. */
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
	user-select: none;
}
.torrent-thumb__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	background: #e7eaee;
	z-index: 2;
}
.torrent-thumb__glyph {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 1;
}
.torrent-thumb__glyph > svg {
	width: 56%;
	height: 56%;
	display: block;
}
/* Pulse-dot badge in the top-right corner while metadataStatus=pending
   and no posterUrl. Pure CSS animation — no JS. */
.torrent-thumb__fetching {
	position: absolute;
	top: 6px;
	right: 6px;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: #2d6cdf;
	box-shadow: 0 0 0 2px #fff;
	z-index: 3;
	animation: torrent-thumb-pulse 1.6s ease-in-out infinite;
}
@keyframes torrent-thumb-pulse {
	0%, 100% { opacity: 0.35; transform: scale(0.9); }
	50%      { opacity: 1;    transform: scale(1.15); }
}

/* Kind palette — one accent per kind, neutral background shared. */
.torrent-thumb--kind-movie     { color: #d9534f; background: #f6e4e3; }
.torrent-thumb--kind-series    { color: #2f8a83; background: #dceeec; }
.torrent-thumb--kind-audiobook { color: #6a4cc4; background: #e7e0f5; }
.torrent-thumb--kind-music     { color: #c98e1e; background: #f7ebd5; }
.torrent-thumb--kind-other     { color: #5a6470; background: #e7eaee; }
.torrent-thumb--kind-unknown   { color: #6c7680; background: #ebedf0; }

/* List-row thumb sits inside the .torrent-row-layout flex container.
   The wrapper enforces a fixed pixel slot so a flex-shrink torrent-title
   never steals horizontal space from the thumb. */
.torrent-row-thumb {
	flex: 0 0 64px;
	display: flex;
	align-items: center;
	justify-content: center;
	min-width: 64px;
}

/* Hero on the per-torrent detail page. Side-by-side on desktop:
   the 120x180 poster sits left of the title + identify-button +
   stats block. Margin-top matches the .ti-back spacing so the
   hero reads as a single chunk under the back-link. */
.torrent-hero {
	display: flex;
	align-items: flex-start;
	gap: 18px;
	margin: 14px 0 22px 0;
	padding: 12px 0;
	border-bottom: 1px solid #edf0f3;
}
.torrent-hero__poster {
	flex: 0 0 auto;
}
.torrent-hero__poster .torrent-thumb--hero {
	width: 120px;
	height: 180px;
	border-radius: 6px;
}
.torrent-hero__poster .torrent-thumb--hero .torrent-thumb__glyph > svg {
	width: 50%;
	height: 50%;
}
.torrent-hero__poster .torrent-thumb__fetching {
	width: 10px;
	height: 10px;
	top: 9px;
	right: 9px;
}
.torrent-hero__meta {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}
/* Inside the hero, the existing .ti-title rule (in torrentPage.html
   inline <style>) keeps the typography — we only need to neutralise
   its margin so the flex gap is the single spacing source. */
.torrent-hero__title {
	margin: 0 !important;
}
.torrent-hero__stats {
	margin: 0 !important;
}
.torrent-hero__identify {
	align-self: flex-start;
	min-height: 32px;
	display: inline-flex;
	align-items: center;
	gap: 4px;
}

/* Mobile breakpoint — phones. Tighter row, smaller thumb, hero
   stacks the poster ABOVE the title block. The 48x72 box keeps
   the silhouette of each kind glyph legible. */
@media (max-width: 767px) {
	.torrent-thumb--list {
		width: 48px;
		height: 72px;
	}
	.torrent-row-thumb {
		flex: 0 0 48px;
		min-width: 48px;
	}
	.torrent-row-layout {
		/* Tighten gap on phones — every 4px counts at 390 CSS px. */
		gap: 8px !important;
	}
	.torrent-hero {
		flex-direction: column;
		gap: 12px;
		align-items: flex-start;
		padding: 8px 0;
		margin: 8px 0 16px 0;
	}
	.torrent-hero__poster .torrent-thumb--hero {
		width: 80px;
		height: 120px;
		border-radius: 5px;
	}
}

/* Very narrow phones (≤480px) — shrink the list thumb further only
   if the row would otherwise wrap. The existing .torrent-row-layout
   rules already accommodate; this is purely a defensive margin. */
@media (max-width: 480px) {
	.torrent-thumb--list {
		width: 44px;
		height: 66px;
	}
	.torrent-row-thumb {
		flex: 0 0 44px;
		min-width: 44px;
	}
}

/* When the resolver completes and the row has a real <img>, the
   onerror handler hides it and sets data-img-broken="1" on the
   parent so the glyph below becomes visible without a layout
   shift. The selector is here (not in the tag) so the fallback
   is global and re-styleable in one place. */
.torrent-thumb[data-img-broken="1"] .torrent-thumb__img {
	display: none !important;
}

/* =========================================================
   DETAIL-PAGE DESCRIPTION BLOCK (task #46)
   ---------------------------------------------------------
   Sits between the hero and the Files section on
   /client/torrent/<hash>. Server-rendered, pure-CSS toggle —
   no JS, no FOUC. Markup contract lives in
   app/views/client/torrentPage.html (#torrent-description).

   The section is only emitted when the linked
   torrent_metadata row has at least one of description_en /
   description_ru populated. The template never renders an
   empty placeholder, so the rules below never need to handle
   a zero-content state.

   Layout:
     - Block-level <section>, max-width 720px to match the
       reading column of the hero meta on desktop; on mobile
       it stretches edge-to-edge inside the .span10 column.
     - 24 px above (separates from the hero rule), 16 px
       below (before the Files <h2>).
     - Body text: 14 px desktop / 16 px mobile (mobile bump
       prevents iOS Safari auto-zoom on tap).

   Collapse:
     - When the text > 240 chars the template emits TWO
       <span>s: --short (preview) and --full (full body).
     - A sibling <input type="checkbox" class="...__toggle">
       drives visibility via the ~ general-sibling selector.
       Toggle is the <label>...__more</label> at the end of
       the section — clicking it flips the checkbox.
     - Default state: checkbox unchecked -> show --short and
       the "Show more" label, hide --full and "Show less".
     - Checked: hide --short, show --full, swap label copy.
   ========================================================= */
.torrent-description {
	margin: 24px 0 16px 0;
	padding: 0;
	max-width: 720px;
	font-size: 14px;
	line-height: 1.55;
	color: #2c3640;
	/* Word-wrap defenses for languages that pack long tokens
	   (CJK, German compound nouns, etc.). The TMDb overview is
	   plain text so we never need a code-block monospace path. */
	overflow-wrap: anywhere;
	word-wrap: break-word;
}
.torrent-description__text {
	display: block;
	white-space: pre-wrap;
}
.torrent-description__ellipsis {
	/* Visual ellipsis after the short preview cut. Kept inline
	   inside the short span so it disappears together with the
	   preview when the user expands. */
	opacity: 0.7;
	margin-left: 1px;
}
/* Visually hide the toggle checkbox but keep it focusable and
   in the accessibility tree. The .visually-hidden pattern below
   (also known as sr-only) leaves the checkbox reachable by Tab
   so keyboard-only users can focus it and press Space to flip
   the collapsed/expanded state. The <label> is the visible
   affordance for mouse / touch / screen-reader-with-virtual-cursor
   users; the aria-label on the checkbox is the screen-reader
   text when it lands in the tab order.
   Don't `display: none` — the ~ sibling selector below depends
   on the checkbox being part of the document layout flow. */
.torrent-description__toggle {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	border: 0;
	white-space: nowrap;
}
/* Render a focus ring on the visible label when the (visually
   hidden) checkbox has keyboard focus. Without this, a Tab-only
   user lands on an invisible checkbox with no on-screen cue. */
.torrent-description__toggle:focus-visible ~ .torrent-description__more {
	outline: 2px solid #2d6cdf;
	outline-offset: 2px;
	border-radius: 3px;
}
/* Default (collapsed) — show short, hide full. */
.torrent-description--collapsible .torrent-description__text--full {
	display: none;
}
.torrent-description--collapsible .torrent-description__text--short {
	display: block;
}
/* Expanded — checkbox checked → swap which span shows. */
.torrent-description__toggle:checked ~ .torrent-description__text--short {
	display: none;
}
.torrent-description__toggle:checked ~ .torrent-description__text--full {
	display: block;
}
/* "Show more / Show less" toggle — refined-utilitarian
   register, matches the muted-link visual weight of .ti-back
   (gray text, underline on hover). Min-height 32 px keeps the
   tap target above WCAG 2.5.5 minimum without going overboard
   for a single inline link. */
.torrent-description__more {
	display: inline-block;
	margin: 8px 0 0 0;
	padding: 6px 0;
	min-height: 32px;
	font-size: 13px;
	line-height: 1.4;
	font-weight: 500;
	color: #2d6cdf;
	cursor: pointer;
	user-select: none;
	background: transparent;
	border: 0;
}
.torrent-description__more:hover,
.torrent-description__more:focus-within {
	color: #1b4ea0;
	text-decoration: underline;
}
/* Default state ("Show more" visible, "Show less" hidden). */
.torrent-description__more .torrent-description__more-hide {
	display: none;
}
/* Expanded state — flip the labels. */
.torrent-description__toggle:checked ~ .torrent-description__more .torrent-description__more-show {
	display: none;
}
.torrent-description__toggle:checked ~ .torrent-description__more .torrent-description__more-hide {
	display: inline;
}

/* Mobile (≤767 px) — bump body text to 16 px to prevent iOS
   Safari auto-zoom on tap, and let the block stretch to the
   full width of the .span10 column with the standard 16 px
   gutter the rest of the detail page uses. */
@media (max-width: 767px) {
	.torrent-description {
		max-width: none;
		font-size: 16px;
		line-height: 1.6;
		margin: 18px 0 14px 0;
	}
	.torrent-description__more {
		font-size: 14px;
	}
}

/* =========================================================
   MOBILE FILE LIST — STACK LAYOUT (P1-21, audit 2026-05-25)

   On mobile the .ti-files-table used to render as a normal
   Bootstrap-2 4-column <table> ("Name / Size / Actions / Done")
   inside a horizontally-scrollable wrapper (.ti-files-scroll).
   At 390 CSS px the Actions and Done columns were clipped past
   the right edge so users had to horizontally scroll to even
   discover the Play / Download buttons, and the buttons rendered
   at ~30×30 px — below the WCAG 2.5.5 minimum 44×44 touch target
   AND adjacent to each other, which produced mis-taps on the
   audiobook cohort (dominant mobile demographic).

   The block below converts the table to a stack-of-cards on
   ≤767px: each <tr> becomes a 2-column grid (filename + size
   stacked on the left, Play/Download stacked on the right as
   44×44 buttons). The Bootstrap-2 markup mode here is a bare
   header <tr> with <th> children (no <thead> wrapper), which
   we hide via :first-child:has(>th). The "Done" column is
   dropped on mobile entirely — when the parent torrent is 100%
   the column is already gone server-side (file-row.html /
   P1-19); for in-progress torrents the percentage adds clutter
   that the parent torrent's stats line already shows.

   Selector scope: only .ti-files-table (set on both the legacy
   torrent-info-modal and the full-page torrentPage.html file
   tables). Does NOT touch .torrent-row-thumb / .torrent-hero
   (P1-N1, list-row thumbs from commit 05c44a2) and does NOT
   touch the audiobook bottom-bar block at L445+ (different
   selector tree — .gt-player-modal). Verified no class
   collisions with .file-name / .file-size / .file-actions /
   .file-done before adding the block.
   ========================================================= */
@media (max-width: 767px) {
    .ti-files-table {
        display: block;
        width: 100%;
        box-sizing: border-box;
        border-collapse: separate;
        background: transparent;
    }
    /* Header row — bare <tr> with <th> children. Hide both the
       <thead>-wrapped shape (defensive) and the Bootstrap-2 inline
       shape we actually emit. */
    .ti-files-table > thead,
    .ti-files-table > tbody > tr:first-child:has(> th),
    .ti-files-table > tr:first-child:has(> th) {
        display: none;
    }
    .ti-files-table > tbody {
        display: block;
        width: 100%;
    }
    .ti-files-table > tbody > tr,
    .ti-files-table > tr {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        column-gap: 8px;
        row-gap: 2px;
        align-items: center;
        padding: 10px 8px;
        border-bottom: 1px solid #e7e7e7;
        background: #fafafa;
        border-radius: 6px;
        margin-bottom: 6px;
    }
    .ti-files-table td {
        display: block;
        padding: 0;
        border: none;
        background: transparent;
        font-size: 14px;
        line-height: 1.35;
    }
    .ti-files-table td.file-name {
        grid-column: 1 / 2;
        grid-row: 1 / 2;
        font-weight: 500;
        word-break: break-word;
        overflow-wrap: anywhere;
        color: #1a1a1a;
    }
    .ti-files-table td.file-size {
        grid-column: 1 / 2;
        grid-row: 2 / 3;
        font-size: 12px;
        color: #6c6c6c;
    }
    /* Actions column spans both rows on the right — buttons sit
       vertically-centered alongside name + size. */
    .ti-files-table td.file-actions {
        grid-column: 2 / 3;
        grid-row: 1 / 3;
        display: flex;
        align-items: center;
        gap: 6px;
        white-space: nowrap;
    }
    /* WCAG 2.5.5 — minimum 44×44 CSS px tap target for Play / Download
       on phones. Bootstrap-2's .btn-mini is 22-26 px tall by default,
       which compounded with adjacency to produce mis-taps. */
    .ti-files-table td.file-actions .btn-mini,
    .ti-files-table td.file-actions .btn {
        min-width: 44px;
        min-height: 44px;
        padding: 10px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-size: 16px;
        line-height: 1;
    }
    .ti-files-table td.file-actions .btn-mini i,
    .ti-files-table td.file-actions .btn i {
        margin: 0;
    }
    /* Drop the percent column on mobile entirely. Server-side already
       hides it when the torrent is 100% complete (file-row.html
       _hidePercentComplete, set in torrentPage.html / torrent-info.html);
       this rule also hides it for in-progress torrents on phones
       where the column would steal space from the more important
       Play / Download buttons. The parent torrent's stats line shows
       the overall %% anyway. */
    .ti-files-table td.file-done {
        display: none;
    }
    /* Audiobook track-prefix sits inline with the filename — render
       it as a dimmer micro-label so the eye lands on the chapter
       name first instead of the "Track N / M" header. */
    .ti-files-table .file-track-prefix {
        color: #6c6c6c;
        font-size: 12px;
        font-weight: 400;
    }
    /* The horizontal-scroll wrapper around the table on torrentPage
       was there to force horizontal scroll on small viewports — with
       the stack layout the wrapper no longer needs to scroll. Drop
       the overflow so a long file list scrolls with the page instead
       of pinning at the top of an inner scroller. */
    .ti-files-scroll {
        overflow-x: visible;
    }
}


/* =========================================================
   METADATA CORRECTION MODAL (task #26)

   Manual override flow — opens from .torrent-hero__identify on
   /client/torrent/<hash>, and from .torrent-thumb-identify-btn
   wrappers around miss/failed thumbs on /client (which navigate
   to the detail page first; the modal lives there).

   States are reflected on the modal root as data-state="...":
     search          Search input + kind tabs + result list (default)
     preview         One result blown up, with confirm/back
     byid            TMDb URL / numeric ID input
     confirm-miss    "Mark as no cover" red-button sub-confirm

   Section-level visibility is gated by data-state on the dialog;
   each .mc-state-* section is display:none unless the parent
   data-state matches.

   Desktop max-width is 720px (override Bootstrap-2's 560px).
   Mobile (≤767px) is bottom-sheet — same shape as
   .gt-player-modal in audio-only mode.
   ========================================================= */

.metadata-correction.modal {
    width: 720px;
    margin-left: -360px;  /* Bootstrap-2 centring math */
    padding: 0;
}
.metadata-correction .mc-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 18px;
    border-bottom: 1px solid #e7e7e7;
}
.metadata-correction .mc-header h3 {
    margin: 0;
    font-size: 17px;
    font-weight: 600;
    line-height: 1.3;
    color: #1b2730;
}
.metadata-correction .mc-close {
    background: transparent;
    border: 0;
    color: #5a6470;
    font: 300 24px/1 sans-serif;
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: 1;
    text-shadow: none;
    padding: 0;
}
.metadata-correction .mc-close:hover,
.metadata-correction .mc-close:focus { color: #1b2730; outline: none; }

.metadata-correction .mc-body {
    padding: 16px 18px;
    max-height: 70vh;
    overflow-y: auto;
}
.metadata-correction .mc-section-heading {
    margin: 4px 0 10px 0;
    font-size: 13px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #5a6470;
}

/* ---- Current pick block ---- */
.metadata-correction .mc-current-pick {
    margin: 0 0 18px 0;
    padding: 12px;
    border: 1px solid #e7e7e7;
    border-radius: 4px;
    background: #fafafa;
}
.metadata-correction .mc-current-pick__row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
}
.metadata-correction .mc-current-pick__poster {
    width: 60px;
    height: 90px;
    flex: 0 0 60px;
    background: #e9e9e9;
    border-radius: 3px;
    overflow: hidden;
    position: relative;
}
.metadata-correction .mc-current-pick__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.metadata-correction .mc-current-pick__placeholder {
    position: absolute;
    inset: 0;
    background:
        repeating-linear-gradient(45deg,
            transparent 0 6px,
            rgba(0,0,0,0.04) 6px 12px);
}
.metadata-correction .mc-current-pick__meta {
    flex: 1 1 auto;
    min-width: 0;
}
.metadata-correction .mc-current-pick__title {
    font-size: 15px;
    font-weight: 600;
    color: #1b2730;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.metadata-correction .mc-current-pick__sub {
    margin-top: 4px;
    font-size: 13px;
    color: #5a6470;
}
.metadata-correction .mc-current-pick__dot { margin: 0 6px; opacity: 0.6; }
.metadata-correction .mc-current-pick__query {
    margin-top: 6px;
    font-size: 12px;
    color: #6b6b6b;
    font-style: italic;
}

/* ---- Search section ---- */
.metadata-correction .mc-search-row {
    margin-bottom: 8px;
}
.metadata-correction .mc-input-search {
    width: 100%;
    box-sizing: border-box;
    padding: 10px 12px;
    font-size: 16px;   /* iOS no-zoom minimum */
    line-height: 1.3;
    border: 1px solid #c9c9c9;
    border-radius: 4px;
    background: #fff;
    color: #1b2730;
}
.metadata-correction .mc-input-search:focus {
    border-color: #2a7ae2;
    outline: none;
    box-shadow: 0 0 0 3px rgba(42,122,226,0.15);
}
.metadata-correction .mc-kind-tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 10px;
    border-bottom: 1px solid #e7e7e7;
}
.metadata-correction .mc-kind-tab {
    background: transparent;
    border: 0;
    padding: 8px 12px;
    margin-bottom: -1px;
    font-size: 13px;
    color: #5a6470;
    border-bottom: 2px solid transparent;
    cursor: pointer;
    min-height: 36px;
}
.metadata-correction .mc-kind-tab:hover { color: #1b2730; }
.metadata-correction .mc-kind-tab.active {
    color: #1b2730;
    font-weight: 600;
    border-bottom-color: #2a7ae2;
}
.metadata-correction .mc-results {
    list-style: none;
    margin: 0;
    padding: 0;
}
.metadata-correction .mc-result {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 0;
    border-bottom: 1px solid #f0f0f0;
}
.metadata-correction .mc-result:last-child { border-bottom: 0; }
.metadata-correction .mc-result__poster {
    width: 48px;
    height: 72px;
    flex: 0 0 48px;
    background: #e9e9e9;
    border-radius: 3px;
    overflow: hidden;
    position: relative;
}
.metadata-correction .mc-result__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.metadata-correction .mc-result__placeholder {
    position: absolute;
    inset: 0;
    background:
        repeating-linear-gradient(45deg,
            transparent 0 6px,
            rgba(0,0,0,0.04) 6px 12px);
}
.metadata-correction .mc-result__meta {
    flex: 1 1 auto;
    min-width: 0;
}
.metadata-correction .mc-result__title-row {
    display: flex;
    align-items: baseline;
    gap: 6px;
    flex-wrap: wrap;
}
.metadata-correction .mc-result__title {
    font-size: 14px;
    font-weight: 600;
    color: #1b2730;
}
.metadata-correction .mc-result__year {
    font-size: 13px;
    color: #5a6470;
    font-weight: 400;
}
.metadata-correction .mc-result__sub {
    margin-top: 2px;
    font-size: 12px;
    color: #5a6470;
}
.metadata-correction .mc-result__overview {
    margin: 4px 0 0 0;
    font-size: 12px;
    color: #444;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.metadata-correction .mc-result__actions {
    flex: 0 0 auto;
    align-self: center;
}
.metadata-correction .mc-results-status {
    margin: 8px 0 0 0;
    font-size: 13px;
    color: #5a6470;
    min-height: 18px;
}

.metadata-correction .mc-alt-actions {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px dashed #e7e7e7;
    font-size: 13px;
    color: #5a6470;
}
.metadata-correction .btn-link {
    background: transparent;
    border: 0;
    padding: 4px 0;
    color: #2a7ae2;
    cursor: pointer;
    font-size: 13px;
    min-height: 32px;
}
.metadata-correction .btn-link:hover { text-decoration: underline; }
.metadata-correction .mc-alt-sep { margin: 0 8px; color: #c9c9c9; }

/* ---- Preview state ---- */
.metadata-correction .mc-preview {
    display: flex;
    gap: 14px;
    align-items: flex-start;
    margin-bottom: 12px;
}
.metadata-correction .mc-preview__poster {
    width: 120px;
    height: 180px;
    flex: 0 0 120px;
    background: #e9e9e9;
    border-radius: 4px;
    overflow: hidden;
}
.metadata-correction .mc-preview__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.metadata-correction .mc-preview__meta {
    flex: 1 1 auto;
    min-width: 0;
}
.metadata-correction .mc-preview__title {
    font-size: 17px;
    font-weight: 600;
    color: #1b2730;
    margin-bottom: 4px;
}
.metadata-correction .mc-preview__sub {
    font-size: 13px;
    color: #5a6470;
    margin-bottom: 8px;
}
.metadata-correction .mc-preview__overview {
    margin: 0;
    font-size: 14px;
    line-height: 1.5;
    color: #333;
}
.metadata-correction .mc-preview__teaching {
    margin: 8px 0 0 0;
    font-size: 13px;
    color: #5a6470;
    font-style: italic;
}

/* ---- By-ID state ---- */
.metadata-correction .mc-byid-help {
    font-size: 13px;
    color: #5a6470;
    margin: 0 0 8px 0;
}
.metadata-correction .mc-byid-input {
    width: 100%;
    box-sizing: border-box;
    padding: 10px 12px;
    font-size: 16px;   /* iOS no-zoom */
    line-height: 1.3;
    border: 1px solid #c9c9c9;
    border-radius: 4px;
    color: #1b2730;
}
.metadata-correction .mc-byid-input:focus {
    border-color: #2a7ae2;
    outline: none;
    box-shadow: 0 0 0 3px rgba(42,122,226,0.15);
}

/* ---- Section visibility by state ---- */
.metadata-correction .mc-state-search,
.metadata-correction .mc-state-preview,
.metadata-correction .mc-state-byid,
.metadata-correction .mc-state-confirm-miss { display: none; }
.metadata-correction[data-state="search"] .mc-state-search { display: block; }
.metadata-correction[data-state="preview"] .mc-state-preview { display: block; }
.metadata-correction[data-state="byid"] .mc-state-byid { display: block; }
.metadata-correction[data-state="confirm-miss"] .mc-state-confirm-miss { display: block; }
.metadata-correction[data-state="preview"] .mc-current-pick,
.metadata-correction[data-state="byid"] .mc-current-pick,
.metadata-correction[data-state="confirm-miss"] .mc-current-pick { display: none !important; }

/* ---- Identify affordance on .torrent-hero ---- */
.torrent-hero__identify {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 8px 0;
    min-height: 36px;
}
.torrent-hero__identify--muted {
    color: #6b6b6b !important;
    background: #f0f0f0 !important;
    border-color: #d6d6d6 !important;
}
.torrent-hero__identify--muted:hover {
    color: #1b2730 !important;
    background: #e6e6e6 !important;
}

/* ---- Row identify wrapper + ? corner badge ---- */
.torrent-thumb-identify-btn {
    background: transparent;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    display: inline-block;
    /* Anchor for the absolutely-positioned badge */
    position: relative;
}
.torrent-thumb-identify-btn:focus { outline: 2px solid #2a7ae2; outline-offset: 2px; }
.torrent-thumb[data-needs-identify="1"] {
    position: relative;
}
.torrent-thumb__identify-badge {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 22px;
    height: 22px;
    border-radius: 11px;
    background: #f0ad4e;
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    line-height: 22px;
    text-align: center;
    box-shadow: 0 1px 2px rgba(0,0,0,0.2);
    pointer-events: none;
    z-index: 2;
}

/* ---- Mobile: bottom-sheet pattern (≤767px) ---- */
@media (max-width: 767px) {
    .metadata-correction.modal {
        width: 100% !important;
        max-width: 100% !important;
        margin: 0 !important;
        left: 0 !important;
        right: 0 !important;
        top: auto !important;
        bottom: 0 !important;
        border-radius: 12px 12px 0 0;
        max-height: 90vh;
        padding-bottom: env(safe-area-inset-bottom);
        transform: none !important;
    }
    .metadata-correction .mc-body {
        max-height: calc(90vh - 110px - env(safe-area-inset-bottom));
    }
    .metadata-correction .mc-preview {
        flex-direction: column;
    }
    .metadata-correction .mc-preview__poster {
        width: 120px;
        height: 180px;
        align-self: center;
    }
    .metadata-correction .mc-result {
        flex-direction: column;
        align-items: stretch;
    }
    .metadata-correction .mc-result__actions {
        align-self: flex-end;
    }
    .metadata-correction .mc-kind-tab {
        min-height: 44px;
        padding: 10px 12px;
    }
    .torrent-thumb-identify-btn {
        min-width: 48px;
        min-height: 48px;
    }
    /* Footer: pin to bottom and ensure the primary action sits visually
       in the lower third for thumb-reach. */
    .metadata-correction .modal-footer {
        position: sticky;
        bottom: 0;
        background: #f5f5f5;
        padding-bottom: calc(12px + env(safe-area-inset-bottom));
    }
}

/* sr-only utility — used by labels in the modal. Bootstrap-2 doesn't
   ship one. */
.metadata-correction .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
