/* ===========================================================================
   Responsive / mobile layer.

   Loaded last so it can adjust the desktop-first rules in the other
   stylesheets. Anything that must not change the desktop rendering lives
   inside a max-width media query.
   =========================================================================== */

/* ===================== PAGE SHELL ===================== */
/* Replaces the inline `max-width: <n>vw` that every page used to carry.
   On a 390px phone 65vw was 253px of usable width. */

.page-shell {
    width: 100%;
    max-width: 65vw;
    margin-left: auto;
    margin-right: auto;
}
.page-shell--narrow {
    max-width: 55vw;
}
.page-shell--tight {
    max-width: 40vw;
}

/* Tablets: 65vw of a 1024px screen is only 665px, and the md columns have
   not stacked yet. Desktop (>=1200px) keeps the original proportions. */
@media (max-width: 1199.98px) {
    .page-shell {
        max-width: 85vw;
    }
    .page-shell--narrow {
        max-width: 75vw;
    }
    .page-shell--tight {
        max-width: 60vw;
    }
}

@media (max-width: 991.98px) {
    .page-shell,
    .page-shell--narrow,
    .page-shell--tight {
        max-width: 100%;
    }
}

/* Flex children need this to be allowed to shrink below their content size. */
.min-w-0 {
    min-width: 0;
}


/* ===================== GLOBAL SAFETY NETS ===================== */

/* Stop iOS/Android from re-scaling text in landscape. */
html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

/* No image should ever be able to push the page wider than the viewport. */
img,
svg,
video {
    max-width: 100%;
}

/* Remove the 300ms tap delay and the grey flash on tap. */
a,
button,
label,
summary,
[role="button"],
.btn,
.form-check-input {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

/* Momentum scrolling inside the app's many scroll panes. */
.recent-tierdrops-card .card-body,
.panel-scroll,
.mini-tierlist,
.ranker-preview-list,
.unassigned-tier,
.edit-tiers-form,
.select-column-form {
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
}
/* NOT `.tier .sortable-tier`. A tier is no longer its own scroll container —
   #tierlist-container is — and `overscroll-behavior: contain` on the inner
   list swallowed every wheel and drag that landed inside a tier instead of
   letting it chain up to the pane that can actually scroll. */

/* Long unbroken item names should wrap rather than overflow. */
.card-title,
.modal-title,
.tier-title,
h1, h2, h3, h4, h5, h6 {
    overflow-wrap: anywhere;
}
/* ...except where the design deliberately truncates with an ellipsis. */
.title-header,
.no-wrap,
.text-truncate,
.tierlist-title,
.compare-card-title,
.tierdrop-preview-card h6,
.select-column-label {
    overflow-wrap: normal;
}

/* Respect the notch / home indicator on phones. */
footer {
    padding-bottom: env(safe-area-inset-bottom, 0px);
}


/* ===================== SCROLL PANES ===================== */
/* Fixed `vh` scroll panes nested inside a scrolling page are painful on
   touch. On phones they become ordinary content that grows with the page. */

.panel-scroll {
    height: 67vh;
}
.panel-scroll--short {
    height: 60vh;
}
.panel-scroll--compact {
    height: 55vh;
}
.panel-scroll--tall {
    height: 70vh;
}

/* Long-form policy pages. */
.doc-panel {
    max-height: 75vh;
}

@media (max-width: 767.98px) {
    .panel-scroll,
    .doc-panel {
        height: auto;
        max-height: none;
        overflow: visible !important;
    }
    .panel-scroll > .card-body,
    .doc-panel > .card-body {
        height: auto;
        max-height: none;
        overflow: visible !important;
    }
}


/* ===================== TOUCH AFFORDANCES ===================== */

@media (hover: none) and (pointer: coarse) {
    /* Hover transforms stick after a tap on touch devices. */
    .card:hover,
    .tierdrop-card:hover,
    .compare-card:hover,
    .drag-drop-item:hover,
    .tierlist-drag-drop-item:hover,
    .tierdrop-preview-card:hover,
    .btn-primary.btn-lg:hover,
    .btn-secondary.btn-lg:hover,
    .thumbnail-picker:hover img {
        transform: none;
    }

    /* Grab cursors mean nothing without a mouse. */
    .drag-drop-item,
    .tierlist-drag-drop-item,
    .sortable-item {
        cursor: default;
    }

    /* A min-height alone only makes the box taller — the label stays at its
       padding offset and reads as top-aligned. Center it in the taller box. */
    .btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    /* Comfortable minimum hit area (WCAG 2.5.5 target size). */
    .btn,
    .navbar-nav .nav-link,
    .dropdown-item,
    .select-column-btn-primary,
    .select-column-btn-secondary,
    .edit-tiers-btn-add,
    .edit-tiers-btn-save,
    .edit-tiers-btn-delete {
        min-height: 44px;
    }
    .btn-sm {
        min-height: 40px;
        min-width: 40px;
    }
    /* Bootstrap sizes the close button to the glyph itself (1em box), which
       is a ~16px target. Grow the box, keep the glyph. */
    .btn-close {
        width: 2.25rem;
        height: 2.25rem;
        background-size: 0.8rem auto;
    }

    /* Keyboard-shortcut helper is meaningless without a keyboard. */
    #help-button,
    #help-info {
        display: none !important;
    }
}


/* ===================== NAVBAR ===================== */

:root {
    --mobile-navbar-height: 56px;
}

@media (max-width: 991.98px) {
    /* The navbar had a hard 10vh height, so the expanded menu spilled out of
       its own background and floated unstyled over the page. */
    .navbar {
        height: auto;
        min-height: var(--mobile-navbar-height);
        padding-top: 0.25rem;
        padding-bottom: 0.25rem;
    }
    .navbar-brand {
        font-size: 1.05rem;
    }
    .navbar-brand img {
        height: 40px;
    }
    .navbar-collapse {
        background-color: var(--navbar-bg-color);
        border-top: 1px solid var(--card-border-color);
        margin-top: 0.35rem;
        padding: 0.5rem 0.25rem;
    }
    /* The nav only carries icon links, so keep them on one right-aligned row
       under the toggler — that also lines the profile menu up with the
       avatar that opens it. */
    .navbar-nav {
        flex-direction: row;
        justify-content: flex-end;
        align-items: center !important;
        gap: 0.75rem;
    }
    .navbar-nav .nav-item.me-3 {
        margin-right: 0 !important;
    }
    .navbar-nav .nav-link {
        display: flex;
        align-items: center;
        padding: 0.5rem 0.75rem;
    }
    .navbar .fa-spotify {
        font-size: 1.75rem;
    }
    .navbar-profile-icon {
        width: 40px;
        height: 40px;
    }
    /* The profile dropdown is absolutely positioned; inside the collapsed
       menu it needs to stay anchored to the right edge. */
    .navbar .dropdown-menu-end {
        right: 0;
        left: auto;
    }
}

/* Bootstrap's toggler icon is drawn dark, which is invisible on the dark
   navbar. The site themes with a body class rather than data-bs-theme. */
body.dark-mode .navbar-toggler-icon {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}
body.dark-mode .navbar-toggler {
    border-color: rgba(255, 255, 255, 0.25);
}
.navbar-toggler:focus {
    box-shadow: 0 0 0 0.2rem rgba(var(--shadow-rgb, 0, 0, 0), 0.15);
}


/* ===================== PAGE FRAME ===================== */

@media (max-width: 991.98px) {
    /* Desktop reserves 10vh for the fixed navbar via padding on <body> plus
       a margin on <main>. The navbar is a fixed height on mobile now. */
    html,
    body {
        padding-top: 0;
    }
    /* A fixed background attachment is not repainted during momentum
       scrolling on iOS and is expensive on Android. */
    body {
        background-attachment: scroll;
    }
    .main-content {
        width: 100%;
        margin-top: 0;
        padding-top: calc(var(--mobile-navbar-height) + 0.75rem);
        min-height: auto;
    }
}


/* ===================== TYPOGRAPHY ===================== */

.title-wrapper {
    font-size: clamp(1.4rem, 5.5vw, 2.5rem);
}

/* Keep a title and its action button from butting up against each other once
   the page is narrow enough for them to nearly meet. */
@media (max-width: 991.98px) {
    .title-row {
        gap: 0.75rem;
        align-items: flex-start;
        /* Once the action buttons wrap onto their own line they sit directly
           on top of the page content — the Tie button against the two items
           being compared, Continue Comparing against the results thumbnail. */
        margin-bottom: 1rem;
    }
}

@media (max-width: 767.98px) {
    .title-wrapper {
        max-width: 100%;
        margin-bottom: 0.75rem;
    }
    /* A single ellipsised line loses too much of a long ranking name when
       there is only a phone's worth of width. Allow a second line. */
    .title-header {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        -webkit-box-orient: vertical;
        white-space: normal;
        overflow: hidden;
    }
    /* Several pages put a title and an action button in the same flex row. */
    .title-row {
        flex-wrap: wrap;
        gap: 0.5rem;
    }
    .title-row > .title-wrapper {
        flex: 1 1 100%;
    }
}


/* ===================== FORMS ===================== */

@media (max-width: 991.98px) {
    /* iOS Safari zooms the page when a focused control is under 16px. */
    .form-control,
    .form-select,
    input[type="text"],
    input[type="email"],
    input[type="password"],
    input[type="number"],
    input[type="search"],
    input[type="url"],
    textarea,
    select,
    .compact-form .form-control,
    .modal-dialog.modal-sm .modal-content .form-control,
    .edit-tiers-input {
        font-size: 16px;
    }
    .form-actions {
        flex-direction: column;
    }
    .form-actions .btn {
        width: 100%;
    }
}


/* ===================== HOME / MANAGE ITEMS ===================== */

@media (max-width: 767.98px) {
    .recent-tierdrops-card .card-body {
        padding: 0.65rem;
    }
    /* The thumbnail picker is a third of a desktop row but the full width of
       a phone, where it pushed the actual form below the fold. */
    .thumbnail-picker {
        display: block;
        max-width: 220px;
        margin-left: auto;
        margin-right: auto;
    }
    /* The create form and the list read better with breathing room between
       them once they stack. */
    .row > [class*="col-md-"] + [class*="col-md-"] {
        margin-top: 1rem;
    }
}


/* ===================== RANKING DASHBOARD ===================== */

/* Flex parents defaulted to min-width:auto, so the right-hand column could
   not shrink and pushed the layout past the viewport. */
.tierdrop-main-row,
.tierdrop-main-row > [class*="col-"] {
    min-width: 0;
}

.tierdrop-preview-card {
    max-width: 100%;
}

@media (max-width: 767.98px) {
    /* Thumbnail and the edit/manage/share/delete icons sit side by side
       instead of stacking into a tall column. */
    .tierdrop-aside {
        flex-direction: row !important;
        align-items: center !important;
        width: 100%;
        gap: 0.75rem !important;
    }
    .tierdrop-actions {
        flex-direction: row !important;
        justify-content: space-around;
        align-items: center;
        margin-top: 0 !important;
        gap: 0.5rem !important;
    }
    .tierdrop-actions .fa-3x {
        font-size: 1.9em;
    }

    .tierdrop-preview-card {
        width: 40%;
        max-width: 130px;
    }
    .duel-preview-row {
        gap: 0.5rem;
        margin-top: -0.5rem;
    }

    /* Let the preview panes grow with their content rather than trapping a
       second scrollbar inside the page. */
    .mini-tierlist,
    .ranker-preview-list {
        height: auto;
        max-height: 45vh;
    }
    .tierdrop-section-half {
        min-height: 0;
    }
    .tierdrop-section-half .card-body {
        overflow: visible;
    }
}


/* ===================== DUEL RANKER (COMPARE) ===================== */

.compare-card {
    max-width: 100%;
}

@media (max-width: 991.98px) {
    /* Two 40vh-wide cards could not fit side by side, so both items spilled
       off the screen edges. They now share the row evenly. */
    #comparison-container {
        gap: 0.6rem !important;
        align-items: stretch !important;
    }
    #comparison-container > .text-center {
        flex: 1 1 0;
        min-width: 0;
        display: flex;
    }
    .compare-card {
        width: 100%;
        height: auto;
        min-height: 0;
        padding: 0.5rem;
        border-width: 2px;
    }
    .compare-card .card-body {
        padding: 0;
    }
    .compare-card-title {
        font-size: 0.9rem;
        line-height: 1.25;
    }

    /* Title on one line, Go Back / Tie underneath at full tap size. */
    #button-row {
        flex: 1 1 100%;
        gap: 0.5rem;
    }
    #button-row > div {
        flex: 1 1 0;
        min-width: 0;
    }
    #button-row > div:empty {
        display: none;
    }
    #button-row .btn {
        width: 100%;
    }
    #go-back {
        margin-right: 0 !important;
    }
    .btn-equal-width {
        min-width: 0;
    }
}

@media (max-width: 575.98px) {
    .compare-card-title {
        font-size: 0.8rem;
    }
    #comparison-container .fs-4 {
        font-size: 1rem !important;
    }
}

/* Keep the floating help button clear of the home indicator. */
#help-button {
    bottom: calc(32px + env(safe-area-inset-bottom, 0px)) !important;
}


/* ===================== TAILORED RANKER (DRAG AND DROP) ===================== */

@media (max-width: 767.98px) {
    /* One row per item — grip, rank, thumbnail, name, then the four moves.
       Every part but the name is a fixed width, so the name absorbs whatever
       is left over and ellipsises. */
    .drag-drop-item {
        flex-wrap: nowrap;
        gap: 0.3rem;
        padding: 6px;
    }
    .drag-drop-item > .d-flex.flex-grow-1 {
        min-width: 0;
    }
    .drag-drop-item .pos-badge {
        width: 1.6rem;
        font-size: 0.8rem;
        margin-right: 0 !important;
    }
    .drag-drop-item .list-thumb {
        /* Without flex:0 0 auto the thumbnail shrinks off its own width and
           stops being square, since it is a flex item in a tight row. */
        flex: 0 0 auto;
        width: 34px;
        height: 34px;
        margin-right: 0.4rem !important;
    }
    .drag-drop-item .no-wrap {
        font-size: 0.8rem;
    }
    .completion-item .no-wrap {
        font-size: 0.95rem;
    }
    .drag-drop-item .button-group {
        flex: 0 0 auto;
        gap: 0.1rem;
    }
    .drag-drop-item .button-group .btn {
        min-width: 26px;
        min-height: 30px;
        padding: 0 0.2rem;
        font-size: 0.8rem;
    }
    /* The name wrapper capped itself at 75% of a very narrow row. */
    .drag-drop-item .item-name-wrap,
    .completion-item .item-name-wrap {
        max-width: 100% !important;
        min-width: 0;
    }
}


/* ===================== TIER LIST RANKER ===================== */

/* Do NOT reorder these columns with CSS `order`. SortableJS hit-tests
   geometrically but inserts by DOM order, and a mismatch between the two makes
   cross-tier drops silently fail on high-DPR screens. */

@media (max-width: 991.98px) {
    .tier {
        min-height: 88px;
        resize: none;
    }
    .tier .sortable-tier {
        gap: 0.4rem;
    }
    /* Both panes are only a third of a phone wide, so give them more of the
       screen's height to work with. */
    #tierlist-container,
    .unassigned-tier {
        height: 62vh;
    }
}

@media (max-width: 767.98px) {
    /* A third of a phone is ~100px of tray. Beside a thumbnail that leaves the
       name about one character wide, so the two stack instead — the name then
       gets the whole column, and the strip under each thumbnail is still free
       to scroll by. */
    .unassigned-tier .sortable-item {
        flex-direction: column;
        align-items: center;
        gap: 0.15rem;
    }
    .unassigned-tier .tierlist-title {
        text-align: center;
    }
    /* Reclaim the card's padding for the items themselves. */
    .tierlist-unassigned-col .card-body {
        padding: 0.4rem 0.3rem;
    }
    .tierlist-unassigned-col .card-header {
        padding: 0.4rem 0.5rem;
    }
    /* "Unassigned" was breaking mid-word under the global overflow-wrap. */
    .tierlist-unassigned-col .card-title {
        font-size: 0.8rem;
        overflow-wrap: normal;
        text-align: center;
    }
}

@media (max-width: 575.98px) {
    .sortable-item {
        width: 64px;
    }
    .tierlist-img {
        width: 56px;
        height: 56px;
    }
    .tierlist-title {
        max-width: 64px;
    }
    /* The tray is a single column, not a grid of squares, so its items size
       themselves off the column rather than off those caps. */
    .unassigned-tier .tierlist-img {
        width: 48px;
        height: 48px;
    }
    .unassigned-tier .tierlist-title {
        max-width: 100%;
    }
}

/* Sortable's own drag mirror should sit above the fixed navbar. */
.sortable-fallback,
.sortable-drag {
    z-index: 1100;
}


/* ===================== EDIT TIERS / SELECT COLUMNS ===================== */

@media (max-width: 991.98px) {
    .edit-tiers-form {
        max-width: 100%;
        max-height: none;
        padding: 1rem;
    }
    .select-column-form {
        max-height: none;
        padding: 1rem;
    }
    .edit-tiers-heading,
    .select-column-heading {
        font-size: 1.35rem;
    }
    .select-column-btn-primary,
    .select-column-btn-secondary {
        width: 100%;
    }
}


/* ===================== COMPLETION / RESULTS ===================== */

@media (max-width: 767.98px) {
    /* Three fixed 180px columns needed 540px of width. */
    .highlight-grid {
        grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
        gap: 0.6rem;
        justify-content: stretch;
    }
    .highlight-card img {
        width: 100%;
        height: auto;
        aspect-ratio: 1;
    }
    .completion-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    /* Buttons pinned to a 200px width overflowed alongside the title. */
    .btn-fixed-200 {
        width: 100% !important;
    }
    #button-row {
        flex: 1 1 100%;
    }
    #button-row > div {
        width: 100%;
    }
}


/* ===================== MODALS ===================== */

@media (max-width: 575.98px) {
    .modal-dialog {
        margin: 0.5rem;
    }
    .modal-dialog.modal-sm {
        max-width: calc(100% - 1rem);
    }
    .modal-footer {
        flex-wrap: wrap;
    }
    .modal-footer .btn {
        flex: 1 1 auto;
        min-width: 0;
    }
    /* A tall modal body should scroll inside the modal, not the page. */
    .modal-body {
        max-height: 70vh;
        overflow-y: auto;
    }
}


/* ===================== DRAG HANDLES ===================== */
/* A touch drag and a touch scroll are the same gesture, so SortableJS had to
   guess which one was meant — it waited out a press-and-hold before picking an
   item up, and any drift during that hold cancelled it. On a phone that reads
   as "nothing is draggable". Dedicated handles remove the ambiguity: the grip
   drags, everything else scrolls. The Tailored Ranker gets an explicit grip,
   passed to Sortable only when this same media query matches, so pointer
   devices keep whole-row dragging and never see the grip. The Tier List needs
   no grip — its thumbnails are the handles on every device. */

.drag-handle {
    display: none;
}

@media (hover: none) and (pointer: coarse) {
    .drag-handle {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        flex: 0 0 auto;
        min-width: 44px;
        min-height: 44px;
        margin-right: 0.35rem;
        border-radius: 6px;
        background: rgba(128, 128, 128, 0.16);
        color: var(--card-text-color);
        font-size: 1.05rem;
        opacity: 0.75;
        /* Without this the browser consumes the gesture for scrolling and
           Sortable never sees the moves that make up a drag. */
        touch-action: none;
        user-select: none;
        -webkit-user-select: none;
        -webkit-touch-callout: none;
    }
    .drag-handle:active {
        opacity: 1;
    }

    /* Keeping the whole item on one line costs the grip its 44px square; the
       row is only ~340px wide and the name still needs to be readable. */
    .drag-drop-item .drag-handle {
        min-width: 30px;
        min-height: 38px;
        margin-right: 0.1rem;
    }
}


/* ===================== LANDSCAPE PHONES ===================== */
/* Last in the file so these deliberately win over the width-based rules. */

/* Landscape phones have very little height. Cap the duel artwork so a whole
   comparison — both cards, their titles and the progress bar — fits on screen
   instead of forcing a scroll between the two things being compared. */
@media (max-height: 520px) and (orientation: landscape) {
    .title-wrapper {
        font-size: 1.25rem;
        margin-bottom: 0.35rem;
    }
    /* Vertical space is the scarce resource here — keep the title and its
       buttons on one line rather than stacking them, and trim the gap the
       portrait layout leaves under them. */
    .title-row {
        margin-bottom: 0.5rem;
    }
    .title-row > .title-wrapper {
        flex: 1 1 auto;
        min-width: 0;
    }
    #button-row {
        flex: 0 0 auto;
    }
    .main-content {
        padding-top: calc(var(--mobile-navbar-height) + 0.25rem);
    }
    .compare-card {
        padding: 0.4rem;
    }
    .compare-card img {
        max-height: 38vh;
        width: auto;
        margin-inline: auto;
    }
    .compare-card-title {
        font-size: 0.8rem;
        padding-top: 0.3rem;
        margin-top: 0.3rem;
    }
    .progress-bar,
    .progress-container {
        height: 18px;
        line-height: 18px;
    }
}
