html, body {
    /* same fonts as the theme (Layout/AppTheme.cs) */
    font-family: ui-rounded, 'SF Pro Rounded', Nunito, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

.mud-main-content {
    padding-top: 24px !important;
}

/* height of the sticky header (.app-header, with its bottom border): the filter bars stick below it; brand and
   menu toolbars on larger screens, brand only on phones */
:root {
    --app-header-height: 113px;
}

@media (max-width: 599.98px) {
    :root {
        --app-header-height: 57px;
    }
}

/* header (brand, search and actions, then the menu on larger screens): sticky and translucent over the scrolled
   content, full width with small margins (blackberry's HeaderToolBar) */
.app-header {
    position: sticky;
    top: 0;
    z-index: var(--mud-zindex-appbar);
    background: color-mix(in srgb, var(--mud-palette-background) 72%, transparent);
    backdrop-filter: blur(12px) saturate(180%);
    -webkit-backdrop-filter: blur(12px) saturate(180%);
    border-bottom: 1px solid var(--mud-palette-lines-default);
    color: var(--mud-palette-text-primary);
}

.app-header-progress {
    position: absolute;
    inset: auto 0 0 0;
    height: 2px;
}

/* logo of the header (AppLogo): hops at the start, during the loads and on hover (its ribbon swinging), a blink from
   time to time;
   transforms only, on a 32px image: no layout, nothing when motion is reduced */
.app-logo {
    flex-shrink: 0;
    overflow: visible;
}

.app-logo-body {
    transform-box: fill-box;
    transform-origin: 50% 100%;
}

.app-logo-ribbon {
    transform-box: fill-box;
    transform-origin: 50% 0;
}

.app-logo-eye {
    transform-box: fill-box;
    transform-origin: center;
    animation: app-logo-blink 7s infinite;
}

/* start and loads (AppLogo, app-logo-busy): hops on its own element, the hover hops stopped meanwhile */
.app-logo-jump,
.app-logo-flag {
    transform-box: fill-box;
}

.app-logo-jump {
    transform-origin: 50% 100%;
}

.app-logo-flag {
    transform-origin: 50% 0;
}

.app-logo-busy .app-logo-tick,
.app-logo-busy .app-logo-jump {
    animation: app-logo-hop 0.7s ease-in-out infinite;
}

.app-logo-busy .app-logo-flag {
    animation: app-logo-swing 0.7s ease-in-out infinite;
}

@media (hover: hover) {
    .app-brand:hover .app-logo:not(.app-logo-busy) .app-logo-body {
        animation: app-logo-hop 0.7s ease-in-out infinite;
    }

    .app-brand:hover .app-logo:not(.app-logo-busy) .app-logo-ribbon {
        animation: app-logo-swing 0.7s ease-in-out infinite;
    }
}

/* px: units of its viewBox (368 wide), 40 is about 3.5px on screen */
@keyframes app-logo-hop {
    0%, 20%, 100% {
        transform: translateY(0) scale(1, 1);
    }
    36% {
        transform: translateY(0) scale(1.06, 0.94);
    }
    65% {
        transform: translateY(-40px) scale(0.97, 1.03);
    }
}

@keyframes app-logo-swing {
    0%, 20%, 100% {
        transform: rotate(0);
    }
    45% {
        transform: rotate(10deg);
    }
    75% {
        transform: rotate(-8deg);
    }
}

@keyframes app-logo-blink {
    0%, 94%, 100% {
        transform: scaleY(1);
    }
    97% {
        transform: scaleY(0.1);
    }
}

@media (prefers-reduced-motion: reduce) {
    .app-logo-eye,
    .app-logo-busy .app-logo-jump,
    .app-logo-busy .app-logo-flag,
    .app-brand:hover .app-logo:not(.app-logo-busy) .app-logo-body,
    .app-brand:hover .app-logo:not(.app-logo-busy) .app-logo-ribbon {
        animation: none;
    }
}

/* banner of a page (PageHero), in the colors of the logo */
.page-hero {
    padding: 20px;
    border-radius: 20px;
    background: linear-gradient(133deg, var(--mud-palette-primary) 0%, var(--mud-palette-tertiary) 100%);
    color: var(--mud-palette-primary-text);
}

/* details or actions with nothing to show (e.g. no counter yet) */
.page-hero > div:empty {
    display: none;
}

.page-hero h1 {
    overflow-wrap: anywhere;
}

.page-hero-pill {
    padding: 2px 10px;
    border-radius: 999px;
    background: color-mix(in srgb, currentColor 18%, transparent);
    font-size: 0.8125rem;
}

/* illustrated banner (home): books floating on its right side, behind the texts, and two twinkling stars */
.page-hero-illustrated {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.page-hero-illustrated::before {
    content: "";
    position: absolute;
    inset: -40% -10% auto auto;
    z-index: -1;
    width: 260px;
    height: 260px;
    border-radius: 50%;
    background: radial-gradient(circle, color-mix(in srgb, var(--mud-palette-secondary) 45%, transparent), transparent 70%);
}

.page-hero-illustration {
    position: absolute;
    right: 8px;
    bottom: -6px;
    z-index: -1;
    width: 150px;
    fill: currentColor;
    opacity: 0.9;
}

.page-hero-books {
    animation: page-hero-float 6s ease-in-out infinite;
}

.page-hero-book-band {
    fill: var(--mud-palette-secondary);
}

.page-hero-star {
    fill: var(--mud-palette-warning);
    transform-box: fill-box;
    transform-origin: center;
    animation: page-hero-twinkle 3s ease-in-out infinite;
}

.page-hero-star-late {
    animation-delay: 1.5s;
}

/* phones: the books behind the texts stay discreet */
@media (max-width: 599.98px) {
    .page-hero-illustration {
        width: 84px;
        opacity: 0.6;
    }
}

@keyframes page-hero-float {
    50% {
        transform: translateY(-4px);
    }
}

@keyframes page-hero-twinkle {
    50% {
        opacity: 0.3;
        transform: scale(0.7);
    }
}

@media (prefers-reduced-motion: reduce) {
    .page-hero-books,
    .page-hero-star {
        animation: none;
    }
}

/* covers (BookCover): layers stacked, a generated one (title on a color of the palette) below the images */
.book-cover {
    position: relative;
    display: block;
    flex-shrink: 0;
    overflow: hidden;
    border-radius: 6px;
}

.book-cover-fluid {
    width: 100%;
    height: auto;
    aspect-ratio: 2 / 3;
}

.book-cover > *,
.book-cover picture > img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

.book-cover img {
    display: block;
    object-fit: cover;
    opacity: 0;
    transition: opacity 0.3s ease-out;
}

/* once loaded (BookCover): faded in when downloaded, at once from the cache of the browser */
.book-cover img.book-cover-loaded,
.book-cover img.book-cover-cached {
    opacity: 1;
}

.book-cover img.book-cover-cached {
    transition: none;
}

@media (prefers-reduced-motion: reduce) {
    .book-cover img {
        transition: none;
    }
}

.book-cover-generated {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding: 8px;
    border-radius: inherit;
    background: color-mix(in srgb, var(--cover-color) 28%, var(--mud-palette-surface));
    border: 1px solid color-mix(in srgb, var(--cover-color) 40%, transparent);
    color: var(--mud-palette-text-primary);
}

.book-cover-generated-icon {
    align-items: center;
}

.book-cover-title {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
    width: 100%;
    font-size: 0.8125rem;
    font-weight: 700;
    line-height: 1.2;
}

/* filters of the books (BookFilterChips, and the search of a shared shelf): stuck under the header while the books
   scroll, translucent like it; the chips scroll sideways on one line. Below the popovers (menus, selects: rendered at
   the root of the page), which open over it */
.filter-bar {
    position: sticky;
    top: var(--app-header-height);
    z-index: calc(var(--mud-zindex-popover) - 1);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-inline: -8px;
    padding: 8px;
    border-radius: 0 0 var(--mud-default-borderradius) var(--mud-default-borderradius);
    background: color-mix(in srgb, var(--mud-palette-background) 72%, transparent);
    backdrop-filter: blur(12px) saturate(180%);
    -webkit-backdrop-filter: blur(12px) saturate(180%);
}

.filter-chips {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    align-items: center;
    overflow-x: auto;
    scrollbar-width: none;
    /* the chips cut by the edge fade out */
    mask-image: linear-gradient(to right, black calc(100% - 24px), transparent);
}

.filter-chips::-webkit-scrollbar {
    display: none;
}

/* next to a search field: on their own line */
.filter-bar > .mud-input-control ~ .filter-chips {
    flex-basis: 100%;
}

/* search page: the field and the language menu always on one line, the field shrinking on phones */
.search-bar {
    flex-wrap: nowrap;
}

.search-bar > .mud-input-control {
    flex: 1 1 0;
    min-width: 0;
}

/* danger zone of a settings page (DangerZone: deletion of a shelf, leaving a shared shelf), Smoothies SettingsCard */
.danger-zone {
    --blackberry-card-border-color: var(--mud-palette-error);
}

/* cards of the settings page (Settings): each one at its own height; on larger screens, two columns, the access card
   (the tallest) alone on the right next to the other cards stacked on the left, the storage diagnostic below them.
   TODO: real masonry (display: grid-lanes / grid-template-rows: masonry) once the browsers support it, instead of this
   placement by hand */
.settings-cards {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
    align-items: start;
}

/* the card reached by a link (Settings.razor) first on phones, where the cards are stacked */
@media (max-width: 599px) {
    .settings-cards > .settings-cards-first {
        order: -1;
    }
}

@media (min-width: 600px) {
    .settings-cards {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .settings-cards > * {
        grid-column: 1;
    }

    /* SettingsCard fills its cell: as tall as the cards on the left */
    .settings-cards > .settings-cards-tall {
        grid-area: 1 / 2 / span 3;
        align-self: stretch;
    }

    .settings-cards > .settings-cards-wide {
        grid-column: 1 / -1;
    }
}

.filter-chips .mud-chipset {
    display: flex;
    flex-wrap: nowrap;
}

.filter-chips .mud-chip {
    flex-shrink: 0;
}

.filter-chip-count {
    margin-inline-start: 6px;
    font-weight: 700;
    opacity: 0.7;
}

/* grid of covers (BookTile) */
.book-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
    gap: 20px 14px;
}

.book-tile {
    display: flex;
    /* a button is as wide as its content otherwise */
    width: 100%;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    padding: 0;
    border: none;
    background: none;
    color: inherit;
    font: inherit;
    text-align: start;
    cursor: pointer;
}

/* top of its cell: a button centers its content vertically */
.book-grid > .book-tile {
    align-self: start;
}

.book-tile-cover {
    position: relative;
    display: block;
    /* not stretched by the button: as wide as its content (layers of the cover, positioned: none) otherwise */
    width: 100%;
    border-radius: 6px;
    box-shadow: 0 2px 6px color-mix(in srgb, var(--mud-palette-primary) 18%, transparent);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.book-tile:focus-visible .book-tile-cover {
    transform: translateY(-3px);
    box-shadow: 0 8px 18px color-mix(in srgb, var(--mud-palette-primary) 28%, transparent);
}

/* touch screens: no hover left after a tap */
@media (hover: hover) {
    .book-tile:hover .book-tile-cover {
        transform: translateY(-3px);
        box-shadow: 0 8px 18px color-mix(in srgb, var(--mud-palette-primary) 28%, transparent);
    }
}

.book-tile:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 4px;
    border-radius: 6px;
}

.book-tile-badge {
    position: absolute;
    top: 6px;
    right: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--mud-palette-surface);
    box-shadow: 0 1px 4px color-mix(in srgb, var(--mud-palette-text-primary) 25%, transparent);
}

.book-tile-title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.25;
}

.book-tile-caption {
    display: block;
    /* flex item: as wide as its text otherwise, never truncated */
    min-width: 0;
    max-width: 100%;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

@media (prefers-reduced-motion: reduce) {
    .book-tile-cover {
        transition: none;
    }
}

/* home: cards of the reservations to approve, carousel of the wishes of the relatives */
.home-card {
    padding: 12px;
    border-radius: 16px;
    background: color-mix(in srgb, var(--mud-palette-warning) 14%, var(--mud-palette-surface));
}

/* carousel: as many whole books as fit (about 90 to 120px wide, 126px on phones: smaller than the cover of the dialog
   of a book, 136px), then half of the next one, cut by the edge: there is more to scroll; its scrollbar on mouse
   screens only (no horizontal wheel), hidden on touch screens */
.carousel {
    --carousel-gap: 14px;
    container-type: inline-size;
    display: flex;
    gap: var(--carousel-gap);
    overflow-x: auto;
    padding: 4px 2px 12px;
    scroll-snap-type: x mandatory;
    scrollbar-width: thin;
}

.carousel-item {
    /* whole books shown, by the width of the carousel below */
    --carousel-count: 2;
    flex: 0 0 calc((100cqi - var(--carousel-count) * var(--carousel-gap)) / (var(--carousel-count) + 0.5));
    min-width: 0;
    scroll-snap-align: start;
}

@container (min-width: 392px) {
    .carousel-item {
        --carousel-count: 3;
    }
}

@container (min-width: 466px) {
    .carousel-item {
        --carousel-count: 4;
    }
}

@container (min-width: 584px) {
    .carousel-item {
        --carousel-count: 5;
    }
}

@container (min-width: 702px) {
    .carousel-item {
        --carousel-count: 6;
    }
}

@container (min-width: 820px) {
    .carousel-item {
        --carousel-count: 7;
    }
}

@container (min-width: 940px) {
    .carousel-item {
        --carousel-count: 8;
    }
}

@container (min-width: 1060px) {
    .carousel-item {
        --carousel-count: 9;
    }
}

/* gift ideas of a shared shelf: one per row, two when the section is wide enough (a long empty row otherwise) */
.gift-ideas {
    container-type: inline-size;
}

@container (min-width: 720px) {
    .gift-ideas-list {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: 16px;
    }
}

@media (pointer: coarse) {
    .carousel {
        scrollbar-width: none;
    }

    .carousel::-webkit-scrollbar {
        display: none;
    }
}

/* phones: up to the edges of the screen, over the margin of the page (.main-content, 16px), its first book aligned
   with the page */
@media (max-width: 599.98px) {
    .carousel {
        margin-inline: -16px;
        padding-inline: 16px;
        scroll-padding-inline: 16px;
    }
}

/* code scanner (CodeScanner): camera preview, frame of the barcode, square for a QR code */
.code-scanner {
    position: relative;
    overflow: hidden;
    border-radius: 12px;
    background: var(--mud-palette-black);
    aspect-ratio: 4 / 3;
}

.code-scanner-video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.code-scanner-frame {
    position: absolute;
    inset: 30% 12%;
    border: 3px solid var(--mud-palette-primary);
    border-radius: 12px;
    box-shadow: 0 0 0 999px color-mix(in srgb, var(--mud-palette-black) 35%, transparent);
}

.code-scanner-frame-square {
    inset: 12% auto;
    left: 50%;
    translate: -50% 0;
    aspect-ratio: 1;
}

/* every dialog (MudDialogProvider, message boxes too): bottom sheet on phones, sliding up from the bottom of the screen;
   centered on larger screens, with the width of MudDialogProvider */
@media (max-width: 599.98px) {
    /* :has() for a specificity above the one of the position of MudBlazor (mud-dialog-center) */
    .mud-dialog-container:has(> .mud-dialog) {
        align-items: flex-end;
    }

    .mud-dialog-container > .mud-dialog {
        width: 100%;
        max-width: 100%;
        max-height: 90dvh;
        margin: 0;
        border-radius: 20px 20px 0 0;
        padding-bottom: env(safe-area-inset-bottom);
        animation: sheet-up 0.22s ease-out;
    }

    /* handle: a sheet, closed by a tap outside */
    .mud-dialog-container > .mud-dialog::before {
        content: "";
        display: block;
        flex: none;
        width: 36px;
        height: 4px;
        margin: 10px auto 0;
        border-radius: 2px;
        background: var(--mud-palette-lines-inputs);
    }
}

@keyframes sheet-up {
    from {
        transform: translateY(100%);
    }
    to {
        transform: translateY(0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .mud-dialog-container > .mud-dialog {
        animation: none;
    }
}

/* top of the dialog of a book (BookSheetHeader): its cover larger than in the lists, its title and details next to it */
.book-sheet-header {
    display: flex;
    gap: 16px;
}

.book-sheet-header .book-cover {
    box-shadow: var(--mud-elevation-4);
}

.book-sheet-info {
    flex: 1 1 0;
    min-width: 0;
    padding-top: 4px;
}

.book-sheet-title {
    line-height: 1.25;
    overflow-wrap: anywhere;
}

/* paragraphs of the summary of a book (BookDetailsView) */
.book-summary {
    white-space: pre-line;
}

/* empty page or list (EmptyState): books of the colors of the theme */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 32px 16px;
}

.empty-state-illustration {
    position: relative;
    margin-bottom: 8px;
}

.empty-state-disc {
    fill: color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-surface));
}

.empty-state-book-1 {
    fill: var(--mud-palette-secondary);
}

.empty-state-book-2 {
    fill: var(--mud-palette-primary);
}

.empty-state-book-3 {
    fill: var(--mud-palette-tertiary);
}

.empty-state-shelf {
    fill: color-mix(in srgb, var(--mud-palette-text-primary) 30%, transparent);
}

.empty-state-badge {
    position: absolute;
    right: -4px;
    bottom: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--mud-palette-surface);
    box-shadow: 0 2px 6px color-mix(in srgb, var(--mud-palette-primary) 25%, transparent);
}

.empty-state-text {
    max-width: 360px;
    color: var(--mud-palette-text-secondary);
}

/* loading placeholders (LoadingSkeleton), in the shape of the content */
.skeleton-hero {
    border-radius: 20px;
}

.skeleton-cover {
    width: 100%;
    aspect-ratio: 2 / 3;
    border-radius: 6px;
}

/* card of a shelf (Shelves): its last books, fanned out on a tinted shelf */
.shelf-card {
    overflow: hidden;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

@media (hover: hover) {
    .shelf-card:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 18px color-mix(in srgb, var(--mud-palette-primary) 18%, transparent);
    }
}

.shelf-card-covers {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    height: 120px;
    padding: 16px 16px 0;
    overflow: hidden;
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-surface));
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.shelf-card-cover {
    flex: 0 0 64px;
    margin-left: -12px;
    /* bottom of the covers hidden by the edge of the shelf */
    transform: translateY(16px) rotate(calc((var(--cover-index) - 1.5) * 4deg));
    border-radius: 6px;
    box-shadow: 0 2px 8px color-mix(in srgb, var(--mud-palette-text-primary) 25%, transparent);
}

.shelf-card-cover:first-child {
    margin-left: 0;
}

@media (prefers-reduced-motion: reduce) {
    .shelf-card {
        transition: none;
    }
}

/* card of a collection (CollectionsView): the cover of its last volume, blurred and faded into the surface of the
   card (the text stays readable), behind its content */
.collection-card {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.collection-card-backdrop {
    position: absolute;
    inset: -40px;
    z-index: -1;
    background-position: center;
    background-size: cover;
    filter: blur(32px) saturate(1.1);
    opacity: 0.3;
    pointer-events: none;
}

/* strip of the volumes of a collection (CollectionsView): owned (filled), wanted (outlined), to find (dashed, a
   link to the search), the next volume (dotted), a range of a long series (wider, unfolds it) */
.collection-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 8px;
}

.collection-volume {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    min-width: 26px;
    height: 26px;
    padding: 0 4px;
    border: 1.5px solid transparent;
    border-radius: 6px;
    background: none;
    color: var(--mud-palette-text-primary);
    font: inherit;
    font-size: 0.75rem;
    line-height: 1;
    text-decoration: none;
}

a.collection-volume,
button.collection-volume {
    cursor: pointer;
}

a.collection-volume:hover,
button.collection-volume:hover {
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, transparent);
}

.collection-volume-owned {
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

button.collection-volume-owned:hover {
    background: var(--mud-palette-primary-darken);
}

.collection-strip-complete .collection-volume-owned {
    background: var(--mud-palette-success);
    color: var(--mud-palette-success-text);
}

.collection-volume-wanted {
    border-color: var(--mud-palette-primary);
}

.collection-volume-missing {
    border: 1px dashed var(--mud-palette-text-disabled);
    color: var(--mud-palette-text-secondary);
}

.collection-volume-next {
    border: 1.5px dotted var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

.collection-volume-range {
    padding: 0 8px;
}

/* legend of the strips, next to the title of the collections */
.collection-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
}

.collection-legend > span {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.collection-legend .collection-volume {
    min-width: 12px;
    width: 12px;
    height: 12px;
    padding: 0;
    border-radius: 3px;
}

/* page changes on phones (ViewTransitions): the header and the bottom menu stay still; the new page slides in from
   the right over the old one (forward), the old one slides out to the right (back), or they fade (pages of the menu) */
.app-header {
    view-transition-name: app-header;
}

.bottom-nav {
    view-transition-name: bottom-menu;
}

/* "+" button of the phones (Smoothies ResponsiveBottomMenu, AppMenu): the main action, on the gradient of the brand
   (as PageHero) with a shadow of its color, its "+" enlarged in the same button; pressed: it sinks a little, its "+"
   turning a quarter while the sheet opens */
.bottom-nav .mud-fab.bottom-menu-fab {
    background-image: linear-gradient(133deg, var(--mud-palette-primary) 0%, var(--mud-palette-tertiary) 100%);
    box-shadow: 0 8px 22px color-mix(in srgb, var(--mud-palette-primary) 45%, transparent);
    transition: transform 0.15s ease-out;
}

.bottom-nav .mud-fab.bottom-menu-fab:active {
    transform: scale(0.92);
}

.bottom-nav .bottom-menu-fab .mud-icon-root {
    font-size: 2.25rem;
    transition: transform 0.3s ease-out;
}

.bottom-nav:has(~ .bottom-form .mud-drawer--open) .bottom-menu-fab .mud-icon-root {
    transform: rotate(90deg);
}

/* empty library (MainLayout, library-empty): a halo spreads from the button every few seconds, until a first book is
   added; its shadow animated (the button hides what overflows it), kept under the halo */
.mud-layout:has(.library-empty) .bottom-nav .mud-fab.bottom-menu-fab {
    animation: fab-pulse 2.4s ease-out infinite;
}

@keyframes fab-pulse {
    from {
        box-shadow: 0 8px 22px color-mix(in srgb, var(--mud-palette-primary) 45%, transparent),
            0 0 0 0 color-mix(in srgb, var(--mud-palette-primary) 55%, transparent);
    }
    70%,
    to {
        box-shadow: 0 8px 22px color-mix(in srgb, var(--mud-palette-primary) 45%, transparent),
            0 0 0 16px color-mix(in srgb, var(--mud-palette-primary) 0%, transparent);
    }
}

@media (prefers-reduced-motion: reduce) {
    .bottom-nav .mud-fab.bottom-menu-fab,
    .bottom-nav .bottom-menu-fab .mud-icon-root {
        transition: none;
    }

    .mud-layout:has(.library-empty) .bottom-nav .mud-fab.bottom-menu-fab {
        animation: none;
    }
}

:root {
    --page-transition-duration: 320ms;
    --page-transition-easing: cubic-bezier(0.32, 0.72, 0, 1);
}

/* the pages slide over each other: no blending of their overlapping parts */
::view-transition-old(root),
::view-transition-new(root) {
    mix-blend-mode: normal;
    animation-duration: var(--page-transition-duration);
    animation-timing-function: var(--page-transition-easing);
    animation-fill-mode: both;
}

html[data-page-transition="forward"]::view-transition-old(root) {
    animation-name: page-behind;
}

html[data-page-transition="forward"]::view-transition-new(root) {
    animation-name: page-from-right;
}

/* the old page leaves above the one it uncovers */
html[data-page-transition="back"]::view-transition-old(root) {
    z-index: 1;
    animation-name: page-to-right;
}

html[data-page-transition="back"]::view-transition-new(root) {
    animation-name: page-from-behind;
}

html[data-page-transition="fade"]::view-transition-old(root) {
    animation-duration: 90ms;
    animation-timing-function: ease-out;
    animation-name: page-fade-out;
}

html[data-page-transition="fade"]::view-transition-new(root) {
    animation-duration: 160ms;
    animation-timing-function: ease-out;
    animation-name: page-fade-in;
}

@keyframes page-from-right {
    from {
        transform: translateX(100%);
    }
}

@keyframes page-to-right {
    to {
        transform: translateX(100%);
    }
}

/* the page under the sliding one moves a little, and darkens */
@keyframes page-behind {
    to {
        transform: translateX(-30%);
        filter: brightness(0.85);
    }
}

@keyframes page-from-behind {
    from {
        transform: translateX(-30%);
        filter: brightness(0.85);
    }
}

@keyframes page-fade-out {
    to {
        opacity: 0;
    }
}

@keyframes page-fade-in {
    from {
        opacity: 0;
    }
}

/* alert with a button in its message (e.g. StorageWarningBanner): icon, message and close button centered on one line */
.alert-centered .mud-alert-position {
    align-items: center;
}

/* choice of a status (owned / wanted): labels with room around them */
.mud-toggle-group.status-toggle .mud-toggle-item {
    padding: 4px 16px;
}

/* the whole width of the dialog of a book, a half each */
.mud-toggle-group.status-toggle-full {
    display: flex;
    width: 100%;
}

.mud-toggle-group.status-toggle-full .mud-toggle-item {
    flex: 1 1 0;
}

/* undo button of a quick add (Search, snackbar-undo): its border empties while the notification stays (after its
   show transition: 400ms, during its visible duration: 5s, the durations of ShowAdded); on ::before, the ripple of
   the button is on ::after */
@property --undo-progress {
    syntax: "<percentage>";
    inherits: false;
    initial-value: 100%;
}

.snackbar-undo .mud-snackbar-action-button::before {
    content: "";
    position: absolute;
    inset: 0;
    padding: 2px;
    border-radius: inherit;
    background: conic-gradient(currentColor var(--undo-progress), color-mix(in srgb, currentColor 20%, transparent) 0);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
    pointer-events: none;
    animation: undo-countdown 5s linear 0.4s forwards;
}

@keyframes undo-countdown {
    to {
        --undo-progress: 0%;
    }
}

/* not supported by all browsers */
.truncate {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* error */
#blazor-error-ui {
    color-scheme: light dark;
    background: #910707;
    color: white;
    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;

    .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
}

.blazor-error-boundary {
    background: #910707;
    padding: 1rem;
    color: white;

    ::after {
        content: "An error has occurred."
    }
}

/* loading */
.loading-progress {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 9999;
    width: 100%;
    height: 0.5rem;
    overflow: hidden;
}

.loading-progress-bar {
    height: 100%;
    width: 0;
    background-color: #FF5FA8;
    background-image: linear-gradient(
            45deg,
            rgba(255, 255, 255, 0.25) 25%,
            transparent 25%,
            transparent 50%,
            rgba(255, 255, 255, 0.25) 50%,
            rgba(255, 255, 255, 0.25) 75%,
            transparent 75%,
            transparent
    );
    background-size: 1rem 1rem;
    animation: loading-progress-bar-stripes 1s linear infinite;
    transition: width 0.2s ease;
}

.loading-container {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem;
    box-sizing: border-box;
    background: #732a9b;
    background: linear-gradient(133deg, rgba(115, 42, 155, 1) 0%, rgba(206, 130, 209, 1) 50%, rgba(222, 164, 214, 1) 100%);

    @supports (height: 100dvh) {
        min-height: 100dvh;
    }
}

.loading-logo {
    display: block;
    width: min(70vw, 512px);
    height: auto;
    max-height: 70vh;
    object-fit: contain;
}

@keyframes loading-progress-bar-stripes {
    from {
        background-position-x: 1rem;
    }
    to {
        background-position-x: 0;
    }
}

/* collection of a book of a shelf (ShelfBookDialog): its suggestion or its fields, on the background of the info
   alerts */
.collection-panel {
    background-color: var(--mud-palette-info-hover);
    border-radius: var(--mud-default-borderradius);
    padding: 8px 12px;
}
