/* Brand Colors */
:root {
  --mm-green: #94cf1c;
  --mm-green-dark: #6fa312;
}

.btn-outline-mm-green {
  color: var(--mm-green-dark);
  border-color: var(--mm-green);
}

.btn-outline-mm-green:hover,
.btn-outline-mm-green:active,
.btn-outline-mm-green:focus {
  color: #fff;
  background-color: var(--mm-green);
  border-color: var(--mm-green);
}

/* Width Utilities */
.w-33 {
  width: 33.333333% !important;
}

.w-66 {
  width: 66.666667% !important;
}

.hover-row {
  transition:
    box-shadow 0.2s ease,
    background-color 0.2s ease;
  /* cursor: pointer;  optional, makes it feel clickable */
}

.hover-row:hover {
  background-color: var(--bs-light); /* light background on hover */
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); /* subtle shadow */
}

.form-check-input.switch-lg {
  width: 4em;
  height: 2em;
}

.wrapper-white-full-flex {
  background-color: white;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.fixed-modal-body {
  height: 600px; /* Set fixed height */
  overflow-y: auto; /* Scroll inside modal */
}

/* ==========================================================================
   Asset widgets
   ========================================================================== */

.asset-widget {
  border-radius: 0.5rem;
  transition:
    box-shadow 0.2s ease,
    transform 0.2s ease,
    border-color 0.2s ease;
}

.asset-widget:hover {
  box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.08);
}

.asset-widget-minheight {
  min-height: 80px;
}

/*
  Meta strip sits in normal flow above the header. Previously it was
  absolutely positioned, which let long asset labels and badges run
  underneath the title and the action buttons.
*/
.asset-meta-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
  min-width: 0;
}

.asset-label {
  background: rgba(200, 200, 200, 0.8);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.75rem;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Title must be allowed to shrink and wrap so it never slides under the
   action buttons on narrow columns. */
.asset-title {
  overflow-wrap: anywhere;
  word-break: break-word;
}

.min-w-0 {
  min-width: 0 !important;
}

/*
  Hover-reveal for the meta strip. Collapsing max-height/margin (rather than
  only fading) means the hidden strip reserves no vertical space, so headers
  stay compact until hovered.
*/
.asset-hover-expand {
  opacity: 0;
  max-height: 0;
  padding-top: 0 !important;
  overflow: hidden;
  transform: translateY(-4px);
  transition:
    opacity 0.15s ease,
    transform 0.15s ease,
    max-height 0.15s ease,
    padding-top 0.15s ease;
  pointer-events: none;
}

/* Reveal is driven from the whole card: the meta strip is a sibling of the
   header, so a header-scoped descendant selector would never match it. */
.asset-widget:hover .asset-hover-expand,
.asset-widget:focus-within .asset-hover-expand {
  opacity: 1;
  max-height: 4rem;
  padding-top: 0.5rem !important;
  transform: translateY(0);
  pointer-events: auto;
}

.asset-footer:empty {
  display: none !important;
}

/* Collapse the meta strip when every badge in it has been suppressed, so it
   does not leave an empty padded band above the header. `:empty` cannot be
   used here - Django template whitespace leaves text nodes inside the div -
   so this keys off :not(:has(...)) instead. */
.asset-meta-strip:not(:has(> *)) {
  display: none !important;
}

/* ==========================================================================
   Reporting / list layout
   ========================================================================== */

/* Filter toolbar for the reporting screens */
.filter-container {
  background: #fff;
  border: 1px solid var(--bs-border-color);
  border-radius: 0.5rem;
  padding: 1rem;
}

/*
  Single card holding the whole chart row - the charts and the status table are
  sections within it rather than three separate boxes.
*/
.report-card {
  background: #fff;
  border: 1px solid var(--bs-border-color);
  border-radius: 0.5rem;
  padding: 1rem;
}

.report-card-title {
  font-size: 0.8125rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--bs-secondary-color);
  margin-bottom: 0.75rem;
}

/*
  Hairline between sections. The columns are col-xxl-5/5/2 but col-lg-6/6/12,
  so below xxl the third section wraps onto its own line - only draw the
  divider at the width where all three genuinely sit side by side, and on the
  second section from lg up where it still shares a row with the first.
*/
@media (min-width: 992px) {
  .row > .col-lg-6.report-section-divider {
    border-left: 1px solid var(--bs-border-color);
  }
}

@media (min-width: 1400px) {
  .report-section-divider {
    border-left: 1px solid var(--bs-border-color);
  }
}

/* ==========================================================================
   Filter card (variant B) - labeled field grid with a header row for
   reset/export, and a full-width search row beneath. A different rhythm to
   .filter-bar below: grouped fields with visible labels instead of a single
   wrapping strip of bare controls.
   ========================================================================== */
.filter-card {
  background: #fff;
  border: 1px solid var(--bs-border-color);
  border-radius: 0.75rem;
  padding: 1rem 1.25rem;
}

.filter-card-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.filter-card-title {
  font-size: 0.9375rem;
  font-weight: 600;
}

.filter-card-header-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.filter-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}

.filter-field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.filter-field label {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--bs-secondary-color);
}

.filter-card-search .input-group-text {
  color: var(--bs-secondary-color);
}

/*
  Compact single-strip filter bar. Every control sits on one wrapping line
  rather than the four stacked rows the reporting screens used to have, so the
  charts and list start much higher up the page.
*/
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0.75rem;
  background: #fff;
  border: 1px solid var(--bs-border-color);
  border-radius: 0.5rem;
  padding: 0.5rem 0.75rem;
  font-family: "Roboto", var(--bs-body-font-family);
}

/*
  The bar's own font-family is inherited by most of its contents, but form
  controls and buttons take a UA font instead of inheriting, so they have to be
  named. The rest of the app keeps the Bootstrap system stack.
*/
.filter-bar input,
.filter-bar select,
.filter-bar textarea,
.filter-bar button,
.filter-bar label,
.filter-bar .form-control,
.filter-bar .btn,
.filter-bar .input-group-text,
.filter-bar .badge {
  font-family: "Roboto", var(--bs-body-font-family);
}

/*
  The depot dropdown is rendered in place inside the bar, so it inherits - but
  it is listed anyway because Bootstrap will float it to the body in some
  configurations, which would break the inheritance chain.
*/
.filter-bar .dropdown-menu,
.filter-bar .dropdown-menu .dropdown-item {
  font-family: "Roboto", var(--bs-body-font-family);
}

/*
  Middle column: preset time ranges on top, depot picker and the custom date
  range beneath them.
*/
.filter-controls {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}

.filter-controls-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

/*
  Report title + active range/depot summary. Kept as a single compact stack on
  the left of the bar rather than the full-width heading block it used to be.
*/
.filter-summary {
  display: flex;
  flex-direction: column;
  justify-content: center;
  line-height: 1.25;
  padding-right: 0.75rem;
  border-right: 1px solid var(--bs-border-color);
}

.filter-summary-title {
  font-size: 0.8125rem;
  font-weight: 600;
}

.filter-summary-meta {
  font-size: 0.75rem;
  color: var(--bs-secondary-color);
}

/*
  The two search fields stack vertically so they occupy one bar-height column
  instead of a second full-width row.
*/
.filter-searches {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.375rem;
  flex: 1 1 220px;
  min-width: 180px;
  margin-left: auto;
}

.filter-bar .filter-dates .form-control {
  width: auto;
  flex: 0 1 auto;
}

/* Icon-only reset, sized to line up with the small controls beside it. */
.filter-reset {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 31px;
  height: 31px;
  border: 1px solid var(--bs-border-color);
  border-radius: 0.25rem;
  color: var(--bs-secondary-color);
  cursor: pointer;
  flex-shrink: 0;
}

.filter-reset:hover {
  background: var(--bs-secondary-bg);
  color: var(--bs-body-color);
}

/*
  Once the bar wraps, the columns stack full width - the summary's vertical
  divider and the searches' right-alignment no longer make sense.
*/
@media (max-width: 991.98px) {
  .filter-summary {
    padding-right: 0;
    border-right: 0;
  }

  .filter-searches {
    margin-left: 0;
  }
}

/*
  Charts need a bounded height, otherwise Chart.js grows the canvas on every
  HTMX re-render and the charts overlap the content beneath them.
*/
.chart-box {
  position: relative;
  width: 100%;
  height: 260px;
}

.chart-box > canvas {
  position: absolute;
  inset: 0;
  width: 100% !important;
  height: 100% !important;
}

/*
  The same chart re-rendered inside the expand modal. Sized off the viewport so
  it grows on large screens, which is the whole point of expanding it. The
  canvas is pinned to the box so Chart.js sizes to it rather than the reverse.
*/
.chart-box-expanded {
  position: relative;
  width: 100%;
  height: min(70vh, 640px);
}

.chart-box-expanded > canvas {
  position: absolute;
  inset: 0;
  width: 100% !important;
  height: 100% !important;
}

/*
  Heading row for a chart: the existing heading on the left, the expand
  affordance on the right.
*/
.chart-heading-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

/* The heading inside the row keeps its own bottom margin off. */
.chart-heading-row > h6 {
  margin-bottom: 0;
}

.chart-expand-btn {
  border: 0;
  background: transparent;
  padding: 0.125rem 0.25rem;
  line-height: 1;
  border-radius: 0.25rem;
  color: var(--bs-secondary-color);
  cursor: pointer;
}

.chart-expand-btn:hover,
.chart-expand-btn:focus-visible {
  color: var(--bs-body-color);
  background: var(--bs-secondary-bg);
}

/* Boxed list rows */
.check-row {
  border: 0;
  border-radius: 0.5rem;
  background: #fff;
  padding: 0.75rem;
}

.check-row + .check-row {
  margin-top: 0.75rem;
}

.check-row-defects {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 0.5rem;
  align-items: stretch;
}

.check-empty-state {
  border-radius: 0.5rem;
  min-height: 100%;
}

/*
  The Checks by Status panel sits beside the two charts, so it stretches to the
  same height rather than sitting short at the top of its column. Its three
  rows then spread over that height instead of bunching under the heading.
*/
.checks-by-status {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 260px; /* matches .chart-box */
  padding-bottom: 1.5rem;
}

.checks-by-status-rows {
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  flex: 1 1 auto;
}

/* Slightly larger than the default so the rows carry the extra height rather
   than leaving it as empty gaps between them. */
.checks-by-status .status-row {
  font-size: 1.0625rem;
}

.checks-by-status .status-row .fw-semibold {
  font-size: 1.125rem;
}

/* ==========================================================================
   Reporting - Checks by Status drilldown
   ========================================================================== */

/* The three status rows open a vehicle-list modal, so they have to read as
   controls rather than as static figures. */
.status-row {
  cursor: pointer;
  border-radius: 0.25rem;
  transition:
    background-color 0.15s ease,
    font-weight 0.15s ease;
}

.status-row:hover,
.status-row:focus-visible {
  background-color: var(--bs-light);
  font-weight: 600;
}

.sortable-table th.sort-col {
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
}

/* The caret is only rendered on the active column, so the slot is reserved at
   a fixed width - otherwise headers jump sideways on the first sort. */
.sortable-table th.sort-col .sort-icon {
  display: inline-block;
  width: 0.75em;
  margin-left: 0.25rem;
  color: var(--bs-secondary-color);
}

/* Defect rows expand in place to list their defects. */
.sortable-table tr.defect-row {
  cursor: pointer;
}

/* The detail row is a continuation of the row above it, so drop the border
   that would otherwise split the two apart. */
.sortable-table tr.defect-detail-row > td {
  border-top: 0;
}

/*
  Search inputs: drop Bootstrap's blue focus treatment (blue border +
  $input-focus-box-shadow glow), which read as an error/active state on what is
  just a text box. The field still shows a visible focus state - the border
  darkens to the body colour - so keyboard users keep an unambiguous target.
  Listed by id because the search boxes are plain .form-control inputs with no
  shared class of their own; the [type=search] rule covers any future ones.
*/
#vehicle_search:focus,
#driver_search:focus,
#defect_search:focus,
#depot_search:focus,
#response_search:focus,
#infringement_search:focus,
#vehicle_types_search:focus,
#employee_role_search:focus,
.form-control[type="search"]:focus {
  border-color: var(--bs-border-color);
  box-shadow: none;
  outline: 0;
}

/*
  Garage availability month calendar (workshop booking modal). A deliberately
  plain, Google Calendar-style grid - thin cell borders, a light hover state,
  no per-status background colour except for a full/empty day, so the
  booked/max figure stays the thing the eye lands on.
*/
.workshop-availability-grid {
  table-layout: fixed;
}

.workshop-availability-grid th {
  text-align: center;
  font-weight: 600;
  padding-bottom: 0.25rem;
}

.workshop-availability-cell {
  border: 1px solid var(--bs-border-color);
  height: 3.25rem;
  vertical-align: top;
  padding: 0.25rem;
  text-align: center;
  transition: background-color 0.1s ease-in-out;
}

.workshop-availability-cell:not(.workshop-availability-cell-blank):hover {
  background-color: var(--bs-tertiary-bg);
}

.workshop-availability-cell-blank {
  border-color: transparent;
}

.workshop-availability-cell-today {
  background-color: rgba(148, 207, 28, 0.08);
}

.workshop-availability-day-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
}

.workshop-availability-cell-today .workshop-availability-day-number {
  background-color: var(--mm-green);
  color: #fff;
}

.workshop-availability-cell-full {
  background-color: rgba(220, 53, 69, 0.06);
}

/* Circle marker around the day number for the currently-picked date - mirrors
   the "today" circle above but ringed rather than filled, so a selected day
   stays distinguishable from today when they're not the same cell. Targets a
   dedicated class on the day-number div itself rather than a positional
   pseudo-selector - the radio input that precedes it in the DOM means
   :first-child never actually matched the day-number div, so this same
   pattern silently never worked for the pre-existing "today" circle either
   until both were switched to this class-based selector. */
.workshop-availability-cell-selected .workshop-availability-day-number {
  border: 2px solid var(--mm-green);
}

.workshop-availability-cell-today.workshop-availability-cell-selected .workshop-availability-day-number {
  background-color: var(--mm-green);
  border-color: #fff;
  box-shadow: 0 0 0 2px var(--mm-green);
}

/* Compliance rows on the vehicle edit form (workshop/vehicle_compliance/_item_row.html):
   each row keeps a divider except the last, so the list reads as one clean
   block rather than ending on a stray line. */
.compliance-item-list > div:last-child {
  border-bottom: none !important;
}

/* ==========================================================================
   Clamped list + hover tooltip (employee row "Assigned Depots" column;
   vehicle type row's checklists/vehicles/service templates columns)
   ========================================================================== */

/*
  Left divider separating a clamped-list column from its neighbour, and
  vertical centering so the column uses the row's full height rather than
  sitting top-aligned with empty space beneath it.
*/
.depot-column {
  border-left: 1px solid var(--bs-border-color);
  padding-left: 1rem;
}

/*
  Names stack one per line and clip after 3 rows rather than the column
  growing with the item count - a driver with many depots, or a vehicle type
  with many vehicles, would otherwise stretch every row in the list to match.
*/
.clamped-list-trigger {
  display: block;
  cursor: default;
}

.clamped-list-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.clamped-list-clamp li {
  list-style: none;
}

.clamped-list-more {
  font-size: 0.75rem;
  color: var(--bs-secondary-color);
}

/*
  Styled tooltip with the full list, shown on hover/focus. A native title
  attribute can't be styled and truncates awkwardly on multi-line content, so
  this is a small absolutely-positioned panel instead. Opens upward
  (anchored to the trigger's top, not its bottom) so a row near the bottom
  of a long list doesn't need the page scrolled further to see it - the
  list above the trigger is always on-screen already, unlike the space
  below a row that's near the end of the page.
*/
.clamped-list-tooltip {
  position: absolute;
  z-index: 1070; /* above Bootstrap dropdowns (1000) and level with tooltips */
  bottom: calc(100% + 0.25rem);
  left: 0;
  min-width: 12rem;
  max-width: 18rem;
  max-height: 12rem;
  overflow-y: auto;
  background: var(--bs-body-bg);
  border: 1px solid var(--mm-green);
  border-radius: 0.5rem;
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
  padding: 0.5rem 0.75rem;
  opacity: 0;
  transform: translateY(4px);
  pointer-events: none;
  transition:
    opacity 0.1s ease,
    transform 0.1s ease;
}

.clamped-list-tooltip ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.clamped-list-tooltip li {
  padding: 0.125rem 0;
}

.clamped-list-trigger:hover .clamped-list-tooltip,
.clamped-list-trigger:focus-within .clamped-list-tooltip {
  opacity: 1;
  pointer-events: auto;
}

/*
  Any native <select multiple> tagged .tick-multiselect (depot/garage picker
  on the employee add/edit form, vehicle-type pickers, etc.) - a browser
  cannot render custom markup (an icon) inside an <option>, so the tick is
  prefixed onto the option's own text by JS instead (see
  depot-multiselect-js.html). The browser's default blue selected-row fill
  is suppressed so the tick is the only selection indicator.
*/
.tick-multiselect {
  min-height: 8rem;
}

.tick-multiselect option:checked {
  background: none;
  color: inherit;
}

/*
  Health check shortcut chips (Part 2 rectification). Built on Bootstrap's
  .btn-check pattern (a visually-hidden checkbox driving a <label class="btn">)
  so the existing multi-select/hx-post-on-change wiring needs no change -
  only made bigger and more finger-friendly, since these are tapped on a
  mechanic's phone/tablet mid-repair, not clicked with a mouse.
*/
.shortcut-chip-group {
  gap: 0.5rem !important;
}

.shortcut-chip {
  padding: 0.5rem 1rem;
  font-size: 1rem;
  border-radius: 1.5rem;
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
}
