/* =========================================
   1. BASE PORTAL CSS (series.listening.portal.css)
   ========================================= */



/* Header */
.app-header {
    padding: var(--container-padding);
    background: var(--bg-gradient-black-70);
}

.app-header h1 {
    color: var(--accent-color);
    text-transform: uppercase;
    letter-spacing: 2px;
}

.library-grid {
    display: grid;

}

/* Grid Layout */
.series-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--gap-size);
    padding: var(--container-padding);
}

/* Series Card */
.series-card {
    background-color: var(--card-bg);
    border-radius: var(--border-radius);
    overflow: hidden;
    transition: transform 0.3s ease, box-shadow 0.3s ease;
    position: relative;
}


.series-card:hover {
    transform: scale(1.05);
    z-index: 2;
    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5);
}

.card-image {
    width: 100%;
    object-fit: cover;
    display: block;
    aspect-ratio: 4/3;
}

#library-rows > section.category-row > div.row-canvas > div.scroll-container > div.series-card > img,
#home-rows > section.category-row > div.row-canvas > div.scroll-container > div.series-card > img.card-image{
    aspect-ratio: 1/1;
    height:240px;
}


.card-details {
    padding: 10px;
}

.card-details .card-title {
    font-size: 0.95rem;
    font-weight: bold;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.card-meta {
    font-size: 0.8rem;
    color: var(--text-secondary);
}



.badge-new {
    position: absolute;
    top: 10px;
    right: 10px;
    background-color: var(--accent-color);
    color: var(--text-main);
    font-size: 0.7rem;
    padding: 2px 6px;
    border-radius: 2px;
    font-weight: bold;
}




/* Modal / Detail View */
.modal {
    display: none;
    /* Hidden by default */
    position: fixed;
    z-index: 100;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: var(--modal-overlay);
    backdrop-filter: var(--fx-filter-blur);
    animation: fadeIn 0.3s;
}

@keyframes fadeIn {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

.modal-content {
    background-color: var(--card-bg);
    margin: 5% auto;
    padding: 2rem;
    width: 90%;
    max-width: 800px;
    border-radius: var(--border-radius);
    position: relative;
    box-shadow: 0 5px 30px rgba(0, 0, 0, 0.5);
}

.close-btn {
    position: absolute;
    top: 15px;
    right: 20px;
    font-size: 30px;
    font-weight: bold;
    color: var(--text-secondary);
    transition: color 0.2s;
}

p.muted {
    color: var(--text-secondary);
}

.close-btn:hover {
    color: var(--text-primary);
}

.modal-header {
    display: flex;
    gap: 2rem;
    margin-bottom: 2rem;
}

.modal-profile-img {
    width: 225px;
    height: 225px;
    object-fit: contain;
    border-radius: var(--border-radius);
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5);
}

.modal-info {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.modal-meta {
    color: var(--text-secondary);
    font-weight: bold;
    margin-bottom: 1rem;
}







/* =========================================
   2. PORTAL V2 OVERRIDES (series.listening.portal.v2.css)
   ========================================= */


/* --- Layout --- */
.app-container {
    display: flex;
    min-height: 100vh;
}

/* --- Sidebar --- */
.sidebar {
    width: var(--sidebar-width);
    background-color: var(--sidebar-bg);
    padding: 2rem 0;
    display: flex;
    flex-direction: column;
    position: fixed;
    height: 100vh;
    z-index: 50;
    transition: transform 0.3s ease;
}

.logo {
    color: var(--accent-color);
    font-size: 1.5rem;
    font-weight: bold;
    padding: 0 1.5rem 2rem;
    letter-spacing: 2px;
}

/* The scrolling behaviour that used to live here moved to
   quizflix.nav.css — it was missing from the v2 sheet, so the game screens'
   sidebars ran off the bottom instead of scrolling. One owner now. */
.nav-list {
    list-style: none;
}

/* .nav-group (the scrolling sub-list), .nav-caret (the control that opened one)
   and .nav-thumb (the 30px art in one) are all GONE. The sidebar has no
   expanding panes left — series, films and finally games all became plain links
   to the screen that lists them (owner, 2026-08-18). Nothing in the app renders
   those three classes any more, and a rule kept for markup nobody builds is how
   a stylesheet ends up describing a menu that no longer exists. */

.nav-item {
    padding: 1rem 1.5rem;
    color: var(--text-secondary);
    transition: color 0.2s, background 0.2s, border 0.2s;
    border-left: 4px solid transparent;
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
}

.nav-item:hover {
    color: var(--text-primary);
    background-color: #222;
}

.nav-item.active {
    color: var(--text-primary);
    border-left: 4px solid var(--accent-color);
    font-weight: bold;
    background-color: #222;
}

/* The profile entry's own rules (.nav-item.nav-profile, its 48px icon and
   .nav-profile-name) moved to quizflix.nav.css, together with the pop-out menu
   that entry now opens. They were never copied into the v2 sheet, so the profile
   block rendered as a plain row on the quiz, trivia and game screens.

   .nav-signout / .nav-signout-btn were deleted outright: Sign Out is no longer a
   block pinned to the bottom of the sidebar. It is an item in the profile menu. */

/* --- Main Content --- */
.main-content {
    flex: 1;
    margin-left: var(--sidebar-width);
    /* Offset for fixed sidebar */
    width: calc(100% - var(--sidebar-width));
}

/* --- Hero Section --- */
.hero-section.main-page {
    background-image: url('../../images/backgrounds/quizflix.login.background.png');
    background-size: cover;
    background-position: center;
}

/* --- Screen banners (WDF1-4.4) ------------------------------------------
   One block per named screen, kept together so the set reads as one thing.

   Two layers rather than one: the first is the screen's own banner and the
   second is the shared `.main-page` background underneath it. A layer whose
   file is missing simply does not paint — the browser drops it and the one
   below shows through. That IS the fallback the owner asked for: no existence
   check, no JS, no 404 handling. So a block may be written before its art
   exists, and the screen gains the banner the moment the file lands.

   `search.jpg` and `options.jpg` are NOT on disk yet — those two screens paint
   the shared background until the owner's art arrives, which is the specified
   behaviour and not a defect.

   The unfiltered library, home, the directory and the profile hero on any
   other route are deliberately not here: the item names four screens and the
   rest are left exactly as they are.

   Series and Movies are the same page (`library.html?type=`), so their class
   is put on the hero in JS — Render.Hero's default: branch in
   assets/script/portals/quizflix.render.logic.js. The other three take a
   static class in their own markup. */
.hero-section.main-page.arcade-hero {
    background-image:
        url('../../images/banners/arcade.jpg'),
        url('../../images/backgrounds/quizflix.login.background.png');
}

.hero-section.main-page.library-hero-series {
    background-image:
        url('../../images/banners/series.jpg'),
        url('../../images/backgrounds/quizflix.login.background.png');
}

.hero-section.main-page.library-hero-movie {
    background-image:
        url('../../images/banners/movies.jpg'),
        url('../../images/backgrounds/quizflix.login.background.png');
}

.hero-section.main-page.search-hero {
    background-image:
        url('../../images/banners/search.jpg'),
        url('../../images/backgrounds/quizflix.login.background.png');
}

/* "Options" is the profile screen — owner ruling 2026-08-13 (Q9). The file is
   named for the owner's word rather than for the page, so the art they drop in
   lands where this rule is already looking. */
.hero-section.main-page.options-hero {
    background-image:
        url('../../images/banners/options.jpg'),
        url('../../images/backgrounds/quizflix.login.background.png');
}

.hero-section.main-page h1 {
    color: var(--accent-color);
}

.hero-section {
    position: sticky;
    position: -webkit-sticky;
    /* For Safari */
    z-index: 9;
    /* min-height, not height. The hero is the taller of the 30vh band and its
       own content. With a fixed height it could not grow, and because the
       content is bottom-aligned, anything that did not fit overflowed out of
       the TOP of the box (flex items overflow away from the alignment edge) —
       putting the title above the header and, once the sticky offset pulled
       the hero up as well, off the screen entirely. A long "Starring:" line or
       a short viewport was enough to trigger it. See ScrollEffect.Hero in
       assets/script/portals/quizflix.logic.helpers.js for the other half. */
    min-height: 30vh;
    /*position: relative;*/
    display: flex;
    align-items: flex-end;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: left top;
}

.hero-section::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: linear-gradient(to bottom, rgba(20, 20, 20, 0) 0%, rgba(20, 20, 20, 0.6) 50%, var(--bg-color) 100%);
}

.hero-content {
    position: relative;
    z-index: 2;
    padding: var(--container-padding);
    width: 100%;
    background-size: cover;
}

.hero-title {
    font-size: 3rem;
    margin-bottom: 0.5rem;
    text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
}

.hero-meta {
    color: var(--text-secondary);
    font-size: 1.1rem;
    margin-bottom: 1rem;
    display: flex;
    gap: 15px;
    align-items: center;
}

.hero-badge {
    border: 1px solid var(--text-secondary);
    padding: 2px 5px;
    font-size: 0.8rem;
    line-height: 24px;
    text-transform: capitalize;
}

/* --- Season Info Section --- */
#seasonInfoContainer {
    gap: 16px;
    margin-top: 38px;
    width: 96%;
    padding-left: var(--container-padding);
}

#inner-block-trailers {
    display: flex;
    justify-content: space-between;
}

.trailer-video-container {
    box-sizing: border-box;
    margin: 8px 16px 16px 16px;
    background-color: rgb(51, 51, 51);
    padding: 16px;
    height: 276px;
    border-radius: var(--border-radius);


}

#seriesOverview {
    display: block;
    justify-content: left;
    margin: 18px 16px 14px 0px;
    min-height: 145px;
    width: 60%;
}

#seriesOverview h3 {
    /*height: 36px;*/
    line-height: 36px;
    vertical-align: top;
}

#seriesOverview p {
    overflow-y: auto;
    line-height: 1.6;
    font-size: 1rem;
    color: var(--text-secondary);
    max-height: 175px;
}

#trailer-video {
    aspect-ratio: 3/2;
    height: 245px;
    margin: 0 auto;
    background-size: contain;
    background-repeat: no-repeat;
}

#trailer-play-button-container {
    display: flex;
    width: 90%;
    justify-content: space-between;
    height: 40px;
    padding: 8px;
    padding-left: var(--container-padding);
}

#trailer-play-button-container h3 {
    padding: 5px 8px;
    height: 30px;
    padding-left: var(--container-padding);
}

#trailer-play-button-container div.trailer-play-button {
    font-size: var(--font-size-base);
    line-height: var(20px);
    height: 30px;
    transition: all 0.3s ease-in-out;
    padding-left: 8px;
    padding-right: 8px;
}

#trailer-play-button-container div.trailer-play-button:hover {
    color: var(--accent-color);
    border-color: var(--accent-hover);
    background-color: var(--hover-overlay);
    backdrop-filter: blur(8px);
}

/* --- Seasons & Grid --- */
.seasons-container {
    padding: 0 var(--container-padding) var(--container-padding);
}

.season-block {
    margin-bottom: 3rem;
}

.season-title {
    font-size: 1.2rem;
    color: var(--text-secondary);
    margin-bottom: 1rem;
    border-bottom: 1px solid #333;
    padding-bottom: 0.5rem;
}

.episodes-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--gap-size);
}

.series-card,
.episode-card {
    flex: 0 0 240px;
    position: relative;
    background-color: var(--card-bg);
    border-radius: var(--border-radius);
    transition: transform 0.2s, box-shadow 0.2s;
    overflow: hidden;
}

/* W4.3 (WDF1-4.3) — "some images float over the hero", reported as a defect
   rather than a style preference.

   🔴 The cause, reproduced in a browser before this value was touched: a card
   in the hover state was `z-index: 10` while `.hero-section` is `z-index: 9`,
   and NO ancestor of a card establishes a stacking context — so the two
   competed directly in the root stacking context and the card won. Scrolling a
   hovered card up under the sticky hero painted `img.card-image` OVER it.
   Measured at both 1440x900 and 390x844: at the overlap, elementFromPoint
   returned the card's image, not the hero.

   A hovered card only ever needs to sit above its RESTING SIBLINGS, which are
   `z-index: auto`, so that `scale(1.08)` is not clipped by the next card along.
   It never needed to beat the hero. `z-index: 2` does that job and is what the
   other `.series-card:hover` rule in this file (~line 44) already asks for, so
   the two no longer disagree.

   Checked against everything else that stacks here: .sidebar is 50 (still
   above), .hero-section is 9 (now above a hovered card), the in-card progress
   badge is 4 and lives inside the card, and the 10s at #media-modal .close-btn
   are inside a modal. Nothing else moves.

   ⚠️ The `left: 8px; top: 14px` shift is the "floating" LOOK and is left
   exactly as it was — WDF1-4.3 says that removing or repositioning is the
   owner's choice, and this change did not need to make it. The defect was the
   stacking, not the offset. */
.episode-card:hover,
.series-card:hover {
    transform: scale(1.08);
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
    z-index: 2;
    left: 8px;
    top: 14px;
}

.episode-thumb,
.card-image {
    height: 180px;
    object-fit: cover;
    display: block;
    aspect-ratio: 4/3;
    background-color: #333;
    padding: 8px;
}

/* =========================================
   LOGO FALL-THROUGH ART (.is-logo)
   =========================================

   When a title has no art for a slot, engine/art.resolver.js falls through to
   its logo and reports kind:"logo"; the front end puts `is-logo` on the element
   (see assets/script/portals/quizflix.art.js). Everything below is scoped to
   that class, so it applies ONLY to the logo case — real banners, profile art
   and episode stills keep the framing the theme already gives them.

   A logo is a transparent PNG at the show's own aspect ratio, dropped into a
   container built for a still. Three things follow, whatever the container:

     1. contain, never cover — cropping a wordmark makes it unreadable
     2. centred on both axes — a letterboxed logo pinned to an edge reads as a
        layout bug, not as art
     3. a flat backing behind the transparency, or the page shows through and
        the container's own border-radius/shadow outlines empty space

   Each container below differs only in padding, because they differ in size.
   ----------------------------------------- */

/* Square art: library + search cards, continue-watching cards, episode thumbs. */
.episode-thumb.is-logo,
.card-image.is-logo {
    object-fit: contain;
    object-position: center;
    padding: 18px;
}

/* The 225px square in the series / movie / episode modal header. */
.modal-profile-img.is-logo {
    object-fit: contain;
    object-position: center;
    background-color: #333;
    padding: 20px;
}

/* The 30px circle in the sidebar's sub-lists had a rule here too. It went with
   .nav-thumb itself — the sidebar has no sub-lists to put art in. */

/* The 44px thumbnail on each Your Progress row of the profile screen. */
.profile-progress-row img.is-logo {
    object-fit: contain;
    object-position: center;
    background-color: #333;
    padding: 4px;
}

/* The directory hero. Real banner art is anchored `left top` (see
   .hero-section) so the artwork's subject stays put as the hero scrolls; a
   logo has no subject to anchor, so it is centred in the band instead. */
.hero-section.is-logo {
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}

/* The still behind the trailer player on the directory page. */
#trailer-video.is-logo {
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}

.episode-info {
    padding: 1rem;
}

.episode-name {
    font-weight: bold;
    font-size: 0.95rem;
    margin-bottom: 0.3rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.episode-desc {
    font-size: 0.8rem;
    color: var(--text-secondary);
}

/* Watch-progress badge overlaid on episode cards (T22) */
.episode-badge {
    position: absolute;
    top: 8px;
    right: 8px;
    min-width: 22px;
    height: 22px;
    padding: 0 6px;
    border-radius: 11px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    font-weight: bold;
    color: #fff;
    z-index: 4;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
}

.episode-badge.watched {
    background-color: #2e7d32;
}

.episode-badge.started {
    background-color: var(--accent-color, #E50914);
}

/* --- Modal V2 --- */
.modal {
    display: none;
    position: fixed;
    z-index: 1000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: var(--modal-overlay);
    backdrop-filter: blur(5px);
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.3s ease;
}

.modal.show {
    display: flex;
    opacity: 1;
}

.modal-content {
    background-color: #181818;
    width: 90%;
    max-width: 900px;
    max-height: 90vh;
    border-radius: 8px;
    box-shadow: 0 0 50px rgba(0, 0, 0, 0.8);
    overflow-y: auto;
    animation: slideUp 0.6s ease;
}

@keyframes slideUp {
    from {
        transform: translateY(50px);
        opacity: 0;
    }

    to {
        transform: translateY(0);
        opacity: 1;
    }
}

.modal-body {
    display: flex;
    flex-direction: row;
    padding: 2rem;
    gap: 2rem;
}

/* Modal Left: Image & Buttons */
.modal-left {
    flex: 0 0 300px;
    /* Fixed width for left column */
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

.modal-image-wrapper {
    width: 100%;
    aspect-ratio: 4/3;
    /* 1:1 Square */
    background: #000;
    border-radius: var(--border-radius);
    overflow: hidden;
    border: 1px solid #333;
}

.modal-image-wrapper img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* Crucial Requirement */
}

.modal-actions {
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
}

.action-btn {
    padding: 0.8rem;
    font-size: 1rem;
    border: none;
    border-radius: 4px;
    font-weight: bold;
    transition: background 0.2s, transform 0.1s;
}

.action-btn:active {
    transform: scale(0.98);
}

.action-btn.primary {
    background-color: var(--accent-color);
    color: var(--text-main);
}

.action-btn.primary:hover {
    background-color: var(--accent-hover);
}

.action-btn.secondary {
    background-color: var(--text-main);
    color: black;
}

.action-btn.secondary:hover {
    background-color: rgba(255, 255, 255, 0.8);
}

.action-btn.outline {
    background-color: transparent;
    border: 1px solid #444;
    color: var(--text-secondary);
}

.action-btn.outline:hover {
    border-color: var(--text-main);
    color: var(--text-main);
}

/* Modal Right: Text */
.modal-right {
    flex: 1;
}

.modal-meta-tags {
    color: var(--accent-color);
    font-weight: bold;
    margin-bottom: 1.5rem;
    font-size: 0.9rem;
    text-transform: uppercase;
    letter-spacing: 1px;
}

.modal-summary {
    color: var(--text-secondary);
    margin-bottom: 2rem;
    line-height: 1.4;
    font-size: var(--text-main);
    max-height: 155px;
    overflow-y: scroll;
    color: var(--text-secondary);

}

.modal-extras h4 {
    color: var(--text-main);
    margin-bottom: 0.5rem;
    border-bottom: 1px solid #333;
    padding-bottom: 5px;
}

.vocab-list {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.vocab-list li {
    background: #333;
    padding: 4px 10px;
    border-radius: 15px;
    font-size: 0.85rem;
    color: #ddd;
}

/* --- Mobile Responsiveness V2 --- */
.mobile-menu-btn {
    display: none;
    position: fixed;
    top: 15px;
    left: 15px;
    z-index: 100;
    background: rgba(0, 0, 0, 0.8);
    color: var(--text-main);
    border: none;
    font-size: 24px;
    padding: 5px 10px;
    border-radius: 4px;
}

/* 1. Main Content Wrapper V2 */
#media-modal .modal-content {
    background-color: var(--glass-bg-light);
    backdrop-filter: blur(8px);
    color: var(--text-primary);
    font-family: var(--font-body);
    width: 100%;
    max-width: 850px;
    /* Standard "Netflix" modal width */
    border-radius: var(--border-radius);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
    position: relative;
    /* For positioning the close button */
    overflow: hidden;
    /* Keeps child border-radius in check */
    margin: 2rem auto;
    /* Centers the content vertically/horizontally in the modal wrapper */
}

/* 2. Close Button V2 */
#media-modal .close-btn {
    position: absolute;
    top: 1rem;
    right: 1rem;
    color: var(--text-primary);
    font-size: 2rem;
    line-height: 1;
    z-index: 10;
    background: rgba(0, 0, 0, 0.5);
    width: 36px;
    height: 36px;
    border-radius: 50%;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
}

#media-modal .close-btn:hover {
    background-color: var(--text-primary);
    color: var(--bg-color);
}

/* 3. Header Layout (The Profile + Info area) V2 */
#media-modal .modal-header {
    display: flex;
    align-items: flex-start;
    column-gap: var(--gap-size);
    row-gap: var(--gap-inner-controls);
    justify-content: space-around;
    flex-wrap: wrap;
    padding: var(--container-padding);
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0.7) 0%, var(--card-bg) 100%);
    margin-bottom: 0;
}



#media-modal .modal-header>div {
    width: 50%;
    max-height: 340px;
}

#media-modal .modal-header>div:first-of-type {
    max-width: 303px;
    display: inline-flex;
    flex-wrap: wrap;
    justify-content: space-between;
}


/* 4. The Profile Image V2 */
#modal-profile {
    width: 303px;
    height: auto;
    object-fit: cover;
    aspect-ratio: 4/3;
    margin: 0 auto;
    border-radius: var(--border-radius);
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.5);
    flex-shrink: 0;

}


#modal-go-button,
#modal-play-button {
    position: relative;
    width: 48%;
    height: 28px;
    font-size: 10px;
    text-transform: uppercase;
    font-family: var(--font-heading);
    font-weight: bold;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: var(--fx-transition-all);
    padding-left: 10px;
    padding-right: 10px;
}

#modal-play-button {
    width: 50;
}





/* The cover art is the play control, so the trailer plays in the space the
   cover occupies rather than in a panel of its own: the container sits behind
   the image, exactly over it, and the image fades out to reveal it. */
#media-modal .modal-header>div:first-of-type {
    position: relative;
}

#modal-trailer-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 303px;
    aspect-ratio: 4/3;
    background: #000;
    border-radius: var(--border-radius);
    overflow: hidden;
    display: none;
    align-items: center;
    justify-content: center;
}

#modal-trailer-container.playing {
    display: flex;
}

#trailer-preview {
    width: 100%;
    height: auto;
    border: 0;
    aspect-ratio: 16/9;
}

/* Above the video, and it fades rather than cuts — when the trailer ends the
   cover comes back over the top of it. */
#modal-profile {
    position: relative;
    z-index: 2;
    transition: opacity 0.5s ease;
}

#modal-profile.is-playable {
    cursor: pointer;
}

#modal-profile.trailer-playing {
    opacity: 0;
    pointer-events: none;
}

/* Go to Series clears the cover and sits under its bottom-right corner. */
#modal-go-button {
    width: auto;
    min-width: 140px;
    margin-left: auto;
    margin-top: 14px;
}

/* A step that is not open yet stays visible and stays put — the order of the
   track is the point — but reads as unavailable and does not light up. */
.deck-list-item.locked-item {
    opacity: 0.45;
    cursor: default;
}

.deck-list-item.locked-item:hover {
    background-color: var(--sbl-bg);
    color: var(--text-secondary);
    border-left: 3px solid var(--sbl-tab);
    border-right: none;
    padding-right: 4px;
}

/* 🛑 `.vocab-chip` IS GONE — deleted, not commented out, 2026-08-20. The
   vocabulary column drew a bubble per word until the owner's 3-2 ruling:
   "In the center is a vocabulary column. Remove the words and place 2 options
   similar to the other columns." Nothing emits the class any more
   (modal-columns.js renderVocabularyOptions), so the rules went with it —
   a style for markup that cannot exist is a style the next person has to
   disprove before they can delete it.

   The column's own rule stays: the two options are `.deck-list-item` rows now,
   and they start at the left edge like every other column's rows. */
#media-modal .vocabulary-list {
    justify-content: flex-start;
    column-gap: 6px;
}

#modal-btn-go-to-series {
    max-width: unset;
    flex-wrap: wrap;
    text-align: left;
    gap: 4px;
    position: relative;
    width: 125px;
}

#modal-btn-go-to-series:hover {
    border-left: 65%;
    border-right: solid gold 10px;
}



#modal-btn-go-to-series span {
    display: block;
    width: 100%;
}

#modal-go-to-text {
    height: 12px;
    margin: 0;
}

#modal-go-to-name-text {
    font-size: var(--font-size-base);
    font-weight: bold;
    font-family: var(--font-heading);
}


/* 5. Text Info Area V2 */
#media-modal .modal-info {
    flex: 1;
    /* Takes up remaining space */
    display: flex;
    flex-direction: column;
    justify-content: center;
}

#media-modal #modal-title {
    font-size: var(--font-size-xl);
    font-weight: bold;
    margin: 0 0 0.5rem 0;
    color: var(--text-primary);
}

#media-modal .modal-meta {
    color: var(--text-secondary);
    font-size: var(--font-size-base);
    font-weight: bold;
    margin-bottom: 1rem;
}

#media-modal #modal-summary {
    line-height: height 1.5em;
    margin: 0;
}


#media-modal .modal-header>div>div.activities-container,
#media-modal .modal-header>div>div.exercises-container,
#media-modal .modal-header>div>div.lessons-container {
    border-top: 1px solid #333;
    padding-left: 0;
    width: 31%;
    position: relative;
    max-height: unset;
    overflow: unset;
}

#media-modal .modal-header>div>.deck-list {
    max-height: 125px;
    width: 30%;
    overflow-y: auto;
    overflow-x: hidden;

}

#media-modal .activities-container>h3,
#media-modal .exercises-container>h3,
#media-modal .lessons-container>h3 {
    margin-top: 13px;
    margin-bottom: 1rem;
    text-align: center;
    width: 100%;
    margin-bottom: 1rem;
    border-bottom: 1px solid #333;
    padding-bottom: 0.5rem;
}


#seasonsContainer {
    padding-top: 32px;
}

.category-row {
    padding-left: var(--container-padding);
    width: 96%;
    margin: 1rem auto 3rem auto;
}

.category-row .row-canvas {
    overflow-x: scroll;
    overflow-y: hidden;
    padding: 0;
    margin: 0;
}

.row-title {
    font-size: 30px;
    color: var(--text-primary);
    margin-bottom: 1rem;
    font-weight: bold;
}


#seasonsContainer .scroll-container .episode-card {
    min-height: 350px;
}

#seasonsContainer .scroll-container .episode-card .start-btn {
    float: right;
    bottom: 8px;
    right: 8px;
    padding: 6px;
    position: relative;
    background-color: var(--hover-overlay);
    backdrop-filter: blur(8px);
    color: var(--text-primary);
}

#seasonsContainer .scroll-container .episode-card .start-btn:hover {
    background-color: var(--modal-overlay);
    color: var(--accent-color);
}



.hero-section.exercise-hero {
    height: 30vh;
    background-image: url("../../images/backgrounds/quizflix.gameset.background.png");
    background-repeat: no-repeat;
    aspect-ratio: 2/1;
    width: 100%;
    background-position-y: -59vh;
    background-size: cover;
}

p.hero-starring {
    color: var(--text-secondary);
    margin-top: 1rem;
}

/* =========================================
   3. EXERCISES CSS (series.listening.exercises.css)
   ========================================= */

/* Reuse grid logic but specific for vertical scrolling questions */
.quiz-grid {
    display: flex;
    flex-direction: column;
    gap: var(--gap-size);
    max-width: 800px;
    margin: 0 auto;
}


/* Question Card - Matches .episode-card styling */
.question-card {
    background-color: var(--card-bg);
    border-radius: var(--border-radius);
    padding: 2rem;
    border: 1px solid transparent;
    transition: border-color 0.3s;
}

.question-card h3 {
    font-size: 1.2rem;
    margin-bottom: 1.5rem;
    color: var(--text-primary);
    line-height: 1.4;
}

.question-card h4 {
    font-size: 0.9rem;
    color: var(--accent-color);
    text-transform: uppercase;
    margin-bottom: 1rem;
    letter-spacing: 1px;
}

/* Options Grid */
.options-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Button styles reusing .action-btn logic */
.quiz-btn {
    width: 100%;
    padding: 1rem;
    text-align: left;
    background-color: rgba(255, 255, 255, 0.05);
    border: 1px solid #333;
    color: var(--text-secondary);
    border-radius: 4px;
    transition: all 0.2s;
    font-size: 1rem;
}

.quiz-btn:hover:not(:disabled) {
    background-color: var(--hover-overlay);
    backdrop-filter: blur(8px);
    border-color: var(--text-primary);
    color: var(--text-primary);
}

/* State Classes */
.quiz-btn.correct {
    background-color: #2e7d32 !important;
    /* Success Green */
    color: white !important;
    border-color: #2e7d32 !important;
}

.quiz-btn.wrong {
    background-color: var(--accent-color) !important;
    /* Netflix Red */
    color: white !important;
    border-color: var(--accent-color) !important;
}

.quiz-btn:disabled {
    opacity: 0.7;
}

/* Tense Fill Styles */
.tense-container {
    font-size: 1.1rem;
    line-height: 1.8;
}

.tense-gap {
    display: inline-block;
    min-width: 100px;
    margin: 0 5px;
    text-align: center;
}

.tense-btn-group {
    display: flex;
    gap: 10px;
    margin-top: 10px;
}

.inline-btn {
    padding: 5px 15px;
    border: 1px solid #444;
    background: transparent;
    color: var(--text-secondary);
    border-radius: 15px;

}

.inline-btn:hover {
    border-color: var(--text-main);
    color: var(--text-main);
}

/* Fill In The Blank Styles */
.paragraph-box {
    line-height: 2;
    font-size: 1.1rem;
    color: var(--text-secondary);
    margin-bottom: 1.5rem;
}

.blank-slot {
    border-bottom: 2px solid var(--accent-color);
    color: var(--text-primary);
    padding: 0 5px;
    font-weight: bold;
}

.word-bank {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    padding-top: 1rem;
    border-top: 1px solid #333;
}

.word-chip {
    background-color: #333;
    padding: 8px 16px;
    border-radius: 20px;
    user-select: none;
    transition: background 0.2s;
}

.word-chip:hover {
    background-color: #555;
}

.word-chip.used {
    opacity: 0.3;
    text-decoration: line-through;
}

/* --- View-failure banner (quizflix.trouble.js) ---------------------------
   Shown when a background load fails after the view has already rendered.
   A failure *during* load sends the user to the technical-difficulties page
   instead; this is the non-fatal case, so it must not block the screen. */
.trouble-banner {
    position: fixed;
    left: 50%;
    bottom: 24px;
    transform: translateX(-50%);
    z-index: 200;
    display: flex;
    align-items: center;
    gap: 16px;
    max-width: min(90vw, 620px);
    padding: 12px 16px;
    background-color: #1a1a1a;
    border: 1px solid var(--accent-color);
    border-radius: 4px;
    color: var(--text-primary);
    font-size: 0.9rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
}

.trouble-banner-close {
    background: none;
    border: none;
    color: var(--text-secondary);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}

.trouble-banner-close:hover {
    color: var(--text-primary);
}


/* --- In-view error panel (Trouble.View) ----------------------------------
   Replaces the contents of main.main-content when a view cannot be built, or
   when a control that has nowhere to go yet is clicked. The sidebar is left
   alone, so every route out of the screen survives the failure.

   min-height keeps the panel roughly a screen tall whatever the viewport, so
   the image is not left floating against the top edge of an empty page. */
.error-view {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 1.25rem;
    min-height: 80vh;
    padding: var(--container-padding);
}

/* The technical-difficulties still. `contain` because it is a fixed-ratio
   image being dropped into a container of unknown shape — the same reasoning
   as .is-logo elsewhere. */
.error-hero {
    max-width: min(90%, 640px);
    max-height: 45vh;
    object-fit: contain;
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.7);
}

.error-title {
    font-family: var(--font-heading);
    color: var(--text-primary);
    margin: 0;
}

.error-message {
    color: var(--text-secondary);
    max-width: 52ch;
    margin: 0;
}

.error-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--gap-inner-controls, 12px);
}

/* These actions are anchors, and .btn sets no colour — only .btn-red does, via
   its own rule. Without this the secondary action renders in the browser's
   default link blue. Scoped to the panel so the global button styles are left
   exactly as they are. */
.error-actions .btn {
    color: var(--text-primary);
    cursor: pointer;
}

.error-detail {
    color: var(--text-muted);
    font-size: var(--font-size-sm);
    letter-spacing: 0.5px;
    margin: 0;
}


/* --- Profile screen ------------------------------------------------------ */

/* 🛑 THE WHOLE SET ON ONE LINE (owner, 2026-08-19: "all the stats should fit
   across the screen they are much too large and cumbersome").

   `repeat(auto-fit, minmax(180px, 1fr))` could not do that. auto-fit divides by
   a minimum WIDTH, and it has no idea seven is the whole set — at any window
   narrower than 7 x 180 + gaps it fitted five and dropped two onto a second row,
   which is the "cumbersome" being described. --stat-count is the count itself,
   written by renderStats() from the array it just rendered, so the grid is told
   how many columns to make instead of inferring it. `minmax(0, 1fr)` and not
   `1fr`: a grid track's automatic minimum is its content, so a long label would
   push a column wider than its share and shove the last card off the line.

   ⚠️ The card is smaller as well as narrower, and it has to be — seven columns
   of a 1500px content area are ~190px each, and 1.25rem of padding around a 2rem
   number in a box that size is why they read as heavy. Nothing is truncated:
   the value is 1.35rem and the label wraps to two lines inside the same card.

   The count is IGNORED below 1100px (see the media query at the foot of this
   block). Seven across a phone is not a row. */
.profile-grid {
    display: grid;
    grid-template-columns: repeat(var(--stat-count, 7), minmax(0, 1fr));
    gap: 0.6rem;
    padding: 0 3rem 2rem;
}

.profile-stat {
    background-color: #1a1a1a;
    border: 1px solid #2a2a2a;
    border-radius: 4px;
    padding: 0.8rem 0.85rem;
}

.profile-stat-value {
    font-size: 1.35rem;
    font-weight: bold;
    color: var(--text-primary);
    line-height: 1.1;
}

.profile-stat-label {
    margin-top: 0.3rem;
    color: var(--text-secondary);
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    line-height: 1.35;
}

/* Two sections on one line — Account and Display Name (owner, 2026-08-19: "it
   could be half its current width and another panel be placed beside it").

   The ROW carries the 3rem page gutter and the sections inside it carry none,
   which is what makes each of them exactly half. Doing it the other way — two
   sections keeping their own `padding: 0 3rem` — would put 6rem of gutter down
   the middle of the page and 3rem at each edge, and the two panels would not be
   the same width as the full-width sections above and below them. */
.profile-columns {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2rem;
    padding: 0 3rem 2.5rem;
    align-items: start;
}

.profile-columns .profile-section {
    padding: 0;
}

/* A row of the detail list that holds a CONTROL rather than a value. It is the
   same row — same padding, same rule beneath it, same key on the left — so the
   Display Name panel reads as the Account panel with an input where the text
   would be, which is what "a mirror of the account settings form" means. The
   label is a <label> and not a <span>, so the whole key is a hit target for the
   box beside it. */
.profile-field {
    align-items: center;
}

.profile-field-input {
    flex: 1 1 auto;
    min-width: 0;
    max-width: 60%;
    padding: 0.45rem 0.6rem;
    background-color: #111;
    border: 1px solid #333;
    border-radius: 4px;
    color: var(--text-primary);
    font-family: inherit;
    font-size: 0.95rem;
}

.profile-field-input:focus {
    outline: none;
    border-color: var(--accent-color);
}

/* The word after the Save button. It is in the action row rather than under it
   so that saving does not change the panel's height — the two panels are on one
   line and one of them growing would drag the other's baseline with it. */
.profile-field-note {
    align-self: center;
    font-size: 0.82rem;
}

.profile-section {
    padding: 0 3rem 2.5rem;
}

.profile-section h3 {
    color: var(--text-primary);
    margin-bottom: 1rem;
}

.profile-detail-list {
    list-style: none;
    background-color: #1a1a1a;
    border: 1px solid #2a2a2a;
    border-radius: 4px;
    overflow: hidden;
}

.profile-detail-list li {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.85rem 1.25rem;
    border-bottom: 1px solid #2a2a2a;
    color: var(--text-primary);
    font-size: 0.95rem;
}

.profile-detail-list li:last-child {
    border-bottom: none;
}

.profile-detail-key {
    color: var(--text-secondary);
}

.profile-progress-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.85rem 1.25rem;
    border-bottom: 1px solid #2a2a2a;
    cursor: pointer;
}

.profile-progress-row:last-child {
    border-bottom: none;
}

.profile-progress-row:hover {
    background-color: #222;
}

.profile-progress-row img {
    width: 44px;
    height: 44px;
    border-radius: 4px;
    object-fit: cover;
    flex-shrink: 0;
}

.profile-progress-meta {
    flex: 1;
    min-width: 0;
}

.profile-progress-title {
    color: var(--text-primary);
    font-weight: bold;
}

.profile-progress-sub {
    color: var(--text-secondary);
    font-size: 0.82rem;
    margin-top: 2px;
}

.profile-bar {
    width: 120px;
    height: 6px;
    background-color: #333;
    border-radius: 3px;
    overflow: hidden;
    flex-shrink: 0;
}

.profile-bar span {
    display: block;
    height: 100%;
    background-color: var(--accent-color);
}

/* Below this there is no line to fit seven cards across, so the count is
   dropped and they wrap — auto-fit is the right tool once the whole set is not
   the goal. The two panels stack for the same reason: half of a narrow window
   is not a form width. */
@media (max-width: 1100px) {

    .profile-grid {
        grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    }

    .profile-columns {
        grid-template-columns: minmax(0, 1fr);
        gap: 2.5rem;
    }
}

@media (max-width: 768px) {

    .profile-grid,
    .profile-section,
    .profile-columns,
    .tab-strip,
    .rows-picker,
    .row-size {
        padding-left: 1.25rem;
        padding-right: 1.25rem;
    }

    .profile-field-input {
        max-width: 55%;
    }

    /* Closer together so three or four labels still fit across a phone before
       the strip has to scroll. */
    .tab-strip {
        gap: 1.25rem;
    }
}


/* --- Tag chips ------------------------------------------------------------
   Moved verbatim out of portals/search.html's own <style> block so more than
   one screen can use them: the search filters, the all-tags modal and the
   profile row picker are all the same chip. Nothing here is new. */

.genre-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.genre-chip {
    background: var(--bg-black-flat);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    color: var(--text-muted);
    font-family: var(--font-body);
    font-size: 0.8rem;
    padding: 6px 14px;
    cursor: pointer;
    text-transform: capitalize;
    transition: var(--fx-transition-all);
}

.genre-chip:hover {
    background: var(--hover-overlay);
    color: var(--text-primary);
}

.genre-chip.selected {
    background: var(--accent-color);
    border-color: var(--accent-color);
    color: #fff;
}

/* "More tags" is a .genre-chip too, so it picks up the same hover glow
   as the tags either side of it. Dashed border is the only tell that it
   opens something rather than filtering. */
.genre-chip.more-chip {
    border-style: dashed;
    color: var(--text-primary);
}

.chip-count {
    margin-left: 6px;
    opacity: 0.55;
    font-variant-numeric: tabular-nums;
}

/* --- Chip-picker modal --- */
.tag-modal-content {
    max-width: 720px;
}

.tag-modal-title {
    margin-bottom: 0.25rem;
    padding-right: 2rem;
}

.tag-modal-hint {
    color: var(--text-muted);
    font-size: var(--font-size-sm);
    margin-bottom: 1.25rem;
}

/* .modal-content already scrolls at 90vh; this keeps the heading in
   view and confines the scrolling to the cloud itself. */
.tag-cloud {
    max-height: 55vh;
    overflow-y: auto;
}

/* --- Profile row picker ---------------------------------------------------
   The selected rows, in the order they will appear on the library screen.
   Same surfaces as the rest of the theme: flat black rows, bordered, with the
   accent colour reserved for the control the pointer is on. */

.rows-order-title {
    color: var(--text-primary);
    font-size: 0.95rem;
    margin: 1.5rem 0 0.5rem;
}

.rows-order {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.rows-order li {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--bg-black-flat);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius);
    padding: 8px 12px;
}

.rows-order-name {
    flex: 1;
    color: var(--text-primary);
    font-size: 0.9rem;
}

.rows-order-count {
    color: var(--text-muted);
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
}

.rows-order-move {
    width: 28px;
    height: 28px;
    line-height: 1;
    background: none;
    border: 1px solid var(--border-color);
    border-radius: 4px;
    color: var(--text-muted);
    cursor: pointer;
    transition: var(--fx-transition-all);
}

.rows-order-move:hover:not(:disabled) {
    color: var(--text-primary);
    border-color: var(--accent-color);
}

.rows-order-move:disabled {
    opacity: 0.3;
    cursor: default;
}

.rows-picker {
    padding: 0 3rem 2.5rem;
    max-width: 900px;
}

.rows-picker-hint {
    color: var(--text-muted);
    font-size: var(--font-size-sm);
    margin-bottom: 1.25rem;
}

.rows-picker-empty {
    color: var(--text-muted);
    font-size: var(--font-size-sm);
}

.rows-picker-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    margin-top: 1.5rem;
}

/* Save used to close the modal, and that was the acknowledgement. A panel does
   not close, so the button needs to say something or it looks inert. */
.rows-picker-status {
    color: var(--text-muted);
    font-size: var(--font-size-sm);
}

/* --- Row size (W4B.4, WDF1-3.3) -------------------------------------------
   Three words under the row picker on each library's tab page. WDF1-1.7 governs
   this screen, so this control is chrome-free for the same reason the tab strip
   is: no pill, no border, no background, no box of any kind. The chosen size is
   --text-primary with the app's 3px accent bar under it, the other two are
   --text-muted, and that bar is the only thing painted.

   The bar is an ::after and not a border-bottom. A border is chrome the ruling
   names outright; this is the same 3px accent edge the sidebar's .nav-item.active
   carries and the tab strip's indicator draws — the app's own selected state,
   turned on its side once already and reused here rather than invented again.

   Aligned to .rows-picker's own 3rem gutter so the heading lines up with the
   picker above it and with the tab labels above that. */

.row-size {
    padding: 0 3rem 2.5rem;
    max-width: 900px;
}

.row-size-title {
    color: var(--text-primary);
    font-size: 0.95rem;
    margin: 0 0 0.35rem;
}

.row-size-hint {
    color: var(--text-muted);
    font-size: var(--font-size-sm);
    margin-bottom: 1rem;
}

.row-size-options {
    display: flex;
    flex-wrap: wrap;
    gap: 2rem;
}

.row-size-option {
    position: relative;
    flex: 0 0 auto;
    -webkit-appearance: none;
    appearance: none;
    background: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
    margin: 0;
    /* Bottom only, and it is not spacing: it is the channel the 3px bar sits in,
       the same 0.7rem the tab labels leave for theirs. */
    padding: 0 0 0.7rem;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 0.95rem;
    line-height: 1.2;
    cursor: pointer;
    transition: color 0.2s ease;
}

.row-size-option:hover {
    color: var(--text-primary);
}

.row-size-option.selected {
    color: var(--text-primary);
}

.row-size-option.selected::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background-color: var(--accent-color);
}

/* :focus-visible only — a mouse click must not draw a ring around a control
   whose whole point is that nothing is drawn around it. Keyboard focus still
   shows, which is the case the outline exists for. */
.row-size-option:focus {
    outline: none;
}

.row-size-option:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 4px;
}

.row-size-status {
    display: inline-block;
    margin-top: 1rem;
    color: var(--text-muted);
    font-size: var(--font-size-sm);
}

/* Choose Your Plan, under the Account list it belongs to. It was a hero button
   until the owner removed that row (2026-08-13). */
.profile-section-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 1rem;
}


/* --- Tabs -----------------------------------------------------------------
   WDF1-1.7, owner ruling 2026-08-13: THE TAB IS NOT A BUTTON. No pills, no
   rounded rectangles, no borders, no button chrome of any kind — the labels are
   plain text in a row, the selected one in --text-primary and the rest in
   --text-secondary, and the only thing painted is a 3px accent bar under the
   selected label that slides between them. No box is ever drawn, and there is
   no track under the strip either.

   It is .nav-item.active's 4px accent edge turned on its side, which is what
   makes this read as part of the app rather than as a widget dropped into it.

   The element is still a <button role="tab"> — see quizflix.tabs.js. The chrome
   is stripped here, where appearance belongs; the semantics stay, because a
   strip that cannot be reached from the keyboard is broken rather than clean. */

.tab-strip {
    position: relative;
    display: flex;
    flex-wrap: nowrap;
    /* W4.6 (WDF1-1.8): the space to the left and right of each word lives HERE,
       in the gap, and not in the label's own padding. The accent bar is sized
       from the label's border box — `width = button.offsetWidth` in
       quizflix.tabs.js — so padding on the label would widen the bar past the
       word it underlines, which is the one thing WDF1-1.7 says may never happen.
       A gap is invisible to offsetWidth. 4rem reads as 2rem either side of a
       word; the ends keep the 3rem gutter below, which is .profile-grid's own
       padding and is what keeps the first label flush with the content. */
    gap: 4rem;
    padding: 0 3rem;
    margin: 0 0 2rem;
    /* Never wraps. The bar is positioned from a label's offsetLeft, which is a
       single axis — a second row would leave it under the wrong word. Four
       short labels scroll rather than wrap on a narrow screen. */
    overflow-x: auto;
}

.tab-label {
    flex: 0 0 auto;
    -webkit-appearance: none;
    appearance: none;
    background: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
    margin: 0;
    /* W4.6: top space goes on the label, because padding-top does NOT change
       offsetWidth and so cannot reach the accent bar. The strip sits directly
       under the hero with no margin above it, so before this the words butted
       against it. The 0.7rem at the bottom is not spacing — it is the channel
       the 3px bar sits in, and it is unchanged. */
    padding: 0.75rem 0 0.7rem;
    font-family: var(--font-heading);
    font-size: 1rem;
    letter-spacing: 1px;
    text-transform: uppercase;
    /* Deliberately NOT bold when selected: weight changes a label's width, and
       every label after it would shift sideways on every switch. Colour is the
       whole of the selected state, exactly as the ruling describes it. */
    font-weight: normal;
    /* --text-secondary, as WDF1-1.7's ruling words it. This read --text-muted
       while --text-secondary was broken (quizflix.styles.css:48 declared it as
       a reference to itself, a cycle CSS makes invalid at computed-value time,
       so it came out white). Q15 repaired that declaration to --text-muted at
       :root on 2026-08-14, so the two now resolve to the same #a3a3a3 and this
       is back to naming the variable the ruling names. */
    color: var(--text-secondary);
    white-space: nowrap;
    cursor: pointer;
    transition: color 0.2s ease;
}

.tab-label:hover {
    color: var(--text-primary);
    box-shadow: none;
}

.tab-label.selected {
    color: var(--text-primary);
    box-shadow: none;
}

/* :focus-visible only — a mouse click must not draw a ring around a control
   whose whole point is that nothing is drawn around it. Keyboard focus still
   shows, which is the case the outline exists for. */
.tab-label:focus {
    outline: none;
    box-shadow: none;
}

.tab-label:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 4px;

}

.tab-indicator {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 0;
    height: 3px;
    background-color: var(--accent-color);
    pointer-events: none;
}

/* Added one frame after mount, so the bar is placed under the opening tab
   instead of sliding in from the left edge on every page load. */
.tab-strip.ready .tab-indicator {
    transition: transform 0.25s ease, width 0.25s ease;
}

@media (prefers-reduced-motion: reduce) {
    .tab-strip.ready .tab-indicator {
        transition: none;
    }
}

/* Explicit: a panel is hidden by the `hidden` attribute, and enough resets in
   the wild break the default that it is not worth relying on. */
.tab-panel[hidden] {
    display: none;
}

.tab-panel:focus {
    outline: none;
}

.tab-panel:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 4px;
}
