:root {
  /* Same brand palette as mcray-roofing-site/css/styles.css -- keep these
     two files in sync if the brand colors ever change. */
  --maroon: #870412;
  --maroon-dark: #5C0210;
  --charcoal: #1E1517;
  --slate: #4A3C3E;
  --gray: #99A1AF;
  --gray-light: #f6f2f1;
  --off-white: #FAF9F7;
  --white: #ffffff;

  /* Copper/gold, pulled from the logo's roof-tile gradient (see
     mcray-roofing-site/css/styles.css --roof-1..4) -- the "luxurious"
     accent family. Used for borders/rules/CTAs, never for body text
     (gold-on-white body text fails contrast, so it stays an outline/
     accent color, not an ink color). */
  --gold: #C9932F;
  --gold-light: #E8C77C;
  --gold-dark: #8B6914;
  --gold-gradient: linear-gradient(135deg, #DA984F, #FBA86B);
  --gold-gradient-deep: linear-gradient(135deg, #8B4416, #DA984F);

  /* Dark UI Mode palette (Settings menu > Display) -- a dark, GRAY-leaning
     maroon rather than black, per Caleb's explicit ask. --dark-surface is
     the elevated-card tone (a step lighter than the page's own maroon-to-
     charcoal gradient, for depth); --dark-ink is a warm off-white rather
     than pure #fff, matching how --off-white already avoids pure white
     elsewhere in this palette. Only referenced inside the
     html[data-theme="dark"] override below -- never used directly. */
  --dark-surface: #3A262A;
  --dark-surface-subtle: #4A3236;
  --dark-ink: #F5EDEC;
  --dark-ink-muted: #C9AFB3;
  /* --maroon/--maroon-dark's own relative luminance is nearly IDENTICAL
     to --dark-surface's (confirmed by computing both: ~44.8/~30.5 vs
     ~44.4) -- maroon text/borders/links that read fine on a white card go
     almost invisible on the new dark card. --dark-warn is a lighter,
     more saturated red for ANY maroon-toned accent TEXT/border that sits
     on a surface that goes dark -- table/link text, danger buttons, warn
     stat tiles, aging-job tags -- never for maroon-as-BACKGROUND (the
     banner, .submit-btn, etc.), which stays exactly as-is regardless of
     theme since a fixed vivid background provides its own contrast. */
  --dark-warn: #E8918F;

  /* --surface/--ink are the semantic "current theme's card background /
     ink color" pair -- everything that should flip between a white card
     and a dark maroon-gray one in Dark Mode reads these two variables
     (never --white/--charcoal directly for that purpose). --white and
     --charcoal themselves are left completely alone and keep meaning
     literal, always-white / always-charcoal -- e.g. text sitting on a
     permanently-maroon banner or a permanently-gold button, which must
     NOT invert just because the page theme did. --warn-text is the same
     idea, covering every maroon/maroon-dark-as-TEXT-or-border spot that
     sits on something that goes dark (see --dark-warn above for why). */
  --surface: var(--white);
  --ink: var(--charcoal);
  --warn-text: var(--maroon-dark);

  /* Corner radius scale -- Caleb asked for "slightly sharper" corners
     app-wide (2026-07-30) for a crisper look than the original values
     (4/6/8/10/14px). Every box-like border-radius in this file should
     reference one of these instead of a hardcoded px value, so a future
     "a little sharper/softer still" ask is a one-line change here instead
     of hunting down ~40 call sites again. Pill shapes (999px) and circles
     (50%) are intentionally NOT part of this scale -- those are meant to
     stay fully round regardless of this "boxes" adjustment. */
  --radius-xs: 2px;   /* was 4px, then 3px -- small tags/inputs */
  --radius-sm: 3px;   /* was 6px, then 5px -- inputs, buttons, small controls */
  --radius-md: 4px;   /* was 8px, then 6px -- most cards/panels/dropdowns */
  --radius-lg: 5px;   /* was 10px, then 8px -- bigger cards, tables, avatars-square */
  --radius-xl: 7px;   /* was 14px, then 11px -- modals, login card */

  /* Shared easing + shadow scale for the visual-polish pass (2026-07-31)
     -- new rules below reach for these instead of inventing yet another
     one-off cubic-bezier/rgba string; existing declarations elsewhere in
     this file were left as literal values rather than mass-refactored,
     to keep this pass reviewable as additive polish, not a rewrite. */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --shadow-xs: 0 1px 2px rgba(30, 21, 23, 0.06);
  --shadow-sm: 0 2px 10px rgba(30, 21, 23, 0.08);
  --shadow-md: 0 6px 20px rgba(30, 21, 23, 0.12);
  --shadow-lg: 0 16px 40px rgba(30, 21, 23, 0.18);
  --focus-ring: 0 0 0 3px rgba(201, 147, 47, 0.28);
}

* {
  box-sizing: border-box;
}

/* Base heading scale -- every page previously relied on browser UA
   defaults (each h1/h2/h3 a different, inconsistent size/weight from
   page to page) with one-off inline `style="margin:..."` overrides for
   spacing only. This sets one consistent size/weight/line-height/color
   scale app-wide; the many existing inline margin overrides still win
   (inline beats a bare-element rule) so no page's spacing shifts, only
   the type itself now reads consistently. More specific existing rules
   (.card h2/h3, .login-wrap h1, .cal-title, etc.) still win their own
   piece as before -- this is only a shared foundation underneath them. */
h1, h2, h3, h4 {
  font-weight: 700;
  line-height: 1.25;
  color: var(--ink);
  margin: 0 0 0.75rem;
  letter-spacing: -0.01em;
}
h1 { font-size: 1.65rem; }
h2 { font-size: 1.35rem; }
h3 { font-size: 1.05rem; }
h4 {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--slate);
}

/* Smooth, deliberate transitions for anything that changes state via a
   class toggle elsewhere in this file (dropdown panels, modals, custom
   selects) -- keeps this one timing/easing pair consistent instead of
   each getting its own hand-picked duration. */
::selection {
  background: var(--gold-light);
  color: var(--charcoal);
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  /* Light backdrop with just a whisper of gold for the main app. An
     app-wide dark maroon/charcoal version of this was tried and walked
     back as too heavy -- that look is kept ONLY for the login/reset
     pages now, via .login-page below. Every white "surface" component
     (.card, .stat-tile, table.data-table, etc.) explicitly pins its own
     text to --charcoal rather than relying on inheritance, so it stays
     correct regardless of which background is active. */
  /* The gradient sits on top; a very faint tiled watermark of the logo's
     own roof-triangle motif runs underneath for texture -- a branded
     geometric pattern rather than generic shapes. Opacity is baked into
     the SVG stroke itself (0.05/0.06) since background-image has no
     separate opacity control. */
  background-image:
    radial-gradient(circle at center, var(--off-white) 0%, var(--off-white) 60%, #F9F1DE 100%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='140' viewBox='0 0 160 140'%3E%3Cpath d='M80 14 L138 122 L22 122 Z' fill='none' stroke='%23C9932F' stroke-width='1.5' opacity='0.06'/%3E%3Cpath d='M40 90 L60 128 L20 128 Z' fill='none' stroke='%23870412' stroke-width='1.5' opacity='0.05'/%3E%3C/svg%3E");
  background-repeat: no-repeat, repeat;
  background-attachment: fixed, fixed;
  color: var(--ink);
  min-height: 100vh;
}

/* Login/forgot-password/reset-password pages only -- the dark maroon-to-
   charcoal look Caleb specifically wants kept for the sign-in moment,
   distinct from the rest of the app's light theme. */
body.login-page {
  background: radial-gradient(circle at top, var(--maroon-dark) 0%, var(--charcoal) 65%) fixed;
  color: var(--off-white);
}

.top-banner {
  background: linear-gradient(135deg, var(--maroon), var(--maroon-dark));
  color: var(--white);
  padding: 0.75rem 1.5rem;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  border-bottom: 3px solid var(--gold);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);
}

.top-banner .brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--white);
}

.brand-logo-badge {
  background: var(--white);
  border-radius: var(--radius-md);
  padding: 0.3rem 0.6rem;
  display: flex;
  align-items: center;
  line-height: 0;
  border: 1.5px solid var(--gold);
}

.brand-logo-img {
  height: 24px;
  display: block;
}

.brand-suffix {
  font-weight: 700;
  font-size: 1.1rem;
  letter-spacing: 0.02em;
}

.top-nav {
  display: flex;
  align-items: center;
  gap: 1.25rem;
}

.top-nav a {
  position: relative;
  color: var(--white);
  text-decoration: none;
  font-weight: 600;
  line-height: 1;
  opacity: 0.75;
  transition: opacity 0.15s ease;
}

/* Underline is an absolutely-positioned pseudo-element, not layout
   padding/border -- that way it doesn't add reserved space below the
   text that would shift the link's own box (and so its flex-centered
   position) out of line with the logo next to it. */
.top-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.4rem;
  height: 2px;
  background: transparent;
  transition: background 0.15s ease;
}

.top-nav a:hover {
  opacity: 1;
}

.top-nav a.active {
  opacity: 1;
}

.top-nav a.active::after {
  background: var(--gold);
}

.banner-right {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-left: auto;
}

/* Shared dropdown pattern for the create menu / bell / avatar --
   JobNimbus-inspired: a trigger button in the banner, a floating panel
   below it, toggled via static/js/banner-menus.js. */
.dropdown-wrap {
  position: relative;
}

.dropdown-panel {
  display: none;
  position: absolute;
  top: calc(100% + 0.6rem);
  right: 0;
  min-width: 220px;
  background: var(--surface);
  border: 1.5px solid var(--gold);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  z-index: 200;
  transform-origin: top right;
}

.dropdown-panel.visible {
  display: block;
  animation: dropdown-in 0.16s var(--ease);
}

@keyframes dropdown-in {
  from { opacity: 0; transform: scale(0.96) translateY(-4px); }
  to { opacity: 1; transform: scale(1) translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .dropdown-panel.visible { animation: none; }
}

.dropdown-panel-header {
  padding: 0.75rem 1rem;
  background: var(--gray-light);
  color: var(--ink);
  font-weight: 700;
  font-size: 0.9rem;
}

.dropdown-panel a,
.dropdown-panel button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.65rem 1rem;
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
  background: none;
  border: none;
  border-top: 1px solid var(--gray-light);
  cursor: pointer;
}

.dropdown-panel a:hover,
.dropdown-panel button:hover {
  background: var(--gray-light);
}

/* Settings menu > Display (UI Size / Full-Width Layout) -- these live in
   a non-navigating section of the dropdown, so their buttons need to
   override the generic ".dropdown-panel a, .dropdown-panel button" rule
   above (full-width block rows with a top border) rather than inherit it. */
.settings-section {
  padding: 0.65rem 1rem;
  border-top: 1px solid var(--gray-light);
}

.settings-section-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--slate);
  margin-bottom: 0.4rem;
}

.segmented-control {
  display: flex;
  border: 1px solid var(--gray);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.segmented-control .segmented-option {
  flex: 1;
  width: auto;
  border: none;
  border-left: 1px solid var(--gray);
  background: var(--surface);
  color: var(--slate);
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.4rem 0.3rem;
  cursor: pointer;
}

.segmented-control .segmented-option:first-child {
  border-left: none;
}

.segmented-control .segmented-option:hover {
  background: var(--gray-light);
}

.segmented-control .segmented-option.active {
  background: var(--gold-gradient);
  color: var(--charcoal);
}

/* "Content Width" slider (Settings menu > Display) -- native
   <input type="range">, restyled to match the app's gold accent family
   rather than the browser default. Thumb styling needs separate
   -webkit-/-moz- prefixed rules (no shared shorthand exists across
   engines for range-input parts). */
.settings-slider-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.4rem;
}

.settings-slider-value {
  color: var(--slate);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.settings-slider {
  width: 100%;
  height: 4px;
  margin: 0;
  border-radius: 999px;
  background: var(--gray-light);
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
}

.settings-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--gold-gradient);
  border: 1.5px solid var(--gold-dark);
  cursor: pointer;
}

.settings-slider::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--gold-gradient);
  border: 1.5px solid var(--gold-dark);
  cursor: pointer;
}

.settings-slider-labels {
  display: flex;
  justify-content: space-between;
  font-size: 0.7rem;
  color: var(--gray);
  margin-top: 0.2rem;
}

.create-menu-trigger {
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1;
  padding: 0.4rem 0.9rem !important;
}

/* .top-banner prefix on these two -- without it, the generic
   ".top-banner button, .btn" rule further down (element+class = higher
   specificity than a single class) was winning and repainting these as
   white boxes with 6px corners, which is exactly what made the bell
   invisible and turned the avatar into "a square with a circle in it". */
.top-banner .icon-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.1);
  color: var(--white);
  cursor: pointer;
  transition: background 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
}

.top-banner .icon-btn:hover {
  background: rgba(255, 255, 255, 0.2);
  border-color: rgba(255, 255, 255, 0.6);
  transform: translateY(-1px);
}

.top-banner .icon-btn:active {
  transform: translateY(0);
}

.top-banner .icon-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.35);
}

.icon-btn svg {
  width: 18px;
  height: 18px;
}

.notif-panel {
  min-width: 320px;
  max-height: 70vh;
  display: none;
  flex-direction: column;
}

.notif-panel.visible {
  display: flex;
}

.notif-panel-body {
  overflow-y: auto;
}

.notif-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 1rem;
  border-top: 1px solid var(--gray-light);
  border-bottom: none;
  text-decoration: none;
  color: var(--ink);
  font-weight: 600;
  font-size: 0.85rem;
}

.notif-row:hover {
  background: var(--gray-light);
}

.top-banner .avatar-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  border-radius: 50%;
  transition: transform 0.15s ease;
}

.top-banner .avatar-btn:hover {
  transform: translateY(-1px);
}

.top-banner .avatar-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.35);
  border-radius: 50%;
}

.avatar-circle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--gold-gradient-deep);
  color: var(--white);
  font-weight: 700;
  font-size: 0.85rem;
  border: 1.5px solid var(--white);
  overflow: hidden;
}

.avatar-circle img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.avatar-circle-lg {
  width: 72px;
  height: 72px;
  font-size: 1.5rem;
  border-color: var(--gold);
  flex-shrink: 0;
}

.account-avatar-row {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  margin-bottom: 1rem;
}

.profile-panel {
  min-width: 240px;
}

/* Groups the "+" create menu tight against the search box, matching
   JobNimbus's layout (the two sit adjacent, not spread across the
   banner) -- a smaller gap than the banner's general 1.5rem. */
.search-and-create {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Banner trigger -- a button styled like a search box (JobNimbus's
   pattern: click it to open a real search modal, it's not an inline
   input itself). */
.global-search-trigger {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 0 1 220px;
  min-width: 140px;
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--gold);
  border-radius: 999px;
  background: var(--surface);
  color: var(--gray);
  font-size: 0.85rem;
  cursor: pointer;
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

.global-search-trigger:hover {
  border-color: var(--gold-dark);
  box-shadow: 0 2px 8px rgba(201, 147, 47, 0.3);
}

.global-search-trigger .search-icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.global-search-trigger span:first-of-type {
  flex: 1;
  text-align: left;
}

.search-kbd {
  font-size: 0.7rem;
  color: var(--gray);
  border: 1px solid var(--gray-light);
  border-radius: var(--radius-xs);
  padding: 0.05rem 0.35rem;
  flex-shrink: 0;
}

/* The modal itself -- a real "command palette" style search box, not a
   dropdown, so there's room for multi-line result previews. */
.search-modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(30, 21, 23, 0.55);
  z-index: 1000;
  padding-top: 10vh;
}

.search-modal-overlay.visible {
  display: block;
  animation: overlay-in 0.15s ease;
}

.search-modal {
  max-width: 640px;
  margin: 0 auto;
  background: var(--surface);
  border: 1.5px solid var(--gold);
  border-radius: var(--radius-xl);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
  overflow: hidden;
  max-height: 75vh;
  display: flex;
  flex-direction: column;
  animation: modal-in 0.18s var(--ease);
}

@keyframes overlay-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes modal-in {
  from { opacity: 0; transform: translateY(-10px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .search-modal-overlay.visible,
  .search-modal {
    animation: none;
  }
}

.search-modal-input-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--gray-light);
  flex-shrink: 0;
}

.search-modal-input-row .search-icon {
  width: 20px;
  height: 20px;
  color: var(--gray);
  flex-shrink: 0;
}

.search-modal-input-row input {
  flex: 1;
  border: none;
  font-size: 1.1rem;
  padding: 0.25rem 0;
  margin-bottom: 0;
  color: var(--ink);
}

.search-modal-input-row input:focus {
  outline: none;
}

.search-modal-close {
  background: none;
  border: none;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--gray);
  cursor: pointer;
  padding: 0 0.25rem;
}

.search-modal-close:hover {
  color: var(--warn-text);
}

.modal-search-results {
  overflow-y: auto;
  padding: 0.5rem 0;
}

.search-group-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--slate);
  background: var(--gray-light);
  padding: 0.5rem 1.25rem;
}

.search-result-card {
  display: block;
  padding: 0.75rem 1.25rem;
  text-decoration: none;
  color: var(--ink);
  border-bottom: 1px solid var(--gray-light);
}

.search-result-card:hover {
  background: var(--gray-light);
}

.search-result-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.search-result-label {
  font-weight: 700;
  font-size: 0.95rem;
}

.search-result-detail {
  font-size: 0.8rem;
  color: var(--slate);
  margin-top: 0.2rem;
}

.search-empty {
  padding: 1.5rem 1.25rem;
  color: var(--slate);
  font-size: 0.9rem;
  text-align: center;
}

/* Native replacement for the browser's own confirm() dialog -- same dark
   overlay + gold-bordered surface as .search-modal-overlay/.search-modal
   above, just a small centered message box instead of a search box. Any
   form opts in with data-confirm="..."; see confirm-modal.js. */
.confirm-modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(30, 21, 23, 0.55);
  z-index: 1100;
  align-items: center;
  justify-content: center;
}

.confirm-modal-overlay.visible {
  display: flex;
  animation: overlay-in 0.15s ease;
}

.confirm-modal {
  max-width: 380px;
  margin: 1rem;
  background: var(--surface);
  border: 1.5px solid var(--gold);
  border-radius: var(--radius-xl);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
  padding: 1.5rem;
  animation: modal-in 0.18s var(--ease);
}

.confirm-modal-message {
  margin: 0 0 1.25rem;
  color: var(--ink);
  font-size: 1rem;
}

.confirm-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
}

@media (prefers-reduced-motion: reduce) {
  .confirm-modal-overlay.visible,
  .confirm-modal {
    animation: none;
  }
}

/* Picker-modal fields on the job form (Contact/Board/Stage/Sales Rep) --
   same command-palette modal as the banner's global search
   (.search-modal-overlay/.search-modal/.search-result-card reused as-is),
   just triggered from inside a normal vertical form instead of the
   banner, so the trigger button needs to span the full field width
   rather than the banner's fixed ~220px. */
.field-picker-trigger {
  width: 100%;
  flex: none;
  margin-bottom: 1rem;
}

/* .search-result-card was written for <a> result links; reused here on
   <button> elements for picker rows, which need their own reset since
   buttons don't inherit link styling. */
button.search-result-card {
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-bottom: 1px solid var(--gray-light);
  font: inherit;
  cursor: pointer;
}

.contact-picker-create-row .search-result-label {
  color: var(--gold-dark);
}

.contact-picker-create-panel {
  padding-top: 0.5rem;
}

/* Estimate template picker rows are individual <form>s (each posts its
   own template_id and submits immediately on click) rather than a single
   shared hidden input like the job-form pickers -- the form itself needs
   to behave like a block-level list row with no default margin. */
.template-picker-row {
  display: block;
  margin: 0;
}

.quick-action {
  background: var(--gold-gradient) !important;
  color: var(--charcoal) !important;
  font-weight: 700;
  border: 1px solid var(--gold-dark) !important;
  box-shadow: 0 2px 8px rgba(201, 147, 47, 0.45);
}

.quick-action:hover {
  background: var(--gold-gradient-deep) !important;
  color: var(--white) !important;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(201, 147, 47, 0.55);
}

.quick-action:active {
  transform: translateY(0);
  box-shadow: 0 2px 6px rgba(201, 147, 47, 0.45);
}

.quick-action:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring), 0 2px 8px rgba(201, 147, 47, 0.45);
}

.top-banner form {
  margin: 0;
}

.top-banner button,
.btn {
  background: var(--white);
  color: var(--maroon);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 0.5rem 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

/* Hardcoded, not var(--gray-light) -- .btn's base state is deliberately
   literal white/maroon regardless of theme (a self-contained light
   accent chip, reads fine on a dark page same as a gold-gradient
   button would), so its hover needs to stay a literal near-white too;
   var(--gray-light) now flips dark in Dark Mode and would otherwise
   make this hover state go darker than the button's own resting state. */
.top-banner button:hover,
.btn:hover {
  background: #f6f2f1;
  border-color: var(--gold);
}

.top-banner button:active,
.btn:active {
  transform: translateY(1px);
}

.top-banner button:focus-visible,
.btn:focus-visible {
  outline: none;
  border-color: var(--gold);
  box-shadow: var(--focus-ring);
}

.btn:disabled,
.btn.disabled {
  opacity: 0.55;
  cursor: default;
  transform: none;
  box-shadow: none;
}

/* "Content Width" preference (Settings menu > Display) -- a slider, not
   an on/off toggle, so Caleb can land on a middle ground between the
   original 900px reading-width cap and true edge-to-edge instead of only
   having those two extremes. --wrap-max-width is set on <html> (as a
   real px value, or the literal keyword "none" at the slider's max
   notch) by static/js/ui-prefs.js / the early inline <head> script in
   base.html; the 900px here is just the fallback for a user who's never
   touched the slider. */
.wrap {
  max-width: var(--wrap-max-width, 900px);
  margin: 0 auto;
  padding: 2rem 1.5rem;
}

/* The kanban board always forces full-width unconditionally (needs the
   room for 14+ stage columns) regardless of the Content Width slider --
   .wrap.wrap-full's two-class specificity still wins over plain .wrap
   above either way, so this doesn't need to reference the CSS variable
   at all. */
.wrap.wrap-full {
  max-width: none;
  padding-bottom: 0.5rem;
}

/* "UI Size" preference (Settings menu > Display) -- applied via `zoom`
   on <html>, not a font-size trick, so it scales EVERYTHING uniformly
   (px-based icon buttons/borders/avatar circles included), not just
   rem-based type/spacing. zoom is used deliberately instead of
   transform:scale: transform creates a new containing block, which
   would break the two position:fixed elements on this page (the global
   search modal overlay, the kanban drag-and-drop toast) -- zoom doesn't
   have that problem and behaves like real browser zoom (Cmd/Ctrl +/-),
   just persisted as a setting instead of a per-tab browser state. */
html[data-ui-density="compact"] {
  zoom: 0.85;
}

html[data-ui-density="comfortable"] {
  zoom: 1.15;
}

/* Dark UI Mode (Settings menu > Display) -- a dark, GRAY-leaning maroon
   theme, not black, per Caleb's explicit ask ("dark maroon, almost a
   dark gray maroon, with white text"). Redefines --surface/--ink (see
   :root) plus --gray-light/--gray/--slate/--off-white directly, which is
   what makes the ~30 rules already swapped above to --surface/--ink (and
   the many more already written against --gray-light/--gray/--slate)
   repaint correctly with zero further changes -- this is the ONLY place
   in the stylesheet those four variables get redefined.
   Scoped to `body:not(.login-page)` specifically so the sign-in page's
   own already-dark, already-locked-in maroon/charcoal look (confirmed
   earlier this session, see body.login-page above) is completely
   unaffected either way -- its .login-wrap card and shared label/input
   styles keep using the light-mode --ink/--surface values regardless of
   this toggle, since body.login-page never matches this selector. */
html[data-theme="dark"] body:not(.login-page) {
  --surface: var(--dark-surface);
  --ink: var(--dark-ink);
  --gray-light: var(--dark-surface-subtle);
  --gray: var(--dark-ink-muted);
  --slate: var(--dark-ink-muted);
  --off-white: var(--dark-surface-subtle);
  --warn-text: var(--dark-warn);
  background-image: radial-gradient(circle at top, var(--maroon-dark) 0%, var(--charcoal) 70%);
  color: var(--ink);
}

/* .flash.error's light pink is hardcoded (not on the --surface/--ink
   system, since it's a semantic error color, not a neutral surface) --
   needs its own explicit dark variant so it doesn't sit as a jarring
   bright-pink box on an otherwise dark page. */
html[data-theme="dark"] body:not(.login-page) .flash.error {
  background: #4A1F1F;
  color: #FFC2C2;
  border-color: var(--maroon);
}

.card {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--gold);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  margin-bottom: 1rem;
  box-shadow: 0 2px 10px rgba(30, 21, 23, 0.08);
}

.card h2,
.card h3 {
  padding-bottom: 0.4rem;
  border-bottom: 2px solid var(--gold-light);
  display: inline-block;
}

.flash {
  padding: 0.75rem 1rem;
  border-radius: var(--radius-sm);
  margin-bottom: 1rem;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--gold);
}

.flash.error {
  background: #fde8e8;
  color: var(--maroon-dark);
  border: 1px solid var(--maroon);
}

label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.25rem;
  font-size: 0.9rem;
  color: var(--ink);
}

input[type="email"],
input[type="password"],
input[type="text"],
input[type="datetime-local"],
select,
textarea {
  width: 100%;
  padding: 0.6rem;
  border: 1px solid var(--gray);
  border-radius: var(--radius-sm);
  margin-bottom: 1rem;
  font-size: 1rem;
  background: var(--surface);
  color: var(--ink);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* These previously had no focus treatment at all -- tabbing/clicking into
   a field fell back to each browser's own default outline (a blue ring
   that clashes with the gold accent family used everywhere else a focus
   state IS defined, e.g. .native-select-trigger, .native-select-search).
   Matches those two exactly: gold border + the same soft gold ring. */
input[type="email"]:focus,
input[type="password"]:focus,
input[type="text"]:focus,
input[type="datetime-local"]:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: var(--focus-ring);
}

input[readonly] {
  background: var(--off-white);
  color: var(--gray);
  cursor: default;
}

input[readonly]:focus {
  border-color: var(--gray);
  box-shadow: none;
}

.field-hint {
  margin-top: -0.75rem;
  margin-bottom: 1rem;
  font-size: 0.8rem;
  color: var(--gray);
}

.field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0 1rem;
}
.field-grid input {
  margin-bottom: 0.75rem;
}

/* Custom dropdown -- site-wide replacement for a plain <select>. A real
   <select>'s OPEN option list is always rendered by the OS (no way to
   restyle it with CSS alone, in any browser) -- this swaps it for a
   hidden input + trigger button + our own absolutely-positioned panel,
   built with the app's own gold/luxury look instead. Markup/JS pattern:
   static/js/native-select.js's wireCustomSelect(wrapId), used on every
   .native-select on the page. Default look matches every other plain
   input/select in the app (bordered, var(--surface) background,
   margin-bottom) so it drops into a normal field group unchanged; the
   table.measurement-table override below strips that back down to the
   borderless "type directly in the cell" look that section uses. */
.native-select {
  position: relative;
  margin-bottom: 1rem;
}
.native-select-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  width: 100%;
  padding: 0.6rem;
  border: 1px solid var(--gray);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font: inherit;
  font-size: 1rem;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.native-select-trigger:hover {
  border-color: var(--gold);
}
.native-select-trigger:focus {
  outline: none;
}
.native-select.open .native-select-trigger {
  border-color: var(--gold);
  box-shadow: 0 0 0 2px rgba(199, 154, 78, 0.25);
}
.native-select-arrow {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: var(--gray);
  transition: transform 0.15s ease;
}
.native-select.open .native-select-arrow {
  transform: rotate(180deg);
}
.native-select-panel {
  display: none;
  position: absolute;
  top: calc(100% + 0.4rem);
  left: 0;
  right: 0;
  background: var(--surface);
  border: 1.5px solid var(--gold);
  border-radius: var(--radius-md);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
  overflow: hidden;
  overflow-y: auto;
  max-height: 280px;
  z-index: 50;
  transform-origin: top center;
}
.native-select.open .native-select-panel {
  display: block;
  animation: dropdown-in 0.14s var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  .native-select.open .native-select-panel { animation: none; }
}
.native-select-option {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.65rem 1rem;
  border: none;
  border-top: 1px solid var(--gray-light);
  background: none;
  font: inherit;
  color: var(--ink);
  cursor: pointer;
}
.native-select-option:first-child {
  border-top: none;
}
.native-select-option:hover,
.native-select-option.selected {
  background: var(--gray-light);
}
.native-select-search {
  display: block;
  width: 100%;
  padding: 0.65rem 1rem;
  border: none;
  border-bottom: 1.5px solid var(--gold-light);
  border-radius: 0;
  margin: 0;
  background: var(--surface);
  font: inherit;
  color: var(--ink);
  position: sticky;
  top: 0;
  z-index: 1;
}
.native-select-search:focus {
  outline: none;
  border-bottom-color: var(--gold);
}
.native-select-search + .native-select-option {
  border-top: none;
}
.native-select-empty {
  padding: 0.65rem 1rem;
  color: var(--gray);
  font-size: 0.9rem;
}

/* "Button-styled" native-select variant -- used where a dropdown sits
   inline in a row of .btn's (e.g. the board filter row) and should read
   as one of them rather than a normal bordered form field. Mirrors .btn
   exactly (white, transparent border, --radius-sm, same padding/weight/
   hover), same recipe the measurement-table override uses elsewhere:
   .native-select's own defaults are for a normal field group, and this
   context-specific wrapper class restyles the trigger down to match. */
.native-select-btn .native-select {
  margin-bottom: 0;
}
.native-select-btn .native-select-trigger {
  background: var(--white);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 0.5rem 1rem;
  font-weight: 600;
  color: var(--maroon);
}
.native-select-btn .native-select-trigger:hover {
  background: #f6f2f1;
}
.native-select-btn .native-select.open .native-select-trigger {
  border-color: var(--gold);
  box-shadow: 0 0 0 2px rgba(199, 154, 78, 0.25);
}

.board-filter-form {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Board search -- matches JobNimbus's own pattern (screenshots supplied
   2026-07-30): a small icon-only button until clicked, which swaps in
   place for a real search box (search icon + input + a clear "x") rather
   than opening a whole modal like the banner's global search does. A
   lighter, page-scoped interaction on purpose -- this is filtering one
   board's own jobs, not a site-wide command palette. */
.board-search {
  position: relative;
  display: flex;
  align-items: center;
}

.board-search-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 1px solid var(--gray);
  border-radius: 50%;
  background: var(--white);
  color: var(--slate);
  cursor: pointer;
}

.board-search-toggle:hover {
  background: #f6f2f1;
  border-color: var(--gold);
}

.board-search-toggle svg {
  width: 18px;
  height: 18px;
}

.board-search.expanded .board-search-toggle {
  display: none;
}

/* .board-search form.board-search-form (two classes + element, 0/2/1) --
   a single-class or single-class+element selector here isn't safely
   stronger than .toolbar form (0/1/1) since that rule sits LATER in this
   file and wins any specificity tie by source order. Two ancestor
   classes wins on specificity alone regardless of where either rule
   sits, which is what actually matters: without this, .toolbar form's
   display:flex silently overrides this display:none and the search box
   shows immediately instead of staying hidden until the button is
   clicked -- confirmed as a real bug, not a one-off. */
.board-search form.board-search-form {
  display: none;
  align-items: center;
  gap: 0.5rem;
  width: 220px;
  padding: 0.45rem 0.75rem;
  border: 1px solid var(--gold);
  border-radius: var(--radius-sm);
  background: var(--white);
  margin: 0;
}

.board-search.expanded form.board-search-form {
  display: flex;
}

.board-search-form svg {
  width: 16px;
  height: 16px;
  color: var(--gray);
  flex-shrink: 0;
}

.board-search-form input[type="text"] {
  flex: 1;
  min-width: 0;
  border: none;
  margin: 0;
  padding: 0;
  background: none;
  font-size: 0.9rem;
}

.board-search-form input[type="text"]:focus {
  outline: none;
}

.board-search-clear {
  flex-shrink: 0;
  color: var(--gray);
  font-size: 1.2rem;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
}

.board-search-clear:hover {
  color: var(--maroon);
}

/* Uniform sizing + a shared grey outline across every control in the
   board page's top-right action row (search, sales rep filter, Board/
   Table toggle, Export CSV, + Add Job) -- Caleb wanted them all to read
   as one cohesive row instead of a mix of button/dropdown/segmented-
   control sizes and border treatments. Scoped to .board-toolbar-actions
   (only used on this one page) rather than touching .btn/.segmented-
   control globally, since both of those are shared with other pages
   (Contacts list, the Settings dropdown's UI Size/Theme toggles) that
   should NOT pick up this sizing. 32px matches the segmented control's
   own natural compact height -- everything else is brought down/up to
   match it, not the other way around. */
.board-toolbar-actions .board-search-toggle {
  width: 32px;
  height: 32px;
  border-color: rgba(153, 161, 175, 0.4);
}

.board-toolbar-actions .native-select-btn .native-select-trigger {
  height: 32px;
  box-sizing: border-box;
  border: 1px solid rgba(153, 161, 175, 0.4);
}

.board-toolbar-actions #boardViewToggle {
  height: 32px;
  box-sizing: border-box;
  border-color: rgba(153, 161, 175, 0.4);
  transition: border-color 0.15s ease;
}

.board-toolbar-actions #boardViewToggle:hover {
  border-color: var(--gold);
}

.board-toolbar-actions #boardViewToggle .segmented-option {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

.board-toolbar-actions .btn {
  display: inline-flex;
  align-items: center;
  height: 32px;
  box-sizing: border-box;
  padding: 0 1rem;
  border: 1px solid rgba(153, 161, 175, 0.4);
}

/* Spreadsheet-style input table (Roof Measurements) -- two label/input
   pairs per row so it reads like filling in a real table, not a wrapping
   grid of stacked label-above-input blocks. Reuses table.data-table's
   border/radius/shadow so it matches every other table in the app. */
table.measurement-table {
  table-layout: fixed;
}
table.measurement-table th {
  width: 22%;
  background: var(--gray-light);
  text-transform: none;
  letter-spacing: normal;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink);
}
table.measurement-table th label {
  margin: 0;
  cursor: pointer;
}
table.measurement-table td {
  width: 28%;
  padding: 0;
}
table.measurement-table td input {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0.75rem 1rem;
  border: none;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  font: inherit;
  color: inherit;
}
table.measurement-table td input:focus {
  outline: none;
  background: var(--gray-light);
  box-shadow: inset 0 0 0 2px var(--gold);
}
table.measurement-table td .native-select {
  height: 100%;
  margin-bottom: 0;
}
table.measurement-table td .native-select-trigger {
  height: 100%;
  padding: 0.75rem 1rem;
  border: none;
  border-radius: 0;
  background: transparent;
}
table.measurement-table td .native-select.open .native-select-trigger {
  background: var(--gray-light);
  box-shadow: inset 0 0 0 2px var(--gold);
}
table.measurement-table tr:hover td {
  background: var(--surface);
}
table.measurement-table tr:hover td:has(input:focus, .native-select.open) {
  background: var(--gray-light);
}
@media (max-width: 640px) {
  table.measurement-table,
  table.measurement-table tbody,
  table.measurement-table tr,
  table.measurement-table th,
  table.measurement-table td {
    display: block;
    width: 100%;
  }
  table.measurement-table th {
    border-bottom: none;
    padding-bottom: 0.25rem;
  }
  table.measurement-table td {
    padding-top: 0;
  }
}

.catalog-suggestions {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  background: var(--surface);
  border: 1px solid var(--gold);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
  max-height: 280px;
  overflow-y: auto;
  margin-top: -0.75rem;
}
.catalog-suggestion-row {
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  border-bottom: 1px solid var(--gray-light);
}
.catalog-suggestion-row:last-child {
  border-bottom: none;
}
.catalog-suggestion-row:hover {
  background: var(--off-white);
}
.catalog-suggestion-name {
  display: block;
  font-weight: 600;
  color: var(--ink);
}
.catalog-suggestion-detail {
  display: block;
  font-size: 0.8rem;
  color: var(--gray);
}

.login-wrap {
  max-width: 360px;
  margin: 4rem auto;
  padding: 3rem 2rem;
  background: var(--white);
  border: 1.5px solid var(--gold);
  border-radius: var(--radius-xl);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35), 0 0 0 1px rgba(201, 147, 47, 0.15);
}

.login-logo {
  display: block;
  height: 56px;
  margin: 0 auto 1rem;
}

.login-wrap h1 {
  color: var(--maroon);
  font-size: 1.5rem;
  margin-bottom: 1.5rem;
  text-align: center;
}

.submit-btn {
  width: 100%;
  background: var(--maroon);
  color: var(--white);
  border: 1px solid var(--gold);
  border-radius: var(--radius-sm);
  padding: 0.75rem;
  font-weight: 600;
  font-size: 1rem;
  cursor: pointer;
  transition: background 0.15s ease, box-shadow 0.15s ease;
}

.submit-btn:hover {
  background: var(--maroon-dark);
  box-shadow: 0 2px 10px rgba(201, 147, 47, 0.35);
}

.submit-btn:active {
  transform: translateY(1px);
}

.submit-btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring), 0 2px 10px rgba(201, 147, 47, 0.35);
}

.login-forgot-link {
  text-align: center;
  margin-top: 1rem;
}

.login-forgot-link a {
  color: var(--slate);
  font-size: 0.85rem;
}

.login-reset-prompt {
  margin-top: 1.5rem;
  padding: 1rem;
  background: var(--gray-light);
  border-radius: var(--radius-md);
  text-align: center;
}

.login-reset-prompt p {
  margin: 0 0 0.75rem;
  color: var(--maroon-dark);
  font-weight: 600;
  font-size: 0.9rem;
}

.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

.toolbar form {
  display: flex;
  gap: 0.5rem;
  margin: 0;
}

.toolbar-actions {
  display: flex;
  gap: 0.75rem;
  align-items: center;
}

.toolbar input[type="text"] {
  margin-bottom: 0;
  min-width: 220px;
}

table.data-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  color: var(--ink);
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--gold-light);
  box-shadow: 0 2px 10px rgba(30, 21, 23, 0.06);
}

table.data-table th,
table.data-table td {
  text-align: left;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--gray-light);
  transition: background-color 0.12s ease;
}

table.data-table th {
  background: var(--gray-light);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--slate);
}

table.data-table tr:hover td {
  background: var(--gray-light);
}

table.data-table a {
  color: var(--warn-text);
  font-weight: 600;
  text-decoration: none;
}

table.data-table a:hover {
  text-decoration: underline;
}

/* Previously just centered gray text floating on the page background --
   read as "something failed to load" as much as "there's nothing here
   yet". A dashed card treatment plus a small glyph reads as deliberate
   instead. Works as-is whether the markup is a <p>, <div>, or a <td>
   spanning a table row (the board Table view's "no jobs yet" row) --
   the border/background box just nests inside the cell's own padding. */
.empty-state {
  color: var(--slate);
  padding: 2.25rem 1.5rem;
  text-align: center;
  border: 1.5px dashed var(--gray-light);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--gold) 3%, var(--surface));
  font-size: 0.92rem;
}

.empty-state::before {
  content: "";
  display: block;
  width: 34px;
  height: 34px;
  margin: 0 auto 0.6rem;
  border-radius: 50%;
  background: var(--gray-light);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23C9932F' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 10h18v9a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-9Z'/%3E%3Cpath d='M3 10l2.5-6h13L21 10'/%3E%3Cpath d='M9 14h6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 16px 16px;
}

.empty-state a {
  color: var(--gold-dark);
  font-weight: 600;
}

/* A .empty-state sitting inside a table cell (colspan'd "no rows" row) or
   a tight .card already has its own outer border/padding doing that job
   -- the dashed box only needs to read as its own element when it's
   floating loose on the page/card background. */
table.data-table .empty-state {
  border: none;
  background: none;
  padding: 1.75rem 0;
}

.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1rem;
}

.detail-grid {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 0.5rem 1rem;
  margin: 1rem 0;
}

.detail-grid dt {
  color: var(--slate);
  font-weight: 600;
}

.detail-grid dd {
  margin: 0;
}

.actions {
  display: flex;
  gap: 0.75rem;
  margin-top: 1rem;
}

.btn-link {
  color: var(--gold-dark);
  text-decoration: none;
  font-weight: 600;
  transition: color 0.15s ease;
}

.btn-link:hover {
  color: var(--gold);
}

/* Same "visibly greyed out" treatment .btn:disabled already gets --
   .btn-link needs its own copy since opacity is the one property that
   still wins even when a button also carries an inline color (e.g.
   style="color:var(--maroon-dark)" on the various Delete buttons), so
   "Delete Selected" (and "Copy Line Items from Estimate" when there's no
   estimate to copy from) actually look disabled, not just behave that
   way. */
.btn-link:disabled,
.btn-link.disabled {
  opacity: 0.45;
  cursor: default;
}

/* .btn-link reads fine on the dark page backdrop already; inside a
   white card it needs a touch more contrast than the base gold-dark. */
.card .btn-link {
  color: var(--warn-text);
}

.card .btn-link:hover {
  color: var(--gold-dark);
}

.btn-danger {
  background: transparent;
  color: var(--warn-text);
  border: 1px solid var(--warn-text);
  border-radius: var(--radius-sm);
  padding: 0.5rem 1rem;
  cursor: pointer;
}

.board-tabs {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.board-tab {
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  background: var(--surface);
  border: 2px solid var(--gray-light);
  color: var(--slate);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

/* Hover preview for the board tabs -- while one board is open, hovering
   any of the OTHER (non-active) tabs tints the tab with a soft preview
   of that board's own color plus a small lift, so switching boards feels
   like a real choice rather than a plain text link. Each tab already
   sets color:{{ b.color }} inline (board.html) for its border/text, so
   color-mix() with currentColor reuses that same per-board hex without
   needing a second inline variable just for hover. */
.board-tab:not(.active):hover {
  background: color-mix(in srgb, currentColor 15%, var(--surface));
  transform: translateY(-1px);
  box-shadow: 0 3px 10px rgba(30, 21, 23, 0.12);
}

/* Drop target for cross-board drags -- dropping a card here moves the
   job to that board (see kanban.js/jobs/routes.py's move_job). */
.board-tab.tab-drag-over {
  transform: scale(1.08);
  box-shadow: 0 0 0 3px var(--gold), 0 4px 12px rgba(201, 147, 47, 0.5);
}

/* Default active look for .board-tab used WITHOUT a per-board inline
   color (e.g. Tasks' Open/Completed/All filter tabs) -- previously just
   "color: white" with no background override, which on the default
   white .board-tab background meant invisible white-on-white text.
   Actual kanban board tabs still win over this: their inline
   style="background:{{ b.color }}" always beats a CSS class rule. */
.board-tab.active {
  background: var(--gold);
  color: var(--charcoal);
  border-color: var(--gold);
}

.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1rem;
  margin: 1.25rem 0 1.5rem;
}

.stat-tile {
  display: block;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--gold);
  border-top: 3px solid var(--gold);
  border-radius: var(--radius-lg);
  padding: 1.25rem;
  box-shadow: 0 2px 10px rgba(30, 21, 23, 0.08);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  text-decoration: none;
  cursor: pointer;
}

.stat-tile:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(201, 147, 47, 0.25);
}

.stat-value {
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.1;
  background: var(--gold-gradient-deep);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.stat-label {
  font-size: 0.85rem;
  color: var(--slate);
  margin-top: 0.25rem;
}

.stat-tile-warn {
  border-color: var(--warn-text);
  border-top-color: var(--warn-text);
}

.stat-tile-warn .stat-value {
  background: linear-gradient(135deg, var(--warn-text), var(--maroon-dark));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 1rem;
}

.dash-list {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
}

.dash-list li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--gray-light);
}

.dash-list li:last-child {
  border-bottom: none;
}

.dash-tag {
  font-size: 0.75rem;
  color: var(--slate);
  white-space: nowrap;
}

.dash-tag-overdue {
  color: var(--warn-text);
  font-weight: 600;
}

.type-badge {
  display: inline-block;
  background: var(--gray-light);
  color: var(--warn-text);
  border-radius: 999px;
  padding: 0.15rem 0.6rem;
  font-size: 0.75rem;
  font-weight: 600;
}

.tag-pill {
  display: inline-block;
  background: var(--gray-light);
  color: var(--slate);
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
  font-size: 0.7rem;
  margin: 0.1rem 0.2rem 0.1rem 0;
}

/* Click-to-edit cells on the Contacts list (see static/js/inline-edit.js).
   .cell-display is the normal read-only rendering; .editable-cell marks
   which <td>s have one; clicking it (or the Name cell's own
   .cell-edit-trigger, since its display is a real link) reveals the
   cell's own .cell-editor form with an explicit Save/Cancel pair -- an
   edit is only ever applied on that Save click, never on blur, so
   nothing commits by accident. */
.editable-cell .cell-display {
  cursor: pointer;
  border-bottom: 1px dashed var(--gold-light);
  display: inline-block;
}

.editable-cell .cell-display:hover {
  border-color: var(--gold);
}

.cell-edit-trigger {
  background: none;
  border: none;
  color: var(--gold-dark);
  cursor: pointer;
  font-size: 0.8rem;
  padding: 0 0.2rem;
  vertical-align: middle;
}

.cell-edit-trigger:hover {
  color: var(--gold);
}

.cell-editor {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem;
}

.cell-editor input,
.cell-editor select {
  min-width: 90px;
  max-width: 140px;
  margin-bottom: 0;
  padding: 0.2rem 0.4rem;
  border: 1px solid var(--gold);
  border-radius: var(--radius-xs);
  font: inherit;
  font-size: 0.85rem;
}

/* The Type/Source/Rep cell editors use the site's own custom dropdown
   (native_select macro) instead of a plain <select>, so its OPEN option
   list matches the rest of the app instead of OS-native chrome -- same
   compact-override pattern table.measurement-table already uses for the
   same component. */
.cell-editor .native-select {
  min-width: 100px;
  max-width: 150px;
  margin-bottom: 0;
}

.cell-editor .native-select-trigger {
  padding: 0.2rem 0.4rem;
  font-size: 0.85rem;
  border-color: var(--gold);
}

.cell-editor-actions {
  display: flex;
  gap: 0.2rem;
}

.cell-save,
.cell-cancel {
  border: none;
  border-radius: var(--radius-xs);
  width: 1.5rem;
  height: 1.5rem;
  line-height: 1;
  cursor: pointer;
  font-size: 0.85rem;
}

.cell-save {
  background: var(--gold);
  color: var(--white);
}

.cell-save:disabled {
  opacity: 0.55;
  cursor: default;
}

.cell-cancel {
  background: var(--gray-light);
  color: var(--slate);
}

.cell-editor-error {
  flex-basis: 100%;
  color: var(--warn-text);
  font-size: 0.75rem;
}

/* Marks a Task ai_tasks.py created, not a person -- gold accent family
   since that's this app's reserved "something special" color, distinct
   from .tag-pill's neutral gray. */
.ai-badge {
  display: inline-block;
  background: var(--gold-gradient);
  color: var(--charcoal);
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  margin-left: 0.4rem;
  vertical-align: middle;
}

.cell-sub {
  font-size: 0.75rem;
  color: var(--slate);
}

.shingle-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
}

.shingle-card {
  background: var(--surface);
  border: 1px solid var(--gold-light);
  border-radius: var(--radius-lg);
  border-top: 6px solid var(--gray);
  padding: 1rem;
  box-shadow: 0 2px 10px rgba(30, 21, 23, 0.08);
}

.shingle-card-name {
  font-weight: 700;
  margin-bottom: 0.3rem;
}

.shingle-card-price {
  font-size: 1.1rem;
  color: var(--slate);
  margin-bottom: 0.75rem;
}

.board-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1rem;
}

.board-card {
  background: var(--surface);
  border: 1px solid var(--gold-light);
  border-radius: var(--radius-lg);
  border-top: 6px solid var(--gray);
  padding: 1.25rem;
  text-decoration: none;
  color: var(--ink);
  box-shadow: 0 2px 10px rgba(30, 21, 23, 0.08);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.board-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(201, 147, 47, 0.3);
  border-color: var(--gold);
}

/* Click-anywhere-in-the-box add affordance -- used for the Notes quick-add
   trigger and the Documents upload label (jobs/detail.html,
   contacts/detail.html). Deliberately the exact same recipe as
   .empty-state above (same dashed border, background tint, and icon
   badge) so a job's "No invoices yet" state and its Notes/Documents add
   boxes read as one cohesive family of component, not three different
   looks -- just with hover/focus states added since, unlike
   .empty-state, this one is always clickable. Only works on real
   elements (<label>, <div>/<button>), never a <textarea>/<input> directly
   -- browsers don't render ::before on replaced form controls, which is
   why the Notes box is a click-to-open-a-small-modal trigger rather than
   the textarea itself. */
.add-box {
  display: block;
  width: 100%;
  border: 1.5px dashed var(--gray-light);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--gold) 3%, var(--surface));
  padding: 2.25rem 1.5rem;
  text-align: center;
  color: var(--slate);
  font-size: 0.92rem;
  cursor: pointer;
  font-family: inherit;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.add-box:hover,
.add-box:focus-within,
.add-box:focus-visible {
  border-color: var(--gold);
  background: color-mix(in srgb, var(--gold) 8%, var(--surface));
  outline: none;
}

.add-box::before {
  content: "";
  display: block;
  width: 34px;
  height: 34px;
  margin: 0 auto 0.6rem;
  border-radius: 50%;
  background: var(--gray-light);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23C9932F' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 10h18v9a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-9Z'/%3E%3Cpath d='M3 10l2.5-6h13L21 10'/%3E%3Cpath d='M9 14h6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 16px 16px;
}

.add-box-title {
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 0.25rem;
}

.add-box-hint {
  font-size: 0.8rem;
}

/* Visually hidden but still focusable/functional -- the file input a
   .add-box <label> targets. display:none would risk the browser's "an
   invalid form control is not focusable" quirk on validation; this
   pattern stays a real, interactable element. */
.visually-hidden-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.board-card-name {
  font-weight: 700;
  font-size: 1.1rem;
  margin-bottom: 0.4rem;
}

.board-card-stats {
  font-size: 0.85rem;
  color: var(--slate);
}

.inline-board-form {
  display: flex;
  align-items: flex-end;
  gap: 1rem;
  flex-wrap: wrap;
}

.inline-board-form > div {
  display: flex;
  flex-direction: column;
}

.inline-board-form input[type="text"] {
  margin-bottom: 0;
  min-width: 220px;
}

.inline-board-form input[type="color"] {
  width: 60px;
  height: 40px;
  padding: 0.2rem;
  border: 1px solid var(--gray);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.inline-board-form .submit-btn {
  width: auto;
  padding: 0.6rem 1.25rem;
}

.color-swatch {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  margin-right: 0.4rem;
  vertical-align: middle;
}

/* Generic drag-to-reorder table rows (static/js/drag-reorder.js) -- same
   "grab it, it fades while dragging" language as the kanban board's job
   cards, adapted for reordering rows within one list instead of moving
   between drop zones. First used for Pipeline Setup's stage order, then
   reused as-is for an estimate's line-item order. */
.drag-handle {
  width: 24px;
  color: var(--gray);
}

.drag-handle svg {
  width: 18px;
  height: 18px;
}

table.data-table tr[draggable="true"] {
  cursor: grab;
  transition: background-color 0.15s ease;
}

table.data-table tr[draggable="true"]:active {
  cursor: grabbing;
}

table.data-table tr[draggable="true"].dragging {
  opacity: 0.5;
  background: var(--gray-light);
}

table.data-table tr[draggable="true"].dragging td {
  box-shadow: inset 0 0 0 1.5px var(--gold);
}

.drag-handle svg {
  transition: color 0.15s ease;
}

table.data-table tr[draggable="true"]:hover .drag-handle {
  color: var(--gold-dark);
}

/* A row that's deliberately excluded from reordering (no `draggable`
   attribute at all) -- e.g. Pipeline Setup's "Lost" row, which always
   stays pinned first. Muted the same way the kanban Lost column itself
   is, so it visibly reads as "not part of the reorderable list" rather
   than just an oversight. */
.reorder-row-pinned {
  opacity: 0.7;
}

.kanban {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  padding-bottom: 1rem;
}

.kanban-column {
  flex: 0 0 260px;
  background: var(--gray-light);
  color: var(--ink);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  /* height (not max-height) so every column reaches the bottom of the
     viewport regardless of how many jobs it holds, matching a real
     Trello/JobNimbus-style board -- the dropzone below still scrolls
     internally (overflow-y: auto) once a column's own jobs exceed this. */
  height: calc(100vh - 165px);
}

/* The Lost column is a dead-end bin, not a step in the pipeline -- muted
   tone plus a heavy divider sets it apart from the sequential flow. */
.kanban-column-lost {
  background: var(--gray-light);
  opacity: 0.85;
  position: relative;
  margin-right: 0.5rem;
  padding-right: 0.5rem;
  border-right: 3px dashed var(--gray);
  transition: flex-basis 0.2s ease;
}

.kanban-column-lost .kanban-column-header {
  color: var(--slate);
}

/* Collapsed via the eye toggle -- shrinks to a slim strip instead of
   vanishing, so there's still something to click to bring it back. */
.kanban-column-lost.collapsed {
  flex: 0 0 44px;
  overflow: hidden;
}

.kanban-column-lost.collapsed .kanban-column-header {
  flex-direction: column;
  padding: 0.75rem 0.25rem;
  border-bottom: none;
}

.kanban-column-lost.collapsed .kanban-column-title,
.kanban-column-lost.collapsed .kanban-count {
  display: none;
}

.kanban-column-lost.collapsed .kanban-dropzone {
  display: none;
}

/* Paid/Job Close Out ("completed") columns -- same collapsible-to-a-
   slim-strip mechanic as Lost above (so the eye icon stays reachable to
   bring it back), but a gold left-border instead of Lost's muted dashed
   one: these are successful, wrapped-up jobs, not a discard bin, so they
   shouldn't read as visually de-emphasized the way Lost deliberately is. */
.kanban-column-won {
  position: relative;
  border-left: 3px solid var(--gold);
  padding-left: 0.5rem;
  transition: flex-basis 0.2s ease;
}

.kanban-column-won.collapsed {
  flex: 0 0 44px;
  overflow: hidden;
}

.kanban-column-won.collapsed .kanban-column-header {
  flex-direction: column;
  padding: 0.75rem 0.25rem;
  border-bottom: none;
}

.kanban-column-won.collapsed .kanban-column-title,
.kanban-column-won.collapsed .kanban-count {
  display: none;
}

.kanban-column-won.collapsed .kanban-dropzone {
  display: none;
}

.kanban-column-header {
  padding: 0.75rem 1rem;
  font-weight: 700;
  color: var(--ink);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  border-bottom: 1px solid var(--gray);
}

.kanban-column-title {
  flex: 1;
}

.eye-toggle {
  background: none;
  border: none;
  padding: 0.2rem;
  display: flex;
  align-items: center;
  color: var(--slate);
  cursor: pointer;
  flex-shrink: 0;
}

.eye-toggle:hover {
  color: var(--gold-dark);
}

.icon-eye,
.icon-eye-off {
  width: 18px;
  height: 18px;
}

/* Task "mark done"/"delete" icon-button pair -- shared by the Tasks list,
   job/contact detail's inline task lists, and the task edit page (see
   templates/_task_actions.html), so a task offers the same two actions
   everywhere it appears rather than each surface inventing its own. */
.row-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--gray);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.row-icon-btn svg {
  width: 16px;
  height: 16px;
}

.row-icon-btn:hover {
  background: var(--gray-light);
  color: var(--ink);
}

.row-icon-btn-done.is-completed {
  color: var(--gold-dark);
}

.row-icon-btn-trash:hover {
  color: var(--warn-text);
}

.kanban-count {
  background: var(--surface);
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
  font-size: 0.8rem;
  color: var(--slate);
}

.kanban-dropzone {
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  overflow-y: auto;
  min-height: 80px;
  transition: background 0.15s ease, outline-color 0.15s ease;
}

.kanban-dropzone.drag-over {
  background: var(--gray-light);
  outline: 2px dashed var(--warn-text);
}

.kanban-card {
  background: var(--surface);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  padding: 0.75rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  text-decoration: none;
  color: var(--ink);
  cursor: grab;
  transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease), border-color 0.15s ease, opacity 0.15s ease;
}

.kanban-card:hover {
  border-color: var(--gold);
  box-shadow: 0 3px 10px rgba(201, 147, 47, 0.3);
  transform: translateY(-1px);
}

.kanban-card:active {
  cursor: grabbing;
}

/* Dragged card visibly "lifts" (scale + a slight tilt + a deeper shadow)
   instead of just fading -- reads as picking the card up off the board
   rather than the card merely becoming disabled/translucent. */
.kanban-card.dragging {
  opacity: 0.5;
  transform: scale(1.03) rotate(-1.5deg);
  box-shadow: var(--shadow-lg);
  cursor: grabbing;
}

.kanban-card-title {
  font-weight: 600;
  margin-bottom: 0.25rem;
}

.kanban-card-meta {
  font-size: 0.8rem;
  color: var(--slate);
}

.kanban-card-rep {
  color: var(--gold-dark);
  font-weight: 600;
}

.cal-nav {
  display: flex;
  gap: 0.5rem;
}

.cal-title {
  color: var(--warn-text);
  margin: 0 0 1rem;
}

table.cal-month {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  color: var(--ink);
  border-radius: var(--radius-lg);
  overflow: hidden;
  table-layout: fixed;
  border: 1px solid var(--gold-light);
  box-shadow: 0 2px 10px rgba(30, 21, 23, 0.06);
}

table.cal-month th {
  background: var(--gray-light);
  padding: 0.5rem;
  font-size: 0.8rem;
  color: var(--slate);
  text-transform: uppercase;
}

.cal-cell {
  vertical-align: top;
  border: 1px solid var(--gray-light);
  padding: 0.4rem;
  height: 100px;
  width: 14.28%;
}

.cal-cell.other-month {
  background: var(--gray-light);
  opacity: 0.6;
}

.cal-cell.today .cal-daynum {
  background: var(--gold-gradient-deep);
  color: var(--white);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  box-shadow: 0 0 0 2px var(--gold-light);
}

.cal-daynum {
  font-weight: 600;
  font-size: 0.85rem;
  margin-bottom: 0.25rem;
}

.cal-task {
  display: block;
  font-size: 0.75rem;
  background: var(--gray-light);
  border-radius: var(--radius-xs);
  padding: 0.15rem 0.35rem;
  margin-bottom: 0.15rem;
  color: var(--ink);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cal-task.done {
  text-decoration: line-through;
  opacity: 0.6;
}

.cal-more {
  font-size: 0.7rem;
  color: var(--slate);
}

.cal-days {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
}

.cal-day-card {
  flex: 1 0 160px;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--gold-light);
  border-radius: var(--radius-lg);
  padding: 1rem;
}

.cal-day-card.today {
  border: 2px solid var(--gold);
  box-shadow: 0 2px 10px rgba(201, 147, 47, 0.25);
}

.cal-day-card h3 {
  margin: 0 0 0.5rem;
  font-size: 0.95rem;
  color: var(--slate);
}

.mcray-toast {
  position: fixed;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--charcoal);
  color: var(--white);
  border: 1px solid var(--gold);
  border-radius: var(--radius-md);
  padding: 0.75rem 1.25rem;
  font-size: 0.9rem;
  font-weight: 600;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  opacity: 0;
  transition: opacity 0.25s ease, transform 0.25s ease;
  z-index: 1000;
}

.mcray-toast.visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Job detail page's left sidenav -- click through a job's sections
   (Overview/Estimate/Notes, "Coming Soon" placeholders for Documents/
   Payments/Invoices) instead of one long scrolled page, mirroring
   JobNimbus's own per-job sidebar. static/js/job-tabs.js handles the
   switching (hash-routed, no reload). */
.job-number-badge {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.15rem 0.6rem;
  border: 1px solid var(--gold-light);
  border-radius: var(--radius-sm);
  background: var(--gray-light);
  color: var(--slate);
  font-size: 0.85rem;
  font-weight: 600;
  vertical-align: middle;
}

.job-layout {
  display: flex;
  align-items: flex-start;
  gap: 1.5rem;
}

.job-sidenav {
  flex: 0 0 200px;
  position: sticky;
  top: 1rem;
  background: var(--surface);
  border: 1px solid var(--gold-light);
  border-radius: var(--radius-lg);
  box-shadow: 0 2px 10px rgba(30, 21, 23, 0.06);
  padding: 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.job-sidenav-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  text-align: left;
  padding: 0.6rem 0.75rem;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  font-size: 0.92rem;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

.job-sidenav-item:not(.disabled):not(.active):hover {
  transform: translateX(2px);
}

.job-sidenav-item:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.job-sidenav-item:hover {
  background: var(--gray-light);
}

.job-sidenav-item.active {
  background: var(--gold-gradient);
  color: var(--charcoal);
}

.job-sidenav-item.disabled {
  color: var(--gray);
  cursor: default;
}

.job-sidenav-item.disabled:hover {
  background: none;
}

.job-sidenav-badge {
  background: var(--gray-light);
  color: var(--slate);
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
  font-size: 0.75rem;
  font-weight: 700;
}

.job-sidenav-item.active .job-sidenav-badge {
  background: rgba(30, 21, 23, 0.15);
  color: inherit;
}

.job-sidenav-divider {
  border-top: 1px solid var(--gray-light);
  margin: 0.4rem 0;
}

.job-sidenav-section-label {
  padding: 0.2rem 0.75rem 0.3rem;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--gray);
}

.job-content {
  flex: 1;
  min-width: 0;
}

@media (max-width: 800px) {
  .job-layout {
    flex-direction: column;
  }
  .job-sidenav {
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
    position: static;
  }
  .job-sidenav-divider,
  .job-sidenav-section-label {
    display: none;
  }
  .job-sidenav-item.disabled {
    display: none;
  }
}
