/* study-mobile.css -- ALL mobile/responsive media queries: FAB, mobile set cards, mobile detail, mobile KLM, mobile study methods */


        /* ===== FAB: Create Set (mobile) ===== */
        /* OLD view-specific FABs, hidden now that the nav has a unified FAB */
        .sets-fab { display:none !important; }
        .review-fab { display:none !important; }
        .klm-mobile-fab-bar { display:none !important; }

        /* ===== MOBILE: SET CARDS ===== */
        @media (max-width: 760px) {
            /* Hide action cards on mobile, the FAB handles creation */
            .action-cards { display: none !important; }

            /* Compact hero section */
            .hero-section { padding: 12px 16px 12px; }
            .hero-title { font-size: 22px !important; margin-bottom: 4px; }
            .hero-sub { display: none; }
            .hero-head { margin-bottom: 12px; }

            /* Mobile collection header (legacy review/klm bars, not the new dashboard header) */
            .mobile-collection-bar { display: flex; align-items: center; gap: 12px; padding: 14px 16px 10px; }
            .mobile-collection-avatar { width: 100%; height: 100%; }
            .mobile-collection-title { font-size: 20px; font-weight: 800; color: var(--study-text); letter-spacing: -0.04em; }
            .mobile-collection-subtitle { display: none; }

            /* ── Simplified mobile dashboard: just show sets ── */
            .hero-section { display: none !important; }
            .hero-title, .hero-sub, .hero-head, .hero-filters { display: none !important; }
            .sets-heading { display: none !important; }
            .folders-toolbar { display: none !important; }
            .sets-header { display: none !important; }
            .sets-section-header { margin: 0 !important; }
            .folder-chips { display: none !important; }
            .folder-create-btn { display: none !important; }

            /* Sets container: full width, no extra padding */
            .sets-container { padding: 8px 12px !important; }
            .sets-grid { margin-top: 18px !important; gap: 10px !important; }
            .sets-grid.grid-view { grid-template-columns: 1fr; }
            .review-landing { padding: 0 12px 24px !important; }
            .review-landing > .mobile-collection-bar { margin: 0 -12px; padding: 14px 16px 10px; }
            /* Push the Review cards down from the mobile header, match
               Study Sets. Padding (not margin) defeats margin-collapse
               weirdness when the parent has padding:0. */
            .review-landing .sets-section { padding: 0 !important; }
            .review-set-grid {
                margin-top: 0 !important;
                padding-top: 22px !important;
                gap: 10px !important;
            }
            .review-landing .sets-search-wrap { margin-bottom: 18px; }
            .mobile-collection-search { display: none; margin-top: 4px; }
            .mobile-collection-search.is-open { display: flex; }

            /* Clean set cards */
            .set-card, .review-set-row { flex-direction: row; align-items: center; gap: 14px; padding: 14px 16px; border-radius: 14px; }
            /* Badge base: sizing only. Colors come from the scholar-set-badge--* tone
               classes in study-themes.css. */
            .review-set-badge { flex-shrink: 0; }
            .review-set-main { gap: 14px; }
            .review-set-info h4 { font-size: 15px; font-weight: 700; line-height: 1.3; margin-bottom: 2px; }
            .review-set-meta { font-size: 11px; }
            .review-set-methods { display: none !important; }
            .review-set-actions { position: absolute; top: 50%; right: 12px; transform: translateY(-50%); }
            .set-card-methods { display: none !important; }
            .set-card-progress { display: none !important; }
            .set-card-badges { display: none !important; }
            .method-icon-sm { display: none !important; }
            .set-card-more { position: absolute; top: 12px; right: 12px; }
            .set-card-subject { font-size: 11px; padding: 3px 8px; border-radius: 6px; }
            .set-card-meta { font-size: 11px; color: var(--study-text-tertiary); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
            .mobile-empty-prompt { min-height: 0; }
            /* Empty-state on Sets: hide the standalone "+ Create new set"
               pill AND its 50px-top-margin wrapper so the peach card sits
               flush against the topbar (matches Review's empty layout).
               Also drop the .sets-section's 20px horizontal padding so
               the card's 18px outer margin lands edge-to-edge like
               Review's #reviewLanding parent does. Both reverse
               automatically the moment the user creates their first set
               (renderSets removes .is-empty-scroll-lock when sets > 0). */
            #view-sets.is-empty-scroll-lock .mobile-dashboard-heading-row,
            #view-sets.is-empty-scroll-lock #mobileDashboardCreate,
            #view-review.is-empty-scroll-lock .mobile-dashboard-heading-row,
            #view-review.is-empty-scroll-lock .mobile-dashboard-create,
            #view-solve.is-empty-scroll-lock .mobile-dashboard-heading-row,
            #view-solve.is-empty-scroll-lock .mobile-dashboard-create { display: none !important; }
            #view-sets.is-empty-scroll-lock .sets-section { padding: 0 !important; }

            /* Suppress the desktop-style "Review & Learn" hero strip on
               the Review tab. renderReviewDemoLanding (study.js:15267)
               emits a .review-landing-header wrapper with INLINE
               `display:flex` styling for Recent / Filter pills + a hero
               title, those bypass the .hero-section / .hero-title
               hide rules above because mobile CSS targets the wrapper,
               not this parent. Reported by James during a rapid
               Review↔Sets tab swap: the desktop hero leaked through.
               The .action-cards row beneath it is already hidden on
               mobile (line 13). The Your-Sets section header that
               renderReviewDemoLanding paints also hides since
               renderReviewLanding produces a clean section without it
               on the proper mobile path. */
            #view-review .review-landing-header,
            #view-review .review-landing-section-head { display: none !important; }
            /* Stop iOS rubber-band on the mobile landing views so the page
               doesn't "scroll to white" when there's nothing to scroll. Scroll
               still works when content actually exceeds the viewport. The rule
               is applied to the whole chain (html/body → layout → view) so
               the bounce can't leak through at any level. */
            html, body {
                overscroll-behavior: none !important;
            }
            .study-layout, .study-main {
                overscroll-behavior: none !important;
            }
            #view-sets, #view-review, #view-solve, #view-klm, .study-view {
                overscroll-behavior: none !important;
                -webkit-overflow-scrolling: auto;
            }
            /* When a landing view has no content worth scrolling, JS adds
               .is-empty-scroll-lock to the view container and we turn off
               scrolling entirely so the bounce can't happen. */
            .study-view.is-empty-scroll-lock {
                overflow: hidden !important;
            }
        }

        @media (max-width: 760px) {
            .lecture-recorder { justify-content: flex-end; padding: 0; background: rgba(0,0,0,0.4); }
            .lr-sheet { width: 100%; max-width: none; min-height: 60vh; border-radius: 24px 24px 0 0; border-bottom: none; padding: 12px 24px calc(32px + env(safe-area-inset-bottom, 0px)); background: #1a1a1a; }
            .lr-sheet-handle { width: 40px; height: 5px; border-radius: 99px; background: rgba(255,255,255,0.2); margin: 0 auto 16px; }
            .lr-brand { display: flex; align-items: center; justify-content: center; gap: 8px; margin-bottom: 20px; }
            .lr-brand-icon { width: 28px; height: 28px; border-radius: 8px; }
            .lr-brand span { font-size: 16px; font-weight: 800; color: #fff; letter-spacing: -0.02em; }
            .lr-captions-wrap { flex: 1; max-height: none; min-height: 0; border-radius: 0; background: transparent; padding: 0; }
            .lr-captions-wrap .lr-placeholder { margin-top: 0; text-align: left; font-size: 15px; color: rgba(255,255,255,0.35); font-style: italic; }
            /* Waveform visualization */
            .lr-waveform { display: flex; align-items: center; justify-content: center; gap: 2px; height: 40px; margin: auto 0 24px; overflow: hidden; }
            .lr-waveform-dot { width: 3px; border-radius: 99px; background: rgba(255,255,255,0.15); transition: height 0.1s; min-height: 4px; }
            .lr-meta { margin: 0 0 20px; display: flex; align-items: center; justify-content: space-between; }
            .lr-indicator { display: flex; align-items: center; gap: 8px; }
            .lr-dot { width: 10px; height: 10px; border-radius: 50%; background: #ef4444; }
            .lr-status { font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.7); }
            .lr-timer { font-size: 16px; font-weight: 700; color: rgba(255,255,255,0.5); font-variant-numeric: tabular-nums; }
            .lr-controls { gap: 16px; margin-top: 0; justify-content: center; }
            .lr-btn { width: 64px; height: 64px; padding: 0; border-radius: 50%; flex-direction: column; gap: 0; }
            .lr-btn i { width: 24px; height: 24px; }
            .lr-btn-pause { background: rgba(255,255,255,0.1); }
            .lr-btn-stop { width: 64px; height: 64px; background: #ef4444; box-shadow: 0 8px 24px rgba(239,68,68,0.3); }
            .lr-link-cancel { display: block; margin-top: 16px; font-size: 14px; color: rgba(255,255,255,0.35); background: none; border: none; cursor: pointer; font-family: inherit; }
            .lr-processing { min-height: min(52vh, 460px); }
        }

        /* ===== MOBILE: Hide bottom nav in detail view ===== */
        @media (max-width: 760px) {
            body.in-detail .mobile-nav { display: none !important; }
            /* Hide mastery pills */
            .mastery-pills { display: none !important; }
            .mastery-scope-chips { display: none !important; }
            /* Slim detail topbar, account for iOS notch */
            .detail-topbar, .detail-topbar.visible { height: auto !important; min-height: 44px !important; padding: calc(env(safe-area-inset-top, 0px) + 4px) 12px 4px !important; border-bottom: 1px solid rgba(0,0,0,0.06) !important; }
            .detail-topbar-right { display: none !important; }
            .mobile-method-nav { border-bottom: none !important; }
            /* Detail layout: fullscreen */
            .detail-layout { padding: 0 !important; gap: 0 !important; }
            /* Hide settings/mode buttons */
            .fc-mode-btn[onclick*="Settings"], .fc-mode-btn[onclick*="openTest"] { display: none !important; }
            .fc-mode-btns { gap: 6px !important; padding: 8px 12px !important; flex-wrap: wrap; }
            .fc-mode-btn { font-size: 12px !important; padding: 6px 12px !important; }
            .mastered-link { display: none !important; }
            .review-filter-compact { font-size: 12px; }
        }

        /* ===== MOBILE: Create Wizard fullscreen ===== */
        @media (max-width: 760px) {
            .modal-overlay { padding: 0; align-items: stretch; }
            .modal { max-width: 100%; max-height: 100%; border-radius: 0; height: 100%; }
            .modal-header { padding: calc(16px + env(safe-area-inset-top, 0px)) 20px 14px; }
            .modal-header h3 { font-size: 18px; }
            .modal-body { padding: 20px; }
            .wizard-step h4 { font-size: 16px; }
            .dropzone { padding: 32px 20px; border-radius: 14px; }
            .dropzone-title { font-size: 13px; }
            .methods-grid { grid-template-columns: 1fr 1fr; gap: 8px; }
            .method-card { padding: 16px 10px; min-height: 80px; gap: 6px; }
            .method-card-label { font-size: 12px; }
            .btn-wizard { border-radius: 14px; padding: 16px; font-size: 15px; }
            .url-input-wrap { border-radius: 12px; }
            .url-input-wrap input { font-size: 14px; padding: 12px 0; }
        }

        /* ===== MOBILE: Notes/PDF/StudyGuide UI fixes ===== */
        @media (max-width: 760px) {
            /* 1. Hide notes formatting toolbar on mobile */
            .ql-toolbar.ql-snow { display: none !important; }

            /* 2. PDF/Content viewer: fit to screen */
            .pdf-viewer-wrap { height: 100% !important; }
            .pdf-canvas-area { padding: 4px !important; }
            .pdf-canvas-area canvas { max-width: 100% !important; height: auto !important; }
            .pdf-toolbar { padding: 4px 8px !important; gap: 4px !important; font-size: 12px; flex-wrap: wrap; }
            .pdf-toolbar button { padding: 4px 6px !important; font-size: 11px !important; }
            .pdf-page-info { font-size: 12px !important; }
            .content-tab-pills { font-size: 11px; overflow-x: auto; flex-wrap: nowrap; gap: 4px !important; padding: 4px 8px !important; }
            .content-tab-pill { white-space: nowrap; font-size: 11px !important; padding: 5px 10px !important; }

            /* 3. Study guide task stages (Ask Why/Review/Reason/Results) */
            .sg-task-stages { gap: 2px !important; overflow-x: auto; flex-wrap: nowrap; padding: 0 4px; }
            .sg-stage { padding: 6px 10px !important; font-size: 11px !important; white-space: nowrap; flex-shrink: 0; }
            .sg-task-modal { padding: 12px !important; }
            .sg-task-title { font-size: 15px !important; }

            /* 4. Study guide lesson nav (bottom steps) */
            .sg2-lesson-nav { padding: 8px 12px !important; gap: 4px !important; overflow-x: auto; flex-wrap: nowrap; }
            .sg2-lesson-nav-item { font-size: 11px !important; padding: 6px 10px !important; white-space: nowrap; flex-shrink: 0; }

            /* 5. Notes content cleanup */
            .ql-editor { padding: 16px 14px !important; font-size: 15px !important; }
            .ql-editor h1 { font-size: 22px !important; }
            .ql-editor h2 { font-size: 18px !important; }

            /* 6. Study guide content formatting */
            .sg2-step-detail { font-size: 14px !important; line-height: 1.65 !important; }
            .sg2-step-detail h2, .sg2-step-detail h3 { font-size: 17px !important; margin-top: 20px !important; margin-bottom: 8px !important; }
            .sg2-step-detail ul, .sg2-step-detail ol { padding-left: 20px !important; }
            .sg2-step-detail li { margin-bottom: 6px !important; }
            .sg2-step { padding: 12px 0 !important; }
            .sg2-step-list { padding: 0 12px !important; }

            /* 7. Flashcards: fill the screen */
            .fc-container { padding: 0 12px !important; }
            .fc-header { margin-bottom: 8px !important; padding: 0 !important; }
            .fc-header-left { gap: 2px !important; }
            .fc-set-title { font-size: 13px !important; }
            .fc-counter { font-size: 16px !important; }
            .fc-card-wrap { aspect-ratio: auto !important; max-height: none !important; min-height: 0 !important; flex: 1; margin-bottom: 12px !important; }
            .fc-card { border-radius: 16px !important; }
            .fc-face { padding: 20px 16px !important; border-radius: 16px !important; }
            .fc-text { font-size: 17px !important; }
            .fc-card-tag { top: 10px !important; left: 12px !important; font-size: 9px !important; }
            .fc-hint { bottom: 10px !important; font-size: 10px !important; }
            .fc-bottom-bar { padding: 6px 0 0 !important; }
            .fc-actions { gap: 6px !important; }
            .fc-btn { padding: 8px 0 !important; font-size: 11px !important; border-radius: 10px !important; min-width: 70px; }
            .fc-btn i { width: 18px !important; height: 18px !important; }
            .card-nav { padding: 8px 0 !important; gap: 12px !important; }
            .fc-bottom-hint { display: none !important; }
            /* Hide the deck-progress bar on mobile for flashcards +
               multiple choice, the "1 / 56" counter beside the deck
               title already conveys position; the orange fill bar was
               redundant and clipped under the sticky method nav. */
            .fc-progress-bar { display: none !important; }
            /* Hide the mastery bar (red/amber/green/gray segmented bar
               that sits above the question/card on mobile). James:
               "get rid of this orange bar on mobile", at 100%
               unfamiliar (#ef4444) it reads as a wide red-orange band.
               Stat counts and the "1 / 144" counter already convey
               progress; the bar is desktop-only now. */
            .mastery-pills-row,
            .mastery-bar-wrap { display: none !important; }
        }

        /* ===== MOBILE: KLM NotebookLM-style redesign ===== */
        .klm-mobile-tabs { display: none; }
        @media (max-width: 760px) {
            body.capacitor-app #view-klm,
            body.mobile-app #view-klm,
            body.capacitor-app #view-solve,
            body.mobile-app #view-solve {
                padding-top: 0 !important;
            }
            /* Background is light-theme only. Without the [data-scheme="light"]
               scope the ID-level specificity (0,1,1,1) won over every dark
               override and forced #fff in dark mode, which is why James saw
               a white Khio LM page even after picking Dark in the menu. */
            body.capacitor-app[data-scheme="light"] #view-klm,
            body.mobile-app[data-scheme="light"] #view-klm,
            body.capacitor-app[data-scheme="light"] #view-solve,
            body.mobile-app[data-scheme="light"] #view-solve {
                background: #ffffff !important;
            }
            body.capacitor-app .study-layout.klm-notebook-open #view-klm,
            body.mobile-app .study-layout.klm-notebook-open #view-klm,
            body.capacitor-app .study-layout.klm-notebook-open #view-solve,
            body.mobile-app .study-layout.klm-notebook-open #view-solve {
                padding-top: env(safe-area-inset-top, 0px) !important;
            }
            /* Scoped to [data-scheme="light"] so dark/Mono/Ember themes
               can paint their own backgrounds. Without this, .klm-layout/
               .klm-center forced white inside Khio LM picker even after
               #view-solve was made theme-aware, the inner wrappers were
               still painting white over the dark parent. */
            body.capacitor-app[data-scheme="light"] #view-klm .klm-layout,
            body.mobile-app[data-scheme="light"] #view-klm .klm-layout,
            body.capacitor-app[data-scheme="light"] #view-solve .klm-layout,
            body.mobile-app[data-scheme="light"] #view-solve .klm-layout,
            body.capacitor-app[data-scheme="light"] #view-klm .klm-center,
            body.mobile-app[data-scheme="light"] #view-klm .klm-center,
            body.capacitor-app[data-scheme="light"] #view-solve .klm-center,
            body.mobile-app[data-scheme="light"] #view-solve .klm-center,
            body.capacitor-app[data-scheme="light"] #view-klm .klm-chat-area,
            body.mobile-app[data-scheme="light"] #view-klm .klm-chat-area,
            body.capacitor-app[data-scheme="light"] #view-solve .klm-chat-area,
            body.mobile-app[data-scheme="light"] #view-solve .klm-chat-area {
                background: #ffffff !important;
            }
        }
        @media (max-width: 760px) {
            /* ── KLM Picker: NotebookLM-style ── */
            .klm-picker-header { display: none !important; }
            .klm-picker-inner { padding: 0 !important; width: 100% !important; }
            .klm-layout.picker-mode .klm-picker { padding: 0 !important; max-width: 100% !important; width: 100% !important; display: block !important; }
            /* Khio LM picker: kill the 8px padding + bg-tertiary tint on .klm-layout
               so the header + picker sit flush against .study-main like the other tabs.
               This removes the "white bar" at the top of the Khio LM tab caused by the
               .klm-layout wrapper having its own background that was lighter than
               .study-main. */
            .klm-layout.picker-mode {
                background: transparent !important;
                padding: 0 !important;
                gap: 0 !important;
            }
            /* #klmMobileHeader is now injected as a DIRECT child of #view-solve,
               above .klm-layout (see public/js/study/study-klm.js). #view-solve
               is already `display: flex; flex-direction: column` when active
               (via .study-view.active), so children stack naturally. All we
               need to do is stop .klm-layout from grabbing 100% height away
               from the header, switch it to flex:1/min-height:0 in
               picker-mode only, scoped to #view-solve so we don't touch the
               notebook-open layout.
               PREVIOUS VERSION of this rule also set
               `display: flex !important` on #view-solve itself, which
               OVERRODE `.study-view { display: none }` for the inactive
               state and caused #view-solve to render on TOP of every other
               tab (Sets, Review, etc.). Do NOT add a display override here. */
            #view-solve > .klm-layout.picker-mode {
                flex: 1 1 auto !important;
                height: auto !important;
                min-height: 0 !important;
            }
            /* Khio LM header block, transparent so it inherits .study-main's bg
               (same behavior as the Sets and Review dashboards). */
            #klmMobileHeader {
                width: 100%;
                background: transparent !important;
                flex-shrink: 0;
                position: relative;
                z-index: 2;
            }
            #klmMobileHeader .mobile-dashboard-header { display: flex !important; }
            /* ── Shared usage bar, IDENTICAL sizing and spacing on Sets, Review, Khio LM ── */
            /* Full-bleed: bar spans 100vw regardless of parent padding, so the
               X/25 sets text sits at exactly 16px from the viewport edge on all tabs */
            #studyUsageBar,
            #reviewLanding .mobile-dashboard-header + .study-usage-bar,
            #klmMobileHeader .study-usage-bar {
                display: flex !important;
                width: 100vw !important;
                max-width: 100vw !important;
                margin-left: calc(50% - 50vw) !important;
                margin-right: calc(50% - 50vw) !important;
                margin-top: 0 !important;
                margin-bottom: 16px !important;
                padding: 2px 16px 14px !important;
                gap: 12px !important;
                border-bottom: 1px solid rgba(0, 0, 0, 0.12) !important;
                box-sizing: border-box !important;
            }
            .klm-picker-grid {
                grid-template-columns: 1fr !important; gap: 10px !important;
                margin-top: 0 !important;
                padding: 22px 16px 8px !important;
                width: 100% !important; max-width: 100% !important;
                box-sizing: border-box !important;
                overflow-x: hidden !important;
            }

            /* Kill the off-color "discoloration strip" below picker content
               on mobile for Study Sets, Review, and Khio LM. Body bg is
               #fafafa (lavender-grey) but each picker's inner container
               paints white. Once the cards run out, the grey body peeks
               through below, reads as a banner at the bottom of the
               screen. Extending white all the way out to study-main /
               body on these three views (mobile only) makes the whole
               viewport one continuous color. Scoped per-view via the
               id selectors so detail/tutor/grade/focus views keep their
               own backgrounds. */
            /* Scoped to [data-scheme="light"] so dark/Mono/Ember themes
               can paint their own backgrounds. Without the scope this
               unconditionally forced #fff on Review/Khio LM/Solve/Sets,
               which combined with dark-theme text color (#f4f4f5) made
               titles invisible on dark themes (rgb(244,244,245) on white). */
            body.mobile-app[data-scheme="light"],
            body.mobile-app[data-scheme="light"] .study-layout,
            body.mobile-app[data-scheme="light"] .study-main,
            body.mobile-app[data-scheme="light"] #view-sets,
            body.mobile-app[data-scheme="light"] #view-review,
            body.mobile-app[data-scheme="light"] #view-solve,
            body.mobile-app[data-scheme="light"] #view-klm { background: #ffffff !important; }
            body.mobile-app[data-scheme="light"] .klm-layout.picker-mode { background: #ffffff !important; }
            /* Bug #5: close the gap between the mobile header and the notebook cards */
            #klmMobileHeader .study-usage-bar { margin-bottom: 8px !important; padding-bottom: 10px !important; }
            #klmMobileHeader .mobile-dashboard-header { padding: calc(env(safe-area-inset-top, 0px) + 10px) 20px 6px !important; }
            /* Bug #4: when demo cards use the review-set-row layout the grid
               needs to render as a flat column (no grid columns) so rows stretch full width */
            .klm-picker-grid.klm-picker-grid-rows {
                display: flex !important; flex-direction: column !important;
                grid-template-columns: none !important; gap: 10px !important;
            }
            .klm-picker-grid.klm-picker-grid-rows .review-set-row { width: 100% !important; }
            /* Hide create cards on mobile (moved to FAB) */
            .klm-picker-card-create { display: none !important; }
            /* Notebook cards: IDENTICAL to study set cards.
               Forced width/box-sizing prevents the card overflowing the
               viewport on narrow phones (the symptom was an orange-ish
               curve bleeding off the left edge, turned out to be the
               iOS -webkit-tap-highlight-color rendering through the
               radial blob underneath the card content during touch).
               outline + tap-highlight-color suppression keeps the card
               flat-clean on iOS. */
            .klm-picker-card, .klm-picker-card:hover {
                flex-direction: row !important; align-items: center !important; text-align: left !important;
                aspect-ratio: unset !important; min-height: auto !important;
                padding: 19px 16px !important; gap: 14px !important;
                border-radius: 14px !important; border: 1px solid rgba(0,0,0,0.06) !important;
                box-shadow: 0 1px 4px rgba(0,0,0,0.03) !important; justify-content: flex-start !important;
                background: var(--bg-card, #fff) !important; transform: none !important;
                width: 100% !important; max-width: 100% !important;
                box-sizing: border-box !important; overflow: hidden !important;
                -webkit-tap-highlight-color: transparent !important;
                outline: none !important;
            }
            .klm-picker-card:active { opacity: 0.8 !important; background: var(--bg-card, #fff) !important; }
            .klm-picker-card:focus, .klm-picker-card:focus-visible { outline: none !important; }
            /* Defensive: kill any transition / animation / will-change on the
               KLM picker rows on mobile. Prevents the "bouncing card" report
               James saw, iOS Safari can re-trigger transitions when the
               --khio-kbh CSS var or body bg flips during URL-bar scroll
               collapse, and any non-instant transition on the card or its
               parents can cause it to visually pulse up and down. */
            .klm-picker-row, .klm-picker-card,
            .klm-picker-grid, #klmPickerGrid,
            .klm-picker-inner, #klmPicker,
            .klm-center, .klm-layout.picker-mode {
                transition: none !important;
                animation: none !important;
                will-change: auto !important;
            }
            /* Belt-and-suspenders: blob is already hidden, but stamp it out
               in case any specific path forgets the !important. */
            .klm-card-blob, .klm-card-footer { display: none !important; visibility: hidden !important; }
            .klm-picker-card-emoji { font-size: 28px !important; margin-bottom: 0 !important; flex-shrink: 0; width: 42px; height: 42px; display: flex; align-items: center; justify-content: center; }
            .klm-picker-card-info { flex: 1; min-width: 0; }
            .klm-picker-card-title { font-size: 15px !important; font-weight: 700 !important; line-height: 1.3 !important; color: #1a1a1a !important; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 2px !important; }
            .klm-picker-card-meta { font-size: 11px !important; margin-top: 0 !important; color: rgba(0,0,0,0.35) !important; }
            .klm-card-icon { width: 42px !important; height: 42px !important; min-width: 42px !important; min-height: 42px !important; margin-bottom: 0 !important; flex-shrink: 0; border-radius: 12px !important; display: flex !important; align-items: center !important; justify-content: center !important; }
            .klm-card-icon i { width: 20px !important; height: 20px !important; }
            .klm-card-blob { display: none !important; }
            .klm-card-footer { display: none !important; }
            .klm-picker-card-menu { top: 50% !important; right: 12px !important; transform: translateY(-50%) !important; opacity: 0.3 !important; }
            /* Usage bar hidden */
            #klmUsageBar { display: none !important; }
            /* Mobile FAB */
            .klm-mobile-fab { display: none; }
            .klm-layout.picker-mode .klm-mobile-fab {
                display: flex; position: fixed; bottom: calc(64px + env(safe-area-inset-bottom, 0px) + 16px);
                left: 50%; transform: translateX(-50%); z-index: 100; gap: 10px;
            }
            .klm-mobile-fab-create {
                display: flex; align-items: center; gap: 8px; padding: 14px 24px;
                background: var(--study-accent, #e8853a); border: none; border-radius: 999px;
                font-size: 15px; font-weight: 700; color: #fff; cursor: pointer;
                font-family: inherit; box-shadow: 0 4px 16px rgba(232,133,58,0.3);
            }
            .klm-mobile-fab-create:active { transform: scale(0.96); }
            .klm-center-topbar { padding: 8px 12px !important; height: 44px !important; }
            /* KLM add source modal must be above the fullscreen panels */
            .klm-add-modal { position: fixed !important; z-index: 300 !important; }
            /* When a notebook is open, hide the mobile picker header. The
               header now lives as a sibling of .klm-layout (direct child of
               #view-solve), so the old descendant selector
               `.klm-layout:not(.picker-mode) #klmMobileHeader` never matches.
               Key off the study-layout class that is toggled on open. */
            .study-layout.klm-notebook-open #klmMobileHeader { display: none !important; }
            /* Center panel takes full width in notebook mode */
            .klm-layout:not(.picker-mode) .klm-center { width: 100% !important; border-radius: 0 !important; }
            /* Input bar fixed at bottom above tabs, solid white strip so the pill blends.
               Adds var(--khio-kbh, 0px) so when the on-screen keyboard opens the input
               lifts above it instead of being covered. study-core.js sets that var via
               visualViewport.resize and toggles body.khio-kb-open. */
            .klm-layout:not(.picker-mode) .klm-input-wrap {
                position: fixed !important; bottom: calc(48px + env(safe-area-inset-bottom, 0px) + var(--khio-kbh, 0px)) !important;
                left: 0 !important; right: 0 !important; z-index: 160 !important;
                padding: 10px 12px 6px !important; max-width: 100% !important;
                background: #ffffff !important;
                border-top: none !important;
                transition: bottom 0.18s ease;
            }
            /* When the keyboard is open the bottom tab bar is already covered by the
               keyboard, so collapse the 48px tab-strip offset and lift the input flush
               to the visual viewport bottom. Also hide the tabs themselves so a half-
               visible strip doesn't peek out.

               Don't add safe-area-inset-bottom here, when the keyboard is up the
               home indicator is hidden, and iOS reports keyboardHeight EXCLUDING
               that area. Adding env() back in leaves a ~34px white gap between the
               input bar and the top of the keyboard. */
            body.khio-kb-open .klm-layout:not(.picker-mode) .klm-input-wrap {
                bottom: var(--khio-kbh, 0px) !important;
            }
            body.khio-kb-open .klm-mobile-tabs,
            body.khio-kb-open .study-layout.klm-notebook-open .klm-mobile-tabs,
            body.khio-kb-open .klm-mobile-tabs.visible { display: none !important; }
            /* Anchor chat messages to the BOTTOM of the chat area on mobile
               so when there's only a message or two, they sit right above
               the input/keyboard instead of stranded at the top with a huge
               empty gap below. margin-top:auto on the first message in a
               flex column does exactly that, content gets pushed down by
               the auto margin filling all remaining space, but a long
               conversation still scrolls naturally because once content
               overflows the auto margin collapses to 0. */
            /* Only push messages to the bottom when there are actual chat
               messages. Without :has(), the previous rules pushed the lone
               summary card to the middle of an empty container, creating
               a huge empty gap above the notebook icon on first open. With
               :has(.klm-msg) the rule is gated on a real chat message
               existing, opens with just the summary now sit at the top
               naturally. */
            /* Removed: the justify-content: flex-end + margin-top: auto
               rules. They created two bugs at once, short conversations
               had a huge gap above the summary card, and longer ones had
               their overflow pushed off the top of the scroll area where
               the user couldn't reach it by scrolling up. Natural top-to-
               bottom flow handles both cases cleanly. */
            /* Ensure the final message is never hidden behind the fixed
               input bar. Padding only needs to clear the input-bar height +
               safe-area, NOT the keyboard. When the keyboard opens we
               instead shrink .klm-chat-area's height by --khio-kbh below
               (so messages physically can't render in the keyboard region),
               which means the user can't scroll into a tall pad of empty
               whitespace ("infinite scroll past the bottom"). */
            /* Bottom buffer below the chat. The fixed input bar sits in
               its own row BELOW .klm-messages, not overlapping it, so we
               only need a small visual breathing-room buffer here, not
               the old "clear-the-input-bar" 110px buffer that showed up
               as a huge white gap at scroll-bottom. */
            .klm-layout:not(.picker-mode) .klm-messages {
                padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px)) !important;
            }
            .klm-layout:not(.picker-mode) #klmChatMessages {
                padding-bottom: 0 !important;
            }
            /* Shrink the chat area so its bottom edge sits at the top of
               the on-screen keyboard. Without this the container fills the
               full webview height and content can scroll into the area
               that's visually covered by the keyboard, which combined
               with our padding-bottom buffer feels like infinite scroll. */
            body.khio-kb-open .klm-layout:not(.picker-mode) .klm-chat-area,
            body.khio-kb-open .klm-layout:not(.picker-mode) .klm-center,
            body.khio-kb-open .study-layout.klm-notebook-open #view-klm {
                max-height: calc(100dvh - var(--khio-kbh, 0px)) !important;
                height: calc(100dvh - var(--khio-kbh, 0px)) !important;
            }
            /* Same lift for any other fixed-bottom mobile UI that hosts an input. */
            body.khio-kb-open .klm-mobile-fab { display: none !important; }
            /* Also make the notebook-mode layout fully white so there's no cream/beige tint */
            .study-layout.klm-notebook-open .klm-layout { background: #ffffff !important; }
            .study-layout.klm-notebook-open .klm-center,
            .study-layout.klm-notebook-open .klm-chat-area { background: #ffffff !important; }
            .klm-layout:not(.picker-mode) .klm-input-card {
                background: #ffffff !important;
                border: 1px solid rgba(0,0,0,0.06) !important;
                border-radius: 14px !important; padding: 10px 16px !important;
            }
            /* Disclaimer row below input, also white */
            .klm-layout:not(.picker-mode) .klm-input-disclaimer {
                background: #ffffff !important;
            }
            /* Bottom tabs also white to match */
            .study-layout.klm-notebook-open .klm-mobile-tabs,
            .klm-mobile-tabs.visible { background: #ffffff !important; }
            /* Messages area: align top, not centered.
               IMPORTANT: do NOT use the `padding` shorthand here, the
               padding-bottom set by the rule above
               (calc(110px + safe-area)) needs to survive. Using shorthand
               would clobber it and the last messages would bleed past the
               lifted input bar (= AI reply tail "different topic." poking
               out below the disclaimer). */
            .klm-layout:not(.picker-mode) .klm-messages {
                padding-top: 12px !important;
                padding-left: 14px !important;
                padding-right: 14px !important;
                align-items: stretch !important;
                justify-content: flex-start !important;
                overflow-x: hidden !important; max-width: 100vw !important;
            }
            /* Block horizontal scroll anywhere inside KLM on mobile */
            .klm-layout, .klm-layout .klm-center, .klm-layout .klm-chat-area,
            .klm-layout .klm-sources, .klm-layout .klm-source-detail,
            .klm-layout .klm-source-detail-body, .klm-layout .klm-source-detail-content {
                overflow-x: hidden !important; max-width: 100% !important;
            }
            .klm-msg-ai-body, .klm-msg-user-bubble {
                max-width: 100% !important; overflow-x: hidden !important;
                overflow-wrap: break-word !important; word-break: break-word !important;
            }
            .klm-msg-ai-body img, .klm-msg-ai-body video, .klm-source-detail-content img {
                max-width: 100% !important; height: auto !important;
            }
            .klm-msg-ai-body table { table-layout: fixed !important; width: 100% !important; max-width: 100% !important; }
            .klm-msg-ai-body pre { overflow-x: auto !important; overflow-y: hidden !important; max-width: 100% !important; }
            /* Summary: no extra padding, text at top */
            .klm-summary-wrap { margin-bottom: 16px !important; }
            .klm-summary-header-title { font-size: 20px !important; }
            .klm-summary-card { font-size: 14px !important; line-height: 1.7 !important; }
            /* Hide the promo bar on mobile */
            .kf-promo-bar { display: none !important; }
            /* KLM chat text formatting */
            /* Hide AI message icon (black dot / cat loader) on mobile */
            .klm-msg-ai-icon { display: none !important; }
            .klm-msg-ai { gap: 0 !important; }
            .klm-msg-ai-body { font-size: 15px !important; line-height: 1.7 !important; }
            .klm-msg-ai-body p { margin-bottom: 12px !important; }
            .klm-msg-ai-body ul, .klm-msg-ai-body ol { padding-left: 20px !important; margin-bottom: 12px !important; }
            .klm-msg-ai-body li { margin-bottom: 6px !important; line-height: 1.6 !important; }
            .klm-msg-ai-body strong { font-weight: 700 !important; }
            .klm-msg-ai-body h1, .klm-msg-ai-body h2, .klm-msg-ai-body h3 { font-size: 17px !important; font-weight: 800 !important; margin: 16px 0 8px !important; }
            .klm-msg-user-bubble { font-size: 15px !important; line-height: 1.5 !important; }
            .klm-suggestions { padding: 0 !important; gap: 6px !important; }
            .klm-suggestion-btn { font-size: 13px !important; padding: 8px 14px !important; }
            /* Show bottom tabs when notebook is open */
            .study-layout.klm-notebook-open .klm-mobile-tabs,
            .klm-mobile-tabs.visible {
                display: flex; position: fixed; bottom: 0; left: 0; right: 0; z-index: 200;
                background: var(--study-bg, #f8f6f2);
                border-top: 1px solid rgba(0,0,0,0.06); padding: 2px 0 env(safe-area-inset-bottom, 0px);
            }
            .klm-mobile-tab {
                flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
                padding: 8px 4px 6px; border: none; background: none; cursor: pointer;
                color: rgba(0,0,0,0.7); font-size: 10px; font-weight: 500; font-family: inherit;
                letter-spacing: 0.02em; transition: color 0.15s;
            }
            .klm-mobile-tab svg { width: 20px; height: 20px; stroke-width: 1.8; }
            /* All three tabs use the same color, no active highlight */
            .klm-mobile-tab.active { color: rgba(0,0,0,0.7); }
            .klm-mobile-tab.active svg { stroke-width: 1.8; }
            /* When a tab is active, show the corresponding panel */
            .study-layout.klm-notebook-open .klm-sources[data-mob-visible="1"] {
                display: flex !important; flex-direction: column !important; position: fixed; inset: 44px 0 56px; z-index: 150;
                background: var(--study-bg, #f8f6f2); overflow-y: auto; border-radius: 0; width: 100% !important;
                min-width: 100% !important; padding: 0 !important;
            }
            .study-layout.klm-notebook-open .klm-sources[data-mob-visible="1"] .klm-collapsed-strip { display: none !important; }
            .study-layout.klm-notebook-open .klm-sources[data-mob-visible="1"] .klm-panel-header { display: flex !important; }
            .study-layout.klm-notebook-open .klm-sources[data-mob-visible="1"] .klm-add-source-btn { display: flex !important; }
            .study-layout.klm-notebook-open .klm-sources[data-mob-visible="1"] .klm-sources-list { display: block !important; }
            .study-layout.klm-notebook-open .klm-sources[data-mob-visible="1"] .klm-sources-select { display: flex !important; }
            .study-layout.klm-notebook-open .klm-sources[data-mob-visible="1"] .klm-src-search-wrap { display: block !important; }
            .study-layout.klm-notebook-open .klm-sources[data-mob-visible="1"] .klm-collapse-btn { display: none !important; }
            .study-layout.klm-notebook-open .klm-studio[data-mob-visible="1"] {
                display: flex !important; flex-direction: column !important; position: fixed; inset: 44px 0 56px; z-index: 150;
                background: var(--study-bg, #f8f6f2); overflow-y: auto; border-radius: 0; width: 100% !important;
                min-width: 100% !important; padding: 0 !important;
            }
            .study-layout.klm-notebook-open .klm-studio[data-mob-visible="1"] .klm-collapsed-strip { display: none !important; }
            .study-layout.klm-notebook-open .klm-studio[data-mob-visible="1"] .klm-panel-header { display: flex !important; }
            .study-layout.klm-notebook-open .klm-studio[data-mob-visible="1"] .klm-collapse-btn { display: none !important; }
            .study-layout.klm-notebook-open .klm-studio[data-mob-visible="1"] .klm-studio-grid {
                display: flex !important; flex-direction: column !important; gap: 8px !important; padding: 8px 14px !important;
            }
            .study-layout.klm-notebook-open .klm-studio[data-mob-visible="1"] .klm-studio-btn {
                flex-direction: row !important; align-items: center !important; justify-content: flex-start !important;
                height: auto !important; padding: 14px 16px !important; gap: 12px !important; border-radius: 14px !important;
            }
            .study-layout.klm-notebook-open .klm-studio[data-mob-visible="1"] .klm-studio-btn-icon { margin-bottom: 0 !important; width: 22px !important; height: 22px !important; }
            .study-layout.klm-notebook-open .klm-studio[data-mob-visible="1"] .klm-studio-btn-label { font-size: 14px !important; font-weight: 700 !important; }
            .study-layout.klm-notebook-open .klm-studio[data-mob-visible="1"] .klm-studio-btn-edit { top: 50% !important; transform: translateY(-50%) !important; right: 12px !important; opacity: 0.5 !important; }
            .study-layout.klm-notebook-open .klm-studio[data-mob-visible="1"] .klm-studio-outputs { display: block !important; padding: 8px 14px !important; }
            /* Output items: clean pill style */
            .klm-studio-output-item {
                border: none !important; background: rgba(0,0,0,0.03) !important; border-radius: 14px !important;
                padding: 14px 16px !important; margin-bottom: 8px !important;
            }
            .klm-studio-output-item:hover { background: rgba(0,0,0,0.05) !important; border: none !important; }
            .klm-studio-output-icon { width: 22px !important; height: 22px !important; color: var(--study-accent) !important; }
            .klm-studio-output-title { font-size: 15px !important; font-weight: 700 !important; color: #1a1a1a !important; }
            .klm-studio-output-meta { font-size: 12px !important; color: var(--study-accent) !important; margin-top: 1px !important; }
            .klm-studio-output-delete { opacity: 0.3 !important; }
            /* "Generated media" section header */
            .klm-studio-outputs-header { display: block !important; padding: 16px 0 8px !important; font-size: 13px !important; font-weight: 600 !important; color: rgba(0,0,0,0.35) !important; text-transform: uppercase !important; letter-spacing: 0.04em !important; }
            /* Studio view (output detail) must be above the panel */
            .klm-studio-view {
                position: fixed !important; inset: 0 !important; z-index: 300 !important;
                background: var(--study-bg, #f8f6f2) !important; border-radius: 0 !important;
            }
            /* Generating card */
            .klm-studio-generating { border-radius: 14px !important; }
            /* Hide panels when not active */
            .study-layout.klm-notebook-open .klm-sources:not([data-mob-visible="1"]) { display: none !important; }
            .study-layout.klm-notebook-open .klm-studio:not([data-mob-visible="1"]) { display: none !important; }
            /* Ensure sources/studio collapsed strip is hidden on mobile */
            .klm-collapsed-strip { display: none !important; }
            .klm-panel-header .klm-collapse-btn { display: none !important; }
            /* Hide main mobile nav when in KLM notebook */
            .study-layout.klm-notebook-open .klm-mobile-tabs { display: flex; }
            body.in-klm-notebook .mobile-nav { display: none !important; }
            /* KLM input padding for bottom tabs */
            /* padding handled by fixed position now */
            /* Hide picker tabs. #klmMobileTabs sits as a SIBLING of
               `.klm-layout` inside #view-solve (not a descendant), so the
               old descendant selector `.klm-layout.picker-mode .klm-mobile-tabs`
               never matched anything, which is why the Sources/Chat/Studio
               strip stayed stuck on the picker whenever `.visible` had been
               set by a prior notebook open. Use the general-sibling combinator
               (~) so the selector actually targets the strip. */
            .klm-layout.picker-mode ~ .klm-mobile-tabs { display: none !important; }
        }

        /* ===== MOBILE: ALL STUDY METHODS ===== */
        @media (max-width: 760px) {
            /* Flashcards */
            .fc-container { padding: 0; }
            .fc-card-wrap { aspect-ratio: 4/3; max-height: 300px; min-height: 200px; margin-bottom: 16px; }
            .fc-face { padding: 24px 20px; border-radius: 16px; }
            .fc-card { border-radius: 16px; }
            .fc-text { font-size: 16px; }
            .fc-card-tag { top: 14px; left: 16px; font-size: 10px; }
            .fc-hint { bottom: 16px; font-size: 10px; }
            .fc-hint kbd { display: none; }
            .fc-header { margin-bottom: 14px; }
            .fc-counter { font-size: 18px; }
            .fc-bottom-bar { padding: 10px 0 0; }
            .fc-bottom-btn { padding: 6px 12px; font-size: 12px; }
            .fc-bottom-hint { display: none; }
            .fc-actions { gap: 8px; }
            .fc-btn { padding: 10px 20px; font-size: 13px; border-radius: 8px; }
            .srs-actions { gap: 8px; }
            .srs-btn { min-width: 68px; padding: 10px 10px; font-size: 11px; border-radius: 10px; }
            .fc-mode-btns { gap: 6px; }
            .fc-mode-btn { padding: 6px 10px; font-size: .7rem; }

            /* Multiple Choice */
            .mc-question { font-size: 18px; margin-bottom: 20px; padding-bottom: 12px; }
            .mc-grid { gap: 10px; }
            .mc-option { padding: 14px 14px; gap: 12px; font-size: 14px; border-radius: 12px; }
            .mc-option .opt-num { width: 28px; height: 28px; font-size: 12px; }

            /* Fill-in-Blanks */
            .fib-sentence { font-size: 20px; margin-bottom: 20px; line-height: 1.6; }
            .fib-input-row { flex-direction: column; gap: 10px; }
            .fib-input { padding: 14px 16px; font-size: 16px; }
            .fib-check { padding: 12px 24px; font-size: 13px; width: 100%; }

            /* Written Test */
            .wt-container { padding: 4px 0; }
            .wt-question { font-size: 18px; margin-bottom: 20px; }
            .wt-textarea { min-height: 160px; padding: 14px 16px; font-size: 15px; }
            .wt-submit { padding: 10px 24px; font-size: 13px; }
            .wt-feedback { padding: 14px 16px; }

            /* Notes view */
            .notes-view { padding: 16px 20px; font-size: 15px; line-height: 1.85; }
            .notes-view h1 { font-size: 1.5rem; margin: 10px 0 16px; }
            .notes-view h2 { font-size: 1.4rem; margin: 24px 0 12px; }
            .notes-view h3 { font-size: 1.15rem; margin: 18px 0 8px; }
            .notes-view p { margin: 8px 0 22px; }
            .notes-view li { margin-bottom: 10px; }
            .notes-view hr { margin: 24px 0; }
            .notes-view blockquote { padding: 8px 14px; margin: 14px 0; }
            .notes-view pre { padding: 10px; margin: 12px 0; }
            .notes-view img { max-width: 100%; }
            .notes-concept-grid { grid-template-columns: 1fr; gap: 10px; }

            /* Image lightbox, bigger on mobile, allow pinch-zoom */
            .img-lightbox img { max-width: 100vw; max-height: 100vh; border-radius: 0; object-fit: contain; touch-action: pinch-zoom; }
            .img-lightbox-close { top: 10px; right: 10px; }

            /* Course / Module view */
            .module-hero { padding: 24px 20px 20px; margin-bottom: 24px; min-height: 180px; border-radius: 12px; }
            .module-hero-title { font-size: 22px; max-width: 100%; }
            .module-hero-desc { font-size: 13px; max-width: 100%; }
            .module-hero-art {
                width: 100%;
                max-width: none;
                aspect-ratio: 1.32 / 1;
                min-height: 220px;
                max-height: none;
                justify-self: stretch;
            }
            .module-hero-img {
                display: block;
                width: 100%;
                height: 100%;
                min-height: 0;
            }
            .module-hero-fallback-img { width: min(100%, 260px); }
            .module-section-title { font-size: 1.6rem; }
            .module-content .notes-view h2 { font-size: 1.3rem; margin-top: 32px; }
            .module-content .notes-view h3 { font-size: 1.1rem; margin-top: 20px; }

            /* Review / Learn container */
            .review-container { padding: 16px 16px 24px; }
            .review-top-bar { gap: 10px; padding-bottom: 12px; }
            .review-mode-tab { padding: 8px 14px; font-size: 13px; }
            .review-landing { padding: 12px 12px 20px; }

            /* Grade view */
            .grade-container { padding: 24px 16px 24px; }
            .grade-heading { font-size: 22px; }
            .grade-cards { grid-template-columns: 1fr; gap: 16px; }
            .grade-cards-v2 { grid-template-columns: 1fr; }
            .grade-card { padding: 24px 20px; min-height: auto; border-radius: 16px; }
            .grade-result-layout { flex-direction: column; }
            .grade-result-left { width: 100%; }
            .grade-result-right { padding: 20px 16px; }
            .grade-tab { padding: 10px 16px; font-size: 13px; }
            .grade-tabs { gap: 6px; flex-wrap: wrap; }
            .grade-rubric-row { flex-direction: column; gap: 10px; }

            /* Exam */
            .exam-intro { padding: 24px 16px; gap: 20px; }
            .exam-intro-title { font-size: 1.6rem; }
            .exam-intro-icon { width: 52px; height: 52px; }
            .exam-intro-icon i { width: 24px; height: 24px; }
            .exam-start-btn { padding: 14px 32px; font-size: 1rem; }
            .exam-config { padding: 20px 16px; }
            .exam-dot { width: 30px; height: 30px; font-size: .7rem; }
            .exam-nav-btn { padding: 10px 18px; font-size: .82rem; }
            .exam-submit-btn { padding: 12px 24px; font-size: .88rem; }
            .exam-results-btn { padding: 12px 20px; font-size: .82rem; }
            .exam-score-hero { padding: 24px 16px; }
            .exam-score-pct { font-size: 3rem; }
            .exam-q-result { padding: 12px 14px; }
            .exam-areas { padding: 14px 16px; }

            /* Humanizer */
            .humanizer-panel { padding: 16px 16px 14px; }
            .humanizer-panel-title { font-size: 15px; }

            /* ───────────────────────────────────────────────────────────
               Mobile dashboard "Create new set" CTA, pinned to the
               bottom (above the mobile bottom nav) instead of sitting at
               the top of the page hero. James asked for thumb-reach
               placement on Sets / Review / Khio LM / Solve, plus the
               usage indicator ("1/25 sets · 211 KB/500 MB") stacked
               BELOW the button instead of at the top of the page.

               Layout from bottom to top of viewport:
                 - Mobile bottom nav (compressed margin)
                 - Usage bar (fixed)
                 - Create CTA button (fixed)
                 - Page content (sets/review list)

               The empty hero collapses naturally since heading-row got
               position:fixed lifted out of flow. */
            /* Create CTA + usage indicator, built into the page flow
               so they SCROLL with the page (no longer position:fixed).
               JS (moveMobileCtaToBottom in study.js) physically moves
               these two elements to the end of the active .study-view
               on every render. CSS just styles them as a centered
               block + handles the 200px top push James asked for. */
            .mobile-dashboard-heading-row {
                position: static !important;
                display: flex !important;
                justify-content: center !important;
                width: 100%;
                max-width: 380px;
                margin: 50px auto 0 !important;
                padding: 0 16px !important;
                box-sizing: border-box;
            }
            .mobile-dashboard-create {
                width: 100% !important;
            }
            /* The empty hero shouldn't reserve vertical space at the top
               since the CTA moved out, collapse its height. */
            .mobile-dashboard-hero {
                min-height: 0 !important;
                padding: 0 !important;
                margin: 0 !important;
            }
            /* Usage line, same flow, sits right under the button.
               Track (progress bar) hidden on mobile, just the two text
               pieces with a dot separator. */
            #studyUsageBar.study-usage-bar,
            #klmUsageBar.study-usage-bar,
            body[data-scheme] #studyUsageBar.study-usage-bar,
            body[data-scheme] #klmUsageBar.study-usage-bar {
                position: static !important;
                width: auto;
                max-width: calc(100% - 32px);
                margin: 12px auto calc(120px + env(safe-area-inset-bottom, 0px)) !important;
                background: transparent !important;
                border: none !important;
                box-shadow: none !important;
                padding: 0 !important;
                display: flex !important;
                align-items: center;
                justify-content: center;
            }
            #studyUsageBar.study-usage-bar .study-usage-track,
            #klmUsageBar.study-usage-bar .study-usage-track,
            body[data-scheme] #studyUsageBar.study-usage-bar .study-usage-track,
            body[data-scheme] #klmUsageBar.study-usage-bar .study-usage-track {
                display: none !important;
            }
            #studyUsageBar.study-usage-bar .study-usage-info,
            #klmUsageBar.study-usage-bar .study-usage-info {
                display: inline-flex !important;
                align-items: center !important;
                gap: 8px !important;
                font-size: 12px !important;
                color: rgba(26,26,26,0.55) !important;
                white-space: nowrap;
            }
            #studyUsageBar.study-usage-bar .usage-sets-text + .usage-storage-text::before,
            #klmUsageBar.study-usage-bar .usage-sets-text + .usage-storage-text::before {
                content: '·';
                margin-right: 8px;
                color: rgba(26,26,26,0.4);
            }
            /* Restore mobile-nav default margin since the CTA is no
               longer pinned above it. */
            .mobile-nav-inner,
            body[data-scheme] .mobile-nav-inner {
                margin: 0 auto calc(8px + env(safe-area-inset-bottom, 0px)) !important;
            }
            /* Force-hide CTA stack elements that don't belong in the
               current view (set by moveMobileCtaToBottom). Beats the
               !important display:flex on .study-usage-bar / the
               base .mobile-dashboard-heading-row visibility. Covers
               BOTH the ID'd usage bars (#studyUsageBar / #klmUsageBar)
               AND the inline-rendered .study-usage-bar copies that
               getUsageBarHtml() drops at the top of Review / KLM. */
            .mobile-dashboard-heading-row.cta-bottom-hidden,
            .study-usage-bar.cta-bottom-hidden,
            #studyUsageBar.cta-bottom-hidden,
            #klmUsageBar.cta-bottom-hidden,
            body[data-scheme] .study-usage-bar.cta-bottom-hidden,
            body[data-scheme] #studyUsageBar.cta-bottom-hidden,
            body[data-scheme] #klmUsageBar.cta-bottom-hidden {
                display: none !important;
            }
            /* Pre-mount: hide the heading-row + usage bars until the
               JS mover (moveMobileCtaToBottom) has placed them in
               their final position at the bottom of the cards grid.
               Without this they flash at the TOP of the page for one
               paint frame before the JS appends them, the "glitch
               on first load" James reported. .cta-mounted is added by
               the mover after appendChild succeeds. */
            body.mobile-app .mobile-dashboard-heading-row:not(.cta-mounted),
            body.capacitor-app .mobile-dashboard-heading-row:not(.cta-mounted),
            body.mobile-app #studyUsageBar:not(.cta-mounted),
            body.capacitor-app #studyUsageBar:not(.cta-mounted),
            body.mobile-app #klmUsageBar:not(.cta-mounted),
            body.capacitor-app #klmUsageBar:not(.cta-mounted) {
                display: none !important;
            }
            /* On Khio LM picker: belt-and-braces, always hide the
               inline usage bar that sits inside klmMobileHeader (it's
               the duplicate at the top of the page that James saw).
               The ID'd #klmUsageBar lives in #klmPicker and is the one
               we want to keep, moved to below the Create button. */
            #klmMobileHeader .study-usage-bar { display: none !important; }
            /* The "weird line" James saw on Khio LM: a 1px border at
               the bottom of .klm-center-topbar. Remove on mobile. */
            .klm-center-topbar,
            body[data-scheme] .klm-center-topbar {
                border-bottom: none !important;
            }
            /* Hide the lifted CTA + usage in the detail view (in-detail)
               and while the keyboard is open, those screens shouldn't
               show a free-floating Create button. */
            body.in-detail .mobile-dashboard-heading-row,
            body.in-detail #studyUsageBar,
            body.in-detail #klmUsageBar,
            body.khio-kb-open .mobile-dashboard-heading-row,
            body.khio-kb-open #studyUsageBar,
            body.khio-kb-open #klmUsageBar { display: none !important; }
        }

        /* ───────────────────────────────────────────────────────────────
           Module filter (Flashcards / Multiple Choice / Written Response)
          , horizontal-scroll row on mobile.

           Desktop renders this with inline `flex-wrap: wrap` so 14 modules
           fold onto 3+ rows. On a phone that turns into a 250-px-tall
           crowded grid before the user even sees the question. Override
           the inline styles (need !important) to a single horizontally-
           scrollable row of fixed-size pills, native iOS momentum scroll,
           hidden scrollbar, with subtle fade-out edges so the user reads
           it as scrollable.

           Same component is used by review and flashcards, so this fixes
           both at once. */
        @media (max-width: 760px) {
            .flash-module-filter {
                flex-wrap: nowrap !important;
                gap: 8px !important;
                align-items: center !important;
                position: relative;
            }
            .flash-module-filter-left {
                flex-wrap: nowrap !important;
                overflow-x: auto !important;
                overflow-y: hidden;
                -webkit-overflow-scrolling: touch;
                scroll-behavior: smooth;
                scrollbar-width: none;
                padding: 4px 4px 6px !important;
                margin: 0 -4px;
                gap: 6px !important;
                /* Soft fade on the right edge, hints "scrollable" */
                -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 24px), transparent 100%);
                mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 24px), transparent 100%);
            }
            .flash-module-filter-left::-webkit-scrollbar { display: none; }
            .flash-module-filter-left .flash-filter-label,
            .flash-module-filter-left .flash-filter-chip,
            .flash-module-filter-left .flash-filter-sep {
                flex-shrink: 0 !important;
                white-space: nowrap !important;
            }
            .flash-module-filter-left .flash-filter-label {
                font-size: 12px;
                color: var(--study-text-tertiary);
                font-weight: 600;
            }
            .flash-module-filter-left .flash-filter-chip {
                min-width: 40px;
                padding: 8px 12px;
                font-size: 13px;
                font-weight: 600;
            }
            /* Options button stays pinned to the right */
            .flash-module-filter .fc-options-wrap { flex-shrink: 0 !important; }

            /* Hide the SRS counter row ("138 due  138 new  2 learning…")
               on mobile, it eats vertical space above the question without
               adding much value on a phone screen. The progress bar above
               it is still visible. Applies to flashcards, multiple choice,
               and written response since they all render through the same
               mastery-pills-row component. */
            .mastery-pills-row .mastery-stats { display: none !important; }
        }

