/* MudBlazor UI refinements that are independent of any page; candidates for the main project.
   Loaded after theme-new.css in App.razor. Every rule is scoped so that desktop rendering stays
   untouched: the picker rules apply only inside a MudBlazor dialog container (PickerVariant.Dialog)
   and only on small screens. Colours come from the MudBlazor palette variables. */

/* ---------------------------------------------------------------------------------------------
   Date / date range picker in dialog mode on phones (<= 600 px, MudBlazor's Xs breakpoint).
   The selectors are the class names MudBlazor 9.9.0 renders: .mud-dialog-container (dialog host),
   .mud-picker-container, .mud-picker-content, .mud-picker-datepicker-toolbar with .mud-button-date /
   .mud-button-year, .mud-picker-actions, .mud-picker-calendar .mud-day. */
@media (max-width: 600px) {
    /* The picker never grows beyond the viewport; the calendar area scrolls instead. */
    .mud-dialog-container .mud-picker-container {
        max-height: calc(100vh - 24px);
        max-height: calc(100dvh - 24px);
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }

    .mud-dialog-container .mud-picker-content {
        min-height: 0;
    }

    /* Toolbar title: a full date range ("Tue, 25 Aug - Wed, 02 Sep") fits on one line instead of
       wrapping the 2.125 rem desktop headline. */
    .mud-dialog-container .mud-picker-datepicker-toolbar .mud-button-date {
        font-size: 1.25rem;
        line-height: 1.3;
    }

    .mud-dialog-container .mud-picker-datepicker-toolbar .mud-button-year {
        font-size: 0.875rem;
        line-height: 1.5;
    }

    /* Action row: stays visible at the bottom of the picker while the calendar scrolls, and wraps
       instead of truncating its buttons. */
    .mud-dialog-container .mud-picker-actions {
        position: sticky;
        bottom: 0;
        z-index: 1;
        flex-wrap: wrap;
        gap: 4px 8px;
        padding: 8px 12px;
        background: var(--mud-palette-surface);
        border-top: 1px solid var(--mud-palette-lines-default);
    }

    /* MudBlazor spaces the action buttons with margins; the gap above replaces them so wrapped
       rows keep the same spacing. */
    .mud-dialog-container .mud-picker-actions > :not(:first-child) {
        margin-left: 0;
        margin-inline-start: 0;
    }

    /* No grey tap flash on the day cells and action buttons. The 36 px day cells are kept:
       40 px cells would wrap the seven-day rows inside MudBlazor's 310 px calendar. */
    .mud-dialog-container .mud-picker-calendar .mud-day,
    .mud-dialog-container .mud-picker-actions .mud-button-root {
        -webkit-tap-highlight-color: transparent;
    }
}

/* ---------------------------------------------------------------------------------------------
   Viewport: nothing may pan the page sideways. `clip` (not `hidden`) clips horizontal overflow
   without turning html/body into scroll containers, so position: sticky / fixed and the vertical
   scroll are unaffected; on the root element the clip is applied to the viewport. */
html,
body {
    overflow-x: clip;
}

/* The canvas (the area behind and beside the page, e.g. the strip Firefox for Android composites
   next to its overlay scrollbar when layout and visual viewport differ by a subpixel, and
   overscroll regions) is painted with the html element's background colour. Without this rule
   html is transparent and those regions render browser-default white. The palette variable
   follows the active MudBlazor theme in both designs. */
html {
    background-color: var(--mud-palette-background);
}

/* ---------------------------------------------------------------------------------------------
   The page content keeps a fixed distance below the app bar. MudBlazor's dense rule sets the main
   content padding-top to exactly the app bar height, which puts the page title flush against the
   bar; the 32 px on top of that are the distance the page headings are laid out with and the value
   the pages that size a panel from the viewport height are based on (/ai-chat: calc(100vh - 96px)
   = 80 px above + 16 px below). The selector matches the specificity of MudBlazor's dense rule and
   this sheet loads after MudBlazor.min.css, so no !important is needed. A pt-* utility cannot be
   used for this: those carry !important and would replace the app bar offset instead of adding to
   it. The app bar is always dense (MainLayout); the login page and the remote tool windows render
   none, so the sibling selector does not match there and they keep MudBlazor's own padding-top. */
.mud-appbar-dense ~ .mud-main-content {
    padding-top: calc(var(--mud-appbar-height) - var(--mud-appbar-height) / 4 + 32px);
}

/* ---------------------------------------------------------------------------------------------
   Responsive drawer below MudBlazor's Md breakpoint (959 px): stretch it from MudBlazor's own top
   offset to the viewport bottom instead of a computed height, so it always reaches the bottom while
   the browser toolbar collapses (the "page background below the drawer" on phones). The second
   selector matches the specificity of MudBlazor's dense-app-bar rule; this sheet loads later. */
@media (max-width: 959px) {
    /* The mini variant (user setting drawer_mini_variant) renders as .mud-drawer-mini, not
       .mud-drawer-responsive — it needs the same bottom anchoring or the gap stays. The
       .mud-appbar-dense selectors match MudBlazor's dense-offset rules in specificity; this
       sheet loads later, so height: auto wins over the calc() heights. */
    .mud-drawer.mud-drawer-fixed.mud-drawer-responsive,
    .mud-drawer.mud-drawer-fixed.mud-drawer-mini,
    .mud-drawer.mud-drawer-mini.mud-drawer-clipped-always,
    .mud-appbar-dense ~ .mud-drawer-fixed.mud-drawer-responsive.mud-drawer-clipped-always,
    .mud-appbar-dense ~ .mud-drawer.mud-drawer-mini.mud-drawer-clipped-always {
        bottom: 0;
        height: auto;
    }
}

/* ---------------------------------------------------------------------------------------------
   Shared page toolbar/filter layout (the audit page pattern), design-independent. A page renders:
   an outlined card; a `nlui-filters` grid of captioned, outlined dense inputs (caption above via
   `nlui-field-label`); a muted `nlui-count` line; a `nlui-toolbar` row with text buttons on the left
   and the debounced search (`nlui-search`) plus a Columns menu on the right (`nlui-toolbar-group`
   for each side); then the table. Pages without a filter grid start with the toolbar and use the
   `nlui-toolbar--borderless` modifier. */
.nlui-filters {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 12px;
}

@media (max-width: 1200px) {
    .nlui-filters {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 768px) {
    .nlui-filters {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Every filter cell puts its input on the same top and bottom edge: the caption gets a fixed
   bottom margin and the input control loses MudBlazor's own vertical margins
   (.mud-input-control-margin-dense = 4px top and bottom).
   The selector reaches into the cell instead of only its direct children, because the depth of
   the input control depends on the component: MudTextField and MudNumericField render it as the
   direct cell child, MudSelect and MudAutocomplete wrap it in a div.mud-select (OuterClassname in
   MudSelect.razor) and pickers wrap it in a div.mud-picker. It keeps the child combinator on the
   cell itself so its specificity stays above MudBlazor's own dense-margin rule instead of relying
   on stylesheet order. Popovers and dialogs are rendered by the providers in MainLayout.razor
   outside <MudLayout>, never inside a cell, so nested controls are not reached.
   Contract for a filter input: Variant.Outlined + Margin.Dense and no Label - the caption above
   the field is the label. Every dense outlined MudBlazor input is 40px high (one line box plus
   2 x 10.5px padding), and a Label would give it the more specific
   .mud-input-outlined-with-label margins (8px/4px), which this reset does not override. */
.nlui-filters > div {
    display: flex;
    flex-direction: column;
}

.nlui-filters > div .mud-input-control {
    margin-top: 0;
    margin-bottom: 0;
}

.nlui-field-label {
    display: block;
    margin-bottom: 4px;
    color: var(--mud-palette-text-secondary);
}

.nlui-count {
    display: block;
    margin-top: 8px;
    color: var(--mud-palette-text-secondary);
}

.nlui-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 8px;
    padding: 8px 0 4px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.nlui-toolbar--borderless {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
}

.nlui-toolbar-group {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.nlui-search {
    width: 240px;
}

@media (max-width: 768px) {
    .nlui-search {
        width: 100%;
    }
}

/* ---------------------------------------------------------------------------------------------
   Snackbars on phones (<= 600 px, MudBlazor's Xs breakpoint). The console pins the container
   bottom-right (see Classes/Helper/Notifications/Snackbar_Service.cs). MudBlazor 9.9.0 places it 24 px
   from the corner and gives every toast min-width 288 px / max-width 500 px, so a long toast runs out
   of the left edge on narrow viewports and sits behind the iOS home indicator in the PWA. The
   selectors are the class names MudBlazor renders: #mud-snackbar-container carrying
   .mud-snackbar-location-bottom-right, and .mud-snackbar for each toast. */
@media (max-width: 600px) {
    #mud-snackbar-container.mud-snackbar-location-bottom-right {
        left: 8px;
        right: 8px;
        bottom: calc(8px + env(safe-area-inset-bottom));
    }

    #mud-snackbar-container .mud-snackbar {
        min-width: 0;
        max-width: none;
        width: 100%;
        margin-top: 8px;
    }
}

/* ---------------------------------------------------------------------------------------------
   Row actions of list pages (Components/Shared/Row_Actions, guidelines "UI CONVENTION - List page
   actions"). The icon buttons of the "actions" column sit in one non-wrapping inline row and the cell
   shrinks to its content, so the data columns keep the width. Below MudBlazor's Xs breakpoint (600 px)
   MudTable stacks every cell into "label | content"; the icons then sit right-aligned on one line and
   the tap target grows from the 30 px Size.Small button to 36 px. */
.nlui-row-actions {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    white-space: nowrap;
    vertical-align: middle;
}

.nlui-row-actions-cell {
    width: 1%;
    white-space: nowrap;
}

@media (max-width: 600px) {
    .nlui-row-actions {
        justify-content: flex-end;
    }

    .nlui-row-actions .mud-icon-button {
        padding: 8px;
    }
}

/* ---------------------------------------------------------------------------------------------
   Dialog scrim. The blurred backdrop behind every dialog comes from the global MudDialogProvider
   (BackgroundClass="dialog-blurring" in MainLayout.razor); this is its single definition. The
   coarse-pointer block in theme-new.css disables the blur on touch devices with !important, which
   deliberately overrides this rule in both themes. */
.dialog-blurring {
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

/* Minimum sizes for dialogs whose content loads after the dialog opens (mail viewers, ticket
   detail, the mobile screen stream), so the surface does not collapse while empty. Applied
   through the MudDialog Class parameter; the width itself comes from the dialog's options. */
.nlui-dialog-min-h-400 { min-height: 400px; }
.nlui-dialog-min-h-500 { min-height: 500px; }
.nlui-dialog-min-h-600 { min-height: 600px; }
.nlui-dialog-min-w-60 { min-width: 60vw; }

/* ---------------------------------------------------------------------------------------------
   Mobile foundation (phones, <= 600 px — MudBlazor's Xs breakpoint), both themes. The first four
   rules moved here from theme-new.css so the Classic theme gets them too. */
@media (max-width: 600px) {
    /* Tighter content padding on phones; this rule only narrows left, right and bottom. The
       padding-top comes from the app bar offset rule above and is the same on every viewport. */
    .mud-main-content { padding-left: 8px !important; padding-right: 8px !important; padding-bottom: 8px !important; }

    /* Crowded toolbars wrap instead of overflowing the viewport. */
    .responsive-toolbar { flex-wrap: wrap !important; }

    /* Wide tables scroll horizontally inside their wrapper instead of widening the page. */
    .responsive-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

    /* Column prioritization: secondary columns marked col-hide-xs disappear on phones. */
    .col-hide-xs { display: none !important; }
}

/* Phones: dialogs open full screen (the same look MudBlazor's FullScreen option produces),
   except message boxes and the shared confirm dialog, which stay small centered prompts.
   The dialog content area already flexes and scrolls, so header and actions stay visible. */
@media (max-width: 599.98px) {
    .mud-dialog-container .mud-dialog:not(.mud-message-box):not(.nlui-confirm-dialog) {
        width: 100vw;
        max-width: 100vw;
        height: 100vh;
        height: 100dvh;
        max-height: 100vh;
        max-height: 100dvh;
        margin: 0;
        border-radius: 0;
    }

    /* Action rows wrap instead of pushing buttons off screen. */
    .mud-dialog .mud-dialog-actions {
        flex-wrap: wrap;
    }

    /* Tables sized to the desktop viewport (table-fill-<N>) scroll with the page on phones,
       capped so one table cannot occupy more than most of the screen. */
    [class*="table-fill-"] .mud-table-container {
        height: auto !important;
        max-height: 70vh;
    }
}

/* Touch devices: larger hit areas without changing the compact desktop look. Small buttons and
   icon buttons reach the 40 px recommendation, dense table rows and inputs get room to tap,
   nav links a little more. The row-actions cells keep their tighter 36 px targets. */
@media (hover: none) and (pointer: coarse) {
    .mud-button-root.mud-button-small { min-height: 40px; }
    .mud-icon-button.mud-icon-button-size-small { padding: 10px; }
    .mud-table-dense .mud-table-body .mud-table-cell { padding-top: 10px; padding-bottom: 10px; }
    .mud-input.mud-input-margin-dense { min-height: 40px; }
    .mud-nav-link { min-height: 44px; }

    .nlui-row-actions .mud-icon-button { padding: 8px; }
}

/* Desktop table heights. table-fill-<N> replaces the former per-table Height="calc(100vh - Npx)"
   attribute: the scrollable area fills the viewport minus the page chrome above it, and the
   phone block above lets the same tables scroll with the page instead. */
.table-fill-250 > .mud-table-container { height: calc(100vh - 250px); }
.table-fill-300 > .mud-table-container { height: calc(100vh - 300px); }
.table-fill-320 > .mud-table-container { height: calc(100vh - 320px); }
.table-fill-350 > .mud-table-container { height: calc(100vh - 350px); }
.table-fill-460 > .mud-table-container { height: calc(100vh - 460px); }
.table-fill-500 > .mud-table-container { height: calc(100vh - 500px); }
.table-fill-520 > .mud-table-container { height: calc(100vh - 520px); }
.table-fill-560 > .mud-table-container { height: calc(100vh - 560px); }

/* ---------------------------------------------------------------------------------------------
   Games (the mini games behind the AppBar gamepad button). The wrapper fixes the aspect ratio
   of the playing field and the canvas fills it; the game letterboxes its logical field inside the
   canvas, so hit-testing stays exact at any size and DPR. touch-action: none hands every touch
   gesture to the game instead of scrolling the dialog; the canvas is focusable (tabindex) so the
   keyboard reaches the game only while it has focus. */
.nlgame-wrapper {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 10;
    max-height: calc(100vh - 240px);
    max-height: calc(100dvh - 240px);
    min-height: 240px;
    border-radius: 8px;
    overflow: hidden;
    background: transparent;
}

.nlgame-wrapper.nlgame-aspect-4-3 { aspect-ratio: 4 / 3; }
.nlgame-wrapper.nlgame-aspect-20-17 { aspect-ratio: 20 / 17; }

.nlgame-wrapper canvas {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    touch-action: none;
    outline: none;
    cursor: crosshair;
    user-select: none;
    -webkit-user-select: none;
    -webkit-tap-highlight-color: transparent;
}

.nlgame-wrapper canvas:focus-visible {
    box-shadow: inset 0 0 0 2px var(--mud-palette-primary);
}

/* Best-score list in the dialog side cards. */
.nlgame-scores {
    list-style: none;
    margin: 0;
    padding: 0;
    font-variant-numeric: tabular-nums;
}

.nlgame-scores li {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    padding: 2px 0;
}

.nlgame-scores li span:last-child {
    font-weight: 600;
}

/* Keyboard reference table in the "How to play" card. */
.nlgame-keys {
    border-collapse: collapse;
    width: 100%;
}

.nlgame-keys td {
    padding: 2px 4px;
    vertical-align: top;
}

.nlgame-keys kbd {
    display: inline-block;
    min-width: 1.4em;
    padding: 0 4px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    font-family: inherit;
    font-size: 0.8em;
    text-align: center;
    line-height: 1.5;
}

/* Phones held upright: the field gets small, so a rotate hint appears under the canvas. */
.nlgame-portrait-hint {
    display: none;
}

@media (max-width: 599.98px) and (orientation: portrait) {
    .nlgame-portrait-hint {
        display: block;
    }
}

/* Desktop: the information cards sit left of the field; on phones and tablets the field comes
   first and the cards stack below it. */
@media (min-width: 960px) {
    .nlgame-side {
        order: -1;
    }
}

/* Phones: the full-screen dialog gives the field the whole width; the height cap above would
   otherwise fight the aspect ratio on short viewports. */
@media (max-width: 599.98px) {
    .nlgame-wrapper {
        max-height: 70vh;
        max-height: 70dvh;
    }
}
