.drag-handle {
    cursor: grab;
    touch-action: none;
}

.drag-handle:active { cursor: grabbing; }

.flex-1 { flex: 1; }

.shopping-row {
    cursor: pointer;
    min-height: 48px;
    -webkit-tap-highlight-color: transparent;
}

/* Winkels: duidelijke edit-affordance op de winkelnaam (omlijning + focus-state)
   zodat zichtbaar is dat de rij aantikbaar/bewerkbaar is, i.p.v. alleen het
   potlood-icoon. */
.store-name-edit {
    cursor: pointer;
    border: 1px solid transparent;
    border-radius: 4px;
    padding: 4px 8px;
    margin: -4px -8px;
    min-height: 48px;
    display: flex;
    align-items: center;
    -webkit-tap-highlight-color: transparent;
}

.store-name-edit:hover,
.store-name-edit:focus-visible {
    border-color: var(--mud-palette-lines-inputs);
    outline: none;
}

/*
 * Afvinken: de naam van een afgevinkt item vervaagt en krijgt een doorhaling. Beide
 * horen kort te animeren i.p.v. te springen, zodat zichtbaar is dát er iets afgevinkt
 * is — ook als je net ergens anders keek. De doorhaling zelf is niet animeerbaar
 * (text-decoration kent geen tussenstanden), dus de streep staat altijd al klaar en
 * alleen zijn kleur gaat van doorzichtig naar zichtbaar. Opacity is de hoofdcue.
 * De afgevinkte staat komt van .mud-list-item-checked op de MudListItem (zie
 * ShoppingList.razor), zodat hier geen inline-style meer voor nodig is.
 */
.shopping-item-name {
    text-decoration: line-through;
    text-decoration-color: transparent;
    transition: opacity 180ms ease, text-decoration-color 180ms ease;
}

.mud-list-item-checked .shopping-item-name {
    opacity: 0.5;
    text-decoration-color: currentColor;
}

/*
 * Badge-puls: speelt eenmalig af zodra er een product bíj komt in "nog indelen"
 * (bijvoorbeeld direct na een recept-import) — bewust geen doorlopende knipper, dat
 * leidt af bij het boodschappen doen.
 *
 * De klasse wordt niet weer verwijderd; hij blijft staan zodra de teller één keer is
 * gestegen. Dat mag, want animation-fill-mode staat op de standaard `none`: na de
 * laatste iteratie valt het element terug op zijn normale weergave. Het opnieuw
 * afspelen komt niet van deze klasse maar van de @key in BottomNav.razor: die draagt
 * de puls-teller mee, zodat Blazor het badge-element bij elke stijging opnieuw opbouwt
 * en de animatie op dat verse element vanaf nul begint.
 */
.badge-pulse {
    animation: badge-pulse 500ms ease-out 2;
}

@keyframes badge-pulse {
    0%   { transform: scale(1); }
    35%  { transform: scale(1.3); }
    100% { transform: scale(1); }
}

/*
 * Beide micro-animaties zijn versiering: wie om minder beweging vraagt, krijgt de
 * eindstand meteen. De doorhaling blijft dan gewoon werken (alleen zonder overgang).
 * De puls valt hier helemaal weg: de klasse staat er dan nog wel op (BottomNav haalt
 * hem nooit weg), maar zonder animatie is die zichtbaar een no-op.
 */
@media (prefers-reduced-motion: reduce) {
    .shopping-item-name { transition: none; }
    .badge-pulse        { animation: none; }
}

.bottom-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    justify-content: space-around;
    align-items: stretch;
    height: calc(60px + env(safe-area-inset-bottom));
    padding-bottom: env(safe-area-inset-bottom);
    background-color: var(--mud-palette-surface);
    border-top: 1px solid var(--mud-palette-lines-default);
    z-index: 1300;
}

.bottom-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    flex: 1;
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
}

/* Vijf tabs op 390px: elk label krijgt ~78px; nooit laten omslaan naar twee regels. */
.bottom-nav-item .mud-typography { white-space: nowrap; letter-spacing: 0; }

/*
 * Dialogen full-screen op xs-schermen (<600px, zelfde grens als MudBlazor's
 * eigen sm-breakpoint) — alleen voor dialogen die er zelf voor kiezen via
 * Class="dialog-fullscreen-xs" op hun <MudDialog> (nu: ProductDialog,
 * RecipeDialog), niet voor alle dialogen (MudMessageBox-bevestigingen,
 * EditListItemDialog, enz. horen niet full-screen te gaan voor één zin en
 * twee knoppen). MudDialogProvider in MainLayout blijft de enige plek waar
 * dialooggedrag globaal wordt geconfigureerd (bewust, zie Fase B) —
 * DialogOptions.FullScreen is een gewone bool en dus niet breakpoint-bewust,
 * dus dit gaat hier CSS-only, gericht op de opt-in klasse. Selector heeft
 * bewust twee klassen (specificiteit 0,2,0) zodat hij MudBlazor's eigen
 * .mud-dialog-width-sm/.mud-dialog-width-full-regels (0,1,0) verslaat op
 * specificiteit, niet alleen op laadvolgorde. Center (de standaardpositie,
 * overal in deze app) heeft zelf geen padding om te strippen, dus de
 * .mud-dialog-container hoeft hier niet aangepast te worden.
 */
@media (max-width: 599px) {
    .mud-dialog.dialog-fullscreen-xs {
        width: 100%;
        height: 100%;
        max-width: 100%;
        max-height: none;
        margin: 0;
        border-radius: 0;
        overflow-y: hidden;
    }
}
/*
 * Winkelfilter-chips boven de lijst. Bewust NIET sticky: de quick-add erboven is al
 * het enige vaste element op deze pagina, en twee vaste rijen eten op een 390px-scherm
 * het halve zicht op de lijst op. De chips scrollen dus gewoon mee weg.
 * min-height houdt ze op een fatsoenlijk tap-target, ook in de Medium-maat.
 */
.store-filter .mud-chip {
    min-height: 36px;
}

/* Eén rij die zijwaarts scrollt i.p.v. omvouwen: op een telefoon kost elke extra
   rij boven de lijst schermruimte. Scrollbar verborgen; de afgekapte laatste chip is
   de affordance dat er meer is. */
.store-filter { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; margin-left: -12px; margin-right: -12px; padding-left: 12px; padding-right: 12px; }
.store-filter::-webkit-scrollbar { display: none; }
.store-filter .mud-chip { flex: 0 0 auto; }

/* Actiebalk lijstpagina: twee knoppen + menu moeten op 390px op één regel passen.
   Geen hoofdletters en geen iconen — dat scheelt net de ruimte die anders ontbreekt. */
.list-actions .mud-button-root { text-transform: none; white-space: nowrap; min-width: 0; padding-left: 8px; padding-right: 8px; }

/*
 * Ruimte onder de pagina-inhoud voor de vaste bottom-nav (60px + safe-area) plus wat lucht.
 * !important omdat MudBlazor's pa-3/pa-sm-4 op dezelfde container ook !important zijn en
 * anders winnen op laadvolgorde; de inline stijl die hier eerder stond verloor daarvan.
 */
.page-content {
    padding-bottom: calc(84px + env(safe-area-inset-bottom)) !important;
}

/*
 * Receptdialoog, ingrediëntregels: twee regels per ingrediënt. De hoeveelheid/eenheid-regel
 * springt in tot onder de naam (drag-handle 24 + gap 8 + checkbox 32 + gap 8 = 72px) en de
 * velden hebben vaste breedtes, zodat de rij nooit breder wordt dan het dialoog. Het
 * eerdere <style>-blok in RecipeDialog.razor kapte de eenheid met max-width:90px af.
 */
.recipe-item { padding: 4px 0; }
.recipe-item + .recipe-item { border-top: 1px solid var(--mud-palette-lines-default); }
.recipe-item-qty { padding-left: 72px; }
.recipe-item-amount { width: 84px; flex: 0 0 auto; }
.recipe-item-amount input { text-align: right; }
.recipe-item-unit { width: 100px; flex: 0 0 auto; }

/*
 * Compacte velden in de hoeveelheid/eenheid-rij: MudBlazor's outlined input is 56px hoog
 * (18,5px padding boven en onder om het label; "Dense" zet in 9.9 geen eigen klasse op het
 * input-element). Hier 8px, dus ~35px: secundaire velden onder de naam, geen formulier.
 * De mask-image hoort bij de label-inkeping; deze velden hebben geen label, maar de waarde
 * moet meeschuiven met de padding, anders blijft de bovenrand van de tekst onzichtbaar.
 */
.recipe-item-qty input.mud-input-root-outlined,
.recipe-item-qty div.mud-input-slot.mud-input-root-outlined {
    padding-top: 8px;
    padding-bottom: 8px;
    mask-image: linear-gradient(to bottom, transparent 8px, black 8px);
}

/*
 * Importpreview: dezelfde compacte velden als het receptdialoog (zie .recipe-item-qty):
 * hoeveelheid, eenheid en naam per ingrediëntregel van 56px naar ~35px. Deze velden
 * hebben geen label; de mask-image laat de waarde meeschuiven met de padding.
 */
.import-line-fields input.mud-input-root-outlined,
.import-line-fields div.mud-input-slot.mud-input-root-outlined {
    padding-top: 8px;
    padding-bottom: 8px;
    mask-image: linear-gradient(to bottom, transparent 8px, black 8px);
}

/*
 * Importpreview op 390px (gemeld na de vorige fix): MudBlazor's inputwrapper negeert een
 * inline breedte op het input-element en groeit toch breder dan Style="width:...", waardoor
 * hoeveelheid en eenheid samen bijna de hele rij opeisten en het naamveld tot ~1 teken
 * kromp. Zelfde oplossing als het receptdialoog (recipe-item-amount/-unit): naam op een
 * eigen regel, hoeveelheid/eenheid op vaste breedte met flex: 0 0 auto eronder.
 */
.import-line-name { width: 100%; }
.import-line-amount { width: 84px; flex: 0 0 auto; }
.import-line-amount input { text-align: right; }
.import-line-unit { width: 100px; flex: 0 0 auto; }

/*
 * Scrollen op de lijstpagina (gemeld 2026-09-06): MudBlazor zet touch-action:none op elke
 * MudSwipeArea, en elke rij is er een. De browser mag dan op een rij niet verticaal
 * pannen: de rij licht op, de pagina blijft staan. pan-y geeft verticaal scrollen terug
 * aan de browser; horizontale swipes (afvinken/verwijderen) komen nog steeds als
 * pointer-events bij MudSwipeArea aan, want alleen verticaal wordt door de browser
 * geclaimd. !important omdat dit MudBlazor's eigen regel moet verslaan, ongeacht laadvolgorde.
 */
.mud-swipearea {
    touch-action: pan-y !important;
}

/*
 * Weekmenu. Dagregels zijn flex-rijen van vaste hoogte; de inhoud kapt af met een ellipsis
 * zodat een lange receptnaam de knoppen rechts nooit van het scherm drukt (390px).
 */
.weekmenu-header .weekmenu-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.weekmenu-daychips { display: flex; }
.weekmenu-daychips .mud-chip { flex: 1; justify-content: center; margin: 0; min-width: 0; padding: 0 4px; }
.weekmenu-day {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 48px;
    padding: 4px 4px 4px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}
.weekmenu-day .drag-handle { flex: none; }
.weekmenu-day-label { width: 44px; flex: none; }
.weekmenu-day-content { flex: 1; min-width: 0; cursor: pointer; display: flex; align-items: center; }
.weekmenu-day-content .mud-typography { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.weekmenu-day.day-off { opacity: .45; }
.weekmenu-day.day-off .weekmenu-day-content { cursor: default; }
.weekmenu-day.day-today { background: var(--mud-palette-primary-hover); border-radius: 4px; }
.weekmenu-roll-placeholder { width: 40px; height: 40px; flex: none; }
