/* =========================================================
   Transaction Page Styles
   Menggunakan pola desain yang sama dengan halaman lain
   (Site Performance, Assets Monitor, Executive Overview)
   ========================================================= */

/* Panel shell - border + background only. The content's gutter comes from
   the .transaction-page .dashboard-panel rule below (each MudCardContent
   itself is pa-0). */
.dashboard-panel {
    border: 1px solid #e6e8ec;
    border-radius: 14px;
    background: #ffffff;
}

/* Internal gutter. The page's panels rendered their content flush against
   the card edge (every MudCardContent was given pa-0), while the other
   dashboard panels all keep a consistent padding around their content.
   20px matches Site Performance's --sp-panel-padding - the page whose
   .sp-panel-* classes these panels copy - and matches this page's own
   .chart-panel. Scoped to .transaction-page so the shared .dashboard-panel
   rule (Executive Overview / Site Performance / Dashboard) is untouched. */
.transaction-page .dashboard-panel {
    padding: 20px;
}

/* =========================================================
   SECTION SPACING
   ========================================================= */

/* One flex column with a uniform 16px gap so every card section (Early
   Warning, Filter, list row, Analytics) keeps the same rhythm. Before this,
   the KPI row carried its own mb-3 and Analytics its own margin-top while
   Early Warning / Filter / the list row sat flush against each other with no
   gap at all. The MudGrid's own negative top margin (its column/row gutters)
   is compensated by its first row's padding-top, so it lands on the same 16px
   gap as the other sections. */
.transaction-sections {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* The MudGrid carries its own negative top margin plus an equal padding-top
   on its items (both part of its column/row gutters). Left alone those would
   stack on top of the flex gap and make the gap above the grid land on a
   different value than the other sections. Zero both so the gap above the
   grid is the same unambiguous 16px as everywhere else (the horizontal gutter
   still comes from the items' padding-left). */
.transaction-sections > .mud-grid {
    margin-top: 0;
}

.transaction-sections > .mud-grid > .mud-grid-item {
    padding-top: 0;
}

.transaction-page .analytics-grid {
    margin-top: 0;
}

/* =========================================================
   TRANSACTION LIST + MAP + SELECTED TRANSACTION ROW
   Three panels side by side (see mockup), all the same height. MudGrid's
   flex default (align-items: stretch) already equalizes the three
   .mud-grid-item columns to the tallest one - the missing piece was that
   none of the three panels filled that stretched height themselves, which
   is what left dead empty space under the shorter panels. Making each
   .mud-grid-item a flex container and each panel height:100% + flex-column
   lets every panel's own scrollable body (table / map / detail rows) grow
   to fill the row, instead of the row growing to fit an unbounded panel.
   ========================================================= */

.tx-row > .mud-grid-item {
    display: flex;
}

.tx-row .dashboard-panel {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
}

.tx-row .mud-card-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.tx-row .sp-panel-header {
    flex-shrink: 0;
}

/* Panel header - sama dengan .sp-panel-header di sitePerformance.css */
.sp-panel-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 16px;
}

.sp-panel-heading {
    min-width: 0;
}

.sp-panel-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    flex-shrink: 0;
}

/* Panel title - sama dengan .sp-panel-title di sitePerformance.css */
.sp-panel-title {
    margin: 0;
    font-size: 16px !important;
    font-weight: 700 !important;
    line-height: 1.3;
    color: #172033;
}

.sp-panel-subtitle {
    color: #667085;
}

/* Action button - sama dengan .sp-action-button di sitePerformance.css */
.sp-action-button {
    padding: 4px 0 !important;
    color: #2563eb !important;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.3;
    text-transform: none;
}

/* =========================================================
   KPI CARDS - menggunakan komponen KpiCard yang sama
   ========================================================= */

/* KPI body centering untuk KPI tanpa chart */
.kpi-card-body-centered {
    justify-content: center !important;
    align-items: flex-start !important;
}

.kpi-card-body-centered .kpi-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    width: auto;
}

.kpi-card-body-centered .kpi-value {
    text-align: left;
    width: auto;
}

.kpi-card-body-centered .kpi-compare {
    text-align: left;
    width: auto;
}

.kpi-card-body-centered .kpi-link {
    text-align: left;
    width: auto;
}

/* =========================================================
   EARLY WARNING
   ========================================================= */

/* Carousel - same sliding-window mechanics as Site Performance's own .tank-carousel/.tank-track/
   .tank-card-wrapper (sitePerformance.css), just 4 cards visible instead of 3: a card's flex-basis and
   the track's translateX step must stay the same percentage (25% here) since both are percentages of
   the same reference box (the track's own width == the carousel's width), see TransactionEarlyWarning's
   own code-behind comment. */
.alert-carousel {
    position: relative;
    width: 100%;
    overflow: hidden;
}

.alert-track {
    display: flex;
    /* Every wrapper (and therefore every card) takes the height of the tallest one in the track, so
       a short warning never renders as a smaller box next to a long one. */
    align-items: stretch;
    width: 100%;
    transition: transform 0.35s ease;
}

.alert-card-wrapper {
    flex: 0 0 25%;
    max-width: 25%;
    min-width: 0;
    padding: 0 5px;
    box-sizing: border-box;
    /* Needs to be a flex box itself for the card to fill the stretched height. */
    display: flex;
}

.alert-prev-button,
.alert-next-button {
    position: absolute;
    top: 50%;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    transform: translateY(-50%);
    background: var(--sp-bg, #fff);
    border: 1px solid var(--sp-border, #e4e7ec);
    border-radius: 50%;
    box-shadow: 0 2px 6px rgba(16, 24, 40, 0.08);
    cursor: pointer;
    z-index: 5;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.alert-prev-button:hover,
.alert-next-button:hover {
    background: var(--sp-bg-soft, #f9fafb);
    border-color: #d0d5dd;
}

.alert-prev-button {
    left: 0;
}

.alert-next-button {
    right: 0;
}

.alert-carousel-indicator {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin-top: 14px;
}

.alert-indicator {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #d8dee8;
    transition: all 0.2s ease;
}

.alert-indicator.active {
    width: 20px;
    border-radius: 5px;
    background: var(--sp-primary, #2563eb);
}

.alert-card {
    display: flex;
    gap: 10px;
    padding: 14px 16px;
    border-radius: 8px;
    border: 1px solid transparent;
    /* Fill the wrapper in both directions: equal width (1/4 of the row) and equal height (the
       tallest card in the track), so every warning box is exactly the same size. */
    flex: 1;
    box-sizing: border-box;
}

.alert-card-red {
    background: #fef2f2;
    border-color: #fecaca;
}

.alert-card-orange {
    background: #fff7ed;
    border-color: #fed7aa;
}

.alert-card-amber {
    background: #fffbeb;
    border-color: #fde68a;
}

/* EARLY WARNING heading in red, scoped to this panel only - .sp-panel-title itself stays the
   neutral color Site Performance's own panels use. */
.early-warning-title {
    color: #dc2626 !important;
}

.alert-icon {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    font-size: 18px;
    flex-shrink: 0;
    padding-top: 2px;
}

.alert-icon-red {
    color: #dc2626;
}

.alert-icon-orange {
    color: #f97316;
}

.alert-icon-amber {
    color: #d97706;
}

.alert-content {
    flex: 1;
    min-width: 0;
}

.alert-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 4px;
}

.alert-title {
    font-size: 13px;
    font-weight: 700;
}

.alert-title-red {
    color: #dc2626;
}

.alert-title-orange {
    color: #f97316;
}

.alert-title-amber {
    color: #d97706;
}

.alert-time {
    font-size: 11px;
    color: #667085;
    white-space: nowrap;
}

.alert-transaction-id {
    font-size: 11px;
    color: #667085;
    margin-bottom: 4px;
}

.alert-summary {
    font-size: 12px;
    color: #374151;
}

/* =========================================================
   FILTER PANEL
   ========================================================= */

.filter-row {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-wrap: wrap;
}

.filter-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 140px;
    flex: 1;
}

.filter-label {
    font-size: 11px;
    font-weight: 600;
    color: #667085;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

.filter-date-display {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 40px;
    padding: 0 12px;
    border: 1px solid #bdbdbd;
    border-radius: 12px;
    font-size: 13px;
    color: #424242;
    background: transparent;
}

.filter-select {
    font-size: 13px;
}

/* Same control shell as the page header's Site/Period selects (12px rounded
   outline, #bdbdbd border, ~40px tall) so the filter panel's dropdowns read
   as part of the same control set instead of falling back to MudBlazor's
   default 4px corners. Height is built the same padding-only way the header
   builds it (see .assets-panel .mud-input-slot) rather than an explicit
   height, which would stack on the content-box input and overshoot 40px. */
.filter-select .mud-input-slot {
    padding-top: 11px !important;
    padding-bottom: 10px !important;
}

.filter-select .mud-input-outlined-border {
    border-color: #bdbdbd;
    border-radius: 12px !important;
}

.filter-select .mud-input:hover .mud-input-outlined-border {
    border-color: #98a2b3;
}

.filter-actions {
    display: flex;
    gap: 8px;
    margin-left: auto;
}

.filter-btn {
    min-width: 100px;
    height: 40px;
    border-radius: 12px !important;
    font-weight: 600;
    text-transform: none;
}

/* =========================================================
   TRANSACTION TABLE
   ========================================================= */

.transaction-table {
    width: 100%;
}

.transaction-table .mud-table-head {
    background: #fafbfc;
}

.transaction-table .mud-table-head .mud-table-cell {
    color: #475467;
    font-size: 11px;
    font-weight: 600;
    padding: 8px 6px;
    white-space: nowrap;
}

.transaction-table .mud-table-body .mud-table-cell {
    color: #344054;
    font-size: 11px;
    padding: 8px 6px;
    border-bottom: 1px solid #eef0f2;
}

/* Chips - same compact filled pills as Assets Monitor's .asset-table. Also scoped to .detail-content
   (Selected Transaction's own Type/Status chips) so they read as the same chip style instead of
   falling back to MudBlazor's taller, more saturated default outside .transaction-table. */
.transaction-table .mud-chip,
.detail-content .mud-chip {
    height: 20px;
    min-height: 20px;
    font-size: 10px;
    font-weight: 600;
    border-radius: 10px;
}

.transaction-table .mud-chip-filled.mud-chip-color-primary,
.detail-content .mud-chip-filled.mud-chip-color-primary {
    background: #eff6ff;
    color: #2563eb;
}

.transaction-table .mud-chip-filled.mud-chip-color-success,
.detail-content .mud-chip-filled.mud-chip-color-success {
    background: #ecfdf3;
    color: #039855;
}

.transaction-table .mud-chip-filled.mud-chip-color-secondary,
.detail-content .mud-chip-filled.mud-chip-color-secondary {
    background: #fff7ed;
    color: #ea580c;
}

.transaction-table .mud-chip-filled.mud-chip-color-warning,
.detail-content .mud-chip-filled.mud-chip-color-warning {
    background: #fffaeb;
    color: #b54708;
}

.transaction-table .mud-chip-filled.mud-chip-color-error,
.detail-content .mud-chip-filled.mud-chip-color-error {
    background: #fef3f2;
    color: #d92d20;
}

.transaction-table .mud-chip-filled.mud-chip-color-default,
.detail-content .mud-chip-filled.mud-chip-color-default {
    background: #f2f4f7;
    color: #475467;
}

/* Inside .tx-row (see above) the table becomes the flexible part of the
   panel - it grows to fill the row's height and scrolls internally, while
   the header and pagination stay put. MudTable's own scroll area is
   .mud-table-container, not the root element. */
.tx-row .transaction-table {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.tx-row .transaction-table .mud-table-container {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
}

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    color: #9ca3af;
}

.empty-state i {
    font-size: 32px;
}

.empty-state p {
    margin: 0;
    font-size: 14px;
}

/* Pagination */
.pagination-section {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 12px;
    flex-wrap: wrap;
    gap: 12px;
}

.tx-row .pagination-section {
    flex-shrink: 0;
}

.pagination-info {
    font-size: 12px;
    color: #667085;
}

.pagination-controls {
    display: flex;
    align-items: center;
    gap: 12px;
}

.page-size-select {
    width: auto;
    min-width: 92px;
    flex-shrink: 0;
}

/* Fully rounded pill (not just a 12px radius) - matches the mockup's
   compact "10 / page" dropdown. */
.page-size-select .mud-input-outlined-border {
    border-color: #e4e7ec;
    border-radius: 999px !important;
}

.page-size-select .mud-input-slot {
    padding: 5px 12px !important;
    font-size: 13px;
    color: #344054;
}

.page-size-select .mud-input-outlined {
    border-radius: 999px;
}

.page-size-select .mud-select-icon {
    color: #98a2b3;
}

/* MudPagination - copied as-is from Assets Monitor's .assets-panel
   .mud-pagination* rules (assetMonitor.css) so the two lists' pagination
   reads as one shared component: small boxed squares (8px radius) instead
   of MudBlazor's default pill/circle, dashboard blue instead of the
   default purple, filled blue for the selected page. */
.transaction-page .mud-pagination {
    margin-top: 2px;
    gap: 2px;
    flex: 0 0 auto;
    flex-wrap: nowrap;
}

.transaction-page .mud-pagination-item {
    margin: 0;
    flex: 0 0 auto;
}

.transaction-page .mud-pagination-item .mud-button-root {
    min-width: 26px !important;
    width: 26px !important;
    height: 26px !important;
    padding: 0 !important;

    border-radius: 8px !important;
    border: 1px solid #d0d5dd !important;
    background: #ffffff !important;

    color: #475467 !important;
    font-size: 12px !important;
    font-weight: 600 !important;
    line-height: 1 !important;
}

.transaction-page .mud-pagination-item .mud-button-root:hover {
    border-color: #2563eb !important;
    background: #f5f8ff !important;
    color: #2563eb !important;
}

.transaction-page .mud-pagination-item-selected .mud-button-root,
.transaction-page .mud-pagination-item .mud-button-outlined-primary {
    border-color: #2563eb !important;
    background: #2563eb !important;
    color: #ffffff !important;
}

/* The "…" spacer has no button - keep it muted and aligned with the boxes. */
.transaction-page .mud-pagination-item > span {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    color: #98a2b3;
    font-size: 12px;
}

/* Export button - same shell as Assets Monitor's .asset-filter-button /
   .asset-export-button (40px tall, 12px radius, #bdbdbd border, #475467
   text, sized to its own label). */
.transaction-page .export-btn.mud-button-root {
    height: 40px !important;
    min-width: auto;
    padding-left: 12px !important;
    padding-right: 12px !important;
    border-radius: 12px !important;
    font-weight: 600;
    text-transform: none;
    white-space: nowrap;
}

/* =========================================================
   HOVER STATES
   ========================================================= */

/* Interaction styling matches the other dashboard pages (e.g. Assets
   Monitor's .asset-filter-button / .selected-asset-panel .mud-button-root):
   outlined controls rest grey (#475467 on a #bdbdbd border) and turn
   primary-blue on hover; the filled action uses the page's #2563eb; and
   hoverable surfaces pick up a soft grey wash instead of MudBlazor's
   heavier default hover. */

/* Outlined buttons: Reset, Export. Scoped to .filter-btn/.export-btn
   specifically (not the blanket .mud-button-outlined this used to be) so
   MudPagination's page numbers and Prev/Next arrows are left on MudBlazor's
   own default outlined styling, enabled and disabled alike - same as Assets
   Monitor, which never overrides .mud-button-outlined at all. */
.transaction-page .filter-btn.mud-button-outlined,
.transaction-page .export-btn.mud-button-outlined {
    color: #475467 !important;
    border-color: #bdbdbd !important;
}

.transaction-page .filter-btn.mud-button-outlined:hover,
.transaction-page .export-btn.mud-button-outlined:hover {
    color: #2563eb !important;
    border-color: #98a2b3 !important;
    background-color: #f2f5fa !important;
}

/* Filled primary action: Apply Filter, current page number. */
.transaction-page .mud-button-filled.mud-button-filled-primary {
    background-color: #2563eb !important;
    color: #ffffff !important;
}

.transaction-page .mud-button-filled.mud-button-filled-primary:hover {
    background-color: #1d4ed8 !important;
}

/* Hoverable surfaces - the alert cards and detail rows are clickable in
   spirit (they read as rows), so give them the same soft grey wash the
   reference pages use for hoverable rows. */
.alert-card {
    transition: background-color 0.15s ease;
}

.alert-card:hover {
    background: #f9fafb;
}

.detail-row {
    transition: background-color 0.15s ease;
}

.detail-row:hover {
    background: #f9fafb;
}

/* Table rows keep the reference's soft grey hover rather than MudBlazor's
   default (slightly stronger) tint. Scoped through .transaction-page so it
   beats MudBlazor's own .mud-table-hover rule (same specificity, but loaded
   earlier). */
.transaction-page .transaction-table .mud-table-row:hover {
    background-color: #f8fafc;
}

.transaction-table .mud-table-row.transaction-row--selected {
    background: #eff4ff;
}

.transaction-row-arrow.mud-icon-button {
    color: #98a2b3;
}

.transaction-table .mud-table-row:hover .transaction-row-arrow.mud-icon-button {
    color: #475467;
}

.transaction-row-arrow--active.mud-icon-button {
    color: #2563eb !important;
}

/* =========================================================
   MAP
   ========================================================= */

.map-legend {
    display: flex;
    gap: 12px;
    font-size: 11px;
    color: #667085;
}

.legend-item {
    display: flex;
    align-items: center;
    gap: 4px;
}

.legend-color {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    display: inline-block;
}

.map-container {
    height: 300px;
    background: #f3f4f6;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    overflow: hidden;
}

/* Inside .tx-row the map panel sits next to a table and a detail list that
   are both allowed to grow - the map should grow with them (filling the
   row's full height) instead of staying pinned at a fixed 300px. */
.tx-row .map-container {
    height: auto;
    flex: 1;
    min-height: 260px;
}

.map-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    color: #9ca3af;
}

.map-placeholder i {
    font-size: 48px;
}

.map-placeholder p {
    margin: 0;
    font-size: 14px;
    font-weight: 500;
}

.map-note {
    font-size: 11px;
    color: #d1d5db;
}

/* Flow view shown inside .map-container once a transaction row is selected
   (see TransactionMap.razor) - replaces .map-placeholder, same container. */
.map-flow {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 24px;
    width: 100%;
    padding: 0 24px;
}

.map-flow-node {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

.map-flow-pin {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 18px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}

.map-flow-label {
    font-size: 13px;
    font-weight: 600;
    color: #1d2939;
}

.map-flow-sublabel {
    font-size: 11px;
    color: #667085;
}

.map-flow-path {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    min-width: 80px;
}

.map-flow-line {
    width: 100%;
    height: 2px;
    background: repeating-linear-gradient(90deg, #98a2b3 0, #98a2b3 6px, transparent 6px, transparent 12px);
}

.map-flow-volume {
    font-size: 11px;
    font-weight: 600;
    color: #475467;
    white-space: nowrap;
}

.map-flow-footer {
    position: absolute;
    bottom: 12px;
    left: 16px;
    right: 16px;
    display: flex;
    justify-content: space-between;
    font-size: 11px;
    color: #667085;
}

.map-flow-footer i {
    margin-right: 4px;
}

.map-flow ~ .map-note {
    position: absolute;
    bottom: 32px;
    left: 50%;
    transform: translateX(-50%);
}

/* =========================================================
   DETAIL PANEL
   ========================================================= */

.detail-status {
    font-size: 12px;
    font-weight: 600;
}

.detail-content {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* From/To entity cards - the role label ("From (Fuel Truck)") sits on its own line, then the icon chip
   (role-colored: violet for From, orange for To, matching the mockup) + name/sub-lines below it. */
.detail-entity {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.detail-entity-main {
    display: flex;
    align-items: flex-start;
    gap: 12px;
}

.detail-entity-icon {
    flex-shrink: 0;
    width: 36px;
    height: 36px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.detail-entity-icon--from {
    background: #f3e8ff;
    color: #7c3aed;
}

.detail-entity-icon--to {
    background: #fff7ed;
    color: #ea580c;
}

.detail-entity-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.detail-entity-role {
    font-size: 11px;
    font-weight: 600;
    color: #667085;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

.detail-entity-name {
    font-size: 14px;
    font-weight: 700;
    color: #172033;
}

.detail-entity-sub {
    font-size: 12px;
    color: #667085;
}

/* Wraps .detail-content so the row list can scroll on its own inside
   .tx-row (see above) once there are more detail rows than the row's
   height has space for, while .detail-link (now a sibling, pinned below
   this) always stays visible instead of scrolling out of view. */
.tx-row .detail-content-scroll {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
}

.tx-row .detail-link {
    flex-shrink: 0;
}

.tx-row .detail-empty {
    flex: 1;
    justify-content: center;
}

.detail-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    padding: 4px 0;
}

.detail-row:last-of-type {
    border-bottom: none;
}

.detail-label {
    font-size: 12px;
    color: #667085;
    font-weight: 500;
    min-width: 120px;
}

.detail-value {
    font-size: 13px;
    color: #1d2939;
    font-weight: 600;
    text-align: right;
    flex: 1;
}

.detail-link {
    margin-top: 12px;
    font-size: 13px;
    color: #2563eb;
    text-decoration: none;
    font-weight: 500;
    text-align: center;
    padding: 8px;
    border: 1px solid #dbeafe;
    border-radius: 6px;
    background: #eff6ff;
}

.detail-link:hover {
    background: #dbeafe;
}

.detail-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 40px 20px;
    color: #9ca3af;
}

.detail-empty i {
    font-size: 32px;
}

.detail-empty p {
    margin: 0;
    font-size: 13px;
}

/* =========================================================
   ANALYTICS CHARTS
   ========================================================= */

.analytics-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-top: 24px;
}

.chart-panel {
    padding: 20px;
}

/* CSS Grid's default align-items: stretch already makes every .chart-panel
   match the tallest card in the row (Daily Transaction Volume, driven by
   its 250px chart) - that part is correct. What was missing is that the
   shorter cards' own content (the donut row, the site bar list + its total)
   just sat at the top of that extra height instead of using it. Turning the
   card content into a flex column lets each card decide how to use that
   slack: the donut row centers itself in it (margin auto), the site list's
   total row sinks to the bottom as a footer (margin-top: auto) - see both
   below. */
.analytics-grid .chart-panel {
    display: flex;
    flex-direction: column;
}

.analytics-grid .chart-panel .mud-card-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.chart-container {
    height: 280px;
}

/* Donut + legend side by side (Transaction Type Distribution / Transaction
   Status) - same proven pattern as .activity-chart-container /
   .activity-chart-center in assetMonitor.css: a fixed-size relative wrapper
   around the ApexChart donut with an absolutely centered overlay for the
   total, since ApexCharts' own donut center label isn't used here (kept off
   via PlotOptionsDonut.Labels.Show = false in the component, for the same
   reason AssetActivityBreakdown keeps it off - full control over the
   number's typography). */
.chart-donut-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 24px;
    margin-top: auto;
    margin-bottom: auto;
}

/* Shown instead of .chart-donut-row when a live chart's period has no data at all (0 transactions) -
   same flex-fill-and-center behaviour as .detail-empty, just reused for a donut-shaped slot. */
.chart-empty-state {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1;
    min-height: 150px;
}

.chart-donut-wrap {
    position: relative;
    width: 150px;
    height: 150px;
    flex: 0 0 150px;
}

.chart-donut-wrap .apexcharts-canvas {
    height: 150px !important;
}

.chart-donut-center {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    pointer-events: none;
}

.chart-donut-total {
    font-size: 22px;
    font-weight: 700;
    color: #1d2939;
    line-height: 1.2;
}

.chart-donut-caption {
    font-size: 11px;
    color: #98a2b3;
}

.chart-legend-list {
    display: flex;
    flex-direction: column;
    gap: 14px;
    min-width: 0;
}

.chart-legend-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.legend-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
    margin-top: 5px;
}

.legend-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.legend-label {
    font-size: 13px;
    font-weight: 600;
    color: #1d2939;
}

.legend-value {
    font-size: 12px;
    color: #98a2b3;
    margin-top: 1px;
}

/* Unreconciled Volume by Site - a plain progress-bar list, not an ApexChart
   (the mockup draws it as rows of label/bar/value/percentage, not a bar
   chart axis). */
.site-bar-list {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin-top: 12px;
}

.site-bar-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.site-bar-label {
    font-size: 12px;
    font-weight: 600;
    color: #1d2939;
    min-width: 62px;
    flex-shrink: 0;
}

.site-bar-track {
    flex: 1;
    height: 8px;
    background: #eef1f5;
    border-radius: 4px;
    overflow: hidden;
}

.site-bar-fill {
    height: 100%;
    background: #2563eb;
    border-radius: 4px;
}

.site-bar-track-spacer {
    flex: 1;
}

.site-bar-value {
    font-size: 12px;
    font-weight: 700;
    color: #1d2939;
    min-width: 40px;
    text-align: right;
    flex-shrink: 0;
}

.site-bar-percentage {
    font-size: 12px;
    color: #98a2b3;
    min-width: 44px;
    text-align: right;
    flex-shrink: 0;
}

.site-bar-total {
    margin-top: auto;
    padding-top: 12px;
    border-top: 1px solid #eef0f2;
}

.site-bar-total .site-bar-value,
.site-bar-total .site-bar-percentage {
    color: #1d2939;
    font-weight: 700;
}

/* =========================================================
   RESPONSIVE
   ========================================================= */

@media (max-width: 1400px) {
    .analytics-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 1200px) {
    .filter-row {
        flex-direction: column;
    }
    .filter-field {
        width: 100%;
    }
    .filter-actions {
        width: 100%;
        margin-left: 0;
    }
}

@media (max-width: 768px) {
    .analytics-grid {
        grid-template-columns: 1fr;
    }
    .pagination-section {
        flex-direction: column;
        align-items: flex-start;
    }
}

/* TRANSACTION - loading skeleton. Same stage / real / overlay pattern as Executive Overview and Site
   Performance (css/dashboard.css: .eo-stage/.eo-real-hidden/.eo-real-visible/.eo-skeleton-overlay,
   .eo-fade-in) - real content stays mounted (so nothing is torn down/re-initialised on every filter
   change) and defines the stage's height, the skeleton overlay fills it exactly. Only the skeleton's
   own shape differs here, matching Transaction's actual layout (KPI row, Early Warning, Filter Panel,
   the List/Map/Detail row, Analytics) instead of Executive Overview/Site Performance's panel grid.
   .eo-skeleton-block and the eo-fade-in keyframe are reused as-is from dashboard.css (loaded globally
   for every page, see wwwroot/index.html), so the loading motion reads identically everywhere. */

.tx-stage {
    position: relative;
}

.tx-real-hidden {
    visibility: hidden;
    pointer-events: none;
}

.tx-real-visible {
    visibility: visible;
    animation: eo-fade-in 260ms ease both;
}

.tx-skeleton-overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.tx-skeleton-overlay .kpi-grid {
    flex: 0 0 auto;
}

.tx-skeleton-row {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 8px;
    flex: 1 1 0;
    min-height: 0;
}

@media (max-width: 900px) {
    .tx-skeleton-row {
        grid-template-columns: 1fr;
    }
}

/* TRANSACTION LOCATION MAP - real MapLibre map (js/transactionmap.js). The canvas fills .map-container
   (which already stretches to the row's height inside .tx-row); the overlays sit on top of it. */

.transaction-map-canvas {
    position: absolute;
    inset: 0;
}

.tx-map-overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    text-align: center;
    font-size: 13px;
    font-weight: 500;
    color: #667085;
    background: rgba(243, 244, 246, 0.72);
    pointer-events: none;
}

.tx-map-overlay--error {
    color: #b42318;
}

.tx-map-note {
    position: absolute;
    left: 8px;
    bottom: 8px;
    z-index: 2;
    padding: 2px 8px;
    border-radius: 6px;
    font-size: 11px;
    color: #475467;
    background: rgba(255, 255, 255, 0.88);
    pointer-events: none;
}

.tx-map-note--warning {
    bottom: 32px;
    color: #b54708;
}

/* Top-left / top-right controls drawn over the canvas (js/transactionmap.js owns the behaviour). */
.tx-map-controls,
.tx-map-fullscreen {
    position: absolute;
    top: 10px;
    z-index: 6;
    display: flex;
    gap: 6px;
}

.tx-map-controls {
    left: 10px;
    flex-direction: column;
}

.tx-map-fullscreen {
    right: 10px;
}

.tx-map-control.mud-icon-button {
    background: #ffffff;
    border: 1px solid #e4e7ec;
    border-radius: 8px;
    box-shadow: 0 2px 6px rgba(16, 24, 40, 0.08);
    color: #344054;
}

.tx-map-control.mud-icon-button:hover {
    background: #f9fafb;
}

/* Bottom-right movement summary ("Transactions (MTD)"): Storage → Truck / Truck → Equipment / Total. */
.tx-map-summary {
    position: absolute;
    right: 12px;
    bottom: 12px;
    z-index: 6;
    min-width: 208px;
    padding: 10px 12px;
    background: #ffffff;
    border: 1px solid #e4e7ec;
    border-radius: 10px;
    box-shadow: 0 4px 12px rgba(16, 24, 40, 0.12);
}

.tx-map-summary-title {
    margin-bottom: 6px;
    font-size: 12px;
    font-weight: 700;
    color: #101828;
}

.tx-map-summary-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 18px;
    padding: 3px 0;
    font-size: 12px;
    color: #475467;
}

.tx-map-summary-row > span:last-child {
    font-weight: 700;
    color: #101828;
}

.tx-map-summary-total {
    margin-top: 6px;
    padding-top: 8px;
    border-top: 1px solid #eaecf0;
    font-weight: 700;
    color: #101828;
}

/* Fullscreen: the container is what gets the browser's fullscreen state, so it needs its own
   background and a height the map can fill. */
#transaction-map-container:fullscreen {
    width: 100vw;
    height: 100vh;
    background: #0b1220;
}

/* Selected Transaction: the second/third line under From / To (equipment model, driver, operator ...). */
.detail-value small {
    display: inline-block;
    font-size: 11px;
    font-weight: 400;
    color: #667085;
}

/* A row can be selected by clicking anywhere on it, not only the arrow. */
.transaction-table .mud-table-body .mud-table-row {
    cursor: pointer;
}
