/* ==========================================================================
   Lightning Drones — shared component layer (§10.1)

   theme.css owns the tokens. This owns the things built from them that more
   than one screen needs: buttons, card headers, tables, form fields, page
   headers.

   It exists because 42 of the 70 templates had written
   `style="background: var(--ld-primary);"` on a button by hand. That is not a
   styling problem on its own — it is that there was nowhere else to put it, so
   every screen invented its own spacing, its own hover state and its own focus
   treatment alongside it.

   Loaded from base.html for every shell. The marketing site's site.css loads
   after this and overrides what it needs.
   ========================================================================== */

/* --- Bootstrap, brought onto the brand --------------------------------- */
/* Bootstrap 5.3 reads these separately from --bs-primary, so without them the
   focus ring, the checked checkbox and the active link stayed default blue on
   a green product — visible on every form in the application. */
:root {
  --bs-primary-rgb: 39, 167, 118;
  --bs-link-color: var(--ld-primary-dark);
  --bs-link-hover-color: var(--ld-primary);
  --bs-focus-ring-color: rgba(39, 167, 118, 0.25);
  --bs-focus-ring-width: 3px;
}

.form-control:focus,
.form-select:focus {
  border-color: var(--ld-primary);
  box-shadow: 0 0 0 3px rgba(39, 167, 118, 0.15);
}

.form-check-input:checked {
  background-color: var(--ld-primary);
  border-color: var(--ld-primary);
}

.form-check-input:focus {
  border-color: var(--ld-primary);
  box-shadow: 0 0 0 3px rgba(39, 167, 118, 0.15);
}

/* A visible keyboard focus ring everywhere, not only on form controls. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--ld-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

/* --- Buttons ------------------------------------------------------------ */
.btn-ld,
.btn-ld-soft,
.btn-ld-ghost {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid transparent;
  border-radius: 8px;
  font-weight: 500;
  line-height: 1.4;
  padding: 0.45rem 0.95rem;
  text-decoration: none;
  transition:
    background var(--ld-transition),
    border-color var(--ld-transition),
    box-shadow var(--ld-transition),
    transform var(--ld-transition);
}

.btn-ld {
  background: var(--ld-primary);
  color: #fff;
  box-shadow: 0 1px 2px rgba(30, 130, 89, 0.25);
}

.btn-ld:hover,
.btn-ld:focus {
  background: var(--ld-primary-dark);
  color: #fff;
  box-shadow: 0 3px 10px rgba(30, 130, 89, 0.28);
}

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

.btn-ld-soft {
  background: var(--ld-primary-soft);
  color: var(--ld-primary-dark);
}

.btn-ld-soft:hover,
.btn-ld-soft:focus {
  background: #d7eee4;
  color: var(--ld-primary-dark);
}

.btn-ld-ghost {
  background: transparent;
  border-color: var(--ld-border);
  color: var(--ld-text);
}

.btn-ld-ghost:hover,
.btn-ld-ghost:focus {
  background: var(--ld-bg);
  border-color: #c9d2de;
  color: var(--ld-text);
}

.btn-ld-sm {
  padding: 0.3rem 0.7rem;
  font-size: 0.82rem;
}

/* --- touch ---------------------------------------------------------------
   Every platform's guidelines settle on about 44px for a tap target, and an icon-only
   .btn-sm is 32x31 — small enough to miss repeatedly while holding a phone one-handed,
   which inspectors do in the field and clients do on site.

   Scoped to coarse pointers so a mouse keeps the compact controls, and expressed as
   min-height/min-width so nothing shrinks and only the genuinely small things grow. The
   icon stays its own size; it is the hit area that changes. */
@media (pointer: coarse) {
  .btn-sm,
  .btn-ld-sm,
  .btn.btn-sm,
  .page-link {
    min-height: 2.5rem;
    min-width: 2.5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Checkbox and radio inputs, which Bootstrap draws at 1em. The label is usually the
     larger target, but a bare checkbox in a table has nothing else to hit. */
  .form-check-input {
    min-width: 1.15rem;
    min-height: 1.15rem;
  }
}

/* An <a> cannot be disabled, so the state is carried on aria-disabled and the click is
   cancelled in script. Styling from the attribute rather than a class keeps the two from
   disagreeing — what assistive technology is told and what is drawn are the same source. */
.btn-ld[aria-disabled="true"],
.btn-ld-ghost[aria-disabled="true"],
.btn-ld-soft[aria-disabled="true"] {
  opacity: 0.45;
  pointer-events: none;
}

.btn-ld-lg {
  padding: 0.65rem 1.3rem;
  font-size: 1rem;
}

/* Bootstrap's own buttons, kept consistent with the above. */
.btn { border-radius: 8px; }

/* --- Page header -------------------------------------------------------- */
/* The bar of actions that opens almost every screen. It was an ad-hoc flex row
   written slightly differently on each one. */
.ld-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}

.ld-actions__spacer { margin-left: auto; }

.ld-crumbs {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.8rem;
  color: var(--ld-text-muted);
  margin-bottom: 0.35rem;
}

.ld-crumbs a {
  color: var(--ld-text-muted);
  text-decoration: none;
}

.ld-crumbs a:hover { color: var(--ld-primary-dark); }

/* --- Cards -------------------------------------------------------------- */
.ld-card__head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.8rem 1rem;
  border-bottom: 1px solid var(--ld-border);
}

.ld-card__title {
  font-size: 0.92rem;
  font-weight: 600;
  margin: 0;
}

.ld-card__icon {
  display: grid;
  place-items: center;
  width: 1.85rem;
  height: 1.85rem;
  border-radius: 7px;
  background: var(--ld-primary-soft);
  color: var(--ld-primary-dark);
  font-size: 0.9rem;
  flex: none;
}

.ld-card__body { padding: 1rem; }

/* --- Definition lists --------------------------------------------------- */
/* The detail pages are mostly label/value pairs. Rules between rows make them
   scannable; a plain dl runs together once there are more than about four. */
.ld-dl { margin: 0; }

.ld-dl > div {
  display: flex;
  gap: 1rem;
  padding: 0.5rem 0;
  border-bottom: 1px dashed var(--ld-border);
  font-size: 0.86rem;
}

.ld-dl > div:last-child { border-bottom: 0; }

.ld-dl dt {
  flex: 0 0 42%;
  font-weight: 500;
  color: var(--ld-text-muted);
  margin: 0;
}

.ld-dl dd {
  flex: 1;
  margin: 0;
  overflow-wrap: anywhere;
}

/* --- Tables ------------------------------------------------------------- */
.ld-table { margin-bottom: 0; }

.ld-table > thead > tr > th {
  background: var(--ld-bg);
  color: var(--ld-text-muted);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-bottom: 1px solid var(--ld-border);
  white-space: nowrap;
  padding: 0.6rem 0.75rem;
}

.ld-table > tbody > tr > td {
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--ld-border);
  vertical-align: middle;
}

.ld-table > tbody > tr:last-child > td { border-bottom: 0; }

.ld-table > tbody > tr {
  transition: background var(--ld-transition);
}

.ld-table > tbody > tr:hover > td { background: rgba(39, 167, 118, 0.035); }

/* A long findings table keeps its header in view while it is scrolled. These
   run to hundreds of rows and a headerless screenful is unreadable. */
.ld-table--sticky > thead > tr > th {
  position: sticky;
  top: 0;
  z-index: 2;
}

/* --- Form fields -------------------------------------------------------- */
.ld-field { margin-bottom: 1rem; }

.ld-field__label {
  display: block;
  font-size: 0.8rem;
  font-weight: 500;
  margin-bottom: 0.3rem;
}

.ld-field__required {
  color: var(--ld-sev-high);
  margin-left: 0.15rem;
}

.ld-field__help {
  font-size: 0.78rem;
  color: var(--ld-text-muted);
  margin-top: 0.25rem;
}

.ld-field__error {
  font-size: 0.78rem;
  color: var(--ld-sev-high);
  margin-top: 0.25rem;
}

.ld-field--invalid .form-control,
.ld-field--invalid .form-select {
  border-color: var(--ld-sev-high);
}

/* A titled group of fields, so a long form reads as sections rather than as a
   single column of inputs. */
.ld-fieldset { margin-bottom: 1.4rem; }

.ld-fieldset__legend {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ld-text-muted);
  padding-bottom: 0.4rem;
  margin-bottom: 0.8rem;
  border-bottom: 1px solid var(--ld-border);
}

/* --- Chips -------------------------------------------------------------- */
.ld-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  background: var(--ld-primary-soft);
  color: var(--ld-primary-dark);
  font-size: 0.74rem;
  font-weight: 500;
  white-space: nowrap;
}

.ld-chip--muted {
  background: var(--ld-bg);
  color: var(--ld-text-muted);
  border: 1px solid var(--ld-border);
}

/* --- Thumbnails --------------------------------------------------------- */
.ld-thumb {
  display: block;
  border-radius: 8px;
  border: 1px solid var(--ld-border);
  object-fit: cover;
  transition:
    transform var(--ld-transition),
    box-shadow var(--ld-transition);
}

a:hover > .ld-thumb {
  transform: scale(1.02);
  box-shadow: var(--ld-shadow-md);
}

/* --- Links -------------------------------------------------------------- */
.ld-link {
  color: var(--ld-primary-dark);
  text-decoration: none;
  font-weight: 500;
}

.ld-link:hover {
  color: var(--ld-primary);
  text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) {
  .btn-ld:active { transform: none; }
  a:hover > .ld-thumb { transform: none; }
}

/* --- Modals -------------------------------------------------------------- */
.ld-modal {
  border: 1px solid var(--ld-border);
  border-radius: var(--ld-radius-lg);
  box-shadow: 0 24px 60px rgba(16, 24, 40, 0.22);
  overflow: hidden;
}

.ld-modal__icon {
  display: inline-grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  font-size: 1.4rem;
  background: var(--ld-primary-soft);
  color: var(--ld-primary-dark);
}

.ld-modal__icon--danger {
  background: rgba(220, 53, 69, 0.1);
  color: var(--ld-sev-high);
}

.ld-modal__icon--warning {
  background: rgba(255, 193, 7, 0.16);
  color: #8a6400;
}

/* --- Lightbox ------------------------------------------------------------ */
.ld-lightbox__stage {
  display: grid;
  place-items: center;
  background: #0d1117;
  min-height: 12rem;
  /* Leaves room for the header, the caption bar and the viewport's own margins. */
  max-height: calc(100vh - 14rem);
  overflow: hidden;
}

.ld-lightbox__stage img {
  max-width: 100%;
  max-height: calc(100vh - 14rem);
  object-fit: contain;
  display: block;
}

.ld-lightbox__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 2.5rem;
  height: 2.5rem;
  border: 0;
  border-radius: 50%;
  background: rgba(13, 17, 23, 0.55);
  color: #fff;
  font-size: 1.1rem;
  display: grid;
  place-items: center;
  transition: background var(--ld-transition);
}

.ld-lightbox__nav:hover { background: rgba(13, 17, 23, 0.8); }
.ld-lightbox__nav[hidden] { display: none; }
.ld-lightbox__nav--prev { left: 0.75rem; }
.ld-lightbox__nav--next { right: 0.75rem; }

/* --- File inputs --------------------------------------------------------- */
/* Django's ClearableFileInput prints "Currently: <the whole storage path> / Clear /
   Change:" as raw text. On the project form that is eleven of them at once, each with a
   90-character path that wraps across three lines and collides with its neighbour. The
   widget renders as a tile instead: the current file as a thumbnail, its name once, and
   the two controls. */
.ld-file { }

.ld-file__preview {
  position: relative;
  display: block;
  width: 100%;
  height: 5.5rem;
  border: 1px solid var(--ld-border);
  border-radius: 8px;
  overflow: hidden;
  background:
    repeating-conic-gradient(#f2f4f7 0% 25%, #ffffff 0% 50%) 50% / 12px 12px;
}

.ld-file__preview img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.ld-file__empty {
  display: grid;
  place-items: center;
  height: 5.5rem;
  border: 1px dashed var(--ld-border);
  border-radius: 8px;
  color: var(--ld-text-muted);
  font-size: 1.3rem;
  background: var(--ld-bg);
}

.ld-file__name {
  display: block;
  font-size: 0.72rem;
  color: var(--ld-text-muted);
  margin-top: 0.3rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ld-file__controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.35rem;
}

.ld-file__controls input[type="file"] {
  font-size: 0.75rem;
  flex: 1 1 auto;
  min-width: 0;
}

.ld-file__clear {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.72rem;
  color: var(--ld-text-muted);
  white-space: nowrap;
}

/* --- report progress -----------------------------------------------------
   Shown only while a report is being prepared. A 48-second wait with nothing moving is
   indistinguishable from a broken button, which is the whole reason this exists. */
.report-progress {
  display: none;
  margin-top: 0.6rem;
  max-width: 24rem;
}

.report-progress.is-shown { display: block; }

.report-progress__bar {
  height: 0.5rem;
  border-radius: 999px;
  background: var(--ld-bg);
  border: 1px solid var(--ld-border);
  overflow: hidden;
}

.report-progress__fill {
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--ld-primary), var(--ld-primary-dark));
  transition: width 0.5s ease;
}

.report-progress--failed .report-progress__fill { background: var(--ld-danger, #c0392b); }

.report-progress__text {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.3rem;
  font-size: 0.78rem;
  color: var(--ld-text-muted);
}

.report-progress--failed .report-progress__phase { color: var(--ld-danger, #c0392b); }

@media (prefers-reduced-motion: reduce) {
  .report-progress__fill { transition: none; }
}

/* --- small screens -------------------------------------------------------
   Last in the file on purpose. These override rules defined above them, and a media query
   adds no specificity — so at equal weight the later declaration is the only thing that
   decides. An override placed earlier in the file silently does nothing, which is exactly
   what happened to the first version of this block.

   Uppercase letter-spaced labels read larger than their point size, which is why they are
   set small. Below about 11px that stops being true on a phone held at arm's length in
   daylight. */
@media (max-width: 767.98px) {
  .ld-table > thead > tr > th,
  .table > thead > tr > th { font-size: 0.76rem; }
  .badge.rounded-pill { font-size: 0.72rem; }

  /* --- .ld-stack: a table that becomes cards on a phone -------------------
     Five columns in 390px either scroll sideways or squeeze every value into two
     wrapped lines; neither is readable, and a client checking a project on site gets
     whichever is worse. Stacked, one row is one card with its fields labelled.

     Each cell needs data-label="…", which is what replaces the hidden header. A cell
     without one is still shown — losing a value is worse than losing its label. */
  table.ld-stack thead { display: none; }

  table.ld-stack > tbody > tr {
    display: block;
    border: 1px solid var(--ld-border);
    border-radius: var(--ld-radius);
    margin-bottom: 0.6rem;
    padding: 0.7rem 0.85rem;
  }

  table.ld-stack > tbody > tr > td {
    display: flex;
    gap: 0.6rem;
    align-items: baseline;
    border: 0 !important;
    padding: 0.2rem 0;
    text-align: left !important;
  }

  table.ld-stack > tbody > tr > td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 5.5rem;
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ld-text-muted);
  }

  /* The first cell is the card's heading — the thing you scan for. */
  table.ld-stack > tbody > tr > td:first-child {
    display: block;
    font-weight: 600;
    margin-bottom: 0.35rem;
  }
  table.ld-stack > tbody > tr > td:first-child::before { content: none; }

  /* An empty-state row spans every column and must not be dressed as a card. */
  table.ld-stack > tbody > tr:has(> td[colspan]) {
    display: block;
    border: 0;
    padding: 0;
  }
}
