/* ========================================
   BLAZORPDF VIEWER FIXES
   ======================================== */

/*
 * Gotho.BlazorPdf hardcodes height:100vh on .blazorpdf__scroll. We override
 * with calc(100vh - 64px) so the scroll container fills everything below the
 * AppBar. The viewer div extends to bottom:0 (z-index 950 covers the BottomNav),
 * and padding-bottom on the scroll container reserves room so the last PDF
 * content can be scrolled fully into view above the nav area.
 */
/* Positioning for the full-screen PDF viewer overlay.
   On mobile (< 960px) it covers the full viewport from the AppBar down.
   On desktop (≥ 960px) the persistent sidebar drawer (240px) is always
   visible, so left must start after the drawer to avoid overlap. */
.report-pdf-viewer {
    position: fixed;
    top: 64px;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 950;
    overflow: hidden;
}

@media (min-width: 960px) {
    .report-pdf-viewer {
        left: 240px;
    }
}

/* The PdfViewer component root div has width:auto and expands to the
   canvas width (e.g. 595px for A4 at 1x scale). That makes
   .blazorpdf__scroll { width:100% } inherit 595px instead of the
   actual viewport width, so scrollWidth==clientWidth and horizontal
   scroll is impossible. Capping the direct child to 100% of
   .report-pdf-viewer forces .blazorpdf__scroll to be container-wide. */
.report-pdf-viewer > * {
    max-width: 100% !important;
}

.report-pdf-viewer .blazorpdf__scroll {
    /* Viewer extends to bottom:0 and covers BottomNav (z-index 950 > 900).
       Full height = 100vh minus AppBar only. padding-bottom reserves space
       so the last PDF content can be scrolled into view above the nav area. */
    height: calc(100vh - 64px) !important;
    padding-bottom: calc(64px + env(safe-area-inset-bottom)) !important;
    /* The PdfViewer wrapper chain auto-sizes to the canvas width (595px),
       so width:100% also becomes 595px. Setting 100vw directly bypasses
       the parent chain and ensures the scroll container is viewport-wide,
       making the 595px canvas overflow and enabling horizontal scroll. */
    width: 100vw !important;
    overflow-x: auto !important;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    /* Allow both vertical and horizontal pan natively even if child JS
       calls preventDefault() on touch events (pdf.js textLayer does this) */
    touch-action: pan-x pan-y;
    /* flex-start anchors the canvas at x=0 so all overflow is to the
       right and fully accessible via scrollLeft (center would hide the
       left half of any overflow behind a negative offset). */
    align-items: flex-start !important;
}

/* pdf.js textLayer intercepts touch events for text selection and may set
   touch-action:none as an inline style — !important overrides that so the
   browser still performs native pan in both axes.
   user-select:none prevents text highlight during mouse drag (our JS handles
   scroll, so native text selection is not useful inside the PDF viewer). */
.report-pdf-viewer .textLayer {
    touch-action: pan-x pan-y !important;
    user-select: none !important;
}

/* Grab cursor signals that the PDF is pannable with the mouse */
.report-pdf-viewer .blazorpdf__scroll {
    cursor: grab;
}
.report-pdf-viewer .blazorpdf__scroll:active {
    cursor: grabbing;
}

/* Replace the package's hardcoded dark (#161719) background with the app's
   surface colour so the viewer matches the app's light/dark theme. Applies
   to all three elements the package uses to paint the dark background. */
.report-pdf-viewer .blazorpdf__scroll,
.report-pdf-viewer .blazorpdf-pdf,
.report-pdf-viewer .blazorpdf-pdf__pdf-container {
    background-color: var(--mud-palette-background) !important;
}

/* Override the hardcoded #007bff loader bar with the app primary colour.
   Global selector + !important needed because the element may sit outside
   the report wrapper and the package CSS has no specificity advantage. */
.blazorpdf__loader {
    background-color: var(--mud-palette-primary) !important;
}

/* ========================================
   MUDBLAZOR OVERRIDES
   ======================================== */

/* MudBlazor reduziert die AppBar-Toolbar-Höhe auf kleinen Screens per Media-Query
   (< 600px Portrait: −1/8, Landscape: −1/4). Das führt zu einem Spalt zwischen
   der AppBar und sticky positionierten Elementen, die `top: var(--mud-appbar-height)`
   nutzen. Override erzwingt konsistente Toolbar-Höhe auf allen Viewport-Größen. */
.mud-appbar .mud-toolbar-appbar {
    height: var(--mud-appbar-height) !important;
}

/* mud-main-content padding-top folgt derselben Logik wie die Toolbar-Höhe: auf
   kleinen Screens reduziert MudBlazor den Offset auf 7/8 der AppBar-Höhe, was
   nach dem Toolbar-Override einen Sprung im Sticky-Bar-Verhalten erzeugt.
   Override synchronisiert den Content-Offset mit der nun fixen AppBar-Höhe. */
.mud-main-content {
    padding-top: var(--mud-appbar-height) !important;
}

/* mud-toolbar-gutters wechselt bei ≥ 600px von 16px auf 24px horizontales Padding,
   was die AppBar-Icons sichtbar vom Rand wegspringen lässt. Für eine Mobile-First-App
   ist der kompakte Wert auf allen Viewport-Größen sinnvoller. */
.mud-appbar .mud-toolbar-gutters {
    padding-left: 16px !important;
    padding-right: 16px !important;
}

/* ========================================
   MOBILE / PWA OVERSCROLL
   ======================================== */

/* Suppress native browser pull-to-refresh (Android Chrome) so our custom
   PTR indicator takes over. "contain" keeps bounce-scroll within the element
   without triggering the browser's own refresh animation. */
html, body {
    overscroll-behavior-y: contain;
}

/* ========================================
   PULL-TO-REFRESH INDICATOR
   (element created dynamically by pull-refresh.js)
   ======================================== */

.ptr-indicator {
    position: fixed;
    top: calc(var(--mud-appbar-height, 64px) + 8px);
    left: 50%;
    /* initial position: hidden above viewport (JS sets translateY at runtime) */
    transform: translateX(-50%) translateY(-88px);
    width: 44px;
    height: 44px;
    background: var(--mud-palette-surface);
    border-radius: 50%;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.18);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 500;          /* above page content, below dialogs (~1200) */
    pointer-events: none;  /* never intercepts taps */
    will-change: transform;
}

@keyframes ptr-spin {
    to { transform: rotate(360deg); }
}

.ptr-indicator.ptr-spinning svg {
    animation: ptr-spin 0.75s linear infinite;
    transform-origin: center;
}

.ptr-indicator.ptr-spinning .ptr-arc {
    stroke-dashoffset: 22; /* ~75 % of circumference — indeterminate arc */
}

/* ========================================
   GLOBAL BOTTOM SHEET DIALOG STYLES
   ======================================== */

/* Bottom Sheet Backdrop - darker and at the bottom */
.bottom-sheet-backdrop {
    background-color: rgba(0, 0, 0, 0.5) !important;
}

/* MudBlazor Dialog Container Override for Bottom Position */
.mud-dialog-container {
    align-items: flex-end !important;
    justify-content: center !important;
    padding: 0 !important;
}

/* Force bottom-sheet dialogs to align at bottom without padding */
.bottom-sheet-container {
    align-items: flex-end !important;
    justify-content: center !important;
    padding: 0 !important;
}

/* Remove all default MudBlazor dialog spacing for bottom sheets */
.bottom-sheet-container .mud-dialog {
    margin: 0 !important;
}

/* Global styles for dialogs at bottom position */
.mud-dialog-container:has(.mud-dialog) {
    align-items: flex-end !important;
    padding: 0 !important;
}

/* Ensure full width on mobile */
@media (max-width: 959px) {
    .bottom-sheet-container {
        padding: 0 !important;
    }

    .bottom-sheet-container .mud-dialog {
        width: 100vw !important;
        max-width: none !important;
        left: 0 !important;
        right: 0 !important;
        margin: 0 !important;
    }
}

/* ========================================
   PAGE NAVIGATION TRANSITION ANIMATIONS
   ======================================== */

/* Slide from Right to Left (Forward navigation) */
.page-slide-right-to-left {
    animation: slideRightToLeftPage 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes slideRightToLeftPage {
    from {
        transform: translateX(100%);
        opacity: 0;
    }
    to {
        transform: translateX(0);
        opacity: 1;
    }
}

/* Slide from Left to Right (Back navigation) */
.page-slide-left-to-right {
    animation: slideLeftToRightPage 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes slideLeftToRightPage {
    from {
        transform: translateX(-100%);
        opacity: 0;
    }
    to {
        transform: translateX(0);
        opacity: 1;
    }
}

/* Fade In (Default) */
.page-fade-in {
    animation: fadeInPage 0.3s ease-out;
}

@keyframes fadeInPage {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

/* MudMainContent wrapper for transitions */
:deep .mud-main-content {
    position: relative;
    overflow-x: hidden;  /* Prevent horizontal scrollbar during transitions */
}

/* Responsive media queries for FiscalYears page */
@media (max-width: 599px) {
    .fiscal-years-container {
        padding: 8px;
    }

    .fab-fixed-bottom {
        right: 8px !important;
    }
}

/* ========================================
   SWIPE-REVEAL CARDS
   (shared by Journal, Owners, Accounts, AllocationGroups)
   ======================================== */

.swipe-reveal-wrap {
    position: relative;
    overflow: hidden;
    border-radius: 0;
    margin-bottom: 0;
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

.swipe-reveal-wrap:last-child {
    border-bottom: none;
}

/* Flat card style inside list — no elevation shadow */
.swipe-card-slide .mud-card {
    border-radius: 0;
    box-shadow: none;
}

/* Shared base for both reveal panels */
.swipe-reveal-left,
.swipe-reveal-right {
    position: absolute;
    inset: 0;
    display: none;           /* JS adds .visible to show        */
    align-items: stretch;
}

.swipe-reveal-left.visible,
.swipe-reveal-right.visible {
    display: flex;
}

.swipe-reveal-left  { justify-content: flex-start; }
.swipe-reveal-right { justify-content: flex-end;   }

/* The card element that physically slides */
.swipe-card-slide {
    position: relative;
    z-index: 1;
    will-change: transform;
}

/* Action buttons shared style */
.swipe-action-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    border: none;
    cursor: pointer;
    padding: 0 16px;
    min-width: 65px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.3px;
    color: white;
    text-transform: uppercase;
    -webkit-tap-highlight-color: transparent;
}

.swipe-action-btn:active { filter: brightness(0.88); }

/* Individual action colours */
.swipe-action-duplicate { background: #1976d2; min-width: 80px; }
.swipe-action-delete    { background: #d32f2f; min-width: 80px; }

