/*
  Datos brand refresh
  --------------------
  Purely visual overrides layered on top of the existing Sneat/Bootstrap theme.
  No markup or JS changes -- this file only redefines colors, typography,
  spacing, borders, shadows, and motion on top of classes that already exist
  in every template (.card, .btn-primary, .badge.bg-label-*, etc).

  Why these changes:
  - Brand colors are locked in (see CLAUDE.md): primary blue #2E5EFF,
    secondary red #DD4043 -- carried over from the marketing-site redesign
    into the DBM product UI. This supersedes an earlier navy/red pass that
    predated the locked brand.
  - Typography and surface treatment for DBM specifically follow Tim's
    ledger_2.html reference sample: Space Grotesk for h1/h2/h3, Poppins for
    body copy, JetBrains Mono for labels/mono accents, on a light surface
    palette (white cards, light gray page background). This is DBM-scoped
    and intentionally diverges from the landing page, which keeps DM Serif
    Display headings on a dark background -- the two are no longer meant to
    share one visual system.
  - Bug found in an earlier pass, still relevant: core.css defines
    --bs-primary but never updates the matching --bs-primary-rgb, which is
    still the theme's original default (105, 108, 255 / #696cff). Every
    Bootstrap utility that reads the rgb variable (.text-primary,
    .bg-label-primary, any rgba(var(--bs-primary-rgb)) opacity utility) would
    render a stale purple-blue instead of the intended brand color if left
    unfixed. Fixed here.
  - Cards/buttons get a quieter, thinner-border treatment instead of heavy
    default shadows, spacing is normalized to a 4px-based scale, and hover/
    focus states use a spring easing curve instead of linear/no transition.
*/

:root {
  --brand-blue: #2E5EFF;
  --brand-blue-rgb: 46, 94, 255;
  --brand-blue-hover: #1f47d6;
  --brand-accent: #DD4043;
  --brand-accent-rgb: 221, 64, 67;
  --brand-accent-hover: #c73538;

  --gray-50: #fafafa;
  --gray-100: #f4f4f5;
  --gray-200: #e4e4e7;
  --gray-300: #d4d4d8;
  --gray-500: #71717a;
  --gray-700: #3f3f46;
  --gray-900: #18181b;

  /* Light surface palette -- matches Tim's ledger_2.html reference sample
     (--bg/--surface/--ink/--muted/--border). */
  --dbm-bg: #F5F6FA;
  --dbm-surface: #FFFFFF;
  --dbm-surface-2: #F0F1F5;
  --dbm-border: rgba(10, 10, 15, 0.09);
  --dbm-border-soft: rgba(10, 10, 15, 0.09);
  --dbm-text: #0A0A0F;
  --dbm-muted: #8B8D9B;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;
  --space-12: 48px;

  --ease-spring: cubic-bezier(0.32, 0.72, 0, 1);

  /* Brand blue as the dominant color, fixing the stale rgb bug above */
  --bs-primary: var(--brand-blue);
  --bs-primary-rgb: var(--brand-blue-rgb);
}

/* Typography: Space Grotesk for headings, Poppins for body, JetBrains
   Mono for labels/mono accents -- fonts themselves are loaded in base.html;
   this just applies them on top of the existing Sneat markup. */
body {
  font-family: 'Poppins', sans-serif;
}
h1, h2, h3 {
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 700;
}
.badge, .card-header .card-title small, table thead th,
.form-label, .form-check-label,
.num,
.card-info .card-text, .card-info .card-title, .card-info small {
  font-family: 'JetBrains Mono', monospace;
}

/* Numeric table cells (invoice totals, item prices, etc.) -- template-level
   `class="num"` marks these since Sneat's markup has no shared class for
   them by default. Right-aligned to match the ledger reference's number
   columns. */
td.num, th.num {
  text-align: right;
  vertical-align: middle;
}

/* List pages' headline money column(s) (quotes' Total, invoices' Total/Paid/
   Balance) -- matches the dashboard KPI card number font (Space Grotesk, via
   the h1/h2/h3 rule above) instead of the usual .num JetBrains Mono
   treatment other columns use. */
.metric-num {
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 700;
}

/* Auth page heading (login + register) -- both standalone pages, each with their own text,
   share this one class instead of duplicating rules under two names. DM Serif Display has
   only one real weight (400); font-weight:700 here is a browser-synthesized faux-bold, chosen
   over text-stroke or swapping fonts. Tight negative letter-spacing keeps longer headlines
   ("Datos Business Manager") on one line inside the 480px card. */
.auth-heading {
  font-family: 'DM Serif Display', serif;
  font-weight: 700;
  font-size: clamp(1.9rem, 1.5rem + 1.6vw, 2.4rem);
  letter-spacing: -0.03em;
  color: var(--dbm-text);
}

/* Auth pages (login + register): swap the vendor Sneat corner-graphic pseudo-elements
   (page-auth.css) for a full-page particle canvas, and widen the card. Scoped to .auth-page
   so it only applies where the template opts in. */
.authentication-wrapper.auth-page .authentication-inner:before,
.authentication-wrapper.auth-page .authentication-inner:after {
  /* page-auth.css (vendor) defines the same selector at equal specificity and loads after
     brand-refresh.css in these pages' <head>, so it would otherwise win the cascade. */
  content: none !important;
  display: none !important;
}
#auth-particle-canvas {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.authentication-wrapper.auth-page .authentication-inner {
  position: relative;
  z-index: 1;
  /* page-auth.css sets max-width:400px at equal selector specificity and loads after this
     file, so it would otherwise win the cascade (same issue as the corner-graphics rule
     above) -- !important needed to actually widen the card. */
  max-width: 480px !important;
}

/* Auth page background: dark, matching the landing hero, instead of the light DBM page
   background used everywhere else. Scoped to body.auth-page-body so this doesn't touch the
   site-wide light theme decision. Higher specificity than the `html, body` rule below wins
   the !important tie. */
body.auth-page-body {
  background-color: #0A0A0F !important;
}

/* Navbar profile avatar: same look as the Staff/Employees list avatars (.avatar-initial +
   .bg-label-primary -- salmon fill, dark salmon-red text, bold, uppercase). No
   overflow:hidden here -- that would clip Sneat's .avatar-online status dot (an :after
   pseudo-element sitting in the box's corner, outside the circle's own radius). */
.navbar-avatar {
  position: relative;
  border-radius: 50%;
}

/* Register card is wider than login's -- more fields (name, password confirm) need the room.
   Higher specificity (4 classes vs. 3) than the shared .auth-page rule above, plus
   !important, so it wins over both that rule and the vendor max-width:400px. */
.authentication-wrapper.register-page .authentication-inner {
  max-width: 620px !important;
}

/* Small print under the register form (Terms/Privacy disclaimer) -- same font as the auth
   subtext (inherits Poppins from body), just smaller and muted instead of full-contrast ink. */
.auth-fineprint {
  font-size: 0.8rem;
  color: var(--dbm-muted);
}

/* Auth page links: core.css/theme-default.css (vendor) hardcode a leftover salmon
   (#CD5C5C) on both `a` and `a:hover` from the pre-brand-pivot theme. brand-refresh's site-wide
   `a { color: var(--brand-blue) }` below beats the vendor `a` rule on source order, but never
   touches `:hover`, so the vendor's more specific `a:hover` rule still wins there -- blue
   normally, salmon on hover/click. Scoped fix, not a change to the global `a` rule: links on
   auth pages should read as plain text with just an underline, no color of their own at all.
   This selector already out-specifies the vendor rules, no !important needed. */
.authentication-wrapper.auth-page a,
.authentication-wrapper.auth-page a:hover,
.authentication-wrapper.auth-page a:focus,
.authentication-wrapper.auth-page a:active {
  color: inherit;
  text-decoration: underline;
}

/* ...but a link styled as a button is a button. The rule above is for the small
   text links on these pages ("Sign in instead", "Log out"); it was also
   underlining the primary action on the 404 and 500 pages, which reads as a
   mistake rather than a link. */
.authentication-wrapper.auth-page a.btn,
.authentication-wrapper.auth-page a.btn:hover,
.authentication-wrapper.auth-page a.btn:focus,
.authentication-wrapper.auth-page a.btn:active {
  color: #fff;
  text-decoration: none;
}

/* Cards: white surface, thin quiet border, lift + blue glow on hover instead
   of a heavy default drop shadow. */
.card {
  background-color: var(--dbm-surface) !important;
  border: 1px solid var(--dbm-border) !important;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) !important;
  color: var(--dbm-text);
  transition: border-color 220ms var(--ease-spring), transform 220ms var(--ease-spring),
    box-shadow 220ms var(--ease-spring);
}
.card:hover {
  border-color: rgba(var(--brand-blue-rgb), 0.4) !important;
  transform: translateY(-2px);
  box-shadow: 0 12px 28px rgba(var(--brand-blue-rgb), 0.14) !important;
}

/* Buttons: brand blue primary, spring-eased hover/active instead of an instant color snap.
   !important is needed here -- core.css's compiled Sneat/Bootstrap button rules carry higher
   specificity than a plain .btn-primary selector, so a bare override loses the cascade.
   theme-default.css (vendor) also ships a colored box-shadow, a translateY hover lift, and a
   salmon (#F08080) :active/checked color left over from the old red theme -- all three are
   cleared explicitly below so the button reads flat, not 3D. */
.btn-primary {
  background-color: var(--bs-primary) !important;
  border-color: var(--bs-primary) !important;
  box-shadow: none !important;
  transition: background-color 150ms var(--ease-spring),
    border-color 150ms var(--ease-spring), transform 150ms var(--ease-spring);
}
.btn-primary:hover,
.btn-primary:focus {
  background-color: var(--brand-blue-hover) !important;
  border-color: var(--brand-blue-hover) !important;
  box-shadow: none !important;
  transform: none;
}
.btn-primary:active,
.btn-primary.active,
.btn-check:checked + .btn-primary,
.btn-check:active + .btn-primary {
  background-color: var(--brand-blue-hover) !important;
  border-color: var(--brand-blue-hover) !important;
  box-shadow: none !important;
  transform: scale(0.98);
}
.btn-primary:focus-visible {
  outline: 2px solid var(--brand-accent);
  outline-offset: 2px;
  box-shadow: none !important;
}
.btn-primary:disabled,
.btn-primary.disabled {
  box-shadow: none !important;
}

/* Dashboard refresh + date filter are bare icons, not buttons -- grey by
   default, darkening on hover; the date filter icon turns brand-blue (matching
   the active sidebar tab) whenever a non-default period is applied, via
   .is-filtered. */
.dashboard-refresh-icon,
#periodFilterToggle {
  color: rgba(113, 113, 122, 0.55);
  font-size: 1.1rem;
  cursor: pointer;
  width: 32px;
  height: 32px;
  padding: 0;
  border-radius: 50%;
  border: 2px solid rgba(113, 113, 122, 0.55);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}
.dashboard-refresh-icon:hover,
#periodFilterToggle:hover {
  color: var(--gray-700);
  background-color: var(--gray-100);
}
#periodFilterToggle.is-filtered {
  color: var(--brand-blue);
  background-color: rgba(var(--brand-blue-rgb), 0.1);
  border-color: rgba(var(--brand-blue-rgb), 0.45);
}
.dashboard-refresh-icon.is-loading {
  animation: dbm-refresh-spin 0.7s linear infinite;
  pointer-events: none;
}
@keyframes dbm-refresh-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* Date filter dropdown's active item -- same active-tab treatment as the sidebar
   (.bg-menu-theme .menu-item.active > .menu-link above) instead of Sneat's default
   filled-purple .dropdown-item.active. Sneat's own theme-default.css has a *more*
   specific rule for this exact case (`.dropdown-item:not(.disabled).active`, 3
   classes' worth of specificity) plus !important -- matching with just 2 classes
   here lost that fight silently, so this needs to out-specify it, not just out-!important it. */
.dropdown-menu .dropdown-item.period-option.active {
  background-color: rgba(var(--brand-blue-rgb), 0.1) !important;
  color: var(--brand-blue) !important;
  font-weight: 600 !important;
}

/* Dashboard loading/empty state: whole-card overlays, not just the chart/value area --
   a card with a .card-header (its title) and a card with no header (KPI cards, title
   inside .card-body) both need the same treatment, so this sits directly on .card
   (inset:0 covers header + body alike) rather than nested inside .card-body. Requires
   .card to be a positioning context -- added below, no existing rule conflicts.
   Loading pulses (Instagram/Facebook-style flat grey blink, reusing core.css's global
   `placeholder-glow` keyframe); empty is the same flat grey but static, with a message
   specific to the active period so "no data" doesn't read as "broken" or hide the fact
   that another date filter might have data. */
.card { position: relative; }

.card-overlay-skeleton,
.card-overlay-empty {
  position: absolute;
  inset: 0;
  z-index: 4;
  border-radius: inherit;
  display: none;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 1rem;
}
.card-overlay-skeleton {
  background-color: var(--gray-200, #e9ecef);
  animation: placeholder-glow 2s ease-in-out infinite;
}
.card-overlay-empty {
  background-color: var(--gray-200, #e9ecef);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--dbm-muted);
}
.card-overlay-skeleton.is-active,
.card-overlay-empty.is-active {
  display: flex;
}

/* .text-primary/.text-success/etc utility classes bake a literal color at
   compile time rather than chaining through --bs-primary live (same issue
   as .btn-primary above) -- override explicitly. */
.text-primary { color: var(--bs-primary) !important; }

/* Form field focus: branded, restrained ring instead of the browser default */
.form-control:focus,
.form-select:focus {
  border-color: var(--bs-primary);
  box-shadow: 0 0 0 3px rgba(var(--bs-primary-rgb), 0.12);
}

/* =========================================================================
   DBM light theme
   -------------------------------------------------------------------------
   Reskin of the Sneat admin shell (sidebar, navbar, cards, tables, forms,
   dropdowns) onto a light surface palette matching Tim's ledger_2.html
   reference: soft gray page background, white card surfaces, near-black
   text, thin hairline borders. This is CSS-only -- no markup/JS changes --
   so every page's existing Sneat structure, chart wiring, and API calls
   keep working as-is; only the paint layer changes. Uses !important in the
   same places the rest of this file already does, because Sneat's compiled
   theme classes (.bg-menu-theme, .bg-navbar-theme, table borders, etc.) set
   colors with higher specificity or !important of their own.

   Sneat's own light-theme defaults (core.css/theme-default.css) already
   supply correct, legible colors for plain semantic utilities -- .bg-label-*
   chips, .text-success/.text-info/.text-warning/.text-danger, and
   .avatar-initial.bg-label-* -- so unlike the dark theme this pass used to
   override, those are left alone here and simply fall through to Sneat's
   native pastel-chip styling. Only .badge.bg-label-primary needs an explicit
   rule below, since Sneat ships no built-in class for it.
   ========================================================================= */

html, body {
  background-color: var(--dbm-bg) !important;
  color: var(--dbm-text);
}
h1, h2, h3, h4, h5, h6 {
  color: var(--dbm-text);
}
a { color: var(--brand-blue); }
hr { border-color: var(--dbm-border); opacity: 1; }
.text-muted { color: var(--dbm-muted) !important; }

/* Sidebar */
.bg-menu-theme {
  background-color: var(--dbm-surface) !important;
  color: var(--dbm-muted);
  border-right: 1px solid var(--dbm-border);
}
.bg-menu-theme .menu-header-text { color: var(--dbm-muted) !important; opacity: 0.7; }
.bg-menu-theme .js-sidebar-section-title {
  color: var(--brand-accent) !important;
  opacity: 1;
  font-family: 'JetBrains Mono', monospace;
}
.bg-menu-theme .menu-link { color: var(--dbm-muted); transition: background-color 180ms var(--ease-spring), color 180ms var(--ease-spring); }
.bg-menu-theme .menu-link:hover,
.bg-menu-theme .menu-link:focus {
  background-color: rgba(var(--brand-blue-rgb), 0.06);
  color: var(--dbm-text) !important;
}
.bg-menu-theme .menu-item.active > .menu-link {
  background-color: rgba(var(--brand-blue-rgb), 0.1) !important;
  color: var(--brand-blue) !important;
  box-shadow: none !important;
}
.bg-menu-theme .menu-item.active > .menu-link .menu-icon {
  color: var(--brand-blue) !important;
}
.bg-menu-theme .menu-sub { background-color: transparent; }
.app-brand { border-bottom: 1px solid var(--dbm-border) !important; }

/* Profile page's Account/Company Details tabs (.nav-pills, used nowhere else in the app) --
   same active-tab treatment as the sidebar above, instead of Sneat's default filled pill.
   Sneat's own .nav-pills .nav-link.active rule is 3 classes deep with a baked literal
   color + !important, so these need the ".nav-pills" prefix too just to match its
   specificity -- otherwise it still wins the cascade despite !important on both sides. */
.nav-pills .profile-tab-link {
  background-color: transparent !important;
  color: var(--dbm-muted) !important;
  font-weight: 500;
}
.nav-pills .profile-tab-link:hover {
  background-color: rgba(var(--brand-blue-rgb), 0.06) !important;
  color: var(--dbm-text) !important;
}
.nav-pills .profile-tab-link.active {
  background-color: rgba(var(--brand-blue-rgb), 0.1) !important;
  color: var(--brand-blue) !important;
  font-weight: 600;
  box-shadow: none !important;
}

/* Navbar */
.bg-navbar-theme {
  background-color: rgba(255, 255, 255, 0.85) !important;
  backdrop-filter: blur(10px);
  color: var(--dbm-text);
  border-bottom: 1px solid var(--dbm-border);
}
.bg-navbar-theme .form-control { color: var(--dbm-text); }
.bg-navbar-theme .form-control::placeholder { color: var(--dbm-muted); }

/* Top-of-page greeting, replacing the old search/profile navbar bar -- same DM Serif Display
   faux-bold treatment as the login/register headings (.auth-heading), scaled down for a
   navbar rather than a hero. No card background: floats directly on the page. */
/* Page breadcrumbs (e.g. "Home / Customers") -- font only, size/color/weight all stay as
   whatever the existing h4/text-muted/fw-bold classes already give them. */
.dbm-breadcrumb {
  font-family: 'DM Serif Display', serif;
  font-size: 1.625rem;
}

/* Live running total next to the Add/Edit Quote modals' "+ Add another item" button --
   same typeface as the modal title (.dbm-breadcrumb) but sized to sit inline next to a
   small round icon button rather than as a heading, and muted since it's a live preview
   rather than a committed value. */
.quote-live-total {
  font-family: 'DM Serif Display', serif;
  font-size: 1rem;
  color: var(--dbm-muted);
}

/* Round icon-only "Add" trigger button on list pages, and the matching modal "Close" (x)
   trigger -- same quiet transparent/bordered language as .btn-outline-secondary and the
   pagination buttons below, not a filled button. */
.btn-add-round,
.btn-close-round {
  width: 28px;
  height: 28px;
  min-width: 28px;
  padding: 0;
  border-radius: 50%;
  background-color: transparent !important;
  border: 2px solid rgba(113, 113, 122, 0.55) !important;
  color: rgba(113, 113, 122, 0.55) !important;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8rem;
  transition: background-color 150ms var(--ease-spring), transform 150ms var(--ease-spring);
}
.btn-add-round:hover, .btn-close-round:hover { background-color: rgba(113, 113, 122, 0.08) !important; }
.btn-add-round:active, .btn-close-round:active { transform: scale(0.94); }
.btn-close-round { font-size: 1rem; opacity: 1 !important; box-shadow: none !important; }
/* bx-x and bx-plus have no solid/bold cut in Boxicons (bxs-plus doesn't exist,
   only bxs-plus-circle/-square, which would add an unwanted second shape) --
   fake the thicker line trash gets for free from its bxs- (solid) swap via a
   text stroke instead. */
.btn-close-round i,
.btn-add-round .bx-plus {
  -webkit-text-stroke: 0.4px currentColor;
  font-size: 1.1rem;
}

/* Soft-deleted item row inside an Edit Quote modal -- marked via the formset's
   hidden DELETE checkbox, not actually removed until the form saves. */
.item-row-removed {
  opacity: 0.5;
  background-color: rgba(221, 64, 67, 0.08);
  border-radius: 8px;
  padding: 0.5rem;
}

.dbm-greeting {
  font-family: 'DM Serif Display', serif;
  font-weight: 700;
  font-size: 1.625rem;
  letter-spacing: -0.01em;
  color: var(--dbm-text);
  /* .navbar-nav-right (Sneat) has its own flex-grow and would otherwise squeeze this span
     below its natural width, wrapping "Hi Firstname Lastname" onto two lines. */
  white-space: nowrap;
  flex-shrink: 0;
}
.dbm-greeting-name {
  color: var(--dbm-muted);
  font-size: 1.75rem;
}

/* Cards */
.card-header { border-bottom: 1px solid var(--dbm-border) !important; background-color: transparent !important; }
.card-title { color: var(--dbm-text); }
.card-text { color: var(--dbm-muted); }

/* Inventory page section headers (Products/Services) -- breadcrumb's serif
   display font, scoped so it doesn't bleed into task_home.html's unrelated
   .card-title stat-tile labels. */
.js-inventory-section-title {
  font-family: 'DM Serif Display', serif;
  font-size: 1.25rem;
  color: var(--dbm-muted);
}
.js-inventory-section-subtitle {
  color: var(--dbm-muted);
}

/* Dashboard welcome card */
.dbm-welcome-title { font-size: 2rem; }

/* Tables */
.table { color: var(--dbm-text); }
.table > :not(caption) > * > * { background-color: transparent; color: inherit; border-bottom-color: var(--dbm-border) !important; box-shadow: none; }
.table thead th { color: var(--dbm-muted); border-bottom-color: var(--dbm-border) !important; font-weight: normal; }
.table tbody tr { transition: background-color 150ms var(--ease-spring); }
.table-hover > tbody > tr:hover > * { background-color: rgba(var(--brand-blue-rgb), 0.05) !important; }

/* Forms */
.form-control, .form-select {
  background-color: var(--dbm-surface-2) !important;
  border-color: var(--dbm-border) !important;
  color: var(--dbm-text) !important;
}
/* Same light grey as the breadcrumb/navbar-search placeholder (--dbm-muted) --
   the darker #566a7f label color read as too dark for empty-field text. */
.form-control::placeholder,
.form-control::-moz-placeholder { color: var(--dbm-muted); opacity: 1; }
/* Delete-confirm modal label: reads like the sentence above it (not the
   usual uppercase mono .form-label), just a touch smaller. */
.js-delete-confirm-label {
  font-family: 'Poppins', sans-serif;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: var(--dbm-muted);
  font-size: 0.8rem;
}
/* Delete-confirm modal body sentence -- lighter grey than normal body text,
   only the modal title stays dark. */
.js-delete-confirm-text {
  color: var(--dbm-muted);
}
/* Grey out the Delete button while disabled instead of Bootstrap's default
   dimmed-red (opacity: .65 on top of btn-danger still reads as "red"). */
.js-delete-confirm-submit:disabled {
  background-color: var(--gray-300);
  border-color: var(--gray-300);
  color: var(--gray-500);
  opacity: 1;
}
.form-control:disabled, .form-select:disabled { background-color: var(--dbm-surface) !important; }
/* In-modal grouping headers (e.g. "Add Items" on Add Quote, "Employee
   Information" on Add Employee) -- same serif font as the modal title
   (.dbm-breadcrumb) but smaller, so it reads as a subordinate heading
   rather than competing with it, plus a faint divider above to separate
   it from the field group before it. */
.dbm-modal-section-title {
  font-family: 'DM Serif Display', serif;
  font-size: 1.1rem;
  color: var(--dbm-text);
  border-top: 1px solid var(--dbm-border);
  padding-top: 1rem;
  margin-top: 1.5rem;
}
/* Profile page's view<->edit toggle -- a short crossfade instead of an
   instant display swap, using the same spring easing already established
   for every other transition in this file. */
.dbm-fade-out { opacity: 0; transition: opacity 150ms var(--ease-spring); }
.dbm-fade-in { animation: dbm-fade-in-kf 200ms var(--ease-spring) forwards; }
@keyframes dbm-fade-in-kf { from { opacity: 0; } to { opacity: 1; } }
/* <select> and empty date/datetime-local <input> have no real ::placeholder --
   a select's "Select Customer"/"Select Item" prompt is just its first option,
   and a date input's empty segments just render in the field's normal text
   color -- both inherit the forced dark color above. Grey them out via
   :invalid (empty/placeholder value + required) instead; picking a real
   value makes the field valid again and the color reverts automatically. */
.form-select:invalid,
.form-control:invalid { color: var(--dbm-muted) !important; }

/* Dropdowns */
.dropdown-menu {
  background-color: var(--dbm-surface) !important;
  border: 1px solid var(--dbm-border) !important;
  box-shadow: 0 4px 16px rgba(10, 10, 15, 0.08);
}
.dropdown-item { color: var(--dbm-muted) !important; }
.dropdown-item:hover, .dropdown-item:focus {
  background-color: rgba(var(--brand-blue-rgb), 0.08) !important;
  color: var(--dbm-text) !important;
}
.dropdown-divider { border-color: var(--dbm-border); }

/* User avatar dropdown: the name/role/company line runs long for some
   companies ("Owner · Chimfwembe Estate") and Bootstrap's default dropdown
   min-width was clipping it. Widen this one dropdown rather than every
   dropdown in the product, and give the role/company line a touch more
   room by trimming its size slightly. */
.dropdown-user .dropdown-menu {
  min-width: 16rem;
}
.dropdown-user .dropdown-item-text small {
  font-size: 0.8rem;
}

/* Same typeface as .dbm-breadcrumb, kept at each usage's own size and colour
   rather than the breadcrumb's larger, uncoloured version -- these sit in a
   dropdown menu item and the profile page's name headings, not a page
   heading. */
.dbm-serif-name {
  font-family: 'DM Serif Display', serif;
}

/* Profile page's own name/company headings sit next to a 100px avatar circle,
   where the h5 default reads too small -- the dropdown version above stays
   at its own size on purpose, this one is a page-level heading. */
.dbm-serif-name-lg {
  font-size: 1.75rem;
}

/* Sneat ships no built-in .bg-label-primary (unlike success/info/warning/
   danger/secondary, which already look right via core.css and are left
   untouched), so it needs an explicit light-tint definition here. */
.badge.bg-label-primary { background-color: rgba(var(--brand-blue-rgb), 0.12) !important; color: var(--brand-blue-hover) !important; }

/* Buttons: outline/secondary variant needs a light-surface-aware base too */
.btn-outline-secondary { color: var(--dbm-text) !important; border-color: var(--dbm-border) !important; }
.btn-outline-secondary:hover { background-color: var(--dbm-surface-2) !important; }

/* Country-code dropdown trigger: Bootstrap's own .btn-outline-secondary.dropdown-toggle.show
   rule (vendor core.css) bakes a literal dark grey fill for the "menu open" state --
   override just this button (not every outline-secondary dropdown app-wide) to stay light. */
.country-code-toggle.dropdown-toggle.show {
  background-color: var(--dbm-surface-2) !important;
  color: var(--dbm-text) !important;
  border-color: var(--dbm-border) !important;
}

/* Pagination: the app's one real circular-button pattern (list pages'
   prev/next/page-number controls), matching the ledger reference's round
   .navbtn -- transparent fill, thin grey border, ink text. */
.pagination.custom-pagination .page-link.rounded-circle {
  width: 28px !important;
  height: 28px !important;
  min-width: 28px !important;
  padding: 0 !important;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8rem;
  background-color: transparent !important;
  border: 2px solid rgba(113, 113, 122, 0.55) !important;
  color: rgba(113, 113, 122, 0.55) !important;
  transition: background-color 150ms var(--ease-spring);
}
.pagination.custom-pagination .page-link.rounded-circle:hover {
  background-color: rgba(113, 113, 122, 0.12) !important;
}
.pagination.custom-pagination .active > .page-link.rounded-circle {
  background-color: rgba(var(--brand-blue-rgb), 0.1) !important;
  border-color: transparent !important;
  box-shadow: none !important;
  color: var(--brand-blue) !important;
  font-weight: 700;
}

/* Navbar live-search box (base.html) -- drives the pre-existing but previously
   unused dynamicTableSearch() JS (same file) via #dynamicSearch. */
.dbm-navbar-search {
  gap: 0.5rem;
  padding: 0.375rem 0.75rem;
  max-width: 260px;
}
.dbm-navbar-search i {
  color: var(--dbm-muted);
  font-size: 1.1rem;
}
.dbm-navbar-search .form-control {
  padding: 0;
  /* The sitewide .form-control rule below (real form fields, e.g. login/add-item)
     forces a light-grey fill with !important -- this search box isn't one of
     those, so it needs the same weight to actually go transparent. */
  background-color: transparent !important;
  border: none !important;
}

/* .equal-height (dashboard KPI cards, task_home.html's summary cards) was meant to
   force same-row cards to match height regardless of content, but the stylesheet
   that actually defined it (assets/css/style.css) was never linked in any template
   -- it silently did nothing. Only stayed invisible because every card in a row
   happened to have the same number of content lines; removing a card's helper text
   line exposed it (that card's row column still stretched via Bootstrap's default
   flex align-items:stretch, but the card itself just sized to its own shorter
   content instead of filling that stretched column). Re-defined here since this
   file is the one actually loaded everywhere. */
.equal-height {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.equal-height > .card-body {
  flex-grow: 1;
}

/* Scrollbar, for the odd overflow panel */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--dbm-bg); }
::-webkit-scrollbar-thumb { background: var(--dbm-border); border-radius: 6px; }

/* Phone input's country-code dropdown button -- input-group-merge only strips
   the border for .input-group-text:first-child/:last-child, not a .btn, so the
   dropdown toggle needs the same seamless treatment added by hand to match the
   borderless look of the password show/hide field. */
.input-group-merge .country-code-toggle.dropdown-toggle {
  border-right: 0;
}
/* !important: core.css's compiled .input-group-merge .form-control:not(:first-child)
   rule (padding-left: 0) outranks this on specificity regardless of load order,
   which was zeroing the gap between the dropdown and the number field. */
.input-group-merge .phone-local-input {
  border-left: 0 !important;
  padding-left: 0.5rem !important;
}

/* Real flag icons for the phone input's country dropdown, drawn as inline SVG
   data-URIs rather than flag emoji -- Windows Chrome has no color flag-emoji
   glyphs and falls back to showing the bare ISO letters ("ZM", "GB") as text,
   so this renders identically on every OS. */
.flag-icon {
  display: inline-block;
  width: 18px;
  height: 13px;
  background-size: cover;
  background-position: center;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15) inset;
  vertical-align: middle;
}
.flag-icon-zm {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 15'%3E%3Crect width='20' height='15' fill='%23198A00'/%3E%3Crect x='13' width='2.33' height='9' fill='%23DE2010'/%3E%3Crect x='15.33' width='2.33' height='9' fill='%23000000'/%3E%3Crect x='17.66' width='2.34' height='9' fill='%23EF7D00'/%3E%3C/svg%3E");
}
.flag-icon-za {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 15'%3E%3Crect width='20' height='15' fill='%23FFFFFF'/%3E%3Cpolygon points='0,0 20,0 20,6.5 0,6.5' fill='%23DE3831'/%3E%3Cpolygon points='0,8.5 20,8.5 20,15 0,15' fill='%23002395'/%3E%3Cpolygon points='0,0 9,7.5 0,15' fill='%23000000'/%3E%3Cpolygon points='0,6 8,7.5 0,9' fill='%23FFB612'/%3E%3Cpolygon points='0,6.6 7,7.5 0,8.4' fill='%23007A4D'/%3E%3C/svg%3E");
}
.flag-icon-us {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 15'%3E%3Crect width='20' height='15' fill='%23FFFFFF'/%3E%3Crect y='0' width='20' height='1.15' fill='%23B22234'/%3E%3Crect y='2.3' width='20' height='1.15' fill='%23B22234'/%3E%3Crect y='4.6' width='20' height='1.15' fill='%23B22234'/%3E%3Crect y='6.9' width='20' height='1.15' fill='%23B22234'/%3E%3Crect y='9.2' width='20' height='1.15' fill='%23B22234'/%3E%3Crect y='11.5' width='20' height='1.15' fill='%23B22234'/%3E%3Crect y='13.8' width='20' height='1.15' fill='%23B22234'/%3E%3Crect width='9' height='8.05' fill='%233C3B6E'/%3E%3Ccircle cx='1.8' cy='1.6' r='0.35' fill='%23FFFFFF'/%3E%3Ccircle cx='4.5' cy='1.6' r='0.35' fill='%23FFFFFF'/%3E%3Ccircle cx='7.2' cy='1.6' r='0.35' fill='%23FFFFFF'/%3E%3Ccircle cx='3.1' cy='3.4' r='0.35' fill='%23FFFFFF'/%3E%3Ccircle cx='5.8' cy='3.4' r='0.35' fill='%23FFFFFF'/%3E%3Ccircle cx='1.8' cy='5.2' r='0.35' fill='%23FFFFFF'/%3E%3Ccircle cx='4.5' cy='5.2' r='0.35' fill='%23FFFFFF'/%3E%3Ccircle cx='7.2' cy='5.2' r='0.35' fill='%23FFFFFF'/%3E%3C/svg%3E");
}
.flag-icon-ca {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 15'%3E%3Crect width='20' height='15' fill='%23FF0000'/%3E%3Crect x='5' width='10' height='15' fill='%23FFFFFF'/%3E%3Cpath d='M10 3 L10.6 5 L12 4.3 L11.4 6 L13 6.4 L11.6 7.4 L12.4 9 L10.6 8.4 L10.6 10 L10 9 L9.4 10 L9.4 8.4 L7.6 9 L8.4 7.4 L7 6.4 L8.6 6 L8 4.3 L9.4 5 Z' fill='%23FF0000'/%3E%3C/svg%3E");
}
.flag-icon-gb {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 15'%3E%3Crect width='20' height='15' fill='%23012169'/%3E%3Cpolygon points='0,0 3,0 20,13 20,15 17,15 0,2' fill='%23FFFFFF'/%3E%3Cpolygon points='20,0 20,2 3,15 0,15 0,13 17,0' fill='%23FFFFFF'/%3E%3Cpolygon points='0,0 2,0 20,14 20,15 18,15 0,1' fill='%23C8102E'/%3E%3Cpolygon points='20,0 20,1 2,15 0,15 0,14 18,0' fill='%23C8102E'/%3E%3Crect x='8' width='4' height='15' fill='%23FFFFFF'/%3E%3Crect y='5.5' width='20' height='4' fill='%23FFFFFF'/%3E%3Crect x='8.7' width='2.6' height='15' fill='%23C8102E'/%3E%3Crect y='6.2' width='20' height='2.6' fill='%23C8102E'/%3E%3C/svg%3E");
}

::-webkit-scrollbar-thumb:hover { background: var(--dbm-muted); }

/* Onboarding steps share the auth pages' dark particle backdrop, but they have no
   .authentication-wrapper/.authentication-inner structure to inherit the z-index:1
   rule above -- their layout is a hand-rolled flex centre. Without this the fixed
   canvas (z-index:0) paints over the card. */
.onboarding-shell {
  position: relative;
  z-index: 1;
}
