@import '_content/ChorePoints.UI/ChorePoints.UI.0z5r5gukjv.bundle.scp.css';

/* /Components/Layout/MainLayout.razor.rz.scp.css */
.page[b-739djkm78g] {
    position: relative;
    display: flex;
    flex-direction: column;
    /* Fill the window even when the content doesn't. main is a stretched flex item of
       .page, so this is what lets main paint a backdrop that reaches the bottom of the
       browser instead of stopping where the content stops -- see the page tint on main
       below and Documentation/23-Page-Backdrop.md. dvh rather than vh so a phone's
       collapsing address bar doesn't uncover a strip of body underneath. */
    min-height: 100vh;
    min-height: 100dvh;
}

main[b-739djkm78g] {
    flex: 1;
    /* A flex item won't shrink below its content's width by default, and the no-wrap
       profile-cards row made main wider than the window, pushing the right edge of
       every page off-screen. Letting it shrink makes that row scroll inside itself. */
    min-width: 0;
    /* The page backdrop, for every page rather than just the chore list. It is painted
       here, on <main>, rather than on the <article> that actually holds @Body, because
       <main> is already a stretched flex item of .page (min-height: 100dvh) and so
       reaches the bottom of the window even when a page's content stops a third of the
       way down; <article> is only as tall as what is in it. The profile cards bar is
       inside <main> too and keeps its own background, so the tint starts below it.
       Colour from wwwroot/app.css -- see Documentation/23-Page-Backdrop.md. */
    background-color: var(--brand-page-bg);
}

.sidebar[b-739djkm78g] {
    /* The brand gradient, defined once in wwwroot/app.css. It replaced the Blazor
       template's navy-to-aubergine gradient -- see Documentation/24-Brand-Color.md. */
    background-image: var(--brand-nav-gradient);
}

.top-row[b-739djkm78g] {
    background-color: #f7f7f7;
    border-bottom: 1px solid #d6d5d5;
    justify-content: flex-end;
    height: 3.5rem;
    display: flex;
    align-items: center;
}

.profile-cards-bar[b-739djkm78g] {
    display: flex;
    align-items: center;
    padding-top: 1rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--brand-primary);
    /* The brand stripes, defined once in wwwroot/app.css. They are painted here rather
       than inside ProfileCards because this wrapper is what spans the bar edge to edge:
       the component's own root sits inside this element's px-4, so painting there would
       leave a plain gutter down each side. It is the same reason the page tint
       lives on <main> -- see Documentation/23-Page-Backdrop.md and 40. The flat
       colour underneath is what a browser without color-mix() falls back to. */
    background-color: #f7f7f7;
    background-image: var(--brand-stripes);
}

    .top-row[b-739djkm78g]  a, .top-row[b-739djkm78g]  .btn-link {
        white-space: nowrap;
        margin-left: 1.5rem;
        text-decoration: none;
    }

    .top-row[b-739djkm78g]  a:hover, .top-row[b-739djkm78g]  .btn-link:hover {
        text-decoration: underline;
    }

    .top-row[b-739djkm78g]  a:first-child {
        overflow: hidden;
        text-overflow: ellipsis;
    }

/* The hamburger layout: a narrow screen, OR a short one. A phone held sideways is
   wider than 641px and shorter than its own nav list, so width alone put it in the
   sidebar layout and clipped half the menu. The pair below is the exact complement of
   the sidebar query, so every screen gets one layout and only one.
   See Documentation/79-Navigation-on-a-Short-Screen.md. */
@media (max-width: 640.98px), (max-height: 499.98px) {
    .top-row[b-739djkm78g] {
        justify-content: space-between;
    }

    .top-row[b-739djkm78g]  a, .top-row[b-739djkm78g]  .btn-link {
        margin-left: 0;
    }

    .profile-cards-bar[b-739djkm78g] {
        padding-top: 0.5rem;
        padding-bottom: 0.5rem;
        padding-left: 0.75rem !important;
        padding-right: 0.75rem !important;
    }
}

@media (min-width: 641px) and (min-height: 500px) {
    .page[b-739djkm78g] {
        flex-direction: row;
    }

    .sidebar[b-739djkm78g] {
        width: 250px;
        height: 100dvh;
        position: sticky;
        top: 0;
    }

    .top-row[b-739djkm78g] {
        position: sticky;
        top: 0;
        z-index: 1;
    }

    .top-row.auth[b-739djkm78g]  a:first-child {
        flex: 1;
        text-align: right;
        width: 0;
    }

    .top-row[b-739djkm78g], article[b-739djkm78g] {
        padding-left: 2rem !important;
        padding-right: 1.5rem !important;
    }
}

#blazor-error-ui[b-739djkm78g] {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss[b-739djkm78g] {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
/* /Components/Layout/NavMenu.razor.rz.scp.css */
.navbar-toggler[b-rg61plsfb0] {
    appearance: none;
    cursor: pointer;
    width: 3.5rem;
    height: 2.5rem;
    color: white;
    position: absolute;
    top: 0.5rem;
    right: 1rem;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
}

.navbar-toggler:checked[b-rg61plsfb0] {
    background-color: rgba(255, 255, 255, 0.5);
}

.top-row[b-rg61plsfb0] {
    min-height: 3.5rem;
    background-color: rgba(0,0,0,0.4);
}

.navbar-brand[b-rg61plsfb0] {
    font-size: 1.1rem;
    /* The brand gives way rather than pushing the quick links off the bar. */
    min-width: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    gap: 0.45rem;
}

/* The mark takes its colour from the brand link, so it stays in step with whatever the
   navbar text is: currentColor in the SVG, nothing to keep in sync here.
   See Documentation/27-Logo-and-Favicon.md.

   ::deep because the mark is a child component's markup since doc 60 moved it into the
   shared library. Without it the selector matches nothing, the SVG falls back to its
   intrinsic size, and the name beside it collapses to "Ch...". */
.navbar-brand[b-rg61plsfb0]  .brand-mark {
    width: 1.6rem;
    height: 1.6rem;
    /* The name is what gives way when the bar is tight; the mark never shrinks. */
    flex-shrink: 0;
}

/* The ellipsis moved off .navbar-brand and onto the name, because the flex row now has
   two children and only one of them should be truncated. */
.brand-name[b-rg61plsfb0] {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The Chores and Rewards links that stay on the top bar while the rest of the nav is
   collapsed behind the hamburger. The bar is the navbar's own flex row, so on a phone
   these drop onto a second line under the brand and on a wider small screen they sit
   beside it -- either way they are on screen. The toggler is absolutely positioned over
   the right end of the row, so the margin keeps the links out from under it.
   See Documentation/25-Always-Visible-Nav-Links.md. */
.quick-links[b-rg61plsfb0] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-right: 4rem;
    /* Both labels stay whole; it is the brand that absorbs a squeeze. */
    flex-shrink: 0;
}

    /* Sized for a thumb, not a mouse: these links only exist where the nav is
       collapsed -- a narrow screen, or a short one, both of them a phone -- so there
       is no desktop case to keep small. The
       0.9rem/0.35rem pair they had measured about 32px tall, well under the ~44px a
       touch target wants. See Documentation/76-Bigger-Touch-Targets-on-Small-Screens.md. */
    .quick-links[b-rg61plsfb0]  .nav-link {
        color: #fff;
        font-size: 1rem;
        padding: 0.55rem 0.8rem;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        border-radius: 6px;
        white-space: nowrap;
    }

    .quick-links[b-rg61plsfb0]  a.active {
        background-color: rgba(255,255,255,0.37);
    }

    .quick-links[b-rg61plsfb0]  .nav-link:hover {
        background-color: rgba(255,255,255,0.1);
    }

.bi[b-rg61plsfb0] {
    display: inline-block;
    position: relative;
    width: 1.25rem;
    height: 1.25rem;
    margin-right: 0.75rem;
    top: -1px;
    background-size: cover;
}

.bi-house-door-fill-nav-menu[b-rg61plsfb0] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
}

.bi-plus-square-fill-nav-menu[b-rg61plsfb0] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
}

.bi-list-nested-nav-menu[b-rg61plsfb0] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
}

.nav-item[b-rg61plsfb0] {
    font-size: 0.9rem;
    padding-bottom: 0.5rem;
}

    .nav-item:first-of-type[b-rg61plsfb0] {
        padding-top: 1rem;
    }

    .nav-item:last-of-type[b-rg61plsfb0] {
        padding-bottom: 1rem;
    }

    .nav-item[b-rg61plsfb0]  .nav-link {
        /* White, not the template's #d7d7d7. The brand gradient is much lighter than the
           navy it replaced, and grey-on-lavender fell to about 2.6:1 -- see
           Documentation/24-Brand-Color.md. */
        color: #fff;
        background: none;
        border: none;
        border-radius: 4px;
        height: 3rem;
        display: flex;
        align-items: center;
        line-height: 3rem;
        width: 100%;
    }

.nav-item[b-rg61plsfb0]  a.active {
    background-color: rgba(255,255,255,0.37);
    color: white;
}

.nav-item[b-rg61plsfb0]  .nav-link:hover {
    background-color: rgba(255,255,255,0.1);
    color: white;
}

.nav-scrollable[b-rg61plsfb0] {
    display: none;
}

.navbar-toggler:checked ~ .nav-scrollable[b-rg61plsfb0] {
    display: block;
}

/* Bootstrap's .nav is a wrapping flex container, and `flex-column` only changes its
   direction -- so when the sidebar is shorter than its list, the items that don't fit
   wrap into a SECOND COLUMN instead of overflowing downwards. That column sits past
   the sidebar's 250px and is simply clipped, which is why Your Account and Logout were
   cut in half on a landscape phone, and why the `overflow-y: auto` below never caught
   it: wrapping had already made the content "fit". Turning the wrap off is what lets
   the sidebar scroll. See Documentation/79-Navigation-on-a-Short-Screen.md. */
.nav-scrollable .nav[b-rg61plsfb0] {
    flex-wrap: nowrap;
}

/* --- The compact bar on a narrow screen -------------------------------------------
   Below 641px the two quick links wrapped onto a second line under the wordmark, which
   cost the bar half its height again on exactly the screens with the least of it. The
   name stacks instead -- "Chore" over "Points" -- which is narrow enough that both links
   fit beside it on one row.

   Width only, deliberately, and NOT the (max-height) half of the hamburger query that
   doc 79 added. A phone held sideways is short, not narrow: the one-line wordmark
   already fits beside the links there, and stacking it would make the bar taller on the
   screen with the least height to spare.
   See Documentation/102-Compact-Nav-on-Small-Screens.md. */
@media (max-width: 640.98px) {
    /* The gutter the wordmark no longer needs. ps-3 is a Bootstrap utility and carries
       !important, so this has to as well. Together with the container's own padding
       below it leaves a 0.75rem gutter -- the same one the profile cards bar underneath
       already uses, so the two line up down the left edge. */
    .top-row[b-rg61plsfb0] {
        padding-left: 0.25rem !important;
    }

    /* The hamburger keeps the 44px touch target doc 76 asked for and gives up the
       0.75rem of air around it, which is 20px the row can spend on the links instead.
       Sitting closer to the edge also widens the gap between it and Rewards, which is
       the gap a thumb has to not miss. */
    .navbar-toggler[b-rg61plsfb0] {
        width: 2.75rem;
        right: 0.5rem;
    }

    .top-row .container-fluid[b-rg61plsfb0] {
        padding-left: 0.5rem;
        /* Everything packs to the left: the links sit against the wordmark rather than
           against the right edge, which is what keeps a thumb aimed at Rewards away from
           the menu button. The padding covers the toggler's footprint above (2.75rem
           wide, 0.5rem in from the edge), reserved here so that a squeeze ellipsises the
           name rather than sliding the links under it. */
        justify-content: flex-start;
        flex-wrap: nowrap;
        padding-right: 3.5rem;
    }

    .navbar-brand[b-rg61plsfb0] {
        gap: 0.35rem;
    }

    /* Tall enough to stand beside both stacked lines rather than beside one of them:
       two lines of 1.1rem. */
    .navbar-brand[b-rg61plsfb0]  .brand-mark {
        width: 2.2rem;
        height: 2.2rem;
    }

    .brand-name[b-rg61plsfb0] {
        display: flex;
        flex-direction: column;
        line-height: 1.1rem;
    }

    /* The ellipsis moves down a level with the stacking: .brand-name is the column now,
       so it is each word that has to be able to give. */
    .brand-word[b-rg61plsfb0] {
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .quick-links[b-rg61plsfb0] {
        /* The 4rem that held the links clear of the toggler is the container's padding
           now, because the links no longer run to the right edge. */
        margin-right: 0;
        gap: 0.2rem;
    }

        /* The row only balances if the links give a little back. Measured at 360px: the
           mark, the stacked name and the two links at their doc 76 sizing come to 317px
           against 264px of free bar, so the brand was squeezed to nothing and the name
           disappeared entirely. Trimming the side padding and a twentieth off the type
           brings the pair to 182px, and with the gutter the reclaimed row measures 282px
           against 296px of bar -- the name renders whole at 360, 390 and 430. The 44px
           minimum height that doc 76 is actually about is untouched, and each link is
           still some 80px wide -- a thumb's worth either way. */
        .quick-links[b-rg61plsfb0]  .nav-link {
            font-size: 0.95rem;
            padding-left: 0.3rem;
            padding-right: 0.3rem;
        }
}

/* The sidebar needs a screen that is both wide enough for a 250px column and TALL
   enough for the list in it -- about 500px, which every laptop clears and no phone
   held sideways does. Below either, the hamburger layout is used instead. The height
   half of this pair is the fix for the clipped second column; the nowrap rule above
   covers the squeeze that is left. */
@media (min-width: 641px) and (min-height: 500px) {
    .navbar-toggler[b-rg61plsfb0] {
        display: none;
    }

    /* The sidebar is open at this width, so the same two links are already in it. */
    .quick-links[b-rg61plsfb0] {
        display: none;
    }

    .nav-scrollable[b-rg61plsfb0] {
        /* Never collapse the sidebar for wide screens */
        display: block;

        /* Allow sidebar to scroll for tall menus. dvh rather than vh for the same
           reason .page uses it -- a phone's collapsing address bar. */
        height: calc(100dvh - 3.5rem);
        overflow-y: auto;
    }
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-mzcemie4t6],
.components-reconnect-repeated-attempt-visible[b-mzcemie4t6],
.components-reconnect-failed-visible[b-mzcemie4t6],
.components-pause-visible[b-mzcemie4t6],
.components-resume-failed-visible[b-mzcemie4t6],
.components-rejoining-animation[b-mzcemie4t6] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-mzcemie4t6],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-mzcemie4t6],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-mzcemie4t6],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-mzcemie4t6],
#components-reconnect-modal.components-reconnect-retrying[b-mzcemie4t6],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-mzcemie4t6],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-mzcemie4t6],
#components-reconnect-modal.components-reconnect-failed[b-mzcemie4t6],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-mzcemie4t6] {
    display: block;
}


#components-reconnect-modal[b-mzcemie4t6] {
    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-mzcemie4t6 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-mzcemie4t6 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-mzcemie4t6 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-mzcemie4t6]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-mzcemie4t6 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-mzcemie4t6 {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-mzcemie4t6 {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-mzcemie4t6 {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-mzcemie4t6] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-mzcemie4t6] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-mzcemie4t6] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-mzcemie4t6] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-mzcemie4t6] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-mzcemie4t6] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-mzcemie4t6] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-mzcemie4t6 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-mzcemie4t6] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-mzcemie4t6 {
    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/Layout/SiteFooter.razor.rz.scp.css */
/* Quiet by design. The footer sits under pages that are making an argument -- the landing page,
   the FAQ -- and it is the last thing that should compete with them. */
.site-footer[b-3zsrhyidoa] {
    margin-top: 3rem;
    padding: 1.5rem 1rem 2rem;
    border-top: 1px solid rgba(0, 0, 0, 0.08);
    text-align: center;
    font-size: 0.875rem;
}

.site-footer-links[b-3zsrhyidoa] {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem 1.5rem;
    margin-bottom: 0.75rem;
}

/* 44px targets, as doc 76 asks of anything thumbed on a phone. The negative margin keeps the
   row visually tight while the hit area stays full size. */
.site-footer-links a[b-3zsrhyidoa] {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 0.25rem;
    color: var(--brand-ink);
    text-decoration: none;
}

.site-footer-links a:hover[b-3zsrhyidoa],
.site-footer-links a:focus-visible[b-3zsrhyidoa] {
    text-decoration: underline;
}

.site-footer-line[b-3zsrhyidoa] {
    color: #6c757d;
}

.site-footer-line a[b-3zsrhyidoa] {
    color: inherit;
}
/* /Components/Pages/Admin/Diagnostics.razor.rz.scp.css */
/* Column widths only once there is room for columns. Below the sm breakpoint the checks
   table stops being a table (see the media query underneath), so fixing a width here
   would fight it. */
@media (min-width: 576px) {
    .checks .check-name[b-ultxxtm814] {
        width: 12rem;
    }

    .checks .check-status[b-ultxxtm814] {
        width: 7rem;
    }

    .facts th[b-ultxxtm814] {
        width: 12rem;
    }
}

/* On a phone a three-column table squeezes the detail -- the column that carries the
   whole point of the page -- into a ribbon two or three words wide. Each row becomes a
   block instead: the check's name and its badge on one line, the detail underneath at
   full width. Same markup, so there is no second copy of the table to keep in step. */
@media (max-width: 575.98px) {
    .checks thead[b-ultxxtm814] {
        display: none;
    }

    .checks tbody tr[b-ultxxtm814] {
        display: block;
        padding: 0.6rem 0.5rem;
        border-bottom: 1px solid var(--bs-border-color);
    }

    .checks tbody td[b-ultxxtm814] {
        display: inline;
        border: 0;
        padding: 0;
    }

    /* Bootstrap stripes the cells, and an inline cell's background is only as tall as its
       text -- which comes out as a ragged highlight behind the words rather than a banded
       row. The border above separates the rows instead.
       Bootstrap 5.3 paints the stripe as an inset box-shadow rather than a background, so
       clearing background-color alone leaves it exactly where it was. */
    .checks > :not(caption) > * > *[b-ultxxtm814] {
        box-shadow: none;
        background-color: transparent;
    }

    .checks tbody td.check-name[b-ultxxtm814] {
        font-weight: 600;
    }

    /* The badge sits beside the name; the detail starts its own line. */
    .checks tbody td.check-status[b-ultxxtm814] {
        margin-left: 0.5rem;
    }

    .checks tbody td.check-status[b-ultxxtm814]::after {
        content: "";
        display: block;
        margin-bottom: 0.35rem;
    }

    .facts th[b-ultxxtm814] {
        width: 9rem;
    }
}
/* /Components/Pages/Admin/Families.razor.rz.scp.css */
/* Notes are the column that carries the point of the page, so they read as sentences
   rather than as a table cell: no bullet, and enough room for the full text. */
.notes[b-1gb4irmryx] {
    list-style: none;
    padding-left: 0;
}

.notes li + li[b-1gb4irmryx] {
    margin-top: 0.35rem;
}

.notes .badge[b-1gb4irmryx] {
    margin-right: 0.35rem;
}

/* At 420px a four-column table squeezes the notes into a ribbon two words wide, so the
   row becomes a block instead -- the same treatment, and the same reason, as the checks
   table on the diagnostics page (doc 45). Same markup, so there is no second copy. */
@media (max-width: 575.98px) {
    .families thead[b-1gb4irmryx] {
        display: none;
    }

    .families[b-1gb4irmryx],
    .families tbody[b-1gb4irmryx],
    .families tr[b-1gb4irmryx],
    .families td[b-1gb4irmryx] {
        display: block;
        width: 100%;
    }

    .families tr[b-1gb4irmryx] {
        border-bottom: 1px solid var(--bs-border-color);
        padding: 0.5rem 0;
    }

    .families td[b-1gb4irmryx] {
        border: 0;
        padding: 0.15rem 0;
    }

    /* Bootstrap 5.3 paints a stripe as an inset box-shadow, not a background colour, so
       clearing the background alone leaves the stripe behind. */
    .families > :not(caption) > * > *[b-1gb4irmryx] {
        box-shadow: none;
        background-color: transparent;
    }
}
/* /Components/Pages/Admin/FamilyDetails.razor.rz.scp.css */
/* The icon and the colour sit together: they are one thing on screen -- how a kid picks
   their own card out of the row -- so they read as one cell here too. */
.look[b-c0af0m9jg9] {
    white-space: nowrap;
}

.look i[b-c0af0m9jg9] {
    font-size: 1.15rem;
    margin-right: 0.4rem;
    vertical-align: middle;
}

.swatch[b-c0af0m9jg9] {
    display: inline-block;
    width: 1.1rem;
    height: 1.1rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm);
    vertical-align: middle;
}
/* /Components/Pages/Admin/FeedbackDetails.razor.rz.scp.css */
/* The message as the sender typed it. <pre> keeps their line breaks, which is the point --
   a bug report with steps in it is unreadable reflowed into one paragraph -- but <pre>'s
   own defaults are for code: no wrapping, and a monospace face that makes ordinary prose
   hard going. So it wraps, and it borrows the page's font. See doc 52. */
.message[b-a96abxw3g9] {
    white-space: pre-wrap;
    word-break: break-word;
    font-family: inherit;
    font-size: 1rem;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    padding: 0.75rem 1rem;
    margin-bottom: 0;
}
/* /Components/Pages/Admin/IconFormModal.razor.rz.scp.css */
/* The icon finder on the New Icon form. See doc 51. */

.icon-preview[b-hb4lp7f5zv] {
    /* Fixed so the box does not resize as icons of different widths are tried, and wide
       enough that a tall glyph is not clipped by the input group's own padding. */
    width: 3rem;
    justify-content: center;
    font-size: 1.25rem;
}

.icon-search[b-hb4lp7f5zv] {
    /* Enough room for a couple of words, and still shares the row with the style buttons
       on a desktop. flex-wrap on the row drops the buttons underneath on a phone. */
    flex: 1 1 16rem;
    min-width: 12rem;
}

.icon-grid[b-hb4lp7f5zv] {
    display: grid;
    /* Fills the width with as many as fit rather than a fixed count, so the same markup
       gives ten across on a desktop and six on a phone. */
    grid-template-columns: repeat(auto-fill, minmax(3rem, 1fr));
    gap: 0.25rem;
    max-height: 16rem;
    overflow-y: auto;
    padding: 0.25rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.375rem;
    background-color: var(--bs-body-bg);
}

.icon-choice[b-hb4lp7f5zv] {
    position: relative;
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    color: var(--bs-body-color);
    background: none;
    border: 1px solid transparent;
    border-radius: 0.375rem;
}

.icon-choice:hover[b-hb4lp7f5zv],
.icon-choice:focus-visible[b-hb4lp7f5zv] {
    border-color: var(--bs-border-color);
    background-color: var(--bs-tertiary-bg);
}

.icon-choice.chosen[b-hb4lp7f5zv] {
    border-color: var(--bs-primary);
    background-color: var(--bs-primary-bg-subtle);
}

/* The marker for an icon the database already has. A dot rather than a tick because it is
   a note, not a state the admin just changed, and it has to read at 8 pixels. */
.icon-choice .added[b-hb4lp7f5zv] {
    position: absolute;
    top: 0.2rem;
    right: 0.2rem;
    width: 0.4rem;
    height: 0.4rem;
    border-radius: 50%;
    background-color: var(--bs-secondary);
}
/* /Components/Pages/Admin/Index.razor.rz.scp.css */
/* The dashboard at /admin. See doc 53. */

/* The five counts. Big enough to read from across a desk, which is the whole point of a
   number on a front page. */
.figures .figure-value[b-5mp5tt1ry6] {
    font-size: 2rem;
    font-weight: 600;
    line-height: 1.1;
}

.figures .figure-label[b-5mp5tt1ry6] {
    color: var(--bs-secondary-color);
    font-size: 0.875rem;
}

/* The activity strip: one column per day, each a bar sitting on a baseline. No chart
   library, because the app has no node build step (CLAUDE.md) and a fortnight of small
   numbers does not need one. */
.strip[b-5mp5tt1ry6] {
    display: flex;
    align-items: flex-end;
    gap: 0.25rem;
    height: 8rem;
}

.strip .day[b-5mp5tt1ry6] {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: stretch;
    height: 100%;
    min-width: 0;
}

.strip .bar[b-5mp5tt1ry6] {
    background-color: var(--brand-primary);
    border-radius: var(--bs-border-radius-sm) var(--bs-border-radius-sm) 0 0;
    /* A day with nothing on it still draws a hairline, so the baseline reads as a row of
       days rather than as empty space where the chart stopped. */
    min-height: 2px;
}

.strip .tick[b-5mp5tt1ry6] {
    color: var(--bs-secondary-color);
    font-size: 0.75rem;
    text-align: center;
    padding-top: 0.25rem;
}

/* Matches the families page, so a list of concerns looks the same wherever it appears. */
.notes[b-5mp5tt1ry6] {
    list-style: none;
    padding-left: 0;
}

.notes li + li[b-5mp5tt1ry6] {
    margin-top: 0.5rem;
}
/* /Components/Pages/Admin/Logs.razor.rz.scp.css */
.log[b-zu1z73op2r] {
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    overflow: hidden;
}

.entry[b-zu1z73op2r] {
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.entry:last-child[b-zu1z73op2r] {
    border-bottom: 0;
}

/* A quiet tint rather than a filled row: a page that is mostly errors should still be
   readable, and a wall of red is not. */
.entry-error[b-zu1z73op2r] {
    background-color: rgba(var(--bs-danger-rgb), 0.06);
}

.entry-warning[b-zu1z73op2r] {
    background-color: rgba(var(--bs-warning-rgb), 0.08);
}

/* Log text is monospaced and pre-wrapped: a stack trace's indentation is what makes it
   readable, and wrapping rather than scrolling sideways keeps that true on a phone. */
.entry pre[b-zu1z73op2r] {
    font-size: 0.8125rem;
    line-height: 1.45;
    white-space: pre-wrap;
    word-break: break-word;
    margin-top: 0.25rem;
}
/* /Components/Pages/Chores/ChoreCard.razor.rz.scp.css */
/* One markup tree, two layouts. The card is a grid and the breakpoint only
   reassigns grid areas, so Blazor renders the same DOM at every width -- no
   second component, and nothing for the drag-and-drop wiring to trip over. */

.chore-card-body[b-anvk83phi1] {
    display: grid;
    grid-template-columns: auto auto 1fr auto auto;
    grid-template-areas:
        "check  icon   title  points menu"
        "check  icon   detail detail detail"
        "handle handle handle handle handle";
    column-gap: 1rem;
    row-gap: 0.25rem;
    align-items: center;
}

/* The drag handle gets a thin row of its own, centred under the card. On the
   trailing edge it sat directly beneath the actions menu, and a column of grip
   dots under a column of ellipsis dots read as the same control twice. The
   horizontal fa-grip-lines shape is distinct from the menu and reads as a pull
   tab.

   The target is kept compact on purpose rather than spanning the full row:
   touch-action:none means a swipe starting on the handle drags instead of
   scrolling, so a full-width strip on every card would make the list hard to
   scroll on a phone. Wide horizontal padding gives a comfortable target without
   adding height. The negative margins pull the row into the card's own bottom
   padding so it costs as little vertical space as possible. */
.chore-drag-handle[b-anvk83phi1] {
    grid-area: handle;
    justify-self: center;
    align-self: center;
    margin-top: -0.25rem;
    margin-bottom: -0.625rem;
    padding: 0.125rem 1.5rem;
    color: var(--bs-secondary-color, #6c757d);
    opacity: 0.6;
    cursor: grab;
    line-height: 1;
    touch-action: none;
}

.chore-drag-handle:hover[b-anvk83phi1],
.chore-drag-handle:active[b-anvk83phi1] {
    opacity: 1;
}

.chore-drag-handle:active[b-anvk83phi1] {
    cursor: grabbing;
}

.chore-claim-check[b-anvk83phi1] {
    grid-area: check;
    /* Deliberately larger than Bootstrap's default: this is the primary action on
       the card, and the old 1.5rem box was well under a comfortable tap target. */
    width: 2rem;
    height: 2rem;
    margin: 0;
    cursor: pointer;
    /* Bootstrap's default border (#dee2e6) is about 1.3:1 against the white card,
       under the 3:1 WCAG asks of a control's outline, so the box barely read as
       tappable. gray-600 at 2px measures 4.69:1. */
    border: 2px solid var(--bs-gray-600, #6c757d);
}

/* A faded tick inside the empty box, hinting at what tapping it does.

   It is set through Bootstrap's own --bs-form-check-bg-image variable and only
   while unchecked, so the real checked state (blue fill, white tick) is untouched.

   TICK STRENGTH is the stroke-opacity in the SVG below -- currently .2, chosen to
   start subtle while gathering feedback. .35 is the next step up: clearly visible
   but still distinct from the solid blue checked box. Much past .5 starts to read
   as already done. */
.chore-claim-check:not(:checked)[b-anvk83phi1] {
    --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%236c757d' stroke-opacity='.2' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e");
}

/* The gray border above would otherwise win over Bootstrap's :checked border,
   since this stylesheet loads after Bootstrap. */
.chore-claim-check:checked[b-anvk83phi1] {
    border-color: var(--bs-primary);
}

.chore-icon[b-anvk83phi1] {
    grid-area: icon;
    font-size: 2.5rem;
    line-height: 1;
}

.chore-title[b-anvk83phi1] {
    grid-area: title;
}

.chore-points[b-anvk83phi1] {
    grid-area: points;
    justify-self: end;
    align-self: center;
}

.chore-menu[b-anvk83phi1] {
    grid-area: menu;
}

/* Blazor renders this menu itself with .show, so Bootstrap's JS never runs and never
   stamps [data-bs-popper] on it -- which is what .dropdown-menu-start/-end are keyed
   on, leaving both classes inert. Without this the menu takes .dropdown-menu's default
   left:0 and runs off the trailing edge of the screen, since the button is already
   there. Pin it so it opens leftward and stays visible. */
.chore-menu .dropdown-menu[b-anvk83phi1] {
    right: 0;
    left: auto;
}

.chore-detail[b-anvk83phi1] {
    grid-area: detail;
    min-width: 0;
}

/* The .chore-notes-toggle rules moved to wwwroot/app.css when the add/edit form grew the
   same toggle: scoped CSS is per component, and a second copy of a look is how two things
   that should match drift apart. See doc 78. */

/* --- Narrow screens -------------------------------------------------------
   The title moves to its own full-width row, which is the whole point: in the
   single-row layout it was left with roughly 90px and wrapped to three lines.
   The icon shrinks rather than disappearing -- it is what makes a chore
   recognisable to a child who cannot read the name yet. */
@media (max-width: 575.98px) {
    .chore-card-body[b-anvk83phi1] {
        /* The icon leads the title so the two read as one unit -- for a child who
           cannot read the name yet, the icon *is* the label. */
        grid-template-columns: auto 1fr auto auto;
        grid-template-areas:
            "icon   title  points menu"
            "check  detail detail detail"
            "handle handle handle handle";
        column-gap: 0.5rem;
        row-gap: 0.5rem;
        align-items: start;
    }

    .chore-claim-check[b-anvk83phi1] {
        width: 2.5rem;
        height: 2.5rem;
    }

    .chore-icon[b-anvk83phi1] {
        font-size: 1.75rem;
    }

    .chore-icon[b-anvk83phi1],
    .chore-claim-check[b-anvk83phi1] {
        align-self: center;
    }

    .chore-points[b-anvk83phi1],
    .chore-menu[b-anvk83phi1] {
        align-self: start;
    }
}

/* The actions menu is one glyph in a btn-sm, which comes out around 28px wide -- the
   smallest target on the card, and the one a parent reaches for to snooze or delete.
   Grown on small screens only, where the pointer is a thumb; the wider layout keeps the
   compact button so the title row stays tight. The glyph grows with the box, because a
   44px box around a 14px ellipsis still looks untappable.
   See Documentation/76-Bigger-Touch-Targets-on-Small-Screens.md. */
@media (max-width: 640.98px) {
    .chore-menu-toggle[b-anvk83phi1] {
        --bs-btn-padding-y: 0.25rem;
        --bs-btn-padding-x: 0.5rem;
        min-width: 44px;
        min-height: 44px;
        font-size: 1.3rem;
        line-height: 1;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
}

/* Dragging is off under every sort but the family's own. The handle keeps its space so
   the card doesn't change height when the sort changes, but stops inviting the gesture:
   no grab cursor, and faded enough to read as unavailable rather than merely decorative.
   touch-action goes back to the default so a swipe here scrolls the page again. */
.chore-drag-handle-off[b-anvk83phi1],
.chore-drag-handle-off:hover[b-anvk83phi1],
.chore-drag-handle-off:active[b-anvk83phi1] {
    opacity: 0.3;
    cursor: default;
    touch-action: auto;
}
/* /Components/Pages/Chores/ChoreList.razor.rz.scp.css */
/* SortableJS applies these to the drag wrapper, which this component owns.
   They cannot live in ChoreCard.razor.css -- the wrapper carries ChoreList's
   scope attribute, so rules scoped to ChoreCard would never match it. */

.chore-sort-ghost[b-0a5m9mj08l] {
    opacity: 0.4;
}

.chore-sort-chosen[b-0a5m9mj08l] {
    cursor: grabbing;
}

/* btn-sm is the right size for a mouse and too small for a thumb: about 31px tall. The
   variables are overridden rather than the class dropped, so the button keeps btn-sm on a
   wide screen where the heading row is tighter for it. The controls row's own version of
   this rule moved into ChoreControls with it (doc 109).
   See Documentation/76-Bigger-Touch-Targets-on-Small-Screens.md. */
@media (max-width: 640.98px) {
    .chore-add[b-0a5m9mj08l] {
        --bs-btn-padding-y: 0.55rem;
        --bs-btn-padding-x: 1rem;
        --bs-btn-font-size: 1rem;
        min-height: 44px;
    }
}

.chore-sort-hint[b-0a5m9mj08l] {
    margin-top: -0.5rem;
}

/* A snoozed chore is deliberately quieter than a live one: it is parked, not waiting to be
   done. Enough contrast to read, not enough to compete with the list above it. */
.chore-snoozed-card[b-0a5m9mj08l] {
    opacity: 0.75;
}

.chore-snoozed-card:hover[b-0a5m9mj08l] {
    opacity: 1;
}

/* Pinned to the bottom of the window (doc 95). The toggle used to sit at the true end of
   the page, which on a family's full list meant scrolling past every chore to find the
   extras -- and scrolling back up afterwards. Sticky rather than fixed so it still belongs
   to the page: it gives up its place and lands back at the end of the list once the page is
   scrolled all the way down, which is also what keeps it from covering the last chore card.

   The opaque backdrop is not decoration. The list scrolls underneath the pinned strip, so
   without the page's own colour the cards read straight through it. The colour is the one
   <main> paints (doc 23), because that is what the strip is standing in front of. */
.chore-extras[b-0a5m9mj08l] {
    position: sticky;
    /* bottom rather than top: a bottom-pinned sticky element only lifts off the page once
       its own place is below the fold, which is exactly when the list is long enough to
       have hidden it. A short list never pins anything. */
    bottom: 0;
    /* Above the cards, far below Bootstrap's dropdown (1000) and modal (1055) layers, so a
       chore card's open menu still draws over the strip rather than behind it. */
    z-index: 2;
    background-color: var(--brand-page-bg);
    padding-bottom: 0.5rem;
    /* A soft lift so the pinned strip reads as standing in front of the list rather than
       cutting a card in half. It costs nothing at rest, where there is nothing behind it. */
    box-shadow: 0 -0.5rem 0.75rem -0.5rem rgba(0, 0, 0, 0.18);
}

/* The Extra chores section's header is its own toggle (doc 89): a full-width row that reads as
   a heading, not a button, so it sits under the list as a place rather than another control.
   44px tall so a thumb finds it on a phone, the same floor doc 76 set for the other targets. */
.chore-extras-heading[b-0a5m9mj08l] {
    font-size: 1rem;
}

/* Open, the cards fill the bottom of the window above the toggle. The cap is what stops a
   family with a dozen extras from pinning a panel taller than the window, whose top would
   then sit above the viewport with no way to scroll to it; under the cap nothing scrolls
   here at all, which is the common case and keeps a card's menu out of a clipping
   container. */
.chore-extras-body[b-0a5m9mj08l] {
    max-height: 50dvh;
    overflow-y: auto;
}

/* Extra chores and Snoozed share the bar half and half (doc 107). A flex row whose children
   all grow from a zero basis, so two halves are exactly equal whatever their labels say and a
   lone one takes the whole bar. They stay side by side on a phone: each is an icon, a short
   name and a count, which fit in half of a 360px screen. */
.chore-shelf-toggles[b-0a5m9mj08l] {
    display: flex;
    gap: 0.5rem;
}

.chore-shelf-toggles > .chore-extras-toggle[b-0a5m9mj08l] {
    flex: 1 1 0;
    min-width: 0;
}

.chore-shelf-name[b-0a5m9mj08l] {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chore-shelf-icon[b-0a5m9mj08l] {
    color: var(--brand-primary-deep);
}

/* At half of a phone's width the icon is what gives way, so "Extra chores" keeps its whole
   name: the chevron and the count still frame each half, and the names say the rest. */
@media (max-width: 640.98px) {
    .chore-shelf-toggles > .chore-extras-toggle[b-0a5m9mj08l] {
        gap: 0.4rem;
        padding-left: 0.6rem;
        padding-right: 0.6rem;
    }

    .chore-shelf-icon[b-0a5m9mj08l] {
        display: none;
    }
}

/* The open half reads as pressed: white, with the brand's edge, so it is plain which list
   the body under the bar belongs to. */
.chore-extras-toggle.open[b-0a5m9mj08l] {
    background-color: #fff;
    border-color: var(--brand-primary-deep);
}

.chore-extras-toggle[b-0a5m9mj08l] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    min-height: 44px;
    padding: 0.5rem 0.75rem;
    text-align: start;
    font-weight: 600;
    color: var(--brand-ink);
    background-color: rgba(255, 255, 255, 0.6);
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: var(--bs-border-radius);
}

.chore-extras-toggle:hover[b-0a5m9mj08l],
.chore-extras-toggle:focus-visible[b-0a5m9mj08l] {
    background-color: #fff;
    color: var(--brand-ink);
}

.chore-extras-chevron[b-0a5m9mj08l] {
    width: 1rem;
    color: var(--brand-primary-deep);
}
/* /Components/Pages/Chores/ChoreModal.razor.rz.scp.css */
/* The name box is a textarea that auto-grow.js resizes a line at a time, so it must not
   show the scrollbar it would otherwise flash while growing, and the drag handle has
   nothing to do once the height follows the text.

   ::deep because the <textarea> is rendered by InputTextArea rather than by this file, so
   it never carries this component's scope attribute of its own. See doc 78. */
[b-4qp38fewgj] textarea.chore-name {
    resize: none;
    overflow-y: hidden;
}

/* The days-of-the-week button group (doc 88). The seven days share the row equally so the
   group fits a phone without wrapping: a wrapped .btn-group loses the joined corners that
   make it read as one control, and the three-letter labels alone would leave Wed wider than
   Fri. Capped on a wide screen, where modal-lg would otherwise stretch one week across
   770px. */
.weekday-group[b-4qp38fewgj] {
    width: 100%;
    max-width: 30rem;
}

.weekday-group .btn[b-4qp38fewgj] {
    flex: 1 1 0;
    padding-inline: 0.25rem;
}

/* Finger-sized on a phone, the same 44px the other small-screen controls got in doc 76, and
   the app's general small-screen breakpoint. Bootstrap's own --bs-btn-* variables rather
   than padding properties, so a later global button rule can still win (doc 77). */
@media (max-width: 640.98px) {
    .weekday-group .btn[b-4qp38fewgj] {
        --bs-btn-padding-y: 0.6rem;
        --bs-btn-font-size: 0.9rem;
        min-height: 44px;
    }
}
/* /Components/Pages/Faqs.razor.rz.scp.css */
/* The answer is author-written HTML, so it arrives with its own headings, lists and tables
   and none of the Bootstrap classes the rest of the app hands out. These rules are what
   keep it looking like the app instead of like a raw document.

   They need ::deep. CSS isolation puts its attribute on the elements this component
   renders, and the elements inside an answer are not among them -- they come out of a
   MarkupString at runtime, long after the build wrote the attributes. ::deep moves the
   attribute onto .faq-answer, which this component does render, and leaves the rest of the
   selector to match normally. */

.faq-jump[b-1x4dshgzix] {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

.faq-heading[b-1x4dshgzix] {
    color: var(--brand-primary-dark);
    /* The jump links are same-page anchors, so the heading they land on would otherwise sit
       hard against the top of the window. */
    scroll-margin-top: 1rem;
}

.faq-answer[b-1x4dshgzix]  > :last-child {
    margin-bottom: 0;
}

.faq-answer[b-1x4dshgzix]  h2,
.faq-answer[b-1x4dshgzix]  h3,
.faq-answer[b-1x4dshgzix]  h4,
.faq-answer[b-1x4dshgzix]  h5,
.faq-answer[b-1x4dshgzix]  h6 {
    font-size: 1.05rem;
    font-weight: 600;
    margin-top: 1rem;
}

.faq-answer[b-1x4dshgzix]  a {
    color: var(--brand-primary-dark);
}

.faq-answer[b-1x4dshgzix]  table {
    width: 100%;
    margin-bottom: 1rem;
}

.faq-answer[b-1x4dshgzix]  th,
.faq-answer[b-1x4dshgzix]  td {
    border: 1px solid var(--bs-border-color);
    padding: .4rem .6rem;
}

.faq-answer[b-1x4dshgzix]  pre {
    background: var(--bs-secondary-bg);
    padding: .75rem;
    border-radius: .375rem;
    overflow-x: auto;
}

.faq-answer[b-1x4dshgzix]  blockquote {
    border-left: 3px solid var(--brand-primary);
    padding-left: .75rem;
    color: var(--bs-secondary-color);
}
/* /Components/Pages/Home.razor.rz.scp.css */
/* Landing page styling and motion.

   Scoped to Home.razor, so none of it can leak onto a signed-in page. Colours are derived
   from the brand tokens in wwwroot/app.css rather than written out again: --brand-primary
   and --brand-ink are declared on :root, and scoped CSS only rewrites selectors -- it does
   not isolate the cascade -- so the custom properties reach these rules.

   The hero gradient is a long way darker than the nav gradient on purpose. White text on
   --brand-primary manages about 3.7:1, short of AA; mixing the brand purple down towards
   --brand-ink lands both ends of this gradient past 6:1 while still reading as the brand
   colour. See Documentation/24-Brand-Color.md and Documentation/39-Landing-Page.md.

   The @keyframes below are rewritten too: the build appends the same scope id to the
   animation's name and to every reference to it, so "cp-rise" in Web.styles.css is really
   cp-rise-b-<id> and cannot collide with a rule in another component. */

.landing[b-l0gfn74exd] {
    --shot-radius: 0.9rem;
    --shot-shadow: 0 1.25rem 2.5rem rgba(43, 36, 56, 0.18);
    max-width: 68rem;
    margin: 0 auto;
    padding-bottom: 3rem;
}

/* ---------- hero ---------- */

.hero[b-l0gfn74exd] {
    position: relative;
    overflow: hidden;
    border-radius: 1.5rem;
    padding: 3rem 2.5rem;
    margin-bottom: 4rem;
    color: #fff;
    background-image: linear-gradient(135deg,
        color-mix(in srgb, var(--brand-primary) 62%, var(--brand-ink)) 0%,
        color-mix(in srgb, var(--brand-primary) 38%, var(--brand-ink)) 100%);
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 2.5rem;
    align-items: center;
}

/* A soft highlight in the top-left corner, so the panel reads as lit rather than as a flat
   fill. Sits under everything: the children below all establish their own stacking. */
.hero[b-l0gfn74exd]::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: radial-gradient(60rem 30rem at 12% -10%, rgba(255, 255, 255, 0.22), transparent 60%);
    pointer-events: none;
}

.hero-copy[b-l0gfn74exd],
.hero-shot[b-l0gfn74exd] {
    position: relative;
}

.hero h1[b-l0gfn74exd] {
    font-size: clamp(2.1rem, 5.5vw, 3.25rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.08;
    margin: 0 0 1rem;
}

.hero-lead[b-l0gfn74exd] {
    font-size: clamp(1.1rem, 2.2vw, 1.4rem);
    margin: 0 0 1.25rem;
    color: rgba(255, 255, 255, 0.92);
}

.hero-list[b-l0gfn74exd] {
    list-style: none;
    margin: 0 0 2rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    font-size: 1.05rem;
}

/* A check in a disc rather than a bullet, to echo the mark in the logo. The icon is
   aria-hidden in the markup, so the list still reads as three plain items. */
.hero-list li[b-l0gfn74exd] {
    position: relative;
    padding-left: 2rem;
    color: rgba(255, 255, 255, 0.94);
}

.hero-list li i[b-l0gfn74exd] {
    position: absolute;
    left: 0;
    top: 0.1em;
    font-size: 0.7em;
    width: 1.45rem;
    height: 1.45rem;
    line-height: 1.45rem;
    text-align: center;
    border-radius: 50%;
    background-color: rgba(255, 255, 255, 0.18);
}

/* The two drifting marks behind the copy. Large, very low contrast, and clipped by the
   panel's overflow: hidden -- they are texture, not illustration. */
.hero-star[b-l0gfn74exd] {
    position: absolute;
    color: #fff;
    opacity: 0.09;
    pointer-events: none;
}

.hero-star-a[b-l0gfn74exd] {
    width: 13rem;
    height: 13rem;
    top: -3rem;
    right: -2.5rem;
}

.hero-star-b[b-l0gfn74exd] {
    width: 7rem;
    height: 7rem;
    bottom: -2rem;
    left: -1.5rem;
    opacity: 0.07;
}

/* ---------- calls to action ---------- */

.hero-actions[b-l0gfn74exd] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

.cta[b-l0gfn74exd] {
    display: inline-block;
    padding: 0.7rem 1.5rem;
    border-radius: 999px;
    font-weight: 700;
    text-decoration: none;
    transition: transform 0.18s ease, box-shadow 0.18s ease, background-color 0.18s ease;
}

.cta-solid[b-l0gfn74exd] {
    background-color: #fff;
    color: var(--brand-ink);
    box-shadow: 0 0.5rem 1.25rem rgba(43, 36, 56, 0.28);
}

.cta-ghost[b-l0gfn74exd] {
    color: #fff;
    border: 2px solid rgba(255, 255, 255, 0.6);
    padding: calc(0.7rem - 2px) calc(1.5rem - 2px);
}

.cta:hover[b-l0gfn74exd],
.cta:focus-visible[b-l0gfn74exd] {
    transform: translateY(-2px);
    text-decoration: none;
}

.cta-solid:hover[b-l0gfn74exd],
.cta-solid:focus-visible[b-l0gfn74exd] {
    box-shadow: 0 0.75rem 1.75rem rgba(43, 36, 56, 0.35);
    color: var(--brand-ink);
}

.cta-ghost:hover[b-l0gfn74exd],
.cta-ghost:focus-visible[b-l0gfn74exd] {
    background-color: rgba(255, 255, 255, 0.15);
    border-color: #fff;
    color: #fff;
}

.cta:focus-visible[b-l0gfn74exd] {
    outline: 3px solid #fff;
    outline-offset: 3px;
}

/* ---------- screenshot frames ---------- */

/* The images are crops of the real app, so the frame's job is to say "this is a screen"
   without pretending to be a browser window: a rounded card, a border, a lifted shadow. */
.shot[b-l0gfn74exd] {
    position: relative;
    margin: 0;
    border-radius: var(--shot-radius);
    overflow: hidden;
    background-color: #fff;
    border: 1px solid rgba(43, 36, 56, 0.12);
    box-shadow: var(--shot-shadow);
    transition: box-shadow 0.25s ease;
}

/* The hover lift lives on the image, not on the frame. The reveal animations below hold a
   transform on .shot for as long as the row is on screen, and a hover transform on the
   same element would simply lose to it. */
.shot img[b-l0gfn74exd] {
    display: block;
    width: 100%;
    height: auto;
    transition: transform 0.35s ease;
}

.shot:hover[b-l0gfn74exd] {
    box-shadow: 0 1.75rem 3rem rgba(43, 36, 56, 0.24);
}

.shot:hover img[b-l0gfn74exd] {
    transform: scale(1.02);
}

/* On a phone a full-width crop shrinks to about 350px and stops being legible, so the
   frame shows the left of it at a readable size and lets the rest run off the edge --
   the same "a slice of the real screen" idea, cropped by the viewport instead. The tall
   picker is narrow enough already. */
@media (max-width: 47.99rem) {
    .shot img[b-l0gfn74exd] {
        width: 165%;
    }

    /* The chore list is the widest crop of the four, so it needs the most zoom before the
       chore names are readable. What runs off the edge is the search and sort row. */
    .hero-shot img[b-l0gfn74exd] {
        width: 215%;
    }

    .shot-tall img[b-l0gfn74exd] {
        width: 100%;
    }
}

/* The tall icon-picker crop would otherwise tower over its two sentences. */
.shot-tall[b-l0gfn74exd] {
    max-width: 19rem;
    margin-inline: auto;
}

.hero-shot[b-l0gfn74exd] {
    box-shadow: 0 1.5rem 3rem rgba(43, 36, 56, 0.35);
    border-color: rgba(255, 255, 255, 0.25);
}

/* ---------- feature rows ---------- */

.feature[b-l0gfn74exd] {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1.75rem;
    align-items: center;
    margin-bottom: 4rem;
}

.feature h2[b-l0gfn74exd] {
    font-size: clamp(1.4rem, 3vw, 1.9rem);
    font-weight: 750;
    letter-spacing: -0.01em;
    color: var(--brand-ink);
    margin: 0 0 0.85rem;
}

.feature-copy p[b-l0gfn74exd] {
    font-size: 1.05rem;
    color: #4a4358;
    margin: 0;
}

.feature-copy ul[b-l0gfn74exd] {
    margin: 0;
    padding-left: 1.2rem;
    color: #4a4358;
    font-size: 1.05rem;
}

.feature-copy li + li[b-l0gfn74exd] {
    margin-top: 0.5rem;
}

/* ---------- closing band ---------- */

.closer[b-l0gfn74exd] {
    border-radius: 1.5rem;
    padding: 2.5rem;
    text-align: center;
    color: #fff;
    background-image: linear-gradient(135deg,
        color-mix(in srgb, var(--brand-primary) 38%, var(--brand-ink)) 0%,
        color-mix(in srgb, var(--brand-primary) 62%, var(--brand-ink)) 100%);
}

.closer-line[b-l0gfn74exd] {
    font-size: clamp(1.2rem, 2.5vw, 1.6rem);
    margin: 0 0 1.5rem;
}

.closer .hero-actions[b-l0gfn74exd] {
    justify-content: center;
}

/* ---------- two columns, once there is room ---------- */

@media (min-width: 62rem) {
    .hero[b-l0gfn74exd] {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
        padding: 3.5rem 3rem;
    }

    /* The screenshot runs off the right edge of the panel and is clipped by the hero's
       overflow: hidden. It buys the crop about 15% more width -- which is 15% larger
       text in a shot that is already small -- and the squared-off edge says "this
       carries on" rather than "this is all there was". */
    .hero-shot[b-l0gfn74exd] {
        margin-right: -3.5rem;
        border-top-right-radius: 0;
        border-bottom-right-radius: 0;
    }

    .feature[b-l0gfn74exd] {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: 3rem;
    }

    /* Alternate which side the screenshot sits on. Source order stays copy-then-image so
       the page still reads correctly with styles off, and the heading always precedes the
       picture it describes for a screen reader. */
    .feature-flip .feature-copy[b-l0gfn74exd] {
        order: 2;
    }
}

/* ---------- motion ---------- */

/* Both of these spell out their "to" frame. An implicit one is taken from the element's
   own computed style, and the scroll-driven rules below set opacity: 0 on the element --
   which would make the reveal animate from invisible to invisible. */
@keyframes cp-rise-b-l0gfn74exd {
    from {
        opacity: 0;
        transform: translateY(1.5rem);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes cp-shot-in-b-l0gfn74exd {
    from {
        opacity: 0;
        transform: translateY(2rem) scale(0.96);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes cp-drift-b-l0gfn74exd {
    50% {
        transform: translateY(-1.25rem) rotate(8deg);
    }
}

/* The hero runs on page load, staggered, because it is above the fold on every screen and
   a scroll-driven animation there would either never fire or fire instantly. */
.hero-copy > *[b-l0gfn74exd] {
    animation: cp-rise-b-l0gfn74exd 0.7s cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

.hero h1[b-l0gfn74exd] { animation-delay: 0.05s; }
.hero-lead[b-l0gfn74exd] { animation-delay: 0.15s; }
.hero-list[b-l0gfn74exd] { animation-delay: 0.25s; }
.hero-actions[b-l0gfn74exd] { animation-delay: 0.35s; }

.hero-shot[b-l0gfn74exd] {
    animation: cp-shot-in-b-l0gfn74exd 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.3s backwards;
}

.hero-star[b-l0gfn74exd] {
    animation: cp-drift-b-l0gfn74exd 14s ease-in-out infinite;
}

.hero-star-b[b-l0gfn74exd] {
    animation-duration: 18s;
    animation-direction: reverse;
}

/* Everything below the fold reveals as it scrolls into view. Scroll-driven animations need
   no script and no IntersectionObserver, but they are the one piece here that a browser can
   lack -- so the starting opacity: 0 lives inside the same @supports as the animation. A
   browser without view() shows a plain, fully visible page rather than a blank one. */
@supports (animation-timeline: view()) {
    .feature-copy[b-l0gfn74exd],
    .feature .shot[b-l0gfn74exd],
    .closer[b-l0gfn74exd] {
        opacity: 0;
        animation: cp-rise-b-l0gfn74exd 1ms linear both;
        animation-timeline: view();
        animation-range: entry 5% cover 30%;
    }

    .feature .shot[b-l0gfn74exd] {
        animation-name: cp-shot-in-b-l0gfn74exd;
    }
}

/* One switch for the lot. Reduced motion means no drift, no reveal and no lift on hover;
   the page still has its colour, its frames and its layout. */
@media (prefers-reduced-motion: reduce) {
    .hero-copy > *[b-l0gfn74exd],
    .hero-shot[b-l0gfn74exd],
    .hero-star[b-l0gfn74exd],
    .feature-copy[b-l0gfn74exd],
    .feature .shot[b-l0gfn74exd],
    .closer[b-l0gfn74exd] {
        animation: none;
    }

    /* Only the three that the @supports block above starts at opacity: 0 need putting
       back. The stars are not in this list on purpose -- their 0.09 is what makes them
       texture rather than two enormous white shapes. */
    .feature-copy[b-l0gfn74exd],
    .feature .shot[b-l0gfn74exd],
    .closer[b-l0gfn74exd] {
        opacity: 1;
    }

    .shot[b-l0gfn74exd],
    .shot img[b-l0gfn74exd],
    .cta[b-l0gfn74exd] {
        transition: none;
    }

    .shot:hover img[b-l0gfn74exd],
    .cta:hover[b-l0gfn74exd],
    .cta:focus-visible[b-l0gfn74exd] {
        transform: none;
    }
}
/* /Components/Pages/Login.razor.rz.scp.css */
/* "Sign in with Google" button, following Google's light-theme branding spec:
   40px tall, 1px #747775 border, 4px radius, Roboto Medium 14px in #1f1f1f,
   with the 18px four-colour G logo. Roboto is not bundled, so the stack falls
   back to the platform UI font, which is what the button reads as anyway. */

.google-signin-btn[b-m8gqn5bhao] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    min-height: 40px;
    padding: 0 12px;
    background-color: #fff;
    border: 1px solid #747775;
    border-radius: 4px;
    color: #1f1f1f;
    font-family: Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-size: 14px;
    font-weight: 500;
    letter-spacing: .25px;
    text-decoration: none;
    transition: background-color .15s ease, box-shadow .15s ease;
}

/* Approximates Google's 8% state layer over white. */
.google-signin-btn:hover[b-m8gqn5bhao] {
    background-color: #f7f8f8;
    color: #1f1f1f;
    box-shadow: 0 1px 2px rgba(60, 64, 67, .3), 0 1px 3px 1px rgba(60, 64, 67, .15);
}

.google-signin-btn:active[b-m8gqn5bhao] {
    background-color: #eff0f0;
}

.google-signin-btn:focus-visible[b-m8gqn5bhao] {
    outline: 2px solid #0b57d0;
    outline-offset: 2px;
}

.google-signin-btn-icon[b-m8gqn5bhao] {
    display: flex;
    flex-shrink: 0;
}

/* "or" rule separating the password form from the federated sign-in. */
.login-divider[b-m8gqn5bhao] {
    display: flex;
    align-items: center;
    gap: .75rem;
    color: var(--bs-secondary-color, #6c757d);
    font-size: .875rem;
}

.login-divider[b-m8gqn5bhao]::before,
.login-divider[b-m8gqn5bhao]::after {
    content: "";
    flex: 1;
    border-top: 1px solid var(--bs-border-color, #dee2e6);
}
/* /Components/Pages/Privacy.razor.rz.scp.css */
/* A long read. Wider line height and air between sections do more for finishing it than
   anything else on the page. */
.policy-page[b-txn18twre8] {
    line-height: 1.7;
}

.policy-page h2[b-txn18twre8] {
    color: var(--brand-ink);
}

.policy-page address[b-txn18twre8] {
    font-style: normal;
}
/* /Components/Pages/Profiles/ProfileCards.razor.rz.scp.css */
.profile-cards-row[b-9w9jh3yokk] {
    gap: 1rem;
}

.profile-card-slot[b-9w9jh3yokk] {
    width: 8rem;
}

.profile-card-add-slot[b-9w9jh3yokk] {
    width: 7.2rem;
}

.add-icon[b-9w9jh3yokk] {
    font-size: 2.8rem;
}

.add-profile-label[b-9w9jh3yokk] {
    font-size: 0.875rem;
}

.add-profile-card[b-9w9jh3yokk] {
    border: 2px dashed #adb5bd;
    background-color: #fff;
    color: #495057;
    transition: border-color 0.15s ease-in-out, background-color 0.15s ease-in-out, color 0.15s ease-in-out;
}

    .add-profile-card:hover[b-9w9jh3yokk] {
        border-color: var(--bs-primary);
        background-color: var(--bs-primary-bg-subtle);
        color: var(--bs-primary);
    }

@media (max-width: 640.98px) {
    .profile-cards-row[b-9w9jh3yokk] {
        gap: 0.5rem;
    }

    .profile-card-slot[b-9w9jh3yokk] {
        height: 6.5rem;
        width: 5rem;
    }

    .profile-card-add-slot[b-9w9jh3yokk] {
        width: 4rem;
    }

    .add-icon[b-9w9jh3yokk] {
        font-size: 1.4rem;
    }

    .add-profile-label[b-9w9jh3yokk] {
        font-size: 0.6875rem;
    }
}

/* The switcher and the cards stack; only the cards row scrolls sideways. */
.profile-cards-stack[b-9w9jh3yokk] {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.family-switch-row[b-9w9jh3yokk] {
    margin-bottom: 0.5rem;
}

.family-switch-btn[b-9w9jh3yokk] {
    max-width: 100%;
    /* An outline button is transparent, so the stripes behind the bar ran straight through
       the only control that sits on them. A solid fill puts it back on its own surface --
       and it has to be a real colour rather than "inherit", because what it would inherit
       is the pattern. See Documentation/40-Profile-Cards-Backdrop.md. */
    background-color: #fff;
}

    .family-switch-btn:hover[b-9w9jh3yokk], .family-switch-btn:focus[b-9w9jh3yokk] {
        background-color: var(--bs-primary);
    }

/* A long family name gets an ellipsis rather than pushing the button off a phone. */
.family-switch-name[b-9w9jh3yokk] {
    display: inline-block;
    max-width: 14rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
}

@media (max-width: 640.98px) {
    .family-switch-row[b-9w9jh3yokk] {
        margin-bottom: 0.375rem;
    }

    .family-switch-name[b-9w9jh3yokk] {
        max-width: 10rem;
    }
}
/* /Components/Pages/Rewards/Rewards.razor.rz.scp.css */
/* Small screens only. The Add Reward button is the page's one action and on a phone it
   is pressed with a thumb, so it is grown to the ~44px a touch target wants; a wide
   screen keeps Bootstrap's default, where the heading row has a pointer aiming at it.
   Same breakpoint as the chore list and the profile cards.
   See Documentation/76-Bigger-Touch-Targets-on-Small-Screens.md. */
@media (max-width: 640.98px) {
    .reward-add[b-xcy89rgr9k] {
        --bs-btn-padding-y: 0.65rem;
        --bs-btn-padding-x: 1.1rem;
        --bs-btn-font-size: 1.05rem;
        min-height: 44px;
    }
}

/* A subscription's Stop link on a reward card (doc 91). Grown to the same ~44px on a phone,
   where two of them stack one line apart and a thumb would hit the wrong kid's. */
@media (max-width: 640.98px) {
    .reward-subscribers .btn-link[b-xcy89rgr9k] {
        min-height: 44px;
        min-width: 44px;
    }
}
/* /Components/Pages/SupportOptions.razor.rz.scp.css */
/* Each way of helping is one block with air around it rather than a card: there are only
   ever two or three, and cards inside a card reads as a settings screen.

   These rules live here, with the markup. They were in Support.razor.css while the markup
   was on the page; moving the markup into this component left the selectors matching
   nothing, which is the trap CLAUDE.md records about moving a component -- scoped CSS
   belongs to the file whose markup it targets. */
.support-option[b-94kx5gagd4] {
    margin-top: 1.5rem;
}

.support-option h2[b-94kx5gagd4] {
    color: var(--brand-ink);
}

/* The chip-in buttons sit in a row and wrap on a narrow screen rather than stacking full
   width: there are two of them, they are alternatives to each other, and a column of
   full-width buttons reads as a list of steps. */
.support-chip-in[b-94kx5gagd4] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}
/* /Components/Pages/Terms.razor.rz.scp.css */
/* The policy pages share one look. The rules are the same as Privacy.razor.css on purpose:
   scoped CSS belongs to the file whose markup it targets, so a shared stylesheet here would
   have to live in wwwroot and apply to everything. Two short copies beat that. */
.policy-page[b-j2am4s2dwp] {
    line-height: 1.7;
}

.policy-page h2[b-j2am4s2dwp] {
    color: var(--brand-ink);
}

.policy-page address[b-j2am4s2dwp] {
    font-style: normal;
}
/* /Components/Shared/ApproverPinModal.razor.rz.scp.css */
/* Stack above a modal this was opened from: Bootstrap puts .modal at 1055 and
   .modal-backdrop at 1050, so this backdrop covers the lower modal. */
.approver-pin-modal[b-y440eaagp9] {
    z-index: 1065;
}

.approver-pin-backdrop[b-y440eaagp9] {
    z-index: 1060;
}

.pin-slots[b-y440eaagp9] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.pin-slot[b-y440eaagp9] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3.25rem;
    height: 3.25rem;
    border: 2px dashed var(--bs-border-color);
    border-radius: 0.5rem;
    font-size: 1.6rem;
}

.pin-slot.filled[b-y440eaagp9] {
    border-style: solid;
    border-color: var(--bs-primary);
    background: rgba(13, 110, 253, 0.08);
}

/* Matches IconPicker's grid so the icons look the same everywhere. */
.pin-grid[b-y440eaagp9] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.5rem;
    max-height: 14rem;
    overflow-y: auto;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.375rem;
}

.pin-grid-item[b-y440eaagp9] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    width: 4.5rem;
    padding: 0.5rem 0.25rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.375rem;
    background: var(--bs-body-bg);
    cursor: pointer;
    transition: background-color 0.12s ease, border-color 0.12s ease;
}

/* Behind a hover query so a tap on a tablet doesn't leave the icon it landed on
   highlighted afterwards, which would name the last icon of the PIN to anyone watching.
   See doc 54. */
@media (hover: hover) {
    .pin-grid-item:hover:not(:disabled)[b-y440eaagp9] {
        background: var(--bs-secondary-bg);
        border-color: var(--bs-secondary-color);
    }
}

.pin-grid-item:disabled[b-y440eaagp9] {
    opacity: 0.5;
    cursor: default;
}

.pin-grid-item i[b-y440eaagp9] {
    font-size: 1.75rem;
}

.pin-grid-item-name[b-y440eaagp9] {
    font-size: 0.7rem;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* /Components/Shared/ColorPicker.razor.rz.scp.css */
.color-picker[b-68hvp3v7h4] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.color-swatch[b-68hvp3v7h4] {
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 0.375rem;
    border: 2px solid transparent;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
    color: transparent;
}

.color-swatch:hover[b-68hvp3v7h4] {
    transform: scale(1.1);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
}

.color-swatch:focus[b-68hvp3v7h4] {
    outline: none;
    box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.25);
}

.color-swatch.selected[b-68hvp3v7h4] {
    border-color: var(--bs-body-color);
    color: #fff;
    box-shadow: 0 0 0 2px var(--bs-body-bg), 0 0 0 4px var(--bs-body-color);
}

.color-swatch.selected:hover[b-68hvp3v7h4] {
    transform: none;
}
/* /Components/Shared/IconPicker.razor.rz.scp.css */
.icon-picker[b-52nq9rdd3i] {
    position: relative;
    z-index: 1050;
}

/* Every picker shares the z-index above, so when pickers stack vertically the ones
   further down the page paint over an earlier picker's open panel and backdrop. */
.icon-picker.open[b-52nq9rdd3i] {
    z-index: 1051;
}

.icon-picker-backdrop[b-52nq9rdd3i] {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.25);
    z-index: 1049;
}

.icon-picker-trigger[b-52nq9rdd3i] {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 12rem;
    text-align: left;
}

.icon-picker-trigger.open[b-52nq9rdd3i] {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25);
}

.icon-picker-trigger i[b-52nq9rdd3i] {
    font-size: 1.25rem;
    width: 1.5rem;
    text-align: center;
}

.icon-picker-trigger-name[b-52nq9rdd3i] {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.icon-picker-trigger-placeholder[b-52nq9rdd3i] {
    flex: 1;
    color: var(--bs-secondary-color);
}

.icon-picker-caret[b-52nq9rdd3i] {
    font-size: 0.9rem !important;
    width: auto !important;
    color: var(--bs-secondary-color);
}

.icon-picker-panel[b-52nq9rdd3i] {
    position: absolute;
    top: calc(100% + 0.25rem);
    left: 0;
    min-width: 18rem;
    max-width: 22rem;
    z-index: 1050;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.375rem;
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
    overflow: hidden;
}

.icon-picker-search[b-52nq9rdd3i] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem;
    border-bottom: 1px solid var(--bs-border-color);
    background: var(--bs-secondary-bg);
}

.icon-picker-search-icon[b-52nq9rdd3i] {
    color: var(--bs-secondary-color);
}

.icon-picker-grid[b-52nq9rdd3i] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.75rem;
    max-height: 16rem;
    overflow-y: auto;
}

.icon-picker-item[b-52nq9rdd3i] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    width: 4.5rem;
    padding: 0.5rem 0.25rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.375rem;
    background: var(--bs-body-bg);
    cursor: pointer;
    transition: background-color 0.12s ease, border-color 0.12s ease;
}

.icon-picker-item:hover[b-52nq9rdd3i] {
    background: var(--bs-secondary-bg);
    border-color: var(--bs-secondary-color);
}

.icon-picker-item.selected[b-52nq9rdd3i] {
    border-color: var(--bs-primary);
    background: rgba(13, 110, 253, 0.08);
}

.icon-picker-item i[b-52nq9rdd3i] {
    font-size: 1.75rem;
}

.icon-picker-item-name[b-52nq9rdd3i] {
    font-size: 0.7rem;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.icon-picker-empty[b-52nq9rdd3i] {
    padding: 1rem;
    color: var(--bs-secondary-color);
    text-align: center;
    font-size: 0.9rem;
}

/* The suggested row sits above the full grid on a tinted band, so it reads as an offer
   rather than as the first few icons of the list. Without the tint the row and the grid
   below it are the same thing twice and the heading is doing all the work. */
.icon-picker-suggested[b-52nq9rdd3i] {
    background: var(--bs-secondary-bg);
    border-bottom: 1px solid var(--bs-border-color);
}

.icon-picker-section-label[b-52nq9rdd3i] {
    padding: 0.5rem 0.75rem 0;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--bs-secondary-color);
}

.icon-picker-section-label-ruled[b-52nq9rdd3i] {
    padding-top: 0.75rem;
}

/* The suggested row is four icons at most, so it never needs to scroll; leaving the
   grid's max-height on it would give the panel a second scrollbar.

   It does not wrap either. Four items at 4.5rem with three 0.5rem gaps is 19.5rem, which
   with the grid's padding holds the panel just inside its 22rem maximum -- and a row that
   wrapped to three-and-one would read as the start of another list rather than as one
   short offer. */
.icon-picker-grid-tight[b-52nq9rdd3i] {
    max-height: none;
    overflow-y: visible;
    padding-bottom: 0.5rem;
    flex-wrap: nowrap;
}
/* /Components/Shared/ProfilePicker.razor.rz.scp.css */
.profile-picker[b-anqg7dyj5k] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.profile-picker-item[b-anqg7dyj5k] {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.85rem;
    border-radius: 0.5rem;
    border: 2px solid transparent;
    color: var(--profile-chip-color);
    background-color: var(--profile-chip-bg);
    font: inherit;
    cursor: pointer;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}

.profile-picker-item:hover[b-anqg7dyj5k] {
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.profile-picker-item:focus[b-anqg7dyj5k] {
    outline: none;
    box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.25);
}

.profile-picker-item.selected[b-anqg7dyj5k] {
    border-color: currentColor;
    box-shadow: 0 0 0 2px var(--bs-body-bg), 0 0 0 4px var(--bs-body-color);
}

.profile-picker-item.selected:hover[b-anqg7dyj5k] {
    transform: none;
}

.profile-picker-icon[b-anqg7dyj5k] {
    font-size: 1.1rem;
}

.profile-picker-check[b-anqg7dyj5k] {
    margin-left: 0.15rem;
}
