/* ════════════════════════════════════════════════════════════════════════════
   Report Builder — global styles for the dynamic dashboard module.
   GridStack provides its own positioning; everything below tunes the chrome
   (cards, palette, KPI layout, chart frames) to match the Cargonerds shell.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── List page ───────────────────────────────────────────────────────────── */

.reports-list-page {
    padding: 1.5rem 2rem;
    max-width: 1600px;
    margin: 0 auto;
}

.reports-list-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    margin-bottom: 1.5rem;
    flex-wrap: wrap;
}

.reports-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1rem;
}

.report-card {
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.75rem;
    padding: 1.25rem;
    cursor: pointer;
    transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.report-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
    border-color: var(--bs-primary);
}

.report-card header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 0.5rem;
}

.report-card header h5 {
    margin: 0;
    font-weight: 600;
}

.report-card-desc {
    color: var(--bs-secondary);
    font-size: 0.875rem;
    margin: 0;
    flex-grow: 1;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.report-card footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.8rem;
    color: var(--bs-secondary);
    padding-top: 0.5rem;
    border-top: 1px solid var(--bs-border-color);
}

.reports-empty {
    text-align: center;
    padding: 4rem 1rem;
    color: var(--bs-secondary);
}

/* ── Edit / View pages ───────────────────────────────────────────────────── */

.report-edit-page,
.report-view-page {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: calc(100vh - 8rem);
}

.report-edit-toolbar,
.report-view-header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1rem 1.5rem;
    background: var(--bs-body-bg);
    border-bottom: 1px solid var(--bs-border-color);
}

.report-edit-title h4,
.report-view-header h4 {
    font-weight: 600;
    margin: 0;
}

.report-edit-palette {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    padding: 0.75rem 1.5rem;
    background: var(--bs-tertiary-bg);
    border-bottom: 1px solid var(--bs-border-color);
    flex-wrap: wrap;
}

.report-palette-label {
    font-size: 0.85rem;
    color: var(--bs-secondary);
    margin-right: 0.5rem;
}

.report-palette-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.85rem;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.4rem;
    color: var(--bs-body-color);
    font-size: 0.85rem;
    cursor: pointer;
    transition: all 0.15s;
}

.report-palette-btn:hover {
    background: var(--bs-primary-bg-subtle);
    border-color: var(--bs-primary);
    color: var(--bs-primary);
}

.report-palette-btn i {
    font-size: 0.9rem;
}

.report-edit-canvas,
.report-view-canvas {
    flex-grow: 1;
    padding: 1rem 1.5rem 2rem;
    background: var(--bs-tertiary-bg);
    overflow: auto;
}

/* Two-column layout for the view page: facet sidebar + canvas. The sidebar
   collapses to a sticky top strip on narrow screens so the dashboard still
   has room to breathe on phones. */
.report-view-body {
    display: flex;
    flex-grow: 1;
    min-height: 0;
    background: var(--bs-tertiary-bg);
}

.report-view-facets {
    flex: 0 0 280px;
    max-width: 280px;
    overflow-y: auto;
    border-right: 1px solid var(--bs-border-color);
    background: var(--bs-body-bg);
    padding: 0.75rem;
    position: relative;
    transition: flex-basis 0.18s, max-width 0.18s, padding 0.18s;
}

/* Collapsed: shrink to a thin gutter that just shows the toggle button.
   The canvas next to it grows automatically because flex-basis drops. */
.report-view-facets.is-collapsed {
    flex: 0 0 36px;
    max-width: 36px;
    padding: 0;
    overflow: hidden;
}

/* Toggle chevron always visible, anchored top-right of the panel.
   In collapsed state the panel itself is only 36px wide, so the button
   centres horizontally and the chevron flips direction. */
.report-view-facets-toggle {
    position: absolute;
    top: 0.4rem;
    right: 0.25rem;
    z-index: 2;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--bs-border-color);
    border-radius: 50%;
    background: var(--bs-body-bg);
    color: var(--bs-secondary);
    cursor: pointer;
    transition: background 0.1s, color 0.1s;
}
.report-view-facets-toggle:hover {
    background: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
}

.report-view-facets.is-collapsed .report-view-facets-toggle {
    right: 4px;
}

.report-view-body .report-view-canvas {
    border-left: none;
}

@media (max-width: 900px) {
    .report-view-body { flex-direction: column; }
    .report-view-facets {
        flex: 0 0 auto;
        max-width: 100%;
        border-right: none;
        border-bottom: 1px solid var(--bs-border-color);
        max-height: 250px;
    }
}

/* Facet panel chrome.

   The panel itself is just a thin orchestrator — actual facet styling
   (header, accordions, value rows) lives in FacetFilterBar.razor.css /
   FilterGroup so we share visuals with the rest of the app. The rules
   below only handle the multi-source layout above the bars. */

.report-facet-panel {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

/* Per-entity-set section on dashboards that mix data sources. The header
   is clickable to collapse the whole section's facets — useful when one
   data source has a lot of groups and the user wants to focus on the
   other. The chevron icon mirrors the FacetFilterBar group convention. */
.report-facet-section + .report-facet-section {
    margin-top: 0.5rem;
}

.report-facet-section-header {
    display: flex;
    align-items: center;
    padding: 0.4rem 0.6rem;
    margin-bottom: 0.3rem;
    border-bottom: 1px solid var(--bs-border-color);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--bs-secondary);
    cursor: pointer;
    user-select: none;
    transition: background 0.1s;
}
.report-facet-section-header:hover {
    background: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
}
.report-facet-section-header .badge {
    font-size: 0.65rem;
}

.report-edit-empty {
    text-align: center;
    padding: 4rem 1rem;
    color: var(--bs-secondary);
}

/* ── GridStack canvas tweaks ─────────────────────────────────────────────── */

.report-grid {
    background: transparent;
    min-height: 200px;
}

.report-grid .grid-stack-item-content {
    inset: 0 !important; /* override GridStack inline padding so cards fill the cell */
    padding: 0;
}

/* Visual hint while dragging — show where the tile will land. */
.report-grid .grid-stack-placeholder > .placeholder-content {
    background: var(--bs-primary-bg-subtle);
    border: 2px dashed var(--bs-primary);
    border-radius: 0.5rem;
}

/* ── Widget tile chrome ──────────────────────────────────────────────────── */

.report-widget-card {
    height: 100%;
    width: 100%;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.5rem;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transition: box-shadow 0.15s, border-color 0.15s;
}

.report-widget.is-editable .report-widget-card:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
    border-color: var(--bs-primary-border-subtle);
}

.report-widget-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.85rem;
    border-bottom: 1px solid var(--bs-border-color);
    background: var(--bs-tertiary-bg);
    user-select: none;
}

.report-widget.is-editable .report-widget-header.report-widget-drag {
    cursor: move;
}

.report-widget-icon {
    color: var(--bs-primary);
    font-size: 0.85rem;
    width: 1rem;
    text-align: center;
}

.report-widget-title {
    margin: 0;
    font-size: 0.85rem;
    font-weight: 600;
    flex-grow: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--bs-body-color);
}

.report-widget-actions {
    display: flex;
    gap: 0.1rem;
    opacity: 0;
    transition: opacity 0.15s;
}

.report-widget:hover .report-widget-actions {
    opacity: 1;
}

.report-widget-body {
    flex-grow: 1;
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    min-height: 0;
}

/* Inline view-mode switchers (metric + bucket dropdowns). Sit between the
   header and the chart body so the title stays uncluttered. Dense look —
   small selects, no labels, just the active option. */
.report-widget-controls {
    display: flex;
    gap: 0.4rem;
    padding: 0.35rem 0.85rem 0.5rem;
    border-bottom: 1px solid var(--bs-border-color);
    background: var(--bs-tertiary-bg);
    flex-wrap: wrap;
}
.report-widget-controls .form-select {
    flex: 1 1 120px;
    max-width: 220px;
    font-size: 0.8rem;
    padding: 0.2rem 1.5rem 0.2rem 0.5rem;
}

/* ── KPI ─────────────────────────────────────────────────────────────────── */

.report-kpi {
    display: flex;
    flex-direction: column;
    justify-content: center;
    height: 100%;
    text-align: left;
}

.report-kpi-label {
    font-size: 0.75rem;
    color: var(--bs-secondary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 0.25rem;
}

.report-kpi-value {
    font-size: 2.25rem;
    font-weight: 700;
    line-height: 1;
    color: var(--bs-body-color);
    font-variant-numeric: tabular-nums;
}

.report-kpi-subtitle {
    font-size: 0.8rem;
    color: var(--bs-secondary);
    margin-top: 0.4rem;
}

.report-kpi-skeleton {
    display: inline-block;
    width: 6ch;
    height: 1em;
    background: linear-gradient(90deg, var(--bs-tertiary-bg) 0%, var(--bs-secondary-bg) 50%, var(--bs-tertiary-bg) 100%);
    background-size: 200% 100%;
    animation: report-shimmer 1.4s linear infinite;
    border-radius: 0.25rem;
}

@keyframes report-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* ── Stat (KPI + sparkline) ──────────────────────────────────────────── */

.report-stat-spark {
    flex-grow: 1;
    min-height: 36px;
    max-height: 60px;
    margin-top: 0.5rem;
    overflow: hidden;
    opacity: 0.7;
}

/* Hide axes / grid for sparkline mode — MudBlazor 9.3 doesn't expose
   toggles for these on the legacy ChartOptions, so we kill them via CSS. */
.report-stat-spark .mud-charts-xaxis,
.report-stat-spark .mud-charts-yaxis,
.report-stat-spark .mud-charts-grid,
.report-stat-spark .mud-charts-axis-line {
    display: none !important;
}

/* ── Gauge ──────────────────────────────────────────────────────────── */

.report-gauge {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    padding: 0.5rem;
}

.report-gauge-svg-wrap {
    position: relative;
    width: 100%;
    max-width: 200px;
    aspect-ratio: 1;
}

.report-gauge-svg {
    width: 100%;
    height: 100%;
    transform: rotate(-90deg);
}

.report-gauge-track {
    fill: none;
    stroke: var(--bs-tertiary-bg);
}

/* The arc — colour is applied inline by the renderer via the threshold
   resolver. transition smooths threshold flips when value changes. */
.report-gauge-svg circle.report-gauge-arc {
    fill: none;
    stroke-linecap: round;
    transition: stroke-dasharray 0.4s ease, stroke 0.2s;
}

.report-gauge-center {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}

.report-gauge-center .report-kpi-value {
    font-size: 1.6rem;
}

/* ── Markdown ───────────────────────────────────────────────────────── */

.report-markdown {
    height: 100%;
    overflow: auto;
    padding: 0.25rem 0.5rem;
    font-size: 0.9rem;
}

.report-markdown h1, .report-markdown h2, .report-markdown h3 {
    margin-top: 0.6rem;
    margin-bottom: 0.4rem;
}

.report-markdown :first-child { margin-top: 0; }

/* ── Heatmap ──────────────────────────────────────────────────────────
   The widget renders the grid directly on .report-heatmap (X labels in
   row 1, Y labels in column 1, value cells fill the body). Inline style
   sets grid-template-columns dynamically based on x-axis count, so we
   only need display: grid + gap here. */
.report-heatmap {
    display: grid;
    gap: 2px;
    align-items: stretch;
    width: 100%;
    height: 100%;
    overflow: auto;
    padding: 0.25rem;
}

.report-heatmap-corner {
    background: transparent;
}

.report-heatmap-xlabel,
.report-heatmap-ylabel {
    font-size: 0.7rem;
    color: var(--bs-secondary);
    padding: 0.15rem 0.3rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.report-heatmap-xlabel {
    text-align: center;
    border-bottom: 1px solid var(--bs-border-color);
}

.report-heatmap-ylabel {
    text-align: right;
    border-right: 1px solid var(--bs-border-color);
}

.report-heatmap-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 0.2rem;
    font-size: 0.7rem;
    font-variant-numeric: tabular-nums;
    color: var(--bs-emphasis-color, var(--bs-body-color));
    transition: filter 0.15s;
    cursor: default;
}

.report-heatmap-cell:hover {
    filter: brightness(1.15);
}

/* ── Charts ──────────────────────────────────────────────────────────────── */

.report-chart {
    flex-grow: 1;
    display: flex;
    align-items: stretch;
    justify-content: center;
    overflow: hidden;
    min-height: 0;
}

.report-chart > * {
    flex-grow: 1;
}

/* Pie/Donut wrapper — forces a square viewport regardless of tile aspect ratio.
   MudChart's pie renderer uses clientWidth/clientHeight at draw time and silently
   collapses to 0×0 in a percentage-sized flex parent. Pinning a min-square here
   guarantees there's always something to draw inside, while max-height:100%
   keeps it from overflowing tall narrow tiles. */
.report-chart-pie-wrap {
    flex-grow: 1;
    aspect-ratio: 1;
    max-width: 100%;
    max-height: 100%;
    min-width: 200px;
    min-height: 200px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto;
}

/* Cartesian (Bar / Line / Area) wrapper — Chart.js needs an explicit-sized
   parent because Responsive=true sizes itself relative to the immediate
   parent's clientWidth/clientHeight. Without this rule it expands to 0×0 in
   a flex column whose only child is `position: relative`-sized.
   The `position: relative` lets Chart.js's absolutely-positioned canvas
   layer correctly. min-height:0 lets it shrink inside flex parents. */
.report-chart-cartesian-wrap {
    flex-grow: 1;
    width: 100%;
    height: 100%;
    min-height: 0;
    position: relative;
}

.report-chart-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    color: var(--bs-secondary);
    font-size: 0.85rem;
    font-style: italic;
}

/* ── Data table ──────────────────────────────────────────────────────────── */

.report-table {
    height: 100%;
    overflow: auto;
    display: flex;
    flex-direction: column;
}

.report-table-grid {
    margin: 0;
    font-size: 0.8rem;
}

.report-table-grid thead th {
    position: sticky;
    top: 0;
    /* Bootstrap's --bs-tertiary-bg is semi-transparent in some themes, so the
       sticky header bleeds through scrolling rows. Use the body bg (always
       fully opaque) plus a strong shadow so the header reads as a distinct
       layer above the data even with light themes. */
    background: var(--bs-body-bg);
    background-clip: padding-box;
    border-bottom: 2px solid var(--bs-border-color);
    box-shadow: 0 2px 4px -2px rgba(0, 0, 0, 0.15);
    font-weight: 600;
    color: var(--bs-emphasis-color, var(--bs-body-color));
    z-index: 2;
}

.report-table-grid td {
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.report-table-footer {
    padding: 0.4rem 0.75rem;
    font-size: 0.75rem;
    color: var(--bs-secondary);
    background: var(--bs-tertiary-bg);
    border-top: 1px solid var(--bs-border-color);
}

/* View-mode only: header click toggles a server-side sort. The cursor +
   hover state make the affordance discoverable without a separate icon
   button per column. */
.report-table-grid th.report-th-sortable {
    cursor: pointer;
    user-select: none;
    transition: background 0.1s;
}
.report-table-grid th.report-th-sortable:hover {
    background: var(--bs-tertiary-bg);
}

/* Inline indicator for the next-page fetch. Sits between table + footer so
   users see "more is loading" without the footer shifting around. */
.report-table-loading-more {
    padding: 0.5rem 0.75rem;
    font-size: 0.75rem;
    color: var(--bs-secondary);
    background: var(--bs-body-bg);
    border-top: 1px solid var(--bs-border-color);
    text-align: center;
}

/* ── Config dialog ───────────────────────────────────────────────────────── */

.report-config-form {
    min-width: 380px;
}

/* Widget-type select in the identity row — wider than the title field
   would naturally let it grow because the labels (icons + descriptions)
   need horizontal room to read cleanly. */
.report-config-type {
    min-width: 220px;
}

/* Compact selects in the AvailableMetrics / AvailableBuckets rows —
   they sit inline with text fields, and full-width selects would push
   the row to wrap. The fixed widths mirror the field's content
   (5-letter agg names, 5-letter bucket names) so they stay tight. */
.report-config-agg {
    min-width: 90px;
    max-width: 110px;
}

.report-config-bucket {
    min-width: 95px;
    max-width: 115px;
}

/* Two-pane "visible vs available" layout for the DataTable column picker.
   Side-by-side on wide dialogs, stacked on narrow screens. */
.report-cols-editor {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.75rem;
}

@media (max-width: 720px) {
    .report-cols-editor { grid-template-columns: 1fr; }
}

.report-cols-pane {
    border: 1px solid var(--bs-border-color);
    border-radius: 0.4rem;
    background: var(--bs-tertiary-bg);
    max-height: 240px;
    overflow-y: auto;
}

.report-cols-pane-header {
    position: sticky;
    top: 0;
    background: var(--bs-body-bg);
    border-bottom: 1px solid var(--bs-border-color);
    padding: 0.35rem 0.6rem;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--bs-secondary);
    z-index: 1;
}

.report-cols-row {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.15rem 0.35rem 0.15rem 0.6rem;
    border-bottom: 1px solid var(--bs-border-color);
    font-size: 0.85rem;
    transition: background 0.1s, border-color 0.1s;
}

.report-cols-row:last-child { border-bottom: none; }

.report-cols-row:hover { background: var(--bs-body-bg); }

/* Drag-and-drop affordances. The grip cursor signals "this row is draggable",
   and a top-border highlight on drag-over shows where the dropped item lands. */
.report-cols-row-draggable { cursor: grab; }
.report-cols-row-draggable:active { cursor: grabbing; }
.report-cols-row-draggable.drag-over {
    border-top: 2px solid var(--bs-primary);
    background: var(--bs-primary-bg-subtle);
}

/* Inline search field at the top of the Available pane — sticks while the
   list scrolls so the filter is always reachable on long entity-sets. */
.report-cols-search {
    position: sticky;
    top: 1.85rem; /* directly under the pane header */
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.25rem 0.5rem;
    background: var(--bs-body-bg);
    border-bottom: 1px solid var(--bs-border-color);
    z-index: 1;
}
.report-cols-search input {
    background: transparent;
    box-shadow: none !important;
    padding: 0;
}
.report-cols-search input:focus { outline: none; }

.report-filter-current {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    background: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.4rem;
    padding: 0.35rem 0.6rem;
    margin-bottom: 0.5rem;
    font-size: 0.8rem;
    word-break: break-all;
}

.report-filter-current code {
    color: var(--bs-primary);
    flex-grow: 1;
}
