/*
 * Redesigned screens (Atelier, then Retail): the reference design validated on 2026-09-24 (canvas "Fiche OF -
 * référence UI Atelier"). Colors come only from theme-tokens.css and the MudBlazor palette, plus the few values
 * below, so the dark mode follows on its own. Tones: purple = at work, gold = waiting for a decision, blue = away
 * or external, green = finished, red = stopped, neutral = not started (Components/Common/UiTone.cs).
 *
 * NOTE: technical debt - the classes keep their Atelier prefix "ws-" now that Retail shares them. Renaming them
 * to "ui-" touches every Atelier screen for no visible change; do it in one pass once Retail is done.
 */

:root {
    --ws-faint: #8e8d98;
    --ws-head: #f7f7fa;
    --ws-running: #faf8ff;
    --ws-track: #ecebf1;
}

html.theme-dark {
    --ws-faint: #7d7c86;
    --ws-head: #262b30;
    --ws-running: rgba(140, 116, 232, 0.07);
    --ws-track: rgba(255, 255, 255, 0.10);
}

/* ---- Page ---- */

.ws-page {
    display: flex;
    flex-direction: column;
    gap: 20px;
    padding-bottom: 48px;
}

/* One rhythm on every page (2026-10-04): the blocks of a page are 20px apart and nothing else spaces them. A form that
   wraps the title and the cards (repair, custom order) keeps that rhythm instead of losing it inside the <form>. */
.ws-page > form {
    display: flex;
    flex-direction: column;
    gap: 20px;
    min-width: 0;
}

/* The shared page title (InvestockTitle) keeps 16px under it for the screens not on ws-page yet; on a page the gap
   already spaces it from the first block. */
.ws-page > .ws-head-text,
.ws-page > form > .ws-head-text {
    margin-bottom: 0 !important;
}

/* A grid laid on a page sits at the same 20px as any block. MudBlazor pulls a grid up by its gutter so the items'
   padding does not add to the space above; the old global rule (Investock.css) cancels that pull for spacing 3 only,
   which left 12px more above those grids. Put it back on the page, nowhere else. */
.ws-page > .mud-grid.mud-grid-spacing-xs-3,
.ws-page > form > .mud-grid.mud-grid-spacing-xs-3 {
    margin-top: -12px !important;
}

/* The old global rule (Investock.css) puts 20px under every MudCard; on a page the gap already spaces the blocks, and
   both together made 40px between two cards. */
.ws-page > .mud-card,
.ws-page > form > .mud-card {
    margin-bottom: 0 !important;
}

/* A MudBlazor card on a page has the padding of a redesign card (ws-card-body), whatever screen it is on. */
.ws-page .mud-card.mud-elevation-25 .mud-card-content {
    padding: 24px 28px;
}

@media (max-width: 600px) {
    .ws-page .mud-card.mud-elevation-25 .mud-card-content {
        padding: 20px;
    }
}

/* Sentence case on the Atelier screens; the rest of the application keeps its capitals for now. */
.ws-page .mud-button-root,
.ws-page .mud-tab,
.ws-dialog .mud-button-root {
    text-transform: none;
    letter-spacing: normal;
    font-weight: 600;
}

/* White on the dark purple read at about 3:1; a dark ink reads above 5:1. */
html.theme-dark .ws-page .mud-button-filled.mud-button-filled-primary,
html.theme-dark .ws-dialog .mud-button-filled.mud-button-filled-primary {
    color: #17131f;
}

/* Gold is no longer a button color, and a grey filled button reads as disabled: on the Atelier pages both become the
   outlined secondary button of the reference design (the shared EntityTable's "Recharger" and row "Actions"). */
.ws-page .mud-button-filled.mud-button-filled-secondary,
.ws-page .mud-button-filled.mud-button-filled-default {
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    border: 1px solid var(--mud-palette-lines-inputs);
    box-shadow: none;
}

.ws-page .mud-button-filled.mud-button-filled-secondary:hover,
.ws-page .mud-button-filled.mud-button-filled-default:hover {
    background-color: var(--mud-palette-action-default-hover);
}

.ws-card {
    background-color: var(--mud-palette-surface);
    border: 1px solid var(--card-border);
    box-shadow: var(--card-shadow);
    border-radius: 14px;
    min-width: 0;
}

.ws-card-body {
    padding: 24px 28px;
}

/* ---- Header of a sheet ---- */

.ws-sheet-head {
    display: flex;
    flex-direction: column;
    gap: 22px;
}

.ws-head {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px 24px;
}

/* When the header buttons wrap under the title, they stay on the right edge of the card, as on one line. */
.ws-head > .ws-actions {
    margin-inline-start: auto;
    justify-content: flex-end;
}

.ws-head-text {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}

.ws-title-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
}

.ws-title {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: -0.01em;
    color: var(--mud-palette-text-primary);
}

.ws-subtitle {
    font-size: 0.84rem;
    color: var(--mud-palette-text-secondary);
}

.ws-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

.ws-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 16px;
    padding-top: 18px;
    border-top: 1px solid var(--card-border);
}

.ws-fact {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.ws-label {
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
}

.ws-value {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    overflow-wrap: anywhere;
}

.ws-note {
    font-size: 0.75rem;
    font-weight: 600;
}

/* A value with a small action beside it (sale sheet: the encashment date and its edit pencil). */
.ws-fact-inline {
    display: inline-flex;
    align-items: center;
    gap: 2px;
}

.ws-fact-inline .mud-icon-button {
    margin: -6px 0;
}

/* A switch sitting among the header buttons (sale sheet: weight on the receipt). */
.ws-head-switch {
    margin: 0;
}

.ws-text-green { color: var(--tint-green-fg); }
.ws-text-red { color: var(--tint-red-fg); }
.ws-text-gold { color: var(--tint-gold-fg); }
.ws-text-purple { color: var(--tint-purple-fg); }
.ws-text-blue { color: var(--tint-blue-fg); }
.ws-text-muted { color: var(--mud-palette-text-secondary); }
.ws-empty { color: var(--ws-faint); }

/* ---- Progress by step ---- */

.ws-progress {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.ws-progress-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    font-size: 0.8125rem;
}

.ws-progress-steps {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: 8px;
}

.ws-progress-step {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}

.ws-progress-bar {
    height: 6px;
    border-radius: 999px;
    background: var(--ws-track);
}

.ws-progress-step.is-done .ws-progress-bar { background: var(--tint-green-fg); }
.ws-progress-step.is-active .ws-progress-bar { background: var(--mud-palette-primary); }

.ws-progress-label {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ws-progress-step.is-done .ws-progress-label { color: var(--mud-palette-text-primary); }
.ws-progress-step.is-active .ws-progress-label { color: var(--mud-palette-text-primary); font-weight: 700; }

/* ---- Pills ---- */

.ws-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 26px;
    padding: 0 12px;
    border: 1px solid transparent;
    border-radius: 999px;
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    vertical-align: middle;
}

.ws-chip-sm {
    height: 22px;
    padding: 0 9px;
    font-size: 0.72rem;
}

.ws-chip-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}

.ws-chip-button {
    cursor: pointer;
}

.ws-chip-button:hover {
    filter: brightness(0.96);
}

.ws-chip-button:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.ws-tone-neutral { background: var(--tint-neutral-bg); color: var(--tint-neutral-fg); }
.ws-tone-purple { background: var(--tint-purple-bg); color: var(--tint-purple-fg); }
.ws-tone-gold { background: var(--tint-gold-bg); color: var(--tint-gold-fg); }
.ws-tone-green { background: var(--tint-green-bg); color: var(--tint-green-fg); }
.ws-tone-red { background: var(--tint-red-bg); color: var(--tint-red-fg); }
.ws-tone-blue { background: var(--tint-blue-bg); color: var(--tint-blue-fg); }

.ws-chip-outlined {
    background: transparent;
    border-color: currentColor;
}

/* ---- Tabs ---- */

.ws-tabs .mud-tabs-tabbar {
    background: transparent;
    border-bottom: 1px solid var(--card-border);
    border-radius: 14px 14px 0 0;
}

.ws-tabs .mud-tabs-tabbar-inner {
    padding: 0 16px;
}

.ws-tabs .mud-tab {
    min-height: 52px;
    padding: 0 14px;
    font-size: 0.875rem;
    color: var(--mud-palette-text-secondary);
}

.ws-tabs .mud-tab.mud-tab-active {
    color: var(--mud-palette-primary);
}

.ws-tab-panel {
    padding: 22px 28px 28px;
}

.ws-tab-panel .mud-divider {
    margin: 28px 0 !important;
}

/* Page-level tabs (sale sheet): the bar sits on the page, not in a card, sticks under the app bar, and each panel
   holds its own cards. A sheet with a single tab (create mode) hides the bar. */
.ws-tabs-page .mud-tabs-tabbar {
    border-radius: 0;
    background: var(--mud-palette-background);
}

/* Sticky under the app bar on a page only: in a dialog the app bar offset would leave the bar floating mid-dialog. */
.ws-page .ws-tabs-page .mud-tabs-tabbar {
    position: sticky;
    top: var(--mud-appbar-height);
    z-index: 3;
}

.ws-tabs-page .mud-tabs-tabbar-inner {
    padding: 0;
}

.ws-tab-panel-page {
    padding: 20px 0 0;
}

.ws-tabs-solo .mud-tabs-tabbar {
    display: none;
}

.ws-tabs-solo .ws-tab-panel-page {
    padding-top: 0;
}


/* An action a phone cannot perform (label printing needs the print client of a desk computer). */
@media (max-width: 600px) {
    .ws-hide-phone { display: none !important; }
}

/* Editable table (piece sheet: metal and stone lines). A grid, not a <table>: the columns come from --ws-cols, set by
   the page from the settings, and on a phone or a tablet each row turns into a card whose cells carry their own label.
   On a desk it reads as a table (mockup validated 2026-10-04): a frame, a grey header band, a line between rows, and
   cells without their own outline until one is being typed in. */
.ws-edit-table {
    display: grid;
    max-width: 100%;
    border: 1px solid var(--card-border);
    border-radius: 10px;
    overflow: hidden;
}

.ws-edit-table.is-narrow {
    width: fit-content;
}

.ws-edit-head,
.ws-edit-row {
    display: grid;
    grid-template-columns: var(--ws-cols);
    align-items: center;
}

.ws-edit-head {
    background: var(--ws-head);
    border-bottom: 1px solid var(--card-border);
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.ws-edit-head > span {
    padding: 9px 12px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ws-edit-row + .ws-edit-row {
    border-top: 1px solid var(--card-border);
}

.ws-edit-row:hover {
    background: var(--mud-palette-table-hover);
}

.ws-edit-cell {
    min-width: 0;
    padding: 4px;
}

.ws-edit-cell .mud-input-control {
    margin-top: 0;
}

/* A cell is the field: no outline at rest, a light one under the mouse, the usual one while typing or in error. */
.ws-edit-table .mud-input-outlined:not(:focus-within):not(.mud-input-error) .mud-input-outlined-border {
    border-color: transparent;
}

.ws-edit-table .mud-input-outlined:hover:not(:focus-within):not(.mud-input-error) .mud-input-outlined-border {
    border-color: var(--mud-palette-lines-inputs);
}

/* The clear cross shows only on the cell being pointed at or typed in: at rest it took the room of the value, and a
   shape or a price came out cut. */
.ws-edit-cell:not(:hover):not(:focus-within) .mud-input-clear-button {
    display: none;
}

/* A field wrapped in a MudTooltip (fashion, stone price) fills its cell like its neighbours. */
.ws-edit-cell .mud-tooltip-root {
    display: block;
    width: 100%;
}

.ws-edit-cell.is-action {
    display: flex;
    align-items: center;
    justify-content: center;
    align-self: stretch;
    border-inline-start: 1px solid var(--card-border);
}

.ws-edit-cell.is-action .mud-tooltip-root {
    display: inline-flex;
    width: auto;
}

.ws-edit-lock {
    color: var(--mud-palette-text-disabled);
}

.ws-edit-only-cards {
    display: none !important;
}

/* Cards from md down: up to nine columns do not fit a tablet, let alone a phone. */
@media (max-width: 959.98px) {
    .ws-edit-table {
        gap: 10px;
        border: 0;
        border-radius: 0;
        overflow: visible;
    }

    .ws-edit-table.is-narrow {
        width: auto;
    }

    .ws-edit-head {
        display: none;
    }

    .ws-edit-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 10px;
        padding: 12px;
        border: 1px solid var(--card-border);
        border-radius: 12px;
    }

    .ws-edit-row + .ws-edit-row {
        border-top: 1px solid var(--card-border);
    }

    .ws-edit-row:hover {
        background: none;
    }

    .ws-edit-cell {
        padding: 0;
    }

    /* On a card the fields keep their outline: there is no grid around them to read as cells. */
    .ws-edit-table .mud-input-outlined:not(:focus-within):not(.mud-input-error) .mud-input-outlined-border {
        border-color: var(--mud-palette-lines-inputs);
    }

    .ws-edit-cell::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 4px;
        font-size: 0.72rem;
        color: var(--mud-palette-text-secondary);
    }

    .ws-edit-cell.is-action {
        grid-column: 1 / -1;
        justify-content: flex-end;
        border-inline-start: 0;
    }

    .ws-edit-cell.is-action::before {
        content: none;
    }

    .ws-edit-only-table {
        display: none !important;
    }

    .ws-edit-only-cards {
        display: inline-flex !important;
    }
}

/* Phone tab bar (Components/Common/MobileTabBar.razor): two tabs and "Plus", shown under 600 px only. */
.ws-mobile-tabs {
    display: none;
}

.ws-mobile-tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 48px;
    padding: 0 12px;
    border: 0;
    border-bottom: 2px solid transparent;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font: inherit;
    font-size: 0.875rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
}

.ws-mobile-tab.is-active {
    color: var(--mud-palette-primary);
    border-bottom-color: var(--mud-palette-primary);
}

.ws-mobile-tab:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

.ws-mobile-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--tint-gold-fg);
}

.ws-mobile-menu-item {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

@media (max-width: 600px) {
    .ws-tabs-mobile .mud-tabs-tabbar {
        display: none;
    }

    .ws-mobile-tabs {
        display: flex;
        padding: 0 8px;
        background: var(--mud-palette-surface);
        border-bottom: 1px solid var(--card-border);
    }

    .ws-mobile-more {
        margin-inline-start: auto;
        min-width: 0;
    }

    /* "Plus" takes the name of the open hidden tab ("Ordres de fabrication (1)"): it shrinks and cuts that name
       instead of pushing the bar past a 375px screen. The two visible tabs keep their width. */
    .ws-mobile-tabs > .ws-mobile-tab {
        flex-shrink: 0;
    }

    .ws-mobile-more .mud-menu-activator,
    .ws-mobile-more .ws-mobile-tab {
        min-width: 0;
        max-width: 100%;
    }

    .ws-mobile-tab-label {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .ws-page .ws-mobile-tabs {
        position: sticky;
        top: var(--mud-appbar-height);
        z-index: 3;
        margin: 0 -16px;
    }
}

/* ---- Form pieces shared by the redesigned forms (buyback form, mockup validated 2026-10-05) ---- */

/* A second part inside a card, under a line (the seller's ID under the seller). */
.ws-card-split {
    margin-top: 24px;
    padding-top: 20px;
    border-top: 1px solid var(--card-border);
}

/* Lines that fold: an incomplete line stays open, a complete one folds into its summary. */
.ws-item-lines {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.ws-item-line {
    display: flex;
    flex-direction: column;
    gap: 18px;
    padding: 14px 18px;
    border: 1px solid var(--card-border);
    border-radius: 12px;
}

.ws-item-head {
    display: flex;
    align-items: center;
    gap: 12px;
}

.ws-item-status {
    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    font-size: 0.75rem;
    font-weight: 700;
}

.ws-item-status.is-complete {
    background: var(--tint-green-bg);
    color: var(--tint-green-fg);
}

.ws-item-status.is-incomplete {
    background: var(--tint-gold-bg);
    color: var(--tint-gold-fg);
}

.ws-item-main {
    display: flex;
    flex-direction: column;
    flex-grow: 1;
    gap: 3px;
    min-width: 0;
}

.ws-item-title {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    font-size: 0.875rem;
    font-weight: 700;
}

.ws-item-meta {
    font-size: 0.78rem;
    color: var(--mud-palette-text-secondary);
}

.ws-item-price {
    font-size: 1rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.ws-item-actions {
    display: flex;
    justify-content: flex-end;
    border-top: 1px solid var(--card-border);
    margin-top: 4px;
}

.ws-item-recap {
    display: flex;
    flex-direction: column;
    margin-top: 16px;
    border-top: 1px solid var(--card-border);
}

.ws-item-recap-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 10px 0;
    border-bottom: 1px solid var(--card-border);
    font-size: 0.85rem;
}

.ws-item-recap-amount {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.ws-item-recap-amount.is-empty {
    color: var(--mud-palette-text-disabled);
}

.ws-item-recap-total {
    display: flex;
    justify-content: space-between;
    padding: 12px 0 0;
    font-size: 0.95rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* A choice between two or three values (Revente / Refonte), grey, the chosen one raised. */
.ws-segmented {
    display: inline-flex;
    gap: 2px;
    padding: 3px;
    border-radius: 10px;
    background: var(--tint-neutral-bg);
}

.ws-segmented button {
    height: 34px;
    padding: 0 16px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    cursor: pointer;
}

.ws-segmented button.is-active {
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}

/* A notice inside a card (the legal declaration of a buyback). */
.ws-callout {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 16px;
    border-radius: 10px;
    font-size: 0.85rem;
    line-height: 1.5;
}

.ws-callout.is-gold {
    background: var(--tint-gold-bg);
    color: var(--tint-gold-fg);
}

.ws-callout-quote {
    margin-top: 6px;
    font-style: italic;
}

/* A section title with a pill right after it (Pièce d'identité · Confidentiel). */
.ws-title-with-chip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 10px;
}

/* The facts of an ID document on one row, two columns on a phone. */
.ws-id-facts {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 16px 20px;
}

@media (max-width: 959.98px) {
    .ws-id-facts {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 600px) {
    .ws-id-facts {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* Photo tiles (ID recto and verso): empty with a dashed edge, stored with a lock, shown in inspection mode. */
.ws-photo-pair {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 20px;
}

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

.ws-photo {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}

.ws-photo-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 190px;
    overflow: hidden;
    border-radius: 12px;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
}

.ws-photo-tile b {
    color: var(--mud-palette-text-primary);
}

.ws-photo-tile.is-empty {
    border: 1.5px dashed var(--mud-palette-lines-inputs);
}

.ws-photo-tile.is-stored {
    background: var(--tint-neutral-bg);
}

/* A real border, not an inset shadow: a shadow is painted under the content, so a photo as tall as the tile hid it. */
.ws-photo-tile.is-shown {
    box-sizing: border-box;
    background: var(--tint-neutral-bg);
    border: 2px solid var(--mud-palette-primary);
}

.ws-photo-tile.is-shown img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    cursor: zoom-in;
    user-select: none;
    -webkit-user-drag: none;
}

.ws-photo-busy {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background: color-mix(in srgb, var(--mud-palette-surface) 85%, transparent);
    font-weight: 600;
}

/* A part of a card that folds, its whole head being the button (the access log of an ID). */
.ws-fold-head {
    display: flex;
    width: 100%;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: start;
    cursor: pointer;
}

.ws-log-rows {
    display: flex;
    flex-direction: column;
    margin-top: 8px;
}

.ws-log-row {
    display: grid;
    grid-template-columns: 150px minmax(0, 1fr) minmax(0, 220px);
    align-items: center;
    gap: 12px;
    min-height: 40px;
    border-top: 1px solid var(--card-border);
    font-size: 0.8125rem;
}

.ws-log-date {
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

@media (max-width: 600px) {
    .ws-log-row {
        grid-template-columns: minmax(0, 1fr);
        gap: 2px;
        padding: 8px 0;
    }
}

/* The add bar above a list of files: the kind, the button, what is accepted. */
.ws-add-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border-radius: 12px;
    background: var(--ws-head);
}

/* MudSelect puts its own wrapper around the class it is given: size the wrapper. The upload control keeps the width
   of its button. */
.ws-add-bar > .mud-select {
    flex: 0 0 240px;
    max-width: 100%;
}

.ws-add-bar > .mud-input-control {
    flex: 0 0 auto;
    width: auto;
    margin: 0;
}

@media (max-width: 600px) {
    .ws-add-bar {
        flex-direction: column;
        align-items: stretch;
    }

    .ws-add-bar > .mud-select {
        flex-basis: auto;
    }
}

/* An empty list that says what to add. */
.ws-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 28px 0;
    border-top: 1px solid var(--card-border);
    color: var(--mud-palette-text-secondary);
    font-size: 0.8125rem;
    text-align: center;
}

.ws-empty-state b {
    color: var(--mud-palette-text-primary);
}

/* One row per file: its tile, name and kind, size, date and author, the actions on the right. */
.ws-doc-rows {
    display: flex;
    flex-direction: column;
}

.ws-doc-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 0;
    border-top: 1px solid var(--card-border);
}

.ws-doc-main {
    display: flex;
    flex-direction: column;
    flex-grow: 1;
    gap: 3px;
    min-width: 0;
}

.ws-doc-title {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 8px;
    min-width: 0;
}

.ws-doc-name {
    overflow: hidden;
    max-width: 100%;
    font-size: 0.85rem;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The last card of a form: what comes next on the left, the save on the right. */
.ws-form-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px 16px;
}

.ws-form-foot-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-inline-start: auto;
}

/* ---- Sections inside a card ---- */

.ws-section-head {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 12px 16px;
    margin-bottom: 12px;
}

.ws-section-title {
    margin: 0;
    font-size: 1rem;
    font-weight: 700;
    color: var(--mud-palette-text-primary);
}

.ws-section-help {
    display: block;
    margin-top: 2px;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
}

.ws-empty-text {
    font-size: 0.875rem;
    color: var(--mud-palette-text-secondary);
}

/* ---- Tables ---- */

/* The application's tables carry a 20 px padding; inside a card section the table lines up with the title. */
.ws-table.mud-table {
    background: transparent;
    padding: 0 !important;
    margin-bottom: 0 !important;
}

/* MudBlazor's dense cells carry 16 px on the left and 24 px on the right; the operations table needs the room. The
   doubled class outweighs its ".mud-table-dense * .mud-table-row .mud-table-cell" rule. */
.ws-table .mud-table-row > .mud-table-cell.mud-table-cell {
    padding-left: 10px;
    padding-right: 10px;
}

.ws-table .mud-table-row > .mud-table-cell.mud-table-cell:first-child {
    padding-left: 12px;
}

.ws-table .mud-table-row > .mud-table-cell.mud-table-cell:last-child {
    padding-right: 8px;
}

.ws-table .mud-table-head .mud-table-cell {
    background: var(--ws-head);
    border-top: 1px solid var(--card-border);
    border-bottom: 1px solid var(--card-border);
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.ws-table .mud-table-body .mud-table-cell {
    border-bottom: 1px solid var(--card-border);
    font-size: 0.84rem;
}

.ws-table .mud-table-body .mud-table-row:hover {
    background: var(--card-hover);
}

/* The same look on a MudSimpleTable (plain th / td, without MudBlazor's row and cell classes): cash closing dialogs,
   cash statistics tables, sale boxes. */
.ws-table.mud-simple-table thead th {
    background: var(--ws-head);
    border-top: 1px solid var(--card-border);
    border-bottom: 1px solid var(--card-border);
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    padding: 8px 10px;
}

.ws-table.mud-simple-table tbody td {
    border-bottom: 1px solid var(--card-border);
    font-size: 0.84rem;
    padding: 8px 10px;
}

.ws-table.mud-simple-table tbody tr:hover {
    background: var(--card-hover);
}

.ws-table .ws-row-running {
    background: var(--ws-running);
}

.ws-table .ws-group-row .mud-table-cell {
    padding-top: 16px;
    padding-bottom: 6px;
    background: transparent;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--tint-purple-fg);
}

/* A technical identifier read as typed (audit table, field, trace id). */
.ws-code {
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-size: 0.8rem;
    font-weight: 600;
}

/* The opened detail row of the audit log, on the head tint. */
.ws-audit-detail-cell {
    padding: 4px 16px 12px !important;
    background: var(--ws-head);
}

/* The photo of "Mon compte": a square frame holding the picture or the initial. */
.ws-avatar-frame {
    width: 160px;
    height: 160px;
    border-radius: 14px;
    background: var(--ws-head);
    border: 1px solid var(--card-border);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.ws-avatar-initial {
    font-size: 3rem;
    font-weight: 700;
    color: var(--mud-palette-text-secondary);
}

/* Settings (administration mockup): a group is its title and help on the left (4/12), its rows on the right (8/12); a
   row is the label and help, then the control at the end. One footer saves the whole form. */
.ws-setting-group {
    display: grid;
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    gap: 0 32px;
    padding-top: 24px;
    margin-top: 22px;
    border-top: 1px solid var(--card-border);
}

.ws-setting-group.is-first {
    padding-top: 0;
    margin-top: 0;
    border-top: none;
}

.ws-setting-group-head {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding-top: 14px;
}

.ws-setting-group-rows {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.ws-setting-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 32px;
    padding: 14px 0;
    border-bottom: 1px solid var(--card-border);
}

.ws-setting-row.is-last {
    border-bottom: none;
}

.ws-setting-text {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
    max-width: 620px;
}

.ws-setting-control-cell {
    flex-shrink: 0;
}

.ws-setting-control {
    width: 150px;
}

.ws-setting-control.is-wide {
    width: 260px;
}

.ws-settings-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 16px 28px;
    border-top: 1px solid var(--card-border);
}

/* A printer template typed in its own language: monospace. */
.ws-code-field textarea {
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-size: 0.8rem;
}

@media (max-width: 960px) {
    .ws-setting-group {
        grid-template-columns: minmax(0, 1fr);
    }

    .ws-setting-row {
        flex-wrap: wrap;
        gap: 12px;
    }
}

/* Role permissions (administration mockup): one folding card per menu section, a matrix of resources x actions. */
.ws-perm-group {
    overflow: hidden;
}

.ws-perm-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 20px;
}

.ws-perm-head.is-open {
    border-bottom: 1px solid var(--card-border);
}

.ws-perm-toggle {
    flex: 0 0 28px;
    width: 28px;
    height: 28px;
    border: 0;
    border-radius: 8px;
    background: var(--ws-head);
    color: var(--mud-palette-text-secondary);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.ws-perm-title {
    min-width: 0;
    cursor: pointer;
}

.ws-perm-table .ws-perm-resource {
    min-width: 220px;
}

.ws-perm-table .ws-perm-action {
    width: 78px;
    text-align: center;
}

.ws-perm-others {
    gap: 0 10px;
}

.ws-perm-search {
    min-width: 280px;
    max-width: 420px;
}

/* A file drop zone (collaborator documents): a dashed frame; the hidden file input covers it so a click or a drop
   reaches it. Was a <style> block in UserProfile.razor. */
.ws-file-drop {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 22px;
    border: 1px dashed var(--mud-palette-lines-inputs);
    border-radius: 12px;
    text-align: center;
}

.ws-file-drop.is-dragging {
    border-color: var(--mud-palette-primary);
    background: var(--tint-purple-bg);
}

.ws-file-drop-input {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
    z-index: 10;
    opacity: 0;
}

/* A value that must stay on one line in a cell: a document number, an amount with its currency. */
.ws-nowrap {
    white-space: nowrap;
}

/* A dense list (many figure columns, billing): the cells of the EntityTable inside take the 10 px padding of .ws-table
   instead of MudBlazor's 16 / 24, so the row menu stays inside the card. Opt-in wrapper. */
.ws-compact-table .mud-table-row > .mud-table-cell.mud-table-cell {
    padding-left: 10px;
    padding-right: 10px;
}

/* The small line under a pill or a value in a list cell (a cancellation reason): wraps within a bounded width instead of
   widening the column past the card. */
.ws-cell-note {
    max-width: 180px;
    white-space: normal;
}

.ws-num,
.ws-table .mud-table-cell.ws-num {
    text-align: right !important;
    font-variant-numeric: tabular-nums;
}

/* The header of a figure column stays on one line; the small line under a figure wraps instead of widening the
   column, or the operations table runs past the card. */
th.ws-num,
.ws-table .mud-table-head .ws-num {
    white-space: nowrap;
}

.ws-num .ws-caption {
    min-width: 80px;
    max-width: 150px;
    margin-left: auto;
}

.ws-strong {
    font-weight: 600;
}

.ws-tabular {
    font-variant-numeric: tabular-nums;
}

.ws-caption {
    display: block;
    font-size: 0.72rem;
    color: var(--mud-palette-text-secondary);
}

/* A coloured caption (a change vs the previous period, "Non déclaré"): .ws-caption comes after the .ws-text-* colours
   with the same weight and used to win, so the colour never showed. */
.ws-caption.ws-text-green { color: var(--tint-green-fg); }
.ws-caption.ws-text-red { color: var(--tint-red-fg); }
.ws-caption.ws-text-gold { color: var(--tint-gold-fg); }
.ws-caption.ws-text-blue { color: var(--tint-blue-fg); }

/* A figure on the sheet that disagrees with another one: said, not blocked. */
.ws-caption-warning {
    color: var(--mud-palette-warning-darken);
    font-weight: 600;
}

.ws-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

a.ws-value,
.mud-link.ws-value {
    color: var(--mud-palette-primary);
}

/* ---- Cards and lists (EntityTable) on an Atelier page ----
   The shared EntityTable and the older forms draw a heavy shadow (elevation 25); on the Atelier pages they take the
   card chrome of the reference design instead, without touching the other screens of the application. */

.ws-page .mud-elevation-25 {
    box-shadow: var(--card-shadow) !important;
    border: 1px solid var(--card-border);
    border-radius: 14px !important;
}

.ws-page .mud-table.mud-elevation-25 .mud-table-head .mud-table-cell {
    background: var(--ws-head);
    border-bottom: 1px solid var(--card-border);
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    /* A header never breaks: "Total TTC" on two lines read as two columns (billing list, 2026-10-03). */
    white-space: nowrap;
}

.ws-page .mud-table.mud-elevation-25 .mud-table-body .mud-table-cell {
    border-bottom: 1px solid var(--card-border);
}

/* The actions column of every EntityTable stays on screen: a list with many columns scrolls sideways, and the ⋮
   button used to scroll away with the last column (sales list, 2026-10-04). Pinned to the end side, so it follows RTL.
   Under 600px the table stacks its cells and there is nothing to pin. */
@media (min-width: 600px) {
    .mud-table .mud-table-cell.ws-col-actions {
        position: sticky;
        inset-inline-end: 0;
        z-index: 1;
        background: var(--mud-palette-surface);
        border-inline-start: 1px solid var(--card-border);
    }

    .mud-table .mud-table-head .mud-table-cell.ws-col-actions {
        z-index: 2;
    }

    /* The hover tint is translucent: laid alone, the column scrolling under showed through. It goes over the
       opaque surface instead. */
    .mud-table-hover .mud-table-body .mud-table-row:hover .mud-table-cell.ws-col-actions {
        background: linear-gradient(var(--mud-palette-table-hover), var(--mud-palette-table-hover)), var(--mud-palette-surface);
    }

    /* Columns still hidden behind: a shadow on the pinned column says the table goes on (owner, 2026-10-06).
       js/table-overflow.js sets ws-more-end while the list can scroll towards its end side; mirrored in RTL. */
    .mud-table-container.ws-more-end .mud-table-cell.ws-col-actions {
        box-shadow: -12px 0 12px -10px rgba(0, 0, 0, 0.35);
    }

    [dir="rtl"] .mud-table-container.ws-more-end .mud-table-cell.ws-col-actions,
    .mud-rtl .mud-table-container.ws-more-end .mud-table-cell.ws-col-actions {
        box-shadow: 12px 0 12px -10px rgba(0, 0, 0, 0.35);
    }
}

/* A row's detail opened under it (the operations of a job in the list). */
.ws-subpanel {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 8px 0 12px;
    padding: 14px 16px;
    border: 1px solid var(--card-border);
    border-radius: 12px;
    background: var(--mud-palette-background);
}

/* One task of "Mes tâches" in simple mode: a card inside the page card. */
.ws-task {
    padding: 16px 20px;
    margin-bottom: 12px;
    border: 1px solid var(--card-border);
    border-radius: 12px;
    background: var(--mud-palette-surface);
}

/* The facts of the traveler (Passeport pièce), label and value side by side. */
.ws-traveler-facts.mud-simple-table,
.ws-traveler-facts.mud-simple-table table {
    background: transparent;
}

/* The application pads and spaces every table by 20 px; the facts sit flush under the title. */
.ws-traveler-facts.mud-simple-table {
    padding: 0 !important;
    margin-bottom: 0 !important;
}

.ws-traveler-facts td.ws-traveler-label,
.ws-traveler-facts td.ws-traveler-value {
    border: none !important;
    padding: 6px 8px !important;
    font-size: 0.84rem;
    vertical-align: top;
}

.ws-traveler-facts td.ws-traveler-label {
    width: 120px;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

/* The list is striped; the detail under a row is not. */
.ws-subpanel .mud-table-body .mud-table-row {
    background-color: transparent !important;
}

@media (max-width: 600px) {
    .ws-card-body,
    .ws-tab-panel {
        padding: 20px;
    }

    .ws-facts {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* A section title inside a sheet grid (Ordre, Client et délai, Description et notes). */
.ws-form-section {
    margin-top: 8px;
    padding-top: 20px !important;
    border-top: 1px solid var(--card-border);
}

.ws-form-section.is-first {
    margin-top: 0;
    padding-top: 12px !important;
    border-top: none;
}

/* The payment block of a sheet (buyback): the figures one under the other, then the split by method. A method that
   carried nothing reads "-" so the lines still add up to the total at a glance. */
.ws-pay-figures {
    display: flex;
    flex-direction: column;
}

.ws-pay-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    min-height: 38px;
    padding: 6px 0;
    border-bottom: 1px solid var(--card-border);
    font-size: 0.875rem;
}

.ws-pay-row:last-child {
    border-bottom: none;
}

.ws-pay-row > .ws-num {
    white-space: nowrap;
}

.ws-pay-total {
    font-weight: 700;
    font-size: 1rem;
}

.ws-pay-methods {
    gap: 0;
    padding-top: 4px;
    padding-bottom: 4px;
}

/* Raw text kept as typed (the stones of a buyback line): its own lines, monospace. */
.ws-caption-code {
    font-family: monospace;
    white-space: pre-wrap;
    word-break: break-word;
}

/* ---- Money cards and stat band (customer sheet, mockup validated on 2026-10-01) ----
   Shared blocks, not a page's own look: the card chrome is .ws-card, the colour sits on the icon badge and the figure
   only (tone classes), never on the card background. */

.ws-money-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 2.4fr);
    gap: 14px;
}

/* The five figures beside the two money cards had ~70px each in the customer sheet dialog: "104 999,99" ran into the
   next figure and "Aujourd'hui" was cut (recette 2026-10-05). Measured on the sheet's own width, not the screen's (a
   dialog is narrower than the window): under 1200px (about 140px per figure) the two cards share the first row and the
   band takes the second. */
.ws-money-wrap {
    container-type: inline-size;
}

@container (max-width: 1199.98px) {
    .ws-money-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .ws-money-row > .ws-stat-band {
        grid-column: 1 / -1;
    }
}

.ws-money-card {
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.ws-money-head {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

.ws-money-value {
    font-size: 1.625rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

.ws-icon-badge {
    width: 34px;
    height: 34px;
    border-radius: 10px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.ws-icon-badge.is-small {
    width: 30px;
    height: 30px;
    border-radius: 9px;
}

.ws-stat-band {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
}

.ws-stat {
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

/* inline-start: on the start side in Arabic too (left only drew the outer edge in RTL). */
.ws-stat + .ws-stat {
    border-inline-start: 1px solid var(--card-border);
}

/* A band of 3 or 4 figures instead of 5 (cash statistics: the equation, then the results). */
.ws-stat-band.is-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.ws-stat-band.is-4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* A band on several rows (workshop pilot): 1px gaps on the border colour draw the dividers between cells and between
   rows, in any column count; the last cell runs to the end of its row so no empty slot shows. */
.ws-stat-band.is-grid {
    gap: 1px;
    background-color: var(--card-border);
    overflow: hidden;
}

.ws-stat-band.is-grid > .ws-stat {
    background-color: var(--mud-palette-surface);
    border-inline-start: none;
}

.ws-stat-band.is-grid > .ws-stat:last-child {
    grid-column-end: -1;
}

/* Tabs that are links (one route per tab): the same underline as MudTabs in .ws-tabs. */
.ws-link-tabs {
    display: flex;
    gap: 2px;
    border-bottom: 1px solid var(--card-border);
    overflow-x: auto;
}

.ws-link-tabs a {
    height: 46px;
    padding: 0 14px;
    display: inline-flex;
    align-items: center;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    color: var(--mud-palette-text-secondary);
    font-size: 0.875rem;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none;
}

.ws-link-tabs a:hover {
    color: var(--mud-palette-text-primary);
}

.ws-link-tabs a.is-active {
    color: var(--mud-palette-primary);
    border-bottom-color: var(--mud-palette-primary);
}

/* A card that fills the height of its grid cell, so two cards side by side line up. */
.ws-card.ws-fill {
    height: 100%;
}

.ws-stat-value {
    font-size: 1.125rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* One event of a history: icon badge, what and when, the amount on the right. */
.ws-event {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 0;
    border-top: 1px solid var(--card-border);
}

.ws-event-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ws-event-amount {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    white-space: nowrap;
}

.ws-month {
    padding: 10px 0 6px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

@media (max-width: 959.98px) {
    .ws-money-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .ws-money-row > .ws-stat-band {
        grid-column: 1 / -1;
    }

    .ws-stat-band {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    /* Four figures on three columns left the last one alone on its row. */
    .ws-stat-band.is-4 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .ws-stat + .ws-stat {
        border-inline-start: none;
    }
}

/* ---- Left menu (shared components, validated 2026-10-02) ----
   An icon on every link, every group collapsible, the group title on its own grey band in purple capitals so it is
   never read as the active link (light purple fill). The old rule in Investock.css draws the active link with a
   purple bar on the end side: overridden here. */

/* The drawer spans the whole window height: without room above and below, the first link ("Accueil") and the last
   one touched the edges (owner, 2026-10-07). */
.app-nav {
    padding-block: 10px;
}

.app-nav .mud-nav-link {
    border-radius: 10px;
    margin-inline: 8px;
    width: calc(100% - 16px);
}

.app-nav .app-nav-group.mud-nav-link {
    margin-block: 10px 2px;
    padding-block: 7px !important;
    background: var(--ws-head);
    color: var(--tint-purple-fg);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* Letter spacing breaks the joining of Arabic letters. */
[dir="rtl"] .app-nav .app-nav-group.mud-nav-link {
    letter-spacing: 0;
}

.app-nav .app-nav-group.mud-nav-link .mud-nav-link-expand-icon {
    color: var(--tint-purple-fg);
}

/* .mud-navmenu in the selector: MudBlazor's own active rule is ".mud-navmenu.mud-navmenu-default .mud-nav-link.active"
   and sets font-weight 500 !important. */
.app-nav.mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled) {
    border-inline-end: 0;
    background: var(--tint-purple-bg);
    color: var(--tint-purple-fg);
    font-weight: 700 !important;
}

.app-nav.mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled) .mud-nav-link-icon {
    color: var(--tint-purple-fg);
}

.app-nav .app-nav-discover.mud-nav-link,
.app-nav .app-nav-discover.mud-nav-link .mud-nav-link-icon {
    color: var(--tint-purple-fg);
    font-weight: 600;
}

/* ---- Top bar and home (shared components, validated 2026-10-02) ---- */

.app-bar.mud-appbar {
    border-bottom: 1px solid var(--card-border);
}

.app-bar-logo {
    height: 40px;
}

/* Phones: at 375 px the bar overflowed and pushed the account menu (profile, logout) off-screen (recette of 2026-10-06).
   Smaller logo, no separator, the language and account buttons keep their icon only; their aria-label stays. */
@media (max-width: 599.98px) {
    /* 12 px, not less: the menu button sits at Edge.Start, which MudBlazor pulls 12 px to the left. */
    .app-bar .mud-toolbar-gutters {
        padding-inline: 12px;
    }

    .app-bar-logo {
        height: 28px;
    }

    .app-bar-sep,
    .app-bar-lang > span,
    .app-bar-user > .mud-icon-root {
        display: none;
    }

    .app-bar-lang {
        padding: 0 6px;
    }

    .app-bar-user {
        padding-inline: 4px;
        gap: 4px;
    }
}

.app-bar-lang,
.app-bar-user {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 36px;
    padding: 0 10px;
    border: 0;
    border-radius: 10px;
    background: transparent;
    color: inherit;
    font: inherit;
    font-size: 0.8rem;
    font-weight: 700;
    cursor: pointer;
}

.app-bar-user {
    height: 40px;
    padding-block: 0;
    padding-inline: 12px 6px;
    gap: 10px;
    font-weight: 500;
}

.app-bar-lang:hover,
.app-bar-user:hover {
    background: var(--ws-head);
}

.app-bar-user-name {
    color: var(--mud-palette-text-secondary);
}

.app-bar-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    font-size: 0.85rem;
    font-weight: 700;
}

.app-home {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding: 56px 24px 60px;
    text-align: center;
}

.app-home-logo {
    height: 96px;
    max-width: 100%;
    object-fit: contain;
}

/* ---- Shared list (EntityTable), every screen (shared components, validated 2026-10-02) ----
   The same chrome the redesigned pages had under .ws-page, now on every list: card instead of the heavy shadow, tinted
   header, hairlines, sentence case on its buttons. */

.app-list .mud-elevation-25 {
    box-shadow: var(--card-shadow) !important;
    border: 1px solid var(--card-border);
    border-radius: 14px !important;
}

.app-list .mud-table.mud-elevation-25 .mud-table-head .mud-table-cell {
    background: var(--ws-head);
    border-bottom: 1px solid var(--card-border);
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

.app-list .mud-table.mud-elevation-25 .mud-table-body .mud-table-cell {
    border-bottom: 1px solid var(--card-border);
}

.app-list .mud-button-root {
    text-transform: none;
    letter-spacing: normal;
    font-weight: 600;
}

html.theme-dark .app-list .mud-button-filled.mud-button-filled-primary {
    color: #17131f;
}

.app-list-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 40px 16px;
    text-align: center;
}

.app-list-empty .app-list-empty-icon {
    width: 40px;
    height: 40px;
    padding: 8px;
    border-radius: 12px;
    background: var(--tint-neutral-bg);
    color: var(--tint-neutral-fg);
}

.app-list-empty-title {
    font-weight: 600;
}

.app-list-empty-hint {
    font-size: 0.85rem;
    font-weight: 400;
    color: var(--mud-palette-text-secondary);
}

/* A destructive item of a row menu (Supprimer). */
.mud-menu-item.app-menu-danger,
.mud-menu-item.app-menu-danger .mud-menu-item-text {
    color: var(--tint-red-fg);
}

/* ---- Sign-in pages (shared components, validated 2026-10-02): sentence case on their buttons. ---- */
.app-auth .mud-button-root {
    text-transform: none;
    letter-spacing: normal;
    font-weight: 600;
}

.app-auth-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    text-align: center;
}

.app-auth-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 14px;
}

/* ---- Small shared pieces (shared components, validated 2026-10-02) ---- */

.app-readonly {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 2px 2px 6px;
}

.app-readonly-value {
    min-height: 20px;
    font-size: 0.875rem;
    font-weight: 600;
    word-break: break-word;
}

.app-kpi {
    display: flex;
    flex-direction: column;
    gap: 6px;
    height: 100%;
    padding: 16px;
    box-sizing: border-box;
}

.app-kpi-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 9px;
}

.app-kpi-value {
    font-size: 1.15rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}

/* The current choice of a menu (the active language). */
.mud-menu-item.app-menu-active {
    background: var(--tint-purple-bg);
    color: var(--tint-purple-fg);
    font-weight: 600;
}

.mud-menu-item.app-menu-active .mud-icon-root {
    color: var(--tint-purple-fg);
}

/* Notification drawer: one row per notification, a tinted icon badge, the count in the section title. */
.app-notif-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 0 12px 16px;
}

.app-notif-section {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 12px;
}

.app-notif-section-title {
    font-size: 0.85rem;
    font-weight: 700;
}

.app-notif-row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    width: 100%;
    padding: 10px 8px;
    border: 0;
    border-top: 1px solid var(--card-border);
    background: transparent;
    color: inherit;
    font: inherit;
    font-size: 0.85rem;
    text-align: start;
    cursor: pointer;
}

.app-notif-row:hover {
    background: var(--ws-head);
}

.app-notif-badge {
    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 9px;
}

.app-notif-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.app-notif-check {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 10px 12px;
    border-radius: 10px;
    font-size: 0.85rem;
}

/* Not-found page: the kit card a little below the top of the screen. */
.app-notfound {
    margin-top: 15vh;
}

/* Plans dialog: two kit cards, the price as a big figure, one feature per line with a green tick. */
.app-plans-intro {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    margin-bottom: 16px;
}

.app-plan-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
    height: 100%;
    padding: 20px;
    box-sizing: border-box;
}

.app-plan-price {
    display: flex;
    align-items: baseline;
    gap: 6px;
}

.app-plan-feature {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

/* Glossary: term and definition on two columns. */
.app-glossary-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
    gap: 16px;
    padding: 8px 0;
    border-top: 1px solid var(--card-border);
    font-size: 0.85rem;
    line-height: 1.45;
}

.app-glossary-term {
    font-weight: 700;
}

/* A reminder with no link: clicking only marks it read, so it does not dress up as a link. */
.app-notif-row.is-static {
    cursor: default;
}

.app-notif-row.is-static:hover {
    background: transparent;
}

.app-notif-check[role="button"] {
    cursor: pointer;
}

.app-notif-list .mud-button-root {
    text-transform: none;
    letter-spacing: normal;
    font-weight: 600;
    white-space: nowrap;
}

.app-notif-section {
    gap: 8px;
}

/* Phone toolbar of a list: Exporter and Recharger are round like the main action next to them (owner, 2026-10-02:
   no square buttons beside a round one). Same 48 px circle as a medium MudFab. */
.app-list .mud-icon-button.app-list-fab {
    width: 48px;
    height: 48px;
    border-radius: 50%;
}

/* ---- Cash day sheet (mockup validated on 2026-10-02) ----
   One money card per payment method of the day: as many as the day used, side by side, wrapping on a narrow screen
   (.ws-money-row is the fixed two cards + stat band grid of the customer sheet). */
.ws-method-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 14px;
}

/* Recap of what an action acts on, at the top of a confirmation dialog (cancel a charge, cash dialogs mockup
   2026-10-02): the amount in a neutral box, the facts that identify it in a blue box beside it. */
.ws-recap {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: stretch;
}

.ws-recap-amount {
    flex-shrink: 0;
    min-width: 190px;
    border-radius: 10px;
    background: var(--tint-neutral-bg);
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.ws-recap-facts {
    flex: 1 1 240px;
    border-radius: 10px;
    background: var(--tint-blue-bg);
    padding: 10px 14px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* The same strip in another tone: gold while money is still owed, green once settled (invoice history). */
.ws-recap-facts.ws-tone-gold { background: var(--tint-gold-bg); color: var(--tint-gold-fg); }
.ws-recap-facts.ws-tone-green { background: var(--tint-green-bg); color: var(--tint-green-fg); }

.ws-recap-facts .ws-recap-line {
    display: flex;
    justify-content: space-between;
    gap: 12px;
}

/* An amount that no longer counts (a cancelled charge): still readable, visibly struck. */
.ws-strike {
    text-decoration: line-through;
}

/* After the tablet rule on purpose: on a phone the cash statistics figures carry long amounts and explanations, two
   per row, not three. */
@media (max-width: 599.98px) {
    .ws-stat-band.is-3,
    .ws-stat-band.is-4 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* The running total of an entry against what is due (sales checkout): what was typed on one side, what is left (or
   too much) on the other. Its tone comes from a .ws-tone-* class: gold while money is missing, red when over, green
   when it matches. */
.ws-sum-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    border-radius: 10px;
}

.ws-sum-bar > div:last-child {
    text-align: end;
}

.ws-sum-bar .ws-caption {
    color: inherit;
    opacity: 0.85;
}

.ws-sum-bar .ws-strong {
    display: block;
    font-size: 1.125rem;
    font-variant-numeric: tabular-nums;
}

/* A short list of cases in a dialog (sort help): plain bullets, indented on the start side (right in Arabic). */
.ws-bullets {
    list-style: disc;
    margin: 8px 0 0;
    padding-inline-start: 22px;
}

.ws-bullets li + li {
    margin-top: 2px;
}

/* A chip id (RFID EPC): one line, monospaced, always read left to right (the leading "…" of a shortened id stays on the
   left in Arabic too). */
.ws-epc {
    font-family: 'Roboto Mono', monospace;
    font-size: 0.8rem;
    white-space: nowrap;
    direction: ltr;
    unicode-bidi: isolate;
}

/* The scanner's capture field: focused but invisible, the barcode reader types into it (was an inline style). */
.ws-scanner-input {
    position: fixed;
    top: 0;
    left: 0;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

/* The scanner's waiting frame: a reading area with its state ("Prêt à lire", "En attente d'un nouveau scan"). */
.ws-scan-frame {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 32px 16px;
    border: 2px dashed var(--card-border);
    border-radius: 14px;
    text-align: center;
}

/* A code read by a scanner (work center, label): a larger grey frame, readable from a distance at the bench. */
.ws-code-frame {
    border-radius: 10px;
    background: var(--tint-neutral-bg);
    color: var(--mud-palette-text-primary);
    padding: 14px 16px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 1.4rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    overflow-wrap: anywhere;
    direction: ltr;
    unicode-bidi: isolate;
}

/* A count split by outcome: a sentence over a thin bar (transfers list "Pièces"). The legend explains the colors. */
.ws-split {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 170px;
}

.ws-split-bar {
    display: flex;
    height: 6px;
    gap: 2px;
    border-radius: 999px;
    overflow: hidden;
    background: var(--tint-neutral-bg);
}

.ws-split-bar > span,
.ws-swatch {
    display: inline-block;
}

/* A one-line share of a long transfer must stay visible next to the 2px gaps. */
.ws-split-bar > span {
    min-width: 3px;
}

.ws-split-bar > .is-green, .ws-swatch.is-green { background: var(--tint-green-fg); }
.ws-split-bar > .is-green-soft, .ws-swatch.is-green-soft { background: var(--tint-green-fg); opacity: 0.45; }
.ws-split-bar > .is-gold, .ws-swatch.is-gold { background: var(--tint-gold-fg); }
.ws-split-bar > .is-red, .ws-swatch.is-red { background: var(--tint-red-fg); }
.ws-split-bar > .is-dark, .ws-swatch.is-dark { background: var(--tint-neutral-fg); }
.ws-split-bar > .is-blue, .ws-swatch.is-blue { background: var(--tint-blue-fg); }
.ws-split-bar > .is-purple, .ws-swatch.is-purple { background: var(--mud-palette-primary); }
.ws-split-bar > .is-grey, .ws-swatch.is-grey { background: var(--tint-neutral-fg); opacity: 0.3; }

.ws-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 16px;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

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

.ws-swatch {
    width: 8px;
    height: 8px;
    border-radius: 2px;
}

/* ---- Help center (mockup validated 2026-10-02) ----
   The categories in a rail on the start side, the content next to it; every article is one row of a list card. */

/* The top of a list card: its main button on the start side, the count on the end side. */
.ws-card-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 16px 20px;
}

.ws-help-layout {
    display: grid;
    grid-template-columns: 272px minmax(0, 1fr);
    gap: 20px;
    align-items: start;
}

.ws-help-content {
    display: flex;
    flex-direction: column;
    gap: 16px;
    min-width: 0;
}

.ws-help-rail {
    padding: 18px 12px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ws-help-rail h2 {
    margin: 0 0 6px;
    padding: 0 10px;
    font-size: 0.875rem;
    font-weight: 700;
}

.ws-help-rail a {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 38px;
    padding: 0 10px;
    border-radius: 10px;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
    text-decoration: none;
}

.ws-help-rail a .mud-icon-root {
    color: var(--mud-palette-text-secondary);
}

.ws-help-rail a:hover {
    background-color: var(--tint-neutral-bg);
}

.ws-help-rail a.is-active {
    background-color: var(--tint-purple-bg);
    color: var(--tint-purple-fg);
    font-weight: 700;
}

.ws-help-rail a.is-active .mud-icon-root {
    color: var(--tint-purple-fg);
}

.ws-help-count {
    margin-inline-start: auto;
    min-width: 24px;
    height: 20px;
    padding: 0 7px;
    box-sizing: border-box;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: var(--tint-neutral-bg);
    color: var(--mud-palette-text-secondary);
}

.ws-help-rail a.is-active .ws-help-count {
    background-color: var(--mud-palette-surface);
    color: var(--tint-purple-fg);
}

.ws-help-intro {
    display: flex;
    gap: 16px;
    align-items: center;
}

.ws-help-cats {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
}

.ws-help-cat {
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    color: var(--mud-palette-text-primary);
    text-decoration: none;
}

.ws-help-cat:hover {
    border-color: var(--mud-palette-primary);
}

.ws-help-row:hover {
    background-color: var(--tint-neutral-bg);
}

.ws-help-cat-name {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 0.95rem;
    font-weight: 700;
}

.ws-help-cat-more {
    margin-top: auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--tint-purple-fg);
}

.ws-help-list {
    overflow: hidden;
}

.ws-help-list-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 16px 20px;
    border-bottom: 1px solid var(--card-border);
    background-color: var(--tint-neutral-bg);
}

.ws-help-list-head h3 {
    margin: 0;
    font-size: 0.875rem;
    font-weight: 700;
}

.ws-help-row {
    display: flex;
    gap: 14px;
    align-items: flex-start;
    padding: 16px 20px;
    color: var(--mud-palette-text-primary);
    text-decoration: none;
}

.ws-help-row + .ws-help-row {
    border-top: 1px solid var(--card-border);
}

.ws-help-row-text {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    flex-grow: 1;
}

.ws-help-row-title {
    font-size: 0.9rem;
    font-weight: 700;
}

.ws-help-row-summary {
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--mud-palette-text-secondary);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* The searched words: the soft gold of the mockup rather than the browser's bright yellow. */
.ws-help-row mark,
.ws-help-article-head mark {
    background-color: var(--tint-gold-bg);
    color: inherit;
    padding: 0 2px;
    border-radius: 3px;
}

.ws-help-row-meta {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 4px;
}

.ws-help-chevron {
    align-self: center;
    color: var(--mud-palette-text-disabled);
}

/* The chevrons point to where the reader goes next: the other way in Arabic. */
[dir="rtl"] .ws-help-chevron,
[dir="rtl"] .ws-crumbs .ws-text-muted,
[dir="rtl"] .ws-help-cat-more .mud-icon-root,
[dir="rtl"] .ws-help-related .mud-icon-root {
    transform: scaleX(-1);
}

.ws-help-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 8px 0;
    text-align: center;
}

.ws-crumbs {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    font-size: 0.8125rem;
}

.ws-crumbs a {
    font-weight: 600;
    color: var(--mud-palette-primary);
    text-decoration: none;
}

.ws-crumbs [aria-current] {
    color: var(--mud-palette-text-secondary);
}

.ws-help-article-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 20px;
    align-items: start;
}

.ws-help-article {
    padding: 24px 40px 36px;
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.ws-help-article-head {
    max-width: 720px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.ws-help-article-head h1 {
    margin: 0;
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.3;
}

.ws-help-article-meta {
    display: flex;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary);
}

.ws-help-article-meta > span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.ws-help-side {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.ws-help-side .ws-card {
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.ws-help-side h2 {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 700;
}

.ws-help-related a {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    padding: 11px 0;
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: none;
    color: var(--mud-palette-text-primary);
}

.ws-help-related a + a {
    border-top: 1px solid var(--card-border);
}

/* The article body is HTML written in the editor: readable measure, its own headings, tables and marks. */
.help-article-content { max-width: 720px; font-size: 0.95rem; line-height: 1.7; }
.help-article-content h1 { font-size: 1.4rem; font-weight: 700; margin: 1.5rem 0 0.75rem; }
.help-article-content h2 { font-size: 1.125rem; font-weight: 700; margin: 1.6rem 0 0.6rem; }
.help-article-content h3 { font-size: 1rem; font-weight: 700; margin: 1rem 0 0.5rem; }
.help-article-content p { margin-bottom: 0.875rem; }
.help-article-content ul, .help-article-content ol { margin-bottom: 0.875rem; padding-inline-start: 1.4rem; }
.help-article-content li { margin-bottom: 0.35rem; }
.help-article-content img { max-width: 100%; border-radius: 10px; margin: 0.75rem 0; }
.help-article-content table { width: 100%; border-collapse: collapse; margin: 0.75rem 0; }
.help-article-content th, .help-article-content td { border: 1px solid var(--card-border); padding: 8px 12px; text-align: start; }
.help-article-content th { background: var(--tint-neutral-bg); font-weight: 600; }
.help-article-content blockquote { border-inline-start: 3px solid var(--mud-palette-primary); padding: 0.5rem 1rem; margin: 0.75rem 0; background: var(--tint-blue-bg); border-start-end-radius: 8px; border-end-end-radius: 8px; }
.help-article-content mark { background: var(--tint-gold-bg); color: inherit; padding: 1px 3px; border-radius: 3px; }

@media (max-width: 959.98px) {
    .ws-help-layout,
    .ws-help-article-layout {
        grid-template-columns: minmax(0, 1fr);
    }

    .ws-help-cats {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .ws-help-article {
        padding: 20px;
    }
}

@media (max-width: 599.98px) {
    /* The pilot bands carry a chart and a caption per cell: two per row on a phone. */
    .ws-stat-band.is-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .ws-help-cats {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ---- Support tickets (mockup validated 2026-10-02) ----
   The conversation next to a side column; a message is a bordered block, an internal note a gold one. */

.ws-ticket-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 360px;
    gap: 20px;
    align-items: start;
}

.ws-msg {
    border: 1px solid var(--card-border);
    border-radius: 12px;
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    background-color: var(--mud-palette-surface);
}

.ws-msg.is-internal {
    background-color: var(--tint-gold-bg);
    border-color: color-mix(in srgb, var(--tint-gold-fg) 25%, transparent);
}

.ws-msg-head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.ws-msg-date {
    margin-inline-start: auto;
}

.ws-msg-body {
    font-size: 0.875rem;
    line-height: 1.6;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.ws-msg-files {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.ws-file-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 36px;
    padding-inline: 12px 4px;
    border: 1px solid var(--card-border);
    border-radius: 8px;
    font-size: 0.8125rem;
    background-color: var(--mud-palette-surface);
    max-width: 100%;
}

.ws-file-chip > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ws-history-row {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 0;
    font-size: 0.85rem;
}

.ws-history-row + .ws-history-row {
    border-top: 1px solid var(--card-border);
}

@media (max-width: 959.98px) {
    .ws-ticket-layout {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ---- Dashboard (mockup validated 2026-10-02) ----
   Groups titled on the page, chart cards with their head under the tabs, figure cards with a share per store,
   rankings as MudProgressLinear bars. */

.ws-dash-group {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.ws-dash-chart {
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.ws-dash-chart-head {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 18px 24px 0;
}

.ws-dash-chart-tools {
    display: flex;
    justify-content: flex-end;
    padding: 4px 24px 0;
}

.ws-dash-chart .control-section {
    padding: 8px 16px 16px;
}

.ws-dash-share,
.ws-dash-bars {
    display: flex;
    flex-direction: column;
    gap: 10px;
    height: 100%;
    min-width: 0;
}

.ws-dash-figure {
    font-size: 1.3rem;
    line-height: 1.25;
    font-weight: 700;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    background: none !important;
}

.ws-dash-shares {
    display: flex;
    flex-direction: column;
}

.ws-dash-share-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 5px 8px;
    padding: 8px 0;
    border-top: 1px solid var(--card-border);
    font-size: 0.8rem;
}

.ws-dash-share-row > :nth-child(2),
.ws-dash-share-row > :nth-child(4) {
    text-align: end;
}

.ws-dash-bar-row {
    display: grid;
    grid-template-columns: minmax(90px, 170px) minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    padding: 6px 0;
    font-size: 0.8125rem;
}

.ws-dash-bar-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ws-dash-cycle {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-top: 12px;
    border-top: 1px solid var(--card-border);
}

.ws-dash-cycle-figures {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
}

.ws-dash-filter {
    width: 240px;
    max-width: 100%;
}

@media (max-width: 599.98px) {
    .ws-dash-bar-row {
        grid-template-columns: minmax(0, 1fr) auto;
    }

    .ws-dash-bar-row .mud-progress-linear {
        grid-column: 1 / -1;
        grid-row: 2;
    }
}

/* ---- Material counts (mockup validated 2026-10-02) ---- */

/* The facts of the cycle a dialog acts on, on a grey band. */
.ws-facts.ws-facts-band {
    border-top: none;
    padding: 12px 16px;
    border-radius: 10px;
    background-color: var(--tint-neutral-bg);
}

.ws-dash-filter-note {
    max-width: 520px;
    text-align: end;
    line-height: 1.45;
}

.ws-cycle-event {
    display: flex;
    gap: 12px;
    padding: 14px 0;
}

.ws-cycle-event + .ws-cycle-event {
    border-top: 1px solid var(--card-border);
}

.ws-cycle-event-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.ws-change-row {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    padding: 7px 0;
    border-top: 1px solid var(--card-border);
    font-size: 0.8125rem;
}

.ws-change-row > :last-child {
    text-align: end;
}

.ws-change-old {
    color: var(--mud-palette-text-disabled);
    text-decoration: line-through;
}

.ws-change-arrow {
    vertical-align: -4px;
}

[dir="rtl"] .ws-change-arrow {
    transform: scaleX(-1);
}

/* ---- Suppliers, stores and billing (mockup validated 2026-10-02) ---- */

/* A file an issuer owns (letterhead, stamp): a bordered cell with its name and its two buttons. */
.ws-file-cell {
    border: 1px solid var(--card-border);
    border-radius: 12px;
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    height: 100%;
}

/* The supplier analysis: the amount due on the period next to the band of five figures. */
.ws-supplier-kpis {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 2.6fr);
    gap: 14px;
}

@media (max-width: 959.98px) {
    .ws-supplier-kpis {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* The invoice template editor: settings, then the preview panel that stays in view. */
.ws-template-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 20px;
    align-items: start;
}

.ws-template-preview {
    position: sticky;
    top: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

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

    .ws-template-preview {
        position: static;
    }
}

/* ---- Pipeline (mockup validated 2026-10-02) ---- */

.ws-pipeline-kpis {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 2.4fr);
    gap: 14px;
}

/* The six stages side by side without a horizontal scroll on a desktop. */
.ws-pipeline-board {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(170px, 1fr);
    gap: 12px;
    overflow-x: auto;
    padding-top: 8px;
}

.ws-pipeline-column {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px;
    border-radius: 12px;
    background-color: var(--tint-neutral-bg);
    min-height: 460px;
    min-width: 0;
}

/* An empty stage keeps its frame, faded: the column is there, it just holds no deal. */
.kanban-empty {
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 8px;
    opacity: .6;
}

.ws-deal-card {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 12px;
    margin: 6px 0;
    border-radius: 12px;
    border: 1px solid var(--card-border);
    background-color: var(--mud-palette-surface);
    transition: transform .12s ease, box-shadow .12s ease;
}

.ws-deal-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(93, 63, 211, .18);
}

@media (max-width: 959.98px) {
    .ws-pipeline-kpis {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* A small coloured dot before a history line, on the tone of its kind. */
.ws-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
    background-color: currentColor;
}

/* ---- Appointments (mockup validated 2026-10-02) ----
   One tint per kind: the jeweller reads the day without opening a block. A tinted block in the grid, a coloured
   side line in the agenda list (a full bar per line turned the list into a rainbow). */
.rdv-fitting  { --rdv-bg: var(--tint-purple-bg); --rdv-fg: var(--tint-purple-fg); }
.rdv-delivery { --rdv-bg: var(--tint-green-bg); --rdv-fg: var(--tint-green-fg); }
.rdv-drop     { --rdv-bg: var(--tint-gold-bg); --rdv-fg: var(--tint-gold-fg); }
.rdv-pickup   { --rdv-bg: var(--tint-blue-bg); --rdv-fg: var(--tint-blue-fg); }
.rdv-advice   { --rdv-bg: var(--tint-neutral-bg); --rdv-fg: var(--tint-neutral-fg); }
.rdv-other    { --rdv-bg: var(--mud-palette-surface); --rdv-fg: var(--tint-neutral-fg); }

/* Whoever sets the background sets the text, or the inherited colour becomes unreadable. */
.rdv {
    background: var(--rdv-bg) !important;
    border: 1px solid var(--rdv-fg) !important;
}

.rdv, .rdv * {
    color: var(--rdv-fg) !important;
}

/* !important on the side line: Syncfusion sets its own, more specific, in its default indigo. */
.e-agenda-view .rdv {
    background: transparent !important;
    border: none !important;
    border-inline-start: 4px solid var(--rdv-fg) !important;
    padding-inline-start: 10px;
}

.e-agenda-view .rdv .e-subject   { color: var(--mud-palette-text-primary) !important; }
.e-agenda-view .rdv .e-date-time { color: var(--mud-palette-text-secondary) !important; }

/* A cancelled or missed appointment stays visible but fades: it belongs to the story, not to the attention. */
.rdv-closed {
    opacity: .45;
    text-decoration: line-through;
}

.e-schedule .e-appointment {
    border-radius: 6px;
}

/* "Total saisi / Restant" under the payment fields of an encashment, as on the sale checkout. */
.ws-total-bar {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 10px 14px;
    border-radius: 10px;
    background-color: var(--tint-neutral-bg);
    font-size: 0.875rem;
}

/* An identity photo shown in full (buyback sheet): a light stage, the image fits and stays captive of the app. */
.ws-photo-stage {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 60vh;
    border-radius: 10px;
    background-color: var(--tint-neutral-bg);
    user-select: none;
    -webkit-user-select: none;
}

.ws-photo-stage img {
    max-width: 100%;
    max-height: 75vh;
    object-fit: contain;
    user-select: none;
    -webkit-user-select: none;
    -webkit-user-drag: none;
    pointer-events: none;
}

/* A customer tag: a grey pill with a dot of the tag colour, and a small cross when it can be removed. */
.ws-tag-pill {
    gap: 6px;
}

.ws-tag-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    margin-inline-end: -5px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    cursor: pointer;
}

.ws-tag-remove:hover:not(:disabled) {
    background-color: rgba(20, 16, 40, 0.08);
}

.ws-tag-remove:disabled {
    cursor: default;
    opacity: 0.5;
}

/* The tag list of the "manage tags" window: one line per tag, separated by a hairline. */
.ws-tag-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 6px 4px 6px 6px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.ws-tag-row:last-child {
    border-bottom: 0;
}

.ws-tag-row .ws-tag-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
}

/* ---- Adoption (mockup validated 2026-10-02) ----
   A money card: icon and label, the amount, one line that says what it counts. A segment row is a real button that
   opens the tenant sheet. A chevron that points "forward" flips in Arabic. */
.ws-money-card {
    display: flex;
    flex-direction: column;
    gap: 6px;
    height: 100%;
}

.ws-segment-row {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 11px 0;
    border: 0;
    border-top: 1px solid var(--mud-palette-lines-default);
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: start;
    cursor: pointer;
}

.ws-segment-row:hover {
    background-color: var(--tint-neutral-bg);
}

[dir="rtl"] .ws-flip-rtl {
    transform: scaleX(-1);
}

/* An onboarding milestone of the adoption sheet: a green check when reached, an empty ring when not. */
.ws-onboarding-step {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    border-top: 1px solid var(--mud-palette-lines-default);
    font-size: 0.875rem;
    color: var(--mud-palette-text-secondary);
}

.ws-onboarding-step.is-done {
    color: var(--mud-palette-text-primary);
}

.ws-onboarding-check {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    border-radius: 50%;
    box-shadow: inset 0 0 0 2px var(--mud-palette-lines-default);
}

.ws-onboarding-step.is-done .ws-onboarding-check {
    box-shadow: none;
    background-color: var(--tint-green-bg);
    color: var(--tint-green-fg);
}

/* An entry of a prospect's activity log: type badge, subject and content, date and type, a delete button. The row
   opens the entry for editing. */
.ws-activity-row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 0;
    border-top: 1px solid var(--mud-palette-lines-default);
    cursor: pointer;
}

.ws-activity-row:hover {
    background-color: var(--tint-neutral-bg);
}

.ws-activity-row:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

/* Provider pipeline (mockup validated 2026-10-02): the column head line under the stage pill, the next action strip
   of a deal card (purple when planned, gold when missing or late). */
.ws-pipeline-column-head {
    padding-bottom: 6px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.ws-deal-next {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    border-radius: 8px;
    font-size: 0.72rem;
}

/* A unit written after a stat value ("750 DH HT / mois") stays on the value's line. */
.ws-stat-value .ws-caption {
    display: inline;
    font-weight: 500;
}

/* CRM dashboard (mockup validated 2026-10-02): a stat band inside a card keeps its own hairline frame; a stat that
   leads somewhere is a link; a list row of a card (task, activity) separated by a hairline. */
.ws-stat-band-flat {
    border: 1px solid var(--card-border);
    border-radius: 10px;
}

.ws-stat-link {
    color: inherit;
    text-decoration: none;
}

.ws-stat-link:hover {
    color: var(--mud-palette-primary);
    text-decoration: underline;
}

.ws-list-row {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 0;
    border-top: 1px solid var(--mud-palette-lines-default);
    color: inherit;
    text-decoration: none;
}

a.ws-list-row:hover .ws-strong {
    color: var(--mud-palette-primary);
}

.ws-deal-card:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* Facts directly under a card title (company block of the account sheet): no top rule, no top padding. */
.ws-facts.ws-facts-plain {
    padding-top: 0;
    border-top: 0;
}

/* ---- Shell leftovers (mockup validated 2026-10-02) ----
   The signed-in person of the account menu; the shared light tooltip (definitions, glossary); the help drawer title
   and its purple links. */
.ws-person-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px 12px;
}

.ws-person-avatar {
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    font-weight: 700;
}

.ws-person-name,
.ws-person-email {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mud-tooltip.ws-tooltip {
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    border: 1px solid var(--card-border);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(20, 16, 40, 0.12);
    font-size: 0.8rem;
}

.ws-tooltip-body {
    max-width: 260px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    text-align: start;
    line-height: 1.45;
}

.ws-help-tip-icon {
    font-size: 1rem !important;
    color: var(--ws-faint, var(--mud-palette-text-secondary));
    cursor: help;
    vertical-align: text-bottom;
}

.ws-drawer-title {
    font-size: 1.0625rem;
    font-weight: 600;
}

.ws-help-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 700;
    color: var(--mud-palette-primary);
    text-decoration: none;
}

.ws-help-link:hover {
    text-decoration: underline;
}

/* ---- Quick sale (sale sheet, mockup validated 2026-10-04) ----
   The pieces on the left, the till on the right and sticky under the tab bar. Under md the till leaves for a bar
   fixed at the bottom (what is left to pay, Encaisser) and a bottom sheet with its detail; the client and the store
   then sit above the pieces. Amounts never wrap. */

/* The sheet and its till side by side, the till from the top of the page. */
.ws-sale-shell.has-till {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 380px;
    gap: 20px;
    align-items: start;
}

.ws-sale-shell-main {
    display: flex;
    flex-direction: column;
    gap: 20px;
    min-width: 0;
}

.ws-sale-layout {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.ws-sale-main {
    display: flex;
    flex-direction: column;
    gap: 20px;
    min-width: 0;
}

.ws-sale-panel {
    position: sticky;
    top: calc(var(--mud-appbar-height) + 16px);
    max-height: calc(100vh - var(--mud-appbar-height) - 32px);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}

/* A screen too short for the whole till (a laptop with a small window): the till scrolls with the page rather than
   hiding Encaisser below the fold. */
@media (max-height: 720px) {
    .ws-sale-panel {
        position: static;
    }
}

.ws-sale-client-top {
    display: none;
}

.ws-sale-panel-client {
    padding: 16px;
    border-bottom: 1px solid var(--card-border);
}

.ws-sale-client-fields {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.ws-sale-client-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.ws-sale-avatar {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--tint-purple-bg);
    color: var(--tint-purple-fg);
    font-size: 0.8125rem;
    font-weight: 700;
}

.ws-sale-client-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.ws-sale-client-text > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The ticket: total, what was already paid, what is left, read top to bottom as on a till receipt. */
.ws-ticket {
    padding: 14px 16px;
    background: var(--tint-neutral-bg);
    border-bottom: 1px solid var(--card-border);
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.ws-ticket-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    font-size: 0.84rem;
}

.ws-ticket-row:not(.ws-text-red) > span:first-child {
    color: var(--mud-palette-text-secondary);
}

.ws-ticket-row > span:last-child,
.ws-pay-row > span:last-child,
.ws-ticket-amount,
.ws-line-final,
.ws-line-detail,
.ws-sale-bar-value {
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.ws-ticket-total {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    margin-top: 6px;
    padding-top: 8px;
    border-top: 1px solid var(--mud-palette-lines-inputs);
    font-weight: 700;
}

.ws-ticket-amount {
    font-size: 1.625rem;
    font-weight: 800;
    letter-spacing: -0.02em;
}

.ws-sale-panel-body {
    padding: 12px 16px 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.ws-sale-panel-body .mud-button-root {
    min-height: 44px;
}

.ws-pay-modes {
    border: 1px solid var(--card-border);
    border-radius: 10px;
    padding: 2px 12px;
}

.ws-pay-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    min-height: 38px;
    font-size: 0.84rem;
}

.ws-pay-row + .ws-pay-row {
    border-top: 1px solid var(--card-border);
}

.ws-sale-panel-body .ws-sale-cashin {
    min-height: 52px;
    font-size: 1rem;
}

.ws-sale-panel-actions {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
}

.ws-sale-panel-actions .mud-menu,
.ws-sale-panel-actions .mud-menu .mud-button-root {
    width: 100%;
}

/* ---- Pieces of the sale: one row per piece, the final price on the right ---- */

.ws-sale-pieces {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.ws-sale-pieces-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    padding-block: 16px 12px;
    padding-inline: 20px 16px;
}

.ws-sale-pieces-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.ws-sale-pieces-actions .mud-button-root {
    min-height: 44px;
}

.ws-scan-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding-block: 0 14px;
    padding-inline: 20px 16px;
}

.ws-scan-box {
    position: relative;
    flex: 1;
    min-width: 0;
}

.ws-scan-suggest {
    position: absolute;
    inset-inline: 0;
    top: calc(100% + 4px);
    z-index: 30;
    list-style: none;
    margin: 0;
    padding: 4px;
    max-height: 360px;
    overflow-y: auto;
    background: var(--mud-palette-surface);
    border: 1px solid var(--card-border);
    border-radius: 12px;
    box-shadow: 0 12px 28px rgba(20, 16, 40, 0.16);
}

.ws-scan-suggest li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 10px;
    border-radius: 8px;
    cursor: pointer;
}

.ws-scan-suggest li:hover,
.ws-scan-suggest li.is-active {
    background: var(--tint-purple-bg);
}

.ws-scan-suggest .ws-line-thumb {
    width: 36px;
    height: 36px;
    cursor: pointer;
}

.ws-scan-field {
    flex: 1;
    min-width: 0;
    min-height: 52px;
    display: flex;
    align-items: center;
    gap: 10px;
    padding-inline: 14px;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: 12px;
    background: var(--mud-palette-surface);
    cursor: text;
}

.ws-scan-field:focus-within {
    border-color: var(--mud-palette-primary);
    box-shadow: 0 0 0 3px var(--tint-purple-bg);
}

.ws-scan-field input {
    flex: 1;
    min-width: 0;
    height: 50px;
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--mud-palette-text-primary);
    font: inherit;
    font-size: 1rem;
    font-weight: 600;
}

.ws-scan-field input::placeholder {
    color: var(--mud-palette-text-secondary);
    font-weight: 500;
}

.ws-scan-row .ws-scan-button {
    min-height: 52px;
    flex-shrink: 0;
}

.ws-line-list {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--card-border);
}

.ws-line-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-block: 10px;
    padding-inline: 20px 6px;
    border-bottom: 1px solid var(--card-border);
}

.ws-line-row:last-child {
    border-bottom: 0;
}

.ws-line-row.is-clickable {
    cursor: pointer;
}

.ws-line-row.is-clickable:hover {
    background: var(--mud-palette-action-default-hover);
}

.ws-line-row.is-clickable:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

.ws-line-row.is-cancelled .ws-line-name,
.ws-line-row.is-cancelled .ws-line-final {
    color: var(--mud-palette-text-secondary);
    text-decoration: line-through;
}

.ws-line-thumb {
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    border-radius: 9px;
    object-fit: cover;
    background: var(--tint-neutral-bg);
    cursor: zoom-in;
}

.ws-line-thumb-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--mud-palette-text-secondary);
    cursor: default;
}

.ws-line-thumb-icon.is-clickable {
    cursor: pointer;
}

/* ItemThumb: the square picture of an item in lists, tables and search results. The photo fills the square; without
   one, a quiet icon tile (2026-10-04). The size comes from the component through --thumb-size. */
.ws-thumb {
    width: var(--thumb-size, 44px);
    height: var(--thumb-size, 44px);
    flex-shrink: 0;
    border-radius: 9px;
    object-fit: cover;
    background: var(--tint-neutral-bg);
    vertical-align: middle;
}

.ws-thumb.is-contain {
    object-fit: contain;
}

.ws-thumb-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--mud-palette-text-secondary);
}

.ws-thumb.is-clickable {
    cursor: pointer;
}

/* A piece without photo on its preview: the same quiet tile as a sale line, at the size of a photo. */
.ws-photo-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    aspect-ratio: 4 / 3;
    max-height: 320px;
    border-radius: 12px;
    background: var(--tint-neutral-bg);
    color: var(--mud-palette-text-secondary);
    font-size: 0.875rem;
}

.ws-photo-empty .mud-icon-root {
    font-size: 3rem;
}

.ws-line-main {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ws-line-name {
    font-size: 0.875rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ws-line-qty {
    margin-inline-start: 6px;
    font-weight: 700;
    color: var(--tint-purple-fg);
}

.ws-line-sub {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 6px;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.ws-line-code {
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    color: var(--tint-purple-fg);
    text-decoration: none;
}

.ws-line-code:hover {
    text-decoration: underline;
}

.ws-line-amount {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    text-align: end;
}

.ws-line-final {
    font-size: 1rem;
    font-weight: 700;
}

.ws-line-detail {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.ws-line-menu {
    flex-shrink: 0;
    width: 44px;
    display: flex;
    justify-content: center;
}

/* The price of a line typed on its row (quick sale): the row grows a band under it. */
.ws-line-row.is-editing {
    flex-wrap: wrap;
    background: var(--tint-purple-bg);
}

.ws-line-editor {
    flex-basis: 100%;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding-inline-start: 56px;
    padding-inline-end: 10px;
    padding-bottom: 4px;
    cursor: default;
}

.ws-line-editor-fields {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr) minmax(0, 1.1fr) auto;
    gap: 10px;
    align-items: end;
}

.ws-line-editor-shown,
.ws-line-editor-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.ws-line-editor-shown .ws-strong {
    min-height: 48px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.ws-line-editor-field input {
    width: 100%;
    height: 48px;
    box-sizing: border-box;
    padding-inline: 12px;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: 10px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    font: inherit;
    font-size: 1rem;
    font-weight: 600;
    text-align: end;
    font-variant-numeric: tabular-nums;
    outline: 0;
}

.ws-line-editor-field input:focus {
    border-color: var(--mud-palette-primary);
    box-shadow: 0 0 0 3px var(--tint-purple-bg);
}

.ws-line-editor-field.is-main input {
    border-width: 2px;
    border-color: var(--mud-palette-primary);
    font-weight: 700;
}

.ws-line-editor .ws-line-editor-ok {
    min-height: 48px;
    min-width: 64px;
}

/* Keyboard hints mean nothing on a touch screen. */
@media (hover: none) and (pointer: coarse) {
    .ws-hide-touch {
        display: none;
    }
}

@media (max-width: 599.98px) {
    .ws-line-editor {
        padding-inline-start: 0;
    }

    .ws-line-editor-fields {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .ws-line-editor-shown {
        grid-column: 1 / -1;
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
    }

    .ws-line-editor-shown .ws-strong {
        min-height: 0;
    }

    .ws-line-editor .ws-line-editor-ok {
        grid-column: 1 / -1;
    }
}

.ws-sale-empty {
    margin-block: 0 16px;
    margin-inline: 20px 16px;
    padding: 28px 16px;
    border: 1px dashed var(--mud-palette-lines-inputs);
    border-radius: 12px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    text-align: center;
}

.ws-card-actions {
    display: flex;
    justify-content: flex-end;
    padding: 0 28px 20px;
}

/* The bottom bar and its sheet exist under md only. */
.ws-sale-bar {
    display: none;
}

.ws-sale-sheet.mud-drawer {
    height: auto !important;
    max-height: 85vh;
    overflow-y: auto;
    border-radius: 20px 20px 0 0;
}

/* The sheet belongs to the bottom bar: never on a wide screen, even left open when the window grows. */
@media (min-width: 960px) {
    .ws-sale-sheet.mud-drawer,
    .ws-sale-sheet ~ .mud-overlay {
        display: none;
    }
}

.ws-sale-sheet-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-block: 12px 4px;
    padding-inline: 16px 8px;
}

@media (max-width: 959.98px) {
    .ws-sale-shell.has-till {
        grid-template-columns: minmax(0, 1fr);
    }

    .ws-sale-layout {
        padding-bottom: 88px;
    }

    .ws-sale-panel {
        display: none;
    }

    .ws-sale-client-top {
        display: block;
        padding: 16px;
    }

    .ws-sale-bar {
        display: flex;
        align-items: center;
        gap: 12px;
        position: fixed;
        inset-inline: 0;
        bottom: 0;
        z-index: 20;
        padding: 10px 16px calc(12px + env(safe-area-inset-bottom));
        background: var(--mud-palette-surface);
        border-top: 1px solid var(--card-border);
        box-shadow: 0 -6px 18px rgba(20, 16, 40, 0.08);
    }

    .ws-sale-bar-amount {
        flex: 1;
        min-width: 0;
        min-height: 52px;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: flex-start;
        padding: 0;
        border: 0;
        background: none;
        color: inherit;
        font: inherit;
        text-align: start;
        cursor: pointer;
    }

    .ws-sale-bar-amount:disabled {
        cursor: default;
    }

    .ws-sale-bar-value {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        font-size: 1.375rem;
        font-weight: 800;
    }

    .ws-sale-bar .ws-sale-bar-action {
        min-height: 52px;
        flex-shrink: 0;
    }
}

@media (max-width: 599.98px) {
    .ws-hide-xs {
        display: none;
    }

    .ws-sale-pieces-head,
    .ws-scan-row {
        padding-inline: 14px 10px;
    }

    .ws-line-row {
        gap: 10px;
        padding-inline-start: 14px;
    }

    .ws-sale-bar-value {
        font-size: 1.25rem;
    }

    .ws-card-actions {
        padding: 0 16px 16px;
    }
}

/* Checkout dialog (mockup 2026-10-04): the running total and the buttons stay under the fields; on a phone the dialog
   takes the whole screen. */
.ws-checkout-foot {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.ws-checkout-buttons {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

.ws-checkout-buttons .mud-button-root {
    min-height: 52px;
}

@media (max-width: 599.98px) {
    /* !important: a heavy dialog may size itself inline for a desktop (the customer sheet sets width: 90vw). */
    .mud-dialog.ws-dialog-full-xs {
        margin: 0;
        width: 100% !important;
        max-width: 100% !important;
        height: 100%;
        max-height: 100%;
        min-height: 0 !important;
        border-radius: 0;
    }

    .mud-dialog.ws-dialog-full-xs .mud-dialog-content {
        max-height: none !important;
        flex: 1 1 auto;
        min-height: 0;
    }

    .ws-checkout-buttons {
        grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
    }
}

/* ---- Every dialog and every notice, whatever screen opens it ----
   The audit of 2026-10-05 found about 40 dialogs without the ws-dialog class and some 150 MudAlert banners in the
   legacy style. One rule set here keeps them all on the mockups (GenModal, GenDialogs*) instead of a class to remember
   on each file. */
.mud-dialog .mud-button-root {
    text-transform: none;
    letter-spacing: normal;
    font-weight: 600;
}

/* Investock.css gives every filled button a drop shadow; the mockups have flat buttons in a dialog. */
.mud-dialog .mud-button-filled {
    box-shadow: none !important;
}

html.theme-dark .mud-dialog .mud-button-filled.mud-button-filled-primary {
    color: #17131f;
}

.mud-dialog {
    border-radius: 14px;
}

.mud-dialog .mud-dialog-title {
    padding: 20px 24px 8px;
}

.mud-dialog .mud-dialog-title .mud-typography-h6 {
    font-size: 1.05rem;
    font-weight: 600;
}

.mud-dialog .mud-dialog-actions {
    padding: 12px 24px 20px;
    gap: 10px;
    flex-wrap: wrap;
}

.mud-dialog .mud-dialog-actions > * + * {
    margin-inline-start: 0 !important;
}

/* Some dialogs wrap their buttons in a MudItem or a div (customer quick add): the wrapper spaces them like the
   actions bar does, or they touched each other. */
.mud-dialog .mud-dialog-actions > :not(.mud-button-root):has(> .mud-button-root) {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

/* Phone: the dialog takes the screen width minus a small margin, instead of MudBlazor's 32px each side
   that left about 300px for a form. Heavy dialogs keep ws-dialog-full-xs (full screen). */
@media (max-width: 599.98px) {
    .mud-dialog:not(.ws-dialog-full-xs) {
        margin: 8px;
        max-width: calc(100% - 16px) !important;
        max-height: calc(100% - 16px);
    }

    .mud-dialog.mud-dialog-width-full:not(.ws-dialog-full-xs) {
        width: calc(100% - 16px);
    }

    .mud-dialog .mud-dialog-title {
        padding: 16px 16px 6px;
    }

    .mud-dialog .mud-dialog-content {
        padding-left: 16px;
        padding-right: 16px;
    }

    .mud-dialog .mud-dialog-actions {
        padding: 10px 16px 16px;
    }

    /* A choice dialog sizes its buttons for a desktop (min-width 160px or 250px, no wrap): on a phone they share
       the width and wrap instead of running past the screen. */
    .mud-dialog .mud-dialog-actions > .mud-button-root {
        min-width: 0 !important;
        white-space: normal !important;
        flex: 1 1 auto;
    }
}

/* A MudAlert reads as the note of the mockups: tinted, flat, rounded, the same tones as the pills. */
.mud-alert {
    border-radius: 10px !important;
    box-shadow: none !important;
    border: 0 !important;
    padding: 10px 16px;
    font-size: 0.85rem;
    line-height: 1.5;
}

.mud-alert.mud-alert-text-info, .mud-alert.mud-alert-outlined-info, .mud-alert.mud-alert-filled-info {
    background: var(--tint-blue-bg) !important;
    color: var(--tint-blue-fg) !important;
}

.mud-alert.mud-alert-text-warning, .mud-alert.mud-alert-outlined-warning, .mud-alert.mud-alert-filled-warning {
    background: var(--tint-gold-bg) !important;
    color: var(--tint-gold-fg) !important;
}

.mud-alert.mud-alert-text-error, .mud-alert.mud-alert-outlined-error, .mud-alert.mud-alert-filled-error {
    background: var(--tint-red-bg) !important;
    color: var(--tint-red-fg) !important;
}

.mud-alert.mud-alert-text-success, .mud-alert.mud-alert-outlined-success, .mud-alert.mud-alert-filled-success {
    background: var(--tint-green-bg) !important;
    color: var(--tint-green-fg) !important;
}

.mud-alert.mud-alert-text-normal, .mud-alert.mud-alert-outlined-normal, .mud-alert.mud-alert-filled-normal {
    background: var(--tint-neutral-bg) !important;
    color: var(--tint-neutral-fg) !important;
}

.mud-alert .mud-alert-icon {
    color: inherit !important;
    margin-inline-end: 10px;
    padding: 2px 0 0;
}

.mud-alert .mud-alert-icon .mud-icon-root {
    font-size: 1.15rem;
}

.mud-alert .mud-alert-message {
    padding: 2px 0;
}

/* A row of pills that wraps on a phone (RFID coverage of the piece list). */
.ws-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* A shared table stacked on a phone (one card per row): an empty value takes no line, and each record is set apart
   from the next, as on the operations tab mockup. MudBlazor stacks a Breakpoint.Sm table below 960px and the default
   (xs) one below 600px. */
@media (max-width: 959.98px) {
    .ws-table.mud-sm-table .mud-table-body .mud-table-cell:empty {
        display: none;
    }

    /* The table keeps separate borders, so the row border would not draw: the first cell carries it. */
    .ws-table.mud-sm-table .mud-table-body .mud-table-row + .mud-table-row > .mud-table-cell:first-child {
        border-top: 6px solid var(--tint-neutral-bg);
    }
}

@media (max-width: 599.98px) {
    .ws-table.mud-xs-table .mud-table-body .mud-table-cell:empty {
        display: none;
    }

    /* The table keeps separate borders, so the row border would not draw: the first cell carries it. */
    .ws-table.mud-xs-table .mud-table-body .mud-table-row + .mud-table-row > .mud-table-cell:first-child {
        border-top: 6px solid var(--tint-neutral-bg);
    }
}

/* Moved from the <style> blocks of EntityTable.razor and SalesOrders.razor (no <style> in a .razor file): a wide
   list scrolls inside its card, and on a phone the table toolbar grows with its wrapped content (the sales
   "Trier par" select used to overlap the first row). */
.mud-table-container {
    overflow: auto;
    /* The containing block of an absolute screen-reader label (ws-sr-only) in a row: without it the label was
       placed against the page and widened it past a tablet screen (job sheet operations: 867px on 768px). */
    position: relative;
}

/* The scrollbar of a list stays visible (owner, 2026-10-06): macOS hides overlay scrollbars until one scrolls, so a
   list wider than its card gave no sign of the columns beyond. Chromium and Safari draw a styled bar always;
   Firefox gets a thin one. */
.mud-table-container::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

.mud-table-container::-webkit-scrollbar-thumb {
    background: var(--mud-palette-lines-default);
    border: 2px solid var(--mud-palette-surface);
    border-radius: 6px;
}

.mud-table-container::-webkit-scrollbar-track {
    background: transparent;
}

@supports (-moz-appearance: none) {
    .mud-table-container {
        scrollbar-width: thin;
        scrollbar-color: var(--mud-palette-lines-default) transparent;
    }
}

@media (max-width: 600px) {
    .mud-table-toolbar {
        height: auto;
        flex-wrap: wrap;
        row-gap: 8px;
        padding-bottom: 8px;
    }
}

/* An empty field with an end adornment (calendar, %, MAD): while its label sits inside the field as a placeholder, it
   is cut before the adornment instead of running under it ("Date de retrait réelle", "Taux de TVA (optionnel)"). Once
   the label floats on the border (value or focus), MudBlazor's width applies again. */
.mud-input.mud-input-adorned-end:not(.mud-shrink):not(:focus-within) ~ .mud-input-label {
    max-width: calc(100% - 64px);
}

/* ---- Error screen ----
   Shown by ErrorHandler instead of an empty screen when a page fails. The MudBlazor theme is not available there (it
   lives inside the content that failed), so the block carries its own colors, with a dark variant. It stays in the
   flow: the same component wraps every EntityTable. */

.app-error {
    max-width: 560px;
    margin: 48px auto;
    padding: 24px;
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: 12px;
    background: #ffffff;
    color: #1f1d2b;
    /* The app font comes from the MudBlazor theme, gone with the content that failed. */
    font-family: "Montserrat", "Cairo", Helvetica, Arial, sans-serif;
}

.app-error-title {
    margin: 0 0 8px;
    font-size: 1.125rem;
    font-weight: 600;
}

.app-error-text {
    margin: 0 0 8px;
}

.app-error-ref {
    margin: 0 0 16px;
    font-size: 0.8125rem;
    color: #6b6a75;
}

.app-error-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.app-error-btn {
    padding: 8px 16px;
    border: none;
    border-radius: 8px;
    background: #ededf0;
    color: #1f1d2b;
    font: inherit;
    font-weight: 500;
    cursor: pointer;
}

.app-error-btn-primary {
    background: #5d3fd3;
    color: #ffffff;
}

html.theme-dark .app-error {
    border-color: rgba(255, 255, 255, 0.10);
    background: #1f2328;
    color: #e8e8ee;
}

html.theme-dark .app-error-ref {
    color: #9d9ca6;
}

html.theme-dark .app-error-btn {
    background: rgba(255, 255, 255, 0.10);
    color: #e8e8ee;
}

html.theme-dark .app-error-btn-primary {
    background: #8c74e8;
    color: #ffffff;
}
