/* ── Self-hosted fonts — no Google Fonts, no CDN. A branch till runs whole days with no internet
   (FR-SYN-01), and a blocking request to an external font host would stall first paint until it
   timed out. Both are OFL, variable-weight, Latin-subset (licences alongside the files). */
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("fonts/inter-latin-wght-normal.woff2") format("woff2-variations");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Space Grotesk";
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url("fonts/space-grotesk-latin-wght-normal.woff2") format("woff2-variations");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ── Design tokens ────────────────────────────────────────────────────────────────────────────
   Custom CSS in this product reaches colour only through MudBlazor's own --mud-palette-* variables
   (never a literal hex), so a page written once looks right in light mode, dark mode and under a
   tenant's own branding without a second implementation of any of the three. The handful of tokens
   below are the ones nothing in MudBlazor already exposes — a shared gradient, shadow depths, and
   one motion duration so every transition in the product agrees on how fast "fast" is. */
:root {
    --r360-font-display: "Space Grotesk", "Inter", "Segoe UI", Arial, sans-serif;
    --r360-gradient-brand: linear-gradient(120deg, #4338CA 0%, #6D28D9 55%, #7C3AED 100%);
    --r360-shadow-sm: 0 1px 2px rgba(23, 26, 44, 0.06), 0 1px 1px rgba(23, 26, 44, 0.04);
    --r360-shadow-md: 0 4px 12px rgba(23, 26, 44, 0.08), 0 2px 4px rgba(23, 26, 44, 0.05);
    --r360-shadow-lg: 0 12px 32px rgba(23, 26, 44, 0.14), 0 4px 8px rgba(23, 26, 44, 0.06);
    --r360-speed: 150ms;
}

/* ── Boot splash — no loading markup existed before this pass; the body was blank until WASM
   finished booting. Static, unlocalised (brand name only, pre-render, no data), zero script
   required to show it and only a one-line fallback to hide it (see MainLayout.OnAfterRenderAsync's
   r360HideSplash call) — the primary removal is pure CSS so a slow/failed script never leaves it
   stuck on screen. */
#r360-splash {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1.25rem;
    background-color: #4338CA;
    background-image: var(--r360-gradient-brand);
}

#r360-splash svg {
    width: 3.5rem;
    height: 3.5rem;
}

#r360-splash .r360-splash-word {
    font-family: var(--r360-font-display);
    font-weight: 700;
    font-size: 1.125rem;
    letter-spacing: 0.01em;
    color: #FFFFFF;
}

#r360-splash .r360-splash-bar {
    width: 8rem;
    height: 3px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.25);
    overflow: hidden;
}

#r360-splash .r360-splash-bar::after {
    content: "";
    display: block;
    width: 40%;
    height: 100%;
    background: #FFFFFF;
    animation: r360-splash-pulse 1.1s ease-in-out infinite;
}

@keyframes r360-splash-pulse {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(350%); }
}

/* Primary removal: the moment MainLayout has rendered, .mud-layout exists and the splash is gone
   with no script involved. :has() is supported by every evergreen browser this product targets. */
body:has(.mud-layout) #r360-splash {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    #r360-splash .r360-splash-bar::after {
        animation: none;
    }
}

/* ── App bar — a gradient SHEEN over the solid palette colour, never in place of it.
   The Playwright contrast walker (ShellAccessibilityTests.ContrastScript) resolves only
   getComputedStyle(el).backgroundColor when it walks up looking for an opaque ancestor — a
   background-image is invisible to it. Putting the gradient on background-image and leaving
   background-color as MudBlazor's own --mud-palette-appbar-background var means the walker keeps
   measuring the real, contrast-checked colour while the eye sees the gradient sitting on top of it. */
.mud-appbar {
    background-image:
        linear-gradient(100deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0) 45%),
        linear-gradient(260deg, rgba(124, 58, 237, 0.45) 0%, rgba(124, 58, 237, 0) 55%);
}

/* ── Tables — MudSimpleTable/MudTable ship with none of this: no zebra striping, no distinct
   header treatment. Applied globally through MudBlazor's own table variables so every one of the
   45 tables across the product (and any built after this file was last touched) inherits it for
   free, in both palettes. */
.mud-table-head th, .mud-simple-table thead th {
    font-family: var(--r360-font-display);
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--mud-palette-text-secondary);
    border-bottom: 2px solid var(--mud-palette-lines-default);
}

.mud-table-row:nth-of-type(even), .mud-simple-table tbody tr:nth-of-type(even) {
    background-color: var(--mud-palette-table-striped);
}

.mud-table-row:hover, .mud-simple-table tbody tr:hover {
    background-color: var(--mud-palette-table-hover);
}

/* A money/quantity column opts into this so figures line up on their decimal point instead of
   ragging left — the same reasoning document.css already applies to the printed receipt, extended
   to the on-screen tables that lead up to it. */
.r360-num {
    font-variant-numeric: tabular-nums;
}

/* ── Motion — kept short and consistent rather than left to each component's own default, and
   turned off outright for anyone who has asked the OS not to animate things. */
.mud-button-root, .mud-paper, .mud-nav-link, .mud-chip {
    transition: background-color var(--r360-speed) ease, box-shadow var(--r360-speed) ease, border-color var(--r360-speed) ease, color var(--r360-speed) ease;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* A shared content-width cap so a page doesn't stretch edge-to-edge on a wide monitor while still
   filling a 1024px till screen (NFR-UX-05) — MainLayout's MudContainer stays MaxWidth.False and
   this class does the capping instead, so a page can still opt out for something that genuinely
   wants full width (a dense worklist table, say) by simply not nesting inside it. */
.r360-page {
    max-width: 1480px;
    margin-inline: auto;
}

/* ── Legacy framework hooks — kept because something still uses them ────────────────────────── */

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.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."
    }

/* ── Keyboard focus — NFR-UX-04 ─────────────────────────────────────────────────────────────
   MudBlazor removes the focus ring (.mud-button-root { outline: 0 }) and signals focus with a
   ripple overlay instead, which is drawn on pointer interaction and so is invisible to someone
   tabbing through the shell. Found by
   ShellAccessibilityTests.Focus_is_always_visible_to_the_person_using_it, not by looking.

   This matters more here than on a typical web app. NFR-UX-01 requires a complete cash sale with
   no mouse, so an operator will spend their whole day navigating by keyboard — and an invisible
   focus ring means they cannot tell which control Enter is about to activate.

   :focus-visible, not :focus. The browser applies it to keyboard focus and withholds it from a
   mouse click, which stops a permanent outline appearing around every button an operator has
   tapped on a touchscreen till.

   currentColor keeps it legible on the tenant's own primary colour (NFR-UX-03); a fixed outline
   colour would vanish the moment a tenant branded their app bar something similar.

   The selectors carry a class so they outrank MudBlazor's own (0,1,0) reset rather than tying
   with it and depending on source order. */
.mud-button-root:focus-visible,
.mud-nav-link:focus-visible,
.mud-input-control:focus-visible,
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

/* The router moves focus to the page heading on navigation (FocusOnNavigate), which is what makes
   keyboard routing announce where it arrived. That focus is programmatic, so it should not paint
   a ring — the heading is not something the operator is about to activate. */
h1:focus,
h1:focus-visible {
    outline: none;
}
