﻿/**
 * EffRx Sales Planner - Application Styles
 * Version: 2.0 - Modern Glassmorphism Design System
 *
 * This file imports design tokens and provides global styles using CSS variables.
 * All hard-coded colors have been replaced with design tokens.
 */

/* ========================================
   BASE STYLES
   ======================================== */
html, body {
    font-family: var(--font-family-base);
    background: var(--bg-body);
    color: var(--color-gray-700);
    min-height: 100vh;
}

a, .btn-link {
    color: var(--color-brand);
}

/* ========================================
   BOOTSTRAP OVERRIDES
   ======================================== */
.btn-primary {
    color: var(--color-white);
    background: var(--gradient-brand);
    border-color: var(--color-brand-dark);
}

.btn-primary:hover {
    background: var(--color-brand-dark);
    border-color: var(--color-brand-dark);
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: var(--shadow-focus);
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

/* Form Validation Styles */
.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--color-success);
}

.invalid {
    outline: 1px solid var(--color-danger);
}

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

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

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

/* Checkbox Border */
.darker-border-checkbox.form-check-input {
    border-color: var(--color-gray-400);
}

/* Placeholder Styles */
.form-floating > .form-control-plaintext::placeholder,
.form-floating > .form-control::placeholder {
    color: var(--color-gray-400);
    text-align: end;
}

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

/* Consistent button heights */
.btn {
    min-height: 38px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* R-014172: Until 22.08.2026 this class set ONLY a minimum height and shrank neither
   padding nor font - a .btn-modern.btn-sm was just as big as a normal button. In a table
   row that looked bulky.

   The values below are not newly invented: they already appeared twice, word for word, as
   a local override (.stock-viewer-table .btn-sm and .open-orders-table .btn-sm). The same
   workaround for the same class twice is the signal to fix the base instead of working
   around it a third time.

   The two overrides stay in place - they are equivalent in effect as a result, and class
   names can be built at runtime in Blazor (never remove a CSS rule without proof). */
/* Specificity 0,2,0 instead of 0,1,0 - DELIBERATELY, not by accident:
   .btn-modern appears LATER in this file (position ~8500 against ~4500) and sets
   padding: var(--spacing-2) var(--spacing-5). With equal specificity the later rule wins,
   which is why the first version of this fix had no effect - remeasured on the running
   screen, not assumed. With .btn-modern.btn-sm it no longer depends on the order, so a
   later reshuffling of the file cannot undo it again. */
.btn-modern.btn-sm {
    min-height: 0;
    padding: 2px var(--spacing-3);
    font-size: var(--font-size-sm);
    line-height: 1.2;
}

.btn-lg {
    min-height: 48px;
}

/* ========================================
   GLASSMORPHISM COMPONENTS
   ======================================== */

/* Glass Cards */
.glass-card {
    background: var(--glass-bg-strong);
    border-radius: var(--radius-xl);
    border: 1px solid var(--border-color);
    backdrop-filter: blur(var(--glass-blur));
    box-shadow: var(--shadow-md);
    overflow: hidden;
    transition: transform var(--transition-base), box-shadow var(--transition-base);
}

.glass-card.overflow-visible {
    overflow: visible;
}

.glass-card:hover {
    box-shadow: var(--shadow-lg);
}

.glass-card-elevated {
    box-shadow: var(--shadow-xl);
}

.glass-card-elevated:hover {
    transform: translateY(-4px);
}

.glass-card-brand {
    background: var(--gradient-brand);
    border: none;
}

.glass-card-header {
    padding: var(--spacing-3) var(--spacing-4);
    border-bottom: 1px solid var(--border-color);
    background: var(--gradient-brand-subtle);
}

.glass-card-body {
    padding: var(--spacing-4);
}

.card-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    margin: 0 0 var(--spacing-2);
    color: var(--color-gray-800);
}

.card-text {
    font-size: var(--font-size-base);
    color: var(--color-gray-600);
    margin: 0 0 var(--spacing-4);
}

/* ========================================
   METRIC CARDS
   ======================================== */
.metric-card {
    background: var(--glass-bg-strong);
    border-radius: var(--radius-xl);
    padding: var(--spacing-5);
    display: flex;
    align-items: center;
    gap: var(--spacing-4);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-md);
    transition: transform var(--transition-base), box-shadow var(--transition-base);
    /* Issue 14: fill the equal-height Bootstrap column so all four KPI cards match, even when
       only some carry a sublabel (< 30 days / Restricted Stock). */
    height: 100%;
}

.metric-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
}

/* R-014184: The cards used to carry a saturated border plus a gradient - four cards,
   four colors, all equally strong. That meant the one that needs attention was not
   highlighted. The same ailment as with the badges (R-014179), just one floor higher on
   the same page.

   Now the border carries the hint in a muted way, the gradient is dropped, and the color
   sits in the icon - that was already solved correctly there before (tinted area, colored
   glyph). */
.metric-card-warning {
    border-color: rgba(245, 158, 11, 0.40);
}

.metric-card-danger {
    border-color: rgba(239, 68, 68, 0.40);
}

/* A plain number is not a success. "Total Value" or "Total Products" call for no action
   and therefore get NO color on the border - otherwise the neutral metric would visually
   compete with the warning next to it. The class stays: it is used in the markup, and
   its icon still carries its restrained tint. */
.metric-card-success {
    border-color: var(--border-color);
}

.metric-icon {
    width: 48px;
    height: 48px;
    border-radius: var(--radius-lg);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.metric-icon-brand {
    background: var(--gradient-brand-subtle);
    color: var(--color-brand);
}

.metric-icon-warning {
    background: var(--color-warning-bg);
    color: var(--color-warning);
}

.metric-icon-danger {
    background: var(--color-danger-bg);
    color: var(--color-danger);
}

.metric-icon-success {
    background: var(--color-success-bg);
    color: var(--color-success);
}

.metric-content {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.metric-label {
    font-size: var(--font-size-sm);
    color: var(--color-gray-500);
    font-weight: var(--font-weight-medium);
}

.metric-value {
    font-size: var(--font-size-2xl);
    font-weight: var(--font-weight-bold);
    color: var(--color-gray-900);
    line-height: var(--line-height-tight);
}

.metric-sublabel {
    font-size: var(--font-size-xs);
    color: var(--color-gray-500);
}

.metric-card-warning .metric-sublabel {
    color: var(--color-warning);
}

.metric-card-danger .metric-sublabel {
    color: var(--color-danger);
}

/* ========================================
   MODERN BUTTONS
   ======================================== */
.btn-modern {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-2);
    padding: var(--spacing-2) var(--spacing-5);
    font-family: var(--font-family-base);
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-semibold);
    line-height: 1.5;
    border-radius: var(--radius-md);
    border: none;
    cursor: pointer;
    transition: all var(--transition-base);
    text-decoration: none;
}

.btn-modern:focus-visible {
    outline: none;
    box-shadow: var(--shadow-focus);
}

.btn-modern:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Primary Button */
.btn-modern-primary {
    background: var(--gradient-brand);
    color: white;
    box-shadow: var(--shadow-sm);
}

.btn-modern-primary:hover:not(:disabled) {
    box-shadow: var(--shadow-glow-brand);
    transform: translateY(-1px);
    color: white;
}

/* Secondary Button */
.btn-modern-secondary {
    background: var(--color-gray-600);
    color: white;
    box-shadow: var(--shadow-sm);
}

.btn-modern-secondary:hover:not(:disabled) {
    background: var(--color-gray-700);
    transform: translateY(-1px);
    color: white;
}

/* Success Button */
/* R-014186: Used to be a saturated gradient with a glow effect - the loudest element on
   pages whose tables and cards were toned down with R-014179/R-014184. The class is used
   six times, mostly for "Export CSV"; green claims a state ("succeeded") there that an
   action does not have.

   Solid color instead of gradient, no glow. The color hint stays, the loudness goes away.
   The class name stays so no markup has to be touched. */
.btn-modern-success {
    background: var(--color-success-text);
    color: white;
    box-shadow: var(--shadow-xs);
}

.btn-modern-success:hover:not(:disabled) {
    background: #036147;
    box-shadow: var(--shadow-sm);
    color: white;
}

/* Danger Button */
.btn-modern-danger {
    background: linear-gradient(135deg, var(--color-danger) 0%, var(--color-danger-light) 100%);
    color: white;
    box-shadow: var(--shadow-sm);
}

.btn-modern-danger:hover:not(:disabled) {
    box-shadow: var(--shadow-glow-danger);
    transform: translateY(-1px);
    color: white;
}

/* Warning Button */
.btn-modern-warning {
    background: linear-gradient(135deg, var(--color-warning) 0%, var(--color-warning-light) 100%);
    color: var(--color-gray-900);
    box-shadow: var(--shadow-sm);
}

.btn-modern-warning:hover:not(:disabled) {
    transform: translateY(-1px);
}

/* Light Button */
.btn-modern-light {
    background: rgba(255, 255, 255, 0.2);
    color: white;
    backdrop-filter: blur(4px);
    border: 1px solid rgba(255, 255, 255, 0.3);
}

.btn-modern-light:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.3);
    color: white;
}

/* Outline Buttons */
/* R-014056: .btn-modern-outline-primary was used in Dashboard.razor but was not defined -
   the button rendered without border or color. .btn-modern-outline is already the
   brand-colored outline button, so the selector is extended. See the reasoning at
   .badge-soft-brand. */
.btn-modern-outline,
.btn-modern-outline-primary {
    background: transparent;
    color: var(--color-brand);
    border: 2px solid var(--color-brand);
}

.btn-modern-outline:hover:not(:disabled),
.btn-modern-outline-primary:hover:not(:disabled) {
    background: var(--gradient-brand-subtle);
    color: var(--color-brand);
}

.btn-modern-outline-secondary {
    background: transparent;
    color: var(--color-gray-600);
    border: 2px solid var(--color-gray-300);
}

.btn-modern-outline-secondary:hover:not(:disabled) {
    background: var(--color-gray-100);
    border-color: var(--color-gray-400);
    color: var(--color-gray-700);
}

.btn-modern-outline-success {
    background: transparent;
    color: var(--color-success);
    border: 2px solid var(--color-success);
}

.btn-modern-outline-success:hover:not(:disabled) {
    background: var(--color-success-bg);
    color: var(--color-success);
}

.btn-modern-outline-danger {
    background: transparent;
    color: var(--color-danger);
    border: 2px solid var(--color-danger);
}

.btn-modern-outline-danger:hover:not(:disabled) {
    background: var(--color-danger-bg);
    color: var(--color-danger);
}

.btn-modern-outline-warning {
    background: transparent;
    color: var(--color-warning);
    border: 2px solid var(--color-warning);
}

.btn-modern-outline-warning:hover:not(:disabled) {
    background: var(--color-warning-bg);
    color: var(--color-warning);
}

/* Button Sizes */
.btn-modern-lg {
    padding: var(--spacing-3) var(--spacing-6);
    font-size: var(--font-size-lg);
    border-radius: var(--radius-lg);
}

.btn-modern-sm {
    padding: var(--spacing-1) var(--spacing-3);
    font-size: var(--font-size-sm);
}

/* Button Loading */
.btn-loading {
    position: relative;
}

.btn-loading .spinner-border {
    width: 1rem;
    height: 1rem;
    border-width: 2px;
    margin-right: var(--spacing-2);
}

/* Button Group */
.btn-group-modern {
    display: inline-flex;
    gap: var(--spacing-2);
}

/* ========================================
   ICON BUTTONS
   Ghost icon buttons — square, transparent background, branded hover.
   Used in widget headers, chart picker rows, and modal actions.
   ======================================== */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    background: transparent;
    color: var(--color-gray-500);
    cursor: pointer;
    transition: all var(--transition-fast);
    flex-shrink: 0;
    padding: 0;
}

.btn-icon:hover:not(:disabled) {
    background: var(--color-gray-100);
    color: var(--color-brand);
}

.btn-icon.danger:hover:not(:disabled),
.btn-icon-danger:hover:not(:disabled) {
    background: var(--color-danger-bg);
    color: var(--color-danger);
}

.btn-icon:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.btn-icon-sm {
    width: 28px;
    height: 28px;
    border-radius: var(--radius-sm);
}

/* ========================================
   MODERN BADGES
   ======================================== */
/* R-014179: Small caps and letter spacing were dropped - they made every badge shout,
   even the one for the normal case. The shape is now a flat label with a tinted area and
   dark text instead of a saturated pill with white text; a thin line now provides the
   separation. */
.badge-modern {
    display: inline-flex;
    align-items: center;
    padding: 1px var(--spacing-2);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    line-height: 1.45;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    white-space: nowrap;
}

/* Status Badges */
.badge-blocked {
    background: var(--color-status-blocked);
    color: white;
}

.badge-backlog {
    background: var(--color-status-backlog);
    color: white;
}

.badge-open {
    background: var(--color-status-open);
    color: var(--color-gray-900);
}

.badge-wip {
    background: var(--color-status-wip);
    color: var(--color-gray-900);
}

.badge-transit {
    background: var(--color-status-transit);
    color: white;
}

/* Semantic Badges */
.badge-primary {
    background: rgba(var(--color-brand-rgb), 0.10);
    color: var(--color-brand);
    border-color: rgba(var(--color-brand-rgb), 0.22);
}

.badge-success {
    background: var(--color-success-bg);
    color: var(--color-success-text);
    border-color: rgba(16, 185, 129, 0.28);
}

.badge-warning {
    background: var(--color-warning-bg);
    color: var(--color-warning-text);
    border-color: rgba(245, 158, 11, 0.32);
}

.badge-danger {
    background: var(--color-danger-bg);
    color: var(--color-danger-text);
    border-color: rgba(239, 68, 68, 0.30);
}

.badge-info {
    background: var(--color-info-bg);
    color: var(--color-info-text);
    border-color: rgba(59, 130, 246, 0.28);
}

/* Soft Badges */
/* R-014056: .badge-soft-brand was used in Sales.razor but was defined nowhere - the
   badge rendered unstyled. It means the same styling as .badge-soft-primary, so the
   selector is extended instead of writing the declarations out a second time. Two names
   for one rule are acceptable; two rules for the same color drift apart the moment
   someone touches only one of them. */
.badge-soft-primary,
.badge-soft-brand {
    background: rgba(29, 61, 145, 0.1);
    color: var(--color-brand);
}

.badge-soft-secondary {
    background: var(--color-gray-200);
    color: var(--color-gray-700);
}

.badge-soft-info {
    background: var(--color-info-bg);
    color: var(--color-info);
}

/* R-014056: used in Settings.razor ("Unsaved changes"), was not defined. Follows the
   family: soft area from the background tint, text in the full color. */
.badge-soft-warning {
    background: var(--color-warning-bg);
    color: var(--color-warning);
}

/* ========================================
   MODERN ALERTS
   ======================================== */
.alert-modern {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-2);
    padding: var(--spacing-2) var(--spacing-3);
    border-radius: var(--radius-lg);
    border: 1px solid transparent;
    margin-bottom: var(--spacing-3);
}

.alert-icon {
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.alert-content {
    flex: 1;
    font-size: var(--font-size-base);
    line-height: 1.5;
}

.alert-close {
    flex-shrink: 0;
    background: transparent;
    border: none;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.5;
    transition: opacity var(--transition-fast);
}

.alert-close:hover {
    opacity: 1;
}

.alert-modern.alert-success {
    background: var(--color-success-bg);
    border-color: var(--color-success);
    color: var(--color-success);
}

.alert-modern.alert-danger {
    background: var(--color-danger-bg);
    border-color: var(--color-danger);
    color: var(--color-danger);
}

.alert-modern.alert-warning {
    background: var(--color-warning-bg);
    border-color: var(--color-warning);
    color: var(--color-warning);
}

.alert-modern.alert-info {
    background: var(--color-info-bg);
    border-color: var(--color-info);
    color: var(--color-info);
}

/* ========================================
   MODERN TABLES
   ======================================== */
.table-modern-container {
    overflow-x: auto;
}

.table-modern {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
}

/* R-014042: Child combinator instead of descendant. Four pages nest a
   .table-modern-detail INSIDE a .table-modern - MonthlySales, OpenOrders,
   StockViewer and SampleUI. With ".table-modern thead th" the rule also hit the header
   row of the inner table.

   Why this leaked through despite the inner table's own detail rules: both rule sets have
   specificity (0,1,2), the detail rules come later and therefore win - but ONLY for
   properties they set themselves. For everything else the outer rule stayed in effect.
   The detail table thereby inherited text-align, border, the corner rounding from
   :first-child and :last-child, and the zebra stripe pattern - styling that was never
   meant for an embedded table.

   The combinator sits only at the FIRST step (".table-modern > thead th", not
   "> thead > tr > th"). That is enough, because the inner table's header row is not a
   direct child of the outer one - and it keeps the specificity at (0,1,2). The full child
   path would have been (0,1,3).

   DELIBERATELY NOT CHANGED: the tbody block below. There the first step is not enough,
   because the inner table sits inside a cell of the outer one, so its td stays a
   descendant of the outer tbody. What would be needed is "> tbody > tr > td" with
   specificity (0,1,3) - and that would silently override .stock-viewer-table,
   .open-orders-table and .stock-detail-batch-table (each (0,1,2), currently winning
   through source order). A fix that reverses three existing overrides is not a fix. The
   rest of the leak there is limited to font size and is to be handled as its own item. */
.table-modern > thead {
    background: var(--table-header-bg);
}

/* R-014179: light area, dark text, separation via a line. The column names never
   change - they need no color band pulling attention away from the rows. Tighter
   padding: row density was the second reason the tables felt busy. */
.table-modern > thead th {
    padding: var(--spacing-2) var(--spacing-3);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--table-header-color);
    text-align: left;
    border: none;
    border-bottom: 1px solid var(--table-header-border);
}

.table-modern > thead th:first-child {
    border-top-left-radius: var(--table-radius);
}

.table-modern > thead th:last-child {
    border-top-right-radius: var(--table-radius);
}

.table-modern > thead th.col-sortable {
    cursor: pointer;
    user-select: none;
}

.table-modern > thead th.col-sortable:hover {
    background: var(--color-gray-100);
}

.table-modern tbody td {
    padding: var(--spacing-2) var(--spacing-3);
    font-size: var(--font-size-sm);
    color: var(--color-gray-700);
    border-bottom: 1px solid var(--border-color);
    background: var(--color-white);
}

.table-modern tbody tr:hover td {
    background: var(--table-row-hover);
}

.table-modern tbody tr:nth-child(even) td {
    background: var(--table-stripe-bg);
}

.table-modern tbody tr:nth-child(even):hover td {
    background: var(--table-row-hover);
}

/* R-013977: three tables have been switched to .table-modern - batch traceability,
   returns, and the JSON editor. This makes colors, borders, font weight and header
   background follow the design system instead of hardcoded values; that was exactly the
   point of the consolidation.

   ONE property is deliberately NOT to be aligned: the padding. These three are
   deliberately dense tables - the JSON editor shows key-value pairs, batch traceability
   stacks five tables on top of each other. The design system's default padding would make
   them noticeably taller, and that is not alignment but a loss of function.

   Why as its own rule and not in the existing blocks: their selectors have specificity
   (0,1,1) and have been losing against .table-modern (0,1,2) since the switch - which is
   intended for colors and borders. Naming both classes lifts ONLY the padding back above
   that, without removing anything from the existing blocks. The color and border
   declarations that have become ineffective there stay in place; cleaning them up is part
   of the open decision in R-013977. */
.table-modern.batchtrace-table thead th,
.table-modern.batchtrace-table tbody td {
    padding: 5px 8px;
}

.table-modern.returns-table tbody td {
    padding: 4px 6px;
}

.table-modern.jsonedit-table thead th,
.table-modern.jsonedit-table tbody td {
    padding: 3px 8px;
}

/* R-014187: The chip area has been dropped. A material number appears in EVERY row -
   what looks the same in every row distinguishes nothing and, as a styling choice, adds
   no information, only visual noise. The monospace font stays: it makes digit sequences
   comparable against each other, and that is a real benefit. */
.material-code {
    font-family: var(--font-family-mono);
    font-size: var(--font-size-sm);
    color: var(--color-gray-700);
}

/* Expandable Table Styles */
.expand-col {
    width: 48px;
}

.expand-btn-modern {
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* R-014184: White on semi-transparent white - that was built for the former
       DARK-BLUE table header. Since the header has been tinted light (R-014182), the
       "+" was practically invisible. Now the same brand coloring as the variant in the
       data rows (.expand-btn-row) - one visual language instead of two. */
    background: rgba(var(--color-brand-rgb), 0.12);
    border: none;
    border-radius: var(--radius-sm);
    color: var(--color-brand);
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-bold);
    cursor: pointer;
    transition: background var(--transition-fast);
}

.expand-btn-modern:hover {
    background: rgba(var(--color-brand-rgb), 0.20);
}

.expand-btn-modern.expand-btn-row {
    background: var(--gradient-brand-subtle);
    color: var(--color-brand);
}

.expand-btn-modern.expand-btn-row:hover {
    background: rgba(29, 61, 145, 0.15);
}

.detail-row td {
    background: var(--color-gray-50) !important;
}

.detail-container-modern {
    padding: var(--spacing-4);
    background: linear-gradient(135deg, rgba(29, 61, 145, 0.03) 0%, rgba(59, 103, 212, 0.02) 100%);
    border-left: 3px solid var(--color-brand);
    margin: 0;
}

.table-modern-detail {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: var(--font-size-sm);
}

.table-modern-detail thead {
    background: var(--color-gray-100);
}

.table-modern-detail > thead th {
    padding: var(--spacing-2) var(--spacing-3);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--color-gray-600);
    text-transform: uppercase;
    letter-spacing: 0.025em;
    border-bottom: 1px solid var(--border-color);
}

.table-modern-detail > tbody > tr > td {
    padding: var(--spacing-2) var(--spacing-3);
    color: var(--color-gray-700);
    border-bottom: 1px solid var(--border-color);
    background: var(--color-white);
}

.table-modern-detail > tbody > tr:last-child > td {
    border-bottom: none;
}

/* R-014187: same reasoning as for .material-code - a batch number appears in every
   detail row. Font stays, area goes. */
.batch-code {
    font-family: var(--font-family-mono);
    font-size: var(--font-size-xs);
    color: var(--color-gray-600);
}

.days-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 40px;
    padding: 2px 8px;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-bold);
    border-radius: var(--radius-sm);
}

.days-ok {
    background: var(--color-success-bg);
    color: var(--color-success);
}

.days-warning {
    background: var(--color-warning-bg);
    color: var(--color-warning);
}

.days-critical {
    background: var(--color-danger-bg);
    color: var(--color-danger);
}

/* ========================================
   MODERN FORMS
   ======================================== */
.form-label-modern {
    display: block;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-gray-700);
    margin-bottom: var(--spacing-2);
}

.form-label-modern .required {
    color: var(--color-danger);
}

.form-control-modern {
    display: block;
    width: 100%;
    padding: var(--spacing-2) var(--spacing-3);
    font-family: var(--font-family-base);
    font-size: var(--font-size-base);
    color: var(--color-gray-800);
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    border-radius: var(--input-radius);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form-control-modern:focus {
    outline: none;
    border-color: var(--input-focus-border);
    box-shadow: var(--input-focus-shadow);
}

.form-control-modern:disabled {
    background: var(--color-gray-100);
    cursor: not-allowed;
    opacity: 0.7;
}

.form-control-modern.is-valid {
    border-color: var(--color-success);
}

.form-control-modern.is-valid:focus {
    box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.2);
}

.form-control-modern.is-invalid {
    border-color: var(--color-danger);
}

.form-control-modern.is-invalid:focus {
    box-shadow: var(--shadow-focus-danger);
}

.form-control-modern.form-control-sm {
    padding: var(--spacing-1) var(--spacing-2);
    font-size: var(--font-size-sm);
}

/* Form group wrapper and input alias */
.form-group-modern {
    margin-bottom: var(--spacing-4);
}

/* Alias for form-control-modern — used in modal forms */
.form-input-modern {
    display: block;
    width: 100%;
    padding: var(--spacing-2) var(--spacing-3);
    font-family: var(--font-family-base);
    font-size: var(--font-size-base);
    color: var(--color-gray-800);
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    border-radius: var(--input-radius);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form-input-modern:focus {
    outline: none;
    border-color: var(--input-focus-border);
    box-shadow: var(--input-focus-shadow);
}

.form-input-modern::placeholder {
    color: var(--color-gray-400);
}

.form-help-modern {
    font-size: var(--font-size-xs);
    color: var(--color-gray-500);
    margin-top: var(--spacing-1);
}

.form-feedback {
    font-size: var(--font-size-sm);
    margin-top: var(--spacing-1);
}

.form-feedback.valid {
    color: var(--color-success);
}

.form-feedback.invalid {
    color: var(--color-danger);
}

/* Modern Checkboxes */
.form-check-modern {
    display: flex;
    align-items: center;
    gap: var(--spacing-2);
    margin-bottom: var(--spacing-2);
}

.form-check-modern input[type="checkbox"] {
    width: 18px;
    height: 18px;
    accent-color: var(--color-brand);
    cursor: pointer;
}

.form-check-modern input[type="checkbox"]:disabled {
    cursor: not-allowed;
    opacity: 0.5;
}

.form-check-modern label {
    font-size: var(--font-size-base);
    color: var(--color-gray-700);
    cursor: pointer;
}

.form-actions {
    display: flex;
    gap: var(--spacing-3);
}

/* ========================================
   MODERN MODAL
   ======================================== */
.modal-overlay {
    position: fixed;
    inset: 0;
    background: var(--modal-backdrop);
    backdrop-filter: blur(4px);
    z-index: var(--z-modal);
    animation: fadeIn var(--transition-base);
}

.modal-modern {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 90%;
    max-width: 500px;
    background: var(--modal-bg);
    border-radius: var(--modal-radius);
    box-shadow: 0 10px 40px -8px rgba(20, 34, 80, 0.35), 0 2px 8px rgba(20, 34, 80, 0.10);
    z-index: calc(var(--z-modal) + 1);
    backdrop-filter: blur(var(--glass-blur-strong));
    animation: slideIn var(--transition-base);
    overflow: hidden;
}

/* Accent bar at top — brand gradient stripe */
.modal-modern::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 3px;
    background: linear-gradient(90deg, var(--color-brand), var(--color-brand-light) 55%, var(--color-accent));
    z-index: 1;
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

@keyframes slideIn {
    from {
        opacity: 0;
        transform: translate(-50%, -48%);
    }
    to {
        opacity: 1;
        transform: translate(-50%, -50%);
    }
}

.modal-modern-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--spacing-4) var(--spacing-6);
    border-bottom: 1px solid var(--border-color);
}

.modal-modern-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-gray-900);
    margin: 0;
}

.modal-close {
    background: transparent;
    border: none;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    color: var(--color-gray-500);
    transition: color var(--transition-fast);
}

.modal-close:hover {
    color: var(--color-gray-900);
}

.modal-modern-body {
    padding: var(--spacing-6);
}

.modal-modern-footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--spacing-3);
    padding: var(--spacing-4) var(--spacing-6);
    border-top: 1px solid var(--border-color);
    background: var(--gradient-brand-subtle);
}

/* ========================================
   MODAL SCROLLABLE BODY
   Adds a thin branded scrollbar when modal body content overflows.
   Apply to .modal-modern-body when the list is long.
   ======================================== */
.modal-scroll {
    max-height: 420px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(var(--color-brand-rgb), 0.25) transparent;
}

.modal-scroll::-webkit-scrollbar {
    width: 6px;
}

.modal-scroll::-webkit-scrollbar-track {
    background: transparent;
}

.modal-scroll::-webkit-scrollbar-thumb {
    background: rgba(var(--color-brand-rgb), 0.25);
    border-radius: var(--radius-full);
}

.modal-scroll::-webkit-scrollbar-thumb:hover {
    background: rgba(var(--color-brand-rgb), 0.4);
}

/* ========================================
   CHART PICKER (Add Chart to Dashboard modal)
   Replaces inline styles in Dashboard.razor's "Add Chart" modal list.
   ======================================== */
.chart-picker-section {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-gray-400);
    padding: var(--spacing-3) 0 var(--spacing-2);
    border-bottom: 1px solid var(--color-gray-200);
    margin-bottom: var(--spacing-1);
}

.chart-picker-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--spacing-2) 0;
    border-bottom: 1px solid var(--border-color);
}

.chart-picker-row-main {
    min-width: 0;
    flex: 1;
}

.chart-picker-title {
    font-weight: var(--font-weight-semibold);
    color: var(--color-gray-700);
}

.chart-picker-meta {
    font-size: var(--font-size-xs);
    color: var(--color-gray-500);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chart-picker-actions {
    display: flex;
    align-items: center;
    gap: var(--spacing-1);
    margin-left: var(--spacing-3);
    flex-shrink: 0;
}

/* ========================================
   MODERN SPINNER
   ======================================== */
.spinner-modern {
    width: 40px;
    height: 40px;
    border: 3px solid var(--border-color);
    border-top-color: var(--color-brand);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

/* ========================================
   STOCK VIEWER & CALENDAR (Updated)
   ======================================== */
.stock-calendar {
    margin-bottom: 0;
    font-size: 0.8rem;
    width: auto;
}

.stock-calendar thead th {
    padding: 2px;
    font-size: var(--font-size-xs);
    text-align: center;
    font-weight: var(--font-weight-semibold);
}

.stock-calendar .calendar-day {
    padding: 2px;
    vertical-align: middle;
    font-size: var(--font-size-sm);
    width: 30px;
    height: 30px;
    text-align: center;
}

.stock-calendar .calendar-day.empty {
    background-color: var(--color-gray-50);
}

.stock-calendar .calendar-day.no-data {
    color: var(--color-gray-400);
    background-color: var(--color-gray-50);
}

.stock-calendar .calendar-day.has-data {
    font-weight: var(--font-weight-bold);
    background-color: var(--color-white);
}

.stock-calendar .calendar-day.has-data:hover {
    background-color: var(--calendar-hover-bg);
}

.stock-calendar .calendar-day.selected {
    background-color: var(--calendar-selected-bg);
    color: white;
    font-weight: var(--font-weight-bold);
}

/* Stock Viewer Table - Dense Layout */
.stock-viewer-table {
    font-size: var(--font-size-sm);
}

.table-modern.stock-viewer-table thead th {
    padding: 8px 10px;
    font-size: var(--font-size-sm);
}

.table-modern.stock-viewer-table tbody td {
    padding: 6px 10px;
    vertical-align: middle;
}

.stock-viewer-table .btn-sm {
    padding: 2px 6px;
    font-size: var(--font-size-base);
    line-height: 1.2;
}

.stock-viewer-table .badge {
    font-size: var(--font-size-xs);
    padding: 3px 6px;
}

.stock-viewer-table code {
    font-size: var(--font-size-sm);
}

/* Expand/Collapse Button */
.expand-btn {
    background: transparent;
    border: none;
    padding: 0;
    width: 18px;
    height: 18px;
    line-height: 1;
    cursor: pointer;
    color: var(--color-gray-500);
    font-weight: var(--font-weight-bold);
    font-size: var(--font-size-sm);
}

.expand-btn:hover {
    color: var(--color-brand);
}

/* Stock Detail Container */
.detail-container {
    background-color: var(--color-gray-50);
    padding: 10px;
    border-left: 4px solid var(--color-brand);
}

.detail-container table {
    font-size: var(--font-size-sm);
}

.detail-container table thead th {
    padding: 5px 8px;
    font-size: var(--font-size-xs);
}

.detail-container table tbody td {
    padding: 4px 8px;
}

/* Open Orders Table */
.open-orders-table {
    font-size: var(--font-size-sm);
}

.table-modern.open-orders-table thead th {
    padding: 8px 10px;
    font-size: var(--font-size-sm);
}

.table-modern.open-orders-table tbody td {
    padding: 6px 10px;
    vertical-align: middle;
}

.open-orders-table .btn-sm {
    padding: 2px 6px;
    font-size: var(--font-size-base);
    line-height: 1.2;
}

.open-orders-table .badge {
    font-size: var(--font-size-xs);
    padding: 3px 6px;
}

.open-orders-table code {
    font-size: var(--font-size-sm);
}

/* Order Status Badges (using design tokens) */
.badge.status-blocked {
    background-color: var(--color-status-blocked);
}

.badge.status-backlog {
    background-color: var(--color-status-backlog);
}

.badge.status-open {
    background-color: var(--color-status-open);
    color: var(--color-gray-900);
}

.badge.status-wip {
    background-color: var(--color-status-wip);
    color: var(--color-gray-900);
}

.badge.status-transit {
    background-color: var(--color-status-transit);
}

/* ========================================
   PAGE TITLE
   ======================================== */
.page-title {
    font-size: var(--font-size-2xl);
    font-weight: var(--font-weight-bold);
    color: var(--color-gray-900);
    margin-bottom: var(--spacing-3);
}

/* ========================================
   UTILITY CLASSES
   ======================================== */
.text-brand {
    color: var(--color-brand);
}

.text-success {
    color: var(--color-success) !important;
}

.text-warning {
    color: var(--color-warning) !important;
}

.text-danger {
    color: var(--color-danger) !important;
}

.text-info {
    color: var(--color-info) !important;
}

.bg-brand {
    background: var(--gradient-brand);
}

.bg-brand-subtle {
    background: var(--gradient-brand-subtle);
}

/* ========================================
   SEGMENTED CONTROL
   ======================================== */
.segmented-control {
    display: inline-flex;
    background: var(--color-gray-100);
    border-radius: var(--radius-md);
    padding: 3px;
    gap: 2px;
    border: 1px solid var(--border-color);
}

.segmented-control-item {
    padding: var(--spacing-1) var(--spacing-4);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-gray-600);
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: all var(--transition-fast);
    white-space: nowrap;
}

.segmented-control-item:hover {
    color: var(--color-gray-800);
}

.segmented-control-item.active {
    background: var(--color-white);
    color: var(--color-brand);
    font-weight: var(--font-weight-semibold);
    box-shadow: var(--shadow-sm);
}

/* ========================================
   CHIP INPUT
   ======================================== */
.chip-input-container {
    position: relative;
}

.chip-input-wrapper {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    padding: 4px 8px;
    min-height: 38px;
    align-items: center;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    border-radius: var(--input-radius);
    transition: border-color 0.2s ease;
}

.chip-input-wrapper:focus-within {
    border-color: var(--input-focus-border);
    box-shadow: var(--input-focus-shadow);
}

.chip-input-wrapper input {
    flex: 1;
    min-width: 80px;
    border: none;
    outline: none;
    background: transparent;
    color: var(--color-gray-700);
    font-size: var(--font-size-sm);
    padding: 4px;
}

.chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    background: var(--gradient-brand-subtle);
    color: var(--color-brand-dark);
    border-radius: var(--radius-full);
    font-size: 0.75rem;
    font-weight: var(--font-weight-medium);
    white-space: nowrap;
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chip-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border: none;
    background: rgba(0, 0, 0, 0.1);
    color: var(--color-brand-dark);
    border-radius: 50%;
    cursor: pointer;
    font-size: 0.65rem;
    line-height: 1;
    padding: 0;
    flex-shrink: 0;
}

.chip-remove:hover {
    background: rgba(0, 0, 0, 0.2);
}

.chip-suggestions {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 1050;
    max-height: 240px;
    overflow-y: auto;
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    margin-top: 4px;
    box-shadow: var(--shadow-lg);
}

.chip-suggestion-item {
    padding: 8px 12px;
    cursor: pointer;
    font-size: var(--font-size-sm);
    color: var(--color-gray-700);
    transition: background 0.15s ease;
    border-bottom: 1px solid var(--glass-border);
}

.chip-suggestion-item:last-child {
    border-bottom: none;
}

.chip-suggestion-item:hover {
    background: rgba(99, 102, 241, 0.08);
}

.chip-suggestion-item .suggestion-sub {
    color: var(--color-gray-500);
    font-size: 0.7rem;
}

/* ========================================
   WIZARD STEPS
   ======================================== */
.wizard-steps {
    display: flex;
    gap: 0;
    margin-bottom: var(--spacing-3);
    position: relative;
}

.wizard-step {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    cursor: pointer;
    padding: var(--spacing-1) var(--spacing-2);
    position: relative;
    transition: all 0.2s ease;
}

.wizard-step::after {
    content: '';
    position: absolute;
    top: 16px;
    right: -50%;
    width: 100%;
    height: 2px;
    background: var(--glass-border);
    z-index: 0;
}

.wizard-step:last-child::after {
    display: none;
}

.wizard-step.active::after,
.wizard-step.completed::after {
    background: var(--color-brand);
}

.wizard-step-number {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: var(--font-weight-semibold);
    font-size: var(--font-size-xs);
    background: var(--glass-bg);
    border: 2px solid var(--glass-border);
    color: var(--color-gray-500);
    z-index: 1;
    transition: all 0.2s ease;
}

.wizard-step.active .wizard-step-number {
    background: var(--gradient-brand);
    border-color: var(--color-brand);
    color: var(--color-white);
    box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15);
}

.wizard-step.completed .wizard-step-number {
    background: var(--color-success);
    border-color: var(--color-success);
    color: var(--color-white);
}

.wizard-step-label {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-gray-500);
}

.wizard-step.active .wizard-step-label {
    color: var(--color-brand);
}

.wizard-step.completed .wizard-step-label {
    color: var(--color-success);
}

.wizard-step-summary {
    font-size: 0.7rem;
    color: var(--color-gray-500);
    text-align: center;
    max-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ========================================
   DROPDOWN PANEL (Column Chooser)
   ======================================== */
/* The toolbar above the result table - R-014181.

   Replaces the embedded style attribute "position: relative; z-index: 100" from
   Sales.razor. The number sat there in the middle of the markup and was therefore
   neither discoverable nor aligned with the other stacking values; that is exactly what
   caused the reported bug. */
.results-toolbar {
    position: relative;
    z-index: var(--z-dropdown);
}

/* Only while the column chooser is open. Set permanently, the toolbar would sit above
   the sticky Apply bar that is meant to stay visible while scrolling - the bug would then
   simply be inverted. */
.results-toolbar.collapsible-open {
    z-index: var(--z-collapsible);
}

.dropdown-panel {
    position: absolute;
    bottom: 100%;
    right: 0;
    /* Within the toolbar's context a single value from the scale is enough. The former
       1050 was false precision: it never left this context (R-014181). */
    z-index: var(--z-dropdown);
    min-width: 280px;
    max-height: 400px;
    overflow-y: auto;
    /* Opaque: see --dropdown-bg. No backdrop-filter - nobody needs the stacking context
       it creates here, and the area is not meant to let anything show through anyway. */
    background: var(--dropdown-bg);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-lg);
    margin-bottom: 4px;
    box-shadow: var(--shadow-lg);
    padding: var(--spacing-4);
}

.dropdown-panel-header {
    font-weight: var(--font-weight-semibold);
    font-size: var(--font-size-sm);
    color: var(--color-gray-700);
    margin-bottom: var(--spacing-3);
    padding-bottom: var(--spacing-2);
    border-bottom: 1px solid var(--glass-border);
}

.dropdown-panel-presets {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: var(--spacing-3);
}

.dropdown-panel-presets button {
    padding: 4px 10px;
    font-size: 0.75rem;
    border: 1px solid var(--glass-border);
    background: transparent;
    border-radius: var(--radius-full);
    color: var(--color-gray-600);
    cursor: pointer;
    transition: all 0.2s ease;
}

.dropdown-panel-presets button:hover,
.dropdown-panel-presets button.active {
    background: var(--gradient-brand-subtle);
    border-color: var(--color-brand);
    color: var(--color-brand-dark);
}

/* ========================================
   COLUMN GROUP PICKER (Wizard Step 4)
   ======================================== */
.col-group {
    margin-bottom: var(--spacing-3);
}

.col-group:last-child {
    margin-bottom: 0;
}

.col-group-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--spacing-2);
}

.col-group-name {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-gray-500);
}

.col-group-count {
    font-weight: var(--font-weight-normal);
    color: var(--color-gray-400);
    margin-left: 4px;
}

.col-group-actions {
    font-size: var(--font-size-xs);
}

.col-group-actions a {
    color: var(--color-brand);
    cursor: pointer;
    text-decoration: none;
    font-weight: var(--font-weight-medium);
}

.col-group-actions a:hover {
    text-decoration: underline;
}

.col-group-divider {
    color: var(--color-gray-300);
    margin: 0 2px;
}

.col-group-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.col-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 5px 12px;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-normal);
    color: var(--color-gray-500);
    background: var(--color-gray-100);
    border: 1px solid var(--color-gray-200);
    border-radius: var(--radius-full);
    cursor: pointer;
    transition: all 0.15s ease;
    white-space: nowrap;
    line-height: 1.3;
}

.col-chip:hover {
    background: var(--color-gray-200);
    border-color: var(--color-gray-300);
    color: var(--color-gray-700);
}

.col-chip-selected {
    background: rgba(99, 102, 241, 0.1);
    border-color: rgba(99, 102, 241, 0.3);
    color: var(--color-brand);
    font-weight: var(--font-weight-medium);
}

.col-chip-selected:hover {
    background: rgba(99, 102, 241, 0.18);
    border-color: rgba(99, 102, 241, 0.45);
    color: var(--color-brand-dark);
}

.col-chip svg {
    flex-shrink: 0;
}

/* Sales Summary Panel (Step 4 right side) */
.sales-summary-panel {
    flex: 0 0 280px;
    align-self: flex-start;
    border-left: 2px solid rgba(29, 61, 145, 0.15);
    padding-left: var(--spacing-4);
}

.sales-summary-title {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-gray-500);
    margin-bottom: var(--spacing-2);
}

.sales-summary-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 4px 0;
    gap: var(--spacing-3);
    border-bottom: 1px solid var(--border-color);
}

.sales-summary-row:last-child {
    border-bottom: none;
}

.sales-summary-row .dashboard-summary-label {
    font-size: var(--font-size-xs);
    color: var(--color-gray-500);
    white-space: nowrap;
}

.sales-summary-row .dashboard-summary-value {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--color-gray-700);
    text-align: right;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

@media (max-width: 992px) {
    .sales-summary-panel {
        flex: 1 1 100%;
        border-left: none;
        border-top: 2px solid rgba(29, 61, 145, 0.15);
        padding-left: 0;
        padding-top: var(--spacing-3);
    }
}

/* ========================================
   SAVED VIEWS - LIST + PREVIEW LAYOUT
   ======================================== */
.saved-views-layout {
    display: flex;
    gap: var(--spacing-4);
    min-height: 200px;
}

.saved-views-list {
    flex: 0 0 240px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 320px;
    overflow-y: auto;
}

.saved-views-section-label {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-gray-500);
    padding: var(--spacing-1) var(--spacing-2);
    margin-bottom: 2px;
}

.saved-view-item {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    width: 100%;
    padding: var(--spacing-2) var(--spacing-3);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    cursor: pointer;
    text-align: left;
    transition: all 0.15s ease;
}

.saved-view-item:hover {
    background: var(--color-gray-50);
    border-color: var(--color-gray-200);
}

.saved-view-item.active {
    background: rgba(99, 102, 241, 0.08);
    border-color: rgba(99, 102, 241, 0.25);
}

.saved-view-item-name {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--text-primary);
    line-height: 1.3;
}

.saved-view-item.active .saved-view-item-name {
    color: var(--color-brand);
}

.saved-view-item-desc {
    font-size: var(--font-size-xs);
    color: var(--color-gray-500);
    line-height: 1.3;
}

.saved-view-preview {
    flex: 1;
    background: var(--color-gray-50);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    padding: var(--spacing-4);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-3);
}

.saved-view-preview-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: var(--color-gray-400);
    font-size: var(--font-size-sm);
}

.saved-view-preview-header {
    padding-bottom: var(--spacing-3);
    border-bottom: 1px solid var(--border-color);
}

.saved-view-preview-title {
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-semibold);
    color: var(--text-primary);
}

.saved-view-preview-desc {
    font-size: var(--font-size-sm);
    color: var(--color-gray-500);
    margin-top: 2px;
}

.preview-section {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2);
}

.preview-section-label {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-gray-500);
}

.preview-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.saved-view-preview-actions {
    display: flex;
    align-items: center;
    gap: var(--spacing-2);
    padding-top: var(--spacing-3);
    border-top: 1px solid var(--border-color);
    margin-top: auto;
}

@media (max-width: 768px) {
    .saved-views-layout {
        flex-direction: column;
    }

    .saved-views-list {
        flex: none;
        max-height: 160px;
    }
}

/* ========================================
   SALES EXPLORER - FILTER PANEL
   ======================================== */
.sales-filter-row {
    display: flex;
    gap: var(--spacing-3);
    align-items: flex-start;
    flex-wrap: wrap;
    margin-bottom: var(--spacing-2);
}

.sales-filter-row:last-child {
    margin-bottom: 0;
}

.sales-filter-group {
    flex: 1;
    min-width: 200px;
}

.sales-filter-label {
    display: block;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-gray-600);
    margin-bottom: 4px;
}

/* Sales Explorer filter columns: Product Groups / Customers wider, Period A narrower */
.sales-filter-grid {
    display: grid;
    grid-template-columns: minmax(0, 38fr) minmax(0, 38fr) minmax(0, 24fr);
    gap: var(--spacing-3);
    align-items: start;
}

@media (max-width: 991.98px) {
    .sales-filter-grid {
        grid-template-columns: 1fr;
    }
}

/* Multi-select dropdown with checkboxes */
.multi-select-dropdown {
    position: relative;
}

.multi-select-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 12px;
    min-height: 38px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    border-radius: var(--input-radius);
    cursor: pointer;
    font-size: var(--font-size-sm);
    color: var(--color-gray-700);
    transition: border-color 0.2s ease;
}

.multi-select-trigger:hover {
    border-color: var(--color-brand);
}

.multi-select-panel {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 1050;
    max-height: 240px;
    overflow-y: auto;
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    margin-top: 4px;
    box-shadow: var(--shadow-lg);
    padding: var(--spacing-2);
}

.multi-select-panel .form-check-modern {
    padding: 4px 8px;
    border-radius: var(--radius-sm);
}

.multi-select-panel .form-check-modern:hover {
    background: rgba(99, 102, 241, 0.08);
}

/* ========================================
   DASHBOARD CHART SUMMARIES
   ======================================== */
.dashboard-chart-summary {
    display: flex;
    align-items: center;
    gap: var(--spacing-4);
    padding-top: var(--spacing-3);
    margin-top: var(--spacing-3);
    border-top: 1px solid var(--border-color);
    font-size: var(--font-size-sm);
    flex-wrap: wrap;
}

.dashboard-summary-label {
    color: var(--color-gray-500);
    margin-right: var(--spacing-1);
}

.dashboard-summary-value {
    font-weight: var(--font-weight-semibold);
    color: var(--color-gray-700);
}

.dashboard-summary-divider {
    color: var(--color-gray-300);
}

.dashboard-summary-note {
    font-style: italic;
    color: var(--color-gray-400);
    font-size: var(--font-size-xs);
    margin-left: auto;
}

/* ── Dashboard: gridstack overrides ── */

.grid-stack-item-content {
    inset: 6px;
    overflow: hidden;
}

.widget-drag-handle {
    cursor: grab;
    color: var(--color-gray-400);
    padding: 2px;
    border-radius: var(--radius-sm);
    transition: color 0.15s ease, background-color 0.15s ease;
    display: flex;
    align-items: center;
}

.widget-drag-handle:hover {
    color: var(--color-gray-600);
    background-color: var(--color-gray-100);
}

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

.grid-stack-item > .ui-resizable-handle {
    opacity: 0;
    transition: opacity 0.2s ease;
}

.grid-stack-item:hover > .ui-resizable-handle {
    opacity: 1;
}

.ui-resizable-se {
    width: 16px !important;
    height: 16px !important;
    bottom: 2px !important;
    right: 2px !important;
    background: none !important;
    border-right: 2px solid var(--color-gray-300);
    border-bottom: 2px solid var(--color-gray-300);
    border-radius: 0 0 var(--radius-sm) 0;
    cursor: se-resize;
}

.grid-stack-placeholder > .placeholder-content {
    border: 2px dashed var(--color-brand, #1d3d91) !important;
    background-color: rgba(29, 61, 145, 0.05) !important;
    border-radius: var(--radius-md);
}

.grid-stack-item-content .glass-card {
    height: 100%;
}

.grid-stack-item-content .glass-card-body {
    height: 100%;
    overflow: hidden;
}

@media (max-width: 768px) {
    .widget-drag-handle {
        display: none;
    }
}

.dashboard-widget-card {
    min-height: 380px;
}

.dashboard-widget-card .dashboard-chart-summary {
    font-size: var(--font-size-xs);
    gap: var(--spacing-2);
}

/* Granularity letter buttons (chart header + chart-config bar).
   Inherit base look from .btn-icon / .btn-icon-sm so they match the
   surrounding icon buttons exactly. Only override what's needed for
   the letter glyph and the active state. */
.granularity-btn {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    line-height: 1;
}

.granularity-btn-active {
    background: var(--color-brand) !important;
    color: #fff !important;
    border-color: var(--color-brand) !important;
}

.granularity-btn-active:hover:not(:disabled) {
    background: var(--color-brand-dark) !important;
    border-color: var(--color-brand-dark) !important;
}

/* ── Chart Config Bar ── */

.chart-config-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-3);
    padding-bottom: var(--spacing-3);
    border-bottom: 1px solid var(--border-color);
}

.chart-config-check {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: var(--font-size-sm);
    color: var(--color-gray-600);
    cursor: pointer;
    white-space: nowrap;
}

.chart-config-check input[type="checkbox"] {
    accent-color: var(--color-brand);
}

/* ========================================
   STOCK DETAIL PANEL
   ======================================== */
.stock-detail-panel {
    position: fixed;
    right: 0;
    top: 0;
    width: 550px;
    height: 100vh;
    z-index: 350;
    display: flex;
    flex-direction: column;
    background: var(--color-white);
    border-left: 1px solid var(--border-color);
    box-shadow: var(--shadow-xl);
    transform: translateX(100%);
    transition: transform var(--transition-base);
}

.stock-detail-panel.open {
    transform: translateX(0);
}

.stock-detail-panel-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--spacing-3);
    padding: var(--spacing-4) var(--spacing-5);
    border-bottom: 1px solid var(--border-color);
    flex-shrink: 0;
}

.stock-detail-panel-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-gray-700);
    line-height: 1.3;
}

.stock-detail-panel-subtitle {
    font-size: var(--font-size-sm);
    color: var(--color-gray-500);
    margin-top: 2px;
}

.stock-detail-panel-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--color-gray-500);
    cursor: pointer;
    flex-shrink: 0;
    transition: all 0.15s ease;
}

.stock-detail-panel-close:hover {
    background: var(--color-gray-100);
    color: var(--color-gray-700);
    border-color: var(--color-gray-300);
}

.stock-detail-panel-body {
    flex: 1;
    overflow-y: auto;
    padding: var(--spacing-4) var(--spacing-5);
}

/* Metric Cards Row */
.stock-detail-metrics {
    display: flex;
    gap: var(--spacing-3);
    margin-bottom: var(--spacing-4);
}

.stock-detail-metric-card {
    flex: 1;
    text-align: center;
    padding: var(--spacing-3);
    background: var(--color-gray-50);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
}

.stock-detail-metric-value {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-gray-700);
    line-height: 1.2;
}

.stock-detail-metric-label {
    font-size: var(--font-size-xs);
    color: var(--color-gray-500);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-top: 2px;
}

/* Sections */
.stock-detail-section {
    padding: var(--spacing-4) 0;
    border-top: 1px solid var(--border-color);
}

.stock-detail-section-label {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-gray-500);
    margin-bottom: var(--spacing-3);
}

/* Key-Value Rows */
.stock-detail-kv {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--spacing-1) 0;
    font-size: var(--font-size-sm);
}

.stock-detail-kv-key {
    color: var(--color-gray-500);
}

.stock-detail-kv-value {
    color: var(--color-gray-700);
    font-weight: var(--font-weight-medium);
    text-align: right;
}

/* Batch Toggle */
.stock-detail-batch-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-2);
    background: none;
    border: none;
    color: var(--color-brand);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
    padding: 0;
    transition: color 0.15s ease;
}

.stock-detail-batch-toggle:hover {
    color: var(--color-brand-dark);
}

/* Batch Table Wrapper */
.stock-detail-batch-table-wrapper {
    overflow-x: auto;
    margin-top: var(--spacing-3);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
}

.stock-detail-batch-table {
    font-size: var(--font-size-xs);
    white-space: nowrap;
    margin: 0;
}

.stock-detail-batch-table thead th {
    font-size: 0.65rem;
    padding: var(--spacing-2) var(--spacing-2);
}

.stock-detail-batch-table tbody td {
    padding: var(--spacing-2) var(--spacing-2);
    font-size: var(--font-size-xs);
}

/* Legend */
.stock-detail-legend {
    display: flex;
    gap: var(--spacing-2);
    margin-top: var(--spacing-3);
    justify-content: flex-end;
}

/* Shimmer Loading Placeholder */
.stock-detail-shimmer {
    height: 16px;
    background: linear-gradient(90deg, var(--color-gray-100) 25%, var(--color-gray-200) 50%, var(--color-gray-100) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.5s ease-in-out infinite;
    border-radius: var(--radius-sm);
    margin-bottom: var(--spacing-2);
}

@keyframes shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* Selected & Clickable Rows */
.stock-viewer-table tr.selected-row,
.table-modern-detail tr.selected-row {
    border-left: 3px solid var(--color-brand);
}

.stock-viewer-table tr.selected-row td:first-child,
.table-modern-detail tr.selected-row td:first-child {
    padding-left: calc(var(--spacing-3) - 3px);
}

.stock-viewer-table tr.clickable-row,
.table-modern-detail tr.clickable-row {
    cursor: pointer;
    transition: background 0.15s ease;
}

.stock-viewer-table tr.clickable-row:hover,
.table-modern-detail tr.clickable-row:hover {
    background: rgba(29, 61, 145, 0.04);
}

/* Toast Notification */
.stock-toast {
    position: fixed;
    bottom: var(--spacing-6);
    right: var(--spacing-6);
    z-index: 400;
    min-width: 280px;
    max-width: 420px;
    animation: toast-in 0.3s ease;
}

@keyframes toast-in {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
}

/* Progress Bars */
.panel-progress-track {
    height: 8px;
    background: var(--color-gray-100);
    border-radius: var(--radius-full);
    overflow: hidden;
}

.panel-progress-track.panel-progress-sm {
    height: 4px;
}

.panel-progress-fill {
    height: 100%;
    border-radius: var(--radius-full);
    transition: width 0.3s ease;
}

.panel-progress-brand {
    background: var(--color-brand);
}

.panel-progress-ok {
    background: var(--color-success);
}

.panel-progress-warning {
    background: var(--color-warning);
}

.panel-progress-danger {
    background: var(--color-danger);
}

/* Flag Badges (HELD / QC) */
.panel-flag-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    border-radius: var(--radius-sm);
    letter-spacing: 0.03em;
    vertical-align: middle;
    margin-left: var(--spacing-2);
}

.panel-flag-held {
    background: rgba(239, 68, 68, 0.12);
    color: var(--color-danger);
}

.panel-flag-qc {
    background: rgba(245, 158, 11, 0.12);
    color: var(--color-warning);
}

/* Alert Banner */
.panel-alert-banner {
    display: flex;
    gap: var(--spacing-2);
    flex-wrap: wrap;
    padding: var(--spacing-3);
    background: rgba(239, 68, 68, 0.06);
    border: 1px solid rgba(239, 68, 68, 0.15);
    border-radius: var(--radius-md);
    margin-bottom: var(--spacing-4);
}

/* Expiry Risk Rows */
.panel-expiry-row {
    display: flex;
    align-items: center;
    gap: var(--spacing-3);
    padding: var(--spacing-2) 0;
}

/* Location Distribution Rows */
.panel-location-row {
    padding: var(--spacing-2) 0;
}

/* Responsive */
@media (max-width: 992px) {
    .stock-detail-panel {
        width: 100vw;
    }
}

/* Reduced Motion */
@media (prefers-reduced-motion: reduce) {
    .stock-detail-panel {
        transition: none;
    }

    .stock-detail-shimmer {
        animation: none;
    }

    .stock-toast {
        animation: none;
    }
}

/* ========================================
   LOGIN VERSION FOOTER
   ======================================== */
.login-version {
    margin-top: var(--spacing-4);
    font-size: var(--font-size-xs);
    color: var(--color-gray-400);
    text-align: center;
}

/* FEAT-039 data freshness badge — colors via design-tokens.css (rgba overlays/shadows kept) */
.freshness-wrap { position: relative; }
.freshness-chip { display: inline-flex; align-items: center; gap: 6px; background: rgba(255,255,255,.1); color: var(--color-white); border: 0; border-radius: 999px; padding: 3px 10px; font-size: .72rem; cursor: pointer; }
.freshness-chip-text { white-space: nowrap; }
.freshness-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--color-gray-400); flex: 0 0 auto; }
.freshness-fresh .freshness-dot, .freshness-dot.freshness-fresh { background: var(--color-success); }
.freshness-stale .freshness-dot, .freshness-dot.freshness-stale { background: var(--color-warning); }
.freshness-overdue .freshness-dot, .freshness-dot.freshness-overdue { background: var(--color-danger); }
.freshness-unknown .freshness-dot, .freshness-dot.freshness-unknown { background: var(--color-gray-400); }

/* R-014087: "no expectation" — hollow instead of filled. A filled gray dot looks like a
   state that was measured and came out neutral; here nothing was measured at all. The
   hollow ring says exactly that, without introducing another color word. */
.freshness-no-expectation .freshness-dot, .freshness-dot.freshness-no-expectation {
    background: transparent;
    box-shadow: inset 0 0 0 1.5px var(--color-gray-400);
}

.freshness-row-extra {
    color: var(--color-gray-500);
    font-size: var(--font-size-xs);
    white-space: nowrap;
}
/* R-014195: anchored LEFT, not right.

   Measured on the running screen: with "right: 0" the panel sat at left = -94px, i.e. 94
   pixels outside the window - right where the feed labels are. The reason is a
   calculation that used to work out: the panel is at least 240px wide and grew from the
   RIGHT edge of the badge to the left. The badge sits in the sidebar, which measures
   225px - narrower than the panel is wide.

   No ancestor clipped it; it was the window edge itself. Anchored to the left, the panel
   grows from the badge to the right into the content area, where there is room.

   max-width as a guard: should the panel ever grow beyond the window, it stays readable
   instead of being clipped on the other side - mirroring the same bug would be the most
   obvious way to break this again. */
.freshness-popover {
    position: absolute;
    left: 0;
    right: auto;
    top: 110%;
    z-index: 1050;
    background: var(--color-white);
    color: var(--color-gray-900);
    border: 1px solid var(--color-gray-200);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .15);
    padding: 10px 12px;
    min-width: 240px;
    max-width: calc(100vw - 2rem);
}
.freshness-popover-title { font-weight: 600; font-size: .8rem; margin-bottom: 6px; }
.freshness-row { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: .8rem; }
.freshness-row-label { flex: 1; }
.freshness-row-time { color: var(--color-gray-500); white-space: nowrap; }
.freshness-popover-note { margin-top: 6px; font-size: .68rem; color: var(--color-gray-400); }

/* FEAT-032 attention inbox */
.attention-empty { padding: 24px; text-align: center; color: var(--color-gray-500); }
.attention-group { margin-bottom: 16px; }
.attention-group-title { font-weight: 600; font-size: .85rem; color: var(--color-gray-600); margin: 8px 0; text-transform: uppercase; letter-spacing: .04em; }
.attention-item { display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; border: 1px solid var(--color-gray-200); border-radius: 8px; margin-bottom: 6px; text-decoration: none; color: var(--color-gray-900); background: var(--color-white); }
.attention-item:hover { border-color: var(--color-gray-300); }
.attention-sev-dot { width: 10px; height: 10px; border-radius: 50%; margin-top: 4px; flex: 0 0 auto; background: var(--color-gray-400); }
.attention-critical .attention-sev-dot { background: var(--color-danger); }
.attention-warning .attention-sev-dot { background: var(--color-warning); }
.attention-info .attention-sev-dot { background: var(--color-gray-400); }
.attention-item-body { display: flex; flex-direction: column; }
.attention-item-title { font-weight: 600; font-size: .9rem; }
.attention-item-detail { font-size: .8rem; color: var(--color-gray-500); }

.attention-bell { position: relative; background: transparent; border: 0; color: var(--color-white); cursor: pointer; font-size: 1rem; padding: 2px 4px; }
.attention-bell-count { position: absolute; top: -2px; right: -4px; background: var(--color-danger); color: var(--color-white); font-size: .6rem; line-height: 1; padding: 2px 4px; border-radius: 999px; }

/* FEAT-041 returns analysis */
.returns-filter { display: flex; gap: 12px; align-items: flex-end; margin-bottom: 16px; flex-wrap: wrap; }
.returns-empty { padding: 24px; text-align: center; color: var(--color-gray-500); }
.returns-totals { display: flex; gap: 24px; margin-bottom: 16px; color: var(--color-gray-700); flex-wrap: wrap; }
.returns-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 16px; }
.returns-card { border: 1px solid var(--color-gray-200); border-radius: 8px; padding: 12px 14px; background: var(--color-white); }
.returns-card-title { font-size: .9rem; font-weight: 600; color: var(--color-gray-700); margin-bottom: 8px; }
.returns-table { width: 100%; border-collapse: collapse; font-size: .8rem; }
/* R-013977: padding removed - overridden by .table-modern tbody td and restored by the
   (0,2,2) density rule. vertical-align is not set by .table-modern and stays. */
.returns-table td { vertical-align: middle; }
.returns-label { max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--color-gray-900); }
.returns-bar-cell { width: 40%; }
.returns-bar { display: inline-block; height: 10px; border-radius: 4px; background: var(--color-danger); min-width: 2px; }
.returns-num { text-align: right; color: var(--color-gray-600); white-space: nowrap; }
.returns-row-clickable { cursor: pointer; }
.returns-row-clickable:hover td { background: var(--color-gray-100); }
.returns-row-active td { background: var(--table-stripe-bg, rgba(0, 0, 0, .05)); font-weight: var(--font-weight-semibold); }
.returns-drill-hint { font-size: .72rem; color: var(--color-gray-600); margin: 8px 0 0; }
.returns-drill-clear { border: none; background: none; color: var(--color-brand); cursor: pointer; text-decoration: underline; font-size: .72rem; padding: 0; }

/* FEAT-042 quality batch/quarantine board */
.qstock-summary { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 16px; }
/* Issue 15: badges aligned to the Stock-Viewer KPI cards — rounded card, shadow, hover-lift,
   full status-coloured border, prominent count. */
.qstock-badge { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; border: 1px solid var(--border-color); border-radius: var(--radius-xl); padding: var(--spacing-4); background: var(--glass-bg-strong); box-shadow: var(--shadow-md); cursor: pointer; min-width: 120px; transition: transform var(--transition-base), box-shadow var(--transition-base); }
.qstock-badge:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.qstock-badge-active { box-shadow: 0 0 0 2px var(--color-brand); }
.qstock-badge-label { font-size: .72rem; color: var(--color-gray-600); text-transform: uppercase; letter-spacing: .03em; }
.qstock-badge-count { font-size: 1.5rem; font-weight: 700; color: var(--color-gray-900); line-height: 1.1; }
.qstock-badge-qty { font-size: .7rem; color: var(--color-gray-500); }
.qstock-filter { display: flex; gap: 12px; align-items: flex-end; margin-bottom: 12px; flex-wrap: wrap; }
.qstock-empty { padding: 24px; text-align: center; color: var(--color-gray-500); }
/* R-013977: .qstock-table (3 rules) and .qstock-num removed - the board renders a
   .table-modern since the design-system consolidation, so nothing carried these classes.
   Verified against .razor/.cs/.cshtml/.html/.js: zero occurrences each.

   The .qstock-status-* rules below stay. They look just as unused, but QualityStock.razor
   composes them at runtime as qstock-status-@s.Status.ToString().ToLower() over BatchStatus
   - seven live class names that no text search can find. */
.qstock-tag { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: .72rem; color: var(--color-white); }
/* status accents (full border on badge, background on tag) */
.qstock-badge.qstock-status-blocked { border-color: var(--color-danger); }
.qstock-status-blocked.qstock-tag { background: var(--color-danger); }
.qstock-badge.qstock-status-expired { border-color: var(--color-danger); }
.qstock-status-expired.qstock-tag { background: var(--color-danger); }
.qstock-badge.qstock-status-qcinspection { border-color: var(--color-warning); }
.qstock-status-qcinspection.qstock-tag { background: var(--color-warning); }
.qstock-badge.qstock-status-restricted { border-color: var(--color-warning); }
.qstock-status-restricted.qstock-tag { background: var(--color-warning); }
.qstock-badge.qstock-status-held { border-color: var(--color-warning); }
.qstock-status-held.qstock-tag { background: var(--color-warning); }
.qstock-badge.qstock-status-expiring { border-color: var(--color-warning); }
.qstock-status-expiring.qstock-tag { background: var(--color-warning); }
.qstock-badge.qstock-status-available { border-color: var(--color-success); }
.qstock-status-available.qstock-tag { background: var(--color-success); }

/* FEAT-043 CFO board
   R-013977: this page's own KPI, period and table rules have been dropped. The CFO board
   now uses the shared patterns - metric-card for the KPIs, MonthPillPicker for the period
   selector, table-modern for the table. The rules only remained here; verified on
   2026-08-16 with an individual check per class name against markup, substring, C#
   concatenation and attribute interpolation.
   Removed: cfo-year, cfo-kpis, cfo-kpi, cfo-kpi-label, cfo-kpi-val, cfo-period,
   cfo-period-year, cfo-yearnav, cfo-yearlabel, cfo-months, cfo-month, cfo-table-wrap,
   cfo-table, cfo-sortable, cfo-num. */
.cfo-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.cfo-empty { padding: 24px; text-align: center; color: var(--color-gray-500); }
.cfo-note { font-size: .72rem; color: var(--color-gray-500); margin-bottom: 12px; }

/* JSON setting editors (Issue 3.1) */
.jsonedit { width: 100%; }
.jsonedit-toolbar { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.jsonedit-toggle { padding: 2px 10px; font-size: .72rem; border: 1px solid var(--color-gray-300); border-radius: 999px; background: var(--color-white); color: var(--color-gray-600); cursor: pointer; }
.jsonedit-toggle.active { background: var(--color-brand); border-color: var(--color-brand); color: var(--color-white); }
.jsonedit-toggle:disabled { opacity: .4; cursor: default; }
.jsonedit-err { font-size: .72rem; color: var(--color-danger); }
.jsonedit-raw { width: 100%; font-family: var(--font-mono, monospace); font-size: .75rem; }
.jsonedit-table { border-collapse: collapse; font-size: .78rem; margin-bottom: 8px; }
/* R-013977: .jsonedit-table th and td removed - every declaration lost to .table-modern
   (both were (0,1,1) against (0,1,2)), and the tight padding is carried by the (0,2,2)
   density rule. The base .jsonedit-table rule above stays: border-collapse, font-size and
   margin-bottom are its own and win on source order. */
.jsonedit-center { text-align: center; }
.jsonedit-num { text-align: right; }
.jsonedit-int { width: 70px; }
.jsonedit-sel { min-width: 150px; }
.jsonedit-route { min-width: 180px; }
.jsonedit-del { border: none; background: none; color: var(--color-gray-400); cursor: pointer; font-size: .9rem; }
.jsonedit-del:hover { color: var(--color-danger); }
.jsonedit-order { white-space: nowrap; }
.jsonedit-move { border: 1px solid var(--color-gray-300); background: var(--color-white); color: var(--color-gray-600); cursor: pointer; border-radius: 4px; line-height: 1; padding: 1px 4px; font-size: .7rem; }
.jsonedit-move:disabled { opacity: .35; cursor: default; }
.jsonedit-hint { font-size: .7rem; color: var(--color-gray-500); margin: 4px 0 0; }

/* Derivation popover (Issue 6) — native top-layer popover, no overflow clipping. Anchored to the
   number where the browser supports CSS anchor positioning, otherwise centered (still usable). */
.why { display: inline; }
.why-trigger { border: none; background: none; padding: 0; font: inherit; color: inherit; cursor: pointer; text-decoration: underline dotted; text-underline-offset: 2px; }
.why-trigger:hover { text-decoration-style: solid; }
.why-chip { border: none; cursor: pointer; font: inherit; }
.why-panel { border: 1px solid var(--color-gray-200); border-radius: 8px; background: var(--color-white); box-shadow: 0 8px 28px rgba(0, 0, 0, .16); padding: 12px 14px; min-width: 17rem; max-width: min(28rem, 92vw); font-size: .8rem; color: var(--color-gray-800); }
.why-title { margin: 0 0 8px; font-size: .72rem; font-weight: 600; color: var(--color-gray-500); }
.why-rows { list-style: none; margin: 0; padding: 0; }
.why-row { display: flex; justify-content: space-between; gap: 16px; padding: 4px 0; border-bottom: 1px solid var(--color-gray-100); }
.why-label { color: var(--color-gray-600); }
.why-val { font-weight: 600; white-space: nowrap; }
.why-total { display: flex; justify-content: space-between; gap: 16px; padding-top: 8px; font-weight: 600; }
/* R-013977: six more cfo table rules used to sit here - in the middle of the why block,
   far away from the other cfo rules. This scattering is itself a finding: it is the
   reason nobody noticed, when switching to table-modern, that something was still left
   here. Removed. cfo-pos and cfo-neg stay - they are returned at runtime by GapClass() in
   CfoBoard.razor:237. */
.cfo-pos { color: var(--color-success); font-weight: 600; }
.cfo-neg { color: var(--color-danger); font-weight: 600; }

/* FEAT-040 performance page */
.perf-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.perf-empty { padding: 24px; text-align: center; color: var(--color-gray-500); }
/* R-013977: .perf-year, .perf-kpis, .perf-kpi, .perf-kpi-label, .perf-kpi-val, .perf-table
   (4 rules) and .perf-num removed. The page has used the shared .metric-card and
   .table-modern since the design-system consolidation; these rules had no markup left to
   apply to. Verified against .razor/.cs/.cshtml/.html/.js: zero occurrences each.

   .perf-ok, .perf-amber and .perf-red look equally unused and are NOT removed: TagCls() in
   Performance.razor builds those names at runtime from PerfFlag, so no text search finds
   them. Same reason .cfo-pos and .cfo-neg survived the pass above. The guard for this is
   CssClassesTests.Every_runtime_built_CSS_class_is_defined, which derives the
   expected names from the enum instead of from the markup. */
.perf-pos { color: var(--color-success); font-weight: 600; }
.perf-neg { color: var(--color-danger); font-weight: 600; }
.perf-tag { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: .7rem; color: var(--color-white); margin-right: 4px; }
.perf-ok { background: var(--color-success); }
.perf-amber { background: var(--color-warning); }
.perf-red { background: var(--color-danger); }
.perf-none { background: var(--color-gray-400); }  /* no data — neutral, not green */
.perf-partial { color: var(--color-gray-500); }  /* share over partial IQVIA coverage — dimmed */
.perf-partial-note { margin-left: 3px; color: var(--color-warning); cursor: help; }

/* FEAT-045 batch traceability */
.batchtrace-filter { display: flex; gap: 12px; align-items: end; flex-wrap: wrap; margin: 12px 0; }
.batchtrace-filter label { display: flex; flex-direction: column; font-size: .72rem; color: var(--color-gray-600); gap: 2px; }
.batchtrace-filter .form-control { width: auto; }
.batchtrace-split { display: grid; grid-template-columns: minmax(340px, 1fr) minmax(360px, 1.2fr); gap: 16px; align-items: start; }
@media (max-width: 1100px) { .batchtrace-split { grid-template-columns: 1fr; } }
.batchtrace-list, .batchtrace-detail { border: 1px solid var(--color-gray-200); border-radius: 8px; padding: 10px 12px; background: var(--color-white); overflow-x: auto; }
.batchtrace-empty, .batchtrace-none { padding: 16px; text-align: center; color: var(--color-gray-500); }
.batchtrace-none { padding: 6px 0; text-align: left; font-size: .8rem; }
.batchtrace-error { padding: 16px; text-align: center; color: var(--color-danger); background: var(--color-danger-bg); border-radius: 6px; }
.batchtrace-table { width: 100%; border-collapse: collapse; font-size: .8rem; }
/* R-013977: .batchtrace-table th removed entirely and .batchtrace-table td reduced to the
   one declaration that is still its own. Both rules are (0,1,1) and lose every shared
   property to .table-modern > thead th / .table-modern tbody td, which are (0,1,2). The
   density is carried by the (0,2,2) rule near .table-modern instead.
   vertical-align stays: .table-modern sets none, so this declaration still applies. */
.batchtrace-table td { vertical-align: top; }
.batchtrace-num { text-align: right; white-space: nowrap; }
.batchtrace-table th.batchtrace-num { text-align: right; }
/* Issue 16: the rightmost column of every detail table is right-aligned (header + cells), like Netto CHF. */
.batchtrace-table th:last-child, .batchtrace-table td:last-child { text-align: right; }
.batchtrace-pos { color: var(--color-success); }
.batchtrace-neg { color: var(--color-danger); }
.batchtrace-sub { color: var(--color-gray-500); font-size: .72rem; display: block; }
.batchtrace-list tbody tr { cursor: pointer; }
.batchtrace-list tbody tr:hover { background: var(--color-gray-100); }
.batchtrace-row-active { background: var(--color-success-bg); }
.batchtrace-link { border: none; background: none; color: var(--color-info); font-size: .78rem; cursor: pointer; padding: 0; }
.batchtrace-chip { display: inline-block; padding: 0 6px; border-radius: 999px; font-size: .65rem; color: var(--color-white); margin-left: 4px; background: var(--color-gray-400); }
.batchtrace-red { color: var(--color-danger); }
.batchtrace-chip.batchtrace-red { background: var(--color-danger); color: var(--color-white); }
.batchtrace-chip.batchtrace-amber { background: var(--color-warning); color: var(--color-white); }
.batchtrace-h2 { font-size: 1.05rem; margin: 4px 0 8px; }
.batchtrace-h3 { font-size: .82rem; text-transform: uppercase; letter-spacing: .03em; color: var(--color-gray-600); margin: 14px 0 4px; }
.batchtrace-kpis { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.batchtrace-kpi { display: flex; flex-direction: column; border: 1px solid var(--color-gray-200); border-radius: 6px; padding: 6px 10px; min-width: 80px; }
.batchtrace-kpi span { font-size: .66rem; text-transform: uppercase; color: var(--color-gray-600); }
.batchtrace-kpi b { font-size: 1.05rem; color: var(--color-gray-900); }
.batchtrace-note { font-size: .8rem; color: var(--color-gray-700); }

/* ========================================
   SIDEBAR — HEADER AND USER CARD
   R-014175 / R-014176
   ======================================== */

/* Pulled here from the embedded <style> block of NavMenu.razor: styles belong in the
   central file, an embedded block escapes layer ordering and lint. Carried over
   unchanged, only moved. */
.brand-logo {
    width: 36px;
    height: 36px;
    background: rgba(255, 255, 255, 0.15);
    border-radius: var(--radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    flex-shrink: 0;
}

.brand-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* R-014175: spacing of the home button top and left 1:1. Both come from THE SAME token -
   they are equal because they are the same value, not because two numbers happen to
   match. Previously the top spacing came from centering in a minimum height (14px) and the
   left one from ps-3 (16px). */
.nav-header {
    display: flex;
    flex-direction: column;

    /* R-014175: gap and padding are THE SAME token. That makes the spacing above the
       freshness badge (the gap) equal to the spacing below it (the padding), and the home
       button's top spacing equal to its left spacing. Four measurements, one value - equal
       because it's the same one, not because four numbers happen to match. This requires
       padding: 0 on .top-row, otherwise Bootstrap adds 8px vertically on top (see
       NavMenu.razor.css). */
    gap: var(--spacing-4);
    padding: var(--spacing-4);
    align-items: flex-start;
}

/* The user card at the end of the navigation: initials, name, role, logout. */
.nav-user {
    display: flex;
    align-items: center;
    gap: var(--spacing-3);
    margin: var(--spacing-4) var(--spacing-3) var(--spacing-3);
    padding: var(--spacing-2) var(--spacing-3);
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.06);
}

.nav-user-initials {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.15);
    color: white;
    font-weight: var(--font-weight-semibold);
    font-size: var(--font-size-sm);
    letter-spacing: 0.5px;
}

.nav-user-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1;
}

/* A long name must not break the card layout - it is truncated, not wrapped. */
.nav-user-name {
    color: white;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nav-user-role {
    color: rgba(255, 255, 255, 0.55);
    font-size: var(--font-size-xs);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nav-user-logout {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    padding: 0;
    border: none;
    border-radius: var(--radius-md);
    background: transparent;
    color: rgba(255, 255, 255, 0.6);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.nav-user-logout:hover {
    background: var(--color-danger-bg, rgba(239, 68, 68, 0.15));
    color: rgb(239, 68, 68);
}

.nav-user-logout:focus-visible {
    outline: none;
    box-shadow: var(--shadow-focus);
}

/* ========================================
   QUIET STATE — R-014179
   ======================================== */

/* The normal case gets NO badge, just a small dot and plain text. Reason: in the
   delivery table, "cleanly processed" is the state of four rows out of five. If it
   carries a filled badge, the exception next to it is not visually highlighted - it
   drowns in the color noise. A monitoring view has to work the other way round: quiet
   while there is nothing to report, and visible the moment there is. */
.status-quiet {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-2);
    font-size: var(--font-size-sm);
    color: var(--color-gray-600);
    white-space: nowrap;
}

.status-quiet::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: var(--radius-full);
    background: var(--color-success);
    flex-shrink: 0;
}

/* For states that are neither good nor bad - "not checked", "no expectation". A green
   dot there would be a claim that nobody has verified. */
.status-quiet-neutral::before {
    background: var(--color-gray-400);
}


/* ========================================
   STICKY ELEMENTS — R-014181
   ======================================== */

/* These two rules replace embedded style attributes in Sales.razor. Hardcoded stacking
   values (10 and 200) used to sit there - the project rule requires styles in the central
   file and values from tokens, so the order is decided ONCE and not re-guessed at every
   repair. Measured on 22.08.2026: nine hardcoded z-index values in the application
   against six token uses. */
/* R-014189: OPAQUE, not tinted. The rule .table-modern thead sets --table-header-bg with
   6% opacity - correct for a header that scrolls along, wrong for a sticky one: there the
   data rows underneath keep scrolling past and show through at 94%.
   No backdrop-filter as a fix - it opens its own stacking context, and that is exactly
   what R-014181 suffered from. */
.table-head-sticky {
    position: sticky;
    top: 0;
    z-index: var(--z-table-head);
}

/* The background needs the longer selector, NOT !important.
   Measured on the shipped page: ".table-modern thead" has specificity (0,1,1) and beats a
   plain ".table-head-sticky" (0,1,0) - the opaque color therefore did not land at all
   on the first attempt, even though build and deploy went through without errors. With
   the parent in front of it, it stands at (0,2,1) and wins normally. */
.table-modern > thead.table-head-sticky {
    background: var(--table-header-bg-sticky);
}

/* The bottom action bar. WATCH OUT for backdrop-filter: it opens its own stacking
   context, independent of z-index. Everything inside it - even a popover with a high
   z-index of its own - stays at the level of THIS bar. Anyone who opens something from
   here needs to know that. */
.action-bar-sticky {
    position: sticky;
    bottom: 0;
    z-index: var(--z-sticky);
    background: rgba(255, 255, 255, 0.95);
    backdrop-filter: blur(6px);
}

/* ========================================
   SPACING UTILITY CLASS — R-014183
   ======================================== */

/* Bootstrap sets .gap-3 to 1rem. For this application that is too wide: the class is used
   28 times across 14 files, mostly for toolbars and button groups, where 1rem pulls the
   elements too far apart.

   app.css is loaded AFTER bootstrap.min.css (see App.razor), and Bootstrap's utility
   classes carry !important - hence the same here, otherwise the rule would not take
   effect. This is the only place where a Bootstrap utility class is overridden; the value
   comes from the token, not as a raw number. */
.gap-3 {
    gap: var(--spacing-2) !important;
}

/* ========================================
   TAB BAR — R-014173 / R-014174
   ======================================== */

/* Horizontal navigation above consolidated pages. Deliberately plain: a line under the
   active tab instead of filled pills - the same restraint as with the badges (R-014179).
   A tab is not an action, but a place. */
.tab-bar {
    display: flex;
    gap: var(--spacing-4);
    align-items: stretch;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: var(--spacing-4);
    overflow-x: auto;
}

.tab-bar-item {
    padding: var(--spacing-2) var(--spacing-1);
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-medium);
    color: var(--color-gray-500);
    text-decoration: none;
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;   /* the item's own line covers the bar's line */
    transition: color var(--transition-fast), border-color var(--transition-fast);
}

.tab-bar-item:hover {
    color: var(--color-brand);
    text-decoration: none;
}

.tab-bar-active {
    color: var(--color-brand);
    font-weight: var(--font-weight-semibold);
    border-bottom-color: var(--color-brand);
}

.tab-bar-item:focus-visible {
    outline: none;
    box-shadow: var(--shadow-focus);
    border-radius: var(--radius-sm);
}

/* ========================================
   ROW MENU — R-014180
   ======================================== */

/* A table row's actions behind three vertical dots.

   THE OBSTACLE: .table-modern-container carries overflow-x: auto. Per the CSS spec that
   also computes the VERTICAL direction as auto - an opening menu in the cell would be
   clipped at the bottom. Checked against the markup, not hoped for.

   THE FIX: while a menu is open, the container carries the class .menu-open and allows
   overflow. That costs the table's horizontal scrolling for this one moment - a fair price
   compared to fixed positioning with a coordinate calculation, which would need JavaScript
   and a second source of errors. */
.table-modern-container.menu-open {
    overflow: visible;
}

.row-menu {
    position: relative;
    display: inline-block;
}

.row-menu-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-gray-500);
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast);
}

.row-menu-button:hover,
.row-menu-button[aria-expanded="true"] {
    background: rgba(var(--color-brand-rgb), 0.10);
    color: var(--color-brand);
}

.row-menu-button:focus-visible {
    outline: none;
    box-shadow: var(--shadow-focus);
}

/* Covers the whole page, catches the click elsewhere and closes. Without it the menu would
   stay open until you hit it exactly. Transparent - it should hide nothing, only accept
   clicks. */
.row-menu-backdrop {
    position: fixed;
    inset: 0;
    z-index: var(--z-dropdown);
    background: transparent;
    border: none;
    padding: 0;
    cursor: default;
}

.row-menu-list {
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    z-index: calc(var(--z-dropdown) + 1);
    min-width: 190px;
    padding: var(--spacing-1);
    background: var(--color-white);
    border: 1px solid var(--color-gray-200);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    display: flex;
    flex-direction: column;
    text-align: left;
}

/* The last row of a long table opens UPWARD, otherwise the menu would sit outside the
   screen. */
.row-menu-list-above {
    top: auto;
    bottom: calc(100% + 4px);
}

.row-menu-item {
    display: block;
    width: 100%;
    padding: var(--spacing-2) var(--spacing-3);
    border: none;
    background: transparent;
    color: var(--color-gray-700);
    font-size: var(--font-size-sm);
    text-align: left;
    white-space: nowrap;
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.row-menu-item:hover {
    background: var(--color-gray-100);
    color: var(--color-brand);
}

.row-menu-item:focus-visible {
    outline: none;
    box-shadow: var(--shadow-focus);
}


/* ============================================================================
   Login page (LoginLayout)

   R-013977: moved here from the embedded <style> block in
   Components/Layout/LoginLayout.razor. An embedded block escapes the ordering in the
   central sheet and the lint gate; that exact invisibility is what caused R-014002.
   ============================================================================ */
.login-layout {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: var(--bg-body);
    padding: var(--spacing-6);
}

.login-container {
    width: 100%;
    max-width: 500px;
}


/* ============================================================================
   Month picker (MonthPillPicker)

   R-013977: moved here from the embedded <style> block in
   Components/Shared/MonthPillPicker.razor. An embedded block escapes the ordering in the
   central sheet and the lint gate; that exact invisibility is what caused R-014002.
   ============================================================================ */
/* One compact line: Year | Months | Presets, groups separated by thin dividers. */
.month-pill-picker {
    display: flex;
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--spacing-2, 0.5rem);
    outline: none;
}

.mpp-group {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex-wrap: wrap;
}

.mpp-divider {
    width: 1px;
    align-self: stretch;
    min-height: 1.6rem;
    background: var(--color-gray-200, #e5e7eb);
    margin: 0 0.25rem;
}

.mpp-year-label {
    font-weight: 600;
    font-size: 0.95rem;
    min-width: 3rem;
    text-align: center;
    color: var(--color-gray-800, #1f2937);
}

.mpp-chevron {
    background: transparent;
    border: 1px solid var(--color-gray-300, #d1d5db);
    border-radius: var(--radius-md, 6px);
    width: 1.7rem;
    height: 1.7rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--color-gray-700, #374151);
    transition: background-color 120ms ease;
}
.mpp-chevron:hover, .mpp-chevron:focus-visible { background: var(--color-gray-100, #f3f4f6); outline: none; }

.mpp-pill, .mpp-preset {
    background: transparent;
    border: 1px solid var(--color-gray-300, #d1d5db);
    border-radius: 999px;
    cursor: pointer;
    color: var(--color-gray-700, #374151);
    transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}

.mpp-pill {
    padding: 0.22rem 0.62rem;
    min-width: 2.6rem;
    text-align: center;
    font-size: 0.82rem;
    font-weight: 500;
}
.mpp-preset { padding: 0.22rem 0.7rem; font-size: 0.8rem; }

.mpp-pill:hover, .mpp-pill:focus-visible,
.mpp-preset:hover, .mpp-preset:focus-visible { background: var(--color-gray-100, #f3f4f6); outline: none; }

.mpp-pill.is-active, .mpp-preset.is-active {
    background: var(--color-brand, #1d3d91);
    color: var(--color-white, #fff);
    border-color: var(--color-brand-dark, #152c6b);
}

@media (prefers-reduced-motion: reduce) {
    .mpp-pill, .mpp-preset, .mpp-chevron { transition: none; }
}


/* ============================================================================
   About page (About)

   R-013977: moved here from the embedded <style> block in
   Components/Pages/About.razor. An embedded block escapes the ordering in the central
   sheet and the lint gate; that exact invisibility is what caused R-014002.
   ============================================================================ */
.about-page {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: calc(100vh - 60px);
}

.about-container {
    max-width: 800px;
    width: 100%;
    padding: var(--spacing-6) var(--spacing-4);
}

.about-header {
    text-align: center;
    margin-bottom: var(--spacing-8);
}

.app-icon {
    width: 80px;
    height: 80px;
    background: var(--gradient-brand);
    border-radius: var(--radius-xl);
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto var(--spacing-4);
    color: white;
    box-shadow: 0 10px 30px rgba(25, 46, 87, 0.3);
}

.about-header h1 {
    font-size: var(--font-size-2xl);
    font-weight: 700;
    color: var(--color-brand-dark);
    margin-bottom: var(--spacing-2);
}

.version {
    color: var(--color-gray-500);
    font-size: var(--font-size-sm);
    margin: 0;
}

.about-cards {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-4);
}

.company-card {
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: var(--glass-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-md);
    display: flex;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.company-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
}

.card-accent {
    width: 6px;
    flex-shrink: 0;
}

.effrx-card .card-accent {
    background: linear-gradient(180deg, var(--color-brand-dark) 0%, var(--color-brand) 100%);
}

.solvia-card .card-accent {
    background: linear-gradient(180deg, var(--color-brand) 0%, var(--color-brand-light) 100%);
}

.card-content {
    padding: var(--spacing-5) var(--spacing-6);
    flex: 1;
}

.card-content h3 {
    font-size: var(--font-size-lg);
    font-weight: 600;
    margin-bottom: var(--spacing-4);
}

.effrx-card h3 {
    color: var(--color-brand-dark);
}

.solvia-card h3 {
    color: var(--color-brand);
}

.developed-by {
    font-size: var(--font-size-xs);
    color: var(--color-gray-500);
    margin-bottom: var(--spacing-1);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.company-info {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-3);
}

.info-item {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-3);
    color: var(--color-gray-700);
}

.info-item svg {
    color: var(--color-gray-500);
    flex-shrink: 0;
    margin-top: 2px;
}

.info-item div {
    display: flex;
    flex-direction: column;
}

.info-item span {
    line-height: 1.4;
}

.info-item a {
    color: var(--color-brand);
    text-decoration: none;
    transition: color 0.2s ease;
}

.info-item a:hover {
    color: var(--color-brand-dark);
    text-decoration: underline;
}

.about-footer {
    text-align: center;
    margin-top: var(--spacing-8);
    padding-top: var(--spacing-4);
    border-top: 1px solid var(--border-color);
}

.about-footer p {
    color: var(--color-gray-400);
    font-size: var(--font-size-xs);
    margin: 0;
}

@media (min-width: 768px) {
    .about-cards {
        flex-direction: row;
    }

    .company-card {
        flex: 1;
        flex-direction: column;
    }

    .card-accent {
        width: 100%;
        height: 6px;
    }

    .effrx-card .card-accent {
        background: linear-gradient(90deg, var(--color-brand-dark) 0%, var(--color-brand) 100%);
    }

    .solvia-card .card-accent {
        background: linear-gradient(90deg, var(--color-brand) 0%, var(--color-brand-light) 100%);
    }
}


/* ============================================================================
   Monthly sales - grid (MonthlySales)

   R-013977: moved here from the embedded <style> block in
   Components/Pages/MonthlySales.razor. An embedded block escapes the ordering in the
   central sheet and the lint gate; that exact invisibility is what caused R-014002.
   ============================================================================ */
.ms-grid-scroll {
    max-height: calc(100vh - 320px);
    overflow: auto;
    border: 1px solid var(--color-gray-200, #e5e7eb);
    border-radius: var(--radius-md, 6px);
}

.ms-grid {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}

/* Table look comes from the shared .table-modern (dark header, stripes); ms-grid only adds the
   sortable-cursor + nowrap. Numeric header alignment restored above table-modern's left default. */
.ms-grid thead th {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.table-modern.ms-grid thead th:hover {
    background: rgba(255, 255, 255, 0.1);
}

.table-modern.ms-grid thead th.ms-col-num {
    text-align: right;
}

.ms-grid tbody td {
    white-space: nowrap;
}

.ms-col-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.ms-neg {
    color: var(--color-danger, #dc2626);
}

.ms-sort-ind {
    margin-left: 0.3rem;
    font-size: 0.75rem;
    color: inherit;
}

.ms-totals-row td {
    position: sticky;
    bottom: 0;
    z-index: 2;
    background: var(--color-gray-100, #f3f4f6);
    border-top: 2px solid var(--color-gray-300, #d1d5db);
    font-weight: 600;
    padding: 0.55rem 0.9rem;
}

/* Row expand (Phase 5) */
.ms-row {
    cursor: pointer;
}

.ms-row.is-expanded {
    background: var(--color-gray-50, #f9fafb);
}

.ms-expand-col {
    width: 2.25rem;
    text-align: center;
    padding: 0.2rem !important;
}

.ms-actions-col {
    width: 5.5rem;
    text-align: right;
    white-space: nowrap;
}

.ms-row.is-panel-focused {
    box-shadow: inset 3px 0 0 var(--color-brand, #1d3d91);
}

.ms-chevron-btn {
    background: transparent;
    border: none;
    padding: 0.25rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-gray-600, #4b5563);
    border-radius: 4px;
}

.ms-chevron-btn:hover,
.ms-chevron-btn:focus-visible {
    background: var(--color-gray-100, #f3f4f6);
    outline: none;
}

.ms-chevron-icon {
    transition: transform 180ms ease;
}

.ms-chevron-icon.is-open {
    transform: rotate(90deg);
}

.ms-detail-row > td {
    background: var(--color-gray-50, #f9fafb);
    border-bottom: 1px solid var(--color-gray-200, #e5e7eb);
    padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem) !important;
}

/* R-014002: the former rules .ms-detail-wrap and .ms-detail-table have been dropped.
   They were a second, incomplete version of what .detail-container-modern and
   .table-modern-detail in app.css already provide - and they were missing the text
   color, which is why the header stood white on light. Both class names were verified to
   occur only in this file.

   The only thing that stays its own is the height limit: a material row can have very
   many invoice lines, and the Stock Viewer does not have this problem. */
.ms-detail-scroll {
    max-height: 24rem;
    overflow: auto;
}

/* The detail table adopts the number alignment of the main grid on the same page.
   .table-modern-detail does not know it - text-end alone would be right-aligned, but
   without equal-width digits the columns jump around while paging. */
.table-modern-detail th.ms-col-num,
.table-modern-detail td.ms-col-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
    .ms-chevron-icon {
        transition: none;
    }
}

/* Monthly Sales page root must accept keyboard focus. */
.monthly-sales-page { outline: none; }

/* Cheat-sheet list layout */
.ms-cheat-list {
    display: grid;
    grid-template-columns: minmax(8rem, max-content) 1fr;
    gap: 0.4rem 1rem;
    margin: 0 0 0.75rem;
}

.ms-cheat-list dt {
    font-weight: 500;
    color: var(--color-gray-800, #1f2937);
}

.ms-cheat-list dd { margin: 0; color: var(--color-gray-700, #374151); }

.ms-cheat-list kbd {
    display: inline-block;
    padding: 0.1rem 0.4rem;
    border: 1px solid var(--color-gray-300, #d1d5db);
    border-bottom-width: 2px;
    border-radius: 4px;
    font-family: var(--font-family-mono, ui-monospace, monospace);
    font-size: 0.8rem;
    background: var(--color-gray-50, #f9fafb);
}

/* Mobile tweaks */
@media (max-width: 1023px) {
    .ms-grid-scroll {
        max-height: 60vh;
    }
}


/* ============================================================================
   Monthly sales - detail panel (MonthlySalesDetailPanel)

   R-013977: moved here from the embedded <style> block in
   Components/Shared/MonthlySalesDetailPanel.razor. An embedded block escapes the ordering
   in the central sheet and the lint gate; that exact invisibility is what caused
   R-014002.
   ============================================================================ */
.msdp-wrap {
    position: fixed;
    top: 0;
    right: 0;
    height: 100vh;
    width: 420px;
    max-width: 100vw;
    background: var(--color-white, #fff);
    border-left: 1px solid var(--color-gray-200, #e5e7eb);
    box-shadow: -8px 0 24px rgba(0, 0, 0, 0.08);
    transform: translateX(100%);
    transition: transform 300ms ease-out;
    z-index: 900;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.msdp-wrap.is-open {
    transform: translateX(0);
}

.msdp-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    padding: var(--spacing-4, 1rem) var(--spacing-5, 1.25rem);
    border-bottom: 1px solid var(--color-gray-200, #e5e7eb);
    background: var(--color-gray-50, #f9fafb);
}

.msdp-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--color-gray-900, #111827);
    line-height: 1.3;
}

.msdp-subtitle {
    font-size: 0.85rem;
    color: var(--color-gray-600, #4b5563);
    margin-top: 0.15rem;
}

.msdp-subtitle code {
    background: var(--color-gray-100, #f3f4f6);
    padding: 0.05rem 0.35rem;
    border-radius: 3px;
    font-size: 0.8rem;
}

.msdp-sep {
    margin: 0 0.4rem;
    color: var(--color-gray-400, #9ca3af);
}

.msdp-actions {
    display: flex;
    gap: 0.25rem;
}

.msdp-icon-btn {
    background: transparent;
    border: 1px solid transparent;
    border-radius: 6px;
    width: 2rem;
    height: 2rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--color-gray-600, #4b5563);
}

.msdp-icon-btn:hover,
.msdp-icon-btn:focus-visible {
    background: var(--color-gray-100, #f3f4f6);
    color: var(--color-gray-900, #111827);
    outline: none;
}

.msdp-icon-btn.is-active {
    color: var(--color-brand, #1d3d91);
    border-color: var(--color-brand, #1d3d91);
}

.msdp-live {
    position: absolute;
    left: -9999px;
}

.msdp-body {
    flex: 1;
    overflow: auto;
    padding: var(--spacing-5, 1.25rem);
}

.msdp-kpis {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
    margin-bottom: var(--spacing-5, 1.25rem);
}

.msdp-kpi {
    background: var(--color-gray-50, #f9fafb);
    border: 1px solid var(--color-gray-200, #e5e7eb);
    border-radius: 8px;
    padding: 0.7rem 0.9rem;
}

.msdp-kpi-label {
    font-size: 0.75rem;
    color: var(--color-gray-500, #6b7280);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.msdp-kpi-value {
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--color-gray-900, #111827);
    font-variant-numeric: tabular-nums;
}

.msdp-section {
    margin-bottom: var(--spacing-5, 1.25rem);
}

.msdp-section-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 0.4rem;
}

.msdp-section-title {
    font-size: 0.9rem;
    font-weight: 600;
    margin: 0;
    color: var(--color-gray-700, #374151);
}

.msdp-trend-toggle {
    display: inline-flex;
    border: 1px solid var(--color-gray-300, #d1d5db);
    border-radius: 6px;
    overflow: hidden;
}

.msdp-toggle-btn {
    background: transparent;
    border: none;
    padding: 0.25rem 0.7rem;
    font-size: 0.8rem;
    cursor: pointer;
    color: var(--color-gray-600, #4b5563);
}

.msdp-toggle-btn:hover,
.msdp-toggle-btn:focus-visible {
    background: var(--color-gray-100, #f3f4f6);
    outline: none;
}

.msdp-toggle-btn.is-active {
    background: var(--color-brand, #1d3d91);
    color: var(--color-white, #fff);
}

.msdp-sparkline {
    width: 100%;
    height: auto;
    display: block;
}

.msdp-spark-bar {
    fill: color-mix(in srgb, var(--color-brand, #1d3d91) 35%, transparent);
}

.msdp-spark-bar.is-anchor {
    fill: var(--color-brand, #1d3d91);
}

.msdp-spark-label {
    font-size: 9px;
    fill: var(--color-gray-500, #6b7280);
    font-family: var(--font-family-base, system-ui);
}

.msdp-spark-label.is-anchor {
    fill: var(--color-gray-900, #111827);
    font-weight: 600;
}

.msdp-yoy {
    font-size: 1.05rem;
    font-weight: 600;
    padding: 0.5rem 0.75rem;
    border-radius: 6px;
    background: var(--color-gray-50, #f9fafb);
}

.msdp-tone-positive { color: var(--color-success, #059669); }
.msdp-tone-negative { color: var(--color-danger, #dc2626); }
.msdp-tone-neutral  { color: var(--color-gray-700, #374151); }

.msdp-cust-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.msdp-cust {
    display: grid;
    grid-template-columns: 1fr 4.5rem 6rem 3.5rem;
    gap: 0.5rem;
    align-items: center;
    padding: 0.35rem 0.6rem;
    border-radius: 6px;
    font-size: 0.85rem;
    position: relative;
    background: linear-gradient(
        to right,
        color-mix(in srgb, var(--color-brand, #1d3d91) 15%, transparent) 0%,
        color-mix(in srgb, var(--color-brand, #1d3d91) 15%, transparent) var(--msdp-cust-share, 0%),
        transparent var(--msdp-cust-share, 0%),
        transparent 100%
    );
}

.msdp-cust-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--color-gray-900, #111827);
}

.msdp-cust-qty,
.msdp-cust-rev,
.msdp-cust-share-txt {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--color-gray-700, #374151);
}

.msdp-cust-share-txt {
    font-weight: 600;
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
    .msdp-wrap {
        transition: none;
    }
}

/* Mobile: full-screen bottom sheet */
@media (max-width: 1023px) {
    .msdp-wrap {
        width: 100vw;
        height: 85vh;
        top: auto;
        bottom: 0;
        right: 0;
        border-left: none;
        border-top: 1px solid var(--color-gray-200, #e5e7eb);
        transform: translateY(100%);
        box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.12);
    }

    .msdp-wrap.is-open {
        transform: translateY(0);
    }
}
