/* PlatinumPOS — Platinum Brink Technologies Design System */

/* ── MudBlazor utility shims ──────────────────────────────────────────────
   The markup uses a few Tailwind/Bootstrap class names that MudBlazor 9.x does
   NOT ship (it uses `justify-space-between`, and has no `text-truncate`). Without
   these, flex rows collapse (label/value jam together) and long text overflows
   its box. Aliasing them here fixes every usage app-wide at once. */
.justify-between { justify-content: space-between !important; }
.text-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

html, body {
    margin: 0;
    font-family: Inter, 'Segoe UI', system-ui, Roboto, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    overflow: hidden; /* POS usually locks viewport scroll */
    height: 100vh;
    height: 100dvh; /* iPad Safari: 100vh includes the collapsing toolbar, so the last ~60px of the
                       page sits under it and — with body scroll locked — can never be reached. */
}

h1:focus { outline: none; }

/* ── POS layout scrollbars ──────────────────────────────────────────── */
::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}
::-webkit-scrollbar-track {
    background: transparent;
}
::-webkit-scrollbar-thumb {
    background: var(--mud-palette-lines-default, #E3E3E3);
    border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
    background: var(--mud-palette-lines-inputs, #8E918F);
}

/* ── Brand header ──────────────────────────────────────────── */
.rw-brand-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    padding-bottom: 8px;
}
.rw-brand-text { flex: 1 1 auto; min-width: 0; }

/* ── Section header rows (heading/description + action button(s)) ─────
   Same wrapping recipe as .rw-brand-header: on narrow viewports the action
   button(s) drop below the heading instead of overflowing off-screen or
   overlapping the description text (MudBlazor's plain "d-flex justify-between"
   utility is nowrap by default, which pushed 3-button toolbars and the
   Z-Report button off/over their siblings on mobile). */
.rw-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px 16px;
}
.rw-section-header > *:first-child {
    flex: 1 1 220px;
    min-width: 0;
}
.rw-section-header > .rw-section-actions {
    flex: 0 1 auto;
    flex-wrap: wrap;
}

/* ── Dashboard action tiles ──────────────────────────────────────────── */
.w8-tile {
    cursor: pointer;
    transition: transform .2s, box-shadow .2s;
    border-radius: 24px;
    /* Lets the headline figure below size itself against THIS tile rather than the viewport. */
    container-type: inline-size;
}

/* Stat-tile headline figures must never be cut off. At a fixed h4 (34px) "R39 131 990,00" needs
   ~250px, but a quarter-width tile on a 1024px tablet only offers ~190px — so the last digits were
   being painted underneath the neighbouring tile and the manager read a wrong number. The value now
   scales down to fit its own tile, with a floor that stays comfortably readable. */
.w8-tile .mud-typography-h4 {
    font-size: clamp(1.05rem, 12.5cqw, 2.125rem);
    line-height: 1.2;
    white-space: nowrap;
    max-width: 100%;
}
.w8-tile .mud-typography-h5 {
    font-size: clamp(0.95rem, 10.5cqw, 1.5rem);
    line-height: 1.25;
    white-space: nowrap;
    max-width: 100%;
}
.w8-tile:hover  { transform: translateY(-2px); box-shadow: 0 12px 24px rgba(0,0,0,.08); }
.w8-tile:active { transform: translateY(0);    box-shadow: 0 4px 12px rgba(0,0,0,.05); }

/* ── Footprint code tag ──────────────────────────────────────────────── */
.pa-footprint {
    background: var(--mud-palette-background-gray, #F0F4F9);
    padding: 6px 12px;
    border-radius: 6px;
    font-size: 0.875rem;
    font-weight: 600;
    font-family: 'JetBrains Mono', 'Cascadia Code', 'Fira Code', monospace;
    color: var(--mud-palette-text-primary);
    border: 1px solid var(--mud-palette-lines-default);
    display: inline-block;
    letter-spacing: 0.5px;
}

/* ── Activity card ───────────────────────────────────────────────────── */
.rw-activity-card {
    border-radius: 24px !important;
    border: 1px solid var(--mud-palette-lines-default, #E3E3E3);
    box-shadow: none !important;
    background-color: var(--mud-palette-surface);
}

/* ── Tab bars: separated pills, not one shared card ───────────────────
   rw-activity-card wrapped the header AND the panels together in one bordered
   box, so every tab sat flush against its neighbour with no rounding or
   spacing of its own. rw-tabs (BackOffice / Analytics / Invoicing) drops that
   shared box: the header's own surface background is cleared so each tab can
   be its own rounded, gapped pill floating on the page, and the card look
   moves onto just the panel content underneath, so bare tables (Categories,
   Cashier Profiles, Audit Logs) still sit inside a bordered surface. */
.rw-tabs .mud-tabs-tabbar {
    background-color: transparent !important;
    border-radius: 0 !important;
    margin-bottom: 16px;
}
.rw-tabs .mud-tabs-panels {
    border-radius: 24px !important;
    border: 1px solid var(--mud-palette-lines-default, #E3E3E3);
    background-color: var(--mud-palette-surface);
    overflow: hidden;
}
.rw-tabs .mud-tab {
    border-radius: 999px !important;
    border-bottom: none !important;
}
.rw-tabs .mud-tab:hover {
    background-color: var(--mud-palette-primary-hover);
}
.rw-tabs .mud-tab.mud-tab-active {
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text, #fff);
    font-weight: 700;
}
.rw-tabs .mud-tab.mud-tab-active:hover {
    background-color: var(--mud-palette-primary);
}

/* ── Compact icon-only tabs on phones (Back Office / Analytics) ───────
   MudTabs renders every tab header in one row and horizontally scrolls
   it (via a JS-calculated transform, not native overflow) once it's wider
   than the viewport — which is every time on a phone, since 6 tabs at
   ~110-160px each add up to 700-960px. MudBlazor's own scroll-into-view
   math can overshoot when a tapped tab is more than one position away,
   leaving the visually-highlighted header out of sync with the (still
   correctly rendered) active panel below it. Rather than patch that
   compiled 3rd-party scroll logic, we remove the need to scroll at all
   below 600px: icon-only tabs are narrow enough that all 6 fit in one
   screen width, so the buggy scroll path never triggers. Each tab's
   full label survives as its native title/tooltip (see ToolTip on each
   MudTabPanel) and stays visible from 600px up (tablet/desktop).
   Requires each MudTabPanel to use a <TabContent> with a "rw-tab-label"
   span instead of the plain Text parameter — MudBlazor renders Text as a
   raw sibling text node with no wrapper element we could otherwise target. */
@media (max-width: 600px) {
    .rw-tabs .mud-tab {
        min-width: 44px !important;
        padding-left: 12px !important;
        padding-right: 12px !important;
    }
    /* Visually hidden, not display:none — screen readers still announce the
       label (assistive tech excludes display:none content from the tab's
       accessible name entirely, which would leave these tabs unlabelled). */
    .rw-tabs .rw-tab-label {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }
    .rw-tabs .mud-tab-icon-text {
        margin-right: 0 !important;
    }
}

/* ── Tab bars wrap; they never scroll ─────────────────────────────────────
   MudTabs lays its whole tab strip out in one row and, when that row is wider than the panel,
   positions it with a JS-calculated transform behind an overflow:hidden window. Back Office has 6
   tabs and Analytics 7 — 1455px of tabs inside an 876px window on a 1024px tablet — so several tabs
   were simply unreachable, and the scroll maths routinely left the *active* tab off-screen (the
   same bug the icon-only phone treatment below was originally added to dodge). Rather than scroll
   at all, the strip wraps onto as many rows as it needs: every tab is always visible and tappable
   at every width. The sliding underline can't track a wrapped strip, so the active tab is marked
   directly instead. */
/* Note the nesting: .mud-tabs-tabbar-content > .mud-tabs-tabbar-inner > .mud-tabs-tabbar-wrapper,
   and it is the *wrapper* that holds the tabs and is transformed. That is the element that has to
   wrap. Gap lives here too — this is what actually spaces one pill from the next. */
.rw-tabs .mud-tabs-tabbar-content,
.rw-tabs .mud-tabs-tabbar-inner {
    overflow: visible !important;
    min-width: 0;
}
.rw-tabs .mud-tabs-tabbar-wrapper {
    display: flex !important;
    flex-wrap: wrap !important;
    overflow: visible !important;
    transform: none !important;
    white-space: normal;
    width: 100%;
    min-width: 0;
    gap: 10px;
}
/* MudBlazor pins every tab to a 160px minimum, which forces 7 Analytics tabs onto more rows than
   they need. Sizing to content packs them tighter while staying well above a comfortable tap
   target (each tab keeps its icon, label and 20px of horizontal padding). Scoped to 601px and up so
   it can never undercut the explicit 44px minimum the icon-only phone treatment relies on. */
@media (min-width: 601px) {
    .rw-tabs .mud-tab {
        min-width: 0 !important;
    }
}
.rw-tabs .mud-tabs-scroll-button { display: none !important; }
.rw-tabs .mud-tab-slider { display: none !important; }

/* ── Page-level layout helpers ───────────────────────────────────────── */
.w8-page-content {
    height: calc(100vh - 64px); /* viewport minus app bar */
    height: calc(100dvh - 64px);
    overflow-y: auto;           /* let long pages (Back Office) scroll instead of clipping */
    overflow-x: hidden;
    box-sizing: border-box;
}

/* ── Nav drawer overrides (Google Pill Shape) ────────────────────────── */
.mud-drawer {
    border-right: none !important;
}
.mud-drawer .mud-nav-link {
    border-radius: 100px; /* MD3 pill shape */
    margin: 4px 12px;
    padding: 10px 16px;
    font-weight: 500;
    transition: background-color 0.2s ease, color 0.2s ease;
}
.mud-drawer .mud-nav-link:hover,
.mud-drawer .mud-nav-link:focus {
    background-color: var(--mud-palette-action-default-hover) !important;
}
/* A translucent tint of Primary itself, not PrimaryLighten: in the light theme PrimaryLighten is a
   near-white neutral (so it read fine), but in the dark theme it's just a LIGHTER SHADE OF THE SAME
   BLUE as Primary — active nav text ended up nearly the same colour as its own background. Deriving
   the tint from Primary's own rgb triplet (MudBlazor always exposes one) self-corrects in both themes
   with no separate dark-mode override. Same bug + same fix as PlatinumWeigh's identical rule. */
.mud-drawer .mud-nav-link.active {
    background-color: rgba(var(--mud-palette-primary-rgb), 0.16) !important;
    color: var(--mud-palette-primary) !important;
}
.mud-drawer .mud-nav-link.active .mud-icon-root {
    color: var(--mud-palette-primary) !important;
}

/* ── Page footer ──────────────────────────────────────────────────────── */
.rw-page-footer {
    padding: 8px;
    text-align: center;
}

/* ── MudTable polish ─────────────────────────────────────────────────── */
.mud-table-container {
    border-radius: 0;
    overflow-x: auto;
}
.mud-table-root .mud-table-head .mud-table-cell {
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    border-bottom: 1px solid var(--mud-palette-lines-default);
}
.mud-table-root .mud-table-body .mud-table-cell {
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* ── Dialog polish ───────────────────────────────────────────────────── */
.mud-dialog {
    border-radius: 28px !important;
    box-shadow: 0 24px 38px 3px rgba(0,0,0,0.14), 0 9px 46px 8px rgba(0,0,0,0.12), 0 11px 15px -7px rgba(0,0,0,0.2) !important;
}

/* ── App bar polish ──────────────────────────────────────────────────── */
.mud-appbar {
    border-bottom: none !important;
}

/* ── POS Keypad styling ───────────────────────────────────────────────── */
.pos-keypad-btn {
    border-radius: 50% !important;
    width: 72px;
    height: 72px;
    font-size: 1.5rem !important;
    font-weight: 500 !important;
    border: 1px solid var(--mud-palette-lines-default) !important;
    background-color: var(--mud-palette-surface) !important;
    color: var(--mud-palette-text-primary) !important;
    box-shadow: none !important;
    transition: background-color 0.15s ease;
}
.pos-keypad-btn:active {
    background-color: var(--mud-palette-primary-lighten) !important;
    color: var(--mud-palette-primary) !important;
}

/* ── POS Layout containers ────────────────────────────────────────────── */
.pos-container {
    display: flex;
    height: 100%; /* fill .w8-page-content; internal panels handle their own scroll */
    overflow: hidden;
    gap: 16px;
    padding: 8px;
    box-sizing: border-box;
}

.pos-cart-panel {
    flex: 0 0 360px;
    min-width: 0; /* allow children to truncate instead of overflowing */
    display: flex;
    flex-direction: column;
    height: 100%;
    border-radius: 24px;
    border: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
}

.pos-catalog-panel {
    flex: 1 1 auto;
    min-width: 0; /* critical: lets the grid reflow rather than push the cart off-screen */
    display: flex;
    flex-direction: column;
    height: 100%;
}

/* Clamp product names to 2 lines so long titles never spill out of the tile */
.pos-prod-name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
}

/* ── Catalog header (search + category filters) ───────────────────────────
   Flexbox that wraps, so it adapts to the *catalog panel's* width rather than
   the viewport. In landscape the nav drawer + cart panel can squeeze the
   catalog narrow; here the category strip drops below the search box instead
   of the two colliding. */
.pos-catalog-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
}
.pos-search-box {
    flex: 1 1 230px;
    min-width: 190px;
}
.pos-cat-scroll {
    flex: 100 1 280px;
    min-width: 0;
    display: flex;
    gap: 8px;
    overflow-x: auto;
    white-space: nowrap;
    padding-bottom: 2px;
}

/* ── Product grid: CONTAINER-responsive, not viewport-responsive ───────────
   The number of columns follows the catalog panel's real width, so cards never
   get crushed when the drawer/cart eat horizontal space (the old MudGrid
   md="3" forced 4 columns off the *viewport* width, squashing prices into the
   stock chips in tablet landscape). auto-fill + minmax keeps every card a
   readable width and reflows the count automatically. */
.pos-product-grid-inner {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: 16px;
    align-content: start;
}

/* Price + stock row inside each card. Wraps (chip drops below the price) when
   the card is narrow, so the two never overlap or spill outside the tile. */
.pos-card-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 4px 8px;
    min-width: 0;
}

/* ── Responsive: stack the register vertically on small tablets/portrait ── */
@media (max-width: 860px) {
    .pos-container {
        flex-direction: column;
        height: auto;
        overflow: visible;
    }
    .pos-cart-panel {
        flex: none;
        width: 100%;
        height: auto;
        max-height: 48vh;
    }
    .pos-catalog-panel {
        height: auto;
    }
}

/* Landscape on small/medium tablets: the nav drawer collapses (thanks to Breakpoint.Lg)
   so we have full width. Slim the cart panel and gaps to give the catalog more room. */
@media (min-width: 861px) and (max-width: 1280px) {
    .pos-cart-panel {
        flex-basis: 300px;
    }
    .pos-container {
        gap: 12px;
        padding: 8px 6px;
    }
}

.pos-cart-items {
    flex: 1 1 auto;
    min-height: 0; /* allow the scroll area to shrink so the totals/checkout stay visible */
    overflow-y: auto;
    padding: 8px;
}

.pos-product-grid {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 8px 0;
}

.pos-product-card {
    border-radius: 16px !important;
    border: 1px solid var(--mud-palette-lines-default);
    transition: transform 0.1s ease, box-shadow 0.15s ease;
    cursor: pointer;
    height: 100%;
}
.pos-product-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.08) !important;
}
.pos-product-card:active {
    transform: translateY(1px);
}

/* Divider between the two halves of the checkout dialog. Applied via a media query rather than an
   inline style so it disappears when MudGrid stacks the columns on a portrait tablet — an inline
   border-right survives the stack and leaves a stray vertical rule down the side of the panel. */
.pos-pay-divider { border-right: none; }
@media (min-width: 960px) {
    .pos-pay-divider { border-right: 1px solid var(--mud-palette-divider); }
}

/* ── Receipt item visual list ────────────────────────────────────────── */
.pos-cart-item-row {
    border-bottom: 1px solid var(--mud-palette-divider);
    padding: 8px 4px;
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.pos-cart-item-row:last-child {
    border-bottom: none;
}

/* ── Animated splash screen (canvas particle effect, light + dark modes) ── */
#splash-screen {
    position: fixed;
    inset: 0;
    z-index: 9999;
    overflow: hidden;
    transition: opacity 0.6s ease;
}
#splash-screen.splash-fade {
    opacity: 0;
    pointer-events: none;
}
#splashCanvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}
.splash-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    z-index: 10;
}
.splash-logo-wrap {
    position: relative;
    margin-bottom: 2rem;
}
.splash-glow {
    position: absolute;
    top: -50%; left: -50%; right: -50%; bottom: -50%;
    background: #2563EB;
    filter: blur(60px);
    opacity: 0.18;
    border-radius: 50%;
}
.splash-logo {
    position: relative;
    z-index: 10;
    width: min(18rem, 72vw);
    height: auto;
    filter: drop-shadow(0 0 24px rgba(37,99,235,0.55));
}
#splash-screen.splash-dark .splash-tagline {
    color: rgba(255,255,255,0.70);
    text-shadow: 0 0 10px rgba(37,99,235,0.5);
}
#splash-screen.splash-light .splash-tagline,
#splash-screen:not(.splash-dark) .splash-tagline {
    color: #444746;
    text-shadow: none;
}
.splash-tagline {
    font-family: Inter, 'Segoe UI', system-ui, Roboto, Helvetica, Arial, sans-serif;
    font-size: 0.82rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    margin: 0;
    text-align: center;
    max-width: 90vw;
    padding: 0 12px;
}
/* ── Activity chart sparkline (custom responsive SVG) ───────────────────
   A fixed 0–100 viewBox stretched edge-to-edge (preserveAspectRatio="none").
   Strokes use vector-effect:non-scaling-stroke so they stay crisp & uniform
   regardless of the non-uniform stretch; data dots are HTML so they stay
   perfectly round. This fills the full card width on every screen size. */
.rw-spark {
    position: relative;
    width: 100%;
    height: 250px;
}
.rw-spark--center {
    display: flex;
    align-items: center;
    justify-content: center;
}
.rw-spark-svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    /* `visible` let the non-scaling strokes paint a few pixels past the card and, on the widest
       card, past the viewport edge. The 10%/90% plot band already keeps the line clear of the
       edges, so there is nothing legitimate to overflow. */
    overflow: hidden;
}
.rw-spark-grid {
    stroke: var(--mud-palette-divider, #e2e8f0);
    stroke-width: 1;
    stroke-dasharray: 3 4;
    opacity: 0.5;
}
.rw-spark-dot {
    position: absolute;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--mud-palette-surface, #fff);
    transform: translate(-50%, -50%);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
    transition: width .12s ease, height .12s ease;
    cursor: default;
    z-index: 2;
}
.rw-spark-dot--primary { border: 2.5px solid var(--mud-palette-primary, #ef4444); }
.rw-spark-dot--secondary { border: 2.5px solid var(--mud-palette-secondary, #22c55e); }
.rw-spark-dot:hover {
    width: 14px;
    height: 14px;
    z-index: 3;
}
.rw-spark-ymax {
    position: absolute;
    top: 10%;
    left: 0;
    transform: translateY(-50%);
    font-size: 0.68rem;
    font-weight: 600;
    line-height: 1;
    color: var(--mud-palette-text-secondary);
    background: var(--mud-palette-surface, #fff);
    padding: 1px 5px;
    border-radius: 4px;
    opacity: 0.9;
    pointer-events: none;
}
.rw-spark-axis {
    position: relative;
    width: 100%;
    height: 16px;
    margin-top: 8px;
}
.rw-spark-axis span {
    position: absolute;
    transform: translateX(-50%);
    font-size: 0.7rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}
@media (max-width: 480px) {
    .rw-spark { height: 210px; }
    .rw-spark-axis span { font-size: 0.62rem; }
}


/* Legend swatch (square colour indicator in the legend table) */
.rw-legend-swatch {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    flex-shrink: 0;
}

