/* Shared report layer — the .reports-* design system every report page is built from:
   design tokens, page header, filter bar, cards, the switch, the KPI row, the column chart, and
   the data grid.

   FQ-44: this file is DELIBERATELY NOT a .razor.css. Blazor CSS isolation rewrites every
   selector in a scoped sheet to `.reports-card[b-hash]`, which reaches that one component and
   nothing else - so two report pages sharing this layer meant two copies of it, and the third
   consumer (the reports index, which wants only .reports-busy) would have made a third. The
   copies had already drifted apart. One non-isolated sheet is the fix: each page keeps its own
   rules (.gs-* for Guest Summary, and each new report's equivalent) isolated per component, and
   takes the shared layer from here.

   Two consequences worth knowing before you edit:

   1. Selectors here are plain single-class (0,1,0), so any page's scoped rule outranks them
      automatically - that is the intended override mechanism, no !important needed.
   2. Load order matters against Bootstrap. `.table > :not(caption) > * > *` ties with
      `.reports-grid td` on specificity, so this sheet must stay linked AFTER bootstrap.min.css
      in App.razor or the grid's cell padding and --bs-table-bg silently revert to Bootstrap's.

   There used to be a third, and it was the sharp one: the Daily Summary rendered inside .reports
   while carrying its own unmigrated copy of this whole layer, so every property that copy left
   undeclared fell through to here and editing this file changed that page quietly. FQ-46 deleted
   the page and the hazard with it - every consumer of this sheet now opts in deliberately. Keep it
   that way: a new report takes the shared layer from here and keeps only its own rules scoped. */

.reports {
    --rep-radius: 14px;
    --rep-border: #e5e7eb;
    --rep-text: #111827;
    --rep-muted: #6b7280;
    --rep-primary: #2563eb;
    --rep-primary-hover: #1d4ed8;
    --rep-card-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);

    /* Status / outcome tones */
    --st-good: #16a34a;
    --st-warn: #d97706;
    --st-bad: #dc2626;
    --st-info: #2563eb;
    --st-neutral: #9ca3af;

    /* Heat ramp: five intensity steps plus an explicit empty step. --heat0 is a distinct token
       rather than "no background" because a bucket with nothing in it and the quietest bucket that
       had something in it must not look the same — step 1 is reserved for "at least one", however
       small against the peak. Declared on .reports rather than on the one panel that heat-maps
       anything so a second heatmap inherits the same ramp instead of forking it. */
    --heat0: #f3f4f6;
    --heat1: #dbeafe;
    --heat2: #bfdbfe;
    --heat3: #93c5fd;
    --heat4: #60a5fa;
    --heat5: #2563eb;

    color: var(--rep-text);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    padding-bottom: 2rem;
}

/* ---- Header ---- */
.reports-header {
    margin-bottom: 1rem;
}

.reports-title {
    font-size: 1.35rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    margin: 0;
}

/* ---- Filter bar: segmented date-range control + actions ---- */
.reports-filters {
    display: flex;
    align-items: stretch;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 1.5rem;
}

.reports-range {
    display: flex;
    align-items: center;
    background: #fff;
    border: 1px solid #d1d5db;
    border-radius: 10px;
    padding: 0.3rem 0.75rem;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.reports-range:focus-within {
    border-color: var(--rep-primary);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}

.reports-range-field {
    display: flex;
    flex-direction: column;
    margin: 0;
    cursor: pointer;
}

.reports-range-label {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--rep-muted);
    line-height: 1;
    margin-bottom: 0.1rem;
}

.reports-range-field input[type="date"] {
    border: none;
    outline: none;
    background: transparent;
    padding: 0;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--rep-text);
    font-variant-numeric: tabular-nums;
    font-family: inherit;
}

.reports-range-sep {
    color: #9ca3af;
    font-size: 0.8rem;
    padding: 0 0.85rem;
    align-self: center;
}

.reports-actions {
    display: flex;
    align-items: stretch;
    gap: 0.5rem;
}

.reports-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    border-radius: 10px;
    padding: 0.5rem 1.15rem;
    font-size: 0.92rem;
    font-weight: 600;
    font-family: inherit;
    border: 1px solid transparent;
    cursor: pointer;
    transition: background-color 0.12s ease, border-color 0.12s ease;
    white-space: nowrap;
}

.reports-btn:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

.reports-btn--primary {
    background: var(--rep-primary);
    color: #fff;
}

.reports-btn--primary:hover:not(:disabled) {
    background: var(--rep-primary-hover);
}

/* ---- States ---- */
.reports-busy {
    display: flex;
    justify-content: center;
    padding: 2.5rem 0;
}

.reports-empty {
    padding: 2.5rem 1rem;
    text-align: center;
    color: var(--rep-muted);
    background: #fafbfc;
    border: 1px dashed var(--rep-border);
    border-radius: var(--rep-radius);
}

/* ---- Headline KPIs: the tile row between the filter bar and the cards ---- */
.reports-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 0.9rem;
    margin-bottom: 1.1rem;
}

.reports-kpi {
    border: 1px solid var(--rep-border);
    border-radius: var(--rep-radius);
    background: #fff;
    box-shadow: var(--rep-card-shadow);
    padding: 0.9rem 1rem;
}

.reports-kpi-label {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--rep-muted);
}

.reports-kpi-value {
    font-size: 1.9rem;
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

.reports-kpi-sub {
    font-size: 0.78rem;
    color: var(--rep-muted);
    line-height: 1.3;
}

/* ---- Cards ---- */
.reports-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 0.9rem;
}

.reports-card {
    border: 1px solid var(--rep-border);
    border-radius: var(--rep-radius);
    padding: 1rem 1.1rem 0.85rem;
    background-color: #fff;
    box-shadow: var(--rep-card-shadow);
}

.reports-card-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--rep-muted);
    margin-bottom: 0.6rem;
}

/* Tinted icon chips give each card a colour identity at a glance. */
.reports-card-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.7rem;
    height: 1.7rem;
    border-radius: 8px;
    font-size: 0.78rem;
}

.reports-card-icon--outcome {
    background: #eff6ff;
    color: var(--rep-primary);
}

.reports-card-icon--quote {
    background: #fffbeb;
    color: #b45309;
}

.reports-card-icon--channel {
    background: #ecfdf5;
    color: #047857;
}

.reports-card-hero {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    margin-bottom: 0.55rem;
}

.reports-card-figure {
    font-size: 2.1rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--rep-text);
    font-variant-numeric: tabular-nums;
}

.reports-card-figure-label {
    font-size: 0.82rem;
    color: var(--rep-muted);
}

.reports-card-foot,
.reports-card-empty {
    font-size: 0.76rem;
    color: #868e96;
    margin-top: 0.5rem;
    line-height: 1.35;
}

.reports-card-empty {
    margin-top: 0.25rem;
}

.reports-note {
    font-size: 0.8rem;
    color: var(--rep-muted);
    margin: 1rem 0 0;
    max-width: 90ch;
}

/* ---- Switch: the card-head control that reveals a chart's table twin ----
   margin-left: auto parks it at the far edge of the head, opposite the title. The head's
   uppercase letter-spacing is unset here - it is set on .reports-card-head for the title and
   would otherwise be inherited by the switch's own label, which is sentence case. */
.reports-switch {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-left: auto;
    cursor: pointer;
    user-select: none;
    text-transform: none;
    letter-spacing: normal;
    font-size: 0.8rem;
}

/* The native control still exists and still takes focus - it is only made transparent, never
   display: none or zero-sized. Both of those visually-hidden tricks cost more than they look:
   a zero-box input is not a click target for anything driving the page from outside (Playwright
   refuses to check it), and display: none drops it out of the tab order and off screen readers
   entirely. Stretched over the whole label instead, so the control IS the hit area it appears
   to be, and the label text and track are what you see through it. */
.reports-switch input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}

.reports-switch-track {
    position: relative;
    flex: none;
    width: 2.2rem;
    height: 1.2rem;
    border-radius: 999px;
    background: #d1d5db;
    transition: background-color 0.15s ease;
}

.reports-switch-track::after {
    content: "";
    position: absolute;
    top: 0.13rem;
    left: 0.14rem;
    width: 0.94rem;
    height: 0.94rem;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
    transition: transform 0.15s ease;
}

.reports-switch input:checked + .reports-switch-track {
    background: var(--rep-primary);
}

.reports-switch input:checked + .reports-switch-track::after {
    transform: translateX(1rem);
}

/* Focus ring on the track, since the input it belongs to is invisible. :focus-visible so a
   mouse click doesn't leave a ring behind. */
.reports-switch input:focus-visible + .reports-switch-track {
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.25);
}

/* ---- Column charts: the bar plot inside a card ----

   Geometry note, and the reason this is built the way it is: the value label above each bar sits
   in its OWN grid row, always rendered whether or not the column has a figure to show. The bar
   itself is a percentage of .reports-col-track, which has an explicit height - so a 100% bar
   exactly fills its track and stops there. The label physically cannot ride up over the card's
   hero or summary line, because the space it needs was reserved before the bar was drawn. The
   alternative (absolutely positioning the label at the bar's height) overflows the plot at full
   height, which is exactly the collision this layout exists to prevent. Reserve the headroom;
   never clip the label. FQ-42 landed on this after trying it the other way round.

   Series colours are deliberately NOT here. A segment's fill encodes one report's own semantics
   (bookings vs waitlist; parties checked in vs minutes waited), so each page keeps its own
   --{series} modifier in its own scoped sheet and applies it alongside .reports-col-seg.

   Naming: the .reports-col-* prefix used to carry two meanings at once, because the Daily
   Summary's grid named its TABLE columns .reports-col-date / -wait / -service / -quoted / -quote.
   FQ-46 deleted that page, so in this namespace -col- means a chart column and nothing else.
   Worth keeping that way - if a report needs to name table columns, give them their own prefix. */
.reports-cols {
    display: grid;
    /* Tick-to-tick gutter. A page drawing more than one bar per tick widens it - see
       .reports-cols in WaitTimeSummary.razor.css. */
    gap: 0.35rem;
    align-items: end;
    margin-top: 0.35rem;
}

.reports-col {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
}

/* The reserved headroom row. Fixed height, always present. */
.reports-col-value {
    height: 1.05rem;
    line-height: 1.05rem;
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--rep-muted);
    text-align: center;
    font-variant-numeric: tabular-nums;
    overflow: hidden;
    white-space: nowrap;
}

.reports-col-track {
    height: 6.5rem;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    background: linear-gradient(to top, #f3f4f6 1px, transparent 1px);
    border-radius: 4px 4px 0 0;
}

.reports-col-seg {
    display: block;
    width: 100%;
    min-height: 2px;
}

/* Round only the topmost segment of a stack, so the join between two stacked series stays square
   and the stack reads as one bar. A single-segment column is its own first child, so it gets the
   cap from the same rule. */
.reports-col-track > .reports-col-seg:first-child {
    border-radius: 4px 4px 0 0;
}

.reports-col-label {
    margin-top: 0.3rem;
    font-size: 0.7rem;
    color: var(--rep-muted);
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ---- Data grid: the table twin of a chart ----
   --bs-table-bg transparent lets our own row tints show through Bootstrap's box-shadow
   background mechanism. */
.reports-grid {
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
    font-size: 0.85rem;
    min-width: 100%;
    margin-bottom: 0;
    --bs-table-bg: transparent;
}

.reports-grid th,
.reports-grid td {
    white-space: nowrap;
    vertical-align: middle;
    padding: 0.35rem 0.85rem;
}

.reports-grid thead th {
    color: #495057;
    font-size: 0.78rem;
    font-weight: 700;
    border-bottom: 2px solid #ced4da;
}

.reports-grid tbody th {
    font-weight: 600;
}

.reports-grid tbody td,
.reports-grid tbody th {
    border-bottom: 1px solid var(--rep-border);
}

/* A month with no activity is still a row - dimmed, not hidden, so the axis stays whole. */
.reports-grid tbody tr.reports-row-empty th,
.reports-grid tbody tr.reports-row-empty td {
    color: #c2c7cd;
}

.reports-grid tbody tr:hover th,
.reports-grid tbody tr:hover td {
    background-color: #f1f3f5;
}

.reports-grid tfoot .reports-totals th,
.reports-grid tfoot .reports-totals td {
    border-top: 2px solid #ced4da;
    font-weight: 600;
    background-color: #f6f8fa;
}

/* ---- Mobile ---- */
@media (max-width: 719.98px) {
    .reports-filters {
        flex-direction: column;
    }

    .reports-range {
        width: 100%;
        justify-content: space-between;
    }

    .reports-range-field {
        flex: 1 1 0;
    }

    /* 16px stops iOS from zooming the page when a date field gets focus. */
    .reports-range-field input[type="date"] {
        font-size: 16px;
        width: 100%;
    }

    .reports-actions {
        display: grid;
        grid-template-columns: 1fr;
        width: 100%;
    }

    .reports-cards {
        grid-template-columns: 1fr;
    }

    .reports-card {
        padding: 0.85rem 0.9rem 0.75rem;
    }

    /* The switch wraps onto its own line rather than squeezing the card title. */
    .reports-card-head {
        flex-wrap: wrap;
    }

    .reports-switch {
        margin-left: 0;
    }

    .reports-col-track {
        height: 5rem;
    }

    .reports-col-label,
    .reports-col-value {
        font-size: 0.62rem;
    }

    .reports-grid th,
    .reports-grid td {
        padding: 0.32rem 0.6rem;
    }
}

/* ================================================================================================
   FQ-51 — Guest Summary print: the APP SHELL only.  Keep this block last in the file.

   This is a deliberately small block in a deliberately awkward place, so here is the whole reason
   it is here at all.

   WHY NOT IN THE PAGE'S OWN SHEET. Everything else about the Guest Summary printout lives in
   Floqque.Blazor.App.Client/Pages/Reports/GuestSummary.razor.css, at the end, and that is where
   you should look first. But CSS isolation rewrites every selector in that sheet to `.x[b-hash]`,
   so it reaches only the elements GuestSummary.razor renders - and ::deep only descends. The two
   things a printed report most needs gone are ABOVE the page in the tree: .portal-sidebar (the
   nav) and .content__user-bar (the provider/location selectors and user bar), both rendered by
   PortalLayout2. No selector in an isolated sheet can ever reach them. It has to be a global sheet,
   and this is the global sheet the report pages already load.

   WHY :has() AND NOT A PLAIN RULE. This file is shared by every report page. FQ-51 scopes the work
   to Guest Summary and explicitly excludes Wait Time Summary, whose own print pass is separate
   work - so a bare `@media print { .portal-sidebar { display: none } }` here (or, worse, in
   portal.css) would silently change what every other report, and every other portal page, prints.
   :has(.reports.gs) is the narrowest honest hook available without JavaScript: .reports.gs is the
   root of Guest Summary's permitted state, and nothing else in the app carries it - Wait Time
   Summary is .reports.wts, Daily Summary is a bare .reports. Supported in Chrome/Edge 105+,
   Safari 15.4+, Firefox 121+; where it is not supported the selector simply never matches and the
   printout degrades to today's behaviour (the shell prints) rather than breaking.

   AND WHY IT IS APPENDED RATHER THAN FILED UNDER A HEADING: FQ-46 is editing this file's header
   comment on another branch. An append-only block at the very end keeps the two mergeable. */
@media print {
    /* The interaction-only app shell. Everything here exists to be clicked, watched, or dismissed;
       none of it describes the report. Inventoried from PortalLayout2.razor and App.razor rather
       than guessed:
         .portal-sidebar ..... NavMenu
         .content__user-bar .. AccessControl - the provider and location selectors
         .conn-banner ........ ServerConnectionComponent's offline / reconnecting / back-online strip
         .web-app-version .... the fixed version badge (opacity:0 on screen, but position:fixed, and
                               a fixed box can repeat on every printed page)
         #reconnect-modal .... App.razor's circuit-dropped overlay
         .e-toast* ........... Notifier's SfToast container
         .e-dialog / .e-dlg-* . InactivityAction's SfDialog, which renders its container up front
         .inactivity-details .. the inactivity and session-expiry countdown notices
         .token-expiration .... the debug-page token card */
    body:has(.reports.gs) .portal-sidebar,
    body:has(.reports.gs) .content__user-bar,
    body:has(.reports.gs) .conn-banner,
    body:has(.reports.gs) .web-app-version,
    body:has(.reports.gs) #reconnect-modal,
    body:has(.reports.gs) .e-toast-container,
    body:has(.reports.gs) .e-toast,
    body:has(.reports.gs) .e-dlg-container,
    body:has(.reports.gs) .e-dialog,
    body:has(.reports.gs) .inactivity-details,
    body:has(.reports.gs) .token-expiration {
        display: none !important;
    }

    /* Flatten the shell the report is sitting in. On screen it is a flex row wrapping a rounded
       white card; on paper it is just a container, and every one of those properties is either
       meaningless or actively harmful once the content has to fragment across pages.

       overflow is the one that matters: PortalLayout2.razor.css sets `overflow: clip` on .content
       at >=1025px, and a clipping ancestor is the classic way a printout loses everything after
       page one. A printed page is only ~725px (Letter) / ~703px (A4) of CSS width inside our 12mm
       margin, so that media query should not match when printing - but "should not match" is not a
       good enough reason to leave a clip in the ancestry of a paged document. Forced visible.

       display: block for the same class of reason: block flow is the only layout mode every print
       engine fragments correctly, and nothing about this shell needs flex on paper. */
    body:has(.reports.gs) .portal-page,
    body:has(.reports.gs) .portal-page > main,
    body:has(.reports.gs) .content {
        display: block;
        margin: 0;
        padding: 0;
        border-radius: 0;
        overflow: visible !important;
    }

    /* One named page for the WHOLE document, set on <body> rather than on .reports.gs. A change of
       page name between two boxes forces a page break, so naming only the report would risk a
       blank leading sheet; naming the body means the name never changes anywhere. */
    body:has(.reports.gs) {
        page: gs-report;
    }
}

/* A named page is inert until something references it, so this rule is scoped to the block above
   by construction and changes nothing on any other page. 12mm clears the unprintable edge of every
   common Letter and A4 printer with room to spare, and is the ONLY inset the printed report has -
   the page's own .page-content padding is zeroed for print in GuestSummary.razor.css.

   No `size`: the reader picks the paper in the print dialog, and the report is built to fit both
   Letter and A4 in PORTRAIT - the card grid drops to a single column on paper, and the column
   charts are all `minmax(0, 1fr)` tracks that shrink to whatever measure they are given. Nothing
   needs the landscape escape hatch ScheduledNext's timeline needed (@page sched-timeline). */
@page gs-report {
    margin: 12mm;
}
