/* /Components/Layout/MainLayout.razor.rz.scp.css */
/* MainLayout-scoped rules only.
   The .web-* app chrome moved to wwwroot/css/app-chrome.css under
   #15699 so PortalLayout gets it too. What stays here is the
   breadcrumb set, which is rendered by CHILD pages and so genuinely
   needs ::deep against MainLayout's scope id. */



/* PBI #15233 — shared breadcrumb strip rendered by MainLayout.
   Detail pages (JobDetail/ClientDetail/ProductDetail) populate the
   trail via BreadcrumbsState.Set(...); this replaces the three
   different ad-hoc "Back to ..." button styles those pages each
   invented. List pages (no trail set) render nothing. */
[b-rcrf517nbc] .app-breadcrumbs {
    margin: 0 0 0.85rem;
    font-size: 0.78rem;
    line-height: 1.2;
}

[b-rcrf517nbc] .app-breadcrumbs__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.35rem;
}

[b-rcrf517nbc] .app-breadcrumbs__item {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--text-muted);
}

[b-rcrf517nbc] .app-breadcrumbs__link {
    color: var(--text-muted);
    text-decoration: none;
    border-radius: var(--radius-sm);
    padding: 0.1rem 0.25rem;
    transition: color 120ms ease, background 120ms ease;
}

[b-rcrf517nbc] .app-breadcrumbs__link:hover,
[b-rcrf517nbc] .app-breadcrumbs__link:focus-visible {
    color: var(--brand-sea);
    background: color-mix(in oklab, var(--brand-sea-soft) 55%, var(--surface));
    outline: none;
}

[b-rcrf517nbc] .app-breadcrumbs__sep {
    color: var(--border-strong);
    user-select: none;
}

[b-rcrf517nbc] .app-breadcrumbs__current {
    color: var(--text);
    font-weight: 600;
    padding: 0.1rem 0.25rem;
}
@media (max-width: 768px) {

    /* A three-level trail wraps to two lines and pushes the page
       title below the fold. Keep the trail on one line and let the
       leading crumbs ellipsis instead. */
    [b-rcrf517nbc] .app-breadcrumbs__list {
        flex-wrap: nowrap;
        overflow: hidden;
    }

    /* The <li> is the flex child of the list, and the current-page
       <span> is the flex child of that <li>. Both default to
       min-width: auto, i.e. a min-content floor, so neither can ever
       shrink — text-overflow below never fires and `overflow: hidden`
       above just hard-clips the page name mid-word at the right edge.
       min-width: 0 is what actually turns the clip into an ellipsis. */
    [b-rcrf517nbc] .app-breadcrumbs__item {
        min-width: 0;
    }

    [b-rcrf517nbc] .app-breadcrumbs__link {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        max-width: 8rem;
    }

    [b-rcrf517nbc] .app-breadcrumbs__current {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}
/* /Components/Layout/NavMenu.razor.rz.scp.css */
/* NavMenu — tokenised. Active link now uses the brand-sea
   gradient instead of flat ink black; non-active links are
   muted until hover so the current page reads as the focal
   point. */

.web-module-nav[b-1tvai779q2] {
    display: flex;
    gap: 0.25rem;
    flex-wrap: wrap;
    padding: 0.55rem 1rem 0.65rem;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
}

.web-module-nav[b-1tvai779q2]  .web-module-link {
    display: inline-flex;
    align-items: center;
    min-height: 1.85rem;
    padding: 0.28rem 0.78rem;
    border-radius: 999px;
    color: var(--text-muted);
    text-decoration: none;
    font-weight: 600;
    font-size: 0.8rem;
    line-height: 1;
    border: 1px solid transparent;
    transition: color 120ms ease, background 120ms ease, border-color 120ms ease;
}

.web-module-nav[b-1tvai779q2]  .web-module-link:hover {
    color: var(--brand-sea);
    background: color-mix(in oklab, var(--brand-sea-soft) 55%, var(--surface));
    border-color: color-mix(in oklab, var(--brand-sea) 22%, var(--border));
}

.web-module-nav[b-1tvai779q2]  a.active,
.web-module-nav[b-1tvai779q2]  a.active:hover,
.web-module-nav[b-1tvai779q2]  a.active:focus-visible {
    /* Single rule for active + active-hover + active-focus so the
       base .web-module-link:hover background can never blank out
       the gradient underneath the white text. */
    background: linear-gradient(180deg, var(--brand-sea) 0%, var(--brand-sea-ink) 100%);
    color: #ffffff;
    border-color: transparent;
    box-shadow: var(--shadow-sm);
}

.web-module-nav[b-1tvai779q2]  a.active:hover {
    filter: brightness(1.05);
}

/* PBI #15234 — on narrow viewports the 8 module links would wrap
   to two or three rows, eating vertical space above the actual
   page. Collapse to a single horizontally-scrollable row instead.
   nowrap + overflow-x: auto keeps every link reachable via swipe;
   -webkit-overflow-scrolling: touch gives iOS the momentum feel.

   Raised from 720px to the --bp-lg stop (1024px). 720 was chosen
   for phones and happened to sit just under every iPad width, so
   the exact device this row was designed for never got it: an iPad
   in portrait (768–834) wrapped the 8 links onto two rows, and in
   landscape (1024) it was borderline. At 1024 the links usually
   still fit on one line, in which case nowrap costs nothing and no
   scrollbar appears — but when they don't fit, they swipe. */
@media (max-width: 1024px), (pointer: coarse) and (max-width: 1366px) {
    .web-module-nav[b-1tvai779q2] {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        /* overscroll containment stops a swipe that runs off the end
           of the tab strip from bouncing the whole page sideways. */
        overscroll-behavior-x: contain;
        scrollbar-width: none;
        /* scroll-padding keeps the active pill clear of the edge when
           the browser scrolls it into view on navigation. */
        scroll-padding-inline: 1rem;
    }

    .web-module-nav[b-1tvai779q2]::-webkit-scrollbar {
        display: none;
    }

    .web-module-nav[b-1tvai779q2]  .web-module-link {
        flex: 0 0 auto;
    }
}

/* Touch targets — the 1.85rem pill is 30px tall, well under the 44px
   floor, and these are the app's primary navigation. */
@media (pointer: coarse) {
    .web-module-nav[b-1tvai779q2]  .web-module-link {
        min-height: var(--control-h);
        padding-inline: 0.95rem;
    }
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-lneei1k5q3],
.components-reconnect-repeated-attempt-visible[b-lneei1k5q3],
.components-reconnect-failed-visible[b-lneei1k5q3],
.components-pause-visible[b-lneei1k5q3],
.components-resume-failed-visible[b-lneei1k5q3],
.components-rejoining-animation[b-lneei1k5q3] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-lneei1k5q3],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-lneei1k5q3],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-lneei1k5q3],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-lneei1k5q3],
#components-reconnect-modal.components-reconnect-retrying[b-lneei1k5q3],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-lneei1k5q3],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-lneei1k5q3],
#components-reconnect-modal.components-reconnect-failed[b-lneei1k5q3],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-lneei1k5q3] {
    display: block;
}


#components-reconnect-modal[b-lneei1k5q3] {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-lneei1k5q3 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-lneei1k5q3 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-lneei1k5q3 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-lneei1k5q3]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-lneei1k5q3 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-lneei1k5q3 {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-lneei1k5q3 {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-lneei1k5q3 {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-lneei1k5q3] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-lneei1k5q3] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-lneei1k5q3] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-lneei1k5q3] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-lneei1k5q3] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-lneei1k5q3] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-lneei1k5q3] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-lneei1k5q3 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-lneei1k5q3] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-lneei1k5q3 {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Pages/BidDiagram.razor.rz.scp.css */
/* BidDiagram (BidSketch) page scoped styles. Relies on the global
   tokens from /wwwroot/css/theme.css.

   Bug #15265 — these panel rules used to live as inline style="..."
   attributes on the page with raw 4px border-radius and the wrong
   fallback hex values for --border-muted / --surface-sunken. Moved
   here so the panels read from the theme's radius and color tokens
   directly, and so any future tweak lives in one place. */

.bidsketch-palette-shell[b-t4k7s0uaep] {
    flex: 0 0 240px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    overflow: visible;
    background: var(--surface-sunken);
}

.diagram-canvas-shell[b-t4k7s0uaep] {
    flex: 1 1 auto;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    overflow: auto;
    min-width: 0;
}

.bidsketch-placeholder[b-t4k7s0uaep] {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
}

.bidsketch-placeholder--palette[b-t4k7s0uaep] {
    flex: 0 0 240px;
    background: var(--surface-sunken);
    font-size: 0.8rem;
}

.bidsketch-placeholder--canvas[b-t4k7s0uaep] {
    flex: 1 1 auto;
    font-size: 0.9rem;
}
/* /Components/Pages/BidMobile.razor.rz.scp.css */
/* Mobile field-crew page (PBI #13556) — scoped styles.
   Pulls from the global design tokens in /wwwroot/css/theme.css
   so the page inherits dark mode + brand colors instead of
   fighting them. Tap-target dimensions (44px / 48px) stay literal
   because they are accessibility minimums, not theme values. */

.mobile-page[b-fj1ldqjbzh] {
    font-family: var(--font-body);
    padding: var(--space-2);
    max-width: 100vw;
    color: var(--text);
}

.mobile-page h1[b-fj1ldqjbzh] {
    font-size: 1.2rem;
    margin: var(--space-2) 0 var(--space-1);
}

.mobile-page .subhead[b-fj1ldqjbzh] {
    color: var(--text-muted);
    font-size: 0.85rem;
    margin-bottom: var(--space-2);
}

.mobile-page .room-picker[b-fj1ldqjbzh] {
    position: sticky;
    top: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    padding: var(--space-2) 0;
    z-index: 10;
}

.mobile-page select[b-fj1ldqjbzh],
.mobile-page input[b-fj1ldqjbzh] {
    width: 100%;
    padding: var(--space-3);
    font-size: 1rem;
    box-sizing: border-box;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-xs);
}

.mobile-page button.tap[b-fj1ldqjbzh] {
    display: block;
    width: 100%;
    padding: var(--space-4);
    font-size: 1rem;
    margin: var(--space-1) 0;
    border: none;
    border-radius: var(--radius-xs);
    cursor: pointer;
    min-height: 48px; /* a11y minimum — keep literal */
}

.mobile-page button.tap.primary[b-fj1ldqjbzh] {
    background: var(--brand-sea);
    color: var(--text-inverse);
}

.mobile-page button.tap.ghost[b-fj1ldqjbzh] {
    background: var(--surface-sunken);
    color: var(--text);
}

.mobile-page button.tap.success[b-fj1ldqjbzh] {
    background: var(--status-success);
    color: #fff;
}

.mobile-page button.tap.warning[b-fj1ldqjbzh] {
    background: var(--status-warning);
    color: var(--status-warning-ink);
}

.mobile-page .item-card[b-fj1ldqjbzh] {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: var(--space-3);
    margin: var(--space-2) 0;
    background: var(--surface);
}

.mobile-page .item-card.installed[b-fj1ldqjbzh] {
    border-left: 4px solid var(--status-success);
}

.mobile-page .item-card.tested[b-fj1ldqjbzh] {
    border-left: 4px solid var(--status-info);
}

.mobile-page .item-card.both[b-fj1ldqjbzh] {
    /* "both" = installed AND tested → blend the two signals so
       the card carries information from both states without
       inventing a new color token. */
    border-left: 4px solid color-mix(in oklab, var(--status-success) 50%, var(--status-info));
}

.mobile-page .item-row[b-fj1ldqjbzh] {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.mobile-page .status-row[b-fj1ldqjbzh] {
    display: flex;
    gap: var(--space-2);
    margin-top: var(--space-2);
}

.mobile-page .status-row button[b-fj1ldqjbzh] {
    flex: 1;
    padding: 0.6rem;
    min-height: 44px; /* a11y minimum — keep literal */
}

.mobile-page .badge[b-fj1ldqjbzh] {
    display: inline-block;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    font-size: 0.75rem;
}

.mobile-page .badge-installed[b-fj1ldqjbzh] {
    background: var(--status-success);
    color: #fff;
}

.mobile-page .badge-tested[b-fj1ldqjbzh] {
    background: var(--status-info);
    color: #fff;
}

/* PBI #15271 — page-scoped .toast styles removed. The page now
   publishes via ToastService and <AppToast /> in MainLayout
   renders one app-wide bubble (style at AppToast.razor.css). */

.mobile-page .add-form[b-fj1ldqjbzh] {
    background: var(--surface-sunken);
    padding: var(--space-3);
    border-radius: var(--radius-sm);
    margin: var(--space-2) 0;
}

.mobile-page .room-stats[b-fj1ldqjbzh] {
    display: flex;
    gap: var(--space-3);
    padding: 0.4rem 0;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.mobile-page .room-stats strong[b-fj1ldqjbzh] {
    color: var(--text);
}

.mobile-page summary[b-fj1ldqjbzh] {
    cursor: pointer;
    padding: var(--space-2) 0;
    font-weight: 600;
}

/* Inline helpers — replace per-element `style="color:#666"` etc.
   so the page renders in dark mode and we don't leak raw hex. */
.mobile-page .mobile-error[b-fj1ldqjbzh] {
    color: var(--status-danger);
}

.mobile-page .mobile-muted[b-fj1ldqjbzh] {
    color: var(--text-muted);
}

.mobile-page .room-label[b-fj1ldqjbzh] {
    display: block;
    font-weight: 600;
    margin-bottom: var(--space-1);
}

.mobile-page .pick-room-hint[b-fj1ldqjbzh] {
    margin-top: var(--space-4);
    color: var(--text-muted);
}

.mobile-page .add-form-hint[b-fj1ldqjbzh] {
    font-size: 0.8rem;
    color: var(--text-muted);
    margin: var(--space-1) 0;
}

.mobile-page .photo-uploading[b-fj1ldqjbzh] {
    margin: var(--space-1) 0;
    color: var(--text-muted);
}

.mobile-page .photo-tally[b-fj1ldqjbzh] {
    margin-top: var(--space-3);
    font-size: 0.85rem;
}

.mobile-page .empty-room[b-fj1ldqjbzh] {
    color: var(--text-muted);
    padding: var(--space-4) 0;
}

.mobile-page .item-description[b-fj1ldqjbzh] {
    color: var(--text-muted);
    margin-left: 0.4rem;
    font-size: 0.85rem;
}

.mobile-page .item-qty[b-fj1ldqjbzh] {
    white-space: nowrap;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.mobile-page .item-badges[b-fj1ldqjbzh] {
    margin-top: var(--space-1);
}
/* /Components/Pages/Home.razor.rz.scp.css */
/* Home page scoped styles. Relies on the global tokens from
   /wwwroot/css/theme.css. */

.home-hero[b-1sivlem6g5] {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(18rem, 1fr);
    gap: 1.25rem;
    align-items: center;
    overflow: hidden;
}

.home-hero__copy[b-1sivlem6g5] {
    min-width: 0;
}

.home-hero__ctas[b-1sivlem6g5] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.65rem;
    margin-top: 1rem;
}

.home-hero__art[b-1sivlem6g5] {
    position: relative;
    display: grid;
    place-items: center;
    padding: 0.25rem;
    /* The shipped splash PNG is roughly 16:9 (about 1.9:1).
       Framing it via aspect-ratio keeps the hero panel a
       consistent shape while Grok / swap-in art may vary
       slightly in output dimensions. */
    aspect-ratio: 16 / 9;
    min-height: 14rem;
    max-height: 22rem;
    border-radius: var(--radius-md);
    overflow: hidden;
    /* Subtle tinted bed behind the image so a PNG with a
       transparent background still reads as a framed focal. */
    background:
        linear-gradient(180deg,
            color-mix(in oklab, var(--brand-sea-soft) 70%, var(--surface)) 0%,
            var(--surface) 100%);
    box-shadow: inset 0 0 0 1px var(--border);
}

.home-hero__art picture[b-1sivlem6g5],
.home-hero__art picture img[b-1sivlem6g5],
.home-hero__art > img[b-1sivlem6g5] {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
    object-position: 50% 42%;
    /* Soft halo around the whole image so it feels lifted off
       the card; the inner glow in the artwork itself handles
       the rest. */
    filter: drop-shadow(0 18px 34px color-mix(in oklab, var(--brand-sea) 22%, transparent));
}

/* Collapse to single column on small screens — art goes
   underneath the copy so the call-to-action stays above the
   fold. */
@media (max-width: 1024px) {
    .home-hero[b-1sivlem6g5] {
        grid-template-columns: 1fr;
    }
    .home-hero__art[b-1sivlem6g5] {
        order: 2;
    }
    .home-hero__copy[b-1sivlem6g5] {
        order: 1;
    }
}
/* /Components/Shared/AppToast.razor.rz.scp.css */
/* PBI #15271 — app-wide toast. Style ported from BidMobile's
   page-scoped .toast (the only auto-dismissing surface in the app
   before this work item) so the visual feel is preserved during
   the rollout. Tokens drive every color; no hard-coded hex. */

.app-toast[b-j9zlxaycx6] {
    position: fixed;
    /* #15697: App.razor sets viewport-fit=cover, which extends the layout
       viewport under the home indicator (34px iPhone / 21px iPad). A bare
       var(--space-4) put the toast partly behind it. Additive, not
       max(): the 16px gap belongs ABOVE the indicator, not merely the
       larger of the two. --safe-b is 0 on desktop, so this is a no-op
       everywhere the inset does not exist. */
    bottom: calc(var(--space-4) + var(--safe-b));
    left: 50%;
    transform: translateX(-50%);
    background: var(--text);
    color: var(--text-inverse);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-xs);
    opacity: 0.95;
    z-index: var(--z-toast);
    box-shadow: var(--shadow-sm);
    max-width: min(90vw, 28rem);
    text-align: center;
}

.app-toast.error[b-j9zlxaycx6] {
    background: var(--status-danger);
    color: #fff;
}
