#main-container {
  background-color: var(--dmsp-bg-light);
  flex: 1;
}

:root {
    /* Brand identity — anchor #0f88cd. See BRAND_IDENTITY.md. */
    --dmsp-primary: #0f88cd;
    --dmsp-secondary: #4dabe0;
    --dmsp-primary-dark: #0a6aa0;
    --dmsp-panel-tint: #e6f3fb;
    --dmsp-panel-border: #b8dcf2;
    --dmsp-bg-light: #f8fafc;
    --dmsp-text-dark: #1e293b;
    --dmsp-text-muted: #64748b;
    --dmsp-icon-muted: #7aa9c9;
    --dmsp-success: #059669;
    --dmsp-warning: #d97706;
    --dmsp-danger: #dc2626;
    --dmsp-gradient-bold: linear-gradient(135deg, var(--dmsp-primary), var(--dmsp-secondary));
    /* Gradient banners carry white text and white controls, so they run one step
       deeper than --dmsp-gradient-bold. The bold gradient ends at --dmsp-secondary
       (#4dabe0), which only gives white 2.4:1 -- unreadable. This ramp ends at
       --dmsp-primary instead: white reads 5.9:1 at the dark end and 3.9:1 at the
       light one, and measures 4.8:1 at worst where banner text actually sits.
       Buttons on white pages keep --dmsp-gradient-bold and are unaffected. */
    /* The 40% stop holds the dark end across the left/centre of the box before
       the ramp opens up. Without it a centred banner -- .dmsp-public-header --
       lands its text on the pale corner and the subtitle measures 4.49:1. */
    --dmsp-gradient-header: linear-gradient(135deg, var(--dmsp-primary-dark), var(--dmsp-primary-dark) 40%, var(--dmsp-primary));
    --dmsp-panel-bg: linear-gradient(135deg, var(--dmsp-panel-tint), #fff);

    /* On-banner control surfaces. A DARK scrim -- not a light "frosted" one --
       is what makes a white label readable everywhere on the gradient:
       rgba(0,0,0,.22) gives 5.17:1, while rgba(255,255,255,.18) gives 2.67:1. */
    --dmsp-on-banner-fill: rgba(0, 0, 0, .22);
    --dmsp-on-banner-fill-hover: rgba(0, 0, 0, .34);
    --dmsp-on-banner-border: rgba(255, 255, 255, .55);
    --dmsp-on-banner-border-hover: rgba(255, 255, 255, .85);
    --dmsp-on-banner-focus-ring: rgba(0, 0, 0, .35);

    /* The solid white chip used for a banner's main action. */
    --dmsp-on-banner-chip: #fff;
    --dmsp-on-banner-chip-hover: #f1f8fd;
    --dmsp-on-banner-chip-active: var(--dmsp-panel-tint);

    /* Semantic variants. Each is a dark wash of its own hue carrying a tinted
       label, rather than a mid-tone fill the blue would swallow; every pairing
       clears 5:1. Four tokens per hue so no rule has to write a literal. */
    --dmsp-on-banner-danger-fill: rgba(127, 29, 29, .65);
    --dmsp-on-banner-danger-fill-hover: rgba(127, 29, 29, .88);
    --dmsp-on-banner-danger-text: #ffe0e0;
    --dmsp-on-banner-danger-border: rgba(255, 224, 224, .6);
    --dmsp-on-banner-success-fill: rgba(5, 84, 60, .62);
    --dmsp-on-banner-success-fill-hover: rgba(5, 84, 60, .88);
    --dmsp-on-banner-success-text: #c8f7e2;
    --dmsp-on-banner-success-border: rgba(200, 247, 226, .6);
    --dmsp-on-banner-warning-fill: rgba(122, 68, 5, .62);
    --dmsp-on-banner-warning-fill-hover: rgba(122, 68, 5, .88);
    --dmsp-on-banner-warning-text: #ffe9b8;
    --dmsp-on-banner-warning-border: rgba(255, 233, 184, .6);
    --dmsp-on-banner-info-fill: rgba(10, 63, 102, .55);
    --dmsp-on-banner-info-fill-hover: rgba(10, 63, 102, .85);
    --dmsp-on-banner-info-text: #d7edfb;
    --dmsp-on-banner-info-border: rgba(215, 237, 251, .6);

    /* Badge tints (background) + on-tint text */
    --dmsp-success-tint: #dcfce7;
    --dmsp-success-text: #065f46;
    --dmsp-warning-tint: #fef3c7;
    --dmsp-warning-text: #92400e;
    --dmsp-danger-tint: #fee2e2;
    --dmsp-danger-text: #991b1b;
    --dmsp-muted-tint: #f1f5f9;
    --dmsp-muted-text: #475569;
    --dmsp-info-tint: #dbeafe;
    --dmsp-info-text: #1e40af;

    /* LEGACY — only --primary-color remains: it is grey (#333), genuinely distinct from
       the brand blue, and still consumed by .navbar-brand / .sidebar / chat .typing-*
       (those migrate with the per-app restyles). The other legacy aliases were exact
       duplicates of --dmsp-* tokens; they were removed and their references repointed. */
    --primary-color: #333333;
}

h1, h2, h3, h4, h5, h6, p {
  color: var(--bs-dark);
}

.highlighted {
  border: var(--bs-primary) solid 2px !important;
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

#navbar {
  transition: background-color 0.5s ease-out;
  border-bottom: 1px solid var(--dmsp-panel-border);
}
.navbar {
  font-size: 18px; /* Adjust the size as needed */
}

.navbar-light .navbar-nav .nav-link,
.navbar-light .navbar-nav .nav-item {
  color: var(--dmsp-text-dark);
  transition: color 0.2s ease-in-out;
}

.navbar-light .navbar-nav .nav-link:hover {
  color: var(--dmsp-primary-dark);
  background: var(--dmsp-bg-light);
  border-radius: 8px;
}

.navbar-toggler {
  border-color: #ddd;
}

.navbar-toggler:hover,
.navbar-toggler:focus {
  background-color: var(--dmsp-primary);
}

/* Add animation for dropdown */
.dropdown-menu {
  display: none; /* Hide the menu initially */
  opacity: 0; /* Set initial opacity to 0 */
  transition: opacity 0.3s ease; /* Smooth transition for opacity */
}

.dropdown-menu.show {
  display: block; /* Show the menu when the dropdown is active */
  opacity: 1; /* Set opacity to 1 for fade-in effect */
}

.shadow-sm {
  box-shadow: 0 0.125rem 0.25rem rgba(0,0,0,.075)!important;
}

#footer {
  background-color: #f8f9fa; /* Slightly off-white for a soft look */
  color: #212529; /* Bootstrap's default dark shade for text */
}

#footer a {
  color: var(--dmsp-text-muted);
}

#footer a:hover {
  color: var(--dmsp-primary-dark);
  text-decoration: underline; /* Adds a bit of interaction on hover */
}

/* Hide spinners in WebKit browsers */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Hide spinners in Firefox */
input[type="number"] {
  -moz-appearance: textfield;
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: var(--dmsp-bg-light);
    color: var(--dmsp-text-dark);
}

.navbar-brand {
    font-weight: 700;
    color: var(--primary-color) !important;
}

.sidebar {
    background: #fff;
    border-right: 1px solid var(--dmsp-panel-border);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
    height: calc(100vh - 56px);
    position: sticky;
    top: 56px;
    padding: 0.5rem 0;
}

.export-notes-pre {
    white-space: pre-wrap;
    font-family: inherit;
    max-height: 150px;
    overflow-y: auto;
}

.col-checkbox {
    width: 40px;
}

.progress-xs {
    height: 5px;
}

.icon-bullet {
    font-size: .6rem;
    vertical-align: middle;
}

.history-label {
    min-width: 110px;
    max-width: 110px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.history-value {
    max-width: 160px;
}

/* ===== App sidebar — uniform across tech_notes / vehicle_orders / tire_storage / service.
   Subtle nav items (not solid-blue buttons); active = tinted pill + accent text. ===== */
.sidebar .nav-link {
    display: flex;
    align-items: center;
    color: var(--dmsp-text-dark);
    padding: 0.6rem 0.9rem;
    margin: 0.15rem 0.5rem;
    border-radius: 8px;
    font-size: 0.92rem;
    font-weight: 500;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.sidebar .nav-link .mdi {
    color: var(--dmsp-icon-muted);
}

.sidebar .nav-link:hover {
    background-color: var(--dmsp-bg-light);
    color: var(--dmsp-primary-dark);
}

.sidebar .nav-link.active {
    background-color: var(--dmsp-panel-tint);
    color: var(--dmsp-primary-dark);
    font-weight: 600;
}

.sidebar .nav-link:hover .mdi,
.sidebar .nav-link.active .mdi {
    color: var(--dmsp-primary-dark);
}

/* Canonical group heading — replaces the per-app ad-hoc heading markup. */
.sidebar-heading {
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--dmsp-text-muted);
    padding: 0.75rem 0.9rem 0.25rem;
}

.card {
    border: none;
    box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
    transition: box-shadow 0.2s;
}

.card:hover {
    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

.cost-display {
    font-family: 'Courier New', monospace;
    font-weight: 600;
}

.loading-spinner {
    display: inline-block;
    width: 20px;
    height: 20px;
    border: 3px solid var(--dmsp-muted-tint);
    border-top: 3px solid var(--dmsp-primary);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

@media (max-width: 767.98px) {
    .sidebar {
        position: fixed;
        top: 56px;
        left: -100%;
        width: 280px;
        transition: left 0.3s;
        z-index: 1000;
    }
    .sidebar.show {
        left: 0;
    }
}

/* Mobile sidebar backdrop */
#sidebarBackdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 999;
    cursor: pointer;
}
#sidebarBackdrop.show { display: block; }

/* Mobile sidebar floating toggle button */
#sidebarToggleBtn {
    display: none;
    position: fixed;
    bottom: 3.5rem;
    left: 1.25rem;
    z-index: 1001;
    background: var(--dmsp-primary);
    color: #fff;
    border: none;
    border-radius: 2rem;
    padding: 0.55rem 1.1rem;
    font-size: 0.875rem;
    font-weight: 600;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
    cursor: pointer;
    transition: background 0.2s, transform 0.15s;
    align-items: center;
    gap: 0.45rem;
}
#sidebarToggleBtn:hover { background: var(--dmsp-primary); color: #fff; transform: scale(1.05); }

@media (max-width: 767.98px) {
    #sidebarToggleBtn { display: flex; }
}

.speech-input.listening {
    border-color: #ff4444;
    box-shadow: 0 0 5px rgba(255, 68, 68, 0.5);
}

.mic-btn {
    margin-left: 5px;
    background: none;
    border: 1px solid #ddd;
    border-radius: 3px;
    cursor: pointer;
    padding: 5px 8px;
}

.mic-btn:hover {
    background-color: #f0f0f0;
}

.mic-btn:disabled {
    cursor: not-allowed;
}

/* Icon-only navbar links with hover label */
.nav-icon-link {
    display: flex !important;
    align-items: center;
    position: relative;
    white-space: nowrap;
    padding-left: 1rem !important;
    padding-right: 1rem !important;
}

/* Bigger icons */
.nav-icon-link .mdi {
    font-size: 1.25rem;
    color: var(--dmsp-icon-muted);
}

/* Label: hidden inline by default, expands on hover (shifts siblings) */
.nav-icon-link .nav-label {
    display: inline-block;
    max-width: 0;
    opacity: 0;
    overflow: hidden;
    white-space: nowrap;
    vertical-align: middle;
    margin-left: 0;
    transition: max-width 0.45s ease, opacity 0.35s ease, margin-left 0.45s ease;
}

.nav-icon-link:hover .nav-label,
.nav-icon-link.nav-current .nav-label {
    max-width: 300px;
    opacity: 1;
    margin-left: 0.4rem;
    color: var(--dmsp-primary-dark);
}

.nav-icon-link:hover .mdi,
.nav-icon-link.nav-current .mdi {
    color: var(--dmsp-primary-dark);
}

.nav-icon-link.nav-current {
    background: var(--dmsp-panel-tint);
    border-radius: 8px;
}

/* Used only during JS measurement — no flash, no transition */
.nav-icon-link.measuring .nav-label {
    max-width: none !important;
    opacity: 0 !important;
    margin-left: 0.4rem !important;
    transition: none !important;
}

/* On mobile (collapsed nav), always show labels */
@media (max-width: 991.98px) {
    .nav-icon-link .nav-label {
        max-width: 300px;
        opacity: 1;
        margin-left: 0.4rem;
    }
}

/* ===== DMS-Plus component library — see BRAND_IDENTITY.md ===== */

.dmsp-page-header{
  background:var(--dmsp-gradient-header);color:#fff;
  margin:0 calc(-0.5 * var(--bs-gutter-x, 1.5rem));padding:2.5rem 0;
  position:relative;overflow:hidden;border-radius:0;
}

.dmsp-avatar{
  width:42px;height:42px;border-radius:50%;background:rgba(255,255,255,.22);
  color:#fff;display:flex;align-items:center;justify-content:center;font-weight:600;
}

.dmsp-card{
  background:#fff;border-radius:15px;padding:1.75rem;
  border-left:4px solid var(--dmsp-primary);
  box-shadow:0 2px 10px rgba(0,0,0,.06);
  transition:transform .3s ease,box-shadow .3s ease;height:100%;
}
.dmsp-card:hover{transform:translateY(-3px);box-shadow:0 8px 25px rgba(0,0,0,.1)}
.dmsp-card-icon{
  width:42px;height:42px;border-radius:10px;background:var(--dmsp-panel-tint);
  color:var(--dmsp-primary-dark);display:inline-flex;align-items:center;justify-content:center;font-size:1.2rem;
}
.dmsp-card-title{font-size:1.05rem;font-weight:700;color:var(--dmsp-text-dark)}

.dmsp-btn-primary{
  display:inline-block;text-align:center;text-decoration:none;cursor:pointer;
  background:var(--dmsp-gradient-bold);color:#fff;border:none;border-radius:10px;
  padding:.6rem 1.1rem;font-weight:600;transition:transform .15s ease,box-shadow .15s ease;
}
.dmsp-btn-primary:hover{color:#fff;transform:translateY(-1px);box-shadow:0 6px 18px rgba(15,136,205,.3)}

.dmsp-setting-item{
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:.85rem 0;border-bottom:1px solid var(--dmsp-muted-tint);
}
.dmsp-setting-item:last-child{border-bottom:none}
.dmsp-setting-item small{color:var(--dmsp-text-muted)}

.dmsp-quick-link{
  display:flex;align-items:center;gap:.65rem;padding:.7rem .9rem;border-radius:10px;
  color:var(--dmsp-text-dark);text-decoration:none;transition:background .2s ease,color .2s ease,transform .2s ease;
}
.dmsp-quick-link:hover{background:var(--dmsp-bg-light);color:var(--dmsp-primary-dark);transform:translateX(4px)}
.dmsp-quick-link .mdi:first-child{color:var(--dmsp-icon-muted)}
.dmsp-quick-link:hover .mdi:first-child{color:var(--dmsp-primary-dark)}

.dmsp-table{width:100%;border-collapse:collapse}
.dmsp-table thead th{
  font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--dmsp-text-muted);border-bottom:2px solid var(--dmsp-panel-border);padding:.6rem .75rem;text-align:left;
}
.dmsp-table tbody td{padding:.7rem .75rem;border-bottom:1px solid #f1f1f1;color:var(--dmsp-text-dark)}
.dmsp-table tbody tr:hover{background:var(--dmsp-bg-light)}

.dmsp-badge{display:inline-flex;align-items:center;gap:.3rem;padding:.2rem .55rem;border-radius:999px;font-size:.72rem;font-weight:600}
.dmsp-badge--success{background:var(--dmsp-success-tint);color:var(--dmsp-success-text)}
.dmsp-badge--warning{background:var(--dmsp-warning-tint);color:var(--dmsp-warning-text)}
.dmsp-badge--danger{background:var(--dmsp-danger-tint);color:var(--dmsp-danger-text)}
.dmsp-badge--info{background:var(--dmsp-panel-tint);color:var(--dmsp-primary-dark)}
.dmsp-badge--muted{background:var(--dmsp-muted-tint);color:var(--dmsp-muted-text)}

.dmsp-avatar--brand{background:var(--dmsp-gradient-bold)}
.dmsp-avatar--sm{width:34px;height:34px;font-size:.8rem}

.dmsp-lang-label{background:var(--dmsp-gradient-bold);color:#fff;border:none}

/* ===== Chat components (assistant + tech_notes) — see BRAND_IDENTITY.md ===== */

/* Page wrapper: fills the viewport below the navbar. padding-top gives breathing room
   under the navbar now that the assistant chat has no page header. */
.dmsp-chat-page{display:flex;flex-direction:column;height:calc(100vh - 140px);min-height:420px;
  gap:1rem;padding-top:1rem}
.dmsp-chat-shell{flex:1 1 auto;min-height:0;display:flex;gap:1rem}

/* Conversation rail (assistant). Desktop: permanent side column. */
.dmsp-chat-rail{flex:0 0 var(--dmsp-chat-rail-w,200px);position:relative;
  display:flex;flex-direction:column;min-height:0;
  min-width:0;  /* honor the width basis; without this, flex min-width:auto expands the
                   rail to the widest nowrap conversation title instead of ellipsising it */
  border-right:1px solid var(--dmsp-muted-tint);padding-right:.75rem}
.dmsp-chat-rail-disclosure{min-height:0}
.dmsp-chat-rail-summary{display:none}
.dmsp-chat-rail-list{list-style:none;margin:.5rem 0 0;padding:0;overflow-y:auto}
.dmsp-chat-rail-list li{margin:0}
.dmsp-chat-rail-list a{display:block;padding:.45rem .6rem;border-radius:8px;
  color:var(--dmsp-text-dark);text-decoration:none;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;transition:background .15s ease}
.dmsp-chat-rail-list a:hover{background:var(--dmsp-panel-tint)}
.dmsp-chat-rail-list a.is-active{background:var(--dmsp-panel-tint);
  color:var(--dmsp-primary-dark);font-weight:600;box-shadow:inset 3px 0 0 var(--dmsp-primary)}

/* Desktop: rail disclosure is a flex column with a scrolling list; summary hidden. */
@media (min-width:768px){
  .dmsp-chat-rail-disclosure{flex:1 1 auto;display:flex;flex-direction:column}
  .dmsp-chat-rail-list{flex:1 1 auto}
}

/* Drag handle for the rail width (assistant only — spec 2026-07-27).
   Pure overlay covering the rail's border-right and the shell's 1rem gap:
   no flex child is inserted, so the shell's gap stays untouched. The 3px
   ::before bar lights up on hover/focus to advertise the affordance. */
.dmsp-chat-resizer{position:absolute;top:0;bottom:0;right:-1rem;width:1rem;
  cursor:col-resize;z-index:10;touch-action:none}
.dmsp-chat-resizer::before{content:"";position:absolute;top:0;bottom:0;left:0;
  width:3px;border-radius:2px;background:transparent;transition:background .15s ease}
.dmsp-chat-resizer:hover::before,
.dmsp-chat-resizer:focus-visible::before{background:var(--dmsp-primary)}
.dmsp-chat-resizer:focus-visible{outline:2px solid var(--dmsp-primary);outline-offset:-2px}
/* While dragging (class managed by pane_resize.js): no text selection, and a
   consistent cursor even when the pointer outruns the handle. */
body.dmsp-resizing{-webkit-user-select:none;user-select:none;cursor:col-resize}

/* Main column (assistant). */
.dmsp-chat-main{flex:1 1 auto;display:flex;flex-direction:column;min-width:0}

/* Scrollable message log (both pages). */
.dmsp-chat-log{flex:1 1 auto;overflow-y:auto;padding:.75rem;display:flex;
  flex-direction:column;gap:.6rem;background:#fff}
/* Bounded height for a log whose container is NOT a height-constrained flex column
   (Tech Notes' .dmsp-section-card is a plain block). Restores the internal scroll +
   auto-scroll-to-latest that the removed .chat-container{height:60vh} used to provide;
   the assistant log omits this and fills its flex column instead. */
.dmsp-chat-log--bounded{flex:none;height:60vh}

/* Message bubbles (both). */
.dmsp-chat-msg{max-width:80%;padding:.6rem .85rem;border-radius:12px;
  overflow-wrap:break-word;white-space:normal}
.dmsp-chat-msg--user{align-self:flex-end;background:var(--dmsp-primary);color:#fff}
.dmsp-chat-msg--assistant{align-self:flex-start;background:var(--dmsp-muted-tint);
  color:var(--dmsp-text-dark)}
.dmsp-chat-msg--user :is(a,strong,em,code){color:#fff}
.dmsp-chat-msg-meta{font-size:.7rem;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--dmsp-text-muted);margin-bottom:.25rem}
.dmsp-chat-msg--user .dmsp-chat-msg-meta{color:rgba(255,255,255,.85)}

/* Preserve the assistant's user-bubble literal-newline behaviour. */
.dmsp-chat-msg--user.dmsp-chat-msg--pre{white-space:pre-wrap;overflow-wrap:break-word}

/* Markdown body — add ALONGSIDE .markdown-body / .markdown-content (JS hooks untouched). */
.dmsp-chat-md p{margin:0 0 .5rem}
.dmsp-chat-md p:last-child{margin-bottom:0}
.dmsp-chat-md table{border-collapse:collapse;margin:.4rem 0}
.dmsp-chat-md th,.dmsp-chat-md td{border:1px solid var(--dmsp-panel-border);
  padding:.25rem .5rem;text-align:left}
.dmsp-chat-md code{background:var(--dmsp-panel-tint);color:var(--dmsp-primary-dark);
  padding:.05rem .3rem;border-radius:4px;font-family:monospace}
.dmsp-chat-md pre{background:var(--dmsp-bg-light);padding:.5rem;border-radius:6px;overflow-x:auto}
.dmsp-chat-msg--user .dmsp-chat-md code{background:rgba(255,255,255,.2);color:#fff}
.dmsp-chat-msg--user .dmsp-chat-md pre{background:rgba(0,0,0,.2);color:#fff}
/* Headings/lists/quotes/rules emitted by the shared renderer since 2026-07-21.
   Scoped to .dmsp-chat-md — the hook BOTH AI chats carry (assistant on
   .markdown-body, Tech Notes on .markdown-content) — because they now share one
   renderer; scoping to .markdown-body left Tech Notes with unstyled lists and,
   worse, no scroll container for the tables it just started rendering.
   h1-h3 are covered too: the sanitiser allows them and marked emits them for
   #/##/###, so without these rules an answer opening "## Estimé" rendered at
   Bootstrap page scale (~2rem) inside an 80%-wide bubble. Sized DOWN: a bubble
   heading labels a section of one answer, not a page. */
.dmsp-chat-md h1,.dmsp-chat-md h2,.dmsp-chat-md h3,
.dmsp-chat-md h4,.dmsp-chat-md h5,.dmsp-chat-md h6{margin:.6rem 0 .3rem;
  font-weight:600;line-height:1.3}
.dmsp-chat-md h1,.dmsp-chat-md h2,.dmsp-chat-md h4{font-size:1rem}
.dmsp-chat-md h3,.dmsp-chat-md h5{font-size:.94rem}
.dmsp-chat-md h6{font-size:.88rem;color:var(--dmsp-text-muted)}
.dmsp-chat-md :is(h1,h2,h3,h4,h5,h6):first-child{margin-top:0}
.dmsp-chat-md ul,.dmsp-chat-md ol{margin:0 0 .5rem;padding-left:1.25rem}
.dmsp-chat-md li{margin:.1rem 0}
.dmsp-chat-md li>p{margin:0}
.dmsp-chat-md blockquote{margin:.4rem 0;padding:.15rem 0 .15rem .6rem;
  border-left:3px solid var(--dmsp-panel-border);color:var(--dmsp-text-muted)}
.dmsp-chat-md blockquote>:last-child{margin-bottom:0}
.dmsp-chat-md hr{margin:.6rem 0;border:0;border-top:1px solid var(--dmsp-panel-border)}
/* A wide estimate table must scroll inside the bubble, never widen the chat log.
   Applied to the TABLE, not the whole body: making the body a scroll container
   turns every bubble into one and nests a second scroller inside each <pre>. */
.dmsp-chat-md table{display:block;width:max-content;max-width:100%;overflow-x:auto}
/* Assistant chat inline links (tool-minted in-app URLs only). */
.dmsp-chat-md a.dmsp-chat-link{text-decoration:underline}

/* Assistant chat date separators (timestamps feature). */
.dmsp-chat-daysep{text-align:center;font-size:.78rem;color:var(--dmsp-text-muted);
  margin:.75rem 0 .35rem;user-select:none}

/* Composer (both). */
.dmsp-chat-composer{display:flex;gap:.5rem;align-items:flex-end;padding-top:.6rem;
  border-top:1px solid var(--dmsp-muted-tint)}
.dmsp-chat-input{flex:1 1 auto;resize:none;padding:.55rem .7rem;border-radius:10px;
  border:1px solid var(--dmsp-panel-border);font:inherit;color:var(--dmsp-text-dark);background:#fff}
.dmsp-chat-input:focus{outline:none;border-color:var(--dmsp-primary);
  box-shadow:0 0 0 3px var(--dmsp-panel-tint)}

/* "Thinking…" dots (both). */
.dmsp-chat-typing{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;
  color:var(--dmsp-text-muted);font-style:italic}
.dmsp-chat-typing-dots{display:flex;gap:.25rem}
.dmsp-chat-typing-dots span{width:8px;height:8px;border-radius:50%;
  background:var(--dmsp-primary);animation:dmspChatTyping 1.4s infinite ease-in-out}
.dmsp-chat-typing-dots span:nth-child(1){animation-delay:-.32s}
.dmsp-chat-typing-dots span:nth-child(2){animation-delay:-.16s}
@keyframes dmspChatTyping{0%,80%,100%{transform:scale(.8);opacity:.5}40%{transform:scale(1);opacity:1}}
@media (prefers-reduced-motion: reduce){.dmsp-chat-typing-dots span{animation:none}}

/* Repair-order confirmation card (spec 2026-09-02 §4). Painted by
   staticfiles/js/work_order_card.js into #work-order-card, a SIBLING of the message
   log — never a bubble, and deliberately not styled like one: this is the one control
   in the app that dispatches a DMS write, and it must not read as something the
   assistant said. */
.dmsp-wo-card{margin:.5rem;padding:.75rem .9rem;border-radius:12px;
  border:1px solid var(--dmsp-primary);background:var(--dmsp-panel-tint);
  font-size:.9rem;display:flex;flex-direction:column;gap:.4rem}
.dmsp-wo-head{display:flex;align-items:baseline;gap:.5rem;flex-wrap:wrap}
.dmsp-wo-title{font-weight:700}
.dmsp-wo-flow{font-size:.78rem;text-transform:uppercase;letter-spacing:.05em;
  color:var(--dmsp-text-muted)}
.dmsp-wo-rows{display:flex;flex-direction:column;gap:.15rem}
.dmsp-wo-row{display:flex;gap:.5rem;align-items:baseline}
.dmsp-wo-label{flex:0 0 auto;min-width:7rem;font-weight:600;
  color:var(--dmsp-text-muted)}
.dmsp-wo-value{overflow-wrap:anywhere}
.dmsp-wo-ops{margin:0;padding-left:1.25rem}
.dmsp-wo-ops li{margin:.1rem 0;overflow-wrap:anywhere}
.dmsp-wo-warn{padding:.35rem .55rem;border-radius:8px;
  background:var(--dmsp-warning-tint);color:var(--dmsp-warning-text)}
.dmsp-wo-state{font-weight:600}
.dmsp-wo-actions{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:.2rem}
.dmsp-wo-decline{border:1px solid var(--dmsp-panel-border);background:#fff}
.dmsp-wo-actions button[disabled]{opacity:.6;cursor:default}
/* A refusal the server sent back. --other marks one that is about a DIFFERENT draft
   than the card underneath it, so it is detached rather than read as a caption. */
.dmsp-wo-notice{padding:.4rem .6rem;border-radius:8px;
  background:var(--dmsp-warning-tint);color:var(--dmsp-warning-text)}
.dmsp-wo-notice--other{border:1px dashed var(--dmsp-warning-text)}
.dmsp-wo-notice strong{margin-right:.35rem}

/* Assistant tool-activity lines. */
.dmsp-chat-activity{padding:0 .5rem}
.dmsp-chat-activity-line{font-size:.85rem;color:var(--dmsp-text-muted);padding:.15rem 0;
  display:flex;align-items:center;gap:.4rem}
.dmsp-chat-activity-spin{display:inline-block;animation:spin 1s linear infinite}

/* Assistant full-width agent status banner (data-online is authoritative; keep it). */
.dmsp-chat-banner{margin-bottom:.5rem;padding:.55rem .9rem;border-radius:10px;font-size:.9rem}
.dmsp-chat-banner[data-online="1"]{background:var(--dmsp-success-tint);color:var(--dmsp-success-text)}
.dmsp-chat-banner[data-online="0"]{background:var(--dmsp-warning-tint);color:var(--dmsp-warning-text)}
/* Shared-capacity info tone (sharing spec §8.4). Compound selector so it beats the
   [data-online="0"] rule on specificity regardless of source order. */
.dmsp-chat-banner[data-online="0"][data-shared="1"]{background:var(--dmsp-info-tint);color:var(--dmsp-info-text)}
/* Outdated-agent update nudge (update-nudge spec §5): warning tone must beat the
   [data-online="1"] success tint — same compound-specificity trick as data-shared. */
.dmsp-chat-banner[data-online="1"][data-outdated="1"]{background:var(--dmsp-warning-tint);color:var(--dmsp-warning-text)}
.dmsp-chat-banner[data-online="1"][data-outdated="1"] a{color:var(--dmsp-warning-text)}

/* Toast. */
.dmsp-chat-toast{position:fixed;bottom:1.25rem;left:50%;transform:translateX(-50%);
  background:var(--dmsp-text-dark);color:#fff;padding:.6rem 1rem;border-radius:10px;
  opacity:0;pointer-events:none;transition:opacity .2s;z-index:1080}
.dmsp-chat-toast.show{opacity:1}

/* Connect panel (agent_bridge partial made self-styling; warning-tinted). */
.dmsp-connect{margin-bottom:.5rem;padding:.9rem 1rem;border-radius:12px;
  background:var(--dmsp-warning-tint);color:var(--dmsp-warning-text)}
.dmsp-connect .connect-title{margin:0 0 .35rem;font-size:1rem}
.dmsp-connect .connect-lede{margin:0 0 .6rem}
.dmsp-connect .connect-steps{margin:.4rem 0;padding-left:1.2rem}
.dmsp-connect .connect-steps code,.dmsp-connect .connect-help code{
  background:#fff;color:var(--dmsp-warning-text);padding:.05rem .3rem;
  border-radius:4px;font-family:monospace}
.dmsp-connect .connect-note{font-size:.85rem;opacity:.85;margin:.3rem 0 .5rem}
.dmsp-connect .connect-help{margin:.5rem 0}
.dmsp-connect .connect-help summary{cursor:pointer}
.dmsp-connect .connect-toggle-link{background:none;border:none;padding:0;margin-top:.5rem;
  color:var(--dmsp-warning-text);text-decoration:underline;cursor:pointer;font:inherit;display:block}
.dmsp-connect .connect-status{margin-top:.5rem;font-size:.9rem}

/* Mobile: rail collapses to a <details> disclosure and stacks ABOVE the chat.
   Keep the bounded .dmsp-chat-page height (from the base rule) so the log still
   scrolls INTERNALLY and the composer stays pinned — do NOT switch to height:auto,
   which unbinds the log and pushes the composer off-screen as messages accumulate. */
@media (max-width:767.98px){
  .dmsp-chat-shell{flex-direction:column}
  .dmsp-chat-rail{flex:0 0 auto;border-right:none;padding-right:0}
  .dmsp-chat-resizer{display:none}
  .dmsp-chat-rail-summary{display:flex;align-items:center;gap:.4rem;cursor:pointer;
    padding:.5rem .7rem;border-radius:10px;background:var(--dmsp-panel-tint);
    color:var(--dmsp-primary-dark);font-weight:600;list-style:none}
  .dmsp-chat-rail-summary::-webkit-details-marker{display:none}
  .dmsp-chat-rail-list{max-height:45vh}
}

/* Messages float over the page (fixed) instead of pushing content down.
   Container ignores pointer events so the empty padding doesn't block clicks;
   the alerts themselves re-enable them so the close button still works. */
.alert-container{position:fixed;top:calc(56px + .75rem);left:50%;transform:translateX(-50%);z-index:998;width:100%;max-width:900px;padding:0 1rem;pointer-events:none}
.alert-container .alert{border:none;border-left:4px solid var(--dmsp-primary);pointer-events:auto;box-shadow:0 .5rem 1.5rem rgba(0,0,0,.18);animation:dmspAlertIn .25s ease-out}
@keyframes dmspAlertIn{from{opacity:0;transform:translateY(-12px)}to{opacity:1;transform:translateY(0)}}
@media (prefers-reduced-motion: reduce){.alert-container .alert{animation:none}}
.alert-container .alert.alert-success{border-left-color:var(--dmsp-success)}
.alert-container .alert.alert-danger{border-left-color:var(--dmsp-danger)}
.alert-container .alert.alert-warning{border-left-color:var(--dmsp-warning)}

/* ===== Gradient page header wave + page section (header base is in the component library above) ===== */
.dmsp-page-header::before{
  content:'';position:absolute;inset:0;
  background:url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 100" fill="white" opacity="0.06"><path d="M0,0v46.29c47.79,22.2,103.59,32.17,158,28,70.36-5.37,136.33-33.31,206.8-37.5C438.64,32.43,512.34,53.67,583,72.05c69.27,18,138.3,24.88,209.4,13.08,36.15-6,69.85-17.84,104.45-29.34C989.49,25,1047.58,5.33,1100,1.36V0Z"/></svg>') repeat-x;
  background-size:1000px 100px;animation:dmspWave 20s linear infinite;
}
@media (prefers-reduced-motion: reduce){.dmsp-page-header::before{animation:none}}
@keyframes dmspWave{0%{background-position-x:0}100%{background-position-x:1000px}}
.dmsp-page-header-content{position:relative;z-index:1;display:flex;align-items:center;gap:1.5rem}
.dmsp-page-header-avatar{
  width:72px;height:72px;border-radius:50%;background:rgba(255,255,255,.2);
  border:3px solid rgba(255,255,255,.5);display:flex;align-items:center;justify-content:center;
  flex-shrink:0;overflow:hidden;color:#fff;font-size:1.6rem;font-weight:700;letter-spacing:1px;
}
.dmsp-page-header-avatar .mdi{font-size:2rem}
.dmsp-page-header-avatar img{width:52px;height:52px;object-fit:contain}
.dmsp-page-header-info h1{color:#fff;font-size:1.75rem;font-weight:700;margin-bottom:.25rem}
/* The subtitle used to sit at opacity:.85, which dropped it to 2.9:1 on the
   gradient. Small text cannot pay for hierarchy with transparency -- the
   demotion here comes from size and weight instead, and the colour stays solid. */
.dmsp-page-header-info p{color:#fff;opacity:1;margin-bottom:0;font-size:.95rem;font-weight:400}
.dmsp-page-section{padding:2.5rem 0 3rem}
/* Inset variant for app pages that live inside the sidebar layout (no full-bleed). */
.dmsp-page-header--inset{margin:0;border-radius:12px;padding:1.5rem}
.dmsp-page-header--inset .dmsp-page-header-avatar{width:52px;height:52px}
.dmsp-page-header--inset .dmsp-page-header-info h1{font-size:1.4rem}

/* ===== On-banner controls ==============================================
   Anything dropped inside a gradient banner is remapped here to a
   white-on-blue idiom. Both banners are addressed through one :is() list so
   coverage cannot drift between them -- an earlier hand-duplicated version
   left .dmsp-public-header without the semantic variants.

   Why this is scoped rather than fixed template-by-template: the banner markup
   lives in ~55 templates that between them use .btn-primary, .btn-secondary,
   .btn-danger, every .btn-outline-* variant, .dmsp-btn-primary, .badge.bg-*,
   bare links and .text-muted. Measured against the banner, all of them landed
   between 1.2:1 and 2.7:1 -- .btn-primary is the worst at 1.33:1 because the
   brand override paints it #0f88cd, the banner's own colour.

   Variants work by re-pointing the --dmsp-ob-* aliases rather than restating
   every --bs-btn-* property: custom properties resolve per element, so a rule
   that only swaps --dmsp-ob-fill changes the fill the base rule already wired
   up. Adding a hue is four declarations, not fourteen.
   ====================================================================== */

:is(.dmsp-page-header, .dmsp-public-header) .btn{
  --dmsp-ob-fill:var(--dmsp-on-banner-fill);
  --dmsp-ob-fill-hover:var(--dmsp-on-banner-fill-hover);
  --dmsp-ob-ink:#fff;
  --dmsp-ob-ink-hover:#fff;
  --dmsp-ob-edge:var(--dmsp-on-banner-border);
  --dmsp-ob-edge-hover:var(--dmsp-on-banner-border-hover);

  --bs-btn-color:var(--dmsp-ob-ink);
  --bs-btn-bg:var(--dmsp-ob-fill);
  --bs-btn-border-color:var(--dmsp-ob-edge);
  --bs-btn-hover-color:var(--dmsp-ob-ink-hover);
  --bs-btn-hover-bg:var(--dmsp-ob-fill-hover);
  --bs-btn-hover-border-color:var(--dmsp-ob-edge-hover);
  --bs-btn-active-color:var(--dmsp-ob-ink-hover);
  --bs-btn-active-bg:var(--dmsp-ob-fill-hover);
  --bs-btn-active-border-color:var(--dmsp-ob-edge-hover);
  /* Bootstrap already dims disabled buttons with --bs-btn-disabled-opacity:.65.
     Fading the ink as well multiplies the two and lands near 1.95:1, so the
     colours here stay solid and let that one opacity do the work. */
  --bs-btn-disabled-color:var(--dmsp-ob-ink);
  --bs-btn-disabled-bg:var(--dmsp-ob-fill);
  --bs-btn-disabled-border-color:var(--dmsp-ob-edge);
  --bs-btn-focus-shadow-rgb:255,255,255;
  font-weight:600;
}

/* The page's main action reads as a solid white chip: the strongest available
   figure/ground on blue (fill 3.4:1-4.8:1 vs the banner) with a dark brand
   label on top (5.9:1). Driving it through the aliases rather than a bare
   `background` matters: a static background here would outrank .btn:hover on
   source order at equal specificity and freeze the chip on hover. */
:is(.dmsp-page-header, .dmsp-public-header) .btn-primary{
  --dmsp-ob-fill:var(--dmsp-on-banner-chip);
  --dmsp-ob-fill-hover:var(--dmsp-on-banner-chip-hover);
  --dmsp-ob-ink:var(--dmsp-primary-dark);
  --dmsp-ob-ink-hover:var(--dmsp-primary-dark);
  --dmsp-ob-edge:var(--dmsp-on-banner-chip);
  --dmsp-ob-edge-hover:var(--dmsp-on-banner-chip-hover);
  --bs-btn-active-bg:var(--dmsp-on-banner-chip-active);
  --bs-btn-active-border-color:var(--dmsp-on-banner-chip-active);
  box-shadow:0 2px 8px rgba(0,0,0,.18);
}

/* .dmsp-btn-primary and .dmsp-save-btn are not Bootstrap buttons, so the
   --bs-btn-* wiring above does nothing for them and they need real
   declarations -- including their own :hover, for the source-order reason
   described above. Both were previously the banner gradient drawn on itself. */
:is(.dmsp-page-header, .dmsp-public-header) :is(.dmsp-btn-primary, .dmsp-save-btn){
  background:var(--dmsp-on-banner-chip);
  color:var(--dmsp-primary-dark);
  border:1px solid var(--dmsp-on-banner-chip);
  box-shadow:0 2px 8px rgba(0,0,0,.18);
}
:is(.dmsp-page-header, .dmsp-public-header) :is(.dmsp-btn-primary, .dmsp-save-btn):hover{
  background:var(--dmsp-on-banner-chip-hover);
  color:var(--dmsp-primary-dark);
  box-shadow:0 4px 14px rgba(0,0,0,.24);
}
:is(.dmsp-page-header, .dmsp-public-header) :is(.dmsp-btn-primary, .dmsp-save-btn):active{
  background:var(--dmsp-on-banner-chip-active);
}

/* Destructive and status actions keep their meaning: colour survives as a
   tinted label on a dark wash of the same hue. */
:is(.dmsp-page-header, .dmsp-public-header) :is(.btn-danger, .btn-outline-danger){
  --dmsp-ob-fill:var(--dmsp-on-banner-danger-fill);
  --dmsp-ob-fill-hover:var(--dmsp-on-banner-danger-fill-hover);
  --dmsp-ob-ink:var(--dmsp-on-banner-danger-text);
  --dmsp-ob-edge:var(--dmsp-on-banner-danger-border);
}
:is(.dmsp-page-header, .dmsp-public-header) :is(.btn-success, .btn-outline-success){
  --dmsp-ob-fill:var(--dmsp-on-banner-success-fill);
  --dmsp-ob-fill-hover:var(--dmsp-on-banner-success-fill-hover);
  --dmsp-ob-ink:var(--dmsp-on-banner-success-text);
  --dmsp-ob-edge:var(--dmsp-on-banner-success-border);
}
:is(.dmsp-page-header, .dmsp-public-header) :is(.btn-warning, .btn-outline-warning){
  --dmsp-ob-fill:var(--dmsp-on-banner-warning-fill);
  --dmsp-ob-fill-hover:var(--dmsp-on-banner-warning-fill-hover);
  --dmsp-ob-ink:var(--dmsp-on-banner-warning-text);
  --dmsp-ob-edge:var(--dmsp-on-banner-warning-border);
}
:is(.dmsp-page-header, .dmsp-public-header) :is(.btn-info, .btn-outline-info){
  --dmsp-ob-fill:var(--dmsp-on-banner-info-fill);
  --dmsp-ob-fill-hover:var(--dmsp-on-banner-info-fill-hover);
  --dmsp-ob-ink:var(--dmsp-on-banner-info-text);
  --dmsp-ob-edge:var(--dmsp-on-banner-info-border);
}

/* Keyboard focus needs a ring that survives on blue -- Bootstrap's default
   focus shadow is tinted by the button variant and disappears here. */
:is(.dmsp-page-header, .dmsp-public-header) :is(.btn, .dmsp-btn-primary, .dmsp-save-btn):focus-visible{
  outline:2px solid #fff;outline-offset:2px;
  box-shadow:0 0 0 4px var(--dmsp-on-banner-focus-ring);
}

/* Badges. The .bg-* utilities are !important, so these have to be too. */
:is(.dmsp-page-header, .dmsp-public-header) .badge{
  background:var(--dmsp-on-banner-fill)!important;
  color:#fff!important;
  border:1px solid var(--dmsp-on-banner-border);
  font-weight:600;
}
:is(.dmsp-page-header, .dmsp-public-header) .badge.bg-success{
  background:var(--dmsp-on-banner-success-fill)!important;color:var(--dmsp-on-banner-success-text)!important;
  border-color:var(--dmsp-on-banner-success-border);
}
:is(.dmsp-page-header, .dmsp-public-header) :is(.badge.bg-primary, .badge.bg-info){
  background:var(--dmsp-on-banner-info-fill)!important;color:var(--dmsp-on-banner-info-text)!important;
  border-color:var(--dmsp-on-banner-info-border);
}
:is(.dmsp-page-header, .dmsp-public-header) .badge.bg-warning{
  background:var(--dmsp-on-banner-warning-fill)!important;color:var(--dmsp-on-banner-warning-text)!important;
  border-color:var(--dmsp-on-banner-warning-border);
}
:is(.dmsp-page-header, .dmsp-public-header) .badge.bg-danger{
  background:var(--dmsp-on-banner-danger-fill)!important;color:var(--dmsp-on-banner-danger-text)!important;
  border-color:var(--dmsp-on-banner-danger-border);
}

/* Links inside the banner inherited Bootstrap's #0d6efd -- 1.23:1 on the
   gradient, the single worst element measured. Underlined white instead.

   The underline is !important because .text-decoration-none is: several
   templates carry it to suppress an ugly blue underline on a white page, and
   without !important the link here would end up white text inside white text
   with no affordance at all (the VIN on vehicle_orders/vehicle_detail.html).
   The :not() chain lists the link-shaped controls that already carry their own
   on-banner styling -- .cal-nav-btn--today in particular is a solid white chip,
   and forcing white text onto it made it 1.00:1. Add any future one here. */
:is(.dmsp-page-header, .dmsp-public-header) a:not(.btn):not(.dmsp-btn-primary):not(.dmsp-save-btn):not(.badge):not(.cal-nav-btn){
  color:#fff;text-decoration:underline!important;text-underline-offset:2px;
}
:is(.dmsp-page-header, .dmsp-public-header) a:not(.btn):not(.dmsp-btn-primary):not(.dmsp-save-btn):not(.badge):not(.cal-nav-btn):hover{
  color:#fff;text-decoration-thickness:2px;
}

/* .text-muted is rgba(33,37,41,.75) -- dark grey, meant for white pages. On the
   banner it read as smudged charcoal on blue. Nothing "muted" can be expressed
   in ink here, so it becomes plain white and the demotion is left to size. */
:is(.dmsp-page-header, .dmsp-public-header) :is(.text-muted, .text-dark, .text-body-secondary){
  color:#fff!important;
}

@media (max-width:767.98px){
  .dmsp-page-header-content{flex-direction:column;text-align:center}
  .dmsp-page-header-info h1{font-size:1.4rem}
  .dmsp-page-section{padding:1.5rem 0 2rem}
}

/* ===== Save button (larger primary action) ===== */
.dmsp-save-btn{
  display:inline-block;cursor:pointer;background:var(--dmsp-gradient-bold);color:#fff;border:none;
  padding:.7rem 2.5rem;border-radius:10px;font-weight:600;font-size:1rem;
  transition:transform .3s ease,box-shadow .3s ease;
}
.dmsp-save-btn:hover{color:#fff;transform:translateY(-2px);box-shadow:0 6px 20px rgba(15,136,205,.3)}

/* ===== Profile: phone verification badge ===== */
.dmsp-phone-status{display:inline-flex;align-items:center;gap:.35rem;font-size:.8rem;font-weight:600;padding:.2rem .6rem;border-radius:20px}
.dmsp-phone-status.verified{background:#dcfce7;color:#065f46}
.dmsp-phone-status.unverified{background:#fee2e2;color:#991b1b}

/* ===== Dealer: header badge + team member list + invite ===== */
.dmsp-sub-badge{display:inline-flex;align-items:center;gap:.35rem;font-size:.8rem;font-weight:600;padding:.25rem .7rem;border-radius:20px;color:#fff;background:var(--dmsp-on-banner-fill);border:1px solid var(--dmsp-on-banner-border)}
.dmsp-member-item{display:flex;align-items:center;gap:.75rem;padding:.6rem .85rem;border-radius:10px;transition:background-color .2s ease;margin-bottom:.25rem}
.dmsp-member-item:hover{background:var(--dmsp-bg-light)}
.dmsp-member-avatar{width:34px;height:34px;border-radius:50%;background:var(--dmsp-panel-tint);color:var(--dmsp-primary-dark);display:flex;align-items:center;justify-content:center;font-size:.75rem;font-weight:700;flex-shrink:0}
.dmsp-member-info{flex:1;min-width:0}
.dmsp-member-name{font-weight:600;font-size:.9rem;color:var(--dmsp-text-dark);line-height:1.3}
.dmsp-member-email{font-size:.78rem;color:var(--dmsp-text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dmsp-member-remove{flex-shrink:0;width:28px;height:28px;border-radius:50%;border:none;background:none;color:#cbd5e1;display:flex;align-items:center;justify-content:center;font-size:1rem;cursor:pointer;transition:all .2s ease}
.dmsp-member-remove:hover{background:#fee2e2;color:var(--dmsp-danger)}
.dmsp-invite-form{display:flex;gap:.5rem;margin-bottom:1.25rem}
@media (max-width:767.98px){.dmsp-invite-form{flex-direction:column}}

/* ===== Navbar account avatar dropdown (right side) ===== */
.dmsp-nav-avatar-trigger{padding:0 !important;background:none !important}
.dmsp-nav-avatar-trigger:hover,.dmsp-nav-avatar-trigger:focus{background:none !important}
.dmsp-nav-avatar-trigger .dmsp-avatar{transition:transform .15s ease,box-shadow .15s ease}
.dmsp-nav-avatar-trigger:hover .dmsp-avatar{transform:scale(1.08);box-shadow:0 2px 10px rgba(15,136,205,.3)}
.dmsp-dropdown{border:none !important;border-radius:.5rem !important;box-shadow:0 8px 30px rgba(0,0,0,.15) !important;padding:.35rem !important;min-width:12rem}
.dmsp-dropdown .dropdown-item{border-radius:.35rem;padding:.5rem .75rem;font-weight:500;color:var(--dmsp-text-dark);transition:color .15s ease,background-color .15s ease}
.dmsp-dropdown .dropdown-item:hover,.dmsp-dropdown .dropdown-item:focus{background-color:var(--dmsp-panel-tint);color:var(--dmsp-primary-dark)}
.dmsp-dropdown .dropdown-item .mdi{font-size:1.1em;vertical-align:-2px;color:var(--dmsp-icon-muted);transition:color .15s ease}
.dmsp-dropdown .dropdown-item:hover .mdi,.dmsp-dropdown .dropdown-item:focus .mdi{color:var(--dmsp-primary-dark)}
.dmsp-dropdown-dealer-logo{width:20px;height:20px;object-fit:contain;border-radius:4px;vertical-align:-3px}
.dmsp-dropdown-logout{color:var(--dmsp-danger) !important;border:none;background:none;width:100%;text-align:left;cursor:pointer}
.dmsp-dropdown-logout:hover,.dmsp-dropdown-logout:focus{background-color:#fff1f0 !important;color:var(--dmsp-danger) !important}
.dmsp-dropdown-logout .mdi{color:var(--dmsp-danger) !important}

/* ===== Account-management sub-nav (allauth manage pages) ===== */
.account-subnav{background:#fff;border-left:4px solid var(--dmsp-primary);border-radius:15px;padding:1rem;box-shadow:0 2px 10px rgba(0,0,0,.06)}
.account-subnav .nav-link{display:flex;align-items:center;color:var(--dmsp-text-dark);border-radius:8px;padding:.5rem .75rem;margin:.1rem 0;font-weight:500;transition:background-color .15s ease,color .15s ease}
.account-subnav .nav-link:hover{background:var(--dmsp-bg-light);color:var(--dmsp-primary-dark)}
.account-subnav .nav-link.active{background:var(--dmsp-panel-tint);color:var(--dmsp-primary-dark);font-weight:600}

/* ===== Brand Bootstrap primary buttons + form focus to the dmsp palette =====
   Re-themes Bootstrap's CSS vars so allauth element buttons (manage pages) and any
   remaining .btn-primary pick up the brand blue without per-template edits. */
.btn-primary{--bs-btn-bg:var(--dmsp-primary);--bs-btn-border-color:var(--dmsp-primary);--bs-btn-hover-bg:var(--dmsp-primary-dark);--bs-btn-hover-border-color:var(--dmsp-primary-dark);--bs-btn-active-bg:var(--dmsp-primary-dark);--bs-btn-active-border-color:var(--dmsp-primary-dark)}
.btn-outline-primary{--bs-btn-color:var(--dmsp-primary-dark);--bs-btn-border-color:var(--dmsp-primary);--bs-btn-hover-bg:var(--dmsp-primary);--bs-btn-hover-border-color:var(--dmsp-primary);--bs-btn-active-bg:var(--dmsp-primary-dark);--bs-btn-active-border-color:var(--dmsp-primary-dark)}
.form-control:focus,.form-select:focus{border-color:var(--dmsp-primary);box-shadow:0 0 0 .2rem rgba(15,136,205,.45)}

/* ===== Loaners redesign primitives (Task 3) — see BRAND_IDENTITY.md §6 ===== */

/* 1. Section card — replaces <hr>-separated sections on detail pages. */
.dmsp-section-card{
  background:#fff;border-radius:15px;border-left:4px solid var(--dmsp-primary);
  box-shadow:0 2px 10px rgba(0,0,0,.06);padding:1.5rem 1.65rem;margin-bottom:1.5rem;
}
.dmsp-section-card-header{
  display:flex;align-items:center;gap:.75rem;
  padding-bottom:.85rem;margin-bottom:1.15rem;border-bottom:1px solid var(--dmsp-muted-tint);
}
.dmsp-section-card-header .dmsp-card-icon{flex-shrink:0;width:36px;height:36px;font-size:1.05rem}
.dmsp-section-card-title{
  font-size:1.05rem;font-weight:700;color:var(--dmsp-text-dark);margin:0;line-height:1.2;
}
.dmsp-section-card-header .dmsp-section-card-action{margin-left:auto;display:flex;align-items:center;gap:.5rem}

/* 2. Stat tile — compact summary metric, tiles in a flex/grid strip. */
.dmsp-stat{
  display:flex;flex-direction:column;gap:.2rem;min-width:0;
  padding:.85rem 1.1rem;background:var(--dmsp-bg-light);border-radius:12px;
  border:1px solid var(--dmsp-muted-tint);
}
.dmsp-stat-label{
  font-size:.7rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--dmsp-text-muted);line-height:1.2;
}
.dmsp-stat-value{
  font-size:1.35rem;font-weight:700;color:var(--dmsp-text-dark);line-height:1.2;
}

/* 3. Meter — horizontal progress bar; width set inline on the fill. */
.dmsp-meter{
  width:100%;height:8px;border-radius:999px;background:var(--dmsp-muted-tint);overflow:hidden;
}
.dmsp-meter-fill{
  display:block;height:100%;max-width:100%;
  background:var(--dmsp-gradient-bold);transition:width .4s ease;
}
.dmsp-meter-fill.over{background:var(--dmsp-danger)}

/* 4. Photo grid — responsive thumbnail grid of tap/click targets. */
.dmsp-photo-grid{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:.6rem;
}
.dmsp-photo-grid--lg{grid-template-columns:repeat(auto-fill,minmax(160px,1fr))}
.dmsp-photo-grid a,.dmsp-photo-grid .dmsp-photo-grid-item{
  display:block;aspect-ratio:1;border-radius:10px;overflow:hidden;
  background:var(--dmsp-muted-tint);cursor:pointer;
  transition:transform .2s ease,box-shadow .2s ease;
}
.dmsp-photo-grid a:hover,.dmsp-photo-grid .dmsp-photo-grid-item:hover{
  transform:translateY(-2px);box-shadow:0 6px 18px rgba(0,0,0,.12);
}
.dmsp-photo-grid img{width:100%;height:100%;object-fit:cover;display:block}

/* 5. Form card — centered max-width wrapper for form pages. */
.dmsp-form-card{
  background:#fff;border-radius:15px;border-left:4px solid var(--dmsp-primary);
  box-shadow:0 2px 10px rgba(0,0,0,.06);
  max-width:640px;margin:0 auto;padding:2rem 2.25rem;
}
@media (max-width:576px){.dmsp-form-card{padding:1.5rem 1.25rem}}
/* Wide modifier — for forms that need room (e.g. a rich-text body editor). */
.dmsp-form-card--wide{max-width:920px}

/* 5b. Token panel — copyable merge-field / anchor chips inside the form card. */
.dmsp-token-panel{
  background:var(--dmsp-bg-light);border:1px solid var(--dmsp-muted-tint);
  border-radius:12px;padding:1rem 1.15rem;
}
.dmsp-token-panel-title{font-size:.9rem;font-weight:700;color:var(--dmsp-text-dark)}
.dmsp-token-group{margin-top:.65rem}
.dmsp-token-group-label{
  display:block;font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--dmsp-text-muted);margin-bottom:.4rem;
}
.dmsp-token-chips{display:flex;flex-wrap:wrap;gap:.4rem}
.dmsp-token{
  cursor:pointer;display:inline-block;padding:.25rem .55rem;border-radius:8px;
  background:#fff;border:1px solid var(--dmsp-muted-tint);
  font-size:.78rem;color:var(--dmsp-primary-dark);
  transition:border-color .15s ease,background-color .15s ease,transform .1s ease;
}
.dmsp-token:hover{border-color:var(--dmsp-panel-border);background:var(--dmsp-panel-tint)}
.dmsp-token:active{transform:translateY(1px)}

/* 5c. Doc paper — a "printed page" frame for previewing rendered document HTML. */
.dmsp-doc-paper{
  background:var(--dmsp-bg-light);border-radius:12px;
  padding:1.25rem;display:flex;justify-content:center;
}
.dmsp-doc-paper-frame{
  width:100%;max-width:816px;height:75vh;border:none;border-radius:6px;background:#fff;
  box-shadow:0 4px 24px rgba(0,0,0,.12);
}

/* 7. Filter pills — segmented links that drive a GET param (e.g. ?status=). */
.dmsp-filter-pills{display:flex;flex-wrap:wrap;gap:.5rem;margin-bottom:1.25rem}
.dmsp-filter-pill{
  display:inline-flex;align-items:center;gap:.35rem;
  padding:.35rem .85rem;border-radius:999px;font-size:.82rem;font-weight:600;
  text-decoration:none;color:var(--dmsp-text-muted);
  background:#fff;border:1px solid var(--dmsp-muted-tint);
  transition:color .15s ease,background-color .15s ease,border-color .15s ease;
}
.dmsp-filter-pill:hover{color:var(--dmsp-primary-dark);border-color:var(--dmsp-panel-border);background:var(--dmsp-bg-light)}
.dmsp-filter-pill.is-active{
  color:#fff;background:var(--dmsp-gradient-bold);border-color:transparent;
  box-shadow:0 2px 8px rgba(15,136,205,.25);
}
.dmsp-filter-pill.is-active:hover{color:#fff}

/* 8. Overdue table row — danger left-accent to flag past-due active loans. */
.dmsp-table tbody tr.dmsp-row--overdue td:first-child{
  box-shadow:inset 3px 0 0 0 var(--dmsp-danger);
}
.dmsp-row-flag--overdue{
  display:inline-flex;align-items:center;gap:.2rem;margin-left:.4rem;
  font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;
  color:var(--dmsp-danger-text);
}

/* Whole-row link: a real anchor in the first cell keeps the row keyboard-
   reachable; the row's onclick is a mouse-only convenience on top of it. */
.dmsp-table tbody tr.dmsp-row-link td:first-child .dmsp-row-link-target{
  color:inherit;text-decoration:none;font-weight:600;
}
.dmsp-table tbody tr.dmsp-row-link:hover td:first-child .dmsp-row-link-target,
.dmsp-table tbody tr.dmsp-row-link td:first-child .dmsp-row-link-target:focus{
  color:var(--dmsp-primary-dark);text-decoration:underline;
}

/* 6. Empty state — friendly centered placeholder with optional CTA. */
.dmsp-empty{
  display:flex;flex-direction:column;align-items:center;text-align:center;
  padding:3.5rem 1.5rem;color:var(--dmsp-text-muted);
}
.dmsp-empty-icon{
  font-size:3rem;line-height:1;color:var(--dmsp-icon-muted);margin-bottom:.85rem;
}
.dmsp-empty-message{
  font-size:1rem;color:var(--dmsp-text-dark);font-weight:600;margin-bottom:.35rem;
}
.dmsp-empty-detail{font-size:.875rem;color:var(--dmsp-text-muted);margin-bottom:1.25rem;max-width:28rem}
.dmsp-empty-detail:last-child{margin-bottom:0}

/* 7. Responsive card grid — auto-fill grid of equal-height cards (~260px min). */
.dmsp-card-grid{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:1.25rem;
}
/* A .dmsp-card that is itself a link (whole-card click target, keyboard-focusable). */
a.dmsp-card{display:flex;flex-direction:column;text-decoration:none;color:inherit}
a.dmsp-card:hover{text-decoration:none;color:inherit}
a.dmsp-card:focus-visible{outline:2px solid var(--dmsp-primary);outline-offset:2px}
/* A .dmsp-card that is a <div onclick> with a real inner link (row-link pattern,
   used when a second interactive element must live inside the card). */
.dmsp-card--clickable{display:flex;flex-direction:column;cursor:pointer}
.dmsp-card--clickable .dmsp-row-link-target{color:inherit;text-decoration:none}
.dmsp-card--clickable:focus-within{outline:2px solid var(--dmsp-primary);outline-offset:2px}
.dmsp-card-grid-head{
  display:flex;align-items:flex-start;justify-content:space-between;gap:.75rem;margin-bottom:1rem;
}
.dmsp-card-grid-name{font-size:1.05rem;font-weight:700;color:var(--dmsp-text-dark);line-height:1.3}
.dmsp-card-grid-meta{display:flex;flex-direction:column;gap:.5rem;margin-top:auto}
.dmsp-card-grid-meta-row{display:flex;align-items:center;gap:.5rem;font-size:.875rem;color:var(--dmsp-text-muted)}
.dmsp-card-grid-meta-row .mdi{color:var(--dmsp-icon-muted);font-size:1.05rem;flex-shrink:0}
.dmsp-card-grid-meta-row strong{color:var(--dmsp-text-dark);font-weight:600}

/* ===== Loaners detail page (Task 8) — see BRAND_IDENTITY.md §6 ===== */

/* Stat strip — responsive grid of .dmsp-stat tiles for a summary header. */
.dmsp-stat-strip{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  gap:.85rem;margin-bottom:1.5rem;
}
/* A stat tile that needs to span more room (e.g. the km-allowance meter). */
.dmsp-stat--wide{grid-column:span 2}
@media (max-width:576px){.dmsp-stat--wide{grid-column:auto}}
.dmsp-stat-value--sm{font-size:1rem;font-weight:600;line-height:1.35}
.dmsp-stat-sub{font-size:.8rem;color:var(--dmsp-text-muted);line-height:1.35}

/* Section-card icon colour variants (header glyph tint by section). */
.dmsp-card-icon--success{background:var(--dmsp-success-tint);color:var(--dmsp-success-text)}
.dmsp-card-icon--warning{background:var(--dmsp-warning-tint);color:var(--dmsp-warning-text)}

/* Reveal — a tucked <details> disclosure for secondary "add" forms inside a
   section card. The summary is a quiet pill-style toggle; the body holds the form. */
.dmsp-reveal{
  margin-top:1.1rem;border-top:1px dashed var(--dmsp-muted-tint);padding-top:1rem;
}
.dmsp-reveal>summary{
  display:inline-flex;align-items:center;gap:.4rem;cursor:pointer;list-style:none;
  font-size:.85rem;font-weight:600;color:var(--dmsp-primary-dark);
  padding:.4rem .8rem;border-radius:999px;background:var(--dmsp-panel-tint);
  width:fit-content;transition:background .15s ease,transform .15s ease;
}
.dmsp-reveal>summary::-webkit-details-marker{display:none}
.dmsp-reveal>summary:hover{transform:translateY(-1px)}
.dmsp-reveal>summary .mdi{transition:transform .2s ease}
.dmsp-reveal[open]>summary .mdi{transform:rotate(45deg)}
.dmsp-reveal-body{padding-top:1rem}

/* Inline mini-list rows inside section cards (charges, deposits, documents). */
.dmsp-line-list{display:flex;flex-direction:column;gap:.1rem}
.dmsp-line{
  display:flex;align-items:center;justify-content:space-between;gap:.75rem;
  padding:.7rem .25rem;border-bottom:1px solid var(--dmsp-muted-tint);
}
.dmsp-line:last-child{border-bottom:none}
.dmsp-line-main{display:flex;flex-direction:column;gap:.2rem;min-width:0}
.dmsp-line-title{color:var(--dmsp-text-dark);font-weight:600;display:flex;align-items:center;gap:.45rem;flex-wrap:wrap}
.dmsp-line-sub{font-size:.78rem;color:var(--dmsp-text-muted)}
.dmsp-line-actions{display:flex;align-items:center;gap:.4rem;flex-shrink:0}
.dmsp-line-amount{font-weight:700;color:var(--dmsp-text-dark);white-space:nowrap}
.dmsp-line-empty{padding:.9rem .25rem;color:var(--dmsp-text-muted);font-size:.9rem}

/* Inline-form helpers used by the reveal forms (keeps native widgets aligned). */
.dmsp-inline-form{display:flex;flex-wrap:wrap;gap:.6rem;align-items:center}
.dmsp-inline-form .form-control,.dmsp-inline-form .form-select{width:auto;flex:1 1 9rem;min-width:7rem}
.dmsp-inline-form .dmsp-inline-grow{flex:2 1 12rem}

/* ===== Loaners loan calendar (Task 11) — see BRAND_IDENTITY.md §6 (Calendar) ===== */

/* Header nav — Prev / Today / Next button group, tokenized. */
.cal-nav{display:inline-flex;gap:.4rem;align-items:center}
.cal-nav-btn{
  display:inline-flex;align-items:center;gap:.3rem;text-decoration:none;cursor:pointer;
  padding:.4rem .8rem;border-radius:8px;font-size:.85rem;font-weight:600;line-height:1;
  color:#fff;background:var(--dmsp-on-banner-fill);border:1px solid var(--dmsp-on-banner-border);
  transition:background .15s ease,transform .15s ease;
}
.cal-nav-btn:hover{color:#fff;background:var(--dmsp-on-banner-fill-hover);border-color:var(--dmsp-on-banner-border-hover);transform:translateY(-1px)}
.cal-nav-btn:focus-visible{outline:2px solid #fff;outline-offset:2px}
.cal-nav-btn--today{background:#fff;color:var(--dmsp-primary-dark);border-color:#fff}
.cal-nav-btn--today:hover{color:var(--dmsp-primary-dark);background:#fff}

/* Grid scaffolding — head, day numbers and bars all share the 7-column track. */
.cal-head,.cal-days,.cal-bars{display:grid;grid-template-columns:repeat(7,1fr)}
.cal-head{margin-bottom:.25rem}
.cal-head div{
  text-align:center;font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--dmsp-text-muted);padding:.25rem 0;
}
.cal-week{margin-bottom:.35rem}
.cal-day{
  border:1px solid var(--dmsp-panel-border);min-height:1.7rem;padding:.1rem .35rem;
  font-size:.8rem;color:var(--dmsp-text-dark);
}
.cal-day.cal-out{background:var(--dmsp-bg-light);color:var(--dmsp-icon-muted)}
.cal-day.cal-today{color:var(--dmsp-primary);font-weight:700;box-shadow:inset 0 -2px 0 0 var(--dmsp-primary)}

/* Loan bars — continuous lanes; grid position is set inline (data-driven). */
.cal-bars{gap:2px;padding:2px 0 6px}
.cal-bar{
  display:flex;align-items:center;gap:.35rem;min-width:0;
  background:var(--dmsp-primary);color:#fff;border-radius:6px;padding:.1rem .5rem;
  font-size:.75rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  text-decoration:none;transition:filter .15s ease,transform .15s ease;
}
.cal-bar:hover{color:#fff;filter:brightness(1.06);transform:translateY(-1px)}
.cal-bar--active{background:var(--dmsp-primary)}
.cal-bar--returned{background:var(--dmsp-success)}
.cal-bar--overdue{background:var(--dmsp-danger)}
/* Plate chip inside a bar — translucent on the bar fill, replaces badge bg-dark. */
.cal-bar-plate{
  flex-shrink:0;font-size:.68rem;font-weight:700;line-height:1;letter-spacing:.02em;
  padding:.12rem .35rem;border-radius:4px;background:rgba(255,255,255,.25);color:#fff;
}
.cal-bar-name{overflow:hidden;text-overflow:ellipsis}
.dmsp-inline-check{display:inline-flex;align-items:center;gap:.4rem;font-size:.85rem;color:var(--dmsp-text-dark)}

/* ============================================================
   Customer-facing public pages (return capture + remote signing)
   Mobile-first, centered, welcoming. Seen by customers on phones.
   ============================================================ */
.dmsp-public-shell{
  max-width:560px;margin:0 auto;padding:1.25rem 1rem 3rem;
}
.dmsp-public-card{
  background:#fff;border-radius:18px;overflow:hidden;
  box-shadow:0 6px 30px rgba(15,23,42,.10);border:1px solid var(--dmsp-muted-tint);
}
/* Branded gradient welcome banner */
.dmsp-public-header{
  position:relative;overflow:hidden;background:var(--dmsp-gradient-header);color:#fff;
  padding:1.75rem 1.5rem;text-align:center;
}
.dmsp-public-header::before{
  content:'';position:absolute;inset:0;
  background:url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 100" fill="white" opacity="0.06"><path d="M0,0v46.29c47.79,22.2,103.59,32.17,158,28,70.36-5.37,136.33-33.31,206.8-37.5C438.64,32.43,512.34,53.67,583,72.05c69.27,18,138.3,24.88,209.4,13.08,36.15-6,69.85-17.84,104.45-29.34C989.49,25,1047.58,5.33,1100,1.36V0Z"/></svg>') repeat-x bottom;
  background-size:1000px 100px;animation:dmspWave 20s linear infinite;pointer-events:none;
}
@media (prefers-reduced-motion: reduce){.dmsp-public-header::before{animation:none}}
.dmsp-public-header-content{position:relative;z-index:1}
.dmsp-public-badge{
  display:inline-flex;align-items:center;gap:.4rem;
  font-size:.72rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:#fff;background:var(--dmsp-on-banner-fill);border:1px solid var(--dmsp-on-banner-border);
  border-radius:999px;padding:.3rem .8rem;margin-bottom:.85rem;
}
.dmsp-public-dealer{color:#fff;font-size:1.5rem;font-weight:700;margin:0 0 .15rem;line-height:1.15}
/* Solid white, not opacity:.92 — see .dmsp-page-header-info p. This line is the
   one telling a customer what they are being asked to sign. */
.dmsp-public-title{color:#fff;font-size:.98rem;font-weight:500;margin:0}
.dmsp-public-body{padding:1.6rem 1.5rem 1.75rem}
@media (max-width:400px){.dmsp-public-body{padding:1.3rem 1.1rem 1.5rem}}
.dmsp-public-subject{
  display:flex;align-items:center;gap:.6rem;
  background:var(--dmsp-panel-tint);border-radius:12px;padding:.75rem .95rem;margin-bottom:1.4rem;
  color:var(--dmsp-primary-dark);font-weight:600;font-size:.95rem;
}
.dmsp-public-subject .mdi{font-size:1.3rem;flex-shrink:0}

/* Form field group */
.dmsp-field{margin-bottom:1.25rem}
.dmsp-field > .form-label{
  display:block;font-weight:600;color:var(--dmsp-text-dark);margin-bottom:.4rem;font-size:.95rem;
}
.dmsp-field .form-label small{font-weight:400;color:var(--dmsp-text-muted)}
/* Big, comfortable native controls on public pages */
.dmsp-public-body .form-control{
  border-radius:12px;border:1.5px solid var(--dmsp-panel-border);
  padding:.7rem .9rem;font-size:1rem;background:#fff;transition:border-color .15s ease,box-shadow .15s ease;
}
.dmsp-public-body .form-control:focus{
  border-color:var(--dmsp-primary);box-shadow:0 0 0 3px rgba(15,136,205,.15);outline:none;
}

/* Tap-friendly file dropzone wrapping a real <input type=file> */
.dmsp-filedrop{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.4rem;
  position:relative;border:2px dashed var(--dmsp-panel-border);border-radius:14px;
  background:var(--dmsp-bg-light);padding:1.4rem 1rem;text-align:center;cursor:pointer;
  transition:border-color .15s ease,background-color .15s ease;
}
.dmsp-filedrop:hover,.dmsp-filedrop:focus-within{
  border-color:var(--dmsp-primary);background:var(--dmsp-panel-tint);
}
.dmsp-filedrop.has-files{border-style:solid;border-color:var(--dmsp-primary)}
.dmsp-filedrop .mdi{font-size:2rem;color:var(--dmsp-primary)}
.dmsp-filedrop-text{font-weight:600;color:var(--dmsp-text-dark);font-size:.92rem}
.dmsp-filedrop-hint{font-size:.78rem;color:var(--dmsp-text-muted)}
/* The real input covers the whole zone but stays invisible (keyboard-focusable). */
.dmsp-filedrop input[type=file]{
  position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:pointer;
}
/* Thumbnail previews */
.dmsp-thumbs{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:.75rem}
.dmsp-thumb{
  width:64px;height:64px;border-radius:10px;object-fit:cover;
  border:1.5px solid var(--dmsp-panel-border);background:#fff;
}

/* Large checkbox card */
.dmsp-check-card{
  display:flex;align-items:center;gap:.7rem;
  border:1.5px solid var(--dmsp-panel-border);border-radius:12px;padding:.85rem 1rem;
  background:#fff;cursor:pointer;transition:border-color .15s ease,background-color .15s ease;
  margin-bottom:1.25rem;
}
.dmsp-check-card:hover{border-color:var(--dmsp-primary);background:var(--dmsp-panel-tint)}
.dmsp-check-card .form-check-input{width:1.35rem;height:1.35rem;margin:0;flex-shrink:0;cursor:pointer}
.dmsp-check-card-label{font-weight:600;color:var(--dmsp-text-dark);font-size:.95rem}

/* Full-width primary action with busy state */
.dmsp-btn-block{display:block;width:100%;padding:.85rem 1.1rem;font-size:1.05rem}
.dmsp-btn-primary[aria-busy=true]{opacity:.75;pointer-events:none}
.dmsp-btn-busy{display:none}
.dmsp-btn-primary[aria-busy=true] .dmsp-btn-busy{display:inline}
.dmsp-btn-primary[aria-busy=true] .dmsp-btn-idle{display:none}

/* Error rendering inside public fields */
.dmsp-public-body .errorlist,.dmsp-public-body ul.errorlist{
  list-style:none;margin:.4rem 0 0;padding:0;color:var(--dmsp-danger-text);font-size:.85rem;
}
.dmsp-public-alert{
  background:var(--dmsp-danger-tint);color:var(--dmsp-danger-text);
  border-radius:12px;padding:.75rem .95rem;font-size:.88rem;margin-bottom:1.25rem;
}
.dmsp-public-alert ul{margin:0;padding-left:1.1rem}

/* Signature pad on public/staff signing pages */
.dmsp-sigpad{
  width:100%;height:160px;border:1.5px solid var(--dmsp-panel-border);border-radius:12px;
  background:#fff;touch-action:none;display:block;
}
.dmsp-sig-block{margin-bottom:1.5rem}
.dmsp-sig-actions{display:flex;gap:.6rem;margin-top:.6rem;flex-wrap:wrap}
.dmsp-doc-frame{
  width:100%;height:48vh;border:1px solid var(--dmsp-panel-border);border-radius:12px;
  background:#fff;margin-bottom:1.4rem;
}
.dmsp-btn-ghost{
  display:inline-flex;align-items:center;gap:.35rem;cursor:pointer;
  background:#fff;color:var(--dmsp-primary-dark);border:1.5px solid var(--dmsp-panel-border);
  border-radius:10px;padding:.55rem 1rem;font-weight:600;text-decoration:none;
  transition:border-color .15s ease,background-color .15s ease;
}
.dmsp-btn-ghost:hover{border-color:var(--dmsp-primary);background:var(--dmsp-panel-tint);color:var(--dmsp-primary-dark)}
.dmsp-btn-ghost:focus-visible{outline:2px solid var(--dmsp-primary);outline-offset:2px}

/* Inline "all signatures captured" note on the staff signing page. */
.dmsp-all-signed-note{color:var(--dmsp-success-text);font-weight:600}

/* Friendly success confirmation state */
.dmsp-public-success{text-align:center;padding:2.5rem 1.5rem}
.dmsp-success-icon{font-size:4.5rem;line-height:1;color:var(--dmsp-success);margin-bottom:.5rem}
.dmsp-public-success h1{font-size:1.5rem;font-weight:700;color:var(--dmsp-text-dark);margin-bottom:.5rem}

/* ── PDF placement editor (template_form) ───────────────────────────────── */

/* Outer wrapper — contains the palette and the pages strip */
.dmsp-editor{display:flex;flex-direction:column;gap:1rem;margin-top:1.5rem}

/* Palette bar: chips labelled by type */
.dmsp-editor-palette{
  display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;
  background:var(--dmsp-panel-tint);border:1px solid var(--dmsp-panel-border);
  border-radius:10px;padding:.6rem .85rem;
}
.dmsp-editor-palette-label{
  font-size:.7rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--dmsp-text-muted);margin-right:.25rem;
}

/* Palette chips — clickable; press once to arm, click page to drop */
.dmsp-chip{
  display:inline-flex;align-items:center;
  background:#fff;color:var(--dmsp-text-dark);
  border:1.5px solid var(--dmsp-panel-border);border-radius:999px;
  padding:.25rem .75rem;font-size:.8rem;font-weight:600;cursor:pointer;
  transition:border-color .15s ease,background .15s ease;
}
.dmsp-chip:hover{border-color:var(--dmsp-primary);background:var(--dmsp-panel-tint);color:var(--dmsp-primary-dark)}
.dmsp-chip.is-active{
  background:var(--dmsp-gradient-bold);color:#fff;border-color:var(--dmsp-primary-dark);
}

/* Pages strip: vertically stacked page images */
.dmsp-editor-pages{display:flex;flex-direction:column;gap:1.25rem}

/* Single page container: the image defines the intrinsic dimensions;
   boxes are positioned absolutely as percentages of this element */
.dmsp-editor-page{
  position:relative;display:inline-block;
  border:1px solid var(--dmsp-panel-border);border-radius:8px;overflow:hidden;
  cursor:crosshair;
  box-shadow:0 2px 8px color-mix(in srgb, var(--dmsp-text-dark) 10%, transparent);
}
.dmsp-editor-page-img{max-width:100%;display:block}

/* Placement box */
.dmsp-box{
  position:absolute;box-sizing:border-box;
  border-radius:4px;cursor:move;user-select:none;
  display:flex;align-items:flex-start;justify-content:space-between;
  padding:2px 4px;font-size:.65rem;font-weight:600;line-height:1.2;
}
/* Field box: primary-tinted */
.dmsp-box--field{
  background:color-mix(in srgb, var(--dmsp-primary) 15%, transparent);
  border:1.5px solid var(--dmsp-primary);
  color:var(--dmsp-primary-dark);
}
/* Signature box: warning-tinted */
.dmsp-box--signature{
  background:color-mix(in srgb, var(--dmsp-warning) 15%, transparent);
  border:1.5px solid var(--dmsp-warning);
  color:var(--dmsp-warning-text);
}

.dmsp-box-label{
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;
}
.dmsp-box-remove{
  flex-shrink:0;background:none;border:none;padding:0 0 0 3px;
  font-size:.8rem;line-height:1;cursor:pointer;opacity:.6;
}
.dmsp-box-remove:hover{opacity:1}

/* Resize handle: bottom-right corner, 10×10 px */
.dmsp-box-handle{
  position:absolute;right:0;bottom:0;
  width:10px;height:10px;cursor:nwse-resize;
  background:color-mix(in srgb, var(--dmsp-text-dark) 30%, transparent);
  border-radius:2px 0 4px 0;
}

/* ── end PDF placement editor ───────────────────────────────────────────── */
.dmsp-public-success p{color:var(--dmsp-text-muted);font-size:.98rem;margin:0 auto;max-width:30rem}

/* ===== Loaner checkout — vehicle card picker (radio cards) ===== */
.dmsp-vehicle-picker .dmsp-vehicle-pick{position:relative;cursor:pointer;border:2px solid transparent;margin-bottom:0;display:flex;flex-direction:column}
.dmsp-vehicle-pick input[type="radio"]{position:absolute;opacity:0;pointer-events:none}
.dmsp-vehicle-pick .dmsp-vehicle-pick-check{color:var(--dmsp-primary);font-size:1.35rem;opacity:0;transition:opacity .15s}
.dmsp-vehicle-pick.is-selected,
.dmsp-vehicle-pick:has(input:checked){border-color:var(--dmsp-primary);background:var(--dmsp-panel-tint)}
.dmsp-vehicle-pick.is-selected .dmsp-vehicle-pick-check,
.dmsp-vehicle-pick:has(input:checked) .dmsp-vehicle-pick-check{opacity:1}
.dmsp-vehicle-pick:focus-within{outline:2px solid var(--dmsp-primary);outline-offset:2px}

/* Floating call card (telephony spec 2026-07-30 §4.1) */
#dmsp-call-card{position:fixed;bottom:1.25rem;right:1.25rem;z-index:1050;
  width:20rem;max-width:calc(100vw - 2.5rem);max-height:70vh;overflow-y:auto;
  background:#fff;border:1px solid rgba(0,0,0,.15);border-radius:12px;
  box-shadow:0 6px 18px rgba(0,0,0,.25);font-size:.875rem}
.dmsp-cc-head{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;
  background:var(--dmsp-primary);color:#fff;border-radius:12px 12px 0 0}
.dmsp-cc-head #dmsp-cc-status{flex:1;text-align:right;font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dmsp-cc-btn{background:none;border:none;color:#fff;font-size:1rem;
  line-height:1;cursor:pointer;padding:0 .25rem}
.dmsp-cc-body{padding:.6rem .75rem;display:flex;flex-direction:column;gap:.45rem}
.dmsp-cc-strong{font-weight:600}
.dmsp-cc-error{color:#fff;background:#b02a37;border-radius:6px;padding:.35rem .5rem}
.dmsp-cc-note{color:#664d03;background:#fff3cd;border-radius:6px;padding:.35rem .5rem}
.dmsp-cc-pick{display:block;width:100%;text-align:left;margin-top:.25rem;
  background:var(--dmsp-primary);color:#fff;border:none;border-radius:6px;
  padding:.35rem .5rem;cursor:pointer}
.dmsp-cc-pick-disabled{opacity:.6;padding:.35rem .5rem}
.dmsp-cc-enr{color:#333}
.dmsp-cc-cov-list{display:flex;flex-direction:column;gap:.2rem}
.dmsp-cc-maint-list{display:flex;flex-direction:column;gap:.3rem}
.dmsp-cc-maint-row{display:flex;flex-direction:column}
.dmsp-cc-maint-op{overflow-wrap:anywhere}
.dmsp-cc-maint-meta,.dmsp-cc-maint-more{font-size:.8em;color:#555}
.dmsp-cc-condition{display:flex;align-items:center;flex-wrap:wrap;gap:.35rem}
.dmsp-cc-warn{color:#b02a37}
.dmsp-cc-ask{width:100%;background:#198754;color:#fff;border:none;
  border-radius:6px;padding:.4rem .5rem;cursor:pointer}

/* ===== Estimate editor (dmsp-est-*) — spec docs/superpowers/specs/2026-09-01-estimate-editor-redesign-design.md ===== */
.dmsp-est-header{margin-bottom:1.5rem}
.dmsp-est-header .dmsp-section-card-header{margin-bottom:.6rem}
.dmsp-est-header-reveal{margin-top:0;border-top:0;padding-top:0}
.dmsp-est-header-reveal>summary{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem 1rem;width:100%;background:none;padding:.35rem 0;border-radius:0;font-weight:500;color:var(--dmsp-text-dark)}
.dmsp-est-header-reveal>summary:hover{transform:none}
.dmsp-est-header-summary{display:flex;flex-wrap:wrap;align-items:center;gap:.35rem .9rem;min-width:0;font-size:.95rem;color:var(--dmsp-muted-text)}
.dmsp-est-header-summary code{font-size:.9em;background:var(--dmsp-muted-tint);color:var(--dmsp-text-dark);padding:.1rem .4rem;border-radius:4px}
.dmsp-est-header-toggle{margin-left:auto;display:inline-flex;align-items:center;gap:.35rem;font-size:.85rem;font-weight:600;color:var(--dmsp-primary-dark);padding:.35rem .8rem;border-radius:999px;background:var(--dmsp-panel-tint);white-space:nowrap}
.dmsp-est-header-reveal[open]>summary .dmsp-est-header-toggle .mdi{transform:none}
.dmsp-est-header-reveal[open]~.dmsp-est-header-notes{display:none}
.dmsp-est-header-notes{margin-top:.75rem;padding-top:.75rem;border-top:1px solid var(--dmsp-muted-tint);font-size:.92rem;color:var(--dmsp-muted-text)}
.dmsp-est-header-notes .dmsp-stat-label{display:block;margin-bottom:.2rem}
.dmsp-est-field .form-label{font-weight:600;font-size:.92rem;margin-bottom:.25rem}
.dmsp-est-header-required{color:var(--dmsp-danger)}
/* --- job card --- */
.dmsp-est-job{padding:0;margin-bottom:1.5rem;--dmsp-est-cols:[kind] 6.5rem [pn] 9rem [desc] minmax(12rem,1fr) [qty] 5.5rem [unit] 7.5rem [total] 6.5rem [actions] 2.5rem}
.dmsp-est-job-head{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem 1rem;padding:.9rem 1.1rem .6rem}
.dmsp-est-job-ordinal{font-size:.7rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--dmsp-text-muted);margin:0;line-height:1.2}
.dmsp-est-job-titles{flex:1 1 18rem;min-width:0;display:flex;flex-direction:column;gap:.1rem}
.dmsp-est-job-title,.dmsp-est-job-note{border-color:transparent;background:transparent;padding-left:.4rem;margin-left:-.4rem;box-shadow:none}
.dmsp-est-job-title{font-size:1.05rem;font-weight:600}
.dmsp-est-job-note{font-size:.875rem;color:var(--dmsp-text-muted)}
.dmsp-est-job-title:hover,.dmsp-est-job-note:hover{border-color:var(--dmsp-muted-tint)}
.dmsp-est-job-title:focus,.dmsp-est-job-note:focus{border-color:var(--dmsp-primary);background:var(--dmsp-panel-bg)}
.dmsp-est-job-decision{white-space:nowrap}
.dmsp-est-job-decision-note{font-size:.8rem;color:var(--dmsp-text-muted)}
.dmsp-est-job-subtotal{display:flex;flex-direction:column;align-items:flex-end;line-height:1.15;margin-left:auto}
.dmsp-est-job-subtotal .job-subtotal{font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
.dmsp-est-job-head .job-remove-btn{white-space:nowrap}
.dmsp-est-job-status{padding:0 1.1rem}
.dmsp-est-job-status:empty{display:none}
.dmsp-est-job-status .job-removed-banner{margin:.25rem 0 .5rem}
.dmsp-est-job-status .invalid-feedback{margin-bottom:.4rem}
.dmsp-est-job-body{padding:.25rem 1.1rem 1rem}
.job-card-removed .dmsp-est-job-body{opacity:.55}
.job-card-removed .job-remove-btn{display:none}
.dmsp-est-job[data-decision="declined"] .dmsp-est-job-body{opacity:.6}
/* --- rows: one grid, tracks declared once on the card --- */
.dmsp-est-lines-head,.dmsp-est-row{display:grid;grid-template-columns:var(--dmsp-est-cols);column-gap:.5rem;align-items:center}
.dmsp-est-lines-head{padding:.35rem 0 .3rem;border-bottom:2px solid var(--dmsp-panel-border)}
.dmsp-est-lines-head span{font-size:.66rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--dmsp-text-muted)}
.dmsp-est-lines-head .dmsp-est-num{text-align:right}
.dmsp-est-row{padding:.5rem 0;border-bottom:1px solid var(--dmsp-muted-tint)}
.dmsp-est-row>input[type="hidden"],.dmsp-est-row>.d-none{display:none}
.dmsp-est-cell{min-width:0}
.dmsp-est-cell--desc.dmsp-est-cell--wide{grid-column:pn / qty}
.dmsp-est-cell--total{text-align:right;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
.dmsp-est-cell--actions{display:flex;justify-content:flex-end}
.dmsp-est-cell--error{grid-column:1 / -1}
.dmsp-est-cell .form-control{min-width:0}
.dmsp-est-cell .input-group .form-control.text-end{text-align:right;font-variant-numeric:tabular-nums}
.dmsp-est-cell .input-group-text{padding:.375rem .5rem;color:var(--dmsp-muted-text);background:var(--dmsp-muted-tint)}
.dmsp-est-cell-label{display:none;font-size:.6rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--dmsp-text-muted);margin-bottom:.15rem}
.dmsp-est-row .line-pill{gap:.3rem;white-space:nowrap}
.dmsp-est-menu-btn{padding:.25rem .45rem;line-height:1;color:var(--dmsp-muted-text)}
.dmsp-est-editor .dropdown-menu{z-index:1030}
.dmsp-est-row--removed .dmsp-est-cell:not(.dmsp-est-cell--actions){opacity:.45}
.dmsp-est-row--removed .dmsp-est-cell--desc .form-control{text-decoration:line-through}
.dmsp-est-row--removed .dmsp-est-menu-btn{display:none}
.dmsp-est-row--removed .line-remove-undo{display:inline-flex}
/* FIX 2 (coordinator review): the actions track (2.5rem) is sized for
   the icon-only '⋮' trigger; the text "Undo" button that replaces it
   in the removed state does not fit and overflowed into the Total column.
   The kebab trigger's NORMAL-state geometry is untouched (this only
   applies under .dmsp-est-row--removed) — the removed-state actions cell
   spans into the total track instead, which the stale, frozen line-total
   figure (frozen deliberately — see estimate_editor.js) no longer needs,
   since "Removed" is the label that matters once a row is removed.
   Hiding line-total is width-independent (every breakpoint benefits from
   freeing that space), but the PLACEMENT rules below are NOT: (0,2,0)
   specificity beats every breakpoint's (0,1,0) grid-area rule regardless
   of viewport, with no media query of its own to lose to — so an earlier
   version of this fix silently won at every width, forcing both cells
   into row 1 below 1200px where columns 2-5 belong to desc (found in
   review: it painted "Removed" over the struck-through description on a
   tablet, and at <=575.98px it landed on the kind pill instead). Each
   breakpoint below gets its own removed-state placement in that
   breakpoint's own grid-area vocabulary instead of one rule assumed to
   travel down the cascade unchanged. */
.dmsp-est-row--removed .dmsp-est-cell--total .line-total{display:none}
@media (min-width:1200px){
  .dmsp-est-row--removed .dmsp-est-cell--total{text-align:left;grid-column:total;grid-row:1}
  .dmsp-est-row--removed .dmsp-est-cell--actions{grid-column:total / span 2;grid-row:1}
}
.dmsp-est-row-removed-label{font-weight:500;color:var(--dmsp-text-muted);margin-right:.5rem}
.dmsp-est-add-row{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;padding-top:.75rem}
.dmsp-est-add-row .add-line-btn{display:inline-flex;align-items:center;gap:.35rem;cursor:pointer;font-size:.85rem;font-weight:600;color:var(--dmsp-primary-dark);background:var(--dmsp-panel-tint);border:0;border-radius:999px;padding:.4rem .8rem;white-space:nowrap}
.dmsp-est-add-row .add-line-btn:disabled{opacity:.5;cursor:not-allowed}
.dmsp-est-cap{margin-left:auto;font-size:.8rem;color:var(--dmsp-text-muted)}
.dmsp-est-flash{animation:dmspEstFlash 1s ease-out}
@keyframes dmspEstFlash{from{background:var(--dmsp-panel-tint)}to{background:transparent}}
@media (prefers-reduced-motion: reduce){.dmsp-est-flash{animation:none}}
/* --- below 1200px: a deliberate two-line row, never free wrapping (E3) --- */
@media (max-width:1199.98px){
  .dmsp-est-lines-head{display:none}
  .dmsp-est-row{grid-template-columns:6.5rem 1fr 5.5rem 7.5rem 6.5rem 2.5rem;grid-template-areas:"kind desc desc desc desc actions" "pn pn qty unit total .";row-gap:.4rem;align-items:end}
  .dmsp-est-cell--kind{grid-area:kind;align-self:center}
  .dmsp-est-cell--desc,.dmsp-est-cell--desc.dmsp-est-cell--wide{grid-area:desc;align-self:center}
  .dmsp-est-cell--pn{grid-area:pn}
  .dmsp-est-cell--qty{grid-area:qty}
  .dmsp-est-cell--unit{grid-area:unit}
  .dmsp-est-cell--total{grid-area:total;padding-bottom:.45rem}
  .dmsp-est-cell--actions{grid-area:actions;align-self:center}
  .dmsp-est-cell--error{grid-column:1 / -1;grid-area:auto}
  .dmsp-est-cell-label{display:block}
  .dmsp-est-job-titles{flex-basis:100%;order:10}
  /* removed state: actions has nothing left to show but Undo (the kebab
     is display:none), so it moves into the total area instead of trying
     to fit "Undo" text in the 2.5rem actions track — total's own content
     pins to the top of that shared cell, Undo to the bottom, so the two
     never share the same pixels even though they share the same grid
     area. The "TOTAL" caption is redundant once the row also says
     "Removed" (and its extra line was tall enough to make Removed's own
     text reach down into Undo's territory regardless of align-self) so
     it's dropped here — Removed is the only line total needs to show. */
  .dmsp-est-row--removed .dmsp-est-cell--total{text-align:left;align-self:start}
  .dmsp-est-row--removed .dmsp-est-cell--total .dmsp-est-cell-label{display:none}
  .dmsp-est-row--removed .dmsp-est-cell--actions{grid-area:total;align-self:end;justify-content:flex-end}
}
@media (max-width:575.98px){
  .dmsp-est-row{grid-template-columns:6.5rem 1fr 5.5rem 7.5rem 2.5rem;grid-template-areas:"kind desc desc desc actions" "pn pn pn pn ." "total qty qty unit ."}
  .dmsp-est-cell--total{text-align:left;grid-area:total}
  /* Same idea as the 1199.98px breakpoint: route the removed-state Undo
     into the total area (this breakpoint's own home for it) rather than
     the still-too-narrow actions track. */
  .dmsp-est-row--removed .dmsp-est-cell--total{align-self:start}
  .dmsp-est-row--removed .dmsp-est-cell--actions{grid-area:total;align-self:end;justify-content:flex-end}
}
@media (pointer:coarse){
  .dmsp-est-menu-btn,.dmsp-est-add-row .add-line-btn,.line-remove-undo,.dmsp-est-job-head .job-remove-btn{min-height:2.75rem}
  .dmsp-est-menu-btn{min-width:2.75rem}
}

/* --- footer bar (E9) --- */
.dmsp-est-footer{position:sticky;bottom:0;z-index:1000;display:flex;flex-wrap:wrap;align-items:center;gap:.5rem 1.25rem;background:var(--dmsp-panel-bg);border-top:1px solid var(--dmsp-panel-border);box-shadow:0 -4px 12px rgba(0,0,0,.08);padding:.6rem 1rem;margin:0 calc(-1 * var(--bs-gutter-x,1.5rem) / 2);}
.dmsp-est-footer-breakdown>summary{display:none;cursor:pointer;list-style:none;font-size:.85rem;font-weight:600;color:var(--dmsp-primary-dark)}
.dmsp-est-footer-breakdown>summary::-webkit-details-marker{display:none}
.dmsp-est-footer-stats{display:flex;flex-wrap:wrap;gap:.35rem 1.25rem}
.dmsp-est-stat{display:flex;flex-direction:column;line-height:1.15}
.dmsp-est-stat .dmsp-stat-label{font-size:.62rem}
.dmsp-est-stat strong{font-size:.92rem;font-variant-numeric:tabular-nums;white-space:nowrap}
.dmsp-est-footer-total{display:flex;align-items:center;gap:.6rem;padding-left:1rem;border-left:2px solid var(--dmsp-panel-border)}
.dmsp-est-footer-total strong{font-size:1.25rem;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
.dmsp-est-footer-actions{margin-left:auto;display:flex;align-items:center;gap:.5rem}
.dmsp-est-editor .form-control,.dmsp-est-editor .line-form,.dmsp-est-job-head{scroll-margin-bottom:6rem}
.dmsp-est-status-note{margin-bottom:1.5rem}
.dmsp-est-status-badge{vertical-align:middle;margin-left:.4rem}
.dmsp-est-add-job{display:inline-flex;align-items:center;gap:.35rem;cursor:pointer;font-weight:600;color:var(--dmsp-primary-dark);background:var(--dmsp-panel-tint);border:0;border-radius:999px;padding:.55rem 1.1rem;margin-bottom:1.5rem}
.dmsp-est-add-job:disabled{opacity:.5;cursor:not-allowed}
.dmsp-est-add-job-note{color:var(--dmsp-text-muted);font-size:.9rem;margin-bottom:1.5rem}
@media (max-width:1199.98px){
  .dmsp-est-footer-breakdown>summary{display:inline-flex}
  .dmsp-est-footer-breakdown[open]>summary{margin-bottom:.35rem}
  .dmsp-est-footer-breakdown .dmsp-est-footer-stats{flex-basis:100%}
}
/* m2/m8 fix, v2: a CSS-only attempt lived here (forcing
   .dmsp-est-footer-stats visible at >=1200px regardless of the `open`
   attribute) but does NOT work — a closed <details>' non-summary content
   is hidden via UA content-visibility on the internal ::details-content
   pseudo-element, not a `display` rule any descendant selector can
   out-specify (verified live via CDP: the override never took effect).
   `open` now has a real, resize-aware JS owner instead — see
   estimate_editor.js's matchMedia('(max-width: 1199.98px)') block, which
   also handles a rotation via the query's own `change` event. */
@media (max-width:767.98px){.dmsp-est-footer{position:static;margin:0;border-radius:12px}}
