@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');

/* ---------------------------------------------------------------------------
   Design tokens.

   One place to pick a colour, a type size or a step of spacing from. Anything
   added after this should reference a token rather than choosing its own hex -
   that is the whole point, and it is what stops a fourth grey appearing.

   The neutral ramp is the one the stock receiving screens already established
   (#101828 through #f9fafb); it is kept because it was the most consistent
   family in the app and .data-card's rgba(16,24,40,...) shadows already sit on
   the same hue.

   Bootstrap's own --bs-* variables are re-pointed at the end of this block, so
   components that were never overridden - form controls, links, focus rings,
   BlazorBootstrap widgets - follow along without being restyled one by one.
   --------------------------------------------------------------------------- */

:root {
    /* Chrome. Deep and desaturated so the navigation recedes and the data on
       the page is what carries colour. */
    --am-slate: #223041;
    --am-slate-light: #2c3d51;
    --am-slate-rail: #46586c;

    /* One accent: the AeroMech brand blue. Every interactive thing in the app is
       this blue - there is no second brand blue and no third.

       Two shades below it, and the reason there are two: #447EE2 on white is
       3.94:1, which is under the 4.5:1 needed for body-size text. It is fine as
       a fill - white text on it is 5.33:1 - so it paints buttons, the brand mark
       and active states, while link text takes --am-blue-text at 4.86:1. */
    --am-blue: #447EE2;
    --am-blue-dark: #3a6fcc;
    --am-blue-text: #3a6fcc;
    --am-blue-text-hover: #2f5bab;
    --am-blue-light: #e6eefb;

    /* Neutrals. */
    --am-ink: #101828;
    --am-ink-2: #344054;
    --am-steel: #667085;
    --am-steel-light: #98a2b3;
    --am-rule: #e4e7ec;
    --am-rule-strong: #d0d5dd;
    --am-ground: #f9fafb;
    --am-surface: #ffffff;

    /* Status. These are the service report stage colours, kept as they were
       and simply given names. */
    --am-warn: #d9a406;
    --am-warn-ink: #b54708;
    --am-warn-soft: #fdf6e3;
    --am-good: #16794c;
    --am-good-soft: #e6f3ec;
    --am-bad: #b42318;
    --am-bad-soft: #fdeceb;

    /* Type. Six steps, all rem, with a real middle so a page title does not
       have to drop straight to table text. */
    --am-fs-display: 1.75rem;
    --am-fs-h1: 1.375rem;
    --am-fs-h2: 1.0625rem;
    --am-fs-body: 0.875rem;
    --am-fs-sm: 0.8125rem;
    --am-fs-label: 0.6875rem;

    /* Spacing, on a 4px rhythm. */
    --am-space-1: 0.25rem;
    --am-space-2: 0.5rem;
    --am-space-3: 0.75rem;
    --am-space-4: 1rem;
    --am-space-6: 1.5rem;
    --am-space-8: 2rem;
    --am-space-12: 3rem;

    --am-radius: 4px;
    --am-radius-lg: 8px;

    --am-shadow-1: 0 1px 2px rgba(16, 24, 40, 0.06);
    --am-shadow-2: 0 1px 2px rgba(16, 24, 40, 0.05), 0 10px 26px -10px rgba(16, 24, 40, 0.18);

    /* Re-point Bootstrap at the tokens above. */
    --bs-primary: var(--am-blue);
    --bs-primary-rgb: 68, 126, 226;
    --bs-link-color: var(--am-blue-text);
    --bs-link-color-rgb: 58, 111, 204;
    --bs-link-hover-color: var(--am-blue-text-hover);
    --bs-border-color: var(--am-rule);
    --bs-body-color: var(--am-ink-2);
    --bs-body-bg: var(--am-surface);
    --bs-secondary-color: var(--am-steel);
}

html, body {
    font-family: 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
    color: var(--am-ink-2);
}

h1:focus {
    outline: none;
}

/* Links take the accent. The white here used to be unscoped, which made every
   link inside the content area white text on a white page - the sidebar and the
   top bar are the only places that want white, so they ask for it themselves. */
a, .btn-link {
    color: var(--am-blue-text);
    font-weight: 600;
}

a:hover, .btn-link:hover {
    color: var(--am-blue-text-hover);
}

.sidebar a,
.sidebar .btn-link,
.top-row a,
.top-row .btn-link {
    color: #fff;
}

.btn-primary {
    color: #fff;
    background-color: var(--am-blue);
    border-color: var(--am-blue);
}

    .btn-primary:hover,
    .btn-primary:focus,
    .btn-primary:active {
        background-color: var(--am-blue-dark);
        border-color: var(--am-blue-dark);
    }

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.2rem rgba(68, 126, 226, 0.28);
    border-color: var(--am-blue);
}

.content {
    padding-top: 1.1rem;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--am-good);
}

.invalid {
    outline: 1px solid var(--am-bad);
}

.validation-message {
    color: var(--am-bad);
}

#blazor-error-ui {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

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

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


.footer-buttons {
    display: flex;
    justify-content: end;
    margin: 15px 0px 0 0;
    border-top: 1px solid var(--am-rule);
    padding: 15px 20px 0 0;
}

    .footer-buttons .close {
        margin-right: 20px;
    }

    .footer-buttons .save {
    }

.header {
    display: flex;
}

.add-icon {
    margin-left: 10px;
}

/* Service report row status. The stage colour lives on the row as a custom property so the
   first cell and the filter chips above the grid can both read it from one place. */
.sr-new {
    --sr-status-color: var(--am-warn);
    --sr-status-text: #212529;
}

.sr-quoted {
    --sr-status-color: var(--am-good);
    --sr-status-text: #fff;
}

.sr-complete {
    --sr-status-color: var(--am-bad);
    --sr-status-text: #fff;
}

/* The whole leading cell carries the colour. Bootstrap paints the stripe and hover accents as
   an inset shadow over each cell, so that shadow has to be cleared for the colour to show. */
.table > tbody > tr > td.sr-status-cell {
    background-color: var(--sr-status-color);
    color: var(--sr-status-text);
    box-shadow: none;
    font-weight: 600;
    white-space: nowrap;
}

/* Rows have to keep one constant height. The status filter changes which reports are on the
   page, and any cell that wraps onto a second line makes its whole row taller - so the row
   height shifted about as the filter was used. Nothing in this grid wraps: every cell is held to
   a single line and ellipsised, with the full value on hover for the two text columns. The
   slightly smaller type buys back the width that costs. */
.table > tbody > tr.sr-row > td {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: var(--am-fs-sm);
}

/* The free-text columns are the ones that give way when the grid is short of room, so that the
   short columns - dates, totals, numbers - always keep their content on one line.
   max-width:0 is what lets a column shrink below the width of its own text. Without it the
   nowrap text sets a minimum column width and the table grows wide enough to scroll sideways. */
.table > tbody > tr.sr-row > td.sr-instruction {
    width: 30%;
    max-width: 0;
}

.table > tbody > tr.sr-row > td.sr-client {
    width: 14%;
    max-width: 0;
}

/* Status filter chips above the grid. */
.sr-status-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
}

.sr-status-chip {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .3rem .75rem;
    border: 1px solid var(--sr-status-color);
    border-radius: 999px;
    background-color: var(--am-surface);
    color: var(--am-ink-2);
    font-size: var(--am-fs-sm);
    line-height: 1.2;
    cursor: pointer;
}

.sr-status-chip:hover {
    background-color: rgba(0, 0, 0, .05);
}

.sr-status-chip.active {
    background-color: var(--sr-status-color);
    color: var(--sr-status-text);
}

.sr-status-dot {
    width: .6rem;
    height: .6rem;
    border-radius: 50%;
    background-color: var(--sr-status-color);
}

.sr-status-chip.active .sr-status-dot {
    background-color: var(--sr-status-text);
}

.sr-status-count {
    font-variant-numeric: tabular-nums;
    opacity: .7;
}

.sr-status-clear {
    padding: .3rem .25rem;
    border: 0;
    background: none;
    color: var(--am-steel);
    font-size: var(--am-fs-sm);
    text-decoration: underline;
    cursor: pointer;
}

.toast-container {
    z-index: 99999 !important;
    margin-top: 60px !important;
}

.fsr-button {
    margin-left: 20px !important;
}

.download-report {
    position: absolute;
    right: 70px;
    top: 80px;
}

.table th {
    font-weight: 600;
    font-size: var(--am-fs-body);
}


.table td {
    font-size: var(--am-fs-body);
    color: var(--am-ink-2);
}

.action {
    font-size: var(--am-fs-body);
}

/* Sortable grid headers: the whole cell is the click target and the caret is always present so
   the column keeps its width when the sort moves between columns. */
.table th.sortable {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

    .table th.sortable:hover {
        background-color: rgba(0, 0, 0, 0.05);
    }

    .table th.sortable .sort-indicator {
        margin-left: 4px;
        font-size: 11px;
        vertical-align: baseline;
    }

    .table th.sortable .sort-indicator.idle {
        opacity: 0.2;
    }

/* ---------------------------------------------------------------------------
   Floating data cards.

   Lifts a grid off the page rather than letting it run edge to edge: the card
   carries the elevation and the padding, and the table inside drops its outer
   borders so only the light row rules remain. Used by the quote form and by the
   labour reconciliation on the conversion screen.
   --------------------------------------------------------------------------- */
.data-card {
    background: var(--am-surface);
    border: 1px solid rgba(16, 24, 40, 0.06);
    border-radius: var(--am-radius-lg);
    box-shadow: var(--am-shadow-2);
    padding: 1rem 1.25rem 0.5rem 1.25rem;
    margin-bottom: 1.5rem;
}

.data-card-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding-bottom: 0.5rem;
}

.data-card-title {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--am-steel);
    margin: 0;
}

.data-card-note {
    font-size: var(--am-fs-sm);
    color: var(--am-steel-light);
}

/* The card already frames the grid, so the table gives up its own chrome. */
.data-card .table {
    margin-bottom: 0.5rem;
}

.data-card .table > thead > tr > th {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--am-steel);
    border-top: 0;
    border-bottom: 1px solid rgba(16, 24, 40, 0.08);
    padding-top: 0;
    white-space: nowrap;
}

.data-card .table > tbody > tr > td {
    border-top: 0;
    border-bottom: 1px solid rgba(16, 24, 40, 0.05);
    vertical-align: middle;
}

.data-card .table > tbody > tr:last-child > td {
    border-bottom: 0;
}

.data-card .table > tfoot > tr > td {
    border-top: 1px solid rgba(16, 24, 40, 0.12);
    border-bottom: 0;
    vertical-align: middle;
}

/* The trailing "add a row" line is a control, not data, so it reads quieter. */
.data-card .table tr.add-row > td {
    border-bottom: 0;
    padding-top: 0.75rem;
}

/* Reconciliation rows: agreement and disagreement should be readable at a glance
   without relying on the text alone. */
.recon-ok {
    color: var(--am-good);
}

.recon-off {
    color: var(--am-bad);
}

.recon-row-off > td {
    background-color: rgba(217, 45, 32, 0.04);
}

/* ---------------------------------------------------------------------------
   Stock receiving. The grid is an entry surface rather than a list, so it is
   styled to keep the eye on the two things being decided per row: how many
   are coming in, and what the level becomes. Rules live here rather than in
   the page's scoped stylesheet because the rows render inside ListTemplate.
   --------------------------------------------------------------------------- */

.rs-invoice {
    padding-bottom: .5rem;
}

.rs-invoice-heading {
    margin-bottom: 0;
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--am-ink-2);
}

.rs-empty {
    padding: 2rem 0;
    color: var(--am-steel);
    text-align: center;
}

/* The invoice against the lines captured, kept on one strip so posting is never
   a decision made without the variance in view. */
.rs-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.25rem;
    padding: .6rem .9rem;
    border: 1px solid var(--am-rule);
    border-radius: .5rem;
    background-color: var(--am-ground);
}

.rs-summary-item {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}

.rs-summary-label {
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .02em;
    color: var(--am-steel);
}

.rs-summary-value {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.rs-variance.reconciled .rs-summary-value {
    color: var(--am-good);
}

.rs-variance.unreconciled .rs-summary-value {
    color: var(--am-bad);
}

/* Pushed to the far end so the buttons sit clear of the figures they act on. */
.rs-summary-actions {
    display: flex;
    gap: .5rem;
    margin-left: auto;
}

.rs-totals-warning {
    padding: .5rem .75rem;
    border-radius: .375rem;
    background-color: rgba(217, 45, 32, .06);
    color: var(--am-bad);
    font-size: .875rem;
}

/* Toggle above the grid for hiding every part the invoice does not list. */
.rs-line-filter {
    display: flex;
    align-items: center;
    gap: .5rem;
}

.rs-line-chip {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .3rem .75rem;
    border: 1px solid var(--am-blue);
    border-radius: 999px;
    background-color: var(--am-surface);
    color: var(--am-ink-2);
    font-size: var(--am-fs-sm);
    line-height: 1.2;
    cursor: pointer;
}

.rs-line-chip:hover {
    background-color: rgba(0, 0, 0, .05);
}

.rs-line-chip.active {
    background-color: var(--am-blue);
    color: #fff;
}

.rs-line-count {
    font-variant-numeric: tabular-nums;
    opacity: .7;
}

.table > tbody > tr.rs-row > td {
    vertical-align: middle;
    white-space: nowrap;
    font-size: var(--am-fs-sm);
}

/* A row only joins the invoice once a quantity is entered, and the tint is what
   makes those rows findable again in a long supplier list. */
.table > tbody > tr.rs-row.receiving > td {
    background-color: rgba(68, 126, 226, .06);
}

.table > tbody > tr.rs-row.receiving > td.rs-new-level {
    font-weight: 600;
    color: var(--am-good);
}

/* Descriptions are the column that gives way, so the numeric columns always keep
   their content on one line. max-width:0 is what lets it shrink below its text. */
.rs-description {
    width: 28%;
    max-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rs-number {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.rs-input-col {
    width: 110px;
    text-align: right;
}

.rs-qty-input,
.rs-cost-input {
    height: 30px;
    padding: .15rem .4rem;
    text-align: right;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
}

/* Shown only where the invoice disagrees with the part's current cost, so a
   reprice is never something that happens without being seen. */
.rs-cost-changed {
    display: block;
    margin-top: .15rem;
    color: var(--am-warn-ink);
    font-size: var(--am-fs-label);
    text-align: right;
    white-space: nowrap;
}

/* Receipt history. Rows open in place rather than on their own page: the lines
   are only ever read next to the invoice they were captured against. */
.rs-expand-col {
    width: 34px;
}

.table > tbody > tr.rs-receipt-row {
    cursor: pointer;
}

.table > tbody > tr.rs-receipt-row > td {
    white-space: nowrap;
    font-size: var(--am-fs-sm);
}

.rs-variance-cell.reconciled {
    color: var(--am-good);
}

.rs-variance-cell.unreconciled {
    color: var(--am-bad);
    font-weight: 600;
}

.table > tbody > tr.rs-detail-row > td {
    padding: .75rem 1rem 1rem 2.25rem;
    background-color: var(--am-ground);
}

.rs-detail-table {
    margin-bottom: 0;
    font-size: var(--am-fs-sm);
}

.rs-detail-table th {
    color: var(--am-steel);
    font-weight: 600;
    text-transform: uppercase;
    font-size: var(--am-fs-label);
    letter-spacing: .02em;
}

.rs-detail-empty {
    color: var(--am-steel);
    font-size: .875rem;
}

.rs-detail-notes {
    margin-top: .5rem;
    font-size: .8125rem;
    color: var(--am-steel);
}

/* ---------------------------------------------------------------------------
   Page header.

   An uppercase eyebrow, a 22px title and the primary action on the same line.
   The title used to be a bare Bootstrap h1 at 40px sitting directly above 13px
   table text, which is a jump with nothing in between - and the action next to
   it was an unlabelled "+" glyph.
   --------------------------------------------------------------------------- */

.page-header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--am-space-3);
    margin-bottom: var(--am-space-4);
}

.page-header-text {
    min-width: 0;
}

.page-eyebrow {
    margin: 0 0 var(--am-space-1);
    font-size: var(--am-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--am-steel);
}

.page-title {
    margin: 0;
    font-size: var(--am-fs-h1);
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--am-ink);
}

.page-action {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    flex: 0 0 auto;
    font-size: var(--am-fs-body);
    font-weight: 600;
    white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   List toolbar and grid card.
   --------------------------------------------------------------------------- */

.list-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--am-space-2) var(--am-space-3);
    margin-bottom: var(--am-space-3);
}

/* Held to a sensible width rather than spanning the page: a search box as wide
   as the grid reads as the subject of the screen, which it is not. */
.list-search {
    position: relative;
    flex: 0 1 20rem;
    min-width: 12rem;
}

.list-search-icon {
    position: absolute;
    top: 50%;
    left: 0.625rem;
    transform: translateY(-50%);
    color: var(--am-steel-light);
    font-size: var(--am-fs-body);
    pointer-events: none;
}

.list-search .form-control {
    padding-left: 2rem;
    font-size: var(--am-fs-body);
}

.list-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--am-space-2);
    min-width: 0;
}

.list-card {
    padding: 0;
    margin-bottom: var(--am-space-6);
}

/* Only the grid scrolls sideways, so the page itself never does. */
.list-scroll {
    overflow-x: auto;
}

.list-card .table {
    margin-bottom: 0;
}

.list-card .table > thead > tr > th {
    position: sticky;
    top: 0;
    z-index: 2;
    background-color: var(--am-surface);
    padding: var(--am-space-3) var(--am-space-3);
    border-top: 0;
    border-bottom: 1px solid var(--am-rule);
    font-size: var(--am-fs-label);
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--am-steel);
    white-space: nowrap;
}

.list-card .table > tbody > tr > td {
    padding: var(--am-space-2) var(--am-space-3);
    border-top: 0;
    border-bottom: 1px solid var(--am-rule);
    vertical-align: middle;
}

.list-card .table > tbody > tr:last-child > td {
    border-bottom: 0;
}

.list-empty {
    padding: var(--am-space-12) var(--am-space-4) !important;
    text-align: center;
    color: var(--am-steel);
}

.list-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--am-space-2);
    padding: var(--am-space-2) var(--am-space-3);
    border-top: 1px solid var(--am-rule);
}

.list-count {
    font-size: var(--am-fs-sm);
    color: var(--am-steel);
    font-variant-numeric: tabular-nums;
}

.list-pager-controls {
    display: flex;
    align-items: center;
    gap: var(--am-space-2);
}

.list-page-number {
    font-size: var(--am-fs-sm);
    color: var(--am-steel);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Figures line up down the column rather than drifting with digit width. */
.list-card .table .rate,
.list-card .table .num,
.list-card .table .amount {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
   Shared table odds and ends.
   --------------------------------------------------------------------------- */

.report-date {
    text-align: right;
    min-width: 93px;
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
   Row actions.

   Every grid's edit / delete / print controls go through <RowActions>, so they
   read the same way everywhere: an outlined button you can see without hovering
   for it, a hit target you can land on, a focus ring, and red reserved for the
   ones you cannot take back.
   --------------------------------------------------------------------------- */

.row-actions {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    gap: var(--am-space-1);
}

.row-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.875rem;
    height: 1.875rem;
    padding: 0;
    font-size: 0.875rem;
    line-height: 1;
    color: var(--am-ink-2);
    background-color: var(--am-surface);
    border: 1px solid var(--am-rule-strong);
    border-radius: var(--am-radius);
    transition: color 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}

    .row-action:hover {
        color: var(--am-blue-text);
        background-color: var(--am-blue-light);
        border-color: var(--am-blue);
    }

    .row-action:focus-visible {
        outline: 2px solid var(--am-blue);
        outline-offset: 1px;
    }

    .row-action:disabled {
        color: var(--am-steel-light);
        background-color: var(--am-ground);
        border-color: var(--am-rule);
        pointer-events: none;
    }

.row-action-danger:hover {
    color: var(--am-bad);
    background-color: var(--am-bad-soft);
    border-color: var(--am-bad);
}

/* The actions column takes only the width its buttons need, and holds it, so
   they do not shift about from row to row. */
.row-actions-col {
    width: 1%;
    white-space: nowrap;
    text-align: right;
}

.email {
    max-width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ---------------------------------------------------------------------------
   Small utilities that were repeated as inline style attributes.
   --------------------------------------------------------------------------- */

/* Long free-text cells give way before the numeric columns do. */
.instruction-col {
    max-width: 400px;
}

/* Pickers with a long list scroll inside the menu rather than off the page. */
.dropdown-scroll {
    max-height: 350px;
    overflow: auto;
}

.panel-scroll {
    max-height: 260px;
    overflow-y: auto;
}

/* ---------------------------------------------------------------------------
   The row of filters above a report or a list.

   What has to line up is the controls, not the columns. Bottom-aligning the
   columns lines up whatever each one happens to end on, so a column carrying
   help text under its input has that input pushed up by the height of the help
   while a column without help keeps its input on the baseline - and the row
   reads as though it had been set on two different lines.

   Aligning to the top instead puts every label on one line and every control on
   the next, and lets help text hang below where it moves nothing above it. A
   label long enough to wrap still carries its own control down; the labels here
   are short enough that it does not arise.
   --------------------------------------------------------------------------- */
.filter-row {
    align-items: flex-start;
}

/* A checkbox or a button dropped into a filter row has no label of its own, so
   it would otherwise ride up onto the label line beside its neighbours' labels
   rather than sitting with their inputs. This gives back the space the label
   would have taken and centres a lone control against the height of an input.
   Only from the medium breakpoint up: once the columns stack there is no label
   line left to clear. */
.filter-row .filter-row-control {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: calc(1.5rem + 0.75rem + 2px); /* as .form-control is built up */
}

@media (min-width: 768px) {
    .filter-row .filter-row-control {
        margin-top: 2rem; /* .form-label: one line at 1.5rem, plus its 0.5rem margin */
    }
}

/* ---------------------------------------------------------------------------
   Stock takes.

   The counting grid is not a table. A count is done on a phone walking round a
   warehouse, so the rows are laid out with CSS grid and reflow into cards below
   768px: one markup tree, a dense table on a desk and a thumb-sized card in an
   aisle. .st-meta uses display:contents so that on a wide screen its children
   drop into the row's own columns, and on a narrow one it collapses to a single
   labelled strip.
   --------------------------------------------------------------------------- */

.st-page {
    padding-bottom: 3rem;
}

.st-empty {
    padding: 3rem 0;
    text-align: center;
    color: var(--am-steel);
}

/* Header ------------------------------------------------------------------- */

.st-header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--am-space-4);
    margin-bottom: var(--am-space-4);
}

.st-header-main {
    min-width: 0;
}

.st-header .page-title {
    display: flex;
    align-items: center;
    gap: .6rem;
    flex-wrap: wrap;
}

.st-header-desc {
    margin: .15rem 0 0;
    color: var(--am-ink-2);
    font-size: var(--am-fs-body);
}

.st-header-meta {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem 1rem;
    margin-top: .4rem;
    font-size: var(--am-fs-sm);
    color: var(--am-steel);
}

.st-header-meta strong {
    color: var(--am-steel-light);
    font-weight: 600;
    text-transform: uppercase;
    font-size: var(--am-fs-label);
    letter-spacing: .04em;
    margin-right: .3rem;
}

.st-blind-badge {
    align-self: center;
    padding: .1rem .45rem;
    border-radius: 999px;
    background-color: var(--am-blue-light);
    color: var(--am-blue-dark);
    font-size: var(--am-fs-label);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
}

.st-header-side {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: .5rem;
    min-width: 260px;
}

.st-header-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    justify-content: flex-end;
}

.st-order-select {
    width: auto;
    min-width: 165px;
}

/* Progress ----------------------------------------------------------------- */

.st-progress {
    width: 100%;
    min-width: 220px;
}

.st-progress-top {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
}

.st-progress-count {
    font-size: var(--am-fs-h2);
    font-weight: 700;
    color: var(--am-ink);
    font-variant-numeric: tabular-nums;
}

.st-progress-of {
    font-size: var(--am-fs-sm);
    font-weight: 400;
    color: var(--am-steel);
}

.st-progress-pct {
    font-size: var(--am-fs-sm);
    color: var(--am-steel);
    font-variant-numeric: tabular-nums;
}

.st-progress-track {
    display: block;
    height: 6px;
    margin-top: .3rem;
    border-radius: 999px;
    background-color: var(--am-rule);
    overflow: hidden;
}

.st-progress-fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    background-color: var(--am-blue);
    transition: width .2s ease;
}

/* Written back as each figure is entered, so the counter is told so rather than
   being left to wonder whether the walk to the far aisle was recorded. */
.st-save-state {
    display: block;
    margin-top: .25rem;
    font-size: var(--am-fs-label);
    color: var(--am-good);
    text-align: right;
}

.st-save-state.failed {
    color: var(--am-bad);
    font-weight: 600;
}

/* Status pills ------------------------------------------------------------- */

.st-status {
    display: inline-block;
    padding: .12rem .5rem;
    border-radius: 999px;
    font-size: var(--am-fs-label);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    white-space: nowrap;
}

.st-status-pending {
    background-color: var(--am-rule);
    color: var(--am-ink-2);
}

.st-status-counting {
    background-color: var(--am-blue-light);
    color: var(--am-blue-dark);
}

.st-status-review {
    background-color: var(--am-warn-soft);
    color: var(--am-warn-ink);
}

.st-status-completed {
    background-color: var(--am-good-soft);
    color: var(--am-good);
}

.st-status-cancelled {
    background-color: var(--am-rule);
    color: var(--am-steel);
}

/* Banners ------------------------------------------------------------------ */

.st-banner {
    padding: .6rem .9rem;
    margin-bottom: var(--am-space-3);
    border-radius: var(--am-radius);
    font-size: var(--am-fs-sm);
}

.st-banner-good {
    background-color: var(--am-good-soft);
    color: var(--am-good);
}

.st-banner-warn {
    background-color: var(--am-warn-soft);
    color: var(--am-warn-ink);
}

.st-banner-muted {
    background-color: var(--am-ground);
    color: var(--am-steel);
}

/* Tabs and toolbar --------------------------------------------------------- */

.st-tabs {
    display: flex;
    gap: .25rem;
    border-bottom: 1px solid var(--am-rule);
    margin-bottom: var(--am-space-3);
}

.st-tab {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .5rem .9rem;
    border: 0;
    border-bottom: 2px solid transparent;
    background: none;
    color: var(--am-steel);
    font-size: var(--am-fs-body);
    font-weight: 600;
    cursor: pointer;
}

.st-tab:hover {
    color: var(--am-ink-2);
}

.st-tab.active {
    color: var(--am-blue);
    border-bottom-color: var(--am-blue);
}

.st-tab-badge {
    padding: .05rem .4rem;
    border-radius: 999px;
    background-color: var(--am-rule);
    color: var(--am-ink-2);
    font-size: var(--am-fs-label);
    font-variant-numeric: tabular-nums;
}

.st-tab-badge.urgent {
    background-color: var(--am-warn-soft);
    color: var(--am-warn-ink);
}

.st-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--am-space-3);
    margin-bottom: var(--am-space-3);
}

.st-search {
    flex: 1 1 260px;
    min-width: 0;
}

.st-chips {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
}

.st-chip {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .3rem .7rem;
    border: 1px solid var(--am-rule-strong);
    border-radius: 999px;
    background-color: var(--am-surface);
    color: var(--am-ink-2);
    font-size: var(--am-fs-sm);
    cursor: pointer;
}

.st-chip:hover {
    border-color: var(--am-steel-light);
}

.st-chip.active {
    background-color: var(--am-blue);
    border-color: var(--am-blue);
    color: #fff;
}

.st-chip-warn:not(.active) {
    border-color: var(--am-warn);
    color: var(--am-warn-ink);
}

.st-chip-count {
    font-variant-numeric: tabular-nums;
    opacity: .75;
}

/* The grid ----------------------------------------------------------------- */

.st-list {
    background: var(--am-surface);
    border: 1px solid rgba(16, 24, 40, 0.06);
    border-radius: var(--am-radius-lg);
    box-shadow: var(--am-shadow-2);
    overflow: hidden;
}

.st-list-head,
.st-row {
    display: grid;
    align-items: center;
    gap: .75rem;
    padding: .5rem .9rem;
}

.st-list-count .st-list-head,
.st-list-count .st-row {
    grid-template-columns: 130px minmax(0, 1fr) 90px 90px 80px 168px;
}

/* A blind sheet drops the expected-quantity column rather than blanking it, so
   the row has one column fewer to lay out. */
.st-list-count.blind .st-list-head,
.st-list-count.blind .st-row {
    grid-template-columns: 130px minmax(0, 1fr) 90px 90px 168px;
}

.st-list-review .st-list-head,
.st-list-review .st-row {
    grid-template-columns: 130px minmax(0, 1fr) 80px 90px 90px 110px 180px;
}

.st-list-head {
    background-color: var(--am-ground);
    border-bottom: 1px solid var(--am-rule);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--am-steel);
}

.st-row {
    border-bottom: 1px solid rgba(16, 24, 40, 0.05);
    font-size: var(--am-fs-sm);
}

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

.st-row-counted {
    background-color: rgba(44, 110, 203, .04);
}

.st-row-recount {
    background-color: var(--am-warn-soft);
}

.st-row-unsettled {
    background-color: rgba(217, 45, 32, .04);
}

.st-row-accepted {
    background-color: var(--am-good-soft);
}

.st-list-empty {
    padding: 2rem .9rem;
    text-align: center;
    color: var(--am-steel);
}

/* On a wide screen the meta strip has no box of its own - its children sit in
   the row's columns directly. */
.st-meta {
    display: contents;
}

.st-code {
    font-weight: 600;
    color: var(--am-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The description is the column that gives way, so the numbers never wrap.
   min-width:0 is what lets it shrink below its own text. */
.st-desc {
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--am-ink-2);
}

.st-bin,
.st-sup {
    color: var(--am-steel);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.st-right {
    text-align: right;
}

.st-center {
    text-align: center;
}

.st-expected,
.st-counted,
.st-variance,
.st-varvalue {
    font-variant-numeric: tabular-nums;
}

.st-value-up {
    color: var(--am-good);
    font-weight: 600;
}

.st-value-down {
    color: var(--am-bad);
    font-weight: 600;
}

.st-muted {
    color: var(--am-steel);
}

.st-prev,
.st-recount-note {
    display: block;
    font-size: var(--am-fs-label);
    color: var(--am-warn-ink);
    white-space: nowrap;
}

.st-recount-badge {
    margin-left: .3rem;
    padding: 0 .3rem;
    border-radius: var(--am-radius);
    background-color: var(--am-warn-soft);
    color: var(--am-warn-ink);
    font-size: var(--am-fs-label);
    font-weight: 700;
}

.st-moved {
    display: inline-block;
    margin-left: .4rem;
    color: var(--am-warn-ink);
    font-size: var(--am-fs-label);
    white-space: nowrap;
}

/* Count entry -------------------------------------------------------------- */

.st-qty {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: .3rem;
    flex-wrap: wrap;
}

.st-stepper {
    display: flex;
    align-items: center;
    gap: .2rem;
}

.st-qty-input {
    width: 68px;
    height: 34px;
    padding: .15rem .4rem;
    text-align: center;
    font-size: 15px;
    font-variant-numeric: tabular-nums;
}

/* Hidden where there is a keyboard and a mouse; indispensable where there is a
   thumb. */
.st-step {
    display: none;
    width: 40px;
    height: 40px;
    border: 1px solid var(--am-rule-strong);
    border-radius: var(--am-radius);
    background-color: var(--am-surface);
    color: var(--am-ink-2);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
}

.st-step:disabled {
    opacity: .4;
    cursor: default;
}

.st-clear {
    border: 0;
    background: none;
    color: var(--am-steel-light);
    padding: .2rem .3rem;
    cursor: pointer;
}

.st-clear:hover {
    color: var(--am-bad);
}

/* Decisions ---------------------------------------------------------------- */

.st-decision {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: .3rem;
    flex-wrap: wrap;
}

.st-accepted,
.st-agrees {
    color: var(--am-good);
    font-size: var(--am-fs-sm);
    white-space: nowrap;
}

.st-awaiting {
    color: var(--am-steel);
    font-size: var(--am-fs-sm);
    white-space: nowrap;
}

.st-applied {
    font-size: var(--am-fs-sm);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Summary strip and footers ------------------------------------------------ */

.st-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.25rem;
    padding: .6rem .9rem;
    margin-bottom: var(--am-space-3);
    border: 1px solid var(--am-rule);
    border-radius: .5rem;
    background-color: var(--am-ground);
}

.st-summary-item {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}

.st-summary-label {
    font-size: var(--am-fs-label);
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--am-steel);
}

.st-summary-value {
    font-size: var(--am-fs-h2);
    font-weight: 600;
    color: var(--am-ink);
    font-variant-numeric: tabular-nums;
}

.st-summary-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    margin-left: auto;
}

.st-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--am-space-3);
    padding: .6rem .2rem 0;
}

.st-footer-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--am-space-3);
    margin-top: var(--am-space-4);
}

.st-footer-note {
    color: var(--am-steel);
    font-size: var(--am-fs-sm);
}

.st-modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: .5rem;
}

/* Stock take list ---------------------------------------------------------- */

.table > tbody > tr.st-take-row {
    cursor: pointer;
}

.table > tbody > tr.st-take-row > td {
    white-space: nowrap;
    font-size: var(--am-fs-sm);
    vertical-align: middle;
}

.st-reference {
    font-weight: 600;
    color: var(--am-ink);
}

.st-number {
    text-align: right;
    font-variant-numeric: tabular-nums;
}


.table > tbody > tr.st-take-row > td.st-description {
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.st-progress-label {
    display: block;
    font-variant-numeric: tabular-nums;
}

.table .st-progress-track {
    width: 72px;
    margin-left: auto;
}

/* ---------------------------------------------------------------------------
   Counting on a phone. Below 768px each row becomes a card: the part and its
   description stack, the bin and supplier collapse into one labelled strip, and
   the quantity control grows to something a thumb can hit while holding a box.
   --------------------------------------------------------------------------- */

@media (max-width: 767.98px) {

    .st-header {
        position: sticky;
        top: 0;
        z-index: 5;
        padding: .5rem 0;
        margin-bottom: var(--am-space-3);
        background-color: var(--am-surface);
        border-bottom: 1px solid var(--am-rule);
    }

    .st-header-side {
        align-items: stretch;
        min-width: 100%;
    }

    .st-header-actions {
        justify-content: flex-start;
    }

    .st-save-state {
        text-align: left;
    }

    /* Column headings describe columns that no longer exist; each cell carries
       its own label instead. */
    .st-list-head {
        display: none;
    }

    .st-list-count .st-row {
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            "code qty"
            "desc qty"
            "meta qty";
        gap: .15rem .75rem;
        padding: .75rem .9rem;
    }

    .st-list-review .st-row {
        grid-template-columns: repeat(4, minmax(0, 1fr));
        grid-template-areas:
            "code code code code"
            "desc desc desc desc"
            "exp  cnt  diff val"
            "dec  dec  dec  dec";
        gap: .4rem .5rem;
        padding: .75rem .9rem;
    }

    .st-code {
        grid-area: code;
        font-size: var(--am-fs-body);
    }

    .st-desc {
        grid-area: desc;
        white-space: normal;
    }

    .st-qty {
        grid-area: qty;
        justify-content: flex-end;
    }

    .st-list-count .st-meta {
        grid-area: meta;
        display: flex;
        flex-wrap: wrap;
        gap: .25rem .75rem;
        font-size: var(--am-fs-label);
    }

    .st-list-review .st-expected {
        grid-area: exp;
        text-align: left;
    }

    .st-list-review .st-counted {
        grid-area: cnt;
        text-align: left;
    }

    .st-list-review .st-variance {
        grid-area: diff;
        text-align: left;
    }

    .st-list-review .st-varvalue {
        grid-area: val;
        text-align: left;
    }

    .st-list-review .st-decision {
        grid-area: dec;
        justify-content: flex-start;
    }

    /* Without the column heading above them, the numbers have to say what they
       are themselves. */
    .st-row [data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: var(--am-fs-label);
        font-weight: 700;
        letter-spacing: .04em;
        text-transform: uppercase;
        color: var(--am-steel-light);
    }

    .st-list-count .st-meta [data-label]::before {
        display: inline;
        margin-right: .25rem;
    }

    .st-step {
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    .st-qty-input {
        width: 60px;
        height: 40px;
        font-size: 16px; /* Anything smaller and iOS zooms the page on focus. */
    }

    .st-summary {
        gap: .75rem 1.25rem;
    }

    .st-summary-actions {
        margin-left: 0;
        width: 100%;
    }

    .st-summary-actions .btn {
        flex: 1 1 auto;
    }

    .st-footer-actions .btn {
        width: 100%;
    }
}

/* Accepted lines are shown but not editable; the note reads as settled rather than as a
   warning, which is what the recount note beside it is for. */
.st-locked-note {
    color: var(--am-good);
}

/* ---------------------------------------------------------------------------
   Time sheet data.

   The screen is one drill-down - a day, then someone who worked it, then how
   their hours were made up - and it is now laid out as one. It used to be two
   half-width columns with the right one split again and capped at 30% of its
   own height, which clipped the employee grid mid-row and hid its pager; and
   because the halves were plain col-6 they stayed halves on a phone, at which
   point nothing on the screen fit.

   The rules live here rather than in the page's scoped stylesheet because the
   rows render inside ListTemplate, the same reason the receiving grid's do.
   --------------------------------------------------------------------------- */

/* The range the day list covers. A dated grid with no sign of where it starts
   was the previous state of this control. */
.ts-range {
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    gap: var(--am-space-1);
}

.ts-range-label {
    font-size: var(--am-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--am-steel);
}

.ts-range-input {
    width: 11rem;
    font-size: var(--am-fs-body);
}

/* Days are a rail: the way in to a day's data rather than half the screen. */
.ts-columns {
    display: grid;
    grid-template-columns: minmax(0, 21rem) minmax(0, 1fr);
    gap: var(--am-space-6);
    align-items: start;
}

.ts-detail {
    display: flex;
    flex-direction: column;
    gap: var(--am-space-6);
    min-width: 0;
}

.ts-panel {
    min-width: 0;
}

/* The grid card carries the frame, so the panel only supplies the label above
   it - and gives up the card's own bottom margin to the column gap. */
.ts-panel .list-card {
    margin-bottom: 0;
}

.ts-panel-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--am-space-2) var(--am-space-3);
    margin-bottom: var(--am-space-3);
}

.ts-panel-headings {
    flex: 1 1 auto;
    min-width: 0;
}

/* Each panel says which step of the drill-down it is and what it is showing.
   Before this the three grids were told apart only by their column headings. */
.ts-panel-eyebrow {
    margin: 0 0 2px;
    font-size: var(--am-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--am-steel-light);
}

.ts-panel-title {
    margin: 0;
    font-size: var(--am-fs-h2);
    font-weight: 600;
    color: var(--am-ink);
    overflow-wrap: anywhere;
}

.ts-panel-action {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 0.375rem;
    white-space: nowrap;
}

/* Stepping back out only exists on a narrow screen, where one panel is on show
   at a time. The wide layout has all three and nothing to go back to. */
.ts-back {
    display: none;
}

/* A panel with nothing in it yet says what to do rather than "Nothing here
   yet.", and the dashed edge keeps it from reading as an empty grid. */
.ts-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--am-space-2);
    padding: var(--am-space-12) var(--am-space-6);
    text-align: center;
    color: var(--am-steel);
    background-color: var(--am-surface);
    border: 1px dashed var(--am-rule-strong);
    border-radius: var(--am-radius-lg);
}

.ts-placeholder i {
    font-size: 1.5rem;
    color: var(--am-steel-light);
}

.ts-placeholder p {
    max-width: 28rem;
    margin: 0;
    font-size: var(--am-fs-body);
}

/* What the screen is for: the hours nobody has accounted for yet. The figures
   were always on the page, but only ever one row at a time. */
.ts-summary {
    display: flex;
    flex-wrap: wrap;
    gap: var(--am-space-3) var(--am-space-8);
    padding: var(--am-space-3) var(--am-space-4);
    margin-bottom: var(--am-space-3);
    background-color: var(--am-surface);
    border: 1px solid var(--am-rule);
    border-radius: var(--am-radius-lg);
}

.ts-summary-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    line-height: 1.2;
}

.ts-summary-label {
    font-size: var(--am-fs-label);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--am-steel);
}

.ts-summary-value {
    font-size: var(--am-fs-h2);
    font-weight: 600;
    color: var(--am-ink);
    font-variant-numeric: tabular-nums;
}

.ts-summary-of {
    font-size: var(--am-fs-sm);
    font-weight: 400;
    color: var(--am-steel);
}

.ts-summary-warn .ts-summary-value {
    color: var(--am-warn-ink);
}

/* The whole row drills in. The eye icon that used to be the only way in was a
   20px target on a 40px row, and on a phone that is a miss more often than a
   hit. */
.ts-panel .table > tbody > tr.ts-row {
    cursor: pointer;
}

.ts-panel .table > tbody > tr.ts-row-selected > td {
    background-color: var(--am-blue-light);
}

.ts-panel .table > tbody > tr.ts-row-selected > td:first-child {
    box-shadow: inset 3px 0 0 var(--am-blue);
}

.ts-action-cell {
    width: 1%;
    text-align: right;
    white-space: nowrap;
}

/* Only the drill-in chevrons are left on this: they are a hint that the row
   opens, not an action of their own, so they stay quieter than a <RowAction>. */
.ts-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    font-size: 1rem;
    line-height: 1;
    color: var(--am-steel);
    background: transparent;
    border: 0;
    border-radius: var(--am-radius);
}

    .ts-icon-btn:hover {
        color: var(--am-blue-text);
        background-color: var(--am-blue-light);
    }

    .ts-icon-btn:focus-visible {
        outline: 2px solid var(--am-blue);
        outline-offset: 1px;
    }


.ts-chevron {
    color: var(--am-steel-light);
}

.ts-row-selected .ts-chevron {
    color: var(--am-blue-text);
}

.ts-date-value {
    display: block;
    font-weight: 600;
    color: var(--am-ink);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.ts-date-day {
    display: block;
    font-size: var(--am-fs-sm);
    color: var(--am-steel-light);
}

.ts-employee-name {
    display: block;
    font-weight: 600;
    color: var(--am-ink);
}

.ts-employee-number {
    display: block;
    font-size: var(--am-fs-sm);
    color: var(--am-steel-light);
    font-variant-numeric: tabular-nums;
}

.ts-panel .table > tbody > tr > td.ts-cell-total {
    font-weight: 600;
    color: var(--am-ink);
}

/* A grid of noughts reads calmer greyed out, and it lets the hours that were
   logged carry the eye instead. */
.ts-panel .table > tbody > tr > td.ts-zero {
    font-weight: 400;
    color: var(--am-steel-light);
}

.ts-line-description {
    font-weight: 500;
    color: var(--am-ink);
}

/* Where a line came from decides whether it can be edited here at all, so it is
   a badge rather than a sentence in the same grey as everything else. */
.ts-source {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    font-size: var(--am-fs-label);
    font-weight: 600;
    letter-spacing: 0.02em;
    white-space: nowrap;
    border-radius: 999px;
}

.ts-source-report {
    color: var(--am-blue-text);
    background-color: var(--am-blue-light);
}

.ts-source-manual {
    color: var(--am-steel);
    background-color: var(--am-ground);
    border: 1px solid var(--am-rule);
}

/* --- Adding hours ------------------------------------------------------- */

/* The modal used to open with no sign of whose day it was about. */
.ts-modal-context {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--am-space-3) var(--am-space-4);
    margin-bottom: var(--am-space-4);
    background-color: var(--am-ground);
    border-radius: var(--am-radius-lg);
}

.ts-modal-who {
    font-size: var(--am-fs-h2);
    font-weight: 600;
    color: var(--am-ink);
}

.ts-modal-when {
    font-size: var(--am-fs-sm);
    color: var(--am-steel);
}

.ts-field {
    margin-bottom: var(--am-space-4);
}

.ts-field-label {
    display: block;
    margin-bottom: var(--am-space-1);
    font-size: var(--am-fs-label);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--am-steel);
}

.ts-hours-field {
    display: flex;
    align-items: center;
    gap: var(--am-space-2);
}

.ts-hours-input {
    max-width: 8rem;
    font-variant-numeric: tabular-nums;
}

.ts-hours-unit {
    font-size: var(--am-fs-body);
    color: var(--am-steel);
}

/* Most entries are one of six lengths, so they are a tap rather than a typed
   number - which on a phone is the difference between quick and fiddly. */
.ts-presets {
    display: flex;
    flex-wrap: wrap;
    gap: var(--am-space-2);
    margin-top: var(--am-space-2);
}

.ts-preset {
    padding: 0.3rem 0.75rem;
    font-size: var(--am-fs-sm);
    font-weight: 600;
    color: var(--am-ink-2);
    font-variant-numeric: tabular-nums;
    background-color: var(--am-surface);
    border: 1px solid var(--am-rule-strong);
    border-radius: 999px;
}

    .ts-preset:hover {
        color: var(--am-blue-text);
        border-color: var(--am-blue);
    }

    .ts-preset.active {
        color: #fff;
        background-color: var(--am-blue);
        border-color: var(--am-blue);
    }

.ts-modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--am-space-2);
    margin-top: var(--am-space-6);
}

/* ---------------------------------------------------------------------------
   The same job on anything narrower. Three panels side by side is what made
   this screen unusable on a phone, so below the width where two columns
   genuinely fit, the drill-down shows one step at a time and each row becomes
   a card - a row of figures does not fit a 375px screen, and a sideways
   scrollbar inside a table is not a way to read them.

   The switch is at 1280 rather than at a tablet width because the sidebar
   takes 250px before the page starts: below that the employee grid is left
   with about 500px for five columns, which wraps the names onto two lines and
   puts the total off the end behind a scrollbar. One panel at a time is the
   better use of a narrow window, not a fallback for a small one.
   --------------------------------------------------------------------------- */

@media (max-width: 1279.98px) {

    .ts-columns {
        grid-template-columns: minmax(0, 1fr);
        gap: 0;
    }

    .ts-page[data-step="days"] .ts-detail,
    .ts-page[data-step="employees"] .ts-panel-days,
    .ts-page[data-step="employees"] .ts-panel-lines,
    .ts-page[data-step="lines"] .ts-panel-days,
    .ts-page[data-step="lines"] .ts-panel-employees {
        display: none;
    }

    .ts-back {
        display: inline-flex;
        flex: 1 1 100%;
        order: -1;
        align-items: center;
        gap: 0.375rem;
        padding: 0;
        font-size: var(--am-fs-sm);
        font-weight: 600;
        color: var(--am-blue-text);
        background: transparent;
        border: 0;
    }

    .ts-range {
        flex: 1 1 100%;
    }

    .ts-range-input {
        width: 100%;
        font-size: 16px; /* Anything smaller and iOS zooms the page on focus. */
    }

    .ts-summary {
        gap: var(--am-space-3) var(--am-space-6);
    }

    /* Column headings describe columns that no longer exist; each cell carries
       its own label instead. */
    .ts-panel .list-card thead {
        display: none;
    }

    .ts-panel .list-card .table,
    .ts-panel .list-card .table > tbody {
        display: block;
        width: 100%;
    }

    .ts-panel .list-card .table > tbody > tr {
        display: grid;
        gap: 0.35rem 0.75rem;
        padding: 0.7rem 0.9rem;
        border-bottom: 1px solid var(--am-rule);
    }

        .ts-panel .list-card .table > tbody > tr:last-child {
            border-bottom: 0;
        }

        .ts-panel .list-card .table > tbody > tr > td {
            display: block;
            padding: 0;
            text-align: left;
            border: 0;
        }

    .ts-panel .list-card .table > tbody > tr > td[data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: var(--am-fs-label);
        font-weight: 700;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        color: var(--am-steel-light);
    }

    /* The card's own heading needs no label above it. */
    .ts-panel .list-card .table > tbody > tr > td.ts-date::before,
    .ts-panel .list-card .table > tbody > tr > td.ts-employee::before,
    .ts-panel .list-card .table > tbody > tr > td.ts-cell-source::before,
    .ts-panel .list-card .table > tbody > tr > td.ts-line-description::before {
        content: none;
    }

    /* A lone figure takes the unit instead of a heading repeated down the list;
       the three figures on an employee card keep theirs, because side by side
       they would otherwise be three numbers with nothing to tell them apart. */
    .ts-panel-days .list-card .table > tbody > tr > td.ts-cell-hours::before,
    .ts-panel-lines .list-card .table > tbody > tr > td.ts-cell-hours::before {
        content: none;
    }

        .ts-panel-days .list-card .table > tbody > tr > td.ts-cell-hours::after,
        .ts-panel-lines .list-card .table > tbody > tr > td.ts-cell-hours::after {
            content: " h";
            color: var(--am-steel-light);
        }

    /* :not(.ts-zero) so a day with nothing on it stays quiet rather than being
       set in the same weight as one with a full crew's hours. */
    .ts-panel-days .list-card .table > tbody > tr > td.ts-cell-hours,
    .ts-panel-lines .list-card .table > tbody > tr > td.ts-cell-hours {
        font-size: var(--am-fs-h2);
    }

        .ts-panel-days .list-card .table > tbody > tr > td.ts-cell-hours:not(.ts-zero),
        .ts-panel-lines .list-card .table > tbody > tr > td.ts-cell-hours:not(.ts-zero) {
            font-weight: 600;
            color: var(--am-ink);
        }

    .ts-panel .list-card .table > tbody > tr > td.ts-action-cell {
        width: auto;
    }

    .ts-icon-btn,
    .row-action {
        width: 2.5rem;
        height: 2.5rem;
    }

    /* Date and weekday lead, the hours sit beside them, the actions stay put. */
    .ts-panel-days .list-card .table > tbody > tr {
        grid-template-columns: minmax(0, 1fr) auto auto;
        grid-template-areas: "date hours actions";
        align-items: center;
    }

    .ts-panel-days .table > tbody > tr > td.ts-date {
        grid-area: date;
    }

    .ts-panel-days .ts-date-value {
        font-size: var(--am-fs-h2);
    }

    .ts-panel-days .table > tbody > tr > td.ts-cell-hours {
        grid-area: hours;
    }

    .ts-panel-days .table > tbody > tr > td.ts-action-cell {
        grid-area: actions;
    }

    /* The name leads; the three figures share a line under it. */
    .ts-panel-employees .list-card .table > tbody > tr {
        grid-template-columns: repeat(3, minmax(0, 1fr)) auto;
        grid-template-areas:
            "who who who actions"
            "sr  oth tot actions";
        align-items: center;
    }

    .ts-panel-employees .table > tbody > tr > td.ts-employee {
        grid-area: who;
    }

    .ts-panel-employees .table > tbody > tr > td.ts-cell-sr {
        grid-area: sr;
    }

    .ts-panel-employees .table > tbody > tr > td.ts-cell-other {
        grid-area: oth;
    }

    .ts-panel-employees .table > tbody > tr > td.ts-cell-total {
        grid-area: tot;
    }

    .ts-panel-employees .table > tbody > tr > td.ts-action-cell {
        grid-area: actions;
    }

    .ts-panel-lines .list-card .table > tbody > tr {
        grid-template-columns: minmax(0, 1fr) auto auto;
        grid-template-areas:
            "desc   hours actions"
            "source hours actions";
        align-items: center;
    }

    .ts-panel-lines .table > tbody > tr > td.ts-line-description {
        grid-area: desc;
    }

    .ts-panel-lines .table > tbody > tr > td.ts-cell-source {
        grid-area: source;
    }

    .ts-panel-lines .table > tbody > tr > td.ts-cell-hours {
        grid-area: hours;
    }

    .ts-panel-lines .table > tbody > tr > td.ts-action-cell {
        grid-area: actions;
    }

    .ts-hours-input {
        max-width: none;
        font-size: 16px;
    }

    .ts-preset {
        padding: 0.45rem 0.9rem;
    }

    .ts-modal-actions .btn {
        flex: 1 1 auto;
    }
}
