/* ==========================================================================
   Atlas Design System  (ds-*)
   --------------------------------------------------------------------------
   The canonical UI vocabulary for Atlas pages. Spec: /docs/DESIGN_SYSTEM.md.

   This is a faithful extraction of the patterns proven in production on the
   CommunityManagement "Daily Weather Outlook" (#wx-dash) and "Market Scorecard"
   (#sc-dash) dashboards — same navy/coral palette, hairline-bordered cards,
   underline tabs, pill buttons and type scale — re-prefixed `ds-` and de-scoped
   so ANY page can use the classes without copying a <style> block.

   Namespacing is by class prefix (`ds-`), not by an #id ancestor, so rules are
   safe to load globally: they only touch elements that opt in with a ds- class.
   Wrap page content in `.ds-page` for the base text colour/context.
   ========================================================================== */

:root {
    --ds-navy: #0d1b2e;
    --ds-navy-light: #e8edf4;
    --ds-coral: #e8522a;
    --ds-coral-light: #fdf0eb;
    --ds-bg: #ffffff;
    --ds-bg2: #f4f5f7;
    --ds-text: #0d1b2e;
    --ds-text2: #5a6677;
    --ds-text3: #9aa3af;
    --ds-border: rgba(13, 27, 46, 0.09);   /* crisp hairline for lines/dividers */
    --ds-border2: rgba(13, 27, 46, 0.14);  /* soft structural border (cards, controls) */
    --ds-blue: #1a3356;
    --ds-green: #15803d;
    --ds-yellow: #eab308;
    --ds-red: #b91c1c;
    --ds-r-md: 6px;
    --ds-r-lg: 10px;
    /* Layered, low-opacity shadows — depth without weight (SmartAdmin-clean). */
    --ds-shadow: 0 1px 2px rgba(13, 27, 46, 0.04), 0 1px 3px rgba(13, 27, 46, 0.05);
    --ds-shadow-lift: 0 4px 14px rgba(13, 27, 46, 0.08);
}

/* Root wrapper — sets the page text colour and inherits the app font (Work Sans). */
.ds-page { color: var(--ds-text); }

/* Body copy + inline link — the readable prose defaults inside cards/sections. */
.ds-body { font-size: 14px; line-height: 1.6; color: var(--ds-text2); }
/* Lead — a prominent statement (e.g. a detail-page headline sentence). Larger
   than body and in the primary text colour so it carries visual weight. */
.ds-lead { font-size: 16px; line-height: 1.55; color: var(--ds-text); }
.ds-link {
    font-size: 13px;
    font-weight: 500;
    color: var(--ds-coral);
    text-decoration: none;
}
.ds-link:hover { color: var(--ds-coral); text-decoration: underline; }

/* --------------------------------------------------------------------------
   Breadcrumb — parent trail that reads as the top line of the page header.
   Rendered by the _Breadcrumbs partial from ViewData["Breadcrumbs"], which
   the layout places immediately before the page's .ds-page/.ds-header. The
   trail sits just above the header's icon/title with a little space below,
   and the following header's top padding is dropped so the two group as one
   block (the header has no background/top border, so this is visually the
   same as nesting the trail inside .ds-header). The "›" separator is a CSS
   ::before on every item after the first, so the markup is just a flat list.
   -------------------------------------------------------------------------- */
.ds-breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    margin-top: 1.25rem;   /* mirrors the header top padding it replaces, so page-top spacing matches non-breadcrumb pages */
    margin-bottom: 0.5rem; /* the "little space" between the trail and the icon/title */
}
/* When a trail precedes it, drop the header's own top padding so the icon/title
   sit directly under the breadcrumb (the trail now supplies the top spacing). */
.ds-breadcrumb + .ds-page > .ds-header { padding-top: 0; }
.ds-breadcrumb-item { color: var(--ds-text2); text-decoration: none; }
a.ds-breadcrumb-item { color: var(--ds-coral); }
a.ds-breadcrumb-item:hover { text-decoration: underline; }
.ds-breadcrumb-item.active { color: var(--ds-text); font-weight: 500; }
.ds-breadcrumb-item + .ds-breadcrumb-item::before {
    content: "\203A"; /* › */
    color: var(--ds-text3);
    margin-right: 8px;
}

/* --------------------------------------------------------------------------
   Header — coral icon tile + title + sub + right-aligned actions
   -------------------------------------------------------------------------- */
.ds-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    padding-bottom: 1.25rem;
    padding-top: 1.25rem;
    border-bottom: 1px solid var(--ds-border);
    margin-bottom: 1.5rem;
    gap: 1rem;
    flex-wrap: wrap;
}
.ds-header-left { display: flex; align-items: center; gap: 14px; }
.ds-header-icon {
    width: 40px;
    height: 40px;
    border-radius: var(--ds-r-md);
    background: var(--ds-coral-light);
    color: var(--ds-coral);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.ds-title { font-size: 20px; font-weight: 600; line-height: 1.2; }
.ds-sub { font-size: 12px; color: var(--ds-text2); margin-top: 3px; }
.ds-header-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* A year picker sitting in .ds-header-actions. Keeping the label beside the
   select rather than above it is what lets the buttons next to it align to the
   control: left as a block, `.ds-field`'s width:100% wraps the label onto its
   own line and the actions then centre against a two-row box. */
.year-form { display: flex; align-items: center; gap: 8px; }
.year-form label { font-weight: 500; color: var(--ds-text2); }
.year-form .ds-field { width: 110px; }

/* Pulsing "live" status pill (optional). */
.ds-live {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    font-weight: 500;
    color: var(--ds-coral);
    background: var(--ds-coral-light);
    border-radius: 20px;
    padding: 4px 12px;
    white-space: nowrap;
}
.ds-live::before {
    content: '';
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
    display: block;
    animation: dspulse 1.8s ease-in-out infinite;
}

/* --------------------------------------------------------------------------
   Tabs — underline style with coral active indicator
   -------------------------------------------------------------------------- */
.ds-tabs {
    display: flex;
    gap: 2px;
    margin-bottom: 1.5rem;
    border-bottom: 1px solid var(--ds-border);
    overflow-x: auto;
}
.ds-tab {
    font-size: 13px;
    font-weight: 500;
    padding: 8px 16px;
    cursor: pointer;
    border: none;
    background: none;
    color: var(--ds-text2);
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    white-space: nowrap;
    text-decoration: none;
}
.ds-tab:hover { color: var(--ds-text); }
.ds-tab.active { color: var(--ds-text); border-bottom-color: var(--ds-coral); background: none; }

/* Tabbed content panels. */
.ds-section { display: none; }
.ds-section.active { display: block; animation: dsfade 0.2s ease; }

/* Small uppercase tracked label that introduces a group of cards. */
.ds-section-label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.07em;
    color: var(--ds-text3);
    text-transform: uppercase;
    margin-bottom: 0.9rem;
}

/* --------------------------------------------------------------------------
   Card — the primary content container (replaces the legacy .panel stack)
   -------------------------------------------------------------------------- */
.ds-card {
    /* White surface, hairline border, layered soft shadow — depth without
       weight. Light-gray (--ds-bg2) is reserved for NESTED surfaces (sum
       tiles, hover/region rows) so they read cleanly inside a white card. */
    background: var(--ds-bg);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-r-lg);
    box-shadow: var(--ds-shadow);
    padding: 1.5rem;
    margin-bottom: 1.5rem;
}
.ds-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1rem;
    flex-wrap: wrap;
    gap: 8px;
}
.ds-card-title { font-size: 16px; font-weight: 600; }
/* Small muted meta text (counts, timestamps) beside a card title. */
.ds-stamp { font-size: 14px; color: var(--ds-text3); font-weight: 400; }

/* Card type logo — the canonical coral tile that brands a card by type.
   The ONE allowed treatment for card icons (Material Symbol on coral-light);
   same tile as .ds-header-icon, centred above the .ds-card-title. */
.ds-card-icon {
    width: 50px;
    height: 50px;
    border-radius: var(--ds-r-md);
    background: var(--ds-coral-light);
    color: var(--ds-coral);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    margin: 0 auto 0.85rem;
}

/* A card whose body is a flush data grid: kill the side padding so the grid
   meets the card edge. Pair with .ds-card-head outside / .ds-card-flush body. */
.ds-card-flush { padding-left: 0; padding-right: 0; padding-bottom: 0; }

/* --------------------------------------------------------------------------
   Media cards — responsive grid of clickable image tiles
   -------------------------------------------------------------------------- */
.ds-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 16px;
    margin-bottom: 1.75rem;
}
.ds-media-card {
    /* Resting surface mirrors .ds-card (white + hairline + soft shadow) so the
       clickable tiles read as the same card family; hover adds the lift/glow. */
    background: var(--ds-bg);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-r-lg);
    box-shadow: var(--ds-shadow);
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
    text-decoration: none;
    display: block;
    color: inherit;
}
.ds-media-card:hover {
    border-color: var(--ds-border2);
    transform: translateY(-2px);
    box-shadow: var(--ds-shadow-lift);
}
.ds-img-wrap {
    width: 100%;
    background: var(--ds-bg2);
    overflow: hidden;
    aspect-ratio: 4 / 3;
    display: flex;
    align-items: center;
}
.ds-img { width: 100%; display: block; object-fit: cover; }
.ds-media-label { padding: 9px 12px; font-size: 13px; font-weight: 500; }
.ds-media-sub { font-size: 11px; color: var(--ds-text2); margin-top: 2px; font-weight: 400; }

.ds-twocol { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 600px) { .ds-twocol { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------------------
   Summary stat tiles
   -------------------------------------------------------------------------- */
.ds-sum { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 1.5rem; }
.ds-sum-card {
    /* Light-gray nested surface so tiles read whether they sit on the white
       page or inside a white .ds-card. */
    background: var(--ds-bg2);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-r-md);
    padding: 0.85rem 1.15rem;
    min-width: 120px;
}
.ds-sum-card .ds-sum-value { font-size: 1.5rem; font-weight: 700; line-height: 1.15; }
.ds-sum-card .ds-sum-label { font-size: 11px; color: var(--ds-text3); text-transform: uppercase; letter-spacing: 0.05em; }

/* --------------------------------------------------------------------------
   Data grid — the standard table
   -------------------------------------------------------------------------- */
.ds-grid { width: 100%; border-collapse: collapse; }
.ds-grid th {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--ds-text3);
    white-space: nowrap;
    text-align: left;
    padding: 10px 14px;
    border-bottom: 1px solid var(--ds-border);
}
.ds-grid th a { color: inherit; text-decoration: none; }
.ds-grid th a:hover { color: var(--ds-text); }
.ds-grid td {
    font-size: 13px;
    color: var(--ds-text2);
    padding: 11px 14px;
    border-bottom: 1px solid var(--ds-border);
    vertical-align: middle;
}
.ds-grid tbody tr:last-child td { border-bottom: none; }
.ds-grid tbody tr:hover td { background: var(--ds-bg2); }
.ds-grid td.ds-strong, .ds-grid .ds-strong { color: var(--ds-text); font-weight: 500; }
/* Keep short atomic values (e.g. public IDs like DM-003) on one line — the hyphen
   would otherwise let them break across two lines in a narrow column. */
.ds-nowrap { white-space: nowrap; }
.ds-grid a { color: var(--ds-blue); text-decoration: none; }
.ds-grid a:hover { text-decoration: underline; }
/* Region/group header row + totals row. */
.ds-region td {
    background: var(--ds-bg2);
    font-weight: 600;
    font-size: 11px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--ds-text);
}
.ds-total td { border-top: 1px solid var(--ds-border2); font-weight: 600; color: var(--ds-text); }
/* Inactive / de-emphasised row. */
.ds-grid tr.ds-muted td { color: var(--ds-text3); }

/* --------------------------------------------------------------------------
   Pills & link rows
   -------------------------------------------------------------------------- */
.ds-linkrow { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 1.25rem; align-items: center; }
.ds-pill {
    font-size: 12px;
    color: var(--ds-blue);
    background: var(--ds-navy-light);
    border-radius: 20px;
    padding: 5px 14px;
    text-decoration: none;
    white-space: nowrap;
}
.ds-pill:hover { opacity: 0.75; color: var(--ds-blue); }

/* Navy-light status pill (non-link). */
.ds-status {
    display: inline-block;
    font-size: 11px;
    font-weight: 500;
    padding: 3px 10px;
    border-radius: 20px;
    background: var(--ds-navy-light);
    color: var(--ds-blue);
}

/* --------------------------------------------------------------------------
   Badges — inline category / type chips
   -------------------------------------------------------------------------- */
.ds-badge {
    display: inline-block;
    font-size: 11px;
    font-weight: 500;
    line-height: 1.4;
    padding: 2px 9px;
    border-radius: 6px;
    border: 1px solid transparent;
    white-space: nowrap;
}
.ds-badge-neutral { background: var(--ds-navy-light); color: var(--ds-blue); }
.ds-badge-success { background: #e7f3ec; color: var(--ds-green); border-color: rgba(21, 128, 61, 0.25); }
.ds-badge-info    { background: var(--ds-navy-light); color: var(--ds-blue); border-color: rgba(26, 51, 86, 0.2); }
.ds-badge-warning { background: #fdf5e3; color: #92690a; border-color: rgba(234, 179, 8, 0.3); }
.ds-badge-danger  { background: #fbeaea; color: var(--ds-red); border-color: rgba(185, 28, 28, 0.25); }
/* Solid orange — an emphasis pill (e.g. the "Preferred" vendor status). */
.ds-badge-orange  { background: #f97316; color: #fff; border-color: #ea580c; }

/* --------------------------------------------------------------------------
   Status dots + trend arrows
   -------------------------------------------------------------------------- */
.ds-dot {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    margin-right: 6px;
    vertical-align: middle;
}
.ds-green { background: var(--ds-green); }
.ds-yellow { background: var(--ds-yellow); }
.ds-red { background: var(--ds-red); }
.ds-up { color: var(--ds-green); }
.ds-down { color: var(--ds-red); }
.ds-flat { color: var(--ds-text3); }

/* --------------------------------------------------------------------------
   Buttons — pill shape; navy primary, hairline outline. Standalone (no
   Bootstrap dependency) so they render consistently anywhere.
   -------------------------------------------------------------------------- */
.ds-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
    border-radius: 20px;
    padding: 8px 16px;
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.15s, border-color 0.15s, opacity 0.15s, color 0.15s;
}
.ds-btn:disabled, .ds-btn.disabled { opacity: 0.5; cursor: default; pointer-events: none; }
.ds-btn .material-symbols-outlined { font-size: 18px; }

.ds-btn-primary { background: var(--ds-navy); border-color: var(--ds-navy); color: #fff; }
.ds-btn-primary:hover { opacity: 0.9; color: #fff; }

.ds-btn-outline { background: transparent; border-color: var(--ds-border2); color: var(--ds-navy); }
.ds-btn-outline:hover { background: var(--ds-navy); border-color: var(--ds-navy); color: #fff; }

/* Semantic variants — destructive (danger) and positive (success) actions. */
.ds-btn-danger { background: var(--ds-red); border-color: var(--ds-red); color: #fff; }
.ds-btn-danger:hover { opacity: 0.9; color: #fff; }
.ds-btn-success { background: var(--ds-green); border-color: var(--ds-green); color: #fff; }
.ds-btn-success:hover { opacity: 0.9; color: #fff; }
.ds-btn-outline-danger { background: transparent; border-color: var(--ds-red); color: var(--ds-red); }
.ds-btn-outline-danger:hover { background: var(--ds-red); border-color: var(--ds-red); color: #fff; }
.ds-btn-outline-success { background: transparent; border-color: var(--ds-green); color: var(--ds-green); }
.ds-btn-outline-success:hover { background: var(--ds-green); border-color: var(--ds-green); color: #fff; }

/* Text / ghost button — no fill or border for low-emphasis inline actions
   (dismiss, retire, merge). Colour comes from the element (or a semantic text
   utility like .text-danger); hover adds a faint wash for affordance. */
.ds-btn-text { background: transparent; border-color: transparent; color: inherit; }
.ds-btn-text:hover { background: var(--ds-bg2); }

.ds-btn-sm { font-size: 12px; padding: 5px 12px; }

/* Square-ish icon-only button (e.g. row actions). */
.ds-btn-icon {
    padding: 6px;
    width: 32px;
    height: 32px;
    border-radius: var(--ds-r-md);
    background: transparent;
    border: 1px solid var(--ds-border);
    color: var(--ds-text2);
}
.ds-btn-icon:hover { background: var(--ds-bg2); color: var(--ds-text); border-color: var(--ds-border2); }
.ds-btn-icon .material-symbols-outlined { font-size: 18px; }

/* A run of icon buttons sharing borders, like a segmented control. */
.ds-btn-group { display: inline-flex; gap: 4px; }

/* --------------------------------------------------------------------------
   Form fields — text inputs, selects, textareas
   `.ds-field` styles the control it's on (works for input / select / textarea).
   Pair with `.ds-label` for the field label. Add `.ds-field-sm` for compact
   rows. Width defaults to 100%; use a `w-auto` utility for inline pickers.
   -------------------------------------------------------------------------- */
.ds-label {
    display: block;
    font-size: 12px;
    font-weight: 500;
    color: var(--ds-text2);
    margin-bottom: 5px;
}

.ds-field {
    width: 100%;
    font-family: inherit;
    font-size: 13px;
    line-height: 1.4;
    color: var(--ds-text);
    background-color: var(--ds-bg);
    border: 1px solid var(--ds-border2);
    border-radius: var(--ds-r-md);
    padding: 8px 12px;
    transition: border-color 0.15s, box-shadow 0.15s;
    appearance: none;
    -webkit-appearance: none;
}
.ds-field::placeholder { color: var(--ds-text3); }
.ds-field:hover { border-color: var(--ds-text3); }
.ds-field:focus {
    outline: none;
    border-color: var(--ds-coral);
    box-shadow: 0 0 0 3px var(--ds-coral-light);
}
.ds-field:disabled,
.ds-field[readonly] {
    background-color: var(--ds-bg2);
    color: var(--ds-text3);
    cursor: not-allowed;
}

/* Selects get a custom chevron (appearance:none removed the native one). */
select.ds-field {
    padding-right: 34px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239aa3af' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 16px 16px;
    cursor: pointer;
}

textarea.ds-field { min-height: 78px; resize: vertical; }

/* Compact variant for dense toolbars / inline pickers. */
.ds-field-sm { font-size: 12px; padding: 5px 10px; }
select.ds-field-sm { padding-right: 30px; background-position: right 8px center; background-size: 14px 14px; }

/* File inputs — keep the field shell, but restyle the native "Choose file"
   button to match .ds-btn-outline so file pickers read as part of the system. */
input[type="file"].ds-field { padding: 5px 12px; line-height: 1.9; cursor: pointer; }
input[type="file"].ds-field::file-selector-button {
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    color: var(--ds-navy);
    background: transparent;
    border: 1px solid var(--ds-border2);
    border-radius: var(--ds-r-md);
    padding: 4px 12px;
    margin: 0 12px 0 0;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}
input[type="file"].ds-field::file-selector-button:hover {
    background: var(--ds-navy);
    border-color: var(--ds-navy);
    color: #fff;
}

/* Drag-and-drop file zone — a dashed target that wraps a hidden file input.
   Add `.dragover` (via JS) while a file is hovering for the coral highlight. */
.ds-dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    text-align: center;
    padding: 1.1rem 1rem;
    border: 1.5px dashed var(--ds-border2);
    border-radius: var(--ds-r-md);
    background: var(--ds-bg);
    color: var(--ds-text2);
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.ds-dropzone:hover { border-color: var(--ds-text3); }
.ds-dropzone.dragover {
    border-color: var(--ds-coral);
    background: var(--ds-coral-light);
    color: var(--ds-coral);
}
.ds-dropzone .material-symbols-outlined { font-size: 26px; color: var(--ds-text3); }
.ds-dropzone.dragover .material-symbols-outlined { color: var(--ds-coral); }
.ds-dropzone-hint { font-size: 12px; }

/* Checkbox / radio — tint to brand navy. */
.ds-check { width: 16px; height: 16px; accent-color: var(--ds-navy); vertical-align: middle; cursor: pointer; }

/* --------------------------------------------------------------------------
   Accordion — themes a Bootstrap accordion (`.accordion`) to the design system
   by remapping its `--bs-accordion-*` custom properties. Keeps Bootstrap's
   collapse behaviour; just add `ds-accordion` alongside `accordion`.
   -------------------------------------------------------------------------- */
.ds-accordion {
    --bs-accordion-bg: var(--ds-bg);
    --bs-accordion-color: var(--ds-text);
    --bs-accordion-border-color: var(--ds-border);
    --bs-accordion-border-radius: var(--ds-r-md);
    --bs-accordion-inner-border-radius: var(--ds-r-md);
    --bs-accordion-btn-color: var(--ds-text);
    --bs-accordion-btn-bg: var(--ds-bg);
    --bs-accordion-active-color: var(--ds-text);
    --bs-accordion-active-bg: var(--ds-bg2);
    --bs-accordion-btn-focus-border-color: var(--ds-coral);
    --bs-accordion-btn-focus-box-shadow: 0 0 0 3px var(--ds-coral-light);
    --bs-accordion-btn-padding-y: 10px;
    --bs-accordion-btn-padding-x: 14px;
    --bs-accordion-body-padding-y: 14px;
    --bs-accordion-body-padding-x: 14px;
}
.ds-accordion .accordion-item { margin-bottom: 8px; border: 1px solid var(--ds-border); border-radius: var(--ds-r-md); overflow: hidden; }
.ds-accordion .accordion-button { font-size: 13px; font-weight: 500; }
.ds-accordion .accordion-button:not(.collapsed) { box-shadow: none; }

/* --------------------------------------------------------------------------
   Modal — themes a Bootstrap modal to the design system. Add `ds-modal` to the
   `.modal-content` element; Bootstrap keeps its show/hide + backdrop behaviour.
   -------------------------------------------------------------------------- */
.ds-modal {
    background: var(--ds-bg);
    border: 1px solid var(--ds-border2);
    border-radius: var(--ds-r-lg);
    box-shadow: var(--ds-shadow-lift);
    color: var(--ds-text);
}
.ds-modal .modal-header,
.ds-modal .modal-footer { border-color: var(--ds-border); padding: 1rem 1.25rem; }
.ds-modal .modal-body { padding: 1.25rem; }
.ds-modal .modal-title { font-size: 16px; font-weight: 600; color: var(--ds-text); }

/* --------------------------------------------------------------------------
   States + footer note
   -------------------------------------------------------------------------- */
.ds-empty {
    padding: 2.5rem 1.25rem;
    text-align: center;
    color: var(--ds-text2);
    font-size: 13px;
}
.ds-empty .material-symbols-outlined { font-size: 40px; color: var(--ds-text3); display: block; margin: 0 auto 0.5rem; }
.ds-empty h4 { font-size: 15px; font-weight: 600; color: var(--ds-text); margin: 0 0 0.25rem; }
.ds-empty p { margin: 0; }

.ds-loading { padding: 1.5rem 0; text-align: center; color: var(--ds-text3); font-size: 13px; }
.ds-error { font-size: 13px; color: #a32d2d; padding: 0.5rem 0; }

/* "Updating…" badge + dimmed previous content (stale-while-revalidate). */
.ds-updating-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    font-weight: 500;
    color: var(--ds-coral);
    background: var(--ds-coral-light);
    border-radius: 20px;
    padding: 3px 10px;
    white-space: nowrap;
}
.ds-updating-badge svg { width: 12px; height: 12px; animation: dsspin 1s linear infinite; }
.ds-dimmed { opacity: 0.45; transition: opacity 0.2s; pointer-events: none; }

.ds-note {
    margin-top: 2rem;
    padding-top: 1rem;
    border-top: 1px solid var(--ds-border);
    font-size: 11px;
    color: var(--ds-text3);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

/* --------------------------------------------------------------------------
   Pagination — light, hairline
   -------------------------------------------------------------------------- */
.ds-pagination { display: flex; gap: 4px; list-style: none; padding: 0; margin: 1rem 0 0; flex-wrap: wrap; }
.ds-pagination a, .ds-pagination span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    height: 32px;
    padding: 0 8px;
    font-size: 13px;
    border-radius: var(--ds-r-md);
    border: 1px solid var(--ds-border);
    color: var(--ds-text2);
    text-decoration: none;
}
.ds-pagination a:hover { background: var(--ds-bg2); color: var(--ds-text); border-color: var(--ds-border2); }
.ds-pagination .active span, .ds-pagination .active a { background: var(--ds-navy); border-color: var(--ds-navy); color: #fff; }

/* --------------------------------------------------------------------------
   Animations
   -------------------------------------------------------------------------- */
@keyframes dspulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
@keyframes dsspin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes dsfade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* --------------------------------------------------------------------------
   Toasts — transient, stackable feedback for async actions (no page reload).
   Driven by window.dsToast(message, 'success' | 'error' | 'info') in site.js.
   A left accent stripe + tinted icon carries the semantic state at a glance.
   -------------------------------------------------------------------------- */
.ds-toast-host {
    position: fixed;
    top: 16px;
    right: 16px;
    z-index: 1090;
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: min(360px, calc(100vw - 32px));
    pointer-events: none;
}
.ds-toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    background: var(--ds-bg);
    border: 1px solid var(--ds-border2);
    border-left: 3px solid var(--ds-text3);
    border-radius: var(--ds-r-md);
    box-shadow: var(--ds-shadow-lift);
    padding: 11px 14px;
    font-size: 13px;
    line-height: 1.45;
    color: var(--ds-text);
    cursor: pointer;
    opacity: 0;
    transform: translateY(-6px);
    transition: opacity 0.18s ease, transform 0.18s ease;
}
.ds-toast.ds-toast-in { opacity: 1; transform: none; }
.ds-toast-icon { font-size: 20px; line-height: 1.1; flex-shrink: 0; }
.ds-toast-msg { padding-top: 1px; }
.ds-toast-success { border-left-color: var(--ds-green); }
.ds-toast-success .ds-toast-icon { color: var(--ds-green); }
.ds-toast-error { border-left-color: var(--ds-red); }
.ds-toast-error .ds-toast-icon { color: var(--ds-red); }
.ds-toast-info { border-left-color: var(--ds-coral); }
.ds-toast-info .ds-toast-icon { color: var(--ds-coral); }
@media (prefers-reduced-motion: reduce) {
    .ds-toast { transition: none; }
}

/* --------------------------------------------------------------------------
   Banners — page-level flash notices (TempData Success/Error). Keep Bootstrap's
   .alert + .alert-dismissible on the element so data-bs-dismiss="alert" and the
   .btn-close keep working; these classes only re-skin it with the ds tokens.
   -------------------------------------------------------------------------- */
.ds-banner {
    border: 1px solid var(--ds-border2);
    border-radius: var(--ds-r-md);
    background: var(--ds-bg2);
    color: var(--ds-text);
}
.ds-banner-success { background: #e7f3ec; border-color: rgba(21, 128, 61, 0.25); color: var(--ds-green); }
.ds-banner-danger  { background: #fbeaea; border-color: rgba(185, 28, 28, 0.25); color: var(--ds-red); }

/* --------------------------------------------------------------------------
   Print — drop the app chrome and interactive controls; keep content legible.
   `.ds-print-hide` opts any element out of print explicitly.
   -------------------------------------------------------------------------- */
@media print {
    .sidebar, .topbar, .ds-tabs, .ds-header-actions, .ds-btn, .ds-print-hide { display: none !important; }
    .main-content { margin: 0 !important; width: 100% !important; }
    main { padding: 0 !important; }
    .ds-card, .ds-media-card { box-shadow: none !important; border-color: var(--ds-border) !important; }
    .ds-grid th, .ds-grid td, .ds-region td, .ds-total td { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
