/* MarketSync Liquid Glass foundation.
 * Keep this file page-agnostic: new public pages, dashboard views, and builder
 * surfaces should inherit the same material without one-off repainting.
 */
:root {
  --ms-glass-blur: 24px;
  --ms-glass-saturation: 145%;
  --ms-glass-light: rgba(255, 255, 255, .66);
  --ms-glass-light-strong: rgba(255, 255, 255, .82);
  --ms-glass-dark: rgba(9, 20, 39, .46);
  --ms-glass-dark-strong: rgba(8, 18, 35, .64);
  --ms-glass-line: rgba(255, 255, 255, .46);
  --ms-glass-line-dark: rgba(148, 190, 230, .3);
  --ms-glass-shadow: 0 20px 60px rgba(15, 23, 42, .16), inset 0 1px 0 rgba(255, 255, 255, .58);
  --ms-glass-shadow-dark: 0 24px 70px rgba(0, 0, 0, .34), inset 0 1px 0 rgba(255, 255, 255, .13);
  --ms-glass-canvas: radial-gradient(circle at 10% 0%, rgba(76, 190, 255, .22), transparent 34%), radial-gradient(circle at 92% 12%, rgba(116, 89, 255, .2), transparent 36%), linear-gradient(135deg, #e8f7ff 0%, #f4f3ff 52%, #e8f9f5 100%);
}

/* Reusable material primitives for future templates and generated sections. */
.ms-glass-canvas { background: var(--ms-glass-canvas); background-attachment: fixed; }

/* Solid, opaque surfaces — no blur. Use for forms, panels, inspector, content. */
.ms-surface,
.ms-surface-raised {
  background: var(--ms-glass-light-strong);
  border: 1px solid var(--ms-glass-line);
  box-shadow: 0 4px 12px rgba(15, 23, 42, .08);
}
.ms-surface { background: var(--ms-glass-light); }

/* Glass surfaces — with blur. Use for navigation, floating panels, modals. */
.ms-glass,
.ms-glass-nav,
.ms-glass-floating,
.ms-glass-modal,
.ms-glass-surface,
.ms-glass-panel {
  background: var(--ms-glass-light);
  border: 1px solid var(--ms-glass-line);
  box-shadow: var(--ms-glass-shadow);
  backdrop-filter: blur(var(--ms-glass-blur)) saturate(var(--ms-glass-saturation));
  -webkit-backdrop-filter: blur(var(--ms-glass-blur)) saturate(var(--ms-glass-saturation));
}
.ms-glass-surface-strong { background: var(--ms-glass-light-strong); }
.ms-glass-surface-dark {
  background: var(--ms-glass-dark);
  border-color: var(--ms-glass-line-dark);
  box-shadow: var(--ms-glass-shadow-dark);
}

/* Utility classes for builder — never blur inputs. */
.liquid-glass-input {
  background: rgba(255,255,255,.88);
  border: 1px solid rgba(148,163,184,.32);
  box-shadow: inset 0 1px 2px rgba(15,23,42,.04);
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
.dark .liquid-glass-input,
[data-ws-theme="dark"] .liquid-glass-input {
  background: rgba(7,20,38,.88);
  border-color: rgba(148,190,230,.3);
  color: #f8fafc;
}
.liquid-glass-btn {
  background: rgba(255,255,255,.76);
  border: 1px solid rgba(148,163,184,.32);
  box-shadow: 0 2px 6px rgba(15,23,42,.06);
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
.dark .liquid-glass-btn,
[data-ws-theme="dark"] .liquid-glass-btn {
  background: rgba(31,61,96,.58);
  border-color: rgba(148,190,230,.3);
  color: #e2e8f0;
}

/* The public site is one materialized canvas. Semantic containers are selected
 * instead of buttons so calls-to-action retain reliable contrast. */
body.ms-glass-site {
  background: var(--ms-glass-canvas) !important;
  background-attachment: fixed;
}
body.ms-glass-site #app { min-height: 100vh; background: transparent; }
body.ms-glass-site :is(div,section,article,aside,form,details,header,footer,nav).bg-white,
body.ms-glass-site :is(div,section,article,aside,form,details,header,footer,nav).dark\:bg-slate-900 {
  background: var(--ms-glass-light) !important;
  border-color: var(--ms-glass-line) !important;
  box-shadow: var(--ms-glass-shadow);
  backdrop-filter: blur(var(--ms-glass-blur)) saturate(var(--ms-glass-saturation));
  -webkit-backdrop-filter: blur(var(--ms-glass-blur)) saturate(var(--ms-glass-saturation));
}
body.ms-glass-site :is(div,section,article,aside,form,details,header,footer,nav).bg-slate-900 { background: var(--ms-glass-dark) !important; border-color: var(--ms-glass-line-dark) !important; color: #f8fafc; }
body.ms-glass-site :is(input,select,textarea) {
  background: rgba(255,255,255,.72);
  border-color: rgba(148,163,184,.48);
  box-shadow: inset 0 1px 2px rgba(15,23,42,.06), 0 1px 0 rgba(255,255,255,.55);
}

/* Dashboard-wide mode. Apply glass effects ONLY to explicitly marked elements.
   Use .ms-glass-nav, .ms-glass-floating, .ms-glass-modal for intentional glass surfaces. */
html[data-ms-glass="global"] body {
  background: var(--ms-glass-canvas) !important;
  background-attachment: fixed;
}
html[data-ms-glass="global"] {
  --ms-chrome-surface: var(--ms-glass-light);
  --ms-chrome-line: var(--ms-glass-line);
  --ms-chrome-shadow: var(--ms-glass-shadow);
}
/* Global glass effect is restricted to named architectural elements only.
   Do NOT apply to generic divs/sections/forms — these should use explicit material classes. */
html[data-ms-glass="global"] :is(body > header.ms-chrome-glass,#dashboard-nav,#dept-sidebar,#dept-tabbar,.ms-app-shell,.ms-glass-target,.ms-glass-nav,.ms-glass-floating,.ms-glass-modal) {
  background: var(--ms-chrome-surface) !important;
  border-color: var(--ms-chrome-line) !important;
  box-shadow: var(--ms-chrome-shadow);
  backdrop-filter: blur(var(--ms-glass-blur)) saturate(var(--ms-glass-saturation));
  -webkit-backdrop-filter: blur(var(--ms-glass-blur)) saturate(var(--ms-glass-saturation));
}
/* Solid semantic surfaces (forms, panels, inspector) stay opaque, never blurred. */
html[data-ms-glass="global"] :is(.ms-surface,.ms-surface-raised,.ms-inspector-panel,#ws-inspector-panel,form) {
  background: var(--ms-glass-light-strong) !important;
  border-color: var(--ms-glass-line) !important;
  box-shadow: none !important;
  backdrop-filter: none !important;
}
html[data-ms-glass="global"] :is(input,select,textarea) {
  background: rgba(255,255,255,.88) !important;
  border-color: rgba(148,163,184,.48) !important;
  color: #0f172a !important;
  backdrop-filter: none !important;
}
html[data-ms-glass="global"] :is(button,a).bg-white { background: rgba(255,255,255,.88) !important; }
html[data-ms-glass="global"].dark {
  --ms-glass-canvas: radial-gradient(circle at 8% 0%, rgba(22, 132, 190, .26), transparent 34%), radial-gradient(circle at 92% 8%, rgba(85, 64, 190, .24), transparent 36%), linear-gradient(135deg, #071426 0%, #0b1830 52%, #071d25 100%);
  --ms-chrome-surface: var(--ms-glass-dark);
  --ms-chrome-line: var(--ms-glass-line-dark);
  --ms-chrome-shadow: var(--ms-glass-shadow-dark);
}
/* A bg-white control commonly pairs with dark:bg-slate-900. The light glass
   rule above is !important, so without an equally-specific dark counterpart it
   wins the cascade and produces white buttons with light text in dark mode. */
html[data-ms-glass="global"].dark :is(button,a).bg-white {
  background: rgba(15,23,42,.92) !important;
}
/* …and the text must follow. A white button with dark text (Design Studio's
   Publish: bg-white text-indigo-700) and no dark: text colour of its own was
   left as dark text on the now-dark fill — unreadable. */
html[data-ms-glass="global"].dark :is(button,a).bg-white:not([class*="dark:text-"]) {
  color: #F8FAFC !important;
}
html[data-ms-glass="global"].dark :is(.ms-surface,.ms-surface-raised,.ms-inspector-panel,#ws-inspector-panel,form) {
  background: var(--ms-glass-dark-strong) !important;
  border-color: var(--ms-glass-line-dark) !important;
  box-shadow: none !important;
  backdrop-filter: none !important;
}
html[data-ms-glass="global"].dark :is(input,select,textarea) { background: rgba(7,20,38,.88) !important; color: #f8fafc !important; border-color: rgba(148,190,230,.3) !important; backdrop-filter: none !important; }

/* MarketSync HQ pins its navigation material so the chrome reads as one
 * surface rather than inheriting whatever a page happens to set. */
html[data-ms-glass="global"][data-dash-owner="1"][data-dash-mode="marketsync"] {
  --ms-chrome-surface: rgba(255,255,255,.94);
  --ms-chrome-line: rgba(148,163,184,.34);
  --ms-chrome-shadow: 0 14px 36px rgba(15,23,42,.10), inset 0 1px 0 rgba(255,255,255,.82);
}
html[data-ms-glass="global"][data-dash-owner="1"][data-dash-mode="marketsync"] :is(body > header.ms-chrome-glass,#dashboard-nav,#dept-sidebar,#dept-tabbar) {
  color: #0f172a;
}
html[data-ms-glass="global"][data-dash-owner="1"][data-dash-mode="marketsync"] :is(#dashboard-nav,#dept-sidebar) .dept-nav-item {
  color: #334155;
}

/* ...and follows the theme, because the pin above used to hold in dark mode too.
 *
 * The three attribute selectors out-weigh `html[data-ms-glass="global"].dark`,
 * which is the rule that swaps --ms-chrome-surface to the dark glass. So in HQ
 * the header, the desktop rail and the tab-bar stayed WHITE with near-black
 * text while the content canvas went to #0b1020 — a white bar and an unreadable
 * sidebar over a dark page. Repeating the three attributes with `.dark` gives
 * the dark side the higher weight instead of relying on source order.
 *
 * The material is the same one the rest of the app uses in dark mode, at the
 * pin's own .94 opacity so HQ chrome still reads as a solid surface rather than
 * a translucent panel. */
html[data-ms-glass="global"][data-dash-owner="1"][data-dash-mode="marketsync"].dark {
  --ms-chrome-surface: rgba(11,18,32,.94);
  --ms-chrome-line: rgba(148,190,230,.22);
  --ms-chrome-shadow: 0 14px 36px rgba(0,0,0,.42), inset 0 1px 0 rgba(255,255,255,.08);
}
html[data-ms-glass="global"][data-dash-owner="1"][data-dash-mode="marketsync"].dark :is(body > header.ms-chrome-glass,#dashboard-nav,#dept-sidebar,#dept-tabbar) {
  color: #E2E8F0;
}
html[data-ms-glass="global"][data-dash-owner="1"][data-dash-mode="marketsync"].dark :is(#dashboard-nav,#dept-sidebar) .dept-nav-item {
  color: #CBD5E1;
}

/* The website editor is a dense workbench, not a glass surface. Keep its
 * navigation, drawers, inspector, forms, and toolbar fully opaque so the live
 * website remains the only visually expressive layer. */
.ws-studio-container {
  --ws-bg: #0b1220 !important;
  --ws-panel: #111827 !important;
  --ws-panel-sub: #172033 !important;
  --ws-panel-raised: #1e293b !important;
  --ws-border: #334155 !important;
  --ws-input-bg: #0f172a !important;
  --ws-input-border: #475569 !important;
  background: var(--ws-bg) !important;
}
.ws-studio-container[data-ws-theme="light"] {
  --ws-bg: #e5e7eb !important;
  --ws-panel: #ffffff !important;
  --ws-panel-sub: #f8fafc !important;
  --ws-panel-raised: #f1f5f9 !important;
  --ws-border: #cbd5e1 !important;
  --ws-input-bg: #ffffff !important;
  --ws-input-border: #94a3b8 !important;
}
.ws-studio-container :is(.ws-builder-header,.ws-top-action-bar,#ws-left-dock-wrapper nav,#ws-left-drawer-content,#ws-right-dock-wrapper,#ws-inspector-panel,#ws-inspector-content,#ws-palette,#ws-layers-tree,.ws-builder-chrome) {
  background: var(--ws-panel) !important;
  background-image: none !important;
  border-color: var(--ws-border) !important;
  box-shadow: 0 10px 28px rgba(2, 8, 23, .28);
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
.ws-studio-container[data-ws-theme="light"] :is(.ws-builder-header,.ws-top-action-bar,#ws-left-dock-wrapper nav,#ws-left-drawer-content,#ws-right-dock-wrapper,#ws-inspector-panel,#ws-inspector-content,#ws-palette,#ws-layers-tree,.ws-builder-chrome) { box-shadow: 0 8px 24px rgba(15, 23, 42, .14); }
.ws-studio-container :is(.bg-white,.bg-slate-950,.bg-slate-900,.dark\:bg-slate-900) {
  background: var(--ws-panel-raised) !important;
  border-color: var(--ws-border) !important;
}
.ws-studio-container input:not(.liquid-glass-input),
.ws-studio-container select,
.ws-studio-container textarea {
  background: var(--ws-input-bg) !important;
  border-color: var(--ws-input-border) !important;
  color: var(--ws-input-text, var(--ws-text)) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
.ws-studio-container .liquid-glass-input {
  background: var(--ws-input-bg) !important;
  border-color: var(--ws-input-border) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* Generated hero CTAs share this contract. It prevents long labels from
 * collapsing into narrow pills while keeping the button treatment readable
 * over photographs and translucent panels. */
body.ms-glass-site .pt-2.flex.flex-wrap > button,
body.ms-glass-site button.bg-gradient-to-r,
body.ms-glass-site button.brand-bg,
body.ms-glass-site button.bg-indigo-600,
body.ms-glass-site button.bg-emerald-600 {
  min-height: 48px;
  min-width: 148px;
  padding: .75rem 1.5rem !important;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  line-height: 1.2;
}
.ws-studio-container button {
  min-height: 32px;
  padding-inline: .75rem;
  white-space: nowrap;
}

/* Trade appraisal hierarchy: make the three decisions scan as a workflow and
 * keep optional/legal detail visually quiet until it is needed. */
.appraisal-page .appraisal-stepper {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .7rem 1rem;
  border: 1px solid #dbe3ef;
  border-radius: 1rem;
  background: #fff;
  box-shadow: 0 8px 24px rgba(15,23,42,.06);
}
.appraisal-page .appraisal-step {
  display: flex;
  align-items: center;
  gap: .55rem;
  min-width: 0;
  color: #94a3b8;
}
.appraisal-page .appraisal-step span {
  display: grid;
  place-items: center;
  width: 1.55rem;
  height: 1.55rem;
  flex: 0 0 auto;
  border-radius: 999px;
  border: 1px solid rgba(148,190,230,.3);
  font-size: .7rem;
  font-weight: 900;
}
.appraisal-page .appraisal-step b,
.appraisal-page .appraisal-step small { display: block; line-height: 1.2; }
.appraisal-page .appraisal-step b { color: #334155; font-size: .75rem; }
.appraisal-page .appraisal-step small { margin-top: .12rem; font-size: .65rem; color: #64748b; }
.appraisal-page .appraisal-step-active span { background: #2563eb; border-color: #60a5fa; color: white; box-shadow: 0 0 0 3px rgba(37,99,235,.16); }
.appraisal-page .appraisal-stepper > i { height: 1px; flex: 1 1 2rem; min-width: 1rem; background: #cbd5e1; }
.appraisal-page .appraisal-workflow > .space-y-5 > .rounded-2xl,
.appraisal-page .appraisal-workflow > .rounded-2xl { box-shadow: 0 14px 38px rgba(0,0,0,.13), inset 0 1px 0 rgba(255,255,255,.07); }
.appraisal-page aside > .rounded-2xl { box-shadow: 0 14px 38px rgba(0,0,0,.14), inset 0 1px 0 rgba(255,255,255,.07); }
.appraisal-page aside #appr-list { scrollbar-width: thin; }

/* Appraisal page top bar: improved visual hierarchy and readability */
.appraisal-page > .flex.items-center.justify-between {
  background: #ffffff;
  padding: 1.25rem !important;
  border-radius: 1rem;
  border: 1px solid #dbe3ef;
  box-shadow: 0 10px 28px rgba(15,23,42,.07);
  margin-bottom: 1.5rem;
}

.appraisal-page > .flex.items-center.justify-between h2 {
  font-size: 1.375rem;
  letter-spacing: -0.02em;
  color: #0f172a;
}

.appraisal-page > .flex.items-center.justify-between p {
  color: #475569;
  line-height: 1.5;
  font-size: 0.95rem;
}

/* Button containment: ensure buttons stay within their card containers with proper spacing */
.appraisal-page aside .rounded-2xl {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  overflow: hidden;
}

.appraisal-page aside button {
  flex: 0 1 auto;
  min-height: 2.75rem;
  border-radius: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  transition: all 200ms ease;
}

.appraisal-page aside #appr-save-deal {
  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
  color: #ffffff;
  box-shadow: 0 4px 12px rgba(37, 99, 235, .25);
}

.appraisal-page aside #appr-save-deal:hover {
  background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
  box-shadow: 0 6px 16px rgba(37, 99, 235, .35);
  transform: translateY(-2px);
}

.appraisal-page aside #appr-save-deal:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

.appraisal-page aside #appr-doc-pdf-summary,
.appraisal-page aside #appr-doc-pdf-disclosure {
  background: #f8fafc;
  color: #334155;
  border: 1px solid #cbd5e1;
}

.appraisal-page aside #appr-doc-pdf-summary:hover,
.appraisal-page aside #appr-doc-pdf-disclosure:hover {
  background: #eef2f7;
  border-color: #94a3b8;
  color: #0f172a;
  transform: translateY(-1px);
}

.appraisal-page aside #appr-deal-msg {
  font-weight: 500;
  border-radius: 0.875rem;
  padding: 0.875rem 1rem;
  line-height: 1.4;
}

.appraisal-page aside > .flex.items-center.gap-2 {
  padding: 0.25rem 0;
  margin-top: 0.5rem;
}

.appraisal-page aside > .flex.items-center.gap-2 h3 {
  color: #0f172a;
  font-size: 1rem;
  font-weight: 700;
}

/* Improved text readability throughout appraisal cards */
.appraisal-page .rounded-2xl {
  background: #ffffff;
  border-color: #dbe3ef;
}

.appraisal-page .rounded-2xl h3 {
  color: #0f172a;
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
}

.appraisal-page .rounded-2xl p {
  color: #475569;
  font-size: 0.9rem;
  line-height: 1.5;
}

.appraisal-page .rounded-2xl label {
  color: #64748b;
  font-weight: 600;
  font-size: 0.75rem;
  letter-spacing: 0.05em;
}

.appraisal-page .rounded-2xl input,
.appraisal-page .rounded-2xl select,
.appraisal-page .rounded-2xl textarea {
  min-width: 0;
  background: #f8fafc;
  border: 1px solid #cbd5e1;
  color: #0f172a;
  font-size: 0.95rem;
}

.appraisal-page .rounded-2xl input::placeholder,
.appraisal-page .rounded-2xl textarea::placeholder {
  color: #94a3b8;
}

.appraisal-page .rounded-2xl input:focus,
.appraisal-page .rounded-2xl select:focus,
.appraisal-page .rounded-2xl textarea:focus {
  background: #ffffff;
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, .15);
  outline: none;
}

/* Appraisal cards use Tailwind's explicit `space-y-*` rhythm.  Do not add
   borders or padding to every nested div here: many of those divs are field
   groups, so a blanket selector creates uneven double gaps and dividers. */
.appraisal-page .appr-vin-row {
  display: grid;
  grid-template-columns: minmax(0,1fr) auto auto;
  gap: .5rem;
}

/* The appraisal uses light surfaces by default. Dark values are deliberately
 * scoped here so a daytime phone never receives translucent navy cards. */
.dark .appraisal-page .appraisal-stepper { background: rgba(9,20,39,.72); border-color: rgba(148,190,230,.22); box-shadow: inset 0 1px 0 rgba(255,255,255,.08); }
.dark .appraisal-page .appraisal-step b { color: #e2e8f0; }
.dark .appraisal-page .appraisal-stepper > i { background: rgba(148,190,230,.2); }
.dark .appraisal-page > .flex.items-center.justify-between { background: rgba(15,23,42,.72); border-color: rgba(148,190,230,.18); box-shadow: 0 14px 38px rgba(0,0,0,.15); }
.dark .appraisal-page > .flex.items-center.justify-between h2 { color: #ffffff; }
.dark .appraisal-page > .flex.items-center.justify-between p { color: #cbd5e1; }
.dark .appraisal-page aside > .flex.items-center.gap-2 h3,
.dark .appraisal-page .rounded-2xl h3 { color: #f1f5f9; }
.dark .appraisal-page .rounded-2xl { background: rgba(15,23,42,.76); border-color: rgba(148,190,230,.17); }
.dark .appraisal-page .rounded-2xl p { color: #cbd5e1; }
.dark .appraisal-page .rounded-2xl label { color: #94a3b8; }
.dark .appraisal-page .rounded-2xl input,
.dark .appraisal-page .rounded-2xl select,
.dark .appraisal-page .rounded-2xl textarea { background: rgba(2,6,23,.72); border-color: rgba(148,190,230,.22); color: #e2e8f0; }
.dark .appraisal-page .rounded-2xl input::placeholder,
.dark .appraisal-page .rounded-2xl textarea::placeholder { color: #64748b; }
.dark .appraisal-page .rounded-2xl input:focus,
.dark .appraisal-page .rounded-2xl select:focus,
.dark .appraisal-page .rounded-2xl textarea:focus { background: rgba(2,6,23,.88); border-color: #3b82f6; }
.dark .appraisal-page aside #appr-doc-pdf-summary,
.dark .appraisal-page aside #appr-doc-pdf-disclosure { background: rgba(148,163,184,.12); color: #cbd5e1; border-color: rgba(148,163,184,.2); }
.desk-section-summary { list-style: none; }
.desk-section-summary::-webkit-details-marker { display: none; }
.desk-section-chevron { display: inline-block; font-size: 1.25rem; line-height: 1; transform: rotate(0deg); transition: transform 150ms ease; }
.desk-section[open] > .desk-section-summary .desk-section-chevron { transform: rotate(90deg); }
.desk-workflow-steps { display: flex; align-items: center; gap: .65rem; margin: 0 0 1rem; padding: .65rem .85rem; border: 1px solid rgba(148,190,230,.22); border-radius: .9rem; background: rgba(9,20,39,.34); color: #94a3b8; }
.desk-workflow-step { display: inline-flex; align-items: center; gap: .4rem; font-size: .7rem; font-weight: 800; white-space: nowrap; }
.desk-workflow-step b { display: grid; place-items: center; width: 1.35rem; height: 1.35rem; border: 1px solid rgba(148,190,230,.3); border-radius: 999px; font-size: .65rem; }
.desk-workflow-step-active { color: #e2e8f0; }
.desk-workflow-step-active b { background: #2563eb; border-color: #60a5fa; color: #fff; }
.desk-workflow-steps > i { height: 1px; flex: 1 1 1rem; background: rgba(148,190,230,.2); }
.desk-desk-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 320px);
  gap: 1rem;
  align-items: start;
}
.desk-three-column-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
  align-items: start;
  min-width: 0;
  /* Measure THIS grid, not the window. The rail takes 280-320px out of the content
     column, so on a 1366px Chromebook the grid is only ~710px wide while the viewport
     is still far above every px breakpoint below — two 355px half-columns, in which
     "F&I commission (auto from the plan)" and "Split % to co-rep" wrap onto three
     lines. A container query sees the width the cards actually get. */
  container: desk-grid / inline-size;
}
.desk-column { min-width: 0; grid-column: span 2; }
.desk-column > .desk-section { margin-bottom: 1rem; }
.desk-column > .desk-section:last-child { margin-bottom: 0; }
.desk-column--full { grid-column: 1 / -1; }
.desk-column--half { grid-column: span 2; }
.desk-column--summary { grid-column: 1 / -1; position: relative; }
/* Below this the grid cannot hold two readable columns, so every card takes the row.
   The px media queries further down still handle the outer layout and the phone. */
@container desk-grid (max-width: 820px) {
  .desk-column--half { grid-column: 1 / -1; }
  /* F&I products / Fees / Add-ons split the same narrow column three ways off a
     `md:grid-cols-3` viewport breakpoint, so on a 1366px Chromebook they became three
     ~230px cards — narrow enough that each card's title and its right-aligned caption
     printed on top of each other. Measured off the column, they stack instead. */
}
/* Whatever the column count, a card narrower than this cannot fit an uppercase title
   and a right-aligned sentence on one row. Drop the caption rather than overlap it —
   the same call the 700px viewport rule below already makes, measured per card. */
.desk-section { container: desk-card / inline-size; }
.desk-operations-grid {
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:1rem;
  align-items:start;
}
.desk-operations-grid .desk-section { margin:0; min-width:0; }
.desk-operations-grid .desk-section--feature { grid-column:1 / -1; }
.desk-section-summary { min-height:52px; }
.desk-section-summary .ms-section-title { min-width:0; }
.desk-section-summary .desk-section-sub { max-width:280px; }
#desk-fni-catalog .ms-list-row { min-height:58px; }

/* Desk a Deal and Trade Appraisal are working forms. Accent belongs in the
   3px section rule + icon, not across the card surface. Keep light mode truly
   white and dark mode on the standard opaque work surface. */
html:not(.dark) .desk-section.ms-section-card,
html:not(.dark) .appraisal-page .appr-today-card.ms-section-card,
html:not(.dark) #appraisal-action-rail .appr-rail-section.ms-section-card {
  background:#ffffff !important;
  background-image:none !important;
  backdrop-filter:none !important;
  -webkit-backdrop-filter:none !important;
}
html.dark .desk-section.ms-section-card,
html.dark .appraisal-page .appr-today-card.ms-section-card,
html.dark #appraisal-action-rail .appr-rail-section.ms-section-card {
  background:#0f172a !important;
  background-image:none !important;
  backdrop-filter:none !important;
  -webkit-backdrop-filter:none !important;
}
@container desk-grid (max-width: 720px) {
  .desk-operations-grid { grid-template-columns:minmax(0,1fr); }
  .desk-operations-grid .desk-section--feature { grid-column:auto; }
}
@container desk-card (max-width: 460px) {
  .desk-section-summary > p { display: none; }
}
.desk-summary-panel {
  position: sticky;
  top: 1rem;
  align-self: start;
  min-width: 0;
  /* The rail stacks Deal summary → Deal status → actions, which is taller than the
     screen on a laptop. Without its own scroll the actions under the summary can never
     be reached. The subtrahend is NOT 2rem: the page does not scroll on <body>, it
     scrolls in the content <section> inside main.ms-dashboard-shell, whose scrollport
     already starts below the fixed header. 152px = 116px header offset (pt-[116px])
     + 20px shell bottom padding (lg:pb-5) + the 16px `top` inset above. */
  max-height: calc(100vh - 152px);
  overflow-y: auto;
}
.desk-summary-panel #desk-summary { box-shadow: 0 18px 48px rgba(0,0,0,.14), inset 0 1px 0 rgba(255,255,255,.06); }
.desk-column .desk-section-summary { min-width: 0; }
.desk-column .desk-section-summary > span { min-width: 0; }
.desk-column .desk-section-summary h3 { line-height: 1.25; }

@media (max-width: 1500px) {
  .desk-three-column-grid .p-5 { padding: 1rem; }
}
@media (max-width: 1120px) {
  .desk-desk-layout { grid-template-columns: minmax(0, 1fr); }
  /* One column: the deal is built top to bottom, so the summary and status come
     after the form (phones and narrow tablets), not above it. */
  .desk-summary-panel { position: static; order: 1; margin-top: 1rem; max-height: none; overflow-y: visible; }
  .desk-column,
  .desk-column--half { grid-column: 1 / -1; }
  [data-engine-mount="desk"] > [data-page-content="desk"] { padding: 0 !important; margin: 0 !important; }
}
@media (max-width: 700px) {
  .desk-three-column-grid { grid-template-columns: minmax(0, 1fr); gap: .75rem; }
  .desk-column,
  .desk-column--half,
  .desk-column--summary,
  .desk-column--full { grid-column: auto; }
  .desk-column .desk-section-summary { align-items: flex-start; }
  .desk-column .desk-section-summary > p { display: none; }
}
.appraisal-page { padding-top: .75rem; }
.appraisal-page .appr-primary-section { border-radius: 1rem; }
.appraisal-page .appr-section-label { margin-bottom: .75rem; font-size: .75rem; font-weight: 900; letter-spacing: .08em; text-transform: uppercase; color: #64748b; }
.appraisal-page .appr-today-card {
  border-radius: 1rem;
  box-shadow: 0 10px 28px rgba(15,23,42,.07);
}
.appraisal-page .appr-section-label.ms-section-title {
  display:flex;
  align-items:center;
  gap:.55rem;
  color:#334155;
  margin-bottom:.9rem;
}
.dark .appraisal-page .appr-section-label.ms-section-title { color:#e2e8f0; }
.appraisal-page .appr-rail-section.ms-section-card { overflow:hidden; }
.appraisal-page .appr-rail-summary > span:first-child {
  display:flex;
  align-items:center;
  gap:.5rem;
}
.appraisal-page .appr-rail-summary > span:first-child > svg {
  width:26px;
  height:26px;
  flex:0 0 26px;
  padding:6px;
  border-radius:8px;
  background:var(--ms-local-tint,#EFF6FF);
  color:var(--ms-local-accent,#2563EB);
  border:1px solid color-mix(in srgb, var(--ms-local-accent,#2563EB) 18%, transparent);
}

@media (max-width: 640px) {
  .appraisal-page { overflow-x: clip; }
  .appraisal-page .appraisal-stepper { gap: .35rem; padding: .6rem; }
  .appraisal-page .appraisal-step { gap: .35rem; }
  .appraisal-page .appraisal-step small { display: none; }
  .appraisal-page .appraisal-stepper > i { min-width: .5rem; }
  .desk-workflow-steps { gap: .3rem; overflow-x: auto; }
  .desk-workflow-step { font-size: .65rem; }

  /* Mobile appraisal improvements */
  .appraisal-page > .flex.items-center.justify-between {
    flex-direction: column;
    gap: 1rem;
    padding: 1rem !important;
  }

  .appraisal-page > .flex.items-center.justify-between > div:last-child {
    width: 100%;
  }

  .appraisal-page > .flex.items-center.justify-between button {
    width: 100%;
  }

  .appraisal-page aside button {
    min-height: 2.5rem;
    font-size: 0.9rem;
  }

  .appraisal-page .rounded-2xl {
    padding: 1rem;
  }

  .appraisal-page .rounded-2xl h3 {
    font-size: 0.875rem;
  }
  .appraisal-page .appr-vin-row { grid-template-columns: minmax(0,1fr) minmax(0,1fr); }
  .appraisal-page .appr-vin-row #appr-vin { grid-column: 1 / -1; width: 100%; }
  .appraisal-page .appr-vin-row button { width: 100%; min-width: 0; padding-inline: .65rem; }
  .appraisal-page .appr-vin-links > button { flex: 1 1 calc(50% - .5rem); min-width: 0; white-space: normal; line-height: 1.2; }
  .desk-workflow-steps > i { min-width: .5rem; }
}

@supports not ((backdrop-filter: blur(1px))) {
  .ms-glass-surface,.ms-glass-panel,
  body.ms-glass-site :is(div,section,article,aside,form,details,header,footer,nav).bg-white,
  body.ms-glass-site :is(div,section,article,aside,form,details,header,footer,nav).bg-slate-900,
  html[data-ms-glass="global"] :is(div,section,article,aside,form,details,header,footer,nav).rounded-xl.bg-white,
  .ws-studio-container :is(.ws-builder-header,.ws-top-action-bar,#ws-left-dock-wrapper nav,#ws-left-drawer-content,#ws-right-dock-wrapper,#ws-inspector-panel,#ws-inspector-content,#ws-palette,#ws-layers-tree) { background: var(--ws-panel) !important; }
}
@media (prefers-reduced-motion: reduce) {
  .ms-glass-surface,.ms-glass-panel { transition: none !important; }
}
@media (forced-colors: active) {
  .ms-glass-surface,.ms-glass-panel,.ws-studio-container :is(.ws-builder-header,.ws-top-action-bar,#ws-left-drawer-content,#ws-inspector-panel) { background: Canvas !important; border: 1px solid CanvasText !important; box-shadow: none !important; backdrop-filter: none !important; }
}

/* ── Appraisal: size the workflow off its own column, not the window ──────────
   The three grids inside the appraisal flow pick their column count from viewport
   breakpoints (md:/lg:/xl:), but the flow does not get the viewport. From 1280px up
   the pinned "Recent Appraisals" sidebar takes 300–340px out of the row, so the flow
   column is ~650px at 1280px wide while `xl:grid-cols-3` still splits it three ways —
   206px cards whose headings, inputs and buttons all wrap. Below 1280px the sidebar
   stacks but `lg:grid-cols-3` keeps the action row at 227px for the same reason.
   Container queries measure the column that actually holds the cards. The Tailwind
   classes stay as the no-container-query fallback. */
.appraisal-page .appraisal-flow { container: appraisal-flow / inline-size; }

@container appraisal-flow (max-width: 1039px) {
  .appraisal-page .appraisal-workflow { grid-template-columns: minmax(0,1fr) minmax(0,1fr); }
  .appraisal-page .appraisal-disclosure-row { grid-template-columns: minmax(0,1fr); }
}
@container appraisal-flow (max-width: 659px) {
  .appraisal-page .appraisal-workflow { grid-template-columns: minmax(0,1fr); }
}

/* 3 - Appraisal was nested inside the right-hand workflow column, so it could only
   ever be half the flow — ~490px of a 1366 Chromebook once the department nav is
   out — and its Recon / Target gross pair then split that again. It is a row of its
   own now, below the two columns. `1 / -1` rather than a span count, because the
   container queries above change how many columns there are. */
.appraisal-page .appraisal-span { grid-column: 1 / -1; }
.appraisal-page .appraisal-span { container: appraisal-span / inline-size; }
/* Full width would otherwise hand Recon and Target gross a ~500px input each and
   stretch Book value and Comp radius across the whole row. Four money fields read
   as one row once the card is wide enough to hold them; below that they fall back
   to the two-up the markup already asks for, then to one. The `> *` reset clears
   the markup's col-span-2 on Book value and Comp radius when all four fit. */
@container appraisal-span (min-width: 760px) {
  .appraisal-page .appr-field-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .appraisal-page .appr-field-grid > * { grid-column: auto; }
}
@container appraisal-span (max-width: 419px) {
  .appraisal-page .appr-field-grid { grid-template-columns: minmax(0, 1fr); }
  .appraisal-page .appr-field-grid > * { grid-column: auto; }
}
/* Notify Appraiser / Sales Rep / Documents now live in ONE section beside Customer,
   so they sit in a HALF-width column of the workflow grid — a tighter squeeze than the
   full-width row they came from. Same container-query treatment, lower thresholds: two
   across only while the flow is wide enough that half of it still fits two. */
/* Notify Appraiser / Sales Rep / Documents / Recent Appraisals are rail sections now —
   the same collapsible card engineRail() renders for Reports / Next Actions / Quick
   Actions — so the appraisal rail reads as part of the workspace sidebar it gets moved
   into rather than a foreign block appended beneath it. */
.appraisal-page .appr-rail-summary,
#appraisal-action-rail .appr-rail-summary { list-style: none; }
.appraisal-page .appr-rail-summary::-webkit-details-marker,
#appraisal-action-rail .appr-rail-summary::-webkit-details-marker { display: none; }
.appraisal-page .appr-rail-summary::marker,
#appraisal-action-rail .appr-rail-summary::marker { content: ''; }
/* The page reserves a column for the rail. Once appraisal-rail-qa.js lifts the rail into
   the workspace sidebar that column would sit empty, so it is hidden with it. */
.appraisal-page .appr-rail-home.hidden { display: none; }
/* In the workspace sidebar the rail is the column, so drop the page's own sticky offset
   and let the sidebar own the scrolling. */
[data-engine-rail] #appraisal-action-rail { position: static; top: auto; width: 100%; }
[data-engine-rail] #appraisal-action-rail .appraisal-list-filters { grid-template-columns: minmax(0, 1fr); }
[data-engine-rail] #appraisal-action-rail #appr-list { max-height: 40vh; overflow-y: auto; }
/* Between 1024 and 1439px the workspace rail is not a column at all — marketsync-theme
   lays it out as a three-across strip beneath the content. The appraisal rail is a
   single child of that strip, so it was being squeezed into one 343px cell on a 1366px
   Chromebook while two cells sat empty beside it. Span the strip and let its own
   sections fill it. */
@media (min-width: 1024px) and (max-width: 1439px) {
  .ms-engine-layout--rail > [data-engine-rail] > #appraisal-action-rail {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 1rem;
    align-items: start;
  }
  .ms-engine-layout--rail > [data-engine-rail] > #appraisal-action-rail > * { margin: 0; }
}

/* ── The block palette sizes itself off its own column ─────────────────────
   renderElementorPalette() is drawn in TWO places: the narrow left dock, where two
   across and a 360px scroller is right, and the Block Library modal, which is four
   times wider and was showing the same two columns and the same short scroller —
   six of twenty-four blocks visible with a lot of empty modal around them. A
   viewport breakpoint cannot separate the two; they are on screen at the same
   window size. */
#ws-palette { container: ws-palette / inline-size; }

@container ws-palette (min-width: 640px) {
  #ws-palette-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    max-height: 58vh;
  }
}

/* ── A Website settings card sizes its rows off the CARD ───────────────────
   These cards sit in a 1 / 2 / 3-column grid — in the settings modal and on the
   full Settings page — so one card is anywhere from ~290px to the whole width, at
   the same window size. Rows written for the wide case ran out of their card at
   three across: the site address sat under the Published checkbox, and the hero and
   social-share pickers pushed their Upload and Browse Photos buttons up to 219px
   past the card's edge. */
.ms-site-setting-card { container: ms-setting-card / inline-size; }
/* Several of these rows are `prefix + input` on one flex line — "…/site.html?d=" and
   "https://". A flex item will not shrink below its own intrinsic width without this,
   so both inputs ran past the card's right edge however narrow the card became. */
.ms-site-setting-card input:not([type="checkbox"]):not([type="radio"]):not([type="color"]) { min-width: 0; }
/* Same reason one level up: the field's own wrapper is a flex item of the row, and
   `flex-1` leaves min-width at auto, so the wrapper refused to shrink and pushed the
   address input out even once the input itself could. */
.ms-site-setting-card .ms-setting-row > * { min-width: 0; }

@container ms-setting-card (max-width: 420px) {
  /* Address + Published: the checkbox takes the line under the field it applies to
     rather than squeezing it. */
  .ms-setting-row { flex-wrap: wrap; }
  .ms-setting-row > label { margin-top: 0; }
  /* Two fields side by side in ~290px is ~140px each, which is narrower than the
     colour swatch and the image URL both need. */
  .ms-setting-pair { grid-template-columns: minmax(0, 1fr); }
  /* URL box, Upload, Browse Photos. The buttons take the line below, so the URL is
     readable instead of every part being unusable. */
  .ms-setting-picker { flex-wrap: wrap; }
  .ms-setting-picker > input:not([type="file"]) { flex: 1 1 100%; min-width: 0; }
  .ms-setting-picker > button { flex: 0 0 auto; }
}

/* ── The builder's photo row sizes itself off the row, not the window ───────
   Background style / Or upload a photo is a thumbnail, an address box and two
   buttons. The Property Inspector is a 256px dock, so putting all four on one line
   left the address box 28px wide — "https://w", with no way to read or edit the URL
   it was showing. A viewport breakpoint cannot see that: the dock is 256px on a
   1366px Chromebook and on a 4K monitor alike.
   The address box asks for a usable width and the buttons drop beneath it only when
   they no longer fit beside it — so the same field still renders on one line in the
   section-card grid, which is twice as wide. */
.ws-image-field {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}
.ws-image-field > .ws-image-thumb { flex: 0 0 auto; }
/* 9rem is the WRAP THRESHOLD, not the final width: it is small enough to sit beside
   the thumbnail on the dock's 236px line (51 + 144 fits, and the box then grows to
   fill ~177px) and large enough that Upload and Browse cannot also squeeze in, so
   they take the line below. min-width:0 because a flex item will not shrink under
   its own content width without it. */
.ws-image-field > .ws-image-url { flex: 1 1 9rem; min-width: 0; }
/* margin-left:auto keeps the pair against the right edge on both layouts: beside the
   address box when it fits, and under it, still right-aligned, when it does not. */
.ws-image-field > .ws-image-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
  flex: 0 0 auto;
}

/* ── The rail card sizes its contents off ITSELF ────────────────────────────
   Once appraisal-rail-qa.js lifts this rail into the workspace sidebar the cards are
   ~250px wide on a 1366 Chromebook (four across the strip above) and ~300px in the
   pinned sidebar — but everything inside was written for the page's own ~1000px
   column. On a Chromebook the heading clipped to "RECENT APPR…" while its scope label
   broke in half across two lines over it, and a row showed 38px of the vehicle name.
   A viewport breakpoint cannot see any of that: the window is 1366px wide either way.
   Same container-query treatment as .appraisal-flow above. */
.appr-rail-section { container: appr-rail-card / inline-size; }

@container appr-rail-card (max-width: 439px) {
  /* The heading and its scope label are one flex row. Let it wrap, and drop the
     tracking so "RECENT APPRAISALS" fits the line rather than ellipsising at
     "RECENT APPR…". */
  .appr-rail-summary > span:first-child { flex-wrap: wrap; row-gap: 0.125rem; letter-spacing: 0; }
  /* `· all salespeople` is metadata, not a second heading: its own line, and none of
     the heading's uppercase weight. flex-basis rather than a width guess, so it drops
     to that line whatever the card measures. */
  .appr-rail-summary #appr-list-scope {
    flex-basis: 100%;
    white-space: nowrap;
    text-transform: none;
    letter-spacing: normal;
    font-weight: 600;
  }
  /* The row stops being name-beside-price on one line. In 224px of content that gave
     the vehicle 38px. It becomes three rows instead — name, then offer with its
     Retail/Wholesale badge, then the customer line — so the name and the meta each get
     the whole card and the offer is never squeezed:

       2025 Chevrolet Trax LT AWD
       $17,611 CAD             RETAIL
       Jason Massie · Sep 20, 2026

     `display: contents` promotes the wrappers' children to grid items, so the same
     markup serves both layouts and nothing has to be rendered twice. */
  .appr-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 0.5rem;
    row-gap: 0.125rem;
  }
  .appr-row-main,
  .appr-row-title { display: contents; }
  .appr-row-label { grid-column: 1 / -1; grid-row: 1; }
  .appr-row-offer { grid-column: 1; grid-row: 2; }
  .appr-row-title > span:last-child { grid-column: 2; grid-row: 2; justify-self: end; }
  .appr-row-meta { grid-column: 1 / -1; grid-row: 3; }
}

/* The Recent Appraisals filters sit in the 300–340px pinned sidebar from 1280px up,
   where `sm:grid-cols-3` leaves each control ~90px — "Search vehicle, customer, VIN…"
   and "All dispositions" both render clipped. The sidebar only pins at that same
   breakpoint, so stack the filters exactly when it does. */
@media (min-width: 1280px) {
  .appraisal-page aside .appraisal-list-filters { grid-template-columns: minmax(0,1fr); }
}

/* ── Dashboard header fit ───────────────────────────────────────────────────
   Both header groups were flex-shrink:0, so their natural width simply won: at
   1366px (a Chromebook) the row measured 1448px and the profile, notifications
   and sign-out buttons sat 82px past the right edge with no way to reach them.
   The groups shrink now; these rules decide what gives first, cheapest last.
   Written here rather than as Tailwind utilities because `2xl:*` and arbitrary
   max-widths are not in the prebuilt tailwind-built.css and would silently no-op. */
#ext-header-btn .ms-ext-label-full { display: none; }
#ext-header-btn .ms-ext-label-short { display: inline; }
@media (min-width: 1536px) {
  /* Only from here is there room for the long label — measured, not guessed. */
  #ext-header-btn .ms-ext-label-full { display: inline; }
  #ext-header-btn .ms-ext-label-short { display: none; }
}
/* A long dealership line ("MARKETSYNC HQ · PLATFORM OWNER") forced its own width
   and pushed the buttons off. Cap it and let it ellipsis instead. */
.ms-header-identity { max-width: 14rem; }
@media (max-width: 1439px) { .ms-header-identity { max-width: 11rem; } }
/* Above this the row has slack, so show the line in full rather than ellipsising
   a name that fits. */
@media (min-width: 1536px) { .ms-header-identity { max-width: none; } }

/* The marketing studios strip has carried `hide-scrollbar` since it was written, but the
   utility was never defined anywhere — harmless while the strip was `w-max` and simply
   overflowed the page, and visible the moment it started scrolling inside its column. */
.hide-scrollbar { scrollbar-width: none; -ms-overflow-style: none; }
.hide-scrollbar::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* ── Merge-field preview ──────────────────────────────────────────────────────
   A workflow card shows the message a customer will receive. Its dynamic parts
   ({{customer.first_name}}, {{vehicle.model}}) used to render as bordered
   monospace chips, so a three-line SMS arrived on screen as five code boxes
   with sentence fragments between them — loud, and unreadable as a message.

   The value is substituted instead, and marked with a tint and a dashed
   underline: still obviously dynamic, but the sentence stays a sentence. No
   border and no background box, because that is what made the cards shout. */
.ms-merge {
  color: #4338ca;                              /* indigo-700 */
  font-weight: 600;
  border-bottom: 1px dashed rgba(67, 56, 202, 0.45);
  /* Keeps the underline off the descenders so the line of text stays even. */
  padding-bottom: 1px;
}
.dark .ms-merge {
  color: #a5b4fc;                              /* indigo-300 */
  border-bottom-color: rgba(165, 180, 252, 0.4);
}
/* Inside a filled bubble (the SMS simulator) the tint has to read against the
   bubble, not the page, so it borrows the bubble's own foreground. */
.ms-sms-bubble .ms-merge,
.bg-indigo-600 .ms-merge,
.bg-indigo-700 .ms-merge {
  color: inherit;
  border-bottom-color: rgba(255, 255, 255, 0.55);
}
