/* RustDeskPortal page chrome.
   This is a real .css file, never parsed by Razor, so a literal @ needs no escaping here.
   Bar styling mirrors the fixed-position bar in WebApplication1's menuWithBarV3.vue
   (dodgerblue, 5px padding, Calibri 12px) without importing that component. */

[v-cloak] {
    display: none;
}

.portalBarSpacer {
    z-index: 99;
    position: relative;
    /* Sized for a bar that has WRAPPED, not for the one-line bar. .portalBar is
       position:fixed with no height of its own, so every pixel it grows by is
       drawn OVER the page, and this spacer is the only thing holding the page's
       first row of content clear of it. At 58px a two-row bar covered the top of
       the content by 8px.

       Arithmetic. The tallest thing in the bar is 24px - the Log out link: 12px
       text on the inherited 1.5 line-height = 18px, plus 2x2px padding and
       2x1px border. (The help button is 22px and the title's line box 22.5px,
       so 24px is the cap for any row.) The bar adds 5px of padding above and
       below and its row-gap is now 0, so ONE row is 5+24+5 = 34px and TWO rows
       are 5+24+24+5 = 58px. 64px here leaves 6px of slack, so a row would have
       to grow past 27px before content were covered again.

       Two rows is the worst case at 700px and up: the whole super-admin nav
       needs about 1,040px on one line, and a 700px-wide bar takes at least half
       of that per line. Below 700px it can wrap three or four times - a long
       email address alone is 200px+ - which no fixed height can cover, so the
       phone block at the foot of this file takes the bar out of position:fixed
       instead of guessing a number. */
    height: 64px;
    font-family: Calibri, Arial, Helvetica, sans-serif;
    font-size: 12px;
}

.portalBar {
    z-index: 99;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    background-color: dodgerblue;
    padding: 5px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    /* A floor, not a height. It pins the one-row number .portalBarSpacer's
       height is derived from, so a smaller font cannot shrink the blue band and
       leave that arithmetic quietly stale. The bar still grows past it when the
       nav wraps - that is what the spacer's 6px of slack is for. */
    min-height: 34px;
    /* Was gap: 8px, which applied in BOTH directions. Horizontal spacing is what
       the nav actually needs; an 8px row-gap only made a wrapped bar 8px taller
       per extra row, and every one of those pixels is painted over the page. The
       links already carry 2px of vertical padding each, so wrapped rows still do
       not touch with no row-gap at all. */
    column-gap: 8px;
    row-gap: 0;
    box-sizing: border-box;
}

.portalBarTitle {
    color: white;
    font-weight: bold;
    font-size: 15px;
    flex-shrink: 0;
}

.portalBarLink {
    color: white;
    text-decoration: none;
    padding: 2px 6px;
    flex-shrink: 0;
}

.portalBarLink:hover {
    text-decoration: underline;
}

.portalBarLink:focus-visible {
    outline: 2px solid white;
    outline-offset: 1px;
}

.portalBarSpring {
    flex: 1 1 0;
}

.portalBarUser {
    color: white;
    flex-shrink: 0;
}

/* "Loaded 13:05:42 MDT", immediately before the signed-in name.

   Same 12px as everything else in the bar (inherited from .portalBar, exactly
   as .portalBarUser inherits it), so it cannot make the bar taller and cannot
   set off the wrap arithmetic written up at the top of this file.

   Muted rather than plain white on purpose: it is a footnote about the page,
   not a piece of the navigation, and at full white it competes with the name
   beside it. flex-shrink 0 for the same reason the name has it - a squeezed
   timestamp is unreadable and wrapping is the better failure. */
.portalBarRefreshed {
    color: rgba(255, 255, 255, 0.75);
    flex-shrink: 0;
    margin-right: 4px;
}

.portalBarLogout {
    border: 1px solid rgba(255, 255, 255, 0.6);
    border-radius: 3px;
}

/* ---------------------------------------------------------------------------
   Page help (the "i" button at the right-hand end of the bar).

   Plain CSS and plain DOM on purpose. The button sits INSIDE #appMain, which
   Vue compiles and re-renders from the container's innerHTML, but the dialog
   below it is rendered OUTSIDE #appMain so no page's Vue app can own, compile
   or destroy it - see the comment in _Layout.cshtml. That rules out a Vuetify
   v-dialog here, hence these rules.
   --------------------------------------------------------------------------- */
.portalBarHelp {
    color: white;
    background-color: rgba(255, 255, 255, 0.18);
    border: 1px solid rgba(255, 255, 255, 0.6);
    border-radius: 50%;
    width: 22px;
    height: 22px;
    line-height: 1;
    padding: 0;
    flex-shrink: 0;
    cursor: pointer;
    font-family: Calibri, Arial, Helvetica, sans-serif;
    font-size: 13px;
    font-weight: bold;
    font-style: italic;
}

.portalBarHelp:hover {
    background-color: rgba(255, 255, 255, 0.34);
}

.portalBarHelp:focus-visible {
    outline: 2px solid white;
    outline-offset: 1px;
}

/* The dialog is display:none until the delegated click handler adds .isOpen to
   it. Nothing about it depends on script having run before that click. */
.portalHelpOverlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 2400; /* above Vuetify's own overlays (2000-2400) and the bar (99) */
    background-color: rgba(33, 33, 33, 0.45);
    padding: 24px 12px;
    overflow-y: auto;
    font-family: 'Roboto', 'Segoe UI', system-ui, sans-serif;
}

.portalHelpOverlay.isOpen {
    display: block;
}

.portalHelpCard {
    background-color: white;
    max-width: 760px;
    margin: 0 auto;
    border-radius: 4px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
    padding: 14px 18px 16px 18px;
}

.portalHelpHead {
    display: flex;
    align-items: center;
    gap: 10px;
    border-bottom: 1px solid #e0e0e0;
    padding-bottom: 8px;
    margin-bottom: 10px;
}

.portalHelpTitle {
    font-size: 15px;
    font-weight: bold;
    color: #1d4b63;
    flex: 1 1 auto;
}

.portalHelpBody {
    font-size: 13px;
    line-height: 1.5;
    color: #37474f;
}

.portalHelpBody h4 {
    font-size: 13px;
    font-weight: bold;
    color: #1d4b63;
    margin: 12px 0 3px 0;
}

.portalHelpBody p {
    margin: 0 0 8px 0;
}

.portalHelpBody ul {
    margin: 0 0 8px 0;
    padding-left: 20px;
}

.portalHelpBody li {
    margin-bottom: 3px;
}

/* .btnName and .whoFor used to live here and are deliberately gone. They were
   the two props of PROSE help - a button name quoted mid-sentence, and an
   italic "Admins and super admins." tacked on the end of a paragraph. Every
   page's help is now a .portalNoteTable whose LABEL COLUMN is the button name
   and whose last band says who sees what, so both classes had no references
   left. They are not kept "just in case": a rule whose comment explains how to
   write a paragraph is an invitation to write one, which is the thing this
   redesign exists to undo. The h4 / ul / li rules above stay - they are generic
   element styling, not a convention.
   --------------------------------------------------------------------------- */

.portalHelpFoot {
    border-top: 1px solid #e0e0e0;
    margin-top: 10px;
    padding-top: 10px;
    text-align: right;
}

/* ---------------------------------------------------------------------------
   The note table - ONE shape shared by two dialogs that are otherwise nothing
   alike.

   Used by BOTH the page-help dialog (plain static HTML in each page's
   @section HelpContent, rendered by the layout OUTSIDE #appMain) and the
   "what's new" dialog on the Clients page (a Vuetify v-dialog INSIDE that
   page's Vue app). That is exactly why the rules live in this file rather than
   in either page: the help dialog cannot reach a page's @section Styles, and
   duplicating the shape per page is how eleven pages come to look like eleven
   pages.

   Both dialogs are the same reading problem - a list of short facts somebody
   scans rather than reads - so both get the same answer: one line per item,
   a fixed label column, tinted bands for grouping, horizontal rules only.
   The border treatment deliberately matches .portalTable below (#f0f0f0 head
   with a 2px #bdbdbd rule, 1px #e0e0e0 row rules) so a dialog reads as part of
   the portal and not as a document that wandered in.

   NO VERTICAL RULES anywhere. A two-column grid of one-liners is read across,
   and a vertical rule invites the eye to read down a column that means nothing.
   --------------------------------------------------------------------------- */

/* The grey bar at the top of the "what's new" dialog: title left, how many
   unread notes right. The help dialog uses .portalHelpHead instead - it has a
   CLOSE button in the same place, so the two cannot share one rule. */
.portalNoteHead {
    display: flex;
    align-items: baseline;
    gap: 10px;
    background-color: #f0f0f0;
    border-bottom: 2px solid #bdbdbd;
    padding: 7px 10px;
    font-family: 'Roboto', 'Segoe UI', system-ui, sans-serif;
}

.portalNoteHeadTitle {
    font-size: 13px;
    font-weight: bold;
    color: #1d4b63;
    flex: 1 1 auto;
}

.portalNoteHeadCount {
    font-size: 11px;
    color: #78909c;
    flex: 0 0 auto;
    white-space: nowrap;
}

.portalNoteTable {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
    line-height: 1.45;
    color: #37474f;
    font-family: 'Roboto', 'Segoe UI', system-ui, sans-serif;
}

.portalNoteTable td {
    padding: 4px 8px;
    border-bottom: 1px solid #e0e0e0;
    vertical-align: top;
}

/* The label column. A fixed width rather than shrink-to-fit: the labels are
   the thing the eye runs down, and a column that changes width per table would
   stop them lining up between one dialog and the next. Long labels wrap inside
   it instead of widening it. */
.portalNoteTable td.portalNoteK {
    width: 132px;
    font-weight: 600;
    color: #37474f;
}

.portalNoteTable td.portalNoteV {
    color: #37474f;
}

/* A section band: a release in the "what's new" dialog, a topic in page help.
   Spans both columns, so it is the one row that is read as a heading. */
.portalNoteTable tr.portalNoteBand > td {
    background-color: #eef4f7;
    border-bottom: 1px solid #cfd8dc;
    font-size: 12px;
    font-weight: 500;
    color: #1d4b63;
}

/* A band nested INSIDE a band - a topic within one release note. Same family,
   deliberately weaker: paler fill and an indent rule, so the hierarchy is
   visible without a second colour. */
.portalNoteTable tr.portalNoteSub > td {
    background-color: #f7fafb;
    border-bottom: 1px solid #e0e0e0;
    border-left: 3px solid #cfd8dc;
    padding-left: 12px;
    font-size: 12px;
    font-weight: 500;
    color: #1d4b63;
}

.portalNoteBandDate {
    font-weight: normal;
    font-size: 11px;
    color: #78909c;
    padding-left: 8px;
}

/* The one-sentence "what this page is for" line above a help table. */
.portalNoteLead {
    font-size: 12.5px;
    line-height: 1.5;
    color: #37474f;
    margin: 0 0 8px 0;
}

/* The "what's new" dialog scrolls itself rather than relying on v-dialog's
   scrollable prop, which wants a v-card-text child this dialog does not have. */
.portalNoteScroll {
    max-height: 60vh;
    overflow-y: auto;
}

.portalNoteFoot {
    border-top: 1px solid #e0e0e0;
    padding: 10px 10px 8px 10px;
}

/* The buttons used to explain themselves only in a title= tooltip on LATER,
   which is a promise nobody discovers. It is a visible line now. */
.portalNoteFootHint {
    font-size: 11px;
    color: #78909c;
    padding-top: 7px;
    font-family: 'Roboto', 'Segoe UI', system-ui, sans-serif;
}

/* ---------------------------------------------------------------------------
   The horizontal-scroll region a wide grid lives in.

   WITHOUT THIS THE DOCUMENT SCROLLS SIDEWAYS. The Clients grid is twelve
   columns for a super admin and needs roughly 2,370px; the table itself is
   width:100% but its cells are nowrap, so it overflows its container and - with
   nothing between it and <body> that scrolls - the PAGE takes the overflow.
   Reaching a row's Actions buttons then drags the search box, the portal bar
   and the filter rows off the left of the screen, so it is impossible to see
   which machine a button belongs to at the moment of pressing it.

   overflow-x on a wrapper keeps the scrolling inside the grid. Paired with the
   sticky first column below it means the identity of the row stays on screen
   while the buttons are brought into view, which is the actual requirement.
   --------------------------------------------------------------------------- */
.portalTableScroll {
    overflow-x: auto;
    /* A hair of vertical room so the sticky cell's right-hand rule does not sit
       under a horizontal scrollbar drawn over the last row. */
    padding-bottom: 1px;
}

/* The frozen identity column. Applied to the FIRST cell of the head and of
   every body row of a grid that is wide enough to scroll.

   The background is not optional: a sticky cell paints over the cells that
   scroll beneath it, and a transparent one lets them show through. The head
   keeps the grid's own #f0f0f0; a body cell is given the row's stripe colour
   inline, next to the stripe it has to match, because the stripe is a bound
   style on the <tr> and CSS here cannot see which one a row got. */
.portalTable td.portalStickyCell {
    position: sticky;
    left: 0;
    z-index: 1;
    border-right: 1px solid #cfd8dc;
    /* An opaque FALLBACK behind the inline stripe colour described above, not a
       replacement for it: an inline style beats a stylesheet, so the Clients
       grid's striping - and any hover colour a page adds later - is untouched.
       This is only ever what paints when a row arrives without its bound
       background: another grid that borrows this class and forgets the inline
       style, or a row in the instant before Vue has bound one. #ffffff is
       deliberately the LIGHTER of the two stripe colours rather than some third
       value, so such a row reads as an even row and not as a band of its own.
       Without it a transparent frozen cell let the columns scrolling underneath
       show straight through the machine's name. */
    background-color: #ffffff;
    /* A WAN address in the inventory grid can be an IPv6 one - a single
       unbreakable ~245px token in a 155px track ((320 - 10px gap) / 2 for
       .sysGrid's two auto-fit columns). It used to spill out of the track, and
       because this cell is z-index:1 the spill was painted OVER the User and
       Department columns instead of being clipped by them, so the row's own
       identity obscured the row. overflow-wrap is an inherited property, so
       breaking it here reaches .sysGrid's spans without the page needing a rule
       of its own. break-word first for anything that does not know `anywhere`;
       `anywhere` is the one that will also break the token when the track is
       narrower than its own minimum. */
    overflow-wrap: break-word;
    overflow-wrap: anywhere;
}

.portalTable thead td.portalStickyCell {
    z-index: 2;
    background-color: #f0f0f0;
}

/* Keeps the frozen column from eating the viewport. The Clients grid's first
   cell holds a name, a presence chip and an inventory grid, all of which would
   otherwise size themselves to their content.

   320px is a DESKTOP number and it stops being one somewhere around 700px wide:
   320 inner + 16 cell padding + 1 border = 337px of used width against a
   scrollport of viewport minus 48px, which at 375px is 327px. A frozen column
   wider than the region it is frozen inside covers every other column at every
   scroll offset, so the phone block at the foot of this file relaxes both this
   width and the sticky positioning. */
.portalStickyInner {
    width: 320px;
}

/* ---------------------------------------------------------------------------
   Pager buttons (FIRST / PREV / NEXT / LAST), on the Clients, Sessions and
   Audit grids.

   All four are gtrerpLightGrey, so before this rule the ONLY difference between
   a usable NEXT and an unusable one was .gtrerpButton:disabled's opacity: 0.45
   - a whole-button fade that reads as "the page is still loading" rather than
   as "you are on the last page". Opacity is cancelled here and the disabled
   state is drawn instead: a paler fill, a fainter border and grey text, so the
   difference is in colour and not only in strength. 5.11:1 on the label, which
   is above the 4.5:1 target even though a disabled control is exempt from it.
   --------------------------------------------------------------------------- */
.portalPagerBtn:disabled {
    opacity: 1;
    background-color: #f1f3f4;
    border-color: rgba(0, 0, 0, 0.08);
    color: #5c6875 !important;
}

/* Grid styling lifted from CustomerManagement.cshtml's inline table styles so the
   portal's tables match the ERP's without repeating the inline attributes everywhere. */
.portalTable {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
}

.portalTable thead tr {
    background-color: #f0f0f0;
    border-bottom: 2px solid #bdbdbd;
}

.portalTable thead td {
    padding: 4px 8px;
    font-weight: bold;
    white-space: nowrap;
}

.portalTable tbody td {
    padding: 4px 8px;
    border-bottom: 1px solid #e0e0e0;
}

/* ---------------------------------------------------------------------------
   PHONE WIDTHS - the portal's first @media block, and deliberately the only one.

   Everything above was written against a desk monitor and two rules stop being
   true on a phone: a fixed bar with no height limit, and a frozen column wider
   than the region it is frozen inside. Both fail the same way - they cover the
   page rather than merely look cramped - so both are RELAXED here instead of
   being re-tuned. Nothing in this block runs at 700px or above, so the 1100px
   and 1600px layouts are byte-for-byte what they were.

   699px, not 700px: 700px and up is the range the fixed bar's two-row spacer
   arithmetic is provably good for (see .portalBarSpacer).
   --------------------------------------------------------------------------- */
@media (max-width: 699px) {
    /* The bar joins the flow instead of floating over it. At these widths the
       nav wraps to three or four rows, and no spacer height can be both tall
       enough for four rows and not a white band on the pages that only need
       one. A static bar is the version that cannot be wrong: the spacer is the
       bar's own parent, so height:auto makes the space reserved EXACTLY the
       height the bar turned out to be, at any number of rows, and content can
       never be occluded.
       The cost is that the nav scrolls away with the page on a phone. That is
       the better trade here - a wrapped nav is ~130px of a 667px screen, and
       permanently spending a fifth of a phone screen on a menu is worse than
       scrolling back up to it. */
    .portalBarSpacer {
        height: auto;
    }

    /* top / left are left alone deliberately - they are simply inert on a
       static box, and width:100% already reads the same either way. */
    .portalBar {
        position: static;
    }

    /* The frozen identity column unfreezes. Capping it (max-width instead of
       width) is not enough on its own: even a "usable" 60vw = 225px frozen
       column leaves 85px of a 327px scrollport for the eleven columns you are
       scrolling towards, so the thing the freeze exists to make possible - read
       the row's identity, then reach its Actions button - cannot happen either
       way. Unfrozen, the whole 327px goes to whatever you have scrolled to, and
       the row's name is one swipe back to the left. position:static also drops
       the z-index:1 stacking, so there is nothing left that can paint over the
       columns beside it. */
    .portalTable td.portalStickyCell {
        position: static;
    }

    /* Still bounded, so the first thing on screen is not one 337px column with
       no hint that another one follows. min(60vw, 320px): 60vw is 225px at 375px
       and 288px at 480px, always leaving a visible slice of the User column,
       and the 320px arm keeps a 699px phone from getting a FIRST column wider
       (60vw = 419px) than the desktop grid's. */
    .portalStickyInner {
        width: auto;
        max-width: min(60vw, 320px);
    }
}
