/* ---- Typography ---------------------------------------------------------------------------
   No font is named in this file, and nothing here branches on language. culture.js resolves the
   UI font for the active language and publishes it as --app-ui-font on <html>, so adding a
   language never touches this stylesheet. To change a face, edit the FONTS table at the top of
   culture.js.

   Selectors are html[dir] rather than :root deliberately. MudThemeProvider injects its own :root
   block into the DOM at runtime, which lands after this stylesheet in document order — at equal
   specificity it would win. html[dir] outranks :root, so these hold regardless of injection
   order. index.html carries dir="ltr" and culture.js keeps it current, so html[dir] always
   matches. */

html[dir] body {
    font-family: var(--app-ui-font, 'Segoe UI', Tahoma, Helvetica, Arial, sans-serif);
}

/* MudBlazor renders its typography from these custom properties, so redefining them reaches
   every MudText, button and input at once instead of chasing individual components. */
html[dir] {
    --mud-typography-default-family: var(--app-ui-font);
    --mud-typography-h1-family: var(--app-ui-font);
    --mud-typography-h2-family: var(--app-ui-font);
    --mud-typography-h3-family: var(--app-ui-font);
    --mud-typography-h4-family: var(--app-ui-font);
    --mud-typography-h5-family: var(--app-ui-font);
    --mud-typography-h6-family: var(--app-ui-font);
    --mud-typography-subtitle1-family: var(--app-ui-font);
    --mud-typography-subtitle2-family: var(--app-ui-font);
    --mud-typography-body1-family: var(--app-ui-font);
    --mud-typography-body2-family: var(--app-ui-font);
    --mud-typography-button-family: var(--app-ui-font);
    --mud-typography-caption-family: var(--app-ui-font);
    --mud-typography-overline-family: var(--app-ui-font);
}

/* Code keeps the monospace face in both directions. Under RTL it also stays left-to-right:
   identifiers and code are not Arabic text, and letting them mirror mangles them. */
code,
pre {
    font-family: var(--app-mono-font, Consolas, 'Courier New', monospace);
}

html[dir="rtl"] code,
html[dir="rtl"] pre {
    direction: ltr;
    text-align: left;
}

/* Live numeric readouts — countdowns, timers, anything that reticks in place.
   font-variant-numeric: tabular-nums alone is not enough: it is a request for the font's tnum
   OpenType feature, and a face that does not ship tnum makes it a silent no-op, leaving
   proportional digits that change width as the value ticks. Roboto has tnum, Tajawal does not,
   so the same markup was steady in English and jittered in Arabic. The monospace stack is
   tabular by construction, so this holds for every language including ones not yet added.

   Prefixed html[dir] for the same reason the typography block at the top of this file is, and it
   is not optional here: index.html loads this stylesheet BEFORE MudBlazor.min.css, and MudBlazor
   sets both font-family and letter-spacing on .mud-typography-caption. A bare .app-numeric ties
   that on specificity (0,1,0) and loses on document order. */
html[dir] .app-numeric {
    font-family: var(--app-mono-font, Consolas, 'Courier New', monospace);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.5px;
}

/* Keeps a negative (expired) readout as "-04:32" rather than letting bidi reorder the sign
   onto the other side of the digits. */
html[dir="rtl"] .app-numeric {
    direction: ltr;
}

/* The expired-token pulse used by TokenStatusPill. */
@keyframes session-flash {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.3; }
}

/* ---- Right-to-left ---------------------------------------------------------------------
   MudRTLProvider (see MainLayout) flips MudBlazor's own components. The rules below cover what
   it does not: the hand-written CSS in this file that would otherwise hardcode a side. Keyed
   off the dir attribute culture.js sets on <html>, so none of it needs a C# flag. */

/* Mirrors a directional glyph — a back/next arrow or chevron — for the reading direction.
   MudRTLProvider moves a StartIcon to the trailing side but does not touch the glyph itself, so
   an unmarked back arrow still points left under RTL, where left is forwards. Opt in per icon:
   only glyphs meaning "the way you came" or "the way ahead" should turn — a folder or a search
   icon must not.

   Put the class on a MudIcon (first selector) or on the MudButton carrying it (the other two,
   which reach the icon without flipping the label). A MudIconButton renders neither the class
   on the glyph nor a mud-button-icon-start, so it needs the last selector. Deliberately not a
   bare .app-mirror-icon: that would also match the button root and mirror its text. */
html[dir="rtl"] .mud-icon-root.app-mirror-icon,
html[dir="rtl"] .app-mirror-icon .mud-button-icon-start,
html[dir="rtl"] .app-mirror-icon .mud-button-icon-end,
html[dir="rtl"] .app-mirror-icon .mud-icon-root {
    transform: scaleX(-1);
}

/* Email and phone fields under RTL. MudBlazor marks the .mud-input box of those two types
   mud-ltr (direction: ltr !important) so an address or number is typed left to right — but the
   class sits on the whole box, not the <input>, so the adornment icon and the outline's notch
   go left while the label, a sibling outside the box, stays right under MudRTLProvider. An
   outlined field then shows its label striking through the border, beside an empty notch on the
   far side. Put the box back in the page's direction and keep only the typed value left to
   right, aligned to the start of the field. html[dir] plus the chained classes outrank
   MudBlazor's bare .mud-ltr, which is needed as both are !important. */
html[dir="rtl"] .mud-input.mud-ltr:has(input[type="email"]),
html[dir="rtl"] .mud-input.mud-ltr:has(input[type="tel"]) {
    direction: rtl !important;
}

html[dir="rtl"] .mud-input.mud-ltr input[type="email"],
html[dir="rtl"] .mud-input.mud-ltr input[type="tel"] {
    direction: ltr;
    text-align: right;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid red;
}

.validation-message {
    color: red;
}

#blazor-error-ui {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        inset-inline-end: 0.75rem;
        top: 0.5rem;
    }

    /* Logical property: the reload control follows the message in both directions. */
    #blazor-error-ui .reload {
        margin-inline-start: 0.75rem;
    }

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

code {
    color: #c02d76;
}

/* ---- Admin lists that fold to a list on a phone -------------------------------------------
   Below md the users and roles tables stop being tables: each row becomes one tappable list
   item — tinted circle, name, kebab — and the table head goes with it, since column labels have
   nothing left to label once the row is a single cell. The breakpoint is MudBlazor's own md
   (960px), so these rules and the d-md-* classes on the cells switch on the same width. */

@media (max-width: 959.98px) {
    /* Only the headings row goes, not the whole head: MudTable renders its loading bar as a
       second row of the same thead, and hiding the element took the bar with it. */
    .app-list-table thead > tr:first-child {
        display: none;
    }

    /* Fixed layout is what keeps the row inside the screen. In the default auto layout a cell
       is never narrower than its content's minimum width, and a nowrap line's minimum is the
       whole line — so the cell grew to fit the longest address on the page and the container
       scrolled sideways. With fixed layout the single cell is the table's width and the
       ellipsis does its job. */
    .app-list-table .mud-table-root {
        table-layout: fixed;
    }
}

/* While a reload is in flight the rows on screen are the previous answer. MudTable keeps them
   live under a 4px bar, which is easy to miss; dimming them and taking the pointer off says
   "these are stale" at any width. The page toggles the class from its ServerData delegate. */
.app-list-table.app-reloading .mud-table-body {
    opacity: 0.45;
    pointer-events: none;
    transition: opacity 150ms;
}

.app-list-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    min-height: 64px;
    cursor: pointer;
}

/* min-width: 0 is what lets the ellipsis below happen: a flex item's default min-width is auto,
   meaning "never shrink below the content", so a long address would push the row wider than the
   screen instead of truncating inside it. */
.app-list-lines {
    flex: 1;
    min-width: 0;
}

.app-list-primary,
.app-list-secondary {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-list-primary {
    font-weight: 600;
    line-height: 1.35;
}

.app-list-secondary {
    font-size: 0.8125rem;
    line-height: 1.35;
    color: var(--mud-palette-text-secondary);
}

/* One hue per record (TintedAvatar picks it), carried in as --app-avatar-h and turned into a
   pair here: a soft wash for the circle and a deep version of the SAME hue for the initials.
   Same-hue rather than white-on-saturated because ten saturated circles on one screen read as a
   toy, and because white text would have to hold contrast against every hue in the set at one
   lightness — generating each pair from its own hue lands them all at the same contrast.

   Light first, then re-stated for dark off the .app-theme-dark class MainLayout puts on
   MudLayout: no hardcoded colour could serve every theme, but a hue rotated to the right
   lightness can. html[dir] so a tie with MudBlazor's own .mud-avatar-* colour classes is not
   lost on document order. */
html[dir] .mud-avatar.app-avatar {
    background-color: hsl(var(--app-avatar-h, 210), 52%, 87%);
    color: hsl(var(--app-avatar-h, 210), 45%, 30%);
    font-weight: 600;
    font-size: 0.9rem;
}

html[dir] .app-theme-dark .mud-avatar.app-avatar {
    background-color: hsl(var(--app-avatar-h, 210), 32%, 27%);
    color: hsl(var(--app-avatar-h, 210), 60%, 78%);
}

/* The leading element for a row that stands for a thing rather than a person — a role, and
   whatever else follows it. Deliberately NOT the circle above: a circle of coloured initials is
   the person convention wherever it appears, so on a role it reads as a user account. Square-ish
   corners and one monochrome glyph say "an entity" instead. primary-hover is MudBlazor's own
   low-alpha primary, so the tile follows whichever theme is on without naming a colour. */
.app-list-tile {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 10px;
    background-color: var(--mud-palette-primary-hover);
}
