/* ==========================================================================
   SmartPharmacy — Bootstrap → Shadcn/UI theme layer
   ==========================================================================
   Loaded LAST in the design-system chain so it wins the cascade over both
   bootstrap.min.css and the earlier design-system/*.css files.

   SCOPE — this file deliberately does NOT restate rules that the existing
   design-system files already get right (card surfaces/radius, table
   theming, mvc-grid, select2, sweetalert, shell/sidebar/navbar, skeletons).
   Re-declaring them here would create the exact "duplicate override" problem
   this pass is meant to remove. It contains only:
     a) an alias token layer (the public --radius, --shadow, --surface and
        --text names) mapped onto the existing --ds-* tokens, and
     b) the components that were genuinely unstyled or still rendering with
        Bootstrap-era / vendor-default appearance — chiefly the four date
        pickers, alerts, tabs, accordion, switches, and the select indicator.

   Anything already themed is extended here, never duplicated. Read the
   section headers before adding: put new rules in the matching component
   file if one exists, and only here if this is the layer that owns it.

   SECTIONS
     1.  Design tokens (alias layer)
     2.  Typography
     3.  Buttons
     4.  Inputs & textareas
     5.  Selects
     6.  Checkbox / radio / switch
     7.  Date & datetime pickers
     8.  Cards
     9.  Modals & dropdowns
     10. Tables
     11. Navigation, alerts, badges, accordion
     12. Dark mode, accessibility, motion
   ========================================================================== */


/* ==========================================================================
   1. DESIGN TOKENS — alias layer
   ==========================================================================
   The app's source-of-truth palette is the --ds-* set in tokens.css, which
   theme-settings.css remaps per accent preset / radius / density choice.
   These aliases are the shorter public names; they RESOLVE THROUGH to --ds-*
   rather than restating any color, so the Theme Settings panel keeps working
   and there is exactly one place a color is ever defined.

   Consequence worth knowing: overriding --primary does nothing on its own —
   set --ds-primary (what the theme panel does). Aliases are for consuming.
   ========================================================================== */
:root {
    /* Radius — -sm/-md/-lg are owned by tokens.css + theme-settings.css
       (user-configurable via <html data-ds-radius>). Only the two missing
       ends of the scale are introduced here, derived so they follow the
       user's radius preference instead of pinning fixed px. */
    --radius-xs: max(4px, calc(var(--radius-sm) - 2px));
    --radius-xl: calc(var(--radius-lg) + 4px);

    /* Elevation */
    --shadow-xs: var(--ds-shadow-xs);
    --shadow-sm: var(--ds-shadow-sm);
    --shadow-md: var(--ds-shadow-md);
    --shadow-lg: var(--ds-shadow-lg);

    /* Surfaces */
    --surface: var(--ds-surface);
    --surface-elevated: var(--ds-surface-raised);
    --surface-muted: var(--ds-bg);

    /* Borders */
    --border: var(--ds-border);
    --border-hover: color-mix(in srgb, var(--ds-text) 18%, var(--ds-border));

    /* Brand + semantic */
    --primary: var(--ds-primary);
    --primary-hover: var(--ds-primary-hover);
    --primary-active: var(--ds-primary-active);
    --success: var(--ds-success);
    --warning: var(--ds-warning);
    --danger: var(--ds-danger);
    --info: var(--ds-info);

    /* Text */
    --text-primary: var(--ds-text);
    --text-secondary: color-mix(in srgb, var(--ds-text) 72%, var(--ds-bg));
    --text-muted: var(--ds-text-muted);

    /* Focus ring — one definition every component's :focus-visible consumes,
       so the ring can never drift per component (section 12). */
    --ring-width: 3px;
    --ring-color: color-mix(in srgb, var(--ds-primary) 35%, transparent);
    --ring: 0 0 0 var(--ring-width) var(--ring-color);
    --ring-offset-bg: var(--ds-surface);

    /* Motion — Shadcn/Radix "ease-out-expo" curve. Existing --ds-duration-*
       tokens stay authoritative for shell transitions; these are the
       component-level equivalents named per the design brief. */
    --ease: cubic-bezier(0.16, 1, 0.3, 1);
    --duration-fast: 150ms;
    --duration: 200ms;
    --duration-slow: 250ms;

    /* Taller ("spacious") control tier — see the note on .btn in section 3. */
    --control-height-spacious: 40px;
    --control-height-spacious-lg: 44px;
}

/* Live, user-facing toggle: Theme Settings panel → "Control size" →
   Compact/Default/Spacious/Large, wired in theme-settings.js as the
   'ds-control-size' preference and rendered on <html data-ds-control-size="…">.
   Named
   "spacious" (not "comfortable") specifically to avoid colliding with the
   existing Density setting, whose DEFAULT value is already the word
   "comfortable" (data-ds-density="comfortable" vs "compact") — same word,
   different axis, would have been confusing in the same settings panel.

   The default tier stays 36px because a previous pass measured 44px as too
   tall for this app's dense grids (Selling's item table) — see the
   --control-height comment in tokens.css. Spacious raises every control that
   consumes the shared tokens (.btn, .form-control, .form-select,
   .select2-selection, .input-group-text) in one place, no per-component
   edits, for anyone who wants the brief's literal 40–44px sizing. */
:root[data-ds-control-size="spacious"] {
    --control-height: var(--control-height-spacious);
    --control-height-lg: var(--control-height-spacious-lg);
}

/* FormControlSize — "Compact"/"Large" tiers, added alongside the original
   Default/Spacious pair without renaming either (so a prior "spacious"
   choice already saved in a user's localStorage keeps working unchanged).
   Reuses --control-height-sm/-lg, already defined in tokens.css for the
   .form-control-sm/-lg utility classes — no new pixel values introduced.
   Padding scales with it (control-padding-x) per the same tier. */
:root[data-ds-control-size="compact"] {
    --control-height: var(--control-height-sm);
    --control-height-lg: var(--control-height);
    --control-padding-x: var(--space-2);
}

:root[data-ds-control-size="large"] {
    --control-height: var(--control-height-lg);
    --control-height-lg: var(--control-height-spacious-lg);
    --control-padding-x: var(--space-4);
}


/* ==========================================================================
   2. TYPOGRAPHY
   ==========================================================================
   base.css owns the family/scale/headings. Added here: the tighter
   Shadcn-style label + description pairing and tabular numerals for the
   data-dense views, neither of which existed.
   ========================================================================== */

/* Numeric columns/values align on the decimal instead of drifting — the
   feature that makes Stripe/Linear tables read as engineered. Applies to
   money/quantity cells and KPI values, not body copy. */
.stat-card-value,
.table td.text-end,
.table td.numeric,
.mvc-grid td.text-end {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

/* Card titles: Bootstrap leaves these at h5 weight/size with a stray
   bottom margin inside an already-padded .card-body. */
.card-title {
    font-size: var(--ds-text-card-title);
    font-weight: 600;
    letter-spacing: -0.01em;
    margin-bottom: var(--space-1);
}

.card-subtitle,
.card-text.text-muted {
    font-size: var(--ds-text-caption);
    color: var(--text-muted);
}


/* ==========================================================================
   3. BUTTONS
   ==========================================================================
   buttons.css already sets radius/weight/height/primary/ghost/loading. This
   section adds what was missing: the remaining semantic variants routed
   through tokens (they were still painting Bootstrap's stock hex values),
   the full Shadcn variant set (secondary/outline/ghost/link/destructive),
   icon alignment, and a real focus ring.
   ========================================================================== */

/* Icon alignment — buttons.css makes standard buttons inline-flex; give the
   icon a real gap instead of relying on a stray &nbsp; or me-1 in markup,
   and stop the icon from being stretched by the flex container. */
.btn > i,
.btn > svg,
.btn > .bi {
    flex: 0 0 auto;
    line-height: 1;
}

.btn:not(.btn-sm):not(.btn-lg):not(.circle),
.btn-sm:not(.circle),
.btn-lg:not(.circle) {
    gap: var(--space-2);
    white-space: nowrap;
}

/* Bootstrap's .btn box-shadow on :focus is a 4px translucent-brand halo that
   fires on mouse click too. Suppress it and route focus through
   :focus-visible only (keyboard), per section 12. */
.btn:focus,
.btn.focus,
.btn:active:focus {
    box-shadow: none;
}

.btn:focus-visible {
    box-shadow: var(--ring);
    outline: none;
}

/* Soft lift on hover — Shadcn/Linear use a shadow change, not a gradient or
   a color-only shift. transform is intentionally left to buttons.css's
   :active translateY so the two don't fight. */
.btn:not(.btn-link):not(.btn-ghost):hover {
    box-shadow: var(--shadow-sm);
}

/* -- Semantic variants ---------------------------------------------------
   Each was still using bootstrap.min.css's hardcoded palette, so they
   ignored both dark mode and the accent preset. Flat fills, no gradients. */
.btn-secondary {
    background-color: var(--surface);
    border-color: var(--border);
    color: var(--text-primary);
}

.btn-secondary:hover {
    background-color: var(--surface-muted);
    border-color: var(--border-hover);
    color: var(--text-primary);
}

.btn-secondary:active,
.btn-secondary:not(:disabled):not(.disabled).active {
    background-color: var(--surface-muted) !important;
    border-color: var(--border-hover) !important;
    color: var(--text-primary) !important;
}

.btn-success {
    background-color: var(--success);
    border-color: var(--success);
    color: #fff;
}

.btn-danger {
    background-color: var(--danger);
    border-color: var(--danger);
    color: #fff;
}

.btn-warning {
    background-color: var(--warning);
    border-color: var(--warning);
    color: #fff;
}

.btn-info {
    background-color: var(--info);
    border-color: var(--info);
    color: #fff;
}

/* color-mix darkens each fill by a uniform amount rather than needing a
   hand-picked hover hex per variant. */
.btn-success:hover,
.btn-danger:hover,
.btn-warning:hover,
.btn-info:hover {
    color: #fff;
}

.btn-success:hover { background-color: color-mix(in srgb, #000 12%, var(--success)); border-color: color-mix(in srgb, #000 12%, var(--success)); }
.btn-danger:hover  { background-color: color-mix(in srgb, #000 12%, var(--danger));  border-color: color-mix(in srgb, #000 12%, var(--danger)); }
.btn-warning:hover { background-color: color-mix(in srgb, #000 12%, var(--warning)); border-color: color-mix(in srgb, #000 12%, var(--warning)); }
.btn-info:hover    { background-color: color-mix(in srgb, #000 12%, var(--info));    border-color: color-mix(in srgb, #000 12%, var(--info)); }

/* Pressed state — only .btn-primary had this (buttons.css); every other
   filled variant fell through to Bootstrap's own --bs-btn-active-bg, which
   is a hardcoded per-variant hex (e.g. still Bootstrap blue/green/red on
   click regardless of accent preset or dark mode). Darker mix than :hover
   so a click reads as a distinct, deeper press. */
.btn-success:active { background-color: color-mix(in srgb, #000 20%, var(--success)) !important; border-color: color-mix(in srgb, #000 20%, var(--success)) !important; color: #fff; }
.btn-danger:active  { background-color: color-mix(in srgb, #000 20%, var(--danger))  !important; border-color: color-mix(in srgb, #000 20%, var(--danger))  !important; color: #fff; }
.btn-warning:active { background-color: color-mix(in srgb, #000 20%, var(--warning)) !important; border-color: color-mix(in srgb, #000 20%, var(--warning)) !important; color: #fff; }
.btn-info:active    { background-color: color-mix(in srgb, #000 20%, var(--info))    !important; border-color: color-mix(in srgb, #000 20%, var(--info))    !important; color: #fff; }
/* .btn-secondary:active already handled above (line ~244). */

/* Disabled — Bootstrap's own .btn:disabled rule (further down, "Disabled"
   section) only zeroes out opacity/shadow; the background/border/color it
   inherits still resolve through each variant's --bs-btn-disabled-* custom
   properties, which bootstrap.min.css hardcodes to its stock palette (e.g.
   #0d6efd for primary) rather than this app's tokens. Since buttons.css/
   this file already paint the ENABLED state via background-color directly
   (bypassing that variable chain), the disabled state visibly reverted to
   Bootstrap's stock color instead of a dimmed version of the theme's. Reassert
   the same on-theme color here; the opacity:.5 from the Disabled section
   below still does the actual dimming. */
.btn-primary:disabled,   .btn-primary.disabled   { background-color: var(--ds-primary) !important; border-color: var(--ds-primary) !important; color: #fff !important; }
.btn-secondary:disabled, .btn-secondary.disabled { background-color: var(--surface) !important; border-color: var(--border) !important; color: var(--text-primary) !important; }
.btn-success:disabled,   .btn-success.disabled   { background-color: var(--success) !important; border-color: var(--success) !important; color: #fff !important; }
.btn-danger:disabled,    .btn-danger.disabled    { background-color: var(--danger)  !important; border-color: var(--danger)  !important; color: #fff !important; }
.btn-warning:disabled,   .btn-warning.disabled   { background-color: var(--warning) !important; border-color: var(--warning) !important; color: #fff !important; }
.btn-info:disabled,      .btn-info.disabled      { background-color: var(--info)    !important; border-color: var(--info)    !important; color: #fff !important; }
.btn-destructive:disabled, .btn-destructive.disabled { background-color: var(--danger) !important; border-color: var(--danger) !important; color: #fff !important; }
.btn-outline-primary:disabled,   .btn-outline-primary.disabled   { color: var(--primary) !important; border-color: var(--primary) !important; background-color: transparent !important; }
.btn-outline-secondary:disabled, .btn-outline-secondary.disabled { color: var(--text-primary) !important; border-color: var(--border) !important; background-color: transparent !important; }
.btn-outline-success:disabled,   .btn-outline-success.disabled   { color: var(--success) !important; border-color: var(--success) !important; background-color: transparent !important; }
.btn-outline-danger:disabled,    .btn-outline-danger.disabled    { color: var(--danger)  !important; border-color: var(--danger)  !important; background-color: transparent !important; }
.btn-outline-warning:disabled,   .btn-outline-warning.disabled   { color: var(--warning) !important; border-color: var(--warning) !important; background-color: transparent !important; }
.btn-outline-info:disabled,      .btn-outline-info.disabled      { color: var(--info)    !important; border-color: var(--info)    !important; background-color: transparent !important; }
.btn-outline-dark:disabled,      .btn-outline-dark.disabled      { color: var(--text-primary) !important; border-color: var(--border) !important; background-color: transparent !important; }

/* Destructive — Shadcn's name for the danger variant. Alias, so both the
   existing .btn-danger markup and new .btn-destructive markup work. */
.btn-destructive {
    background-color: var(--danger);
    border-color: var(--danger);
    color: #fff;
}

.btn-destructive:hover {
    background-color: color-mix(in srgb, #000 12%, var(--danger));
    border-color: color-mix(in srgb, #000 12%, var(--danger));
    color: #fff;
}

/* -- Outline variants ----------------------------------------------------
   Bootstrap's outline buttons hardcode their border color per variant.
   btn-outline-dark hardcodes #212529, which is invisible against a dark
   surface — alias it to the same neutral tokens as btn-outline-secondary
   so it stays visible (and supports the accent/dark-mode picker) in
   _ThemeSettings.cshtml. */
.btn-outline-secondary, .btn-outline-dark { color: var(--text-primary);  border-color: var(--border); }
.btn-outline-success   { color: var(--success);       border-color: var(--success); }
.btn-outline-danger    { color: var(--danger);        border-color: var(--danger); }
.btn-outline-warning   { color: var(--warning);       border-color: var(--warning); }
.btn-outline-info      { color: var(--info);          border-color: var(--info); }

.btn-outline-secondary:hover, .btn-outline-dark:hover {
    background-color: var(--surface-muted);
    border-color: var(--border-hover);
    color: var(--text-primary);
}

.btn-outline-success:hover { background-color: var(--success); border-color: var(--success); color: #fff; }
.btn-outline-danger:hover  { background-color: var(--danger);  border-color: var(--danger);  color: #fff; }
.btn-outline-warning:hover { background-color: var(--warning); border-color: var(--warning); color: #fff; }
.btn-outline-info:hover    { background-color: var(--info);    border-color: var(--info);    color: #fff; }

/* -- Ghost / link --------------------------------------------------------
   .btn-ghost's base + hover live in buttons.css; only the destructive
   modifier and the link variant are new. */
.btn-ghost-danger {
    background-color: transparent;
    border-color: transparent;
    color: var(--danger);
}

.btn-ghost-danger:hover {
    background-color: var(--ds-danger-bg);
    color: var(--danger);
}

.btn-link {
    color: var(--primary);
    text-decoration: none;
    font-weight: 500;
    box-shadow: none;
    padding-inline: var(--space-1);
}

.btn-link:hover {
    color: var(--primary-hover);
    text-decoration: underline;
    text-underline-offset: 3px;
    background-color: transparent;
}

/* -- Disabled -----------------------------------------------------------
   One consistent treatment; Bootstrap's per-variant .disabled opacity
   leaves some variants looking active. */
.btn:disabled,
.btn.disabled,
fieldset:disabled .btn {
    opacity: .5;
    box-shadow: none;
    pointer-events: none;
}

/* Icon-only square button (Shadcn "icon" size) — distinct from the app's
   existing round .circle shell buttons, which keep their own sizing. */
.btn-icon {
    width: var(--control-height);
    padding: 0;
    flex: 0 0 auto;
}

.btn-icon.btn-sm { width: var(--control-height-sm); }
.btn-icon.btn-lg { width: var(--control-height-lg); }

/* Loading spinner contrast on light-filled variants — buttons.css only
   handles the white-on-brand and brand-on-transparent cases. */
.btn-secondary.btn-loading::after,
.btn-outline-secondary.btn-loading::after,
.btn-light.btn-loading::after {
    border-color: color-mix(in srgb, var(--ds-text) 25%, transparent);
    border-top-color: var(--ds-text);
}


/* ==========================================================================
   4. INPUTS & TEXTAREAS
   ==========================================================================
   forms.css owns radius/height/border/validation. Added here: removal of
   Bootstrap's inset shadow, the hover-border affordance, a proper disabled
   and readonly treatment, and real textarea behavior (forms.css only sets
   min-height).
   ========================================================================== */

.form-control,
.form-select {
    box-shadow: none; /* kills Bootstrap's inset well */
    transition: border-color var(--duration-fast) var(--ease),
                box-shadow var(--duration-fast) var(--ease),
                background-color var(--duration-fast) var(--ease);
}

/* Hover affordance — the border reacts before focus, as in Shadcn. Excluded
   on disabled/readonly so they read as genuinely inert. */
.form-control:hover:not(:focus):not(:disabled):not([readonly]),
.form-select:hover:not(:focus):not(:disabled) {
    border-color: var(--border-hover);
}

/* forms.css already sets the focus border + a 3px ring using --ds-active.
   Re-point it at the shared --ring so inputs, buttons, checkboxes, selects
   and date pickers all render one identical ring. */
.form-control:focus,
.form-select:focus {
    box-shadow: var(--ring);
    outline: none;
}

.form-control::placeholder {
    opacity: 1; /* Firefox dims placeholders on top of the token color */
}

.form-control:disabled,
.form-control[readonly],
.form-select:disabled,
fieldset:disabled .form-control,
fieldset:disabled .form-select {
    background-color: var(--surface-muted);
    border-color: var(--border);
    color: var(--text-muted);
    cursor: not-allowed;
    opacity: 1; /* Bootstrap's opacity:1 + gray bg reads better than a fade */
}

/* readonly-but-focusable fields (common in this app for computed totals)
   should still be selectable, just not editable-looking. */
.form-control[readonly] {
    cursor: default;
}

/* -- Textareas ---------------------------------------------------------- */
textarea.form-control {
    resize: vertical;             /* horizontal resize breaks grid layouts */
    min-height: calc(var(--control-height) * 2);
    padding: var(--space-3);
    line-height: 1.55;
    field-sizing: content;        /* progressive: auto-grows where supported */
    max-height: 60vh;             /* ...but never past the viewport */
}

textarea.form-control[rows] {
    field-sizing: fixed;          /* explicit rows= wins over auto-grow */
}

textarea.form-control-sm { padding: var(--space-2); }

/* -- Labels, help text, validation -------------------------------------
   forms.css styles .form-label and .invalid-feedback. Added: the spacing
   hierarchy between label → control → helper, and the .form-text Bootstrap
   class this app also uses. */
/* Scoped to .form-label only. A blanket `label { display: inline-block }`
   would change width/margin behavior for labels used inline inside sentences
   or table cells across the legacy views. */
.form-label {
    display: inline-block;
    line-height: 1.4;
}

label {
    line-height: 1.4;
}

.form-text {
    font-size: var(--ds-text-caption);
    color: var(--text-muted);
    margin-top: var(--space-1);
}

.invalid-feedback,
.valid-feedback {
    margin-top: var(--space-1);
    font-weight: 500;
}

/* Group spacing — Bootstrap's .mb-3 on every form row is inconsistent
   across this app's 452 views; .form-group is the class already present in
   the older ones. */
.form-group + .form-group {
    margin-top: var(--space-4);
}

/* Required marker: forms.css colors it with --ds-primary. Danger reads as
   the more conventional required signal and matches the validation color. */
label.required::after,
.form-label.required::after {
    color: var(--danger);
    font-weight: 700;
}


/* ==========================================================================
   5. SELECTS
   ==========================================================================
   Replaces Bootstrap's stock caret with a Shadcn chevron. Bootstrap inlines
   the arrow as a data-URI with a BAKED-IN hex stroke, so it cannot follow
   the theme — that is why a dark-mode override is required below rather
   than a single currentColor rule. Kept as a data-URI (not an extra HTTP
   request, not a pseudo-element wrapper) for the same reason Bootstrap does.
   ========================================================================== */

.form-select {
    /* stroke #6b7280 = --ds-text-muted (light) */
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%236b7280' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M4 6l4 4 4-4'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right var(--space-3) center;
    background-size: 15px 15px;
    padding-inline-end: calc(var(--space-3) * 2 + 15px);
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    cursor: pointer;
}

/* RTL — this app runs Arabic/Kurdish shells (see theme-settings.css), where
   the caret belongs on the left. */
[dir="rtl"] .form-select {
    background-position: left var(--space-3) center;
    padding-inline-end: var(--space-3);
    padding-inline-start: calc(var(--space-3) * 2 + 15px);
}

.form-select:disabled {
    cursor: not-allowed;
}

/* Native <option> lists are OS-drawn; the most we can portably do is stop
   them inheriting an unreadable dark-on-dark from the control. */
.form-select option {
    background-color: var(--surface);
    color: var(--text-primary);
}

/* Multi-select has no caret and is not a fixed-height control. */
.form-select[multiple],
.form-select[size]:not([size="1"]) {
    background-image: none;
    padding-inline-end: var(--space-3);
    height: auto;
    min-height: unset;
}


/* ==========================================================================
   6. CHECKBOX / RADIO / SWITCH
   ==========================================================================
   forms.css sets the checked fill + a radius on checkboxes. Added here:
   consistent sizing, the animated check/dot, the switch (which had NO
   styling at all — only the three third-party toggle plugins were themed),
   and label alignment.
   ========================================================================== */

.form-check-input {
    width: 1.05rem;
    height: 1.05rem;
    margin-top: .15em;
    background-color: var(--surface);
    border-width: 1.5px;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease),
                border-color var(--duration-fast) var(--ease),
                box-shadow var(--duration-fast) var(--ease);
}

.form-check-input:hover:not(:disabled):not(:checked) {
    border-color: var(--border-hover);
}

.form-check-input:focus-visible {
    box-shadow: var(--ring);
    outline: none;
}

/* Bootstrap fires its focus shadow on mouse click too. */
.form-check-input:focus:not(:focus-visible) {
    box-shadow: none;
}

.form-check-input:disabled {
    opacity: .5;
    cursor: not-allowed;
}

.form-check-input:disabled ~ .form-check-label {
    opacity: .5;
    cursor: not-allowed;
}

.form-check-label {
    font-weight: 400;
    font-size: var(--ds-text-body);
    cursor: pointer;
    padding-inline-start: var(--space-1);
}

/* Checkmark — Bootstrap's baked-in white glyph is fine; the animation is
   what makes it feel like Shadcn. Scaling the background is cheap (no
   layout, no filter). */
input.form-check-input[type="checkbox"]:checked {
    animation: ds-check-pop var(--duration-fast) var(--ease);
}

@keyframes ds-check-pop {
    0%   { transform: scale(.85); }
    100% { transform: scale(1); }
}

/* Indeterminate (used by "select all" grid headers) */
input.form-check-input[type="checkbox"]:indeterminate {
    background-color: var(--primary);
    border-color: var(--primary);
}

/* -- Radio -------------------------------------------------------------- */
input.form-check-input[type="radio"] {
    border-radius: 50%;
}

input.form-check-input[type="radio"]:checked {
    /* Ring style rather than Bootstrap's filled circle + white dot image:
       renders crisply at any size and needs no data-URI. */
    background-image: none;
    background-color: var(--surface);
    border-color: var(--primary);
    border-width: 5px;
    animation: ds-check-pop var(--duration-fast) var(--ease);
}

/* Bare <input type="radio">/<input type="checkbox"> without .form-check-input
   (several older views markup plain radios inline, e.g. Purchase/Reports
   date-range toggles) render with the OS's native control and completely
   ignore every design-system token/dark-mode/accent choice above — the
   .form-check-input rules only ever matched Bootstrap-classed inputs.
   `accent-color` is a native CSS property (not a custom rebuild like the
   .form-check-input ring/dot above) that retints the browser's own control
   with zero markup changes, so every one of these already-existing inputs
   picks up the current accent color/dark mode automatically. */
input[type="radio"]:not(.form-check-input),
input[type="checkbox"]:not(.form-check-input) {
    accent-color: var(--primary);
    cursor: pointer;
}

/* -- Range (slider) ------------------------------------------------------
   Bootstrap ships .form-range with zero design-system theming — it read
   raw browser/Bootstrap-default colors before this (visible on the Theme
   Settings panel's Sidebar Glass Intensity slider). Retint via the same
   `accent-color` mechanism (broad modern-browser support for range inputs
   too) plus track background + radius from the current Corner Radius theme
   setting, instead of Bootstrap's fixed 1rem pill. */
.form-range {
    accent-color: var(--primary);
}

.form-range::-webkit-slider-runnable-track {
    background-color: var(--surface-muted);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}

.form-range::-moz-range-track {
    background-color: var(--surface-muted);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}

.form-range::-webkit-slider-thumb {
    background-color: var(--primary);
    border: none;
    box-shadow: var(--shadow-sm);
}

.form-range::-moz-range-thumb {
    background-color: var(--primary);
    border: none;
    box-shadow: var(--shadow-sm);
}

.form-range:focus::-webkit-slider-thumb {
    box-shadow: var(--ring);
}

.form-range:focus::-moz-range-thumb {
    box-shadow: var(--ring);
}

.form-range:disabled {
    opacity: .5;
}

/* -- Switch ------------------------------------------------------------
   Bootstrap 5.3 already draws the thumb as a background-image exposed via
   --bs-form-switch-bg and already slides it with
   `transition: background-position`. So the Shadcn look needs only a track
   recolor + a thumb-color override — NOT a re-implementation.

   Deliberately NOT done as a ::after pseudo-element on the input: pseudo-
   elements on <input> are a replaced-element edge case browsers handle
   inconsistently, which is exactly why Bootstrap uses a background image
   here. Overriding the variable keeps Bootstrap's reduced-motion rule and
   its .form-check-reverse (opt-in per-instance RTL class) support working
   for free.

   That is NOT the same as this app's live "Direction" setting, though: this
   app toggles a bare `dir="rtl"` attribute on <html> (see theme-settings.js)
   while loading the LTR-only lib/bootstrap/dist/css/bootstrap.min.css, not
   the bootstrap.rtl.css bundle — so Bootstrap's own physical
   padding-left/margin-left/background-position:left on .form-switch never
   flip for that toggle. The [dir="rtl"] block below mirrors it by hand,
   matching bootstrap.rtl.css's own .form-switch rule value-for-value.

   Only 2 views use .form-switch today; it is the recommended target for new
   toggles instead of adding a fourth toggle plugin. */
.form-switch {
    min-height: 1.35rem;
}

.form-switch .form-check-input {
    width: 2.15rem;
    height: 1.2rem;
    margin-top: .1em;
    border-radius: 999px;
    border: 1.5px solid var(--border);
    background-color: var(--surface-muted);
    flex-shrink: 0;
    /* Opaque white thumb with a hairline edge, versus Bootstrap's 25%-black
       translucent dot — the difference that reads as "Shadcn switch". */
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff' stroke='rgba%280,0,0,0.12%29' stroke-width='0.5'/%3e%3c/svg%3e");
    transition: background-position var(--duration-fast) var(--ease),
                background-color var(--duration-fast) var(--ease),
                border-color var(--duration-fast) var(--ease);
}

/* Bootstrap swaps the thumb to a flat #86b7fe on :focus — keep our thumb. */
.form-switch .form-check-input:focus,
.form-switch .form-check-input:checked {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff' stroke='rgba%280,0,0,0.12%29' stroke-width='0.5'/%3e%3c/svg%3e");
}

.form-switch .form-check-input:checked {
    background-color: var(--primary);
    border-color: var(--primary);
    animation: none;                 /* the thumb slides; no check-pop */
}

.form-switch .form-check-input:hover:not(:checked):not(:disabled) {
    background-color: color-mix(in srgb, var(--ds-text) 6%, var(--surface-muted));
}

/* Live RTL mirroring for the `dir="rtl"` attribute toggle — see the block
   comment above for why Bootstrap's own bundle doesn't do this here. */
[dir="rtl"] .form-switch {
    padding-right: 2.5em;
    padding-left: 0;
}

[dir="rtl"] .form-switch .form-check-input {
    margin-right: -2.5em;
    margin-left: 0;
    background-position: right center;
}

[dir="rtl"] .form-switch .form-check-input:checked {
    background-position: left center;
}

/* Button-group style radio/checkbox toggles (.btn-check) — used for
   segmented filters. Bootstrap leaves the checked state on its stock
   primary hex. */
.btn-check:checked + .btn,
.btn-check:active + .btn {
    background-color: var(--primary);
    border-color: var(--primary);
    color: #fff;
}

.btn-check:focus-visible + .btn {
    box-shadow: var(--ring);
}


/* ==========================================================================
   7. DATE & DATETIME PICKERS
   ==========================================================================
   The largest gap in the previous system: all four date UIs the app loads
   were rendering at 100% vendor default — no tokens, no dark mode, tiny
   click targets. Selector names below were read out of each vendor file, not
   guessed:
     · daterangepicker            (lib/daterangepicker/) — 34 views
     · bootstrap-material-datetimepicker (.dtp-*)        — 21 views
     · jQuery UI datepicker       (.ui-datepicker-*)     — 2 views
     · native <input type=date|datetime-local>           — 32 views
   All four are reskinned to ONE calendar language so a view using
   daterangepicker and a view using .dtp look like the same product.
   ========================================================================== */

/* -- Shared calendar tokens -------------------------------------------- */
:root {
    --cal-cell: 34px;              /* large click target (was ~20px) */
    --cal-radius: var(--radius-md);
    --cal-panel-radius: var(--radius-lg);
}

/* ------------------------------------------------------------------ 7a.
   daterangepicker
   ------------------------------------------------------------------ */
.daterangepicker {
    font-family: var(--ds-font);
    font-size: var(--ds-text-body);
    background-color: var(--surface-elevated);
    border: 1px solid var(--border);
    border-radius: var(--cal-panel-radius);
    box-shadow: var(--shadow-lg);
    color: var(--text-primary);
    padding: var(--space-2);
    animation: ds-pop-in var(--duration) var(--ease);
}

/* The vendor draws its popup arrow with two hardcoded-white borders that
   sit wrong on any non-white surface and break entirely in dark mode. */
.daterangepicker::before,
.daterangepicker::after {
    display: none;
}

.daterangepicker .drp-calendar {
    max-width: none;
    padding: var(--space-2);
}

.daterangepicker .calendar-table {
    background-color: transparent;
    border: none;
    border-radius: 0;
}

.daterangepicker .calendar-table table {
    border-collapse: separate;
    border-spacing: 2px;
}

.daterangepicker th,
.daterangepicker td {
    min-width: var(--cal-cell);
    width: var(--cal-cell);
    height: var(--cal-cell);
    border-radius: var(--cal-radius);
    font-size: var(--ds-text-body);
    font-weight: 500;
    vertical-align: middle;
    transition: background-color var(--duration-fast) var(--ease),
                color var(--duration-fast) var(--ease);
}

/* Weekday header row */
.daterangepicker th.month,
.daterangepicker thead tr:last-child th {
    font-size: var(--ds-text-caption);
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: .03em;
}

.daterangepicker th.month {
    text-transform: none;
    letter-spacing: 0;
    font-size: var(--ds-text-body);
    font-weight: 600;
    color: var(--text-primary);
}

/* Month/year nav — real 30px targets instead of 14px chevrons */
.daterangepicker th.prev,
.daterangepicker th.next {
    cursor: pointer;
    border-radius: var(--cal-radius);
    color: var(--text-muted);
}

.daterangepicker th.prev:hover,
.daterangepicker th.next:hover {
    background-color: var(--ds-hover);
    color: var(--text-primary);
}

/* The vendor chevron is a rotated bordered square; recolor via border. */
.daterangepicker .prev span,
.daterangepicker .next span {
    border-color: currentColor;
    border-width: 0 2px 2px 0;
}

.daterangepicker td.available:hover,
.daterangepicker th.available:hover {
    background-color: var(--ds-hover);
    color: var(--text-primary);
}

.daterangepicker td.off,
.daterangepicker td.off.in-range,
.daterangepicker td.off.start-date,
.daterangepicker td.off.end-date {
    background-color: transparent;
    color: color-mix(in srgb, var(--text-muted) 55%, transparent);
}

.daterangepicker td.in-range {
    background-color: var(--ds-hover);
    color: var(--text-primary);
    border-radius: 0;
}

.daterangepicker td.active,
.daterangepicker td.active:hover,
.daterangepicker td.start-date,
.daterangepicker td.end-date {
    background-color: var(--primary);
    color: #fff;
    font-weight: 600;
}

/* Range ends keep the rounded pill; the middle is square so the run reads
   as one continuous selection. */
.daterangepicker td.start-date          { border-radius: var(--cal-radius) 0 0 var(--cal-radius); }
.daterangepicker td.end-date            { border-radius: 0 var(--cal-radius) var(--cal-radius) 0; }
.daterangepicker td.start-date.end-date { border-radius: var(--cal-radius); }

[dir="rtl"] .daterangepicker td.start-date { border-radius: 0 var(--cal-radius) var(--cal-radius) 0; }
[dir="rtl"] .daterangepicker td.end-date   { border-radius: var(--cal-radius) 0 0 var(--cal-radius); }

.daterangepicker td.today,
.daterangepicker td.available.today:not(.active) {
    box-shadow: inset 0 0 0 1.5px var(--primary);
    color: var(--text-light);
    font-weight: 700;
}

.daterangepicker td.disabled {
    color: color-mix(in srgb, var(--text-muted) 45%, transparent);
    text-decoration: none;
    cursor: not-allowed;
}

/* Month/year dropdowns inside the header */
.daterangepicker select.monthselect,
.daterangepicker select.yearselect,
.daterangepicker select.hourselect,
.daterangepicker select.minuteselect,
.daterangepicker select.secondselect,
.daterangepicker select.ampmselect {
    height: var(--control-height-sm);
    padding: 0 var(--space-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background-color: var(--surface);
    color: var(--text-primary);
    font-size: var(--ds-text-body);
    cursor: pointer;
}

.daterangepicker select:focus-visible {
    outline: none;
    border-color: var(--primary);
    box-shadow: var(--ring);
}

/* Time row */
.daterangepicker .calendar-time {
    padding: var(--space-2) 0 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
}

/* Preset ranges list */
.daterangepicker .ranges {
    margin-top: 0;
    padding: var(--space-1);
}

.daterangepicker .ranges ul {
    width: auto;
    min-width: 150px;
}

.daterangepicker .ranges li {
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    font-size: var(--ds-text-body);
    font-weight: 500;
    color: var(--text-primary);
    transition: background-color var(--duration-fast) var(--ease);
}

.daterangepicker .ranges li:hover {
    background-color: var(--ds-hover);
}

.daterangepicker .ranges li.active {
    background-color: var(--primary);
    color: #fff;
}

/* Footer */
.daterangepicker .drp-buttons {
    border-top: 1px solid var(--border);
    padding: var(--space-3);
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.daterangepicker .drp-selected {
    font-size: var(--ds-text-caption);
    color: var(--text-muted);
    margin-inline-end: auto;
}

/* The vendor markup reuses .btn/.btn-sm, so section 3 already styles these;
   only the vendor's own float/margin needs neutralizing. */
.daterangepicker .drp-buttons .btn {
    float: none;
    margin: 0;
}

/* Vendor separator between the two calendars */
.daterangepicker.show-calendar .drp-calendar.right {
    border-inline-start: 1px solid var(--border);
}

/* ------------------------------------------------------------------ 7b.
   bootstrap-material-datetimepicker (.dtp) — calendar + time in one panel
   ------------------------------------------------------------------ */
.dtp {
    font-family: var(--ds-font);
}

.dtp > .dtp-content {
    background-color: var(--surface-elevated);
    border-radius: var(--cal-panel-radius);
    box-shadow: var(--shadow-lg);
    color: var(--text-primary);
    max-width: 320px;
    overflow: hidden;
}

/* Vendor uses a flat Material-teal header bar. */
.dtp > .dtp-content > .dtp-date-view > header.dtp-header {
    background-color: var(--primary);
    color: #fff;
    padding: var(--space-4) var(--space-5);
    text-align: start;
}

.dtp-header .dtp-actual-day,
.dtp-header .dtp-actual-year {
    font-size: var(--ds-text-caption);
    font-weight: 600;
    opacity: .85;
    text-transform: uppercase;
    letter-spacing: .04em;
}

.dtp-header .dtp-actual-month {
    font-size: var(--ds-text-caption);
    font-weight: 600;
    opacity: .85;
    text-transform: uppercase;
}

.dtp-header .dtp-actual-num {
    font-size: 2.25rem;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -0.02em;
}

.dtp-header .dtp-actual-time,
.dtp-header .dtp-actual-maxtime {
    font-size: 1.15rem;
    font-weight: 600;
}

.dtp-date,
.dtp-time {
    background-color: transparent;
}

.dtp-picker {
    padding: var(--space-4);
}

/* Month navigation row */
.dtp-picker-month,
.dtp-picker-year,
.dtp-picker-time {
    font-size: var(--ds-text-body);
    font-weight: 600;
    color: var(--text-primary);
    padding: 0 0 var(--space-3);
}

.dtp-picker-month .dtp-select-month,
.dtp-select-month,
.dtp-select-year {
    color: var(--text-primary);
}

/* Vendor arrows are <a> with an icon font; give them real targets. */
.dtp a.dtp-select-month-before,
.dtp a.dtp-select-month-after,
.dtp a.dtp-select-year-before,
.dtp a.dtp-select-year-after {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    text-decoration: none;
    transition: background-color var(--duration-fast) var(--ease);
}

.dtp a.dtp-select-month-before:hover,
.dtp a.dtp-select-month-after:hover,
.dtp a.dtp-select-year-before:hover,
.dtp a.dtp-select-year-after:hover {
    background-color: var(--ds-hover);
    color: var(--text-primary);
}

.dtp table.dtp-picker-days {
    border-collapse: separate;
    border-spacing: 2px;
    margin: 0;
}

.dtp table.dtp-picker-days th {
    font-size: var(--ds-text-caption);
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: .03em;
    border: none;
    padding: var(--space-1) 0;
    text-align: center;
}

.dtp table.dtp-picker-days td {
    width: var(--cal-cell);
    height: var(--cal-cell);
    padding: 0;
    border: none;
    text-align: center;
    vertical-align: middle;
}

.dtp table.dtp-picker-days td > a,
.dtp table.dtp-picker-days td > span.dtp-select-day {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--cal-cell);
    height: var(--cal-cell);
    border-radius: var(--cal-radius);
    font-size: var(--ds-text-body);
    font-weight: 500;
    color: var(--text-primary);
    text-decoration: none;
    transition: background-color var(--duration-fast) var(--ease),
                color var(--duration-fast) var(--ease);
}

.dtp table.dtp-picker-days td > a:hover {
    background-color: var(--ds-hover);
}

.dtp table.dtp-picker-days td a.selected,
.dtp table.dtp-picker-days td.selected > a,
.dtp table.dtp-picker-days td > a.selected {
    background-color: var(--primary) !important;
    color: #fff !important;
    font-weight: 600;
}

/* Vendor renders unavailable days as a plain span */
.dtp table.dtp-picker-days td > span:not(.dtp-select-day) {
    color: color-mix(in srgb, var(--text-muted) 55%, transparent);
}

/* Year picker list */
.dtp .dtp-picker-year,
.dtp .dtp-select-year-range {
    color: var(--text-primary);
}

.dtp .dtp-select-year-range li,
.dtp .dtp-picker-year li {
    padding: var(--space-2);
    border-radius: var(--radius-sm);
    font-size: var(--ds-text-body);
    cursor: pointer;
}

.dtp .dtp-select-year-range li:hover {
    background-color: var(--ds-hover);
}

.dtp .dtp-select-year-range li.year-selected,
.dtp .dtp-picker-year li.selected {
    background-color: var(--primary);
    color: #fff;
    font-weight: 600;
}

/* Analog clock face */
.dtp-picker-time .dtp-actual-meridien a,
.dtp .dtp-meridien-am,
.dtp .dtp-meridien-pm {
    border-radius: 999px;
    padding: var(--space-1) var(--space-3);
    font-weight: 600;
    color: var(--text-muted);
    text-decoration: none;
}

.dtp .dtp-meridien-am.selected,
.dtp .dtp-meridien-pm.selected {
    background-color: var(--primary);
    color: #fff;
}

/* Analog clock face — the vendor builds this as inline SVG and sets every
   color as a *presentation attribute* from JS, with NO state classes: the
   selected hour and the active hand are identified only by their literal
   attribute value (#8BC34A Material green). So the hooks below are attribute
   selectors on those exact values. Any CSS rule beats a presentation
   attribute, so `fill`/`stroke` here win cleanly.

   Do NOT broaden these to `svg circle` — the number circles, the centre pin
   and the face are all <circle>, so one blanket fill flattens the clock.
   Verified against bootstrap-material-datetimepicker.js lines 382-545. */
.dtp .dtp-picker-time circle[fill="#eee"] {      /* r=192 dial face      */
    fill: var(--surface-muted);
}

.dtp .dtp-picker-time circle[stroke="#bdbdbd"] { /* dial outline         */
    stroke: var(--border);
}

.dtp .dtp-picker-time circle[fill="#757575"] {   /* r=15 centre pin      */
    fill: var(--primary);
}

.dtp .dtp-picker-time circle[fill="#8BC34A"] {   /* selected hour/minute */
    fill: var(--primary);
}

.dtp .dtp-picker-time line[stroke="#8BC34A"] {   /* the ACTIVE hand      */
    stroke: var(--primary);
}

.dtp .dtp-picker-time line[stroke="#bdbdbd"] {   /* the inactive hand    */
    stroke: var(--border-hover);
}

.dtp .dtp-picker-time text[fill="#000"] {        /* unselected numerals  */
    fill: var(--text-primary);
}

.dtp .dtp-picker-time text {
    font-family: var(--ds-font);
}

/* Footer buttons — vendor uses flat text buttons */
.dtp .dtp-buttons {
    padding: var(--space-3) var(--space-4);
    border-top: 1px solid var(--border);
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    background-color: var(--surface-elevated);
}

.dtp .dtp-buttons .dtp-btn-cancel,
.dtp .dtp-buttons .dtp-btn-ok,
.dtp .dtp-buttons .dtp-btn-clear {
    border-radius: var(--radius-md);
    padding: var(--space-2) var(--space-4);
    font-weight: 600;
    font-size: var(--ds-text-body);
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease);
}

.dtp .dtp-buttons .dtp-btn-cancel:hover,
.dtp .dtp-buttons .dtp-btn-clear:hover {
    background-color: var(--ds-hover);
    color: var(--text-primary);
}

.dtp .dtp-buttons .dtp-btn-ok {
    background-color: var(--primary);
    color: #fff;
}

.dtp .dtp-buttons .dtp-btn-ok:hover {
    background-color: var(--primary-hover);
}

/* Vendor's fullscreen scrim */
.dtp > .dtp-content ~ div,
.dtp.hidden { /* no-op guard: keeps vendor visibility logic intact */ }

/* ------------------------------------------------------------------ 7c.
   jQuery UI datepicker (.ui-datepicker) — jquery-ui.css is loaded globally,
   so its theme leaks into any view that calls .datepicker()
   ------------------------------------------------------------------ */
.ui-datepicker {
    font-family: var(--ds-font);
    font-size: var(--ds-text-body);
    background: var(--surface-elevated);
    border: 1px solid var(--border);
    border-radius: var(--cal-panel-radius);
    box-shadow: var(--shadow-lg);
    padding: var(--space-2);
    width: auto;
    min-width: 260px;
    animation: ds-pop-in var(--duration) var(--ease);
}

.ui-datepicker .ui-datepicker-header {
    background: transparent;
    border: none;
    color: var(--text-primary);
    font-weight: 600;
    padding: var(--space-2);
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.ui-datepicker .ui-datepicker-title {
    margin: 0;
    line-height: 1;
    font-size: var(--ds-text-body);
    font-weight: 600;
    order: 2;
}

.ui-datepicker .ui-datepicker-prev,
.ui-datepicker .ui-datepicker-next {
    position: static;
    top: auto;
    inset-inline: auto;
    width: 30px;
    height: 30px;
    border: none;
    background: transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease);
}

.ui-datepicker .ui-datepicker-prev { order: 1; }
.ui-datepicker .ui-datepicker-next { order: 3; }

.ui-datepicker .ui-datepicker-prev:hover,
.ui-datepicker .ui-datepicker-next:hover {
    background: var(--ds-hover);
    border: none;
    top: auto;
}

.ui-datepicker .ui-datepicker-title select {
    height: var(--control-height-sm);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text-primary);
    margin: 0 2px;
    padding: 0 var(--space-1);
}

.ui-datepicker table {
    margin: 0;
    border-collapse: separate;
    border-spacing: 2px;
    font-size: var(--ds-text-body);
}

.ui-datepicker th {
    font-size: var(--ds-text-caption);
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: .03em;
    border: none;
    padding: var(--space-1) 0;
}

.ui-datepicker td {
    padding: 0;
    border: none;
    width: var(--cal-cell);
    height: var(--cal-cell);
}

.ui-datepicker td span,
.ui-datepicker td a,
.ui-datepicker .ui-state-default {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--cal-cell);
    height: var(--cal-cell);
    padding: 0;
    border: none;
    background: transparent;
    border-radius: var(--cal-radius);
    color: var(--text-primary);
    font-weight: 500;
    text-align: center;
    transition: background-color var(--duration-fast) var(--ease),
                color var(--duration-fast) var(--ease);
}

.ui-datepicker .ui-state-hover,
.ui-datepicker td a:hover {
    background: var(--ds-hover);
    border: none;
    color: var(--text-primary);
}

.ui-datepicker .ui-state-active,
.ui-datepicker td.ui-datepicker-current-day .ui-state-default {
    background: var(--primary);
    border: none;
    color: #fff;
    font-weight: 600;
}

.ui-datepicker td.ui-datepicker-today .ui-state-default:not(.ui-state-active) {
    box-shadow: inset 0 0 0 1.5px var(--primary);
    color: var(--primary);
    font-weight: 700;
    background: transparent;
}

.ui-datepicker .ui-state-disabled,
.ui-datepicker td.ui-datepicker-unselectable .ui-state-default {
    opacity: 1;
    color: color-mix(in srgb, var(--text-muted) 50%, transparent);
}

.ui-datepicker .ui-datepicker-buttonpane {
    border-top: 1px solid var(--border);
    margin: var(--space-2) 0 0;
    padding: var(--space-2);
}

.ui-datepicker .ui-datepicker-buttonpane button {
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text-primary);
    padding: var(--space-1) var(--space-3);
    font-weight: 600;
    cursor: pointer;
}

.ui-datepicker .ui-datepicker-buttonpane button:hover {
    background: var(--surface-muted);
    border-color: var(--border-hover);
}

/* ------------------------------------------------------------------ 7d.
   Native <input type="date"> / "datetime-local" / "time" / "month"
   The dropdown panel itself is drawn by the OS and is not styleable; the
   control, and the picker-indicator button, are.
   ------------------------------------------------------------------ */
input[type="date"].form-control,
input[type="datetime-local"].form-control,
input[type="time"].form-control,
input[type="month"].form-control,
input[type="week"].form-control {
    cursor: pointer;
}
/* Note: deliberately NOT `display: flex` here. It is a common trick to
   re-center the value once forms.css pins the height, but it reaches into
   WebKit's date-input shadow DOM and reorders the y/m/d segments on some
   versions. Vertical centring is left to the browser. */

/* forms.css gives the indicator padding + a circular gray hover; make it a
   themed rounded target that also works in dark mode (where a #eee hover
   would be near-invisible against a dark control). */
input::-webkit-calendar-picker-indicator {
    padding: 4px;
    margin-inline-start: var(--space-1);
    border-radius: var(--radius-sm);
    cursor: pointer;
    opacity: .55;
    transition: background-color var(--duration-fast) var(--ease),
                opacity var(--duration-fast) var(--ease);
}

input::-webkit-calendar-picker-indicator:hover {
    background-color: var(--ds-hover);
    border-radius: var(--radius-sm);
    opacity: 1;
}

input::-webkit-calendar-picker-indicator:focus-visible {
    outline: none;
    box-shadow: var(--ring);
    opacity: 1;
}

/* Placeholder-ish segments (yyyy/mm/dd) before a value is entered */
input[type="date"]::-webkit-datetime-edit-text,
input[type="datetime-local"]::-webkit-datetime-edit-text {
    color: var(--text-muted);
    padding: 0 1px;
}

input[type="date"]:invalid::-webkit-datetime-edit,
input[type="datetime-local"]:invalid::-webkit-datetime-edit {
    color: var(--text-muted);
}

/* Popup animation shared by 7a and 7c */
@keyframes ds-pop-in {
    from { opacity: 0; transform: translateY(-4px) scale(.98); }
    to   { opacity: 1; transform: translateY(0)    scale(1); }
}


/* ==========================================================================
   7z. PAGE CONTAINER — #partIcon
   ==========================================================================
   Across roughly 46 views (Selling, Items, Purchase, etc.) every page wraps
   its ENTIRE content in `<div id="partIcon" class="…" style="padding:…">` —
   an app-wide layout convention despite the misleading name. It never had a
   surface treatment: the wrapper painted no background/border/shadow of its
   own, so its content sat directly on the page background at the same
   color. On a dashboard that otherwise groups content into cards, that read
   as "flat / unstyled", which is what prompted this section (see the Selling
   page screenshot this was diagnosed from).

   Scoped to the id, not `.card` — do NOT rename this to `.card`, several of
   the 46 views nest real `.card` widgets (stat carousels, etc.) *inside*
   #partIcon, and turning the id itself into a full `.card` alias would
   double-frame those.

   Deliberately additive only: background/border/radius/shadow/margin. Never
   sets `padding` — every view already sets its own inline
   `style="padding:Npx"` on this element (10–12px, occasionally a `p-2` /
   `ml-1 mr-1 mt-2` utility-class variant), and an inline style always wins
   specificity over any external stylesheet rule, so overriding it here
   would need `!important`. Not touching the property avoids that fight
   entirely, and keeps each page's own density choice intact. */
#partIcon {
    margin: var(--space-4);
    background-color: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

@media (max-width: 575.98px) {
    /* Full-bleed on phones — a card inset on both sides wastes the small
       viewport's width on a border it can't clearly render anyway. */
    #partIcon {
        margin: var(--space-2);
        border-radius: var(--radius-md);
    }
}


/* ==========================================================================
   8. CARDS
   ==========================================================================
   cards.css already delivers the 16px radius / subtle border / soft shadow /
   consistent padding and the stat-card family. Only two gaps are closed:
   the hover lift firing on non-interactive cards, and header/footer layout.
   ========================================================================== */

/* cards.css raises the shadow on ANY .card:hover, which makes static content
   cards feel clickable. Restrict the lift to cards that actually are. */
.card:hover {
    box-shadow: var(--shadow-sm);
}

.card.ds-card-interactive:hover,
a.card:hover,
.card[role="button"]:hover,
.card[onclick]:hover {
    box-shadow: var(--shadow-md);
    border-color: var(--border-hover);
}

.card.ds-card-interactive,
a.card,
.card[role="button"] {
    cursor: pointer;
    text-decoration: none;
}

.card-header {
    color: var(--text-primary);
    font-size: var(--ds-text-card-title);
}

.card-footer {
    color: var(--text-muted);
}

/* Header/footer as a flex row (title + trailing action or dropdown) is
   OPT-IN, not the default. Bootstrap's .card-header/.card-footer are block,
   and flipping them globally would re-flow any of the 452 views whose header
   stacks block children or mixes a text node with an inline element —
   anonymous flex items would break the wrapping. Add the class where wanted:
     <div class="card-header ds-row">…</div> */
.card-header.ds-row,
.card-footer.ds-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
}

/* A header holding nav tabs needs the tabs flush to the bottom edge. */
.card-header:has(> .nav-tabs) {
    padding-bottom: 0;
}

/* Bootstrap's rounding does not reach a table/list-group flush against the
   card edge, so the corners clip square over the 16px radius. */
.card > .table:last-child,
.card > .table-responsive:last-child,
.card > .list-group:last-child {
    border-bottom-left-radius: inherit;
    border-bottom-right-radius: inherit;
    overflow: hidden;
    margin-bottom: 0;
}

.list-group-item {
    background-color: var(--surface);
    border-color: var(--border);
    color: var(--text-primary);
}


/* ==========================================================================
   9. MODALS & DROPDOWNS
   ==========================================================================
   modals.css sets the base radius/shadow/padding; dropdowns.css sets the
   menu surface. This section layers a Glass Morphism treatment on top of
   Bootstrap's modal — panel/backdrop/header/footer/close-button/form-control
   surfaces and the open/close animation — entirely via CSS (no JS, markup,
   IDs, classes or data attributes touched, so every existing modal trigger,
   focus trap, keyboard handler and business-logic script keeps working
   unmodified). Dark-mode variants of the component tokens below live in
   section 12, next to every other [data-bs-theme="dark"] override.
   ========================================================================== */

/* -- Modal / dialog: glass panel ---------------------------------------- */
.modal-content {
    /* Component tokens — light-mode defaults. Dark-mode re-declares these
       under [data-bs-theme="dark"] in section 12 rather than duplicating the
       rules that consume them here. Opacity bands follow the design brief:
       light 75-90%, dark 70-85%. */
    --modal-surface-1: color-mix(in srgb, var(--surface) 90%, transparent);
    --modal-surface-2: color-mix(in srgb, var(--surface) 80%, transparent);
    --modal-border: color-mix(in srgb, #fff 35%, var(--border));
    --modal-highlight: inset 0 1px 0 rgba(255, 255, 255, .3);
    --modal-shadow-1: 0 20px 60px rgba(15, 23, 42, .15);
    --modal-shadow-2: 0 8px 20px rgba(15, 23, 42, .08);

    background: linear-gradient(180deg, var(--modal-surface-1), var(--modal-surface-2));
    border: 1px solid var(--modal-border);
    border-radius: var(--radius-xl);
    box-shadow: var(--modal-shadow-1), var(--modal-shadow-2), var(--modal-highlight);
    /* Conservative blur (spec: 20px target, 24px ceiling, never past 30px) +
       a touch of saturation so colors behind the panel don't wash out grey —
       the classic "frosted glass" look instead of a milky overlay. */
    backdrop-filter: blur(20px) saturate(1.3);
    -webkit-backdrop-filter: blur(20px) saturate(1.3);
    background-clip: padding-box;
}

/* Backdrop blur is the single most recognizable part of a Radix/Shadcn
   dialog. backdrop-filter is GPU-composited (unlike filter: blur on the
   content), and is skipped entirely under reduced-motion/low-end paths in
   section 12. Kept as a single neutral-slate tint for both themes — a dimmed
   scrim reads correctly regardless of the page underneath; only its density
   changes under dark mode (section 12), not its hue. */
.modal-backdrop {
    background-color: rgba(15, 23, 42, .45);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}

.modal-backdrop.show {
    opacity: 1; /* the alpha now lives in the color, not the opacity */
}

/* Zoom + rise entry, replacing Bootstrap's slide-down. modals.css transitions
   .modal-dialog; this only changes the start/end transform + timing (spec:
   180-220ms, scale .97 -> 1, translateY 8px -> 0). */
.modal.fade .modal-dialog {
    transform: scale(.97) translateY(8px);
    transition: transform 200ms var(--ease),
                opacity 200ms var(--ease);
    opacity: 0;
}

.modal.show .modal-dialog {
    transform: scale(1) translateY(0);
    opacity: 1;
}

/* Header/footer get a faint muted tint distinct from the plain glass body —
   same "bar reads as its own shelf" treatment Shadcn/Linear/Notion use
   (bg-muted/50 in Shadcn's own dialog footer), instead of sitting flush at
   the same shade as the content between them. color-mix over `transparent`
   (not a flat surface color) keeps it layered on top of the existing glass
   gradient rather than replacing it, so blur/translucency still show through. */
.modal-header {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-5) var(--space-6);
    background: color-mix(in srgb, var(--surface-muted) 45%, transparent);
    border-bottom: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
}

.modal-title {
    font-size: 1.125rem;
    font-weight: 600;
    letter-spacing: -0.025em;
    line-height: 1.2;
    color: var(--text-primary);
}

/* Close ("×") button — every modal/offcanvas/toast/alert dismiss control in
   the app. Bootstrap's own .btn-close paints its X via a fixed-hex data-URI
   `background-image` (invisible in dark mode unless .btn-close-white is
   added per instance), which can't be recolored with a CSS variable. Instead
   of layering a background-color under that fixed-color image, the image is
   dropped entirely (`background-image: none`) and the X is redrawn as a
   `::before` shape via `mask-image` — same glyph, but now paints in
   `currentColor`, so it stays correct under any theme/accent without a
   dark-mode filter hack. Neutral (not danger-tinted) to match a plain
   dismiss affordance rather than implying a destructive action. Single
   change here reskins every dismiss control across all views — no
   per-modal markup edits needed. */
.btn-close {
    position: relative;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background-color: color-mix(in srgb, var(--text-muted) 16%, transparent);
    background-image: none;
    border: 1px solid color-mix(in srgb, var(--text-muted) 30%, transparent);
    color: var(--text-muted);
    opacity: 1;
    padding: 0;
    box-shadow: 0 1px 2px rgba(15, 23, 42, .06);
    transition: background-color 200ms var(--ease),
                border-color 200ms var(--ease),
                box-shadow 200ms var(--ease),
                transform 200ms var(--ease);
}

.btn-close::before {
    content: "";
    position: absolute;
    inset: 0;
    margin: auto;
    width: 10px;
    height: 10px;
    display: block;
    background-color: currentColor;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3E%3C/svg%3E");
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
}

/* A handful of legacy modals render their own `<i class="fas fa-times">` or
   `<span aria-hidden="true">&times;</span>` inside .btn-close on top of
   Bootstrap's icon (pre-dating this reskin). Hide it so it doesn't double up
   with (and visually enlarge/blur) the ::before glyph above. */
.btn-close i,
.btn-close span {
    display: none;
}

.btn-close:hover {
    background-color: color-mix(in srgb, var(--text-muted) 28%, transparent);
    border-color: color-mix(in srgb, var(--text-muted) 25%, transparent);
    color: var(--surface);
    box-shadow: 0 3px 8px color-mix(in srgb, var(--text-muted) 20%, transparent);
    transform: scale(1.06);
}

.btn-close:active {
    transform: scale(.94);
    transition-duration: 100ms;
}

.btn-close:focus {
    box-shadow: 0 1px 2px rgba(15, 23, 42, .06);
}

.btn-close:focus-visible {
    box-shadow: var(--ring);
}

.modal-body {
    padding: var(--space-6);
    color: var(--text-primary);
    line-height: 1.6;
}

/* Section grouping — bare <fieldset>/<legend> inside any modal body, no
   .ds-form-section/.ds-form-section-title class required. forms.css already
   offers those classes for pages that opt in explicitly; this is the same
   look applied as the modal default so the ~30 existing modals that just use
   plain <div class="form-group"> rows (no fieldset at all) are unaffected,
   but any modal that DOES group fields with <fieldset><legend> picks up the
   Pharmacy Setting modal's icon-led, uppercase divider styling for free. */
.modal-body fieldset {
    border: none;
    padding: 0 0 var(--space-5);
    margin: 0 0 var(--space-5);
    min-width: 0;
}

.modal-body fieldset:last-of-type {
    padding-bottom: 0;
    margin-bottom: 0;
}

.modal-body legend {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    float: none;
    margin: var(--space-4) 0 var(--space-3);
    padding-bottom: var(--space-2);
    border-bottom: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
    font-size: .8125rem;
    font-weight: 700;
    color: var(--text-primary);
    text-transform: uppercase;
    letter-spacing: .03em;
}

.modal-body legend:first-child {
    margin-top: 0;
}

.modal-body legend i {
    color: var(--primary);
    font-size: .875rem;
}

.modal-footer {
    gap: var(--space-2);
    padding: var(--space-4) var(--space-6) var(--space-5);
    background: color-mix(in srgb, var(--surface-muted) 45%, transparent);
    border-top: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
}

/* Bootstrap adds margin to every footer child on top of the gap. */
.modal-footer > * {
    margin: 0;
}

/* Equal-height, evenly-spaced action row by default; stacks full-width
   below the smallest breakpoint instead of wrapping mid-row. */
.modal-footer {
    flex-wrap: wrap;
    align-items: center;
}

@media (max-width: 575.98px) {
    .modal-header {
        padding: var(--space-4) var(--space-5);
    }

    .modal-body {
        padding: var(--space-4) var(--space-5);
    }

    .modal-footer {
        flex-direction: column;
        align-items: stretch;
        padding: var(--space-4) var(--space-5);
    }

    .modal-footer > * {
        width: 100%;
    }
}

/* -- Glass form controls, scoped to modal content ------------------------
   Semi-transparent surface so controls read as part of the glass panel
   instead of opaque cutouts; the focus ring stays the shared --ring token
   set in section 4 (already avoids the browser-default blue glow) — only
   the resting surface changes here, nothing focus-related is touched. */
.modal-body .form-control,
.modal-body .form-select,
.modal-body textarea.form-control {
    background-color: color-mix(in srgb, var(--surface) 70%, transparent);
    border-color: color-mix(in srgb, var(--border) 85%, transparent);
}

.modal-body .form-control:focus,
.modal-body .form-select:focus {
    background-color: var(--surface);
}

.modal-body .select2-container--default .select2-selection--single,
.modal-body .select2-container--default .select2-selection--multiple {
    background-color: color-mix(in srgb, var(--surface) 70%, transparent) !important;
}

/* -- 9b. Modal — sticky scroll, density, mobile bottom sheet -------------
   Width presets and the title/description grouping live in modals.css
   (no cascade conflict there). These three pieces DO need to win the
   cascade over the rules above in this same section (the entry animation,
   the glass surface, the header/footer padding), which is why they're here
   instead. */

/* .modal-dialog-scrollable already makes .modal-content a flex column with
   .modal-body as the only scrolling child (Bootstrap's own mechanism) — so
   header/footer just need position:sticky, not a rewrite of that layout. */
.modal-dialog-scrollable .modal-header {
    position: sticky;
    top: 0;
    z-index: 1;
}

.modal-dialog-scrollable .modal-footer {
    position: sticky;
    bottom: 0;
    z-index: 1;
}

/* Density (Theme Settings → Density: comfortable/compact) reaches every
   other control's padding via --control-* tokens already; .modal-header/
   -body/-footer padding is hardcoded space-5/-6 above and never followed
   density until now. */
[data-ds-density="compact"] .modal-header {
    padding: var(--space-4) var(--space-5);
}

[data-ds-density="compact"] .modal-body {
    padding: var(--space-5);
}

[data-ds-density="compact"] .modal-footer {
    padding: var(--space-3) var(--space-5) var(--space-4);
}

/* Mobile bottom sheet (<768px) — overrides the zoom+rise entry above with a
   slide-up-from-bottom, and pins the dialog to the viewport's bottom edge
   instead of Bootstrap's centered/margin-auto placement. */
@media (max-width: 767.98px) {
    .modal-dialog {
        margin: 0;
        min-height: 100dvh;
        display: flex;
        align-items: flex-end;
    }

    .modal-content {
        width: 100%;
        max-height: 92dvh;
        border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    }

    .modal.fade .modal-dialog {
        transform: translateY(100%);
    }

    .modal.show .modal-dialog {
        transform: translateY(0);
    }

    /* .modal-dialog-scrollable already caps .modal-content at 100% of its
       flex parent; re-cap against the sheet's own max-height so long
       content scrolls inside the sheet instead of overflowing the sheet
       past the 92dvh ceiling above. */
    .modal-dialog-scrollable .modal-content {
        max-height: 92dvh;
    }
}

/* -- Dropdown ---------------------------------------------------------- */
.dropdown-menu.show {
    animation: ds-pop-in var(--duration) var(--ease);
}

.dropdown-menu {
    /* dropdowns.css sets surface/radius/shadow/padding; add the offset and
       a scroll cap for the long option lists in this app. */
    margin-top: var(--space-1);
    max-height: min(420px, 60vh);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-weight: 500;
    transition: background-color var(--duration-fast) var(--ease);
}

.dropdown-item:active {
    background-color: var(--ds-active);
    color: var(--text-primary);
}

.dropdown-item.active {
    background-color: var(--ds-active);
    color: var(--primary);
    font-weight: 600;
}

.dropdown-item:focus-visible {
    outline: none;
    box-shadow: var(--ring);
}

.dropdown-item.disabled,
.dropdown-item:disabled {
    color: var(--text-muted);
    opacity: .6;
}

.dropdown-divider {
    border-top-color: var(--border);
    margin: var(--space-1) 0;
}

.dropdown-header {
    font-size: var(--ds-text-caption);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-muted);
    padding: var(--space-2) var(--space-3) var(--space-1);
}

/* Search-ready: a sticky filter input at the top of a menu.
   Usage: <li class="dropdown-search"><input class="form-control form-control-sm"></li>
   Wiring the filtering itself stays with the view's own JS. */
.dropdown-search {
    position: sticky;
    top: calc(var(--space-2) * -1);
    z-index: 1;
    background-color: var(--surface);
    padding: var(--space-1) var(--space-1) var(--space-2);
    margin: calc(var(--space-2) * -1) calc(var(--space-2) * -1) var(--space-1);
    border-bottom: 1px solid var(--border);
}

/* Bootstrap's caret is a CSS triangle; a chevron matches the .form-select
   indicator from section 5. */
.dropdown-toggle::after {
    width: .4em;
    height: .4em;
    border: none;
    border-inline-end: 1.75px solid currentColor;
    border-bottom: 1.75px solid currentColor;
    transform: rotate(45deg) translateY(-2px);
    vertical-align: middle;
    margin-inline-start: var(--space-2);
    transition: transform var(--duration-fast) var(--ease);
}

.dropdown-toggle.show::after {
    transform: rotate(225deg) translateY(-2px);
}

/* -- Offcanvas / tooltips / popovers (same surface family) ------------- */
.offcanvas {
    background-color: var(--surface);
    color: var(--text-primary);
    border-color: var(--border);
}

.tooltip-inner {
    background-color: var(--ds-tooltip-bg);
    color: var(--ds-tooltip-text);
    border-radius: var(--radius-sm);
    padding: var(--space-1) var(--space-2);
    font-size: var(--ds-text-caption);
    font-weight: 500;
    box-shadow: var(--shadow-md);
}

.tooltip .tooltip-arrow::before {
    border-top-color: var(--ds-tooltip-bg);
    border-bottom-color: var(--ds-tooltip-bg);
    border-left-color: var(--ds-tooltip-bg);
    border-right-color: var(--ds-tooltip-bg);
}

.popover {
    background-color: var(--surface-elevated);
    border-color: var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    font-family: var(--ds-font);
}

.popover-header {
    background-color: transparent;
    border-bottom-color: var(--border);
    color: var(--text-primary);
    font-weight: 600;
}

.popover-body {
    color: var(--text-primary);
}


/* ==========================================================================
   10. TABLES
   ==========================================================================
   tables.css owns the table + mvc-grid theming and is correct. Only the
   pieces it does not cover are added: the sticky-header background (a
   transparent sticky header lets rows show through as they scroll under
   it — a visible bug wherever .table-sticky-header or the mvc-grid's own
   position:sticky header is used), and striped/bordered token wiring.
   ========================================================================== */

.table-sticky-header thead th,
.mvc-grid thead tr:nth-child(1) th {
    background-color: var(--surface-muted);
    background-clip: padding-box;
}

/* Bootstrap's striping is a hardcoded rgba(emphasis-color, .05) layer.
   Retune it through --bs-table-striped-bg, the variable Bootstrap itself
   reads, rather than setting background-color on the cells: 5.3 paints
   stripe/hover/active as ONE `box-shadow: inset ... var(--bs-table-bg-state,
   var(--bs-table-bg-type, ...))` layer, so a direct cell background would sit
   on top of it and kill row hover on every odd row of a striped table. */
.table {
    --bs-table-striped-bg: var(--surface-muted);
    --bs-table-striped-color: var(--text-primary);
    --bs-table-hover-bg: var(--ds-hover);
    --bs-table-hover-color: var(--text-primary);
    --bs-table-active-bg: var(--ds-active);
    --bs-table-active-color: var(--text-primary);
}

/* Contextual row classes (.table-danger/-success/-warning/-info, e.g. an
   IsLoss row on Views/Accountant/OfferSelling/_OfferReportGrid.cshtml) ship
   from bootstrap.min.css with a hardcoded `--bs-table-color: #000` and a
   light pastel `--bs-table-bg` — no [data-bs-theme="dark"] variant exists in
   this vendor version at all. On the app's dark theme that forces black text
   onto an already-dark row, unreadable regardless of which background wins
   the row (Bootstrap's own --bs-table-bg mechanism, or a utility class like
   bg-danger/bg-opacity-10 layered on top of it). Re-pointed at the same
   translucent --ds-*-bg tokens (already light/dark-aware, matching the
   validation-state styling used elsewhere) with normal readable text instead
   of a hardcoded color. */
.table-danger {
    /* --ds-danger-bg alone (18% in dark mode) read as barely-there once text
       stayed the normal readable color instead of white — mixed with more of
       the base --ds-danger hue directly for a clearly visible "flagged" tint
       that still isn't saturated enough to fight text legibility. */
    --bs-table-bg: color-mix(in srgb, var(--ds-danger) 28%, var(--ds-danger-bg));
    --bs-table-color: var(--text-primary);
    --bs-table-striped-bg: color-mix(in srgb, var(--ds-danger) 36%, var(--ds-danger-bg));
    --bs-table-hover-bg: color-mix(in srgb, var(--ds-danger) 42%, var(--ds-danger-bg));
    color: var(--text-primary);
}

.table-success {
    --bs-table-bg: var(--ds-success-bg);
    --bs-table-color: var(--text-primary);
    --bs-table-striped-bg: color-mix(in srgb, var(--ds-success) 8%, var(--ds-success-bg));
    --bs-table-hover-bg: color-mix(in srgb, var(--ds-success) 12%, var(--ds-success-bg));
    color: var(--text-primary);
}

.table-warning {
    --bs-table-bg: var(--ds-warning-bg);
    --bs-table-color: var(--text-primary);
    --bs-table-striped-bg: color-mix(in srgb, var(--ds-warning) 8%, var(--ds-warning-bg));
    --bs-table-hover-bg: color-mix(in srgb, var(--ds-warning) 12%, var(--ds-warning-bg));
    color: var(--text-primary);
}

/* No dedicated --ds-info-bg/--ds-secondary-bg tokens exist yet — derived the
   same translucent-tint way instead of adding a hardcoded pastel. */
.table-info {
    --bs-table-bg: color-mix(in srgb, var(--ds-info) 15%, var(--surface));
    --bs-table-color: var(--text-primary);
    --bs-table-striped-bg: color-mix(in srgb, var(--ds-info) 22%, var(--surface));
    --bs-table-hover-bg: color-mix(in srgb, var(--ds-info) 28%, var(--surface));
    color: var(--text-primary);
}

.table-bordered,
.table-bordered > :not(caption) > * > * {
    border-color: var(--border);
}

.table > :not(:last-child) > :last-child > * {
    border-bottom-color: var(--border);
}

/* Row hover should not fight a .table-active/selected row. */
.table-hover > tbody > tr.active:hover,
.table-hover > tbody > tr.table-active:hover {
    background-color: var(--ds-active);
}

.table-active > * {
    background-color: var(--ds-active);
    color: var(--text-primary);
}

/* Horizontal scroll container should not clip the card radius or show a
   heavy native scrollbar. */
.table-responsive {
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}

/* Empty-cell and caption polish */
.table caption {
    color: var(--text-muted);
    font-size: var(--ds-text-caption);
    padding: var(--space-3) var(--space-4);
}


/* ==========================================================================
   11. NAVIGATION, ALERTS, BADGES, ACCORDION
   ==========================================================================
   shell.css owns the sidebar and navbar. Everything in this section was
   previously unstyled Bootstrap default: tabs, pills, breadcrumb,
   pagination detail, alerts (17 views), progress, and the accordion.
   ========================================================================== */

/* -- Tabs — Shadcn underline style ------------------------------------- */
.nav-tabs {
    border-bottom: 1px solid var(--border);
    gap: var(--space-1);
}

.nav-tabs .nav-link {
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    color: var(--text-muted);
    font-weight: 600;
    font-size: var(--ds-text-body);
    padding: var(--space-3) var(--space-4);
    margin-bottom: -1px;
    background: transparent;
    transition: color var(--duration-fast) var(--ease),
                border-color var(--duration-fast) var(--ease);
}

.nav-tabs .nav-link:hover {
    color: var(--text-primary);
    border-bottom-color: var(--border-hover);
    isolation: auto;
}

.nav-tabs .nav-link.active {
    color: var(--primary);
    background: transparent;
    border-bottom-color: var(--primary);
}

.nav-tabs .nav-link:focus-visible {
    outline: none;
    box-shadow: var(--ring);
    border-radius: var(--radius-sm);
}

.nav-tabs .nav-link.disabled {
    color: var(--text-muted);
    opacity: .5;
}

/* -- Pills — Shadcn segmented control --------------------------------- */
.nav-pills {
    gap: var(--space-1);
    padding: var(--space-1);
}

.nav-pills .nav-link {
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    font-weight: 600;
    font-size: var(--ds-text-body);
    padding: var(--space-2) var(--space-4);
    transition: background-color var(--duration-fast) var(--ease),
                color var(--duration-fast) var(--ease);
}

.nav-pills .nav-link:hover:not(.active) {
    background-color: var(--ds-hover);
    color: var(--text-primary);
}

.nav-pills .nav-link.active,
.nav-pills .show > .nav-link {
    background-color: var(--primary);
    color: #fff;
    box-shadow: var(--shadow-xs);
}

.nav-pills .nav-link:focus-visible {
    outline: none;
    box-shadow: var(--ring);
}

/* Opt-in enclosed segmented group: <ul class="nav nav-pills nav-segmented"> */
.nav-segmented {
    background-color: var(--surface-muted);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    display: inline-flex;
}

.nav-segmented .nav-link.active {
    background-color: var(--surface);
    color: var(--text-primary);
    box-shadow: var(--shadow-sm);
}

.tab-content {
    padding-top: var(--space-4);
}

/* -- Pagination -------------------------------------------------------- */
.pagination {
    gap: 2px;
}

.pagination .page-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--control-height-sm);
    height: var(--control-height-sm);
    padding: 0 var(--space-2);
    font-size: var(--ds-text-body);
    font-weight: 500;
    background-color: transparent;
    border-color: transparent;
    transition: background-color var(--duration-fast) var(--ease),
                color var(--duration-fast) var(--ease);
}

.pagination .page-link:hover {
    background-color: var(--ds-hover);
    color: var(--text-primary);
    border-color: transparent;
}

.pagination .page-link:focus {
    box-shadow: none;
}

.pagination .page-link:focus-visible {
    box-shadow: var(--ring);
    outline: none;
}

.pagination .page-item.active .page-link {
    color: #fff;
    font-weight: 600;
}

.pagination .page-item.disabled .page-link {
    color: var(--text-muted);
    opacity: .5;
    background-color: transparent;
    border-color: transparent;
}

/* -- Breadcrumb -------------------------------------------------------- */
.breadcrumb {
    font-size: var(--ds-text-caption);
    margin-bottom: 0;
    gap: var(--space-1);
}

.breadcrumb-item,
.breadcrumb-item > a {
    color: var(--text-muted);
    text-decoration: none;
    font-weight: 500;
}

.breadcrumb-item > a:hover {
    color: var(--primary);
}

.breadcrumb-item.active {
    color: var(--text-primary);
    font-weight: 600;
}

.breadcrumb-item + .breadcrumb-item::before {
    color: color-mix(in srgb, var(--text-muted) 60%, transparent);
}

/* -- Alerts (17 views, previously stock Bootstrap) --------------------
   Shadcn treats an alert as a bordered surface with a colored accent and
   icon, not a saturated pastel block. Left border + tinted background keeps
   it recognizable while matching the rest of the system. */
.alert {
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    border-inline-start-width: 3px;
    padding: var(--space-4);
    font-size: var(--ds-text-body);
    color: var(--text-primary);
    background-color: var(--surface);
    box-shadow: var(--shadow-xs);
}

/* Icon + content as a flex row is OPT-IN via an explicit .alert-icon child.
   `.alert` itself stays block: most of the 17 existing alerts are a text node
   with an inline <a> or <strong>, and making the container flex would turn
   each into a separate anonymous flex item — breaking the sentence into
   gapped fragments. Usage:
     <div class="alert alert-warning">
       <i class="alert-icon bi bi-exclamation-triangle"></i>
       <div>Stock is below the reorder point.</div>
     </div> */
.alert:has(> .alert-icon) {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
}

.alert > .alert-icon {
    flex: 0 0 auto;
    margin-top: .1em;
    font-size: 1.05em;
    line-height: 1.45;
}

.alert-heading {
    font-size: var(--ds-text-body);
    font-weight: 700;
    color: inherit;
    margin-bottom: var(--space-1);
}

.alert p:last-child,
.alert ul:last-child {
    margin-bottom: 0;
}

.alert .alert-link {
    color: inherit;
    font-weight: 700;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.alert-success { background-color: var(--ds-success-bg); border-color: color-mix(in srgb, var(--success) 25%, transparent); border-inline-start-color: var(--success); }
.alert-danger  { background-color: var(--ds-danger-bg);  border-color: color-mix(in srgb, var(--danger) 25%, transparent);  border-inline-start-color: var(--danger); }
.alert-warning { background-color: var(--ds-warning-bg); border-color: color-mix(in srgb, var(--warning) 25%, transparent); border-inline-start-color: var(--warning); }
.alert-info,
.alert-primary { background-color: var(--ds-active);     border-color: color-mix(in srgb, var(--primary) 25%, transparent); border-inline-start-color: var(--primary); }

/* Scoped to the opt-in .alert-icon rather than any descendant <i>, so an
   inline icon inside the alert's body text keeps its own color. */
.alert-success > .alert-icon, .alert-success .alert-heading { color: var(--success); }
.alert-danger  > .alert-icon, .alert-danger .alert-heading  { color: var(--danger); }
.alert-warning > .alert-icon, .alert-warning .alert-heading { color: var(--warning); }
.alert-info    > .alert-icon, .alert-primary > .alert-icon,
.alert-info .alert-heading, .alert-primary .alert-heading   { color: var(--primary); }

.alert-secondary,
.alert-light,
.alert-dark {
    background-color: var(--surface-muted);
    border-inline-start-color: var(--border-hover);
}

.alert-dismissible {
    padding-inline-end: var(--space-6);
}

.alert-dismissible .btn-close {
    padding: var(--space-3);
}

/* -- Badges ------------------------------------------------------------
   dropdowns.css gives .badge a radius/weight/padding. Shadcn badges are
   pills with tinted (not saturated) fills; the token-driven variants below
   also fix dark mode, where bg-warning + white text is unreadable.

   border-radius follows --radius-sm (the Corner Radius theme setting) by
   default — this used to be a hardcoded 999px pill that ignored the theme
   setting entirely (dropdowns.css already had the correct var(--radius-sm),
   but this rule loads last and won the cascade). A true pill shape is
   still available, opt-in, via the "Pill" Corner Radius preset itself
   (theme-settings.css), which forces .badge to 999px when chosen. */
.badge {
    border-radius: var(--radius-sm);
    font-size: var(--ds-text-caption);
    font-weight: 600;
    padding: .3em .7em;
    line-height: 1.45;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    vertical-align: middle;
}

.badge.rounded-0,
.badge.rounded,
.badge.rounded-1 {
    border-radius: var(--radius-sm);
}

/* Bootstrap's own escape hatch for an explicit full pill, independent of
   the Corner Radius theme setting. */
.badge.rounded-pill {
    border-radius: 999px;
}

/* Soft variants — opt-in, and also applied to the plain bg-* utilities that
   badges in this app already use, so existing markup gains them for free. */
.badge.bg-success,
.badge.text-bg-success { background-color: var(--ds-success-bg) !important; color: var(--success) !important; }
.badge.bg-danger,
.badge.text-bg-danger  { background-color: var(--ds-danger-bg) !important;  color: var(--danger) !important; }
.badge.bg-warning,
.badge.text-bg-warning { background-color: var(--ds-warning-bg) !important; color: var(--warning) !important; }
.badge.bg-info,
.badge.text-bg-info,
.badge.bg-primary,
.badge.text-bg-primary { background-color: var(--ds-active) !important;     color: var(--primary) !important; }
.badge.bg-secondary,
.badge.text-bg-secondary,
.badge.bg-light,
.badge.text-bg-light   { background-color: var(--surface-muted) !important; color: var(--text-muted) !important; }

/* Bootstrap 4-era ".badge-success"/".badge-info"/etc. naming — 27+ views
   still render badges this way instead of the bg-*/text-bg-* utilities
   above. Those class names have no matching rule anywhere this app
   actually loads (Zephyr.css/style.css define them, but aren't linked on
   most pages), so every one of those badges rendered with zero background/
   color. Aliased here instead of touching every call site. */
.badge.badge-success { background-color: var(--ds-success-bg) !important; color: var(--success) !important; }
.badge.badge-danger   { background-color: var(--ds-danger-bg) !important;  color: var(--danger) !important; }
.badge.badge-warning  { background-color: var(--ds-warning-bg) !important; color: var(--warning) !important; }
.badge.badge-info,
.badge.badge-primary  { background-color: var(--ds-active) !important;     color: var(--primary) !important; }
.badge.badge-secondary,
.badge.badge-light    { background-color: var(--surface-muted) !important; color: var(--text-muted) !important; }
.badge.badge-dark      { background-color: var(--ds-text) !important;      color: var(--ds-surface) !important; }

/* Solid variants stay available for emphasis: .badge.badge-solid.bg-danger */
.badge.badge-solid.bg-success { background-color: var(--success) !important; color: #fff !important; }
.badge.badge-solid.bg-danger  { background-color: var(--danger) !important;  color: #fff !important; }
.badge.badge-solid.bg-warning { background-color: var(--warning) !important; color: #fff !important; }
.badge.badge-solid.bg-primary { background-color: var(--primary) !important; color: #fff !important; }

/* -- Accordion --------------------------------------------------------
   No view uses .accordion today; styled so the first one that does gets the
   design language for free rather than shipping stock Bootstrap. */
.accordion {
    --bs-accordion-bg: var(--surface);
    --bs-accordion-color: var(--text-primary);
    --bs-accordion-border-color: var(--border);
    --bs-accordion-border-radius: var(--radius-lg);
    --bs-accordion-inner-border-radius: calc(var(--radius-lg) - 1px);
    --bs-accordion-btn-color: var(--text-primary);
    --bs-accordion-btn-bg: transparent;
    --bs-accordion-active-color: var(--primary);
    --bs-accordion-active-bg: var(--ds-hover);
    --bs-accordion-btn-focus-box-shadow: var(--ring);
    --bs-accordion-transition: none; /* replaced below with the shared ease */
}

.accordion-item {
    background-color: var(--surface);
    border-color: var(--border);
}

.accordion-button {
    font-weight: 600;
    font-size: var(--ds-text-body);
    padding: var(--space-4) var(--space-5);
    box-shadow: none;
    transition: background-color var(--duration-fast) var(--ease),
                color var(--duration-fast) var(--ease);
}

.accordion-button:not(.collapsed) {
    box-shadow: none;
}

.accordion-button:focus {
    box-shadow: none;
    border-color: var(--border);
}

.accordion-button:focus-visible {
    box-shadow: var(--ring);
    outline: none;
}

/* Bootstrap's chevron is a fixed-hex data-URI (same dark-mode problem as
   .btn-close). Draw it with borders instead so it follows currentColor and
   needs no per-theme override. */
.accordion-button::after {
    background-image: none;
    width: .45em;
    height: .45em;
    border: none;
    border-inline-end: 1.75px solid currentColor;
    border-bottom: 1.75px solid currentColor;
    transform: rotate(45deg);
    margin-top: -.2em;
    flex-shrink: 0;
    transition: transform var(--duration) var(--ease);
}

.accordion-button:not(.collapsed)::after {
    transform: rotate(225deg);
    margin-top: .1em;
}

.accordion-body {
    padding: var(--space-4) var(--space-5);
    color: var(--text-primary);
}

.accordion-collapse {
    transition: height var(--duration-slow) var(--ease);
}

/* -- Progress ---------------------------------------------------------- */
.progress {
    background-color: var(--surface-muted);
    border-radius: 999px;
    height: 8px;
}

.progress-bar {
    background-color: var(--primary);
    border-radius: 999px;
    transition: width var(--duration-slow) var(--ease);
}

/* -- Spinners ---------------------------------------------------------- */
.spinner-border,
.spinner-grow {
    color: var(--primary);
}

/* -- Close button on toasts/alerts in dark mode: see section 12 -------- */


/* ==========================================================================
   11z. BUTTON GROUPS, LIST GROUPS, CLIENT VALIDATION
   ==========================================================================
   A literal pass over every top-level class Bootstrap ships (not just the
   ones already touched), cross-checked against real usage in this app.
   These three were genuine, real-usage gaps at 0% Shadcn treatment:
     .btn-group / .btn-group-vertical / .btn-toolbar  — 23 views, toolbar
       action rows, still rendering as stock double-bordered Bootstrap
       segments (the classic "still looks like Bootstrap" tell).
     .list-group / .list-group-flush / .list-group-item-action — 3-4 views
       (receipt/summary rows).
     .was-validated (HTML5 constraint-validation pseudo-classes) — 5 views,
       previously only the server-rendered .is-invalid/.is-valid path was
       themed; the client-side :invalid/:valid path Bootstrap actually
       triggers via `form.classList.add('was-validated')` was not.
   Everything else in Bootstrap's class list with zero real usage in this
   codebase (carousel, offcanvas, navbar-dark, dropend/dropstart/dropup,
   card-img-*, focus-ring-*, form-floating, placeholder-*, …) is
   intentionally left alone — theming markup nothing in the app renders
   would be dead CSS, not a fix.
   ========================================================================== */

/* -- Button groups — Shadcn segmented control ---------------------------
   Bootstrap's own .btn-group already removes the double border via negative
   margin + border-radius resets on non-edge buttons; what it does NOT do is
   flatten the group to read as one control. Add the enclosing surface. */
.btn-group,
.btn-group-vertical {
    box-shadow: var(--shadow-xs);
    border-radius: var(--radius-md);
}

/* Edge-only rounding so the Corner Radius setting (sharp/default/round)
   still reads as ONE continuous segmented control — squaring the touching
   sides Bootstrap's own negative-margin overlap trick assumes, instead of
   the flat var(--radius-md) this used to apply to every member (which made
   each button look like its own separate rounded pill). Pill mode has its
   own !important fixup below since it needs 999px caps, not var(--radius-md). */
.btn-group > .btn,
.btn-group-vertical > .btn {
    border-radius: 0;
}

.btn-group > .btn:first-child {
    border-start-start-radius: var(--radius-md);
    border-end-start-radius: var(--radius-md);
}

.btn-group > .btn:last-child {
    border-start-end-radius: var(--radius-md);
    border-end-end-radius: var(--radius-md);
}

.btn-group-vertical > .btn:first-child {
    border-start-start-radius: var(--radius-md);
    border-start-end-radius: var(--radius-md);
}

.btn-group-vertical > .btn:last-child {
    border-end-start-radius: var(--radius-md);
    border-end-end-radius: var(--radius-md);
}

/* Members keep their own semantic color (btn-primary/outline/etc.) except
   for the plain unstyled case (no color modifier at all), which is what all
   4 usage patterns in this app actually are — a neutral segmented toolbar,
   not colored per-button. */
.btn-group > .btn:not([class*="btn-outline"]):not([class*="btn-primary"]):not([class*="btn-secondary"]):not([class*="btn-success"]):not([class*="btn-danger"]):not([class*="btn-warning"]):not([class*="btn-info"]):not([class*="btn-light"]):not([class*="btn-dark"]):not([class*="btn-link"]) {
    background-color: var(--surface);
    border-color: var(--border);
    color: var(--text-primary);
}

.btn-group > .btn:hover:not([class*="btn-outline"]):not([class*="btn-primary"]):not([class*="btn-secondary"]):not([class*="btn-success"]):not([class*="btn-danger"]):not([class*="btn-warning"]):not([class*="btn-info"]):not([class*="btn-light"]):not([class*="btn-dark"]):not([class*="btn-link"]) {
    background-color: var(--surface-muted);
    color: var(--text-primary);
}

.btn-group > .btn.active,
.btn-group > .btn:not(:disabled):not(.disabled).active {
    background-color: var(--primary);
    border-color: var(--primary);
    color: #fff;
}

.btn-toolbar {
    gap: var(--space-2);
}

.btn-toolbar .btn-group + .btn-group {
    margin-inline-start: 0; /* toolbar gap replaces Bootstrap's ms-2 convention */
}

/* -- List group ---------------------------------------------------------
   Section 8 already tokens .list-group-item's bg/border. Add the
   surrounding surface (flush variant drops it, matching the app's actual
   usage as a borderless receipt/summary list), hover/active states, and
   the semantic contextual variants. */
.list-group {
    border-radius: var(--radius-md);
    overflow: hidden;
}

.list-group-flush {
    border-radius: 0;
}

.list-group-item-action:hover,
.list-group-item-action:focus {
    background-color: var(--ds-hover);
    color: var(--text-primary);
    z-index: 1;
}

.list-group-item-action:active {
    background-color: var(--ds-active);
}

.list-group-item.active {
    background-color: var(--primary);
    border-color: var(--primary);
    color: #fff;
}

.list-group-item:focus-visible {
    outline: none;
    box-shadow: var(--ring);
    z-index: 2;
    position: relative;
}

.list-group-item-success { background-color: var(--ds-success-bg); color: var(--success); }
.list-group-item-danger  { background-color: var(--ds-danger-bg);  color: var(--danger); }
.list-group-item-warning { background-color: var(--ds-warning-bg); color: var(--warning); }
.list-group-item-info,
.list-group-item-primary { background-color: var(--ds-active);     color: var(--primary); }

/* -- Client-side (HTML5 constraint validation) form feedback ------------
   forms.css / this file theme the SERVER-rendered .is-invalid/.is-valid
   classes. Bootstrap's `.was-validated` class (added by this app's own
   `form.classList.add('was-validated')` on submit, e.g. Selling's forms)
   instead drives the *browser's* :invalid/:valid pseudo-classes directly —
   a separate selector path with no token styling until now. */
.was-validated .form-control:invalid,
.was-validated .form-select:invalid {
    border-color: var(--danger);
}

.was-validated .form-control:invalid:focus,
.was-validated .form-select:invalid:focus {
    box-shadow: 0 0 0 var(--ring-width) var(--ds-danger-bg);
}

.was-validated .form-control:valid,
.was-validated .form-select:valid {
    border-color: var(--success);
}

.was-validated .form-control:valid:focus,
.was-validated .form-select:valid:focus {
    box-shadow: 0 0 0 var(--ring-width) var(--ds-success-bg);
}

.was-validated .form-check-input:invalid {
    border-color: var(--danger);
}

.was-validated .form-check-input:invalid:checked {
    background-color: var(--danger);
    border-color: var(--danger);
}

/* Bootstrap only shows :invalid/:valid feedback text via a sibling-selector
   trick tied to the same pseudo-classes; route its color through tokens to
   match the is-invalid/is-valid path already themed in forms.css. */
.was-validated :invalid ~ .invalid-feedback,
.was-validated :invalid ~ .invalid-tooltip {
    color: var(--danger);
}

.was-validated :valid ~ .valid-feedback,
.was-validated :valid ~ .valid-tooltip {
    color: var(--success);
}

/* -- Small completions found in the same literal sweep ------------------- */
.table-sm td,
.table-sm th {
    padding: var(--space-2) var(--space-3);
}

.img-thumbnail {
    background-color: var(--surface);
    border-color: var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-1);
}

.card-link {
    color: var(--primary);
    font-weight: 600;
    text-decoration: none;
}

.card-link:hover {
    color: var(--primary-hover);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.card-link + .card-link {
    margin-inline-start: var(--space-4);
}


/* ==========================================================================
   12. DARK MODE, ACCESSIBILITY, MOTION
   ==========================================================================
   The app themes via Bootstrap's own [data-bs-theme="dark"] attribute (set
   by js/theme-settings.js), and tokens.css already redefines the whole
   --ds-* palette under it — so every rule above is dark-mode-correct
   automatically through the alias layer.

   What still needs explicit handling is the small set of things that CANNOT
   follow a CSS variable: vendor data-URI images with baked-in hex colors,
   and pure-white hardcoded values inside third-party widgets.

   NOTE on the selector: [data-theme] is ALSO matched below because the
   design brief specifies that attribute name. This app sets data-bs-theme;
   both are accepted so either convention works and neither silently no-ops.
   ========================================================================== */

[data-theme="dark"] {
    color-scheme: dark;
}

[data-bs-theme="dark"],
[data-theme="dark"] {
    /* Slightly stronger ring on dark surfaces, where a 35% tint reads faint */
    --ring-color: color-mix(in srgb, var(--ds-primary) 50%, transparent);
    --border-hover: color-mix(in srgb, #fff 22%, var(--ds-border));
    --text-secondary: color-mix(in srgb, var(--ds-text) 78%, var(--ds-bg));

    /* Native form controls (date inputs, selects, scrollbars) render their
       OS chrome light-on-light without this. */
    color-scheme: dark;
}

/* Select caret — stroke is baked into the data-URI, so it needs one
   re-declaration with the dark muted color (#9095ab = dark --ds-text-muted). */
[data-bs-theme="dark"] .form-select,
[data-theme="dark"] .form-select {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%239095ab' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M4 6l4 4 4-4'/%3e%3c/svg%3e");
}

/* Glass modal — same component tokens .modal-content declares in section 9,
   re-declared directly on .modal-content (not just the html/body ancestor)
   because a variable an element sets on itself always wins over one it would
   otherwise inherit — an ancestor-only override here would silently no-op.
   Denser/darker than the light defaults so the panel still reads as
   elevated glass against an already-dark page instead of disappearing into
   it (opacity band 70-85% per the brief); shadow swaps to near-black since
   a slate-900 shadow is invisible on a dark background. */
[data-bs-theme="dark"] .modal-content,
[data-theme="dark"] .modal-content {
    --modal-surface-1: color-mix(in srgb, var(--surface) 82%, transparent);
    --modal-surface-2: color-mix(in srgb, var(--surface) 72%, transparent);
    --modal-border: color-mix(in srgb, #fff 12%, var(--border));
    --modal-highlight: inset 0 1px 0 rgba(255, 255, 255, .06);
    --modal-shadow-1: 0 20px 60px rgba(0, 0, 0, .55);
    --modal-shadow-2: 0 8px 20px rgba(0, 0, 0, .35);
}

[data-bs-theme="dark"] .modal-backdrop,
[data-theme="dark"] .modal-backdrop {
    background-color: rgba(2, 6, 16, .6);
}

/* Native calendar picker indicator is a dark glyph. */
[data-bs-theme="dark"] input::-webkit-calendar-picker-indicator,
[data-theme="dark"] input::-webkit-calendar-picker-indicator {
    filter: invert(1) brightness(1.6);
}

/* Bootstrap ships a dark-mode thumb override that swaps in a 25%-white
   translucent dot for the unchecked state. Our thumb is an opaque disc in
   both themes (it sits on a dark track, so it must stay light) — restate it
   so Bootstrap's dark rule doesn't win on the unchecked switch. */
[data-bs-theme="dark"] .form-switch .form-check-input:not(:checked):not(:focus),
[data-theme="dark"] .form-switch .form-check-input:not(:checked):not(:focus) {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23cbd5e1'/%3e%3c/svg%3e");
}

/* Vendor date pickers hardcode #fff / #ddd / #000 in several places. */
[data-bs-theme="dark"] .daterangepicker,
[data-theme="dark"] .daterangepicker,
[data-bs-theme="dark"] .daterangepicker .calendar-table,
[data-theme="dark"] .daterangepicker .calendar-table {
    background-color: var(--surface-elevated);
    border-color: var(--border);
    color: var(--text-primary);
}

[data-bs-theme="dark"] .dtp > .dtp-content,
[data-theme="dark"] .dtp > .dtp-content,
[data-bs-theme="dark"] .ui-datepicker,
[data-theme="dark"] .ui-datepicker {
    background-color: var(--surface-elevated);
    color: var(--text-primary);
}

/* jQuery UI ships its own light theme with hardcoded backgrounds/colors on
   these state classes; they are !important-free, but jquery-ui.css loads
   before this file so plain specificity is enough. */
[data-bs-theme="dark"] .ui-widget-content,
[data-theme="dark"] .ui-widget-content {
    background: var(--surface-elevated);
    color: var(--text-primary);
    border-color: var(--border);
}

[data-bs-theme="dark"] .ui-widget-header,
[data-theme="dark"] .ui-widget-header {
    background: transparent;
    color: var(--text-primary);
    border-color: var(--border);
}

/* Toastr — themed in toastr.css for light; the surface needs remapping. */
[data-bs-theme="dark"] #toast-container > div,
[data-theme="dark"] #toast-container > div {
    box-shadow: var(--shadow-lg);
}

/* Skeleton shimmer is a white gradient — invisible-to-wrong on dark. */
[data-bs-theme="dark"] .skeleton::after,
[data-bs-theme="dark"] .skeleton-text::after,
[data-bs-theme="dark"] .skeleton-card::after,
[data-theme="dark"] .skeleton::after,
[data-theme="dark"] .skeleton-text::after,
[data-theme="dark"] .skeleton-card::after {
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .07), transparent);
}

/* -- Accessibility ----------------------------------------------------
   utilities.css declares a 2px outline focus ring on a broad element list.
   That stays as the fallback; this unifies the ring for every component
   this file touches and adds the elements it missed (textarea, summary,
   [tabindex], role=button, contenteditable, and the nav/tab/menu items).
   -------------------------------------------------------------------- */
textarea:focus-visible,
summary:focus-visible,
[tabindex]:not([tabindex="-1"]):focus-visible,
[role="button"]:focus-visible,
[contenteditable="true"]:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* Never remove a focus indicator without replacing it — this catches the
   `outline: none` that several legacy views set inline/in their own CSS. */
:focus-visible {
    outline-color: var(--primary);
}

/* Screen-reader-only helper (Bootstrap has .visually-hidden; this is the
   older name still used in a few views). */
.sr-only:not(:focus):not(:active) {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Skip-link target: give any anchored heading breathing room under the
   sticky navbar so keyboard/anchor navigation doesn't land under it. */
:target {
    scroll-margin-top: calc(var(--space-7) + var(--space-5));
}

/* Minimum hit target for icon-only controls (WCAG 2.5.8 -> 24x24). */
.btn-icon,
.ds-row-action,
.page-link,
.btn-close {
    min-width: 24px;
    min-height: 24px;
}


/* Scoped badge for the Items column — avoids the badge-light/badge-secondary
   color clashes between Zephyr.css, style.css and bootstrap-shadcn-theme.css,
   while still following the current theme (light/dark) via design tokens. */
.item-badge {
    background-color: var(--surface-muted, #E4E6EF) !important;
    color: var(--text-muted, #181C32) !important;
    border: 1px solid var(--border, #c4c8dc);
}


/* High-contrast / forced-colors mode: let the OS palette through rather
   than fighting it with our tokens. */
@media (forced-colors: active) {
    .btn,
    .form-control,
    .form-select,
    .card,
    .dropdown-menu,
    .modal-content {
        border: 1px solid ButtonBorder;
    }

    .form-check-input:checked {
        forced-color-adjust: none;
        background-color: Highlight;
    }
}

/* -- Motion -----------------------------------------------------------
   utilities.css already clamps all animation/transition durations under
   prefers-reduced-motion. Extend that to the transform/blur effects this
   file introduces, which a duration clamp alone does not neutralize (a
   0.01ms scale still lands on the final transform, but the entry offset
   and the backdrop blur are what actually cause discomfort).
   -------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .modal.fade .modal-dialog,
    .modal.show .modal-dialog {
        transform: none;
    }

    .modal-backdrop {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }

    .modal-content {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }

    .btn-close:hover,
    .btn-close:active {
        transform: none;
    }

    .dropdown-menu.show,
    .daterangepicker,
    .ui-datepicker {
        animation: none;
    }

    .btn:active {
        transform: none;
    }

    .stat-card:hover,
    .card.ds-card-interactive:hover {
        transform: none;
    }
}

/* Print — drop shadows/backgrounds that waste toner and hide text.
   tables.css owns the mvc-grid print rules; this covers the components
   added here. */
@media print {
    .card,
    .modal-content,
    .alert,
    .dropdown-menu {
        box-shadow: none !important;
        border: 1px solid #ccc !important;
    }

    /* The glass gradient/blur is a screen-only effect — print a plain white
       panel instead of whatever translucent tint the page background mixed
       into it. */
    .modal-content {
        background: #fff !important;
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
    }

    .btn {
        box-shadow: none !important;
    }
}
