/* FILE: assets/style.css */

* { box-sizing: border-box; }

/* Sep 2: smooth-scrolls any in-page jump link (e.g. Orders page's "Materials
   catalog / Vendors" quick links) instead of snapping straight there. */
html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: #0f1115;
  color: #f2f3f5;
  min-height: 100vh;
}

main {
  max-width: 420px;
  margin: 0 auto;
  padding: 32px 20px;
}

h1 { font-size: 28px; margin-bottom: 4px; }
.subtitle { color: #9aa0a8; margin-top: 0; }

/* Oct 11, James: the logo graphic (assets/images/logo-nav.png) has a
   transparent background drawn for a light surface — sitting directly on
   this app's dark page background made it look unfinished, most visibly
   on the pre-login screens (Login, Signup — views/login.php,
   views/signup.php) where it's the first thing anyone sees before a
   prospect like Matt even gets into the app. A plain white rounded card
   behind just the logo, sized to hug it with a little breathing room,
   rather than touching the logo file itself — .auth-logo-wrap had no
   styling at all until now, so the logo was sitting bare against #0f1115.
   inline-block (not centered) so it lines up with the rest of the
   form's left edge, same as "Company name" etc. below it. */
.auth-logo-wrap {
  display: inline-block;
  background: #ffffff;
  padding: 12px 18px;
  border-radius: 10px;
  margin-bottom: 16px;
}
.auth-logo-wrap img { display: block; }

form { display: flex; flex-direction: column; gap: 6px; margin-top: 24px; }

label { font-size: 14px; color: #c3c7cd; margin-top: 12px; }

input {
  font-size: 18px;
  padding: 14px;
  border-radius: 10px;
  border: 1px solid #3a3f47;
  background: #1a1d23;
  color: #f2f3f5;
}

button {
  margin-top: 24px;
  font-size: 18px;
  font-weight: 600;
  padding: 16px;
  border-radius: 12px;
  border: none;
  background: #2f6fed;
  color: white;
  cursor: pointer;
}

button:disabled { background: #3a3f47; color: #8b909a; cursor: not-allowed; }

.error { color: #ff6b6b; }
.success { color: #6fce8f; }
.note { color: #9aa0a8; font-size: 14px; }

.dashboard { text-align: center; }
.greeting { font-size: 20px; margin-bottom: 32px; }

.record-btn {
  display: block;
  width: 100%;
  padding: 28px;
  font-size: 20px;
  font-weight: 600;
  border-radius: 16px;
  border: none;
  background: #2f6fed;
  color: white;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  /* Aug 31: explicit background/color/border here are a superset of what
     the global `button` rule already gives the #recordBtn element (no
     visual change there) — added so this class also renders correctly on
     the new dashboard's <a class="record-btn"> "New Report" CTA, which
     doesn't get any of button's built-in styling for free. */
}

/* Aug 31: dashboard.php overview — the 2x2 (4-across on desktop) stat
   tiles for both the office/admin portfolio view and the per-job view. */
.dashboard-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin: 20px 0;
}

@media (min-width: 700px) {
  .dashboard-cards {
    grid-template-columns: repeat(4, 1fr);
  }
}

.dashboard-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 18px 10px;
  border-radius: 12px;
  border: 1px solid #3a3f47;
  background: #1a1d23;
  text-decoration: none;
  color: #f2f3f5;
}

.dashboard-card-number {
  font-size: 28px;
  font-weight: 700;
  color: #6ea0ff;
}

.dashboard-card-label {
  font-size: 13px;
  color: #9aa0a8;
  margin-top: 4px;
  text-align: center;
}

/* Sep 1: project detail rework — header band + stat strip (reusing
   .dashboard-cards/.dashboard-card above) + this 2-column grid for the
   Team/Crew/Cost codes/QR sections below it. Single column on mobile,
   same breakpoint as .wide-main since this only ever appears inside one. */
.project-detail-header {
  margin-bottom: 8px;
}

.project-detail-meta {
  color: #9aa0a8;
  font-size: 14px;
  margin: 2px 0;
}

.project-detail-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
  align-items: start;
}

@media (min-width: 700px) {
  .project-detail-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.dashboard a { color: #6ea0ff; }

/* .dashboard a above (class+tag) outranks .record-btn/.dashboard-card's own
   color on specificity alone, which was muting the "New Report" CTA's white
   text and the stat tiles' colors on the new dashboard overview — restore
   them explicitly for anchors specifically. */
.dashboard a.record-btn { color: white; }
.dashboard a.dashboard-card { color: #f2f3f5; }

/* Sep 8: the multi-project dashboard picker — James wanted it "roomyer,"
   so this is deliberately bigger than a form-field select (.field-wrap
   select above): taller padding, larger text, and a custom chevron since
   appearance:none drops the browser's own arrow. Sits in its own bordered
   box (unlike .field-wrap's bare underline-only inputs) so it reads as a
   standalone control at the top of the page, not part of a form. */
.dashboard-project-picker-wrap {
  text-align: left;
  margin-bottom: 20px;
  padding: 14px 16px;
  border-radius: 12px;
  border: 1px solid #3a3f47;
  background: #1a1d23;
}

.dashboard-project-picker-wrap .field-label {
  margin-bottom: 6px;
}

.dashboard-project-picker {
  display: block;
  width: 100%;
  padding: 14px 40px 14px 14px;
  font-size: 17px;
  font-weight: 600;
  border-radius: 10px;
  border: 1px solid #3a3f47;
  background-color: #22262d;
  color: #f2f3f5;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='8' viewBox='0 0 14 8'%3E%3Cpath d='M1 1l6 6 6-6' stroke='%239aa0a8' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  cursor: pointer;
}

.dashboard-project-picker:focus {
  outline: none;
  border-color: #2f6fed;
}

.transcript-box {
  width: 100%;
  min-height: 140px;
  margin-top: 20px;
  padding: 14px;
  font-size: 16px;
  border-radius: 10px;
  border: 1px solid #3a3f47;
  background: #1a1d23;
  color: #f2f3f5;
  resize: vertical;
}

.secondary-btn {
  width: 100%;
  margin-top: 16px;
  padding: 14px;
  font-size: 16px;
  border-radius: 12px;
  background: #1a1d23;
  border: 1px solid #3a3f47;
  color: #f2f3f5;
}

.secondary-btn:disabled { color: #5a5f68; }

.review-heading {
  text-align: left;
  font-size: 18px;
  margin: 28px 0 12px;
}

.field-wrap {
  text-align: left;
  margin-bottom: 14px;
}

.field-label {
  display: block;
  font-size: 13px;
  color: #9aa0a8;
  margin-bottom: 4px;
}

.field-wrap textarea,
.field-wrap input,
.field-wrap select,
.array-row input,
.array-row select {
  width: 100%;
  font-size: 15px;
  padding: 10px;
  border-radius: 8px;
  border: 1px solid #3a3f47;
  background: #1a1d23;
  color: #f2f3f5;
}

.array-section {
  text-align: left;
  border: 1px solid #3a3f47;
  border-radius: 12px;
  padding: 12px;
  margin-bottom: 16px;
}

.array-section legend {
  padding: 0 6px;
  color: #c3c7cd;
  font-size: 14px;
}

.array-row {
  border-top: 1px solid #262a31;
  padding-top: 10px;
  margin-top: 10px;
}

.array-row:first-child { border-top: none; margin-top: 0; }

.array-row .field-wrap { margin-bottom: 8px; }

.checkbox-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: #c3c7cd;
}

.remove-row-btn {
  background: none;
  border: none;
  color: #ff8b8b;
  font-size: 13px;
  padding: 4px 0;
}

.add-row-btn {
  width: 100%;
  margin-top: 8px;
  padding: 10px;
  border-radius: 8px;
  border: 1px dashed #3a3f47;
  background: none;
  color: #6ea0ff;
  font-size: 14px;
}

.approve-btn {
  width: 100%;
  margin-top: 8px;
  padding: 16px;
  border-radius: 12px;
  font-size: 16px;
  font-weight: 600;
  background: #1f7a3f;
  color: white;
  border: none;
}

.approve-btn:disabled { background: #2a3a2f; color: #6b8f77; }

/* history + detail views */

.back-link { text-align: left; margin: 0 0 8px; }
.back-link a { color: #6ea0ff; text-decoration: none; }

a.secondary-btn {
  display: block;
  text-decoration: none;
  text-align: center;
}

.edit-report-link { margin-bottom: 20px; }

.history-heading {
  text-align: left;
  font-size: 24px;
  margin: 4px 0 20px;
}

.history-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 25px; /* added directly on the live site by James (Aug 31) — noted here so this file matches production and a future re-upload doesn't drop it */
}

.history-item {
  display: block;
  text-align: left;
  padding: 14px;
  border-radius: 12px;
  border: 1px solid #3a3f47;
  background: #1a1d23;
  text-decoration: none;
  color: #f2f3f5;
}

/* Sep 9: this class's own `display: block` above is an author-stylesheet
   rule, which beats the browser's built-in `[hidden] { display: none }`
   UA rule regardless of selector order/specificity (author styles always
   outrank user-agent styles for a normal-priority declaration) — so
   `<div class="history-item" hidden>` was silently staying visible.
   Found via the Projects page's new search filter (views/projects.php),
   which toggles `.hidden` on these via JS; needed wherever `hidden` gets
   set on an element that also carries its own `display` rule. */
.history-item[hidden] {
  display: none;
}

.history-item-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.history-date { font-weight: 600; font-size: 15px; }

.history-excerpt {
  margin: 8px 0 0;
  color: #c3c7cd;
  font-size: 14px;
}

/* Sep 2: per-revision diff list inside the report detail page's "View
   history" toggle (views/record_detail.php / lib/report_revisions.php). */
.revision-diff-list {
  margin: 8px 0 0;
  padding-left: 18px;
  color: #c3c7cd;
  font-size: 13px;
}

.revision-diff-list li {
  margin-bottom: 4px;
}

.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  text-transform: capitalize;
  background: #2a3a2f;
  color: #6fce8f;
  white-space: nowrap;
}

.badge-approved { background: #2a3a2f; color: #6fce8f; }
.badge-approved_amended { background: #2a3a2f; color: #6fce8f; }
.badge-pending_review { background: #3a3320; color: #e0b95c; }
.badge-draft { background: #2a2d33; color: #9aa0a8; }
.badge-severe { background: #3a2020; color: #ff8b8b; }
.badge-moderate { background: #3a3320; color: #e0b95c; }
.badge-minor { background: #2a2d33; color: #9aa0a8; }
.badge-none { background: #2a2d33; color: #9aa0a8; }

.detail-section {
  text-align: left;
  margin-bottom: 20px;
}

.detail-heading {
  font-size: 15px;
  color: #9aa0a8;
  margin: 0 0 8px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.detail-text {
  margin: 0;
  font-size: 16px;
  line-height: 1.5;
}

.detail-list-item {
  display: block;
  padding: 10px 0;
  border-top: 1px solid #262a31;
  font-size: 15px;
}

.detail-list-item:first-child { border-top: none; }

/* Sep 18, James: "more defined areas for upcoming deliveries, daily
   reports, delays, unreconciled, etc." — .detail-section itself has no
   visual treatment (used all over the app for plain in-page sections that
   shouldn't look boxed, e.g. record detail's body text), so this is a
   dashboard-scoped modifier class rather than a change to .detail-section
   itself. Reuses the exact same "standalone panel" look already
   established elsewhere in the app (.dashboard-card, .array-section,
   .history-item, .dashboard-project-picker-wrap) instead of inventing a
   new one — see views/dashboard.php, applied alongside .detail-section on
   each of its info blocks. */
.dashboard-panel {
  border: 1px solid #3a3f47;
  border-radius: 12px;
  background: #1a1d23;
  padding: 16px 18px;
}

/* Sep 1: certifications-as-toggle-lines on the Employee/Sub View page —
   collapsed by default to just the cert name + status badge, expanding to
   show the file link/notes/remove button. Keeps a worker with several
   certs readable as a quick scan instead of a wall of detail per cert. */
.cert-toggle-row summary {
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.cert-toggle-row summary::-webkit-details-marker { color: #9aa0a8; }
.cert-toggle-row[open] summary { margin-bottom: 8px; }

.detail-subtext {
  margin: 6px 0 0;
  color: #9aa0a8;
  font-size: 14px;
}

.email-gc-link {
  margin-top: 12px;
  border-color: #6ea0ff;
  color: #6ea0ff;
  font-weight: 600;
}

/* nav + footer */

.app-nav {
  max-width: 420px;
  margin: 0 auto;
  background: #14161b;
  border-bottom: 1px solid #262a31;
}

.app-nav-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px;
}

.app-nav-brand {
  font-weight: 700;
  font-size: 18px;
  color: #f2f3f5;
  text-decoration: none;
  letter-spacing: 0.02em;
}

.app-nav-toggle {
  background: none;
  border: none;
  color: #f2f3f5;
  font-size: 22px;
  margin: 0;
  padding: 4px 8px;
  cursor: pointer;
}

.app-nav-menu {
  display: flex;
  flex-direction: column;
  padding: 4px 20px 14px;
}

.app-nav-menu[hidden] { display: none; }

.app-nav-link {
  display: block;
  padding: 10px 4px;
  color: #c3c7cd;
  text-decoration: none;
  font-size: 15px;
  border-bottom: 1px solid #1e2127;
}

.app-nav-link.active {
  color: #6ea0ff;
  font-weight: 600;
}

.app-nav-logout {
  color: #ff8b8b;
  border-bottom: none;
}

.app-nav-soon {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 4px;
  color: #5a5f68;
  font-size: 15px;
  border-bottom: 1px solid #1e2127;
}

.app-nav-soon em {
  font-style: normal;
  font-size: 11px;
  color: #4a4f57;
  border: 1px solid #333842;
  border-radius: 999px;
  padding: 2px 8px;
}

/* Aug 31: nav dropdown groups (Reports/Workforce/Admin), plain <details>/
   <summary> — see views/partials/nav.php's header comment. Base rules here
   cover mobile (an expand-in-place accordion section); the ≥700px block
   below turns the same markup into a floating dropdown panel instead. */
.app-nav-group summary {
  list-style: none;
  cursor: pointer;
}

.app-nav-group summary::-webkit-details-marker { display: none; }

.app-nav-group-label::after {
  content: '▾';
  margin-left: 6px;
  font-size: 11px;
  opacity: 0.7;
}

.app-nav-group[open] .app-nav-group-label::after { content: '▴'; }

.app-nav-group-items {
  display: flex;
  flex-direction: column;
  padding-left: 14px;
}

.app-nav-project {
  display: block;
  padding: 6px 20px 12px;
  margin-top: -4px;
  font-size: 13px;
  color: #9aa0a8;
  text-decoration: none;
}

/* Aug 31: desktop nav. Same breakpoint/max-width as .wide-main so the
   header lines up with the wide admin pages underneath it. .app-nav has
   three direct children in the markup — .app-nav-bar (brand + ☰ toggle),
   the optional .app-nav-project link, and .app-nav-menu — turning .app-nav
   itself into a wrapping flex row lays all three out inline instead of
   stacked. The toggle button is simply hidden and the menu's [hidden]
   attribute is overridden to always show — no JS changes needed, since the
   toggle script only ever flips that attribute, and it's harmless for it
   to keep doing so off-screen on a desktop-width window. */
@media (min-width: 700px) {
  .app-nav {
    max-width: 1100px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px 16px;
    padding: 10px 24px;
  }

  .app-nav-bar {
    padding: 0;
    flex: 0 0 auto;
  }

  .app-nav-toggle { display: none; }

  .app-nav-project {
    padding: 0;
    margin-top: 0;
    flex: 0 0 auto;
  }

  .app-nav-menu,
  .app-nav-menu[hidden] {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    padding: 0;
    gap: 2px;
    flex: 1 1 auto;
  }

  .app-nav-link,
  .app-nav-soon {
    padding: 8px 10px;
    border-radius: 8px;
    border-bottom: none;
    font-size: 14px;
  }

  .app-nav-link:hover { background: #1e2127; }
  .app-nav-link.active { background: #1a2740; }

  .app-nav-logout { margin-left: auto; }

  /* Nav dropdown groups become real floating menus at desktop width —
     .app-nav-group-items is taken out of flow via position:absolute so an
     open dropdown never reflows the rest of the top-level nav row (see the
     base rules above this media query for the mobile accordion version). */
  .app-nav-group { position: relative; }

  .app-nav-group-items {
    padding-left: 0;
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 4px;
    background: #14161b;
    border: 1px solid #262a31;
    border-radius: 8px;
    padding: 6px;
    min-width: 190px;
    z-index: 50;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  }

  .app-nav-group[open] .app-nav-group-items { display: flex; }

  .app-nav-group-items .app-nav-link,
  .app-nav-group-items .app-nav-soon {
    width: 100%;
  }
}

.app-footer {
  max-width: 420px;
  margin: 24px auto 0;
  padding: 16px 20px 32px;
  text-align: center;
  color: #5a5f68;
  font-size: 12px;
}

/* Oct 11: Getting Started checklist (new-company-admin onboarding) — see
   lib/onboarding.php, views/dashboard.php. Reuses .dashboard-panel/
   .detail-section/.detail-heading/.link-button for the panel itself
   (same "standalone box" look as every other dashboard panel); these are
   just the per-step row + its done/not-done circle. */
.onboarding-step {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-top: 1px solid #262a31;
  color: #f2f3f5;
  text-decoration: none;
  font-size: 15px;
}

.onboarding-step:first-of-type { border-top: none; }

.onboarding-step-done { color: #9aa0a8; }

.onboarding-check {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid #3a3f47;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
}

.onboarding-step-done .onboarding-check {
  background: #2a3a2f;
  border-color: #2a3a2f;
  color: #6fce8f;
}

/* Oct 11: /help — numbered steps inside each .cert-toggle-row accordion
   (views/help.php). Plain <ol>, just given the same body-text color/
   spacing as the rest of the app's note/detail text instead of the
   browser's bare default list. */
.help-steps {
  margin: 10px 0 0;
  padding-left: 22px;
  font-size: 15px;
  line-height: 1.5;
}

.help-steps li {
  margin-bottom: 8px;
}

.help-steps li:last-child { margin-bottom: 0; }

/* Oct 11, James: "we need to have a desktop view as well... most field
   people will be using on tablet" — /help was stacking its topic cards in
   one column no matter how wide the screen got once it picked up
   .wide-main (see views/help.php). This gives it a real 2-column layout
   at the same 700px breakpoint .wide-main itself switches at, so a tablet
   or desktop screen actually uses the extra width instead of just
   stretching one narrow column across it. Each .dashboard-panel inside
   already carries its own margin-bottom (see .detail-section above) —
   zeroed out here since the grid's own gap does that job once there are
   columns to gap between. */
.help-topics {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.help-topics .detail-section { margin-bottom: 0; }

@media (min-width: 700px) {
  .help-topics {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: start;
    gap: 20px;
  }
}

/* Oct 11: /admin-help — reuses .help-topics/.dashboard-panel/
   .cert-toggle-row wholesale (same look as /help), just grouped under a
   category heading per section instead of one flat list. Margin-top on
   every section but the first, so the page doesn't start with a stray gap
   above "Getting Started". */
.admin-help-category:not(:first-child) { margin-top: 28px; }

/* communications */

.email-context-box { margin-bottom: 20px; }

.email-item { display: block; }

.email-recipient {
  margin: 6px 0 0;
  font-size: 15px;
  font-weight: 600;
}

.email-subject {
  margin: 2px 0 0;
  font-size: 14px;
  color: #c3c7cd;
}

.flash-success {
  color: #6fce8f;
  background: #16241c;
  border: 1px solid #2a3a2f;
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 14px;
  margin-bottom: 16px;
}

.flash-error {
  color: #ff8b8b;
  background: #241616;
  border: 1px solid #3a2a2a;
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 14px;
  margin-bottom: 16px;
}

/* projects */

.project-add-link { margin-bottom: 20px; }

.project-item-current {
  border-color: #6ea0ff;
}

.project-item-actions {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
  font-size: 14px;
}

.project-item-actions a { color: #6ea0ff; text-decoration: none; }

/* Sep 1: certifications section (Employee/Sub View pages) — a plain-text
   "Remove" action next to a cert record needs to look like the .project-
   item-actions links above it, but it's a real <form>/<button> (a GET link
   would let a crawler/prefetch trigger a delete), so it needs its own
   reset rather than inheriting button chrome. */
.link-btn {
  background: none;
  border: none;
  padding: 0;
  color: #6ea0ff;
  font-size: 14px;
  text-decoration: none;
  cursor: pointer;
}

/* Aug 31: /delays list — assign dropdown + resolve button sitting side by
   side on each delay card, neither full-width like the page's default
   .secondary-btn/select sizing (fine for a single standalone control, not
   for two small ones next to each other). */
.delay-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
}

.delay-actions select {
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid #3a3f47;
  background: #1a1d23;
  color: #f2f3f5;
  font-size: 14px;
}

.delay-actions .secondary-btn {
  width: auto;
  margin-top: 0;
  padding: 8px 16px;
  font-size: 14px;
}

/* A <button> styled to sit inline like the links above, for actions that
   have to be a POST (state-changing) rather than a plain <a> GET link —
   e.g. the Team page's "resend invite / reset link" action. */
.link-button {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: #6ea0ff;
  text-decoration: none;
  cursor: pointer;
}

.project-current-label {
  color: #6fce8f;
  font-weight: 600;
}

/* photos */

.photo-upload-box { margin-bottom: 24px; }

.photo-date-heading {
  text-align: left;
  font-size: 16px;
  color: #c3c7cd;
  margin: 24px 0 10px;
}

.photo-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-bottom: 8px;
}

.photo-grid-inline {
  grid-template-columns: repeat(3, 1fr);
  margin-top: 10px;
}

/* Sep 18, James: "add desktop/tablet view" — views/photos.php now sits in
   .wide-main, so its grid gets more columns once there's room instead of
   staying capped at mobile's 3-across. Own class (combined with
   .photo-grid, never replacing it) rather than changing .photo-grid
   itself, since .photo-grid-inline above also builds on that same base
   class at report/record-detail's normal narrower width — this leaves
   that usage completely untouched. */
@media (min-width: 700px) {
  .photo-grid.photo-grid-wide { grid-template-columns: repeat(5, 1fr); }
}

@media (min-width: 1000px) {
  .photo-grid.photo-grid-wide { grid-template-columns: repeat(6, 1fr); }
}

.photo-thumb {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid #3a3f47;
  cursor: zoom-in;
}

.photo-lightbox-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
  z-index: 1000;
  align-items: center;
  justify-content: center;
  padding: 24px;
  cursor: zoom-out;
}

.photo-lightbox-overlay.is-open { display: flex; }

.photo-lightbox-img {
  max-width: 100%;
  max-height: 100%;
  border-radius: 8px;
}

.photo-card { text-align: left; }

.photo-context {
  margin: 6px 0 0;
  font-size: 13px;
  color: #9aa0a8;
}

.photo-context a { color: #6ea0ff; }

.photo-caption-text {
  margin: 4px 0 0;
  font-size: 14px;
}

.photo-caption-edit-btn {
  background: none;
  border: none;
  color: #6ea0ff;
  font-size: 12px;
  padding: 4px 0;
}

.photo-add-inline-label {
  display: inline-block;
  margin-top: 12px;
  padding: 8px 14px;
  border-radius: 8px;
  border: 1px dashed #3a3f47;
  color: #6ea0ff;
  font-size: 14px;
  cursor: pointer;
}

/* time tracking */

.qr-code-image {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
  background: #fff;
  padding: 8px;
}

.clock-page {
  max-width: 480px;
}

.clock-confirm {
  border: 1px solid #3a3f47;
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 16px;
  text-align: left;
}

.clock-confirm-text {
  font-size: 17px;
  margin: 0 0 8px;
}

.time-day-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

/* Aug 29 fix: .secondary-btn defaults to width:100%, meant for a single
   standalone button in the app's normal 420px-wide pages. Inside this nav
   row on a wide desktop page (.wide-main), that made each button balloon
   to claim huge amounts of space and squeezed the date/label between them
   down to almost nothing. Buttons here size to their own text instead;
   the middle label/date-picker takes whatever room is left and centers. */
.time-day-nav > a.secondary-btn {
  width: auto;
  flex: 0 0 auto;
  white-space: nowrap;
}

.time-day-nav .time-day-jump,
.time-day-nav .time-week-range-label {
  flex: 1;
  margin: 0;
  text-align: center;
}

.time-day-jump input {
  width: auto;
  max-width: 180px;
  margin: 0 auto;
  display: block;
}

/* Aug 29: running total for whichever week the strip above is showing —
   sits right under the date range in the Prev/Next week nav, so flipping
   weeks updates both together. */
.time-week-total {
  display: block;
  margin-top: 2px;
  color: #6ea0ff;
  font-weight: 600;
}

.time-day-row { text-align: left; }

.time-day-summary {
  cursor: pointer;
  list-style: revert;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 12px;
}

.time-day-summary .history-item-top {
  flex: 1;
  min-width: 200px;
  margin: 0;
}

.time-day-body { margin-top: 12px; }

/* Aug 29 fix: .punch-edit-row is itself a <form>, and the global `form`
   rule above sets flex-direction:column for every form in the app. That
   column direction was never overridden here, so this row's fields have
   actually been stacking vertically (each one growing tall via flex:1 on
   what was really the main/vertical axis) since this form was first
   built — just easy to miss at the old narrow 420px width. Explicit
   row direction restores the intended single-line layout. */
.punch-edit-row {
  display: flex;
  flex-direction: row;
  gap: 10px;
  align-items: flex-end;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

/* These fields used to be flex:1, which (once flex-direction is correctly
   row) grows each one to fill all remaining row width — harmless in the
   old 420px-max container, but leaves huge empty gaps once this row can
   sit inside the wider .wide-main desktop layout (see the /time
   redesign). Sizing to a fixed-ish width instead keeps Job/Clock in/Clock
   out/Save sitting compactly together on desktop; on a narrow phone the
   row still wraps onto its own lines (flex-wrap was already set). */
.punch-edit-row .field-wrap { flex: 0 1 250px; min-width: 190px; margin-bottom: 0; }

.punch-edit-row .secondary-btn {
  width: auto;
  flex: 0 0 auto;
  margin-top: 0;
  align-self: flex-end;
  padding: 10px 20px;
}

/* "Punch N of M" caption (see views/time_employee.php) — only rendered on
   a day with more than one punch. Without this override, the row's own
   .array-row top divider would land BETWEEN the label and its fields,
   splitting them apart instead of reading as one grouped block. */
.punch-index-label { margin: 16px 0 4px; text-align: left; }
.punch-index-label + .punch-edit-row { border-top: none; padding-top: 0; margin-top: 0; }

.time-split-form { margin-top: 12px; }

/* Aug 30: flags a split line that came in from an employee's self-serve
   clock-out submission and hasn't been through a foreman's Save yet (see
   handlers/time_allocation_save.php's status logic). Same divider-
   suppression trick as .punch-index-label above, so the label reads as
   attached to its own row instead of split off by the row's top border.
   Sep 18: was a direct-adjacent (+) selector, but views/time_employee.php
   now sometimes renders a "Scope logged as: ..." <p class="detail-subtext">
   between the banner and .split-line (moved out of the Scope field's own
   label, which was misaligning it) — switched to the general sibling (~)
   combinator so the divider still gets suppressed whether or not that
   extra line is present. */
.review-needed-label { margin: 16px 0 4px; text-align: left; color: #e0b95c; }
.review-needed-label ~ .split-line { border-top: none; padding-top: 0; margin-top: 0; }

/* Sep 18, James: "needs padding below... and different color to stand
   out more" — was reusing .detail-subtext (plain gray, no bottom
   spacing, blends into regular note text). Own class instead: blue
   accent (#6ea0ff, the same "highlighted info" color used elsewhere —
   .time-week-total, badge-confirmed, link text) so it's visually
   distinct from the amber "needs review" banner above it rather than
   competing with it, plus real spacing below before the Job/Scope/Hours
   row starts. */
.review-needed-subtext {
  margin: 2px 0 12px;
  color: #6ea0ff;
  font-size: 14px;
  font-weight: 600;
}
.split-line-pending { background: rgba(224, 185, 92, 0.06); border-radius: 8px; padding: 10px; }

.split-line {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.split-line .field-wrap { flex: 1; min-width: 120px; }

/* Aug 31: per-punch "View location" map (views/time_employee.php) — sits
   right under a punch-edit-row, so it gets its own small top gap rather
   than the .array-row divider treatment (this div isn't an .array-row).
   The button is deliberately NOT full-width like the default .secondary-btn
   — same override reasoning as .punch-edit-row .secondary-btn above. */
.punch-location { margin: 4px 0 14px; text-align: left; }
.punch-location .secondary-btn {
  width: auto;
  margin-top: 0;
  padding: 8px 16px;
  font-size: 14px;
}
.punch-map {
  height: 240px;
  margin-top: 10px;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid #3a3f47;
}

/* Aug 31: the location-disclosure line on the public clock page reads more
   like a notice than a plain instruction, so it gets a little visual
   separation instead of blending into the regular .note styling. */
.clock-location-disclosure {
  border: 1px solid #3a3f47;
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 16px;
}

/* wide pages — desktop gets to use more of the screen; mobile keeps the
   same feel as every other page. First real use of this, Aug 29: the
   /time day/week/employee views, since James flagged that an
   office-desktop-heavy page like this one specifically needs real table
   width to be usable at all, not just "nice to have." Other pages are
   untouched — this is opt-in via a second class on <main>, not a change
   to the global 420px default. */
.wide-main {
  max-width: 420px;
}

@media (min-width: 700px) {
  .wide-main {
    max-width: 1100px;
  }
}

/* Oct 22, James: "not just wide, full screen" — for the handful of pages
   where even .wide-main's 1100px cap still feels cramped (the scopes
   import preview screen, which needs its Description column genuinely
   readable next to a now-wider Cost code column — see .cost-code-select
   below). Own opt-in class, same shape as .wide-main above, just with no
   upper cap at desktop width — a little side padding instead of a max-
   width so it isn't flush against the browser edge. Doesn't touch
   .wide-main or anything using it. */
.full-main {
  max-width: 420px;
}

@media (min-width: 700px) {
  .full-main {
    max-width: 100%;
    padding-left: 32px;
    padding-right: 32px;
  }
}

/* Sep 9: Projects page — the existing mobile card list stays exactly as it
   was, a real .time-table takes over on desktop (denser, sortable, easier
   to scan 30+ jobs than a column of cards). Same 700px breakpoint as
   .wide-main above, since this only ever appears inside one. */
.projects-desktop-table { display: none; }

@media (min-width: 700px) {
  .projects-mobile-list { display: none; }
  .projects-desktop-table { display: block; }
}

.projects-sortable {
  cursor: pointer;
  user-select: none;
}

.projects-sortable:hover { color: #c3c7cd; }

.projects-sortable::after {
  content: '';
  display: inline-block;
  width: 0;
  height: 0;
  margin-left: 5px;
  vertical-align: middle;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  opacity: 0.35;
}

.projects-sortable.sort-asc::after {
  border-bottom: 5px solid #f2f3f5;
  opacity: 1;
}

.projects-sortable.sort-desc::after {
  border-top: 5px solid #f2f3f5;
  opacity: 1;
}

/* Sep 18, James: "most work will be done on a tablet in the field... let's
   add desktop/tablet view" to the list-style admin pages that never got
   the treatment Projects got on Sep 9 (.projects-mobile-list /
   .projects-desktop-table below) — same mobile-card-list-vs-desktop-table
   split, generalized under page-agnostic names so every one of these pages
   can reuse it instead of each inventing its own. Projects itself keeps
   its original .projects-* classes, untouched, to avoid any risk of
   touching its own JS (search/sort) which targets those class names. */
.desktop-table-view { display: none; }

@media (min-width: 700px) {
  .mobile-list-view { display: none; }
  .desktop-table-view { display: block; }
}

/* Sep 18: for pages built out of several SHORT lists side by side (Company:
   divisions, departments, offices, payroll profiles, trade codes) rather
   than one long list — a full desktop table per sub-list would be
   overkill for lists that are often only a handful of items. This keeps
   the existing .history-list card markup as-is and just lets it flow into
   multiple columns once there's room, instead of one column of cards
   stretched uncomfortably wide across a 1100px .wide-main. */
@media (min-width: 700px) {
  .history-list-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
  }
}

/* Sep 9: .tab-buttons (shared with /cost-codes) has no CSS of its own
   today — its links inherit .secondary-btn's default width:100%, which is
   fine stacked on the app's normal 420px pages but wastes most of a
   .wide-main desktop page as a column of oversized buttons. Same
   auto-width-row fix as .time-day-nav > a.secondary-btn above, just
   scoped to the desktop breakpoint so nothing changes on mobile or on
   Cost Codes (which never goes wide-main). */
@media (min-width: 700px) {
  .tab-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }

  .tab-buttons > a.secondary-btn {
    width: auto;
    flex: 0 0 auto;
  }
}

.time-view-toggle {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}

.time-view-tab {
  flex: 1;
  text-align: center;
  padding: 10px;
  border-radius: 10px;
  border: 1px solid #3a3f47;
  color: #c3c7cd;
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
}

.time-view-tab-active {
  background: #1a2740;
  border-color: #2f6fed;
  color: #6ea0ff;
}

.time-filter-input {
  display: block;
  width: 100%;
  margin-bottom: 12px;
}

.time-table-wrap {
  overflow-x: auto;
  border: 1px solid #3a3f47;
  border-radius: 12px;
}

.time-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  white-space: nowrap;
}

.time-table th, .time-table td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid #262a31;
}

/* Sep 2: James on the materials import preview — a long Description
   pushed Cost code off screen, and since .time-table-wrap's horizontal
   scrollbar sits at the bottom of the whole (often tall) table, reaching
   it meant scrolling all the way down, over, then back up just to see
   which rows still needed a cost code. Capping Description's width (with
   the full text still available as a title tooltip, same pattern already
   used for the Cost code select's shortened options) keeps the whole
   row — including Cost code — inside view without any horizontal scroll
   in the common case, rather than trying to chase the scrollbar.
   Narrowed further, 320px -> 240px, once Materials picked up Pending and
   Remaining columns and got crowded again — same tooltip fallback. */
.time-table-desc {
  display: inline-block;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}

/* Oct 22, James: "the issue was we need to see the full description and
   the full cost code" — on the import-preview screens specifically,
   hover-only (the .time-table-desc truncate-plus-title pattern above)
   wasn't enough; he wants the actual text on screen. Modifier class, used
   in place of .time-table-desc only on those two import-preview tables
   (full-main now gives them the width to afford it) — every other place
   .time-table-desc is used (Manage Scopes' own lists, etc.) keeps the
   original truncate-with-tooltip behavior untouched. */
.time-table-desc-full {
  display: block;
  max-width: none;
  overflow: visible;
  text-overflow: unset;
  white-space: normal;
  word-break: break-word;
}

.time-table th {
  color: #9aa0a8;
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  background: #14161b;
  position: sticky;
  top: 0;
}

.time-table tbody tr:last-child td { border-bottom: none; }

.time-table tbody tr:hover { background: #171a20; cursor: pointer; }

.time-table a { color: #6ea0ff; text-decoration: none; }

.time-table-name,
.time-table th:first-child {
  position: sticky;
  left: 0;
  background: #1a1d23;
  font-weight: 600;
  z-index: 1;
}

.time-table th:first-child { background: #14161b; z-index: 2; }

.time-table tbody tr:hover .time-table-name { background: #171a20; }

.time-table-today { color: #6ea0ff !important; }

/* Sep 1: a <select> dropped straight into a .time-table cell (Manage
   Scopes' inline Cost code picker, the import preview's per-row picker)
   has no .field-wrap/.array-row ancestor, so it never picks up this app's
   normal styled-select look and renders as a bare, unconstrained-width
   browser default — cramped and cut off by the table's own horizontal
   scroll long before you'd expect. This gives it the same visual
   treatment directly, capped to a sane width so one wide dropdown can't
   blow out an entire row. */
.time-table select {
  width: 100%;
  max-width: 190px;
  padding: 6px 8px;
  border-radius: 6px;
  border: 1px solid #3a3f47;
  background: #1a1d23;
  color: #e8e9eb;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Oct 22, James: "the dropdown show cost code description at least on
   desktop" — the Cost code picker above now renders "CODE — Description"
   instead of just the bare code (see views/project_scopes.php), but
   .time-table select's unconditional 190px cap was built back when the
   option text was always short (just a code like "01.3113") and would
   still truncate the longer text badly. Own class on just the cost-code
   <select>s (Manage Scopes' inline picker on both Labor and Materials
   tabs, plus the per-row picker on both import-preview screens) rather
   than loosening .time-table select generally, which plenty of OTHER
   inline table dropdowns still want capped tight. Mobile keeps the
   original 190px (unchanged, same cramped-but-workable tradeoff as
   before). Desktop drops the cap entirely rather than just raising it —
   James's follow-up ("need to see the full description and the full cost
   code") made clear a bigger-but-still-truncating width wasn't the ask;
   width:auto sizes the box to whatever the selected option's text
   actually needs, and .time-table-wrap's existing overflow-x:auto is
   there as a safety net on an unusually long name. */
@media (min-width: 700px) {
  .time-table select.cost-code-select {
    width: auto;
    max-width: none;
  }
}

.time-table .link-btn { font-size: 13px; }

/* Sep 2: the "apply a cost code to every checked row" bulk control on the
   scope/material import preview screens was sitting in a plain .array-row
   with an inline align-items:flex-end that did nothing — .array-row has no
   flex layout of its own, so the select and the Apply button just stacked
   full-width/oversized (the button in particular, since .secondary-btn is
   width:100% by default, meant for a standalone mobile action button, not
   a compact inline control). Scoped class instead of changing .array-row
   generally, which plenty of other stacked-vertically forms rely on. */
.bulk-apply-row {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  flex-wrap: wrap;
}

.bulk-apply-row .field-wrap {
  flex: 1;
  min-width: 220px;
  margin-bottom: 0;
}

.bulk-apply-row .secondary-btn {
  width: auto;
  margin-top: 0;
  white-space: nowrap;
}

/* Sep 1: Progress page — each scope line's qty/hours numbers and bars now
   render right on the row (not hidden behind a click), per James's ask. */
.progress-row-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.progress-metric { margin-bottom: 8px; }

.progress-metric-label {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  color: #9aa0a8;
  margin-bottom: 4px;
}

.progress-bar-track {
  background: #20232a;
  border-radius: 6px;
  height: 8px;
  overflow: hidden;
}

.progress-bar-fill {
  height: 100%;
  background: #6ea0ff;
  border-radius: 6px;
}

.progress-bar-fill.is-over { background: #e0b95c; }

/* Sep 1: /certifications — a row with at least one EXPIRED (not just
   expiring-soon) cert gets a red-tinted left border/background on top of
   its normal badge coloring, so it visually jumps out at a glance across a
   long worker or certification-type list, not just readable one badge at a
   time. Reuses .time-table's existing structure — just an accent on top. */
.cert-row-expired td {
  background: rgba(255, 139, 139, 0.06);
  border-left: 3px solid #ff8b8b;
}
.cert-row-expired td:first-child { padding-left: 9px; }
.cert-row-expired.time-table-row:hover td { background: rgba(255, 139, 139, 0.12); }
.cert-row-expired .time-table-name { background: rgba(255, 139, 139, 0.06); }
.cert-row-expired.time-table-row:hover .time-table-name { background: rgba(255, 139, 139, 0.12); }

.time-week-strip {
  display: flex;
  gap: 6px;
  margin-bottom: 16px;
  overflow-x: auto;
}

.time-week-strip-day {
  flex: 1;
  min-width: 60px;
  text-align: center;
  padding: 8px 4px;
  border-radius: 10px;
  border: 1px solid #3a3f47;
  text-decoration: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.time-week-strip-day-active {
  background: #1a2740;
  border-color: #2f6fed;
}

.time-week-strip-dow { font-size: 11px; text-transform: uppercase; color: #9aa0a8; }
.time-week-strip-date { font-size: 13px; font-weight: 600; color: #f2f3f5; }
.time-week-strip-hours { font-size: 12px; color: #6ea0ff; }

/* Aug 31: subcontractor tracking — public clock-page language toggle. Kept
   tiny and unobtrusive (top-right-ish, above the heading) since it's a
   convenience for a shared jobsite device, not a primary action. */
.clock-lang-toggle {
  text-align: right;
  margin: 0 0 8px;
  font-size: 13px;
}
.clock-lang-toggle a { color: #9aa0a8; text-decoration: none; }
.clock-lang-toggle a.clock-lang-active { color: #6ea0ff; font-weight: 600; }

/* Aug 31 follow-up: the sub review action on /subs is an <a> styled like
   .approve-btn (an inline "Review & approve" link on that one row, not a
   full-width form submit like the other .approve-btn uses) — needs its own
   text-decoration/display reset the same way a.secondary-btn already has,
   since the plain .approve-btn rule was only ever written for <button>. */
a.approve-btn {
  text-decoration: none;
  display: inline-block;
  text-align: center;
}

/* Aug 31: order status badges (project_delays already covers open/resolved
   via badge-pending_review/badge-approved, reused for sent/delivered below;
   these two are new). */
.badge-confirmed { background: #1a2740; color: #6ea0ff; }
.badge-cancelled { background: #2a2d33; color: #ff8b8b; }

/* Aug 31: order builder — tap-to-pick catalog chips (views/order_form.php,
   assets/order-form.js). Chips are always a shortcut on top of a plain text
   field, never the only way in — see order-form.js's header comment. */
.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 6px;
}

.chip-btn {
  background: #1c1f25;
  border: 1px solid #333842;
  color: #c3c7cd;
  border-radius: 999px;
  padding: 6px 12px;
  font-size: 13px;
  cursor: pointer;
}

.chip-btn-active {
  background: #1a2740;
  border-color: #6ea0ff;
  color: #6ea0ff;
  font-weight: 600;
}

.catalog-item-list {
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid #262a31;
  border-radius: 8px;
  padding: 6px;
  margin-bottom: 4px;
}

.catalog-item-btn {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-bottom: 1px solid #1e2127;
  color: #f2f3f5;
  padding: 10px 6px;
  font-size: 14px;
  cursor: pointer;
}

.catalog-item-btn:last-child { border-bottom: none; }
.catalog-item-btn:hover { background: #1c1f25; }

.order-line-row [data-size-input],
.order-line-row [data-gauge-input] {
  margin-top: 2px;
}

/* Sep 2: color-code a material line's Remaining-to-order number so status
   is visible at a glance instead of everyone doing the Adjusted Order Qty
   minus Delivered math by eye — James: "no change for something that
   hasn't been order[ed]... yellow for items that have partially been
   delivered, and green for all have been ordered... red if we go over."
   Reuses the exact same green/yellow/red already used for order status
   badges (.badge-approved/.badge-pending_review/.badge-severe) rather than
   inventing a new palette. */
.remaining-partial { color: #e0b95c; font-weight: 600; }
.remaining-complete { color: #6fce8f; font-weight: 600; }
.remaining-over { color: #ff8b8b; font-weight: 600; }