/* IBM Plex Sans, hosted locally (SIL Open Font License, see fonts/ibm-plex-sans/LICENSE.txt). Latin + latin-ext, weights 400/500/600. */
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('fonts/ibm-plex-sans/ibm-plex-sans-latin-ext-400-normal.woff2') format('woff2');
    unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('fonts/ibm-plex-sans/ibm-plex-sans-latin-400-normal.woff2') format('woff2');
    unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('fonts/ibm-plex-sans/ibm-plex-sans-latin-ext-500-normal.woff2') format('woff2');
    unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('fonts/ibm-plex-sans/ibm-plex-sans-latin-500-normal.woff2') format('woff2');
    unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('fonts/ibm-plex-sans/ibm-plex-sans-latin-ext-600-normal.woff2') format('woff2');
    unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
    font-family: 'IBM Plex Sans';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('fonts/ibm-plex-sans/ibm-plex-sans-latin-600-normal.woff2') format('woff2');
    unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

/* The theme (MainLayout) sets the font family through MudBlazor's variable; Bootstrap's own font is only the fallback. */
html, body {
    font-family: var(--mud-typography-default-family, 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif);
}

/* Figures line up under each other in every table. */
.mud-table-cell {
    font-variant-numeric: tabular-nums;
}

/* ===== Theme: app bar, menu ===== */
.kz-appbar {
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.kz-appbar .kz-appbar-title {
    font-size: 16px;
    font-weight: 600;
    line-height: 1.25;
}

.mud-navmenu .mud-nav-link {
    min-height: 36px;
    padding: 0 10px;
    margin: 2px 0;
    border-radius: 8px;
}

.mud-navmenu .mud-nav-link .mud-nav-link-text {
    font-size: 0.9rem;
}

.mud-navmenu .mud-nav-link .mud-icon-root {
    font-size: 20px;
    width: 20px;
    height: 20px;
}

.mud-navmenu .mud-nav-link:hover:not(.mud-nav-link-disabled) {
    background-color: var(--brand-hover, var(--mud-palette-action-default-hover));
}

/* Active row: rounded, tinted with the brand colour (a section link: 14% of its own colour).
   app.css loads BEFORE MudBlazor.min.css, and MudBlazor styles the active row (specificity 5), its :hover (7) and
   :focus-visible/:active (7) with `.mud-navmenu.mud-navmenu-default ...`. Equal specificity would lose on order, so every
   rule below mirrors that selector and adds `.mud-nav-item >` (+1; a section link `.mud-nav-item.kz-nav-section >`, +2).
   ThemeFilesTests guards this prefix. */
.mud-navmenu.mud-navmenu-default .mud-nav-item > .mud-nav-link.active:not(.mud-nav-link-disabled),
.mud-navmenu.mud-navmenu-default .mud-nav-item.kz-nav-current > .mud-nav-link:not(.mud-nav-link-disabled) {
    border-inline-end-width: 0;
    background-color: var(--brand-soft, var(--mud-palette-primary-hover));
    color: var(--mud-palette-text-primary);
    font-weight: 600 !important; /* MudBlazor sets 500 !important on the active link */
}

.mud-navmenu.mud-navmenu-default .mud-nav-item > .mud-nav-link.active:not(.mud-nav-link-disabled):hover:not(.mud-nav-link-disabled),
.mud-navmenu.mud-navmenu-default .mud-nav-item > .mud-nav-link.active:not(.mud-nav-link-disabled):focus-visible:not(.mud-nav-link-disabled),
.mud-navmenu.mud-navmenu-default .mud-nav-item > .mud-nav-link.active:not(.mud-nav-link-disabled):active:not(.mud-nav-link-disabled) {
    background-color: var(--brand-soft, var(--mud-palette-primary-hover));
}

/* Menu links of a section (Klanten, Leveranciers, Aanvragen, Werkorders, Taken, Agenda, Mails): own icon colour, set per item as --nav-c.
   MudNavLink puts Class and Style on its wrapper (.mud-nav-item), the anchor inherits the variable. */
.mud-navmenu .kz-nav-section > .mud-nav-link:not(.mud-nav-link-disabled) .mud-nav-link-icon,
.mud-navmenu .kz-nav-section > .mud-nav-link:not(.mud-nav-link-disabled) .mud-icon-root {
    color: var(--nav-c);
}

.mud-navmenu.mud-navmenu-default .mud-nav-item.kz-nav-section > .mud-nav-link.active:not(.mud-nav-link-disabled),
.mud-navmenu.mud-navmenu-default .mud-nav-item.kz-nav-section > .mud-nav-link.active:not(.mud-nav-link-disabled):hover:not(.mud-nav-link-disabled),
.mud-navmenu.mud-navmenu-default .mud-nav-item.kz-nav-section > .mud-nav-link.active:not(.mud-nav-link-disabled):focus-visible:not(.mud-nav-link-disabled),
.mud-navmenu.mud-navmenu-default .mud-nav-item.kz-nav-section > .mud-nav-link.active:not(.mud-nav-link-disabled):active:not(.mud-nav-link-disabled),
/* The current section on a page outside the link's prefix (NavMenu: Klanten on /customers/...): the same look as the active row. */
.mud-navmenu.mud-navmenu-default .mud-nav-item.kz-nav-section.kz-nav-current > .mud-nav-link:not(.mud-nav-link-disabled),
.mud-navmenu.mud-navmenu-default .mud-nav-item.kz-nav-section.kz-nav-current > .mud-nav-link:not(.mud-nav-link-disabled):hover {
    background-color: color-mix(in srgb, var(--nav-c) 14%, transparent);
}

a, .btn-link {
    color: #006bb7;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA9NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

.mail-body-mud {
    display: block;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    overflow-wrap: break-word;
    word-break: break-word;
    font-size: 1rem; /* matches MudBlazor body1 */
    line-height: 1.5;
}

.mail-body-mud--pre {
    white-space: pre-wrap; /* preserve line breaks for plain text */
    margin: 0;
    font-family: inherit;
}


/* Icon overlay */
.image-wrapper {
    position: relative;
}

.selected-icon {
    position: absolute;
    top: 6px;
    right: 6px;
    background: white;
    border-radius: 50%;
}
.blur {
    backdrop-filter: blur(10px);
}

.dialog-background {
    background-color: transparent;
}

.dialog-background-title {
    background: rgba(var(--mud-palette-info-rgb), 0.5);
    color: var(--mud-palette-white);
}

.dialog-background-surface {
    background: rgba(var(--mud-palette-surface-rgb), 0.75);
}

/* Center image and label inside the MudPaper */
.media-item,
.media-item-selected {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.75rem;
    box-sizing: border-box;
    min-height: 200px; /* adjust as needed for visual balance */
    text-align: center;
}

.media-item-selected {
    border: 2px solid rgba(var(--mud-palette-primary-rgb), 0.6);
    border-radius: 8px;
    background: rgba(var(--mud-palette-primary-rgb), 0.03);
}

/* ===== Theme: overview page header and table (Klanten, Leveranciers, Aanvragen, Werkorders, Taken, Mails) =====
   PageHeader and the MudTable of an overview (Class="kz-overview") both carry ThemeColors.SectionStyle as inline style:
   --sc (section colour), --sc-head (column header background), --sc-text (column header text, mixed darker so it reaches 4.5:1).
   Nothing here touches other MudTables: every table rule starts with .kz-overview. */
.kz-page-header {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}

.kz-page-header .kz-page-header-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 36px;
    height: 36px;
    border-radius: 9px;
    background-color: color-mix(in srgb, var(--sc) 16%, var(--mud-palette-surface));
    color: var(--sc);
}

.kz-page-header .kz-page-header-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.kz-page-header .kz-page-header-title {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 600;
    line-height: 1.3;
}

.kz-page-header .kz-page-header-subtitle {
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary);
}

/* Column headers: light tint of the section colour, darkened section text, a 2 px line in the section colour underneath.
   MudBlazor styles the header cell with `.mud-table-root .mud-table-head .mud-table-cell` (3 classes) and the dense padding with
   `.mud-table-dense * .mud-table-row .mud-table-cell` (3 classes); app.css loads first, so each rule here has 4 classes or more. */
.kz-overview .mud-table-root .mud-table-head .mud-table-row .mud-table-cell {
    background-color: var(--sc-head);
    color: var(--sc-text);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    border-bottom: 2px solid var(--sc);
}

/* Sort labels keep the header colour (the hover dimming of MudBlazor would drop the text below 4.5:1). */
.kz-overview .mud-table-root .mud-table-head .mud-table-row .mud-table-cell .mud-table-sort-label.mud-clickable:hover {
    opacity: 1;
    text-decoration: underline;
}

/* Calm body: lines between rows only (the pages no longer set Bordered/Striped), ~40 px rows set by padding, never by a fixed
   height: below 600 px MudBlazor turns every cell into a flexbox (.mud-xs-table) and a fixed height would let long text overflow. */
.kz-overview .mud-table-root .mud-table-body .mud-table-row .mud-table-cell {
    padding-top: 9.5px;
    padding-bottom: 9.5px;
}

/* Phone (MudTable Breakpoint.Xs, the default): label and value per cell, a cell grows with its text. */
@media (max-width: 600px) {
    .kz-overview.mud-xs-table .mud-table-root .mud-table-body .mud-table-row .mud-table-cell {
        padding-top: 8px;
        padding-bottom: 8px;
        height: auto;
        min-height: 40px;
    }
}

/* A group row (MudTable GroupBy) is a light band. */
.kz-overview .mud-table-root .mud-table-body .mud-table-row .mud-table-cell.mud-table-group-indent,
.kz-overview .mud-table-root .mud-table-body .mud-table-row.mud-table-row-group .mud-table-cell {
    background-color: var(--mud-palette-background-gray);
}

/* Tweestapsverificatie (2FA, plan rollen-en-rechten-beheer §6.12): the setup steps, the QR code (always black on white, whatever the theme, or
   phones cannot read it; drawn by js/qr.js), the key to type over and the recovery codes. */
.kz-steps { padding-left: 20px; margin: 0; }
.kz-steps > li { margin-bottom: 16px; }
.kz-qr {
    width: 200px;
    max-width: 100%;
    aspect-ratio: 1 / 1;
    margin: 8px 0;
    background: white;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
}
.kz-qr svg { display: block; width: 100%; height: 100%; }
.kz-key { font-size: .9rem; word-break: break-all; }
.kz-hint { margin-top: 4px; font-size: .8125rem; color: var(--mud-palette-text-secondary); }
.kz-recovery-codes {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 8px;
}
.kz-recovery-codes code {
    font-size: 1rem;
    padding: 4px 8px;
    text-align: center;
    background: var(--mud-palette-background-gray);
    border-radius: 4px;
}

/* ===== Mail verzenden: the compose window (module MailVerzenden, MailComposeDialog) =====
   A MudDialog rendered by MudDialogProvider, outside the layout: only theme variables (--mud-palette-*), no hex, so it follows light and dark.
   Text that carries meaning (an error) is the error colour mixed towards the text colour, like .kz-text-error (>= 4.5:1, pinned by MailComposeThemeTests).
   Phone rules (<= 600 px): the window is the whole screen, Voorbeeld/Cc/Bcc move behind a menu, every tap target is at least 40 px, nothing scrolls sideways. */
.mud-dialog.kz-mail-dialog {
    max-height: calc(100dvh - 32px);
}

.kz-mail-dialog .kz-mail-content {
    overflow-y: auto;
    overflow-x: hidden;
}

.kz-mail {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
}

.kz-mail-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.kz-mail-label {
    font-size: 0.875rem;
    font-weight: 600;
}

.kz-mail-caption,
.kz-mail-help {
    color: var(--mud-palette-text-secondary);
    font-size: 0.8125rem;
}

.kz-mail-from {
    border-bottom: 1px solid var(--mud-palette-lines-default);
    padding-bottom: 8px;
    overflow-wrap: anywhere;
}

.kz-mail-banner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 16px;
    padding: 10px 12px;
    border-radius: var(--mud-default-borderradius);
    border: 1px solid var(--mud-palette-error);
    background-color: color-mix(in srgb, var(--mud-palette-error) 10%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--mud-palette-error) 35%, var(--mud-palette-text-primary));
}

.kz-mail-banner-text {
    flex: 1 1 260px;
    min-width: 0;
    overflow-wrap: anywhere;
}

.kz-mail-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    min-height: 44px;
    padding: 6px 8px;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: var(--mud-default-borderradius);
    background-color: var(--mud-palette-surface);
}

/* A visible focus ring: 2px in the text colour (at least 3:1 against the surface in both palettes, whatever the brand colour is). */
.kz-mail-chips:focus-within {
    border-color: var(--mud-palette-primary);
    outline: 2px solid var(--mud-palette-text-primary);
    outline-offset: 1px;
}

.kz-mail-chip {
    display: inline-flex;
    align-items: center;
    max-width: 100%;
    min-height: 32px;
    padding: 0 2px 0 10px;
    border-radius: 16px;
    background-color: color-mix(in srgb, var(--mud-palette-primary) 12%, var(--mud-palette-surface));
    color: var(--mud-palette-text-primary);
}

.kz-mail-chip-text {
    min-width: 0;
    overflow-wrap: anywhere;
}

.kz-mail-chip .kz-mail-chip-close {
    min-width: 32px;
    min-height: 32px;
}

.kz-mail-chip-invalid {
    border: 1px solid var(--mud-palette-error);
    background-color: color-mix(in srgb, var(--mud-palette-error) 12%, var(--mud-palette-surface));
}

.kz-mail-input {
    flex: 1 1 160px;
    min-width: 120px;
    min-height: 32px;
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--mud-palette-text-primary);
    font: inherit;
}

.kz-mail-suggest {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
}

.kz-mail-suggest-btn {
    display: inline-flex;
    align-items: center;
    min-height: 32px;
    padding: 0 10px 0 6px;
    border: 1px dashed var(--mud-palette-lines-inputs);
    border-radius: 16px;
    background: transparent;
    color: var(--mud-palette-text-primary);
    font: inherit;
    cursor: pointer;
}

.kz-mail-suggest-btn:hover,
.kz-mail-suggest-btn:focus-visible {
    border-color: var(--mud-palette-primary);
    background-color: color-mix(in srgb, var(--mud-palette-primary) 8%, var(--mud-palette-surface));
}

.kz-mail-error {
    margin-top: 4px;
    font-size: 0.8125rem;
    color: color-mix(in srgb, var(--mud-palette-error) 50%, var(--mud-palette-text-primary));
    overflow-wrap: anywhere;
}

.kz-mail-toggles {
    display: flex;
    gap: 12px;
    align-items: center;
}

.kz-mail-toggle {
    min-height: 32px;
    padding: 0 8px;
    border: 0;
    background: transparent;
    color: var(--mud-palette-primary);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.kz-mail-phone-only {
    display: none;
}

.kz-mail-signature pre,
.kz-mail-preview-body {
    margin: 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-family: inherit;
}

.kz-mail-signature {
    padding: 8px 12px;
    border-left: 3px solid var(--mud-palette-lines-default);
    color: var(--mud-palette-text-secondary);
}

.kz-mail-attachments {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
}

.kz-mail-select,
.kz-mail-title {
    min-width: 0;
    max-width: 100%;
    overflow-wrap: anywhere;
}

.kz-mail-preview-files {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
    margin-top: 8px;
}

.kz-mail-file-row {
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: 40px;
}

.kz-mail-file-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}

.kz-mail-file {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-right: 12px;
}

.kz-mail-preview-head {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 4px 12px;
    margin: 8px 0;
}

.kz-mail-preview-head dt {
    color: var(--mud-palette-text-secondary);
}

.kz-mail-preview-head dd {
    margin: 0;
    overflow-wrap: anywhere;
}

.kz-mail-preview-body {
    padding: 12px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius);
}

.kz-mail-confirm {
    padding: 12px;
    border: 1px solid var(--mud-palette-warning);
    border-radius: var(--mud-default-borderradius);
    overflow-wrap: anywhere;
}

.kz-mail-confirm-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.kz-mail-sending {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

@media (max-width: 600px) {
    /* The whole screen: no margin, no rounded corners, as high as the visible screen (dvh follows the phone's address bar). */
    .mud-dialog.kz-mail-dialog {
        width: 100vw;
        max-width: 100vw;
        height: 100dvh;
        max-height: 100dvh;
        margin: 0;
        border-radius: 0;
    }

    .kz-mail-dialog .kz-mail-content {
        flex: 1 1 auto;
        padding-left: 12px;
        padding-right: 12px;
    }

    /* Voorbeeld, Cc and Bcc live behind the menu of the window. */
    .kz-mail-desktop-only {
        display: none !important;
    }

    .kz-mail-phone-only {
        display: inline-flex;
    }

    .kz-mail-chip,
    .kz-mail-suggest-btn,
    .kz-mail-file-row,
    .kz-mail-toggle {
        min-height: 40px;
    }

    .kz-mail-chip .kz-mail-chip-close {
        min-width: 40px;
        min-height: 40px;
    }

    .kz-mail-actions {
        flex-wrap: wrap;
        gap: 8px;
    }

    .kz-mail-preview-head {
        grid-template-columns: 1fr;
    }
}

/* ===== Mail verzenden: the history tab and the detail of a sent mail (phase 3) =====
   Still the block of the compose window above (it is scanned up to the "Theme: offer screen" block): theme variables only, no hex.
   A status is never colour alone: the word is always there. The pill is the status colour mixed into the surface (background) and into the text colour
   (text), the same recipe as the warning pill of the offer screen, so it reaches 4.5:1 in the light and the dark palette (pinned by MailHistoryThemeTests).
   Phone (<= 600 px): MudTable turns a row into a card by itself; filters and buttons get 40 px tap targets and nothing scrolls sideways. */
.kz-mail-history {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
}

.kz-mail-history-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
}

.kz-mail-filters {
    display: inline-flex;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: var(--mud-default-borderradius);
    overflow: hidden;
}

.kz-mail-filter {
    min-height: 36px;
    padding: 0 14px;
    border: 0;
    background: transparent;
    color: var(--mud-palette-text-primary);
    font: inherit;
    cursor: pointer;
}

.kz-mail-filter + .kz-mail-filter {
    border-left: 1px solid var(--mud-palette-lines-inputs);
}

.kz-mail-filter[aria-pressed="true"] {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 12%, var(--mud-palette-surface));
    font-weight: 600;
    box-shadow: inset 0 -2px 0 var(--mud-palette-primary);
}

.kz-mail-filter:focus-visible {
    outline: 2px solid var(--mud-palette-text-primary);
    outline-offset: -2px;
}

.kz-mail-filter:disabled {
    cursor: default;
    opacity: 0.6;
}

.kz-mail-history-count {
    margin-left: auto;
    color: var(--mud-palette-text-primary);
    font-size: 0.875rem;
}

.kz-mail-empty {
    padding: 24px 12px;
    text-align: center;
}

.kz-mail-table {
    width: 100%;
}

.kz-mail-direction {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    white-space: nowrap;
}

.kz-mail-cell-text {
    overflow-wrap: anywhere;
}

.kz-mail-row-actions {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.kz-mail-history-more {
    display: flex;
    justify-content: center;
}

.kz-mail-status {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 500;
    white-space: nowrap;
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 8%, var(--mud-palette-surface));
    color: var(--mud-palette-text-primary);
}

.kz-mail-status-sent {
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 8%, var(--mud-palette-surface));
    color: var(--mud-palette-text-primary);
}

.kz-mail-status-received {
    background-color: color-mix(in srgb, var(--mud-palette-info) 18%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--mud-palette-info) 25%, var(--mud-palette-text-primary));
}

.kz-mail-status-failed {
    background-color: color-mix(in srgb, var(--mud-palette-error) 18%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--mud-palette-error) 25%, var(--mud-palette-text-primary));
}

.kz-mail-status-wait {
    background-color: color-mix(in srgb, var(--mud-palette-warning) 18%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--mud-palette-warning) 25%, var(--mud-palette-text-primary));
}

.kz-mail-detail-status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
}

.kz-mail-detail-status-text {
    min-width: 0;
    overflow-wrap: anywhere;
}

.kz-mail-detail-body {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    padding: 12px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius);
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 3%, var(--mud-palette-surface));
    color: var(--mud-palette-text-primary);
}

.kz-mail-detail-signature {
    color: var(--mud-palette-text-secondary);
}

.kz-mail-link {
    color: var(--mud-palette-text-primary);
    text-decoration: underline;
}

.kz-mail-link:focus-visible {
    outline: 2px solid var(--mud-palette-text-primary);
    outline-offset: 2px;
}

@media (max-width: 600px) {
    .kz-mail-history-bar > .mud-button-root {
        width: 100%;
        min-height: 40px;
    }

    .kz-mail-filters {
        width: 100%;
    }

    .kz-mail-filter {
        flex: 1 1 0;
        min-height: 40px;
    }

    .kz-mail-history-count {
        margin-left: 0;
    }

    .kz-mail-row-actions .mud-icon-button {
        min-width: 40px;
        min-height: 40px;
    }
}

/* ===== Mail verzenden: the aanvraag (phase 4) =====
   Still the block of the compose window above (scanned up to the "Theme: offer screen" block): theme variables only, no hex. The block "E-mail met offerte"
   on the Info tab sits under the description like the house photos; the offer attachment row of the compose window reuses .kz-mail-file-row. A failed attempt is
   never colour alone (the sentence says so); its text is the error colour mixed into the text colour (>= 4.5:1 in both palettes, pinned by MailOfferThemeTests).
   Phone (<= 600 px): the buttons wrap and get 40 px tap targets. */
.kz-mail-offer {
    margin-top: 16px;
    padding: 12px 16px;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: var(--mud-default-borderradius);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    min-width: 0;
}

.kz-mail-offer-title {
    margin: 0 0 8px;
    font-size: 1rem;
    font-weight: 600;
}

.kz-mail-offer p {
    margin: 0 0 8px;
    overflow-wrap: anywhere;
}

.kz-mail-offer-failed {
    color: color-mix(in srgb, var(--mud-palette-error) 50%, var(--mud-palette-text-primary));
}

.kz-mail-offer-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 4px;
}

.kz-mail-file-row .mud-button-root {
    min-height: 36px;
}

@media (max-width: 600px) {
    .kz-mail-offer-actions .mud-button-root {
        min-height: 40px;
    }
}

/* ===== Mail verzenden: the overview "Verzonden" (phase 5) =====
   Still the block of the compose window above (scanned up to the "Theme: offer screen" block): theme variables only, no hex. The table is the overview table of the
   Mails section (kz-overview); the status pills are those of the history tab. The filters sit in one row on a wide screen and one under the other on a phone
   (<= 600 px), where MudTable turns a row into a card by itself and the row actions get a 40 px tap target. */
.kz-sent-filters {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
    gap: 8px 16px;
    align-items: end;
    margin-bottom: 12px;
}

.kz-sent-filters > * {
    min-width: 0;
}

@media (max-width: 960px) {
    .kz-sent-filters {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }
}

@media (max-width: 600px) {
    .kz-sent-filters {
        grid-template-columns: minmax(0, 1fr);
    }

    .kz-overview .kz-mail-cell-text {
        overflow-wrap: anywhere;
    }
}

/* ===== Mail verzenden: Beheer and the templates (phase 6) =====
   Still the block of the compose window above (scanned up to the "Theme: offer screen" block): theme variables only, no hex. The checklist under the sending settings
   (Beheer, Organisatie) says what is in order, what still has to be done and what can not be known without a real answer of Microsoft 365: the state is always a WORD in the
   text, never only a colour or a mark (the mark is aria-hidden). The test-mail result in the error colour reuses .kz-mail-offer-failed (contrast pinned elsewhere); a result
   that went well is plain text colour. The templates page has a form (name and kind side by side, one under the other on a phone) and a plain table. Phone (<= 600 px):
   buttons and row actions get 40 px tap targets. */
.kz-mail-checklist {
    list-style: none;
    margin: 0 0 12px;
    padding: 0;
}

.kz-mail-check {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    padding: 6px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    overflow-wrap: anywhere;
}

.kz-mail-check-mark {
    flex: none;
    width: 22px;
    height: 22px;
    line-height: 20px;
    text-align: center;
    border: 2px solid var(--mud-palette-text-primary);
    border-radius: 50%;
    font-weight: 700;
    font-size: 0.8rem;
}

.kz-mail-check-done .kz-mail-check-mark {
    background-color: var(--mud-palette-text-primary);
    color: var(--mud-palette-surface);
}

.kz-mail-check-open .kz-mail-check-mark {
    border-style: dashed;
}

.kz-mail-check-unknown .kz-mail-check-mark {
    border-style: dotted;
}

.kz-mail-check-state {
    font-weight: 600;
}

.kz-mail-test-ok {
    font-weight: 600;
    overflow-wrap: anywhere;
}

.kz-mail-steps {
    margin-top: 12px;
}

.kz-mail-steps summary {
    cursor: pointer;
    font-weight: 600;
}

.kz-mail-steps ol {
    margin: 8px 0 0;
    padding-left: 22px;
}

.kz-template-form {
    margin-bottom: 16px;
}

.kz-template-grid {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: 8px 16px;
}

.kz-template-grid > * {
    min-width: 0;
}

@media (max-width: 600px) {
    .kz-template-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .kz-mail-admin .mud-button-root {
        min-height: 40px;
    }

    .kz-template-form .mud-button-root {
        min-height: 40px;
    }
}

/* The ⋮ menu of a line of the table Offerteregels (plan offerteregel-productregel 9): every item 44 px for a finger. The items are drawn by MudPopoverProvider outside the
   component, so a scoped rule does not reach them; the menu carries PopoverClass="offer-line-popover". */
.offer-line-popover .mud-menu-item {
    min-height: 44px;
}

/* ===== Offer line dialog (plan productregel-dialogs 3.9) =====
   MudDialog draws the box of the dialog outside the component, so the scoped CSS of OfferLineDialog does not reach it; the dialog carries Class="kz-line-dialog".
   The dialog always fills the screen, on every width, with a fixed height, so it does not change size per tab or content (plan productregel-1e 3.7, decision 19-10;
   it replaces "full screen under 1280 px" of plan 1d). FullScreen of DialogOptions asks for it as well; this rule holds it when FullScreen works out otherwise in another
   MudBlazor version. The head (the title) and the foot (Annuleren and Opslaan) stay; only the content scrolls, and the tabs of level 1 stick to its top (below).
   The foot keeps no room for the assistant button: that button (z-index 1150) lies under the overlay of a dialog (1400), so the room would stay empty (Controleur CS4,
   a deviation from plan 3.9). MudBlazor's own rules load after this file, so these have three classes and the sizes are !important. Colours only from the palette.
   max-width 100% keeps the box inside its container where 100vw counts a scroll bar of the page as well. */
.mud-dialog-container .mud-dialog.kz-line-dialog {
    /* The height of the sticky tab bar of level 1: MudBlazor 8.15 gives the bar a minimum of 48 px (.mud-tabs-tabbar-inner), higher than the tab of 44 px on a desktop and
       as high as the tab of 48 px on a touch screen, plus the line of 1 px under the bar: 49 px on every screen. */
    --kz-line-dialog-tabbar: 49px;
    display: flex;
    flex-direction: column;
    width: 100vw !important;
    max-width: 100% !important;
    height: 100dvh !important;
    max-height: 100dvh !important;
    margin: 0 !important;
    border-radius: 0 !important;
    background: var(--mud-palette-surface);
}

.mud-dialog-container .mud-dialog.kz-line-dialog .mud-dialog-title {
    flex: 0 0 auto;
}

.mud-dialog-container .mud-dialog.kz-line-dialog .mud-dialog-content {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
    /* No padding at the top: MudBlazor's 8px kept the sticky tab bar 8px under the edge, and the scrolled content showed through (measured in the demo, 19-10). */
    padding-top: 0;
    /* What is scrolled into view (a notice on top of the card, the focus on a button in it, a field) stops below the sticky tab bar instead of behind it. */
    scroll-padding-top: calc(var(--kz-line-dialog-tabbar) + 8px);
}

.mud-dialog-container .mud-dialog.kz-line-dialog .mud-dialog-actions {
    flex: 0 0 auto;
    padding-bottom: 8px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

/* The head, the tabs and the foot of both line dialogs, the large one of a kozijn (OfferLineDialog) and the small one of a loose part (OfferLooseLineDialog): styled once
   for both here instead of in their two scoped files (code review 1d, R1). Level 1 (the tabs of the dialog): directly under the title over the full width, 13 px, bold, the
   primary colour with a line of 3 px under the chosen tab; 48 px high on a tablet and a phone, 44 px on a desktop, so never lower than level 2 (the field groups of the card).
   The tab bar of level 1 sticks to the top of the content that scrolls, with the colour of the surface and above the fields (plan productregel-1e 3.7).
   Every rule starts with .mud-dialog.kz-line-dialog: MudBlazor's own CSS loads after this file, and the scoped rules these replace had a class more than their selector shows. */
.mud-dialog.kz-line-dialog .old-head {
    display: flex;
    align-items: center;
    gap: 8px;
}

.mud-dialog.kz-line-dialog .old-title {
    flex: 1;
    min-width: 0;
    margin: 0;
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.mud-dialog.kz-line-dialog .old-title:focus {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.mud-dialog.kz-line-dialog .old-head .old-icon {
    min-width: 44px;
    min-height: 44px;
}

.mud-dialog.kz-line-dialog .old .old-tabs > .mud-tabs-tabbar .mud-tab {
    min-height: 44px;
    font-size: 13px;
    font-weight: 700;
    text-transform: none;
    color: var(--mud-palette-primary);
}

.mud-dialog.kz-line-dialog .old .old-tabs > .mud-tabs-tabbar .mud-tab-slider {
    height: 3px;
}

.mud-dialog.kz-line-dialog .old .old-tabs > .mud-tabs-tabbar {
    position: sticky;
    top: 0;
    z-index: 2;
    background-color: var(--mud-palette-surface);
    border-bottom: 1px solid var(--mud-palette-lines-default);
    margin-bottom: 12px;
}

.mud-dialog.kz-line-dialog .old-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
}

.mud-dialog.kz-line-dialog .old-summary {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--mud-palette-text-secondary);
}

.mud-dialog.kz-line-dialog .old-foot .old-btn {
    min-height: 44px;
    min-width: 44px;
}

@media (max-width: 1279.98px), (any-pointer: coarse) {
    .mud-dialog.kz-line-dialog .old .old-tabs > .mud-tabs-tabbar .mud-tab {
        min-height: 48px;
    }
}

/* On a phone the sentence in the foot ("Opslaan kan pas als vakken en buitenmaat kloppen.", the summary) breaks over more lines instead of being cut off. */
@media (max-width: 599.98px) {
    .mud-dialog.kz-line-dialog .old-summary {
        white-space: normal;
        text-overflow: clip;
        overflow: visible;
        overflow-wrap: anywhere;
    }
}

/* ===== Status of an aanvraag: the field Status (plan offerte-voortgang 4.2) =====
   The field Status of the offer screen has the colour of the group of its status, the same colour as the step in the progress bar (one colour system, CS1).
   InputClass of MudSelect lands on the input inside the component, so a scoped rule does not reach it; MudBlazor's input colour loads after this file, hence
   !important (as the old fixed colours had). The colours are the per-mode variables --status-<groep> that MainLayout puts on the layout (ThemeColors.StatusGroupColor). */
.status-calculatie,
.status-verzonden,
.status-opdracht,
.status-bestellen,
.status-gereed,
.status-gefactureerd,
.status-afgekeurd {
    font-weight: 700 !important;
}

.status-calculatie { color: var(--status-calculatie) !important; }
.status-verzonden { color: var(--status-verzonden) !important; }
.status-opdracht { color: var(--status-opdracht) !important; }
.status-bestellen { color: var(--status-bestellen) !important; }
.status-gereed { color: var(--status-gereed) !important; }
.status-gefactureerd { color: var(--status-gefactureerd) !important; }
.status-afgekeurd { color: var(--status-afgekeurd) !important; }

/* ---- Facturen (plan factuurproces 13, designs 13.2-13.17) ----
   Tab Facturen, the invoice dialog and the read-only archive. Colours only from the theme (var(--mud-palette-*)) and the status colours of the layout
   (var(--status-*): Concept grey, Definitief blue, Verzonden dark blue), so light and dark follow by themselves. Amounts never break over two lines. Below 600 px
   MudTable turns the rows into cards (Breakpoint.Xs) and here the summary and the buttons stack. */
.kz-invoice-tab { display: flex; flex-direction: column; gap: 12px; }

.kz-invoice-amount { white-space: nowrap; font-variant-numeric: tabular-nums; }

.kz-invoice-hint { font-size: 0.8125rem; color: var(--mud-palette-text-secondary); }

.kz-invoice-summary { display: flex; gap: 12px; flex-wrap: wrap; }

.kz-invoice-figure {
    flex: 1 1 0;
    min-width: 0;
    padding: 10px 14px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    background: var(--mud-palette-surface);
}

.kz-invoice-label { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--mud-palette-text-secondary); }

.kz-invoice-big { font-size: 1.25rem; font-weight: 600; color: var(--mud-palette-text-primary); }

.kz-invoice-status { display: inline-block; font-weight: 700; font-size: 0.8125rem; }
.kz-invoice-status-concept { color: var(--status-aanvraag); }
.kz-invoice-status-final { color: var(--status-calculatie); }
.kz-invoice-status-sent { color: var(--status-verzonden); }
.kz-invoice-status-credited { color: var(--status-gereed); margin-left: 6px; }

.kz-invoice-row-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; align-items: center; }

.kz-invoice-terms { margin: 0; padding-left: 18px; }
.kz-invoice-term { margin: 2px 0; }

.kz-invoice-changes { margin: 4px 0; padding-left: 18px; }

.kz-invoice-block {
    padding: 12px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}
.kz-invoice-block:last-of-type { border-bottom: none; }

.kz-invoice-choices { display: flex; flex-direction: column; gap: 4px; }

.kz-invoice-choice { display: flex; align-items: flex-start; gap: 8px; cursor: pointer; color: var(--mud-palette-text-primary); }
.kz-invoice-choice input { margin-top: 4px; accent-color: var(--mud-palette-primary); }
.kz-invoice-choice-off { cursor: default; color: var(--mud-palette-text-disabled); }

.kz-invoice-free { max-width: 260px; margin-left: 24px; }

.kz-invoice-pair { display: flex; gap: 12px; }
.kz-invoice-pair > * { flex: 1 1 0; min-width: 0; }

.kz-invoice-lines { display: flex; flex-direction: column; }

.kz-invoice-line {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 6px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}
.kz-invoice-line-vat { color: var(--mud-palette-text-secondary); }
.kz-invoice-line-total { font-weight: 700; border-bottom: none; }

.kz-invoice-facts { display: grid; grid-template-columns: max-content 1fr; gap: 4px 16px; margin: 0 0 12px; }
.kz-invoice-facts dt { color: var(--mud-palette-text-secondary); }
.kz-invoice-facts dd { margin: 0; }

.kz-invoice-pdfstate { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }

.kz-invoice-checklist, .kz-invoice-confirm { margin: 6px 0; padding-left: 18px; }

.kz-invoice-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; width: 100%; }

/* The settlement of a final invoice (13.10 block 1): label left, one amount column per rate. */
.kz-final-table { width: 100%; border-collapse: collapse; font-size: 0.875rem; color: var(--mud-palette-text-primary); }
.kz-final-table th { text-align: right; font-weight: 600; color: var(--mud-palette-text-secondary); padding: 4px 0 4px 12px; }
.kz-final-table td { padding: 4px 0; border-bottom: 1px solid var(--mud-palette-lines-default); }
.kz-final-table td + td { text-align: right; padding-left: 12px; white-space: nowrap; }
.kz-final-strong td { font-weight: 700; }

@media (max-width: 599.98px) {
    .kz-invoice-summary { flex-direction: column; }
    .kz-invoice-pair { flex-direction: column; gap: 0; }
    .kz-invoice-free { margin-left: 0; max-width: none; }
    /* MudBlazor hides a table footer as cards; the totals of the final invoice (balance, earlier invoices) stay visible as one row. */
    .kz-invoice-table.mud-xs-table .mud-table-root .mud-table-foot { display: block; }
    .kz-invoice-table.mud-xs-table .mud-table-foot .mud-table-row { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 12px; padding: 8px 16px; }
    .kz-invoice-table.mud-xs-table .mud-table-foot .mud-table-cell { display: block; padding: 0; border: none; }
    .kz-invoice-table.mud-xs-table .mud-table-foot .mud-table-cell:empty { display: none; }
    .kz-invoice-actions,
    .kz-invoice-row-actions { flex-direction: column; align-items: stretch; }
    .kz-invoice-actions .mud-button-root,
    .kz-invoice-row-actions .mud-button-root { width: 100%; }
}
/* ---- end Facturen ---- */

/* ===== Theme: offer screen, tab Prijzen (phase 3) =====
   The tab (Class="kz-prices") carries ThemeColors.SectionStyle(ThemeSection.Aanvragen): --sc, --sc-head, --sc-text.
   Everything below starts with .kz-prices (or .kz-calm-table / .kz-text-error, which need no section colour), so no other table changes.
   The tables are MudSimpleTable (plain td/th, no .mud-table-* classes); MudBlazor styles their cells with `.mud-simple-table table * tr>td` (1 class + 3 elements)
   and `.mud-simple-table.mud-table-dense * tr td` (2 classes + 2 elements). app.css loads first, so each cell rule has 2 classes + 3 elements or more.
   Only theme variables (--mud-palette-*, --sc*): no hex. The shares of the mixes are pinned by OfferScreenThemeTests (>= 4.5:1, light and dark). */
.kz-prices {
    --kz-muted: color-mix(in srgb, var(--mud-palette-text-primary) 80%, var(--mud-palette-surface));
    --kz-warn-bg: color-mix(in srgb, var(--mud-palette-warning) 18%, var(--mud-palette-surface));
    --kz-warn-text: color-mix(in srgb, var(--mud-palette-warning) 25%, var(--mud-palette-text-primary));
}

/* One heading style for every section of the tab. */
.kz-prices .kz-prices-heading {
    margin: 0;
    padding-inline-start: 10px;
    border-inline-start: 3px solid var(--sc);
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.3;
}

/* Plan marge-per-offerte §5.1: the field Marge (%) at the end of the top row, 220 px, right-aligned; on a phone the row wraps and the field takes the full width. */
.kz-prices .kz-prices-markup {
    width: 220px;
    margin-left: auto;
}

@media (max-width: 599.98px) {
    .kz-prices .kz-prices-markup {
        width: 100%;
        margin-left: 0;
    }
}

/* Tables: lines between rows only, ~40 px rows made by padding, figures right-aligned. */
.kz-prices .kz-prices-table table thead th {
    padding: 8px 12px;
    background-color: var(--sc-head);
    color: var(--sc-text);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    border-bottom: 2px solid var(--sc);
}

.kz-prices .kz-prices-table table tbody td {
    padding: 10px 12px;
    border-bottom: 1px solid var(--mud-palette-table-lines);
    font-variant-numeric: tabular-nums;
}

.kz-prices .kz-prices-table table .kz-num {
    text-align: end;
}

.kz-prices .kz-prices-table table .kz-num input {
    text-align: end;
}

/* Group row (the position head, "Eigen regels"): a light band in the section colour. */
.kz-prices .kz-prices-table table tbody tr.kz-prices-group td {
    padding-top: 8px;
    padding-bottom: 8px;
    background-color: color-mix(in srgb, var(--sc) 8%, var(--mud-palette-surface));
    font-size: 0.84rem;
    font-weight: 600;
}

/* Plan prijzen-per-positie: at a locked status a line under the head of its position, indented (the head says the position once). */
.kz-prices .kz-prices-table table tbody tr.kz-prices-in-group td:first-child {
    padding-inline-start: 28px;
}

.kz-prices .kz-prices-table table tbody tr.kz-prices-note td {
    padding-top: 6px;
    padding-bottom: 6px;
    color: var(--kz-muted);
}

/* Plan prijslijsten-per-vak (mockup 9.11): a vak "waarvan" under its Raam, indented and muted; its amount is part of the Raam. */
.kz-prices .kz-prices-table table tbody tr.kz-prices-part td {
    color: var(--kz-muted);
}

.kz-prices .kz-prices-table table tbody tr.kz-prices-part td:first-child {
    padding-left: 28px;
}

/* The totals block: no header, a heavier last line. */
.kz-prices .kz-prices-totals table tbody td {
    padding: 8px 12px;
}

.kz-prices .kz-prices-totals table tbody tr.kz-prices-total td {
    border-top: 2px solid var(--sc);
    font-weight: 600;
}

/* "wijkt af van product" (before 1.19.10 "aangepast"): the section colour as a tint. */
.kz-prices .kz-prices-changed {
    display: inline-flex;
    align-items: center;
    margin-inline-start: 8px;
    padding: 1px 9px;
    border-radius: 99px;
    background-color: var(--sc-head);
    color: var(--sc-text);
    font-size: 0.72rem;
    font-weight: 500;
    white-space: nowrap;
}

/* "Product nu": what the product gives now, small, under the description of a stored line that differs from it. */
.kz-prices .kz-prices-table table td .kz-prices-product-now {
    margin-top: 2px;
    color: var(--kz-muted);
    font-size: 0.78rem;
}

/* Soft warning pill ("prijs ontbreekt", "hoeveelheid onbekend") and the same colours as a note line. */
.kz-prices .kz-prices-warn {
    display: inline-flex;
    align-items: center;
    padding: 1px 9px;
    border-radius: 99px;
    background-color: var(--kz-warn-bg);
    color: var(--kz-warn-text);
    font-size: 0.74rem;
    font-weight: 500;
    white-space: nowrap;
}

.kz-prices .kz-prices-table table td .kz-prices-warn {
    display: flex;
    width: fit-content;
    margin-inline-start: auto;
    margin-bottom: 4px;
}

.kz-prices .kz-prices-table table td:first-child .kz-prices-warn {
    display: inline-flex;
    margin-inline-start: 8px;
    margin-bottom: 0;
}

.kz-prices .kz-prices-warn-note {
    display: block;
    padding: 4px 10px;
    border-radius: 6px;
    background-color: var(--kz-warn-bg);
    color: var(--kz-warn-text);
}

/* A message about a failure in a field (the product field of a position): the error colour mixed towards the text colour so it reads on the surface. */
.kz-text-error {
    color: color-mix(in srgb, var(--mud-palette-error) 50%, var(--mud-palette-text-primary));
}

/* The pick list in the product dialog: calm, neutral (a dialog stands outside the layout, so it has no section colour). */
.kz-calm-table {
    max-height: 360px;
    overflow: auto;
}

.kz-calm-table .mud-table-root .mud-table-head .mud-table-row .mud-table-cell {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    border-bottom: 2px solid var(--mud-palette-lines-default);
}

.kz-calm-table .mud-table-root .mud-table-body .mud-table-row .mud-table-cell {
    padding-top: 9.5px;
    padding-bottom: 9.5px;
}

/* ===== Product cards (plan raamtypes-naar-producten §5.1, §5.7; decisions V5 and V6) =====
   Shared by the overview of the Productcatalogus (ProductCard: li > article) and the window "Product kiezen" (ProductChoiceCard: one button role="radio").
   Vertical: the picture (or the icon of the category) above, the text centred under it, each line on its own and never broken inside a word ("…" at the end,
   the full text in title); the buttons in their own row at the bottom. At most four columns; 200 px per card from 600 px, 150 px on a phone.
   Only palette colours; ProductCardThemeTests pins the rules and the contrast (light and dark). */
.kz-pcards {
    --kz-pcard-min: 200px;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(max(var(--kz-pcard-min), calc((100% - 3 * 10px) / 4)), 1fr));
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.kz-pcards-item {
    display: flex;
    min-width: 0;
}

.kz-pcard {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 44px;
    margin: 0;
    padding: 8px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius);
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    font: inherit;
    text-align: center;
}

/* A Vervallen product: a dashed border, the text at full strength. */
.kz-pcard-off {
    border-style: dashed;
}

/* The picture area: one picture, or the variants of a family side by side, equally wide; the same height with or without a picture. */
.kz-pcard-pic {
    position: relative;
    display: flex;
    align-self: stretch;
    gap: 6px;
    height: 96px;
}

/* The pictures are line drawings on white; they stay white in the dark theme too. */
.kz-pcard-img {
    flex: 1 1 0;
    min-width: 0;
    height: 100%;
    object-fit: contain;
    border-radius: 6px;
    background: var(--mud-palette-white);
}

.kz-pcard-ph {
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-width: 0;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 6px;
    background: color-mix(in srgb, var(--mud-palette-text-primary) 4%, var(--mud-palette-surface));
    color: var(--mud-palette-text-secondary);
}

.kz-pcard-icon {
    width: 40px;
    height: 40px;
    fill: currentColor;
}

.kz-pcard-ph-note {
    max-width: 100%;
    padding: 0 4px;
    overflow: hidden;
    font-size: max(12px, 0.75rem);
    line-height: 1.2;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The check mark of a chosen card: top right, over the picture. */
.kz-pcard-check {
    position: absolute;
    top: 4px;
    right: 4px;
    display: flex;
    border-radius: 50%;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-primary);
}

.kz-pcard-check svg {
    width: 22px;
    height: 22px;
    fill: currentColor;
}

.kz-pcard-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    margin-top: 6px;
    text-align: center;
}

/* Never a word broken (V5): one line, "…" at the end; the full text is in title or aria-label. */
.kz-pcard-text {
    display: block;
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow-wrap: normal;
    word-break: normal;
}

.kz-pcard-name {
    margin: 0;
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1.4;
}

.kz-pcard-name a {
    color: inherit;
    text-decoration: none;
}

.kz-pcard-name a:hover,
.kz-pcard-name a:focus-visible {
    text-decoration: underline;
}

/* Labels side by side stand together in the middle; when they do not fit, the status moves as a whole to the next line. */
.kz-pcard-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-width: 0;
}

.kz-pcard-code {
    padding: 1px 6px;
    border-radius: 4px;
    background: color-mix(in srgb, var(--mud-palette-text-primary) 8%, var(--mud-palette-surface));
    font-size: max(12px, 0.75rem);
    font-weight: 600;
}

.kz-pcard-meta {
    margin: 0;
    color: color-mix(in srgb, var(--mud-palette-text-primary) 80%, var(--mud-palette-surface));
    font-size: max(12px, 0.75rem);
    line-height: 1.4;
}

.kz-pcard-status {
    flex: none;
    padding: 1px 8px;
    border-radius: 99px;
    background: color-mix(in srgb, var(--mud-palette-success) 18%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--mud-palette-success) 25%, var(--mud-palette-text-primary));
    font-size: max(12px, 0.75rem);
    white-space: nowrap;
}

.kz-pcard-status-ending {
    background: color-mix(in srgb, var(--mud-palette-warning) 18%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--mud-palette-warning) 25%, var(--mud-palette-text-primary));
}

.kz-pcard-status-off {
    background: color-mix(in srgb, var(--mud-palette-error) 14%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--mud-palette-error) 30%, var(--mud-palette-text-primary));
}

/* The buttons: their own row under the text, centred, at the same height in every card of a row (V6). */
.kz-pcard-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 4px;
    margin-top: auto;
    padding-top: 4px;
}

/* A chosen card ("Product kiezen"): not by colour alone — a 2 px border, a light background and the check mark. */
.kz-pcard-on {
    border: 2px solid var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, var(--mud-palette-surface));
}

/* Focus looks different from chosen: a ring outside the card in the text colour. */
.kz-pcard:focus-visible {
    outline: 2px solid var(--mud-palette-text-primary);
    outline-offset: 2px;
}

.kz-pcard-choice {
    cursor: pointer;
}

/* "Product kiezen" (B3a): the card is a button, so the lines of its body are spans; each stands on its own line. */
.kz-pcard-choice .kz-pcard-name,
.kz-pcard-choice .kz-pcard-meta {
    display: block;
}

/* Hover is not chosen (Emmanuel, 8090): hover only darkens the 1 px border; chosen has the 2 px primary border, the light background and the check mark. */
.kz-pcard-choice:hover:not(.kz-pcard-on) {
    border-color: var(--mud-palette-text-secondary);
}

/* The cards scroll in their own area: the tabs, the search field and the buttons Annuleren and Kiezen always stay in view. The area takes the height of the
   screen minus the rest of the window (Emmanuel, 8090: the window grows with the screen). */
.kz-pcards-scroll {
    max-height: max(240px, calc(100vh - 320px));
    overflow-y: auto;
    padding: 4px;
}

/* "Product kiezen" (Emmanuel, 8090, 1.61.1): at most three cards side by side, with larger pictures; the window itself is MaxWidth.Large. */
.kz-pcards-scroll .kz-pcards {
    grid-template-columns: repeat(auto-fill, minmax(max(var(--kz-pcard-min), calc((100% - 2 * 10px) / 3)), 1fr));
}

.kz-pcards-scroll .kz-pcard-pic {
    height: 140px;
}

/* The live line of "Product kiezen" (§5.6): a screen reader reads how many products were found; it is not shown. */
.kz-pcards-live {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* The first load: grey cards in the place of the cards to come. */
.kz-pcard-skeleton {
    min-height: 180px;
    border-style: dashed;
    background: color-mix(in srgb, var(--mud-palette-text-primary) 6%, var(--mud-palette-surface));
}

@media (max-width: 599.98px) {
    .kz-pcards {
        --kz-pcard-min: 150px;
    }

    .kz-pcard-pic {
        height: 72px;
    }

    .kz-pcards-scroll .kz-pcard-pic {
        height: 96px;
    }
}

