/* ==========================================================================
   DataMaker Design System
   Dark-first operator UI. Orange accent inherited from mono-tek-com.
   Layer this AFTER Bootstrap 5. No jQuery required.
   Reference: docs/DESIGN_SYSTEM.md
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Brand — same values as mono-tek-com so the family reads as one system */
  --dm-orange:        #FF9600;
  --dm-orange-hover:  #E08700;
  --dm-orange-glow:   rgba(255, 150, 0, 0.25);
  --dm-orange-soft:   rgba(255, 150, 0, 0.10);

  /* Surfaces, darkest to lightest */
  --dm-bg:            #0D1117;
  --dm-surface:       #161B22;
  --dm-surface-2:     #1C2128;
  --dm-surface-3:     #22272E;
  --dm-border:        #30363D;
  --dm-border-strong: #444C56;

  /* Text */
  --dm-text:          #E6EDF3;
  --dm-text-muted:    #8B949E;
  --dm-text-dim:      #6E7681;

  /* Semantic — all AA on --dm-surface */
  --dm-success:       #3FB950;
  --dm-warning:       #D29922;
  --dm-danger:        #F85149;
  --dm-info:          #58A6FF;
  --dm-success-bg:    rgba(63, 185, 80, 0.14);
  --dm-warning-bg:    rgba(210, 153, 34, 0.14);
  --dm-danger-bg:     rgba(248, 81, 73, 0.14);
  --dm-info-bg:       rgba(88, 166, 255, 0.14);

  /* Shape */
  --dm-radius:        12px;
  --dm-radius-sm:     8px;
  --dm-radius-xs:     6px;
  --dm-shadow:        0 8px 32px rgba(0, 0, 0, 0.28);
  --dm-shadow-lg:     0 16px 48px rgba(0, 0, 0, 0.40);

  /* Type */
  --dm-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --dm-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Motion — one duration, one curve. Consistency reads as quality. */
  --dm-ease: cubic-bezier(0.4, 0, 0.2, 1);
  --dm-fast: 140ms;
  --dm-med:  240ms;
  /* Progress indicators. --dm-spin is the ring's revolution; the -calm pair is what the same
     indicators run at under prefers-reduced-motion (#61): still moving, because "still working"
     is essential motion, but slow enough not to be the reason somebody turned the setting on. */
  --dm-spin:       0.62s;
  --dm-spin-calm:  1.6s;
  --dm-pulse-calm: 2s;

  /* Layout */
  --dm-sidebar-w: 232px;
  --dm-topbar-h:  56px;
}

@media (prefers-reduced-motion: reduce) {
  /* Decorative motion stops. Deliberately blanket, so a new entrance or shimmer is covered
     without anyone remembering to add it. */
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  /* #61: the five progress indicators are essential motion (WCAG 2.3.3 is about non-essential
     animation) and every one of them is animation-only, so the blanket above froze them on one
     frame -- a ring that "shows but doesn't spin", on a machine where GNOME's "Reduce
     animation" maps straight to this query. They keep moving, calmer: a slow revolution for the
     rings, and a low-amplitude opacity pulse instead of a bounce, a sweep or a slide. Same
     importance as the blanket, higher specificity, so these win. Every declaration here is
     !important, including animation-name: the base rules below use the `animation` shorthand,
     which also sets the name, and they come later in the file, so a plain longhand here loses
     to them. Measured on the deployed page 2026-09-20 -- the dots were still bouncing at 2s.
     A sixth animation-only indicator must be added here too -- test_ui_shell pins the five. */
  .dm-spinner {
    animation-duration: var(--dm-spin-calm) !important;
    animation-iteration-count: infinite !important;
  }
  .dm-btn.is-loading::after {
    animation-duration: var(--dm-spin-calm) !important;
    animation-iteration-count: infinite !important;
  }
  .dm-dots i {
    animation-name: dm-calm-pulse !important;
    animation-duration: var(--dm-pulse-calm) !important;
    animation-iteration-count: infinite !important;
  }
  .dm-loadbar::after {
    animation-name: dm-calm-pulse !important; width: 100% !important;
    animation-duration: var(--dm-pulse-calm) !important;
    animation-iteration-count: infinite !important;
  }
  .dm-skel {
    animation-name: dm-calm-pulse !important;
    animation-duration: var(--dm-pulse-calm) !important;
    animation-iteration-count: infinite !important;
  }
}
@keyframes dm-calm-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */

* { box-sizing: border-box; }

body {
  font-family: var(--dm-font);
  background: var(--dm-bg);
  color: var(--dm-text);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  margin: 0;
}

a { color: var(--dm-orange); text-decoration: none; }
a:hover { color: var(--dm-orange-hover); text-decoration: underline; }

code, kbd, pre, .dm-mono, .dm-num { font-family: var(--dm-mono); font-variant-numeric: tabular-nums; }

/* Every number in a table is tabular so columns align on the decimal. */
.dm-num { text-align: right; font-variant-numeric: tabular-nums; }

::selection { background: var(--dm-orange); color: var(--dm-bg); }

:focus-visible {
  outline: 2px solid var(--dm-orange);
  outline-offset: 2px;
  border-radius: var(--dm-radius-xs);
}

/* Scrollbars — dark, unobtrusive */
* { scrollbar-width: thin; scrollbar-color: var(--dm-border-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--dm-border-strong); border-radius: 6px; border: 2px solid var(--dm-bg); }
*::-webkit-scrollbar-thumb:hover { background: var(--dm-text-dim); }

/* --------------------------------------------------------------------------
   3. Shell — sidebar + topbar + content
   -------------------------------------------------------------------------- */

.dm-shell { display: grid; grid-template-columns: var(--dm-sidebar-w) 1fr; min-height: 100vh; }

.dm-sidebar {
  background: var(--dm-surface);
  border-right: 1px solid var(--dm-border);
  padding: 14px 10px;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}

.dm-brand {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px 16px;
  font-weight: 800; font-size: 1.05rem; letter-spacing: -0.01em;
  color: var(--dm-text);
  /* This is a link (it goes to the dashboard), but Bootstrap's underlined-link default made
     the wordmark read as a hyperlink. It is brand, not body copy. */
  text-decoration: none;
}
.dm-brand:hover { color: var(--dm-text); text-decoration: none; }
.dm-brand .dm-brand-mark { color: var(--dm-orange); display: inline-flex; align-items: center; }
.dm-brand .dm-brand-mark svg { width: 19px; height: 16px; display: block; }

.dm-nav-section {
  font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--dm-text-dim); padding: 14px 10px 5px;
}

.dm-nav-link {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 10px; border-radius: var(--dm-radius-sm);
  color: var(--dm-text-muted); font-weight: 500; font-size: 0.875rem;
  transition: background var(--dm-fast) var(--dm-ease), color var(--dm-fast) var(--dm-ease);
  text-decoration: none;
}
.dm-nav-link:hover { background: var(--dm-surface-2); color: var(--dm-text); text-decoration: none; }
.dm-nav-link.active {
  background: var(--dm-orange-soft); color: var(--dm-orange); font-weight: 600;
  box-shadow: inset 2px 0 0 var(--dm-orange);
}
.dm-nav-link .dm-nav-count {
  margin-left: auto; font-size: 0.72rem; color: var(--dm-text-dim);
  font-family: var(--dm-mono);
}

.dm-topbar {
  height: var(--dm-topbar-h);
  display: flex; align-items: center; gap: 14px;
  padding: 0 22px;
  border-bottom: 1px solid var(--dm-border);
  background: rgba(13, 17, 23, 0.86);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  position: sticky; top: 0; z-index: 20;
}
.dm-topbar h1 { font-size: 1rem; font-weight: 700; margin: 0; letter-spacing: -0.01em; }
.dm-topbar .dm-spacer { margin-left: auto; }

.dm-content { padding: 22px; max-width: 1600px; }

.dm-page-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 18px; flex-wrap: wrap; }
.dm-page-head h2 { font-size: 1.4rem; font-weight: 800; margin: 0 0 3px; letter-spacing: -0.02em; }
.dm-page-head p { color: var(--dm-text-muted); margin: 0; font-size: 0.875rem; }
.dm-page-head .dm-actions { margin-left: auto; display: flex; gap: 8px; }

@media (max-width: 900px) {
  .dm-shell { grid-template-columns: 1fr; }
  .dm-sidebar {
    position: fixed; inset: 0 auto 0 0; z-index: 50; width: var(--dm-sidebar-w);
    transform: translateX(-100%); transition: transform var(--dm-med) var(--dm-ease);
  }
  .dm-sidebar.open { transform: translateX(0); box-shadow: var(--dm-shadow-lg); }
  .dm-content { padding: 14px; }
}

/* --------------------------------------------------------------------------
   4. Cards & stats
   -------------------------------------------------------------------------- */

.dm-card {
  background: var(--dm-surface);
  border: 1px solid var(--dm-border);
  border-radius: var(--dm-radius);
  padding: 16px 18px;
}
.dm-card-head {
  display: flex; align-items: center; gap: 10px;
  margin: -16px -18px 14px; padding: 12px 18px;
  border-bottom: 1px solid var(--dm-border);
}
.dm-card-head h3 { font-size: 0.9rem; font-weight: 700; margin: 0; }
.dm-card-head .dm-spacer { margin-left: auto; }

/* T-39: every card collapses (data-dm-no-collapse opts out; see
   docs/DESIGN_SYSTEM.md). CSS-only -- a card's contents are hidden rather than
   re-parented, so a live form, a bound table or a <template> inside it survives
   the fold untouched. The bottom margin has to be cancelled too: .dm-card-head
   spans the card's own padding via a negative margin, and without this a
   collapsed card keeps a 14px gap under a border with nothing beneath it. */
.dm-card.is-collapsed > *:not(.dm-card-head) { display: none; }
.dm-card.is-collapsed > .dm-card-head { margin-bottom: -16px; border-bottom-color: transparent; }

.dm-stat-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.dm-stat {
  background: var(--dm-surface); border: 1px solid var(--dm-border);
  border-radius: var(--dm-radius); padding: 14px 16px;
  transition: border-color var(--dm-fast) var(--dm-ease), transform var(--dm-fast) var(--dm-ease);
}
.dm-stat:hover { border-color: var(--dm-orange); transform: translateY(-1px); }
.dm-stat-label {
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.07em; color: var(--dm-text-dim); margin-bottom: 6px;
}
.dm-stat-value { font-size: 1.65rem; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; }
.dm-stat-value.accent { color: var(--dm-orange); }
.dm-stat-sub { font-size: 0.76rem; color: var(--dm-text-muted); margin-top: 4px; font-family: var(--dm-mono); }

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */

.dm-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 7px 14px; border-radius: var(--dm-radius-sm);
  font-size: 0.85rem; font-weight: 600; font-family: inherit;
  border: 1px solid var(--dm-border); background: var(--dm-surface-2); color: var(--dm-text);
  cursor: pointer; white-space: nowrap;
  transition: background var(--dm-fast) var(--dm-ease), border-color var(--dm-fast) var(--dm-ease),
              transform var(--dm-fast) var(--dm-ease), box-shadow var(--dm-fast) var(--dm-ease);
}
.dm-btn:hover { background: var(--dm-surface-3); border-color: var(--dm-border-strong); text-decoration: none; color: var(--dm-text); }
.dm-btn:active { transform: translateY(1px); }
/* aria-disabled covers a <span class="dm-btn"> -- the server pager's Prev/Next at either end
   are spans, not links, precisely so there is nothing to click; they have to LOOK dead too. */
.dm-btn[disabled], .dm-btn[aria-disabled="true"], .dm-btn.is-loading {
  opacity: 0.55; pointer-events: none;
}

/* Dark text on orange: white-on-orange is ~2.2:1 and fails AA.
   Same call mono-tek-com made. */
.dm-btn-primary { background: var(--dm-orange); border-color: var(--dm-orange); color: var(--dm-bg); }
.dm-btn-primary:hover { background: var(--dm-orange-hover); border-color: var(--dm-orange-hover);
  color: var(--dm-bg); box-shadow: 0 4px 16px var(--dm-orange-glow); }

.dm-btn-danger { background: transparent; border-color: var(--dm-danger); color: var(--dm-danger); }
.dm-btn-danger:hover { background: var(--dm-danger-bg); color: var(--dm-danger); }

.dm-btn-ghost { background: transparent; border-color: transparent; color: var(--dm-text-muted); }
.dm-btn-ghost:hover { background: var(--dm-surface-2); color: var(--dm-text); }

.dm-btn-sm { padding: 4px 9px; font-size: 0.78rem; }
.dm-btn-icon { padding: 6px; width: 30px; height: 30px; }

/* --------------------------------------------------------------------------
   6. Forms
   -------------------------------------------------------------------------- */

.dm-form-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.dm-field { display: flex; flex-direction: column; gap: 5px; }
.dm-field.span-2 { grid-column: span 2; }
.dm-field.span-full { grid-column: 1 / -1; }
/* `display: flex` beats the UA `[hidden]` rule, so a hidden field needs its own. */
.dm-field[hidden], .dm-check[hidden] { display: none; }

.dm-label { font-size: 0.78rem; font-weight: 600; color: var(--dm-text-muted); }
.dm-label .dm-req { color: var(--dm-orange); margin-left: 2px; }
.dm-hint { font-size: 0.74rem; color: var(--dm-text-dim); }
.dm-error { font-size: 0.74rem; color: var(--dm-danger); }

.dm-input, .dm-select, .dm-textarea {
  width: 100%; padding: 7px 10px;
  background: var(--dm-bg); color: var(--dm-text);
  border: 1px solid var(--dm-border); border-radius: var(--dm-radius-sm);
  font-family: inherit; font-size: 0.86rem;
  transition: border-color var(--dm-fast) var(--dm-ease), box-shadow var(--dm-fast) var(--dm-ease);
}
.dm-input:focus, .dm-select:focus, .dm-textarea:focus {
  outline: none; border-color: var(--dm-orange); box-shadow: 0 0 0 3px var(--dm-orange-soft);
}
.dm-input::placeholder { color: var(--dm-text-dim); }
.dm-input[aria-invalid="true"], .dm-field.has-error .dm-input { border-color: var(--dm-danger); }
.dm-textarea { min-height: 84px; resize: vertical; font-family: var(--dm-mono); font-size: 0.8rem; }
.dm-select { appearance: none; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--dm-text-muted) 50%),
                    linear-gradient(135deg, var(--dm-text-muted) 50%, transparent 50%);
  background-position: calc(100% - 15px) 15px, calc(100% - 10px) 15px;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; padding-right: 28px; }

.dm-input-group { display: flex; }
.dm-input-group .dm-input { border-radius: var(--dm-radius-sm) 0 0 var(--dm-radius-sm); }
.dm-input-group .dm-btn { border-radius: 0 var(--dm-radius-sm) var(--dm-radius-sm) 0; margin-left: -1px; }

/* Checkbox / radio / switch */
.dm-check { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; font-size: 0.85rem; }
.dm-check input { accent-color: var(--dm-orange); width: 15px; height: 15px; cursor: pointer; }

.dm-switch { position: relative; width: 36px; height: 20px; flex: none; }
.dm-switch input { opacity: 0; width: 0; height: 0; }
.dm-switch span {
  position: absolute; inset: 0; background: var(--dm-border-strong);
  border-radius: 999px; cursor: pointer; transition: background var(--dm-fast) var(--dm-ease);
}
.dm-switch span::before {
  content: ""; position: absolute; width: 14px; height: 14px; left: 3px; top: 3px;
  background: var(--dm-text); border-radius: 50%; transition: transform var(--dm-fast) var(--dm-ease);
}
.dm-switch input:checked + span { background: var(--dm-orange); }
.dm-switch input:checked + span::before { transform: translateX(16px); background: var(--dm-bg); }

/* Filter bar above a table */
.dm-filterbar {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  padding: 10px 12px; background: var(--dm-surface); border: 1px solid var(--dm-border);
  border-radius: var(--dm-radius) var(--dm-radius) 0 0; border-bottom: none;
}
.dm-filterbar .dm-input, .dm-filterbar .dm-select { width: auto; min-width: 150px; }
.dm-filterbar .dm-spacer { margin-left: auto; }

.dm-search { position: relative; }
.dm-search .dm-input { padding-left: 30px; min-width: 220px; }
.dm-search::before {
  content: ""; position: absolute; left: 10px; top: 50%; width: 12px; height: 12px;
  margin-top: -6px; border: 1.8px solid var(--dm-text-dim); border-radius: 50%; pointer-events: none;
}
.dm-search::after {
  content: ""; position: absolute; left: 20px; top: 50%; width: 6px; height: 1.8px;
  margin-top: 3px; background: var(--dm-text-dim); transform: rotate(45deg); pointer-events: none;
}

/* --------------------------------------------------------------------------
   7. Tables — the primary surface of this app
   -------------------------------------------------------------------------- */

.dm-table-wrap {
  border: 1px solid var(--dm-border); border-radius: 0 0 var(--dm-radius) var(--dm-radius);
  overflow: auto; background: var(--dm-surface); max-height: 72vh;
}
.dm-filterbar + .dm-table-wrap { border-top: 1px solid var(--dm-border); }
.dm-table-wrap:first-child { border-radius: var(--dm-radius); }

.dm-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 0.84rem; }

.dm-table thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--dm-surface-2); color: var(--dm-text-muted);
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  text-align: left; padding: 9px 12px; white-space: nowrap;
  border-bottom: 1px solid var(--dm-border);
}
.dm-table thead th.dm-num { text-align: right; }

/* Sortable headers. The caret is always present but dim, so the column
   width never shifts when the sort changes. */
.dm-table th[data-sort] { cursor: pointer; user-select: none; padding-right: 24px; position: relative; }
.dm-table th[data-sort]:hover { color: var(--dm-text); background: var(--dm-surface-3); }
.dm-table th[data-sort]::after {
  content: "\2195"; position: absolute; right: 9px; top: 50%; transform: translateY(-50%);
  font-size: 0.78rem; opacity: 0.3; transition: opacity var(--dm-fast) var(--dm-ease);
}
.dm-table th[data-sort][aria-sort="ascending"]::after  { content: "\2191"; opacity: 1; color: var(--dm-orange); }
.dm-table th[data-sort][aria-sort="descending"]::after { content: "\2193"; opacity: 1; color: var(--dm-orange); }

.dm-table tbody td {
  padding: 8px 12px; border-bottom: 1px solid var(--dm-border);
  vertical-align: middle; color: var(--dm-text);
}
.dm-table tbody tr { transition: background var(--dm-fast) var(--dm-ease); }
.dm-table tbody tr:hover { background: var(--dm-surface-2); }
.dm-table tbody tr:last-child td { border-bottom: none; }
.dm-table tbody tr.is-selected { background: var(--dm-orange-soft); box-shadow: inset 2px 0 0 var(--dm-orange); }

.dm-table.dm-table-zebra tbody tr:nth-child(even) { background: rgba(255, 255, 255, 0.017); }
.dm-table.dm-table-zebra tbody tr:hover { background: var(--dm-surface-2); }
.dm-table.dm-table-compact tbody td { padding: 5px 10px; }
.dm-table.dm-table-compact thead th { padding: 6px 10px; }

/* Sticky first column for wide tables */
.dm-table.dm-sticky-first tbody td:first-child,
.dm-table.dm-sticky-first thead th:first-child {
  position: sticky; left: 0; z-index: 1; background: var(--dm-surface);
}
.dm-table.dm-sticky-first thead th:first-child { z-index: 3; background: var(--dm-surface-2); }

.dm-table-foot {
  display: flex; align-items: center; gap: 12px; padding: 9px 12px;
  border: 1px solid var(--dm-border); border-top: none;
  border-radius: 0 0 var(--dm-radius) var(--dm-radius);
  background: var(--dm-surface); font-size: 0.78rem; color: var(--dm-text-muted);
}
.dm-table-foot .dm-spacer { margin-left: auto; }
/* Rows-per-page picker: sits beside the pager, sized to its content, not the 100% form width */
.dm-table-foot .dm-select { width: auto; padding-top: 4px; padding-bottom: 4px; font-size: 0.78rem;
  background-position: calc(100% - 15px) 11px, calc(100% - 10px) 11px; }

/* Empty and loading states are part of the table, not an afterthought */
.dm-empty { padding: 44px 20px; text-align: center; color: var(--dm-text-muted); }
.dm-empty-icon { font-size: 1.8rem; opacity: 0.4; margin-bottom: 8px; }
.dm-empty h4 { font-size: 0.95rem; font-weight: 700; color: var(--dm-text); margin: 0 0 4px; }
.dm-empty p { font-size: 0.83rem; margin: 0 0 14px; }

/* --------------------------------------------------------------------------
   8. Badges, pills, progress
   -------------------------------------------------------------------------- */

.dm-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 999px;
  font-size: 0.72rem; font-weight: 600; line-height: 1.5;
  background: var(--dm-surface-3); color: var(--dm-text-muted); border: 1px solid var(--dm-border);
}
.dm-badge-success { background: var(--dm-success-bg); color: var(--dm-success); border-color: transparent; }
.dm-badge-warning { background: var(--dm-warning-bg); color: var(--dm-warning); border-color: transparent; }
.dm-badge-danger  { background: var(--dm-danger-bg);  color: var(--dm-danger);  border-color: transparent; }
.dm-badge-info    { background: var(--dm-info-bg);    color: var(--dm-info);    border-color: transparent; }
.dm-badge-accent  { background: var(--dm-orange-soft);color: var(--dm-orange);  border-color: transparent; }

.dm-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.dm-dot-pulse { animation: dm-pulse 1.8s var(--dm-ease) infinite; }
@keyframes dm-pulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 currentColor; }
  50% { opacity: 0.65; box-shadow: 0 0 0 4px transparent; }
}

.dm-progress { height: 5px; background: var(--dm-surface-3); border-radius: 999px; overflow: hidden; }
.dm-progress-bar { height: 100%; background: var(--dm-orange); border-radius: 999px;
  transition: width var(--dm-med) var(--dm-ease); }
.dm-progress-bar.success { background: var(--dm-success); }
.dm-progress-bar.warning { background: var(--dm-warning); }

/* --------------------------------------------------------------------------
   9. Spinners & loading
   -------------------------------------------------------------------------- */

/* Ring — the default. Inherits currentColor so it works on any surface. */
.dm-spinner {
  display: inline-block; width: 15px; height: 15px; flex: none;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; opacity: 0.85;
  animation: dm-spin var(--dm-spin) linear infinite;
}
.dm-spinner-lg { width: 26px; height: 26px; border-width: 3px; }
.dm-spinner-accent { color: var(--dm-orange); }
@keyframes dm-spin { to { transform: rotate(360deg); } }

/* Three dots — for inline "still working" text where a ring feels heavy */
.dm-dots { display: inline-flex; gap: 3px; align-items: center; }
.dm-dots i { width: 5px; height: 5px; border-radius: 50%; background: currentColor;
  animation: dm-bounce 1.1s var(--dm-ease) infinite; }
.dm-dots i:nth-child(2) { animation-delay: 0.16s; }
.dm-dots i:nth-child(3) { animation-delay: 0.32s; }
@keyframes dm-bounce { 0%, 70%, 100% { transform: translateY(0); opacity: 0.45; }
                       35% { transform: translateY(-4px); opacity: 1; } }

/* Bar — top-of-page indeterminate progress for full-page loads */
.dm-loadbar { position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 100; overflow: hidden;
  background: transparent; }
.dm-loadbar::after {
  content: ""; position: absolute; inset: 0; width: 40%;
  background: linear-gradient(90deg, transparent, var(--dm-orange), transparent);
  animation: dm-slide 1.05s var(--dm-ease) infinite;
}
@keyframes dm-slide { from { transform: translateX(-100%); } to { transform: translateX(350%); } }

/* Button loading: swap label for a spinner without the button resizing */
.dm-btn.is-loading { position: relative; color: transparent !important; }
.dm-btn.is-loading::after {
  content: ""; position: absolute; top: 50%; left: 50%; width: 14px; height: 14px;
  margin: -7px 0 0 -7px; border: 2px solid var(--dm-bg); border-right-color: transparent;
  border-radius: 50%; animation: dm-spin var(--dm-spin) linear infinite;
}
.dm-btn:not(.dm-btn-primary).is-loading::after { border-color: var(--dm-text); border-right-color: transparent; }

/* The one live region dm.busy() writes "Working…" into. Visually hidden, never display:none,
   so a screen reader hears the state that the transparent label and the ring cannot say. */
.dm-sr-status {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Skeleton — use for first paint of known-shape content. Never for unknown counts. */
.dm-skel {
  background: linear-gradient(90deg, var(--dm-surface-2) 25%, var(--dm-surface-3) 37%, var(--dm-surface-2) 63%);
  background-size: 400% 100%; border-radius: var(--dm-radius-xs);
  animation: dm-shimmer 1.35s ease-in-out infinite; height: 1em;
}
@keyframes dm-shimmer { from { background-position: 100% 50%; } to { background-position: 0 50%; } }

.dm-overlay {
  position: absolute; inset: 0; display: grid; place-items: center; gap: 10px;
  background: rgba(13, 17, 23, 0.62); backdrop-filter: blur(2px); border-radius: inherit; z-index: 5;
}

/* --------------------------------------------------------------------------
   10. Toasts, modals, tooltips
   -------------------------------------------------------------------------- */

.dm-toasts { position: fixed; bottom: 18px; right: 18px; z-index: 200;
  display: flex; flex-direction: column; gap: 8px; max-width: 380px; }
.dm-toast {
  display: flex; gap: 10px; align-items: flex-start;
  background: var(--dm-surface); border: 1px solid var(--dm-border);
  border-left: 3px solid var(--dm-text-muted);
  border-radius: var(--dm-radius-sm); padding: 11px 13px; box-shadow: var(--dm-shadow);
  animation: dm-toast-in var(--dm-med) var(--dm-ease);
}
.dm-toast.success { border-left-color: var(--dm-success); }
.dm-toast.warning { border-left-color: var(--dm-warning); }
.dm-toast.danger  { border-left-color: var(--dm-danger); }
.dm-toast.info    { border-left-color: var(--dm-info); }
.dm-toast strong { display: block; font-size: 0.84rem; }
.dm-toast p { margin: 2px 0 0; font-size: 0.79rem; color: var(--dm-text-muted); }
.dm-toast.leaving { animation: dm-toast-out var(--dm-med) var(--dm-ease) forwards; }
@keyframes dm-toast-in  { from { opacity: 0; transform: translateX(14px); } }
@keyframes dm-toast-out { to { opacity: 0; transform: translateX(14px); } }

.dm-modal-backdrop {
  position: fixed; inset: 0; background: rgba(0, 0, 0, 0.62);
  backdrop-filter: blur(3px); z-index: 150; display: grid; place-items: center; padding: 18px;
  animation: dm-fade var(--dm-fast) var(--dm-ease);
}
.dm-modal {
  background: var(--dm-surface); border: 1px solid var(--dm-border);
  border-radius: var(--dm-radius); box-shadow: var(--dm-shadow-lg);
  width: min(560px, 100%); max-height: 86vh; overflow: auto;
  animation: dm-modal-in var(--dm-med) var(--dm-ease);
}
.dm-modal-head { padding: 14px 18px; border-bottom: 1px solid var(--dm-border);
  display: flex; align-items: center; gap: 10px; }
.dm-modal-head h3 { margin: 0; font-size: 0.98rem; font-weight: 700; }
.dm-modal-body { padding: 18px; }
.dm-modal-foot { padding: 13px 18px; border-top: 1px solid var(--dm-border);
  display: flex; gap: 8px; justify-content: flex-end; }
@keyframes dm-fade { from { opacity: 0; } }
@keyframes dm-modal-in { from { opacity: 0; transform: translateY(10px) scale(0.985); } }

[data-dm-tip] { position: relative; }
[data-dm-tip]::after {
  content: attr(data-dm-tip); position: absolute; bottom: calc(100% + 6px); left: 50%;
  transform: translateX(-50%); white-space: nowrap;
  background: var(--dm-surface-3); color: var(--dm-text); border: 1px solid var(--dm-border);
  padding: 4px 8px; border-radius: var(--dm-radius-xs); font-size: 0.73rem; font-weight: 500;
  opacity: 0; pointer-events: none; transition: opacity var(--dm-fast) var(--dm-ease); z-index: 30;
}
[data-dm-tip]:hover::after { opacity: 1; }

/* --------------------------------------------------------------------------
   11. Utilities
   -------------------------------------------------------------------------- */

.dm-muted { color: var(--dm-text-muted); }
.dm-dim   { color: var(--dm-text-dim); }
.dm-accent{ color: var(--dm-orange); }
.dm-ok    { color: var(--dm-success); }
.dm-warn  { color: var(--dm-warning); }
.dm-bad   { color: var(--dm-danger); }
.dm-spacer{ margin-left: auto; }
/* Vertical rhythm between sibling blocks. The templates have used these since the first
   screen; they were never defined, so every `mt-3` collapsed to zero and sections sat flush
   against each other. One step only -- a scale invites a second and a third. */
.mt-3 { margin-top: 18px; }
.mb-3 { margin-bottom: 18px; }
.dm-row   { display: flex; align-items: center; gap: 8px; }
.dm-col   { display: flex; flex-direction: column; gap: 8px; }
.dm-wrap  { flex-wrap: wrap; }
.dm-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.dm-divider { height: 1px; background: var(--dm-border); margin: 14px 0; border: 0; }
.dm-code {
  background: var(--dm-bg); border: 1px solid var(--dm-border); border-radius: var(--dm-radius-sm);
  padding: 11px 13px; font-family: var(--dm-mono); font-size: 0.78rem;
  overflow-x: auto; color: var(--dm-text-muted); line-height: 1.6;
}
.dm-kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; font-size: 0.83rem; }
.dm-kv dt { color: var(--dm-text-muted); font-weight: 500; }
.dm-kv dd { margin: 0; font-family: var(--dm-mono); font-size: 0.8rem; }

/* Timestamps are always rendered by dm.fmtDate — see docs/DESIGN_SYSTEM.md §Dates */
.dm-ts { font-family: var(--dm-mono); font-size: 0.79rem; color: var(--dm-text-muted); white-space: nowrap; }

/* --------------------------------------------------------------------------
   12. App layout helpers
   Added for the Flask UI. Layout only — no new colours, radii, durations or
   fonts; every value below is either a token or a plain gap. Anything that
   needed a colour used the tokens in §1.
   -------------------------------------------------------------------------- */

/* The sidebar toggle only means anything below the §3 breakpoint. */
.dm-only-narrow { display: none; }
@media (max-width: 900px) { .dm-only-narrow { display: inline-flex; } }

/* Click-off scrim behind the open mobile sidebar. */
.dm-scrim { position: fixed; inset: 0; z-index: 40; background: rgba(0, 0, 0, 0.5); }
@media (min-width: 901px) { .dm-scrim { display: none; } }

/* Main column of the shell: topbar sticks, content scrolls under it. */
.dm-main { min-width: 0; display: flex; flex-direction: column; }

/* A wide primary panel beside a narrower rail, stacking on small screens. */
.dm-split { display: grid; gap: 14px; grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 1100px) { .dm-split { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); } }
.dm-split-even { display: grid; gap: 14px; grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 900px) { .dm-split-even { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Equal-ish cards that reflow by available width. */
.dm-cols { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

.dm-stack > * + * { margin-top: 14px; }
.dm-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.dm-relative { position: relative; }
.dm-pre { white-space: pre-wrap; word-break: break-word; margin: 0; }

/* Dense multi-select (56 state codes) that never grows the page. */
.dm-check-grid {
  display: grid; gap: 4px 10px;
  grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
  max-height: 190px; overflow-y: auto;
  padding: 9px 10px; border: 1px solid var(--dm-border);
  border-radius: var(--dm-radius-sm); background: var(--dm-bg);
}
.dm-check-grid .dm-check { font-size: 0.79rem; font-family: var(--dm-mono); }

/* One filter row in the query builder. */
.dm-filter-row { display: grid; gap: 8px; grid-template-columns: 1fr; align-items: end; }
@media (min-width: 700px) {
  .dm-filter-row { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr) minmax(0, 1.6fr) auto; }
}

/* Expandable detail row inside a table (query log AST + SQL). */
.dm-table tbody tr.dm-detail-row > td { background: var(--dm-bg); padding: 14px 16px; }
/* #82: a Job log inside a detail row wraps. A `pre` that keeps one 300-character refusal line
   on one line widens the whole table and scrolls the Job column out of view. */
.dm-table tbody tr.dm-detail-row pre.dm-code { white-space: pre-wrap; word-break: break-word; }
.dm-table tbody tr.dm-detail-row:hover > td { background: var(--dm-bg); }
tr[data-dm-expand] { cursor: pointer; }

/* A run-report figure: big number, small caption, no card chrome. */
.dm-figure { padding: 10px 0; }
.dm-figure .dm-figure-value { font-size: 1.25rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.dm-figure .dm-figure-label { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--dm-text-dim); }

/* Demo-mode strip, so nobody mistakes fixtures for production data. */
.dm-demo-strip {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 12px; margin-bottom: 16px;
  border: 1px dashed var(--dm-border-strong); border-radius: var(--dm-radius-sm);
  background: var(--dm-surface); color: var(--dm-text-muted); font-size: 0.78rem;
}

/* "View as" (#140): sticky above everything, warning surface from the existing tokens. */
.dm-impersonation {
  position: sticky; top: 0; z-index: 60;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 16px; font-size: 0.85rem;
  background: var(--dm-warning-bg); color: var(--dm-text);
  border-bottom: 2px solid var(--dm-warning);
}
.dm-impersonation .dm-inline-form { margin-left: auto; }

/* Live reads as settled, demo reads as provisional: a solid left rule instead of
   the dashed border, and no extra colour invented for either. */
.dm-live-strip { border-style: solid; border-left: 3px solid var(--dm-success); }
.dm-provenance { border-left: 3px solid var(--dm-warning); }

/* --------------------------------------------------------------------------
   14. Batch plan
   -------------------------------------------------------------------------- */

/* A fill bar inside a table cell. Width is the only thing set inline, because a
   measured percentage is data, not styling. */
.dm-fill { position: relative; display: block; height: 6px; border-radius: 3px;
           background: var(--dm-surface-3); overflow: hidden; min-width: 64px; }
.dm-fill > i { display: block; height: 100%; background: var(--dm-success); }
.dm-fill.short > i { background: var(--dm-warning); }
.dm-fill.bad > i { background: var(--dm-danger); }

/* Contention attribution: "1,050 of the records AW3 wanted went to AW1". Indented
   under its line so the cause reads as belonging to the effect. */
.dm-attrib { margin: 4px 0 0; padding-left: 14px; border-left: 2px solid var(--dm-border);
             color: var(--dm-text-muted); font-size: 0.78rem; }
.dm-attrib li { list-style: none; }

/* The ordering comparison. The winner is marked, never colour-coded alone. */
.dm-ordering { display: flex; align-items: center; gap: 8px; padding: 3px 0; }
.dm-ordering.win { color: var(--dm-text); font-weight: 600; }
.dm-ordering .dm-bar { flex: 1; height: 6px; border-radius: 3px; background: var(--dm-surface-3); }
.dm-ordering .dm-bar > i { display: block; height: 100%; border-radius: 3px;
                           background: var(--dm-border-strong); }
.dm-ordering.win .dm-bar > i { background: var(--dm-orange); }

/* A spec the parser flagged needs_review. Loud on purpose: this is the one state
   where a click-through ships the wrong 150,000 records. */
.dm-review { border: 1px solid var(--dm-danger); background: var(--dm-danger-bg);
             border-radius: var(--dm-radius-sm); padding: 12px 14px; margin-bottom: 16px; }
.dm-review h4 { margin: 0 0 6px; font-size: 0.95rem; color: var(--dm-danger); }
.dm-review ul { margin: 0; padding-left: 18px; }

/* The email line a field was read from, quoted verbatim next to the value. */
.dm-source-line { font-family: var(--dm-mono); font-size: 0.74rem; color: var(--dm-text-muted);
                  display: block; margin-top: 2px; word-break: break-word; }

/* A stat tile that is also a link keeps the tile's own colours. */
a.dm-stat, a.dm-stat:hover { color: inherit; text-decoration: none; }

/* A multi-select is a list box, not a dropdown — drop the caret the single
   select paints in its top-right corner. */
.dm-select[multiple] { background-image: none; padding-right: 10px; height: auto; }

/* --- sign-in ---------------------------------------------------------- */
/* The only page with no sidebar context to balance against, so it centres on its
   own rather than inheriting the content column's full width. */
.dm-signin { max-width: 420px; margin: 6vh auto 0; }
.dm-signin .dm-card { padding-bottom: 18px; }

/* A form that exists only to make a button POST rather than GET -- sign out, and anything
   else that must not be reachable by following a link. It should not affect layout. */
.dm-inline-form { display: inline-flex; margin: 0; }

/* --- per-row metadata on the staged deliveries table ------------------- */
/* Label, field, label, field, button on one line at desktop width; wrapping to
   two lines rather than squeezing the date input below its usable size. */
.dm-meta-fields {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.dm-meta-fields .dm-label { margin: 0; white-space: nowrap; }
.dm-meta-fields .dm-input { width: auto; min-width: 9rem; }

/* --- a failed ingest, explained ---------------------------------------- */
/* Each failure is its own block with a left rule, so several on one card stay
   separable at a glance rather than running together as prose. */
.dm-issue { border-left: 3px solid var(--dm-danger); padding: 2px 0 2px 12px; margin: 14px 0; }
.dm-issue:first-of-type { margin-top: 6px; }
.dm-issue .dm-code { margin-top: 6px; white-space: pre-wrap; word-break: break-word; }
/* T-39: reused for something that is not a failure -- "Awaiting your decision" is a state,
   not a problem, so it gets the warning colour rather than the danger one. */
.dm-issue-warning { border-left-color: var(--dm-warning); }

/* --- the flagged column on a quarantined row --------------------------- */
/* The field the check actually refused, marked so the eye lands on it first
   rather than reading eleven identical boxes. */
.dm-field-flagged .dm-input { border-color: var(--dm-danger); }
.dm-field-flagged .dm-label { color: var(--dm-danger); }

/* --- fixtures, marked where they sit ----------------------------------- */
/* A banner at the top of the page is not enough when the fixtures look exactly
   like real history. Dimming and a warning rule make the boundary visible at the
   scroll position where somebody is actually reading. */
.dm-example { opacity: 0.62; }
.dm-example:hover { opacity: 0.85; }
section.dm-example { opacity: 1; border-left: 3px solid var(--dm-warning); }

/* --------------------------------------------------------------------------
   15. Print — the PDF surface (ROADMAP 3.19, T-55)

   A plan page and an order page ARE the report, so "save as PDF" is a print
   surface for them rather than a second document. Two rules follow from that
   and they decide everything below:

     * Nothing is REMOVED on paper that the page states. Only controls go --
       a button, a search box or a pager is not a statement, and a column or a
       warning that vanishes in the PDF is drift.
     * Every value keeps its meaning. A regime badge, a short-fill bar and a
       failed-constraint rule all carry their message in a FILL, and browsers
       drop fills when printing unless told not to, so the elements whose
       colour is information get print-color-adjust: exact.

   The rest is repainting a dark-first UI for paper. The tokens are redefined
   here rather than overridden per component, so a component added later is
   printable without touching this section.
   -------------------------------------------------------------------------- */

@media print {
  :root {
    /* Ink on paper. The accent and the four semantic colours are darkened just
       enough to stay legible on white -- the same hues, not new ones. */
    --dm-bg:            #FFFFFF;
    --dm-surface:       #FFFFFF;
    --dm-surface-2:     #F4F5F7;
    --dm-surface-3:     #E9EBEE;
    --dm-border:        #C4C9D0;
    --dm-border-strong: #9AA1AB;

    --dm-text:          #14181D;
    --dm-text-muted:    #444C56;
    --dm-text-dim:      #5B646E;

    --dm-orange:        #B26100;
    --dm-orange-hover:  #B26100;
    --dm-orange-soft:   #FBEBD6;
    --dm-orange-glow:   transparent;

    --dm-success:       #1A7F37;
    --dm-warning:       #8A6100;
    --dm-danger:        #B32821;
    --dm-info:          #0B5CAD;
    --dm-success-bg:    #E4F3E7;
    --dm-warning-bg:    #FAF0DA;
    --dm-danger-bg:     #FBE6E5;
    --dm-info-bg:       #E3EEFA;

    --dm-shadow:        none;
    --dm-shadow-lg:     none;
  }

  @page { size: A4 portrait; margin: 14mm 12mm; }

  body { background: #FFFFFF; color: var(--dm-text); font-size: 10.5pt; }

  /* The chrome. Everything here is a control or a live indicator; none of it is
     part of what the page says. .dm-print-hide is the per-page opt-out the two
     report templates use for their own controls. */
  .dm-sidebar,
  .dm-topbar,
  .dm-scrim,
  .dm-toasts,
  .dm-modal-backdrop,
  .dm-loadbar,
  .dm-page-head .dm-actions,
  .dm-filterbar,
  .dm-table-foot,
  [data-dm-pager],
  .dm-print-hide { display: none !important; }

  /* The shell is a fixed-height, independently scrolling grid. On paper there
     is one flow and it is as long as it needs to be. */
  .dm-shell { display: block; min-height: 0; }
  .dm-main { display: block; }
  .dm-content { padding: 0; max-width: none; }

  /* A table that scrolls inside a 72vh box prints as one screenful and silently
     loses the rest. (The rows themselves are dm.print's job -- paging removes
     them from the DOM, which no stylesheet can undo.) */
  .dm-table-wrap { max-height: none; overflow: visible; border-radius: 0; }
  .dm-table { font-size: 9pt; }
  .dm-table thead th { position: static; }
  .dm-table thead { display: table-header-group; }
  .dm-table tbody tr { break-inside: avoid; }
  .dm-check-grid { max-height: none; overflow: visible; }

  /* Keep a unit of meaning on one page where it fits on one page. */
  .dm-card, .dm-issue, .dm-review, .dm-stat, .dm-figure { break-inside: avoid; }
  .dm-card { box-shadow: none; }
  h2, h3, .dm-nav-section, .dm-card-head { break-after: avoid; }
  .dm-print-break-before { break-before: page; }

  /* A collapsed card would print folded. dm.print unfolds them before the
     dialog opens; this is the belt to that braces, for a print started from
     the browser's own menu rather than the button. */
  .dm-card.is-collapsed > *:not(.dm-card-head) { display: revert; }
  .dm-card.is-collapsed > .dm-card-head { margin-bottom: 0; border-bottom-color: var(--dm-border); }

  /* Two columns of cards at 1600px is two narrow columns at 186mm. */
  .dm-split, .dm-split-even, .dm-cols { grid-template-columns: minmax(0, 1fr); }

  /* Colour that IS the message. Without this the badge prints as its border and
     the fill bar prints as an empty track, and both read as "no finding". */
  .dm-badge,
  .dm-dot,
  .dm-progress,
  .dm-progress-bar,
  .dm-fill,
  .dm-demo-strip,
  .dm-issue,
  .dm-review,
  .dm-table-zebra tbody tr:nth-child(even) > td {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .dm-dot-pulse { animation: none; }

  /* A URL is not useful on paper and an underline on every id is noise. */
  a, a:hover { color: var(--dm-text); text-decoration: none; }
}

/* The print-only header: who this is, and when it was taken off the screen. A
   filed PDF that says neither is a screenshot with extra steps. */
.dm-print-only { display: none; }
@media print {
  .dm-print-only { display: revert; }

  .dm-print-head {
    display: flex; align-items: flex-start; gap: 10px;
    padding-bottom: 8px; margin-bottom: 14px;
    border-bottom: 2px solid var(--dm-orange);
  }
  .dm-print-head .dm-brand-mark { color: var(--dm-orange); display: inline-flex; }
  .dm-print-head .dm-brand-mark svg { width: 19px; height: 16px; display: block; }
  .dm-print-head h1 { font-size: 1.15rem; font-weight: 800; margin: 0; letter-spacing: -0.02em; }
  .dm-print-head p { margin: 2px 0 0; font-size: 0.78rem; color: var(--dm-text-muted); }
  .dm-print-head .dm-print-stamp {
    margin-left: auto; text-align: right; font-size: 0.72rem; color: var(--dm-text-muted);
    font-family: var(--dm-mono);
  }
}

/* --- page-scoped print rules: batch plan (body[data-print-page="plan"]) ---
   Owned by the batch-plan surface. Rules for /batches/<id>/plan go here and
   nowhere else, so two people can work the two report pages at once. */
@media print {
  /* The regime strip is the headline -- "we exceeded the target" vs "the floor
     forced it" vs "this was arithmetically impossible" must not split across a
     page break and arrive as an orphaned badge on one page, sentence on the
     next. .dm-review (the hard-constraint / unsatisfiable banners) already gets
     break-inside: avoid from the shared rule above. */
  body[data-print-page="plan"] .dm-demo-strip { break-inside: avoid; }
}

/* --- page-scoped print rules: order detail (body[data-print-page="order"]) ---
   Owned by the order-detail surface. Rules for /orders/<id> go here and nowhere
   else, for the same reason. */

/* #99: a file dragged over a picker card. Existing tokens only. */
[data-dm-picker].is-dropping {
  outline: 2px dashed var(--dm-orange);
  outline-offset: -2px;
  background: var(--dm-orange-soft);
}

/* --------------------------------------------------------------------------
   13. File share (#145)
   Tokens only. The transfer progress bar is the progress indicator for an upload (it moves with
   real bytes), so nothing here adds an animation-only indicator.
   -------------------------------------------------------------------------- */

/* The three "start something" tiles above the share table. */
.dm-tiles { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.dm-tile {
  display: flex; flex-direction: column; gap: 4px; text-align: left; cursor: pointer;
  padding: 16px 18px; font-family: inherit; color: var(--dm-text);
  background: var(--dm-surface); border: 1px solid var(--dm-border); border-radius: var(--dm-radius);
  transition: border-color var(--dm-fast) var(--dm-ease), transform var(--dm-fast) var(--dm-ease),
              background var(--dm-fast) var(--dm-ease);
}
.dm-tile:hover, .dm-tile[aria-expanded="true"] {
  border-color: var(--dm-orange); background: var(--dm-surface-2); transform: translateY(-1px);
}
.dm-tile-icon {
  width: 34px; height: 34px; border-radius: var(--dm-radius-sm); margin-bottom: 6px;
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.1rem;
  background: var(--dm-orange-soft); color: var(--dm-orange);
}
.dm-tile-title { font-weight: 700; font-size: 0.95rem; }
.dm-tile-sub { font-size: 0.78rem; color: var(--dm-text-muted); }

/* A read-only value with its Copy button: the share link. */
.dm-linkbox { display: flex; gap: 0; }
.dm-linkbox .dm-input {
  border-radius: var(--dm-radius-sm) 0 0 var(--dm-radius-sm); font-family: var(--dm-mono);
  font-size: 0.8rem; color: var(--dm-orange); background: var(--dm-bg);
}
.dm-linkbox .dm-btn { border-radius: 0 var(--dm-radius-sm) var(--dm-radius-sm) 0; margin-left: -1px; }
.dm-whocan {
  display: flex; align-items: flex-start; gap: 8px; margin: 10px 0 0;
  font-size: 0.8rem; color: var(--dm-text-muted);
}

/* Drop zone. */
.dm-drop {
  border: 2px dashed var(--dm-border-strong); border-radius: var(--dm-radius);
  background: var(--dm-bg); padding: 22px 18px; text-align: center;
  transition: border-color var(--dm-fast) var(--dm-ease), background var(--dm-fast) var(--dm-ease);
}
.dm-drop.is-over { border-color: var(--dm-orange); background: var(--dm-orange-soft); }
.dm-drop-icon { font-size: 1.7rem; color: var(--dm-orange); line-height: 1; margin-bottom: 6px; }
.dm-drop-title { font-weight: 700; margin-bottom: 2px; }

/* The per-file transfer list inside a drop zone. */
.dm-xfers { list-style: none; margin: 14px 0 0; padding: 0; text-align: left; display: grid; gap: 8px; }
.dm-xfers:empty { display: none; }
.dm-xfer {
  display: grid; gap: 6px; padding: 10px 12px;
  background: var(--dm-surface); border: 1px solid var(--dm-border); border-radius: var(--dm-radius-sm);
}
.dm-xfer-head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.dm-xfer-name { font-weight: 600; font-size: 0.84rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dm-xfer-meta { font-family: var(--dm-mono); font-size: 0.74rem; color: var(--dm-text-muted); }
.dm-xfer.is-done { border-color: var(--dm-success); }
.dm-xfer.is-failed { border-color: var(--dm-danger); }
.dm-xfer.is-failed .dm-xfer-meta { color: var(--dm-danger); }

/* The branded, shell-less layout for people who have a link but no account. */
.dm-pub { min-height: 100vh; display: flex; flex-direction: column; align-items: center; padding: 28px 16px; }
.dm-pub-brand {
  display: flex; align-items: center; gap: 8px; margin-bottom: 22px;
  font-weight: 800; font-size: 1.05rem; letter-spacing: -0.01em; color: var(--dm-text);
}
.dm-pub-brand .dm-brand-mark { color: var(--dm-orange); display: inline-flex; align-items: center; }
.dm-pub-main { width: 100%; max-width: 720px; }
.dm-pub-card { box-shadow: var(--dm-shadow); }
.dm-pub-title { font-size: 1.35rem; font-weight: 800; letter-spacing: -0.01em; margin: 0 0 4px; }
.dm-pub-from { color: var(--dm-text-muted); margin: 0 0 16px; font-size: 0.88rem; }
.dm-pub-files { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.dm-pub-file {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  background: var(--dm-bg); border: 1px solid var(--dm-border); border-radius: var(--dm-radius-sm);
}
.dm-pub-file-name { flex: 1; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dm-pub-file-meta { font-size: 0.76rem; color: var(--dm-text-muted); font-family: var(--dm-mono); }
.dm-pub-foot { margin-top: 18px; font-size: 0.76rem; color: var(--dm-text-dim); text-align: center; }
@media (max-width: 520px) {
  .dm-pub-file { flex-wrap: wrap; }
  .dm-pub-file .dm-btn { width: 100%; }
}
