/* /Components/Layout/MainLayout.razor.rz.scp.css */
.page[b-l8ps5iyt34] {
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 100vh;   /* fallback for browsers without dvh */
    min-height: 100dvh;  /* footer reaches the bottom even on short pages */
}

main[b-l8ps5iyt34] {
    flex: 1;
    display: flex;
    flex-direction: column;
}

    main article.content[b-l8ps5iyt34] {
        flex: 1; /* push the footer to the bottom */
    }

.app-footer[b-l8ps5iyt34] {
    container-type: inline-size;
    padding-top: 0.6rem;
    padding-bottom: 0.7rem;
    margin-top: 1.5rem;
    border-top: 1px solid #d9d9d9;
    font-size: 0.8rem;
    color: #555555;
}

    /* Narrow (default): plain inline flow — the version continues at the end of
       the notice sentence and wraps like text, left-justified. The container
       query keys on the footer's own width, so a narrow desktop window behaves
       the same as mobile. */
    .app-footer .app-footer-inner[b-l8ps5iyt34] {
        display: block;
    }

    @container (min-width: 44rem) {
        .app-footer .app-footer-inner[b-l8ps5iyt34] {
            display: flex;
            justify-content: space-between;
            align-items: baseline;
            gap: 1.5rem;
        }

        .app-footer .app-version[b-l8ps5iyt34] {
            margin-left: 0;
        }
    }

    .app-footer .beta-badge[b-l8ps5iyt34] {
        display: inline-block;
        background-color: #000000;
        color: #ffffff;
        font-weight: 600;
        font-size: 0.65rem;
        letter-spacing: 0.05em;
        padding: 0.1rem 0.4rem;
        border-radius: 0.25rem;
        margin-right: 0.35rem;
        vertical-align: 0.1em;
    }

    .app-footer a[b-l8ps5iyt34] {
        color: inherit;
        text-decoration: underline;
    }

    .app-footer .app-version[b-l8ps5iyt34] {
        white-space: nowrap;
        margin-left: 0.4rem; /* breathing room when flowing inline after the notice */
    }

.sidebar[b-l8ps5iyt34] {
    background-color: #000000;
}

.top-row[b-l8ps5iyt34] {
    background-color: #ffffff;
    border-bottom: 1px solid #000000;
    justify-content: flex-end;
    height: 3.5rem;
    display: flex;
    align-items: center;
}

    .top-row[b-l8ps5iyt34]  a, .top-row[b-l8ps5iyt34]  .btn-link {
        white-space: nowrap;
        margin-left: 1.5rem;
        text-decoration: none;
    }

    .top-row[b-l8ps5iyt34]  a:hover, .top-row[b-l8ps5iyt34]  .btn-link:hover {
        text-decoration: underline;
    }

    .top-row[b-l8ps5iyt34]  a:first-child {
        overflow: hidden;
        text-overflow: ellipsis;
    }

@media (max-width: 640.98px) {
    /* White login bar: span the full frame edge-to-edge with a small,
       balanced inset. px-4 (1.5rem) leaves an awkward right-side gap on
       phones, so trim it and right-align the login content cleanly. */
    .top-row[b-l8ps5iyt34] {
        justify-content: flex-end;
        padding-left: 0.75rem !important;
        padding-right: 0.75rem !important;
        width: 100%;
    }

    .top-row[b-l8ps5iyt34]  a, .top-row[b-l8ps5iyt34]  .btn-link {
        margin-left: 0;
    }

    /* Article content: balanced small side padding so pages use the frame
       well without touching the edges. Overrides Bootstrap px-4 (!important). */
    article.content[b-l8ps5iyt34], .app-footer[b-l8ps5iyt34] {
        padding-left: 0.5rem !important;
        padding-right: 0.5rem !important;
    }
}

@media (min-width: 641px) {
    .page[b-l8ps5iyt34] {
        flex-direction: row;
    }

    .sidebar[b-l8ps5iyt34] {
        width: 250px;
        height: 100vh;       /* fallback for browsers without dvh */
        height: 100dvh;      /* track the actually-visible viewport (excludes mobile chrome) */
        position: sticky;
        top: 0;
    }

    .top-row[b-l8ps5iyt34] {
        position: sticky;
        top: 0;
        z-index: 1;
    }

    .top-row.auth[b-l8ps5iyt34]  a:first-child {
        flex: 1;
        text-align: right;
        width: 0;
    }

    .top-row[b-l8ps5iyt34], article[b-l8ps5iyt34], .app-footer[b-l8ps5iyt34] {
        padding-left: 2rem !important;
        padding-right: 1.5rem !important;
    }
}

/* Very short landscape viewports (e.g. phones in landscape): cap the sidebar to the
   actually-visible area so the menu never extends past the fold and stays reachable
   via its own internal scroll regardless of page length. */
@media (min-width: 641px) and (max-height: 480px) {
    .sidebar[b-l8ps5iyt34] {
        height: 100vh;       /* fallback */
        height: 100dvh;      /* cap to the visible area on short landscape screens */
    }
}

#blazor-error-ui[b-l8ps5iyt34] {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss[b-l8ps5iyt34] {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
/* /Components/Layout/NavMenu.razor.rz.scp.css */
.navbar-toggler[b-j45lztwxhm] {
    appearance: none;
    cursor: pointer;
    width: 3.5rem;
    height: 2.5rem;
    color: white;
    position: absolute;
    top: 0.5rem;
    right: 1rem;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
}

.navbar-toggler:checked[b-j45lztwxhm] {
    background-color: rgba(255, 255, 255, 0.5);
}

.top-row[b-j45lztwxhm] {
    min-height: 3.5rem;
    background-color: #000000;
}

.navbar-brand[b-j45lztwxhm] {
    font-size: 1.1rem;
}

.bi[b-j45lztwxhm] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: relative;
    width: 1.25rem;
    height: 1.25rem;
    margin-right: 0.75rem;
    top: -1px;
    background-size: cover;
}

.bi-house-door-fill-nav-menu[b-j45lztwxhm] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
}

.bi-plus-square-fill-nav-menu[b-j45lztwxhm] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
}

.bi-list-nested-nav-menu[b-j45lztwxhm] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
}

.nav-item[b-j45lztwxhm] {
    font-size: 0.9rem;
    padding-bottom: 0.5rem;
}

.nav-section-title[b-j45lztwxhm] {
    color: rgba(255, 255, 255, 0.6);
    font-weight: 600;
    letter-spacing: 0.05em;
}

    .nav-item:first-of-type[b-j45lztwxhm] {
        padding-top: 1rem;
    }

    .nav-item:last-of-type[b-j45lztwxhm] {
        padding-bottom: 1rem;
    }

    .nav-item[b-j45lztwxhm]  .nav-link {
        color: #d7d7d7;
        background: none;
        border: none;
        border-radius: 4px;
        height: 3rem;
        display: flex;
        align-items: center;
        line-height: 3rem;
        width: 100%;
    }

.nav-item[b-j45lztwxhm]  a.active {
    background-color: #ffffff;
    color: #000000;
}

.nav-item[b-j45lztwxhm]  .nav-link:hover {
    background-color: #333333;
    color: white;
}

.nav-scrollable[b-j45lztwxhm] {
    display: none;
}

.navbar-toggler:checked ~ .nav-scrollable[b-j45lztwxhm] {
    display: block;
}

@media (min-width: 641px) {
    .navbar-toggler[b-j45lztwxhm] {
        display: none;
    }

    .nav-scrollable[b-j45lztwxhm] {
        /* Never collapse the sidebar for wide screens */
        display: block;

        /* Allow sidebar to scroll for tall menus */
        height: calc(100vh - 3.5rem);    /* fallback */
        height: calc(100dvh - 3.5rem);   /* dynamic viewport (excludes mobile chrome) */
        overflow-y: auto;
    }
}

/* Very short landscape viewports: keep the nav's own scroll area capped to the
   visible viewport so every item is reachable no matter how long the page is. */
@media (min-width: 641px) and (max-height: 480px) {
    .nav-scrollable[b-j45lztwxhm] {
        height: calc(100vh - 3.5rem);
        height: calc(100dvh - 3.5rem);
        overflow-y: auto;
    }
}

/* NOTE: the auto-hide scrollbar styling for .nav-scrollable lives in the
   non-scoped global stylesheet wwwroot/app.css. ::-webkit-scrollbar (and the
   Firefox scrollbar-color) pseudo-elements are not reliably rewritten by
   Blazor's CSS isolation, so they must be declared outside this scoped file. */
/* /Components/Pages/Analysis/LapTimes.razor.rz.scp.css */
/* Mobile balance: keep desktop layout untouched, only adjust at the app's
   mobile breakpoint so content fills the viewport evenly left/right and
   nothing overflows horizontally. The global article side-padding is reduced
   by the layout; here we only neutralize the container-fluid's own gutter and
   guard against horizontal overflow. */
@media (max-width: 640.98px) {
    /* Bootstrap's .container-fluid adds .75rem of left/right padding by default,
       which on a narrow screen (on top of the article padding) leaves an
       uneven gap on the right. Drop it so cards span the available width
       evenly with equal margins. */
    .analysis-page[b-ckbs25t3b5] {
        padding-left: 0;
        padding-right: 0;
        width: 100%;
        max-width: 100%;
        overflow-x: hidden;
    }

    /* The Bootstrap grid uses negative row margins paired with column padding;
       with the container gutter removed, neutralize them too so the chart and
       summary columns line up flush with the cards below. */
    .analysis-page .row[b-ckbs25t3b5] {
        margin-left: 0;
        margin-right: 0;
    }

    .analysis-page .row > [class*="col-"][b-ckbs25t3b5] {
        padding-left: 0;
        padding-right: 0;
    }

    /* Guard: cards (and the chart canvases they wrap) must never exceed the
       viewport width or they create a right-side gap / horizontal scroll. */
    .analysis-page .card[b-ckbs25t3b5] {
        max-width: 100%;
    }

    /* The 5-column "All Laps" table can be wider than the viewport; let it
       scroll inside its card instead of pushing the whole page wider. */
    .analysis-page .table-responsive[b-ckbs25t3b5] {
        max-width: 100%;
    }
}
/* /Components/Pages/Analysis/Overview.razor.rz.scp.css */
/* Overview analysis page layout.
   Desktop defaults below reproduce the original inline styles exactly.
   Mobile overrides (max-width: 640.98px) stack everything into a single column
   so charts and the track map fit a phone viewport without horizontal scroll. */

/* Root: full-height flex column. No min-width: the side-by-side columns track the
   window fluidly at every desktop width (the charts' internal pads adapt in JS),
   so the page never needs a horizontal scrollbar. */
.overview-root[b-eimww3pumj] {
    height: calc(100vh - 5.1rem);
    display: flex;
    flex-direction: column;
    overflow: auto;
}

/* Chart row: charts on the left, map column on the right (~50/50). */
.overview-chart-row[b-eimww3pumj] {
    flex: 1 0 700px;
    display: flex;
    gap: 4px;
    min-height: 0;
    overflow: hidden;
}

/* Separated pedals shows six near-equal charts instead of five, so raise the row's
   flex-basis proportionally (700px x 6/5 = 840px) to keep each chart the same height
   on short viewports. Desktop-only: on mobile the row stacks with flex: 1 1 auto, and
   this compound selector would otherwise out-rank that single-class rule despite the
   media query, so it must not leak below 641px. */
@media (min-width: 641px) {
    .overview-chart-row.pedals-separated[b-eimww3pumj] {
        flex-basis: 840px;
    }
}

/* Left column (stacked telemetry charts) and right column (map + delta). */
.overview-chart-col[b-eimww3pumj],
.overview-map-col[b-eimww3pumj] {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* Map wrapper (Leaflet or Plotly host) and delta-time wrapper. Need min-height:0
   on desktop so they can shrink inside the flex parent; on mobile they get an
   explicit height instead. */
.overview-map-wrapper[b-eimww3pumj],
.overview-delta-wrapper[b-eimww3pumj] {
    min-height: 0;
}

/* ===== Mobile: single column, map below the charts ===== */
@media (max-width: 640.98px) {
    .overview-root[b-eimww3pumj] {
        /* Let the page shrink to the viewport: no forced min-width, no horizontal
           scroll. Use auto height so the stacked content can grow and scroll
           vertically instead of being squeezed into the viewport height. */
        min-width: 0;
        height: auto;
        min-height: calc(100vh - 5.1rem);
        overflow-x: hidden;
        overflow-y: auto;
    }

    /* Stack the two columns vertically; map column ends up BELOW the charts. */
    .overview-chart-row[b-eimww3pumj] {
        flex: 1 1 auto;
        flex-direction: column;
        overflow: visible;
    }

    /* Give the telemetry-chart column a real height so its inner flex charts
       (which size off the parent) have a box to render into. The map column has
       width:100%/min-width:0 but the chart column didn't — without it the column
       (and thus each canvas) didn't claim the full frame width on a phone, leaving
       the charts narrower than the map. Add it so the canvases fill the width. */
    .overview-chart-col[b-eimww3pumj] {
        flex: 0 0 auto;
        width: 100%;
        min-width: 0;
        min-height: 70vh;
    }

    /* Drop the 4px inter-column gap when stacked vertically so charts use the full
       frame width (it only matters as a side-by-side divider on desktop). */
    .overview-chart-row[b-eimww3pumj] {
        gap: 0;
    }

    /* Map column full width, stacked under the charts.
       display:contents dissolves this column's own box so its children (the map
       wrapper and the delta wrapper) become direct flex items of the stacked row.
       That lets `order` reposition the delta independently of the charts below —
       see the .comparing rule. The map/delta wrappers carry their own heights, so
       losing this box is fine. */
    .overview-map-col[b-eimww3pumj] {
        display: contents;
        flex: 0 0 auto;
        width: 100%;
        min-width: 0;
        min-height: 55vh;
    }

    /* When a comparison is active, lift the delta/compare chart to the very top of
       the stack (above the charts and map). Only the real delta chart is moved —
       when not comparing the wrapper holds a placeholder and stays in place. */
    .overview-chart-row.comparing .overview-delta-wrapper[b-eimww3pumj] {
        order: -1;
        /* Now that it sits at the top, trim its height: a single delta trace needs far less
           than the 30vh reserved for the bottom-of-page placeholder, and the surplus read as
           empty space below the chart. (The non-comparing placeholder keeps the full 30vh.) */
        min-height: 22vh;
    }

    /* The map host normally fills its flex parent's height; when stacked it needs
       an explicit height so Leaflet/Plotly has a box to render into. */
    .overview-map-wrapper[b-eimww3pumj] {
        flex: 0 0 auto;
        min-height: 55vh;
    }

    /* Delta-time chart (or its placeholder) needs a real height when stacked. */
    .overview-delta-wrapper[b-eimww3pumj] {
        flex: 0 0 auto;
        min-height: 30vh;
    }
}

/* ===== Tablet & desktop (≥641px): fluid side-by-side layout. ===== */
@media (min-width: 641px) {
    .overview-root[b-eimww3pumj] {
        overflow-x: hidden;
        overflow-y: auto;
        /* Reserve the classic-scrollbar gutter permanently so the vertical scrollbar
           toggling (toolbar wrap / viewport height changes) doesn't nudge the chart
           columns ~15px narrower/wider. No-op with macOS overlay scrollbars. */
        scrollbar-gutter: stable;
    }

    /* Toolbar selects size to their longest option — for the file selector that's a
       full session label (~600px). They shrink fine as flex items, but at ≥641px
       <main> is a row-flex item, so a select's INTRINSIC width propagates up and
       becomes the page's minimum width, forcing horizontal scroll on any window
       under ~950px. A viewport-relative cap bounds that intrinsic contribution
       (percentages are ignored during intrinsic sizing; vw is not) while staying
       roomy on wide screens. Not applied on mobile: the column layout there never
       propagates the intrinsic width, and the selects already render full-row. */
    .overview-root[b-eimww3pumj]  select.form-select {
        max-width: 40vw;
    }
}
/* /Components/Pages/Analysis/PedalTraces.razor.rz.scp.css */
/* Mobile balance: identical treatment to Lap Times for consistency. Keep
   desktop layout untouched; only adjust at the app's mobile breakpoint so the
   stacked chart cards fill the viewport evenly and nothing overflows. The
   global article side-padding is reduced by the layout; here we only
   neutralize the container-fluid's own gutter and guard against overflow. */
@media (max-width: 640.98px) {
    /* Drop .container-fluid's default left/right padding so the stacked cards
       span the available width with equal margins (no right-side gap). */
    .analysis-page[b-2az2hgksgf] {
        padding-left: 0;
        padding-right: 0;
        width: 100%;
        max-width: 100%;
        overflow-x: hidden;
    }

    /* Guard: chart cards (which wrap the Plotly/TelemetryChart canvases) must
       not exceed the viewport width or they create a right-side gap /
       horizontal scroll. */
    .analysis-page .card[b-2az2hgksgf] {
        max-width: 100%;
    }
}
/* /Components/Pages/MyFiles.razor.rz.scp.css */
/* ───── My Files table column sizing & responsive shrink behaviour ───── */

/* Fixed layout makes the browser honour our column widths instead of sizing
   columns to their content. The fixed-width columns (status / time / laps /
   best lap / actions) take what they ask for; the text columns have no explicit
   width and so share whatever space is left over, shrinking fluidly as the page
   narrows. .table-responsive remains only as a last-resort horizontal scroll. */
.files-table[b-qtf6148x3t] {
    table-layout: fixed;
    width: 100%;
}

/* Status icon column: just wide enough for the disk icon, never wraps. */
.files-table .col-status[b-qtf6148x3t] {
    white-space: nowrap;
    width: 48px;
}

/* Actions: the ONLY hard-limited column. Fixed width with a no-wrap rule so its
   buttons always stay on a single line and never stack. Sized to hold the
   worst-case row (Analyze + hardware-warning + suppressed-channel + delete),
   so the buttons sit inside their own track rather than spilling over it. */
.files-table .col-actions[b-qtf6148x3t] {
    white-space: nowrap;
    width: 190px;
}

/* Time / Laps: compact fixed widths, kept on one line. */
.files-table .col-time[b-qtf6148x3t] {
    white-space: nowrap;
    width: 70px;
}

.files-table .col-laps[b-qtf6148x3t] {
    white-space: nowrap;
    width: 80px;
}

/* ───── TASK 7 — Best Lap column ─────
   A touch wider than Laps, plus right padding, so the "Best Lap" label + its
   sort chevron fit on one line and the chevron never crashes into the adjacent
   Actions column. Applies inside every per-day table. */
.files-table .col-bestlap[b-qtf6148x3t] {
    white-space: nowrap;
    width: 104px;
    padding-right: 0.75rem;
}

/* Text columns (Track, Car, Driver, Session): no fixed width, so under the
   fixed layout they share the remaining space and shrink fluidly with the page.
   Long values truncate with an ellipsis on a single line rather than wrapping. */
.files-table .col-text[b-qtf6148x3t] {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ───── Date column (List view, Group-by-date OFF only) ─────
   The flat list (.list-flat) replaces the day-group headers with a per-row Date
   column. On desktop it sits beside the normal Time column, so the time sub-line
   baked into every Date cell stays hidden. On phones (≤575px) there isn't room
   for both: the separate Time column is dropped and the time is shown stacked
   under the date instead (see the portrait block below). */
.files-table .col-date[b-qtf6148x3t] {
    white-space: nowrap;
    width: 104px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.files-table .col-date .date-time[b-qtf6148x3t] {
    display: none;
}

/* ───── Best-lap highlight pills (Best Lap column) ─────
   Lap-time pills mirror the colour-coded title boxes on the pedal (throttle/brake)
   chart: 4px radius, 6px side padding, 600 weight, white text. Two colours:
     purple = the fastest lap within a track's run of consecutive days
     green  = a per-day (per-driver) best that isn't the run's outright fastest
   Purple is the motorsport "fastest" convention; green marks the lesser bests. */
.files-table .col-bestlap .lap-pill[b-qtf6148x3t] {
    display: inline-block;
    color: #fff;
    border-radius: 4px;
    padding: 2px 6px;
    font-weight: 600;
    line-height: 1.2;
}

.files-table .col-bestlap .lap-pill.lap-purple[b-qtf6148x3t] {
    background-color: #6f42c1;
}

.files-table .col-bestlap .lap-pill.lap-green[b-qtf6148x3t] {
    background-color: #198754;
}

/* Clickable rows navigate to the file's Overview page. */
.file-row[b-qtf6148x3t] {
    cursor: pointer;
}

/* ───── "Group by driver" toggle (List view filter row) ─────
   Keep the checkbox + label on a single line and stop the label wrapping so the
   compact one-line control sits neatly beside the Clear Filters button. */
.list-options .form-check-label[b-qtf6148x3t] {
    white-space: nowrap;
    cursor: pointer;
    font-size: 0.875rem;
}

.list-options .form-check-input[b-qtf6148x3t] {
    cursor: pointer;
}

/* ───── Per-day tables (List view) ─────
   Each day is rendered as its OWN <table> so its column count can differ
   (single-driver days keep a Driver column; multi-driver days drop it in
   favour of Track→Driver sub-group headers). A small gap separates the
   day-tables visually. */
.list-tables > .list-day + .list-day[b-qtf6148x3t] {
    margin-top: 1rem;
}

/* ───── TASK 2 — Nesting levels distinguished by row colour, NOT indentation ─────
   All chevrons line up at the same left x (the ms-3 / ms-5 indents were removed);
   the level is read from the row's background instead. Day (thead, table-dark) =
   darkest → Track = light grey → Driver = lighter tint → file rows = white. */

/* Track group header: light grey, a step up from the white file rows. */
.files-table .list-track-header > td[b-qtf6148x3t] {
    background-color: #e2e4e8;
    font-weight: 500;
}

/* Driver sub-group header: lighter / subtle tint, clearly above white rows but
   lighter than the track header. */
.files-table .list-driver-header > td[b-qtf6148x3t] {
    background-color: #eef0f3;
}

/* Day group header — a dark bar and the top (darkest) level. It is a DIV that
   sits ABOVE the table (not a table row) so the table's column-titles row stays
   the first row and its col-* widths actually drive the fixed layout. When the
   day is expanded the column-titles row (table-dark thead) sits directly below
   it, forming one dark header block; when collapsed only this bar shows. */
.list-day-header[b-qtf6148x3t] {
    background-color: #212529;
    color: #fff;
    /* Horizontal padding matches the table cell padding (Bootstrap .table = 0.5rem)
       so the day chevron lines up vertically with the track / driver chevrons. */
    padding: 0.5rem;
    font-weight: 600;
    user-select: none;
}

.list-day-header:hover[b-qtf6148x3t] {
    background-color: #2c3136;
}

/* ───── Responsive top toolbar ─────
   Desktop keeps the original single-row layout. On small screens the toolbar
   above the filters (view toggle + Refresh + Reprocess All) wraps and the
   controls stretch so nothing clips or overflows. The toolbar is opted in with
   the `.files-toolbar` class on the wrapping flex container. */
@media (max-width: 640.98px) {
    .files-toolbar[b-qtf6148x3t] {
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    /* Let the heading take the full first row so the controls drop below it. */
    .files-toolbar > h2[b-qtf6148x3t] {
        flex: 1 1 100%;
        margin-bottom: 0;
        font-size: 1.4rem;
    }

    /* The controls group fills the row and wraps internally. */
    .files-toolbar > .files-toolbar-actions[b-qtf6148x3t] {
        flex: 1 1 100%;
        flex-wrap: wrap;
        gap: 0.5rem !important;
    }

    /* View-mode toggle stays compact; the two action buttons grow to share the
       remaining width so they read clearly and never squish together. */
    .files-toolbar-actions > .btn-group[b-qtf6148x3t] {
        flex: 0 0 auto;
    }

    .files-toolbar-actions > .btn[b-qtf6148x3t] {
        flex: 1 1 auto;
        white-space: nowrap;
    }
}

/* Very narrow: drop the textual labels from the action buttons (kept in the DOM
   for desktop / wider screens) so just the icons show and the row can't clip. */
@media (max-width: 400.98px) {
    .files-toolbar-actions .btn-label[b-qtf6148x3t] {
        display: none;
    }

    .files-toolbar-actions > .btn[b-qtf6148x3t] {
        flex: 1 1 0;
    }
}

/* ───── Responsive table column priority ─────
   Desktop (and anything ≥ 992px) shows every column exactly as before. Below
   that, columns are progressively hidden by priority so the Actions CTA is
   never cut off on a phone. This works WITHIN each per-day table because every
   day-table thead AND every file row carry the same col- / prio- classes.

   Visibility ladder (narrow → wide):
     < 576px  : Time, Driver (single-driver day), Best Lap, Actions
     ≥ 576px  : + Laps, Track
     ≥ 768px  : + Car, Status
     ≥ 992px  : + Session  → full desktop layout restored

   Priority classes are layered on top of the existing width classes:
     .prio-track, .prio-laps  → appear at ≥ 576px
     .prio-car                → appears at ≥ 768px
     .prio-session            → appears at ≥ 992px
   The Status column piggy-backs on .col-status, Driver on .col-driver. */

/* Below desktop: hide the lowest-priority Session column. */
@media (max-width: 991.98px) {
    .files-table .prio-session[b-qtf6148x3t] {
        display: none;
    }
}

/* Below 768px: also hide Car and the Status icon. */
@media (max-width: 767.98px) {
    .files-table .prio-car[b-qtf6148x3t],
    .files-table .col-status[b-qtf6148x3t] {
        display: none;
    }
}

/* Portrait / very narrow: hide everything except Driver, Time, Best Lap, Actions.
   The Actions column drops its fixed 190px width and shrinks so the compact CTA
   can never be clipped off the right edge. */
@media (max-width: 575.98px) {
    .files-table .prio-track[b-qtf6148x3t],
    .files-table .prio-laps[b-qtf6148x3t] {
        display: none;
    }

    /* Flat list: reclaim the Time column's width on phones — its value moves under
       the date in the Date cell, so Date + Time read as a two-line stack in one
       narrow column instead of two competing fixed columns. */
    .files-table.list-flat .col-time[b-qtf6148x3t] {
        display: none;
    }

    .files-table.list-flat .col-date[b-qtf6148x3t] {
        width: 78px;
    }

    .files-table.list-flat .col-date .date-day[b-qtf6148x3t] {
        display: block;
        font-size: 0.8rem;
        line-height: 1.15;
    }

    .files-table.list-flat .col-date .date-time[b-qtf6148x3t] {
        display: block;
        color: #6c757d;
        font-size: 0.75rem;
        line-height: 1.1;
    }

    /* With the action-button labels hidden (icon-only) the column needs only a
       narrow fixed track. A fixed width (not `auto`) is important under
       table-layout: fixed so the Driver column — the only remaining flexible
       column — keeps the leftover space instead of splitting it with Actions.
       Worst-case row is Analyze + warning + suppressed + delete icons. */
    .files-table .col-actions[b-qtf6148x3t] {
        width: 132px;
        text-align: right;
    }

    /* On phones the per-button action group can still be tight; allow the
       buttons to keep to one line but lose their inline label text. */
    .files-table .col-actions .action-label[b-qtf6148x3t] {
        display: none;
    }

    /* Multi-driver days drop the Driver column, so in portrait only fixed-width
       columns (Time, Best Lap, Actions) remain — with no flexible column the
       table wouldn't reach the frame and left an empty gap on the right. Let the
       last column (Actions) flex to absorb the leftover; its buttons stay
       right-aligned (text-align:right above), so the row fills the frame with the
       actions pinned to the right edge. Single-driver days keep the fixed Actions
       width because their Driver text column already absorbs the slack.
       NB: width:100% (not auto) — under table-layout:fixed an `auto` column merely
       SHARES leftover with the (hidden) prio-* auto text columns and collapses to
       ~36px; an explicit 100% greedily claims the remaining width so the table
       actually fills. */
    .files-table.day-no-driver .col-actions[b-qtf6148x3t] {
        width: 100%;
    }

    /* Tables that KEEP the Driver column (single-driver days, and ANY day when the
       "Group by driver" toggle is OFF) need a greedy column too, or the Driver
       column collapses to ~15px: under table-layout:fixed an `auto` text column
       shares leftover with the hidden prio-* auto columns instead of claiming it.
       Make the Driver column itself width:100% so it greedily absorbs the leftover
       (it's the only visible text column in portrait), mirroring the day-no-driver
       Actions:100% fix above. */
    .files-table:not(.day-no-driver) .col-driver[b-qtf6148x3t] {
        width: 100%;
    }
}

/* ───── TASK 1 — Mobile: fill the frame & give the text columns more room ─────
   On phones the combined fixed-column widths left the flexible Driver/Track
   text columns too narrow and the page padding wasted frame width on the right.
   Here we: (1) full-bleed the day-tables a little past the article's own
   horizontal padding (balanced left & right) so the table spans the frame, and
   (2) tighten the fixed columns (Time / Best Lap / Actions) and the cell padding
   so the text columns absorb the freed space. The column-priority hiding above
   still applies, and the Actions CTA stays unclipped. Desktop is untouched. */
@media (max-width: 640.98px) {
    /* Pull the tables out toward the frame edges. The global article padding is
       0.5rem (owned by the layout); a balanced -0.5rem margin lets the tables
       reach the frame without clipping content. */
    .list-tables[b-qtf6148x3t] {
        margin-left: -0.5rem;
        margin-right: -0.5rem;
    }

    /* Compact Time: HH:mm only needs a little room. */
    .files-table .col-time[b-qtf6148x3t] {
        width: 58px;
    }

    /* Best Lap stays wide enough for label + chevron (TASK 7) but trims the
       desktop slack so the text columns gain width. */
    .files-table .col-bestlap[b-qtf6148x3t] {
        width: 92px;
        padding-right: 0.4rem;
    }

    /* Actions: icon-only buttons here, so shave the desktop 190px down to give
       the Driver/Track columns noticeably more room. Kept on one line
       (col-actions is white-space:nowrap) so nothing clips. */
    .files-table .col-actions[b-qtf6148x3t] {
        width: 124px;
    }

    /* Slightly tighter cell padding everywhere on phones to reclaim width. */
    .files-table th[b-qtf6148x3t],
    .files-table td[b-qtf6148x3t] {
        padding-left: 0.4rem;
        padding-right: 0.4rem;
    }
}

/* ───── Shared-with-me marker (left-edge accent) ─────
   A row that is another user's session shared TO the viewer carries a blue left-edge
   accent. It's an inset box-shadow — no layout shift, zero horizontal cost — drawn on the
   row's LEFTMOST-VISIBLE cell. Because the column-priority rules above hide whichever cell
   is leftmost at each breakpoint, the accent is re-targeted to follow it:
     ≥768px            → col-status (first cell, visible)
     <768px, per-day   → col-time   (status hidden; per-day/grouped tables never hide Time)
     <768px, flat list → col-date   (status — and at <576 Time — hidden; Date always shows)
   On desktop the col-status cell ALSO swaps its save icon for a share glyph (see the
   markup); the stripe is the mobile-safe half of the cue. Each rule is scoped to the
   breakpoint where its target cell is the leftmost VISIBLE one, so exactly one stripe shows
   and no style is wasted on a hidden cell. */
@media (min-width: 768px) {
    .files-table .file-row.is-shared > .col-status[b-qtf6148x3t] {
        box-shadow: inset 3px 0 0 0 #0d6efd;
    }
}

@media (max-width: 767.98px) {
    .files-table:not(.list-flat) .file-row.is-shared > .col-time[b-qtf6148x3t],
    .files-table.list-flat .file-row.is-shared > .col-date[b-qtf6148x3t] {
        box-shadow: inset 3px 0 0 0 #0d6efd;
    }
}

/* ───── Share-selection mode ─────
   Selected rows get a clear fill that works at every width — the desktop checkbox lives in
   col-status, which is hidden on phones, so the row highlight is the always-visible cue.
   !important overrides Bootstrap's table-hover cell background. (Shared-in rows can't be
   selected, so .row-selected and .is-shared never coexist; even if they did, the stripe is
   an inset box-shadow that renders above this fill, so both would remain visible.) */
.files-table .file-row.row-selected > td[b-qtf6148x3t] {
    background-color: #cfe2ff !important;
}

.files-table .col-status .select-box[b-qtf6148x3t] {
    font-size: 1.05rem;
    cursor: pointer;
}

/* Group-header "select all in this group" control (share-selection mode). Sits at the left
   of each collapsible header; tri-state shape (empty / dashed / filled). Headers are full
   width, so this works on mobile where a per-row checkbox column wouldn't fit. The padding
   gives a comfortable touch target. Colour is inherited from the header (white on the dark
   day bar, dark on the grey track/driver bars); the filled "all" state adds text-primary. */
.group-select[b-qtf6148x3t] {
    cursor: pointer;
    padding: 0.1rem 0.2rem;
    font-size: 1.05rem;
}

/* Selection action bar above the list while picking sessions to share. It sticks to the top
   of the viewport as the list scrolls so the "N selected / Share" CTA always stays in reach.
   The page scrolls on the window (no inner scroll container), so sticky pins to the viewport.
   On desktop the layout's white login bar (.top-row, 3.5rem) is itself sticky at top:0, so the
   bar sits just BELOW it; on phones that bar scrolls away, so this pins to the very top. The
   z-index keeps it above scrolling rows but below the menu backdrop (1040), file menu (1050)
   and share dialog (2000); in selection mode no row menu is open anyway. */
.share-select-bar[b-qtf6148x3t] {
    position: sticky;
    top: 0;
    z-index: 1020;
    padding: 0.5rem 0.75rem;
    background-color: #eef4ff;
    border: 1px solid #cfe2ff;
    border-radius: 0.375rem;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}

@media (min-width: 641px) {
    .share-select-bar[b-qtf6148x3t] {
        top: 3.5rem; /* clear the sticky .top-row login bar so both stay visible */
    }
}

/* Invisible full-viewport catcher rendered while a row's file menu is open.
   Sits between the page (below) and the menu (inline z-index 1050, above) so
   the first click outside the menu closes it instead of acting on what's
   underneath. */
.menu-backdrop[b-qtf6148x3t] {
    position: fixed;
    inset: 0;
    z-index: 1040;
    cursor: default;
}
