/* Shared responsive behavior for the Blazor server UI. */

/* The app bar's height at the current breakpoint. MudBlazor sizes both .mud-appbar's toolbar and
   .mud-main-content's padding-top on this three-step scale (same media conditions, reproduced here in
   the same order), so anything that measures "the space left below the app bar" has to follow it too.
   Also: MudContainer's mt-6 above every page, mirrored as breathing room below. */
:root {
    --filesync-appbar-height: calc(var(--mud-appbar-height) - var(--mud-appbar-height) / 8);
    --filesync-content-gap: 24px;
}

@media (orientation: landscape) {
    :root {
        --filesync-appbar-height: calc(var(--mud-appbar-height) - var(--mud-appbar-height) / 4);
    }
}

@media (min-width: 600px) {
    :root {
        --filesync-appbar-height: var(--mud-appbar-height);
    }
}

/* MudBlazor gives this a flat var(--mud-appbar-height), which leaves it 8px taller than the app bar
   below the sm breakpoint. This file loads after MudBlazor.min.css at equal specificity, so it wins. */
.mud-drawer-header {
    min-height: var(--filesync-appbar-height);
}

/* Fill the viewport rather than growing past it: the scroll region below takes the leftover height, so
   a long list scrolls inside its panel and the document itself never gains a second scrollbar. */
.fill-viewport {
    display: flex;
    flex-direction: column;
    height: calc(100vh - var(--filesync-appbar-height) - var(--filesync-content-gap) * 2);
    height: calc(100dvh - var(--filesync-appbar-height) - var(--filesync-content-gap) * 2);
    min-height: 320px;   /* on a very short viewport let the page scroll rather than crush the panel */
}

/* Holds the leftover space whichever of loading / empty / results is showing, so the layout doesn't
   jump as the content changes. */
.fill-viewport-body {
    display: flex;
    flex-direction: column;
}

.fill-viewport-scroll {
    overflow: auto;
}

/* MudBlazor components bring their own flex — a MudTextField's .mud-input-control is `flex: 1 1 auto`
   — so an unpinned child grows to swallow the column's free space and shoves the scroll region to the
   bottom. Reset every child to the browser default (0 1 auto: don't grow, may still shrink on a
   cramped viewport), then hand growth to the two elements that should have it. */
.fill-viewport > *,
.fill-viewport-body > * {
    flex: 0 1 auto;
}

/* min-height:0 is load-bearing on both — a flex item won't shrink below its content without it, and
   the outer scrollbar comes straight back. Same trap as the MudDataGrid one noted in CLAUDE.md.
   (0,2,0) against the pin's (0,1,0), so these win regardless of order. */
.fill-viewport > .fill-viewport-body,
.fill-viewport-body > .fill-viewport-scroll {
    flex: 1 1 auto;
    min-height: 0;
}

.wrap-anywhere,
.wrap-anywhere .mud-typography,
.responsive-table .mud-table-cell,
.responsive-grid .mud-table-cell {
    overflow-wrap: anywhere;
    word-break: break-word;
}

.responsive-actions {
    flex-wrap: wrap;
}

/* The file browser's two bars carry more controls than any other toolbar here — up to seven in the
   action bar alone — so they take this instead of .responsive-actions, whose mobile rule below gives
   every child a full-width row of its own. That is right for a two-button toolbar and wrong here: it
   spent more vertical space on chrome than was left for the tree underneath, on the one screen where
   there is least to spare. A separate class rather than a modifier, because beating that rule's
   !important column would take another !important. */
.compact-actions {
    flex-wrap: wrap;
}

/* The file tree's per-row ⋮ menu button. Deliberately not inside the phone breakpoint: what is broken is
   *touch*, not *narrow* — iOS Safari never fires `contextmenu` on a long press, and an iPad reports 810px
   in portrait, so a max-width rule would leave the very device that needs this without it.
   MudBlazor zeroes the padding of every icon button inside a dense tree
   (.mud-treeview-dense .mud-icon-button{padding:0}), which would leave an 18px tap target on the one
   control that exists for fingers. Equal specificity (0,2,0), and this file loads after MudBlazor.min.css,
   so it wins; rows grow a few px, which a phone can afford and a mouse never notices. */
.browse-row-menu .mud-icon-button {
    padding: 6px;
}

/* A file tree row no client with a live hub connection holds — nothing can preview, stream or prepare a
   download from it right now, which is the same question ClientFileFetchService answers on the click.
   The child combinator is exact and not a style choice: MudTreeViewItem's Class lands on the <li>, whose
   direct children are this row's content div and (for a folder) the group <ul>, so a descendant selector
   would tint a whole subtree the day a folder gets a marker. Files are leaves today, so nothing bleeds
   either way — the `>` is what keeps that true later.
   The leading icon dims with the text only because the row passes IconColor="Color.Inherit": MudIcon
   emits *no* colour class for Inherit, leaving .mud-icon-root.mud-svg-icon{fill:currentColor} to pick
   this up. Color.Default would pin it to --mud-palette-text-secondary and it would stay bright.
   Selecting the row restores the primary colour — MudBlazor's .mud-treeview-selected-primary rule is
   (0,3,0) against this (0,2,0). That is deliberate: selection feedback outranks a status hint.
   Colour is never the only signal — the label says "not connected" and the row carries a title. */
.browse-unavailable > .mud-treeview-item-content {
    color: var(--mud-palette-text-disabled);
}

.responsive-dialog .mud-dialog-content {
    min-width: 0;
}

.responsive-dialog .mud-dialog-actions {
    flex-wrap: wrap;
}

/* A text preview is the one preview kind that deliberately takes over the viewport. MudDialog's content
   has to participate in the height chain or a multiline field sizes itself from Lines and leaves most of
   the screen unused. The field is read-only, so native resize handles would only fight this layout. */
.preview-dialog.mud-dialog-fullscreen .mud-dialog-content {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
}

.text-preview-panel {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 0;
    width: 100%;
}

.text-preview-field {
    flex: 1 1 auto;
    min-height: 0;
}

.text-preview-field .mud-input-control-input-container,
.text-preview-field .mud-input,
.text-preview-field textarea {
    height: 100%;
    min-height: 0;
}

.text-preview-field textarea {
    box-sizing: border-box;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
    height: 100% !important;
    margin-bottom: 0;
    margin-top: 0;
    overflow: auto !important;
    overflow-wrap: normal;
    resize: none;
    white-space: pre;
}

/* The home page's Files card lists one deep link per accessible share, and an Admin sees every share on
   the server. MudGrid stretches each item to the tallest card in the row — which is exactly what the
   cards' height:100% relies on to keep their action buttons on one line — so an unbounded list does not
   just make this card tall, it drags the whole row's "Open" buttons down past the fold. Cap it and scroll
   instead: ~7 rows at the links' py-1 metrics. A fixed max-height on a plain block child of
   .mud-card-content, so none of the min-height:0 flex machinery elsewhere in this file applies.
   overscroll-behavior keeps a flick at the end of the list from scrolling the page underneath. */
.home-share-list {
    max-height: 200px;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* Host for the client-side .docx render, which JS fills with a single sandboxed iframe. The other preview
   kinds pin their element to 70vh; this one has to do it here, or the frame would collapse to the iframe
   default (150px) instead of filling the dialog. Scrolling happens *inside* the frame, so the host itself
   does not scroll. docx-preview draws its own page background, so the rendered document reads as a white
   page in either theme — the same as a PDF in the iframe next to it. */
.docx-host {
    height: 70vh;
}

.docx-frame {
    border: 0;
    height: 100%;
    width: 100%;
}

.kdbx-layout {
    height: 70vh;
}

.kdbx-tree {
    width: 280px;
    min-width: 220px;
    overflow: auto;
}

.kdbx-search {
    max-width: 360px;
}

@media (max-width: 600px) {
    .appbar-user {
        display: none;
    }

    /* Keep --filesync-content-gap in step with the smaller margin below, or anything sized off it
       (.fill-viewport) is 8px out on a phone. */
    :root {
        --filesync-content-gap: 16px;
    }

    .filesync-content {
        margin-top: 16px !important;
        padding-left: 12px !important;
        padding-right: 12px !important;
    }

    /* Step page titles down to h5 metrics on a phone, using MudBlazor's own typography scale so they
       stay in step with the theme rather than drifting from it. */
    .filesync-content .mud-typography-h4 {
        font-size: var(--mud-typography-h5-size);
        line-height: var(--mud-typography-h5-lineheight);
    }

    .responsive-actions {
        align-items: stretch !important;
        flex-direction: column !important;
        width: 100%;
    }

    .responsive-actions > *,
    .responsive-actions .mud-button-root,
    .mobile-full-width,
    .mobile-full-width .mud-button-root,
    .mobile-full-width .mud-input-control {
        width: 100%;
        max-width: none !important;
    }

    /* Icon-only, all on one wrapping row. The label is wrapped in a real span in the markup because a
       bare text node cannot be targeted by a selector; hiding it leaves MudButton's start icon as the
       whole of the button's content. The icon is still the same one the desktop button shows, so the
       two widths teach the same vocabulary. */
    .compact-actions .action-label {
        display: none;
    }

    /* Keyed to .action-button rather than .mud-button-root: the search bar carries the Name/Latest
       MudToggleGroup, whose items are buttons too, and squeezing those is not the intent. */
    .compact-actions .action-button {
        min-width: 0;
        padding-left: 10px;
        padding-right: 10px;
        /* 10 + 20 (icon) + 10 leaves a 40px-wide button, so pin the height to match rather than let it
           fall out of the line-height — a phone is exactly where an undersized tap target is felt. */
        min-height: 40px;
    }

    /* MudButton spaces a start icon 8px from its label and pulls it -4px left so it sits optically
       centred against text. With the label gone both are wrong, and the glyph sits visibly off-centre
       in its own button. */
    .compact-actions .action-button .mud-button-icon-start {
        margin-left: 0;
        margin-right: 0;
        margin-inline-start: 0;
        margin-inline-end: 0;
    }

    /* The search field is the one control that should still take the leftover width, so it shares a row
       with the sort toggle rather than claiming one of its own. min-width:0 is what lets an input
       shrink below its intrinsic content width — without it the toggle is pushed onto the next line. */
    .compact-actions .compact-grow {
        flex: 1 1 auto;
        min-width: 0;
    }

    .responsive-table .mud-table-row,
    .responsive-grid .mud-table-row {
        padding-top: 8px;
        padding-bottom: 8px;
    }

    .responsive-table .mud-table-cell[data-label],
    .responsive-grid .mud-table-cell[data-label] {
        align-items: flex-start;
        min-width: 0 !important;
        text-align: left !important;
    }

    .responsive-table .mud-table-cell[data-label]::before,
    .responsive-grid .mud-table-cell[data-label]::before {
        flex: 0 0 42%;
        max-width: 42%;
        padding-right: 12px;
    }

    .responsive-table .mud-table-cell[data-label] > *,
    .responsive-grid .mud-table-cell[data-label] > * {
        min-width: 0;
    }

    .responsive-table .mud-table-cell .mud-stack,
    .responsive-grid .mud-table-cell .mud-stack {
        flex-wrap: wrap;
        min-width: 0;
    }

    /* FullScreen already supplies exact viewport geometry. Keep the comfortable inset only on ordinary
       responsive dialogs, otherwise this rule would quietly turn a phone's text preview back into a card. */
    .responsive-dialog:not(.mud-dialog-fullscreen) {
        height: calc(100dvh - 16px);
        margin: 8px;
        max-height: calc(100dvh - 16px);
        max-width: calc(100vw - 16px) !important;
        width: calc(100vw - 16px);
    }

    .responsive-dialog .mud-dialog-content {
        overflow-x: hidden;
        padding-left: 16px;
        padding-right: 16px;
    }

    .mobile-card-action .mud-button-root {
        width: 100%;
    }

    .no-access-page {
        margin-top: 32px !important;
    }

    .no-access-page .mud-paper {
        padding: 24px 16px !important;
    }

    .kdbx-layout {
        flex-direction: column !important;
        height: calc(100dvh - 210px);
        min-height: 420px;
    }

    .kdbx-tree {
        flex: 0 0 auto;
        max-height: 25vh;
        min-height: 100px;
        min-width: 0;
        width: 100%;
    }

    .kdbx-search {
        max-width: none;
        width: 100%;
    }

    .kdbx-footer {
        align-items: flex-start !important;
        flex-wrap: wrap;
    }

    .kdbx-footer .mud-spacer {
        display: none;
    }
}
