/* Reset */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--mn-font-sans);
  color: var(--mn-text);
  background: var(--mn-bg);
  font-size: 15px;
  line-height: 1.5;
  font-feature-settings: "cv11", "ss01"; /* Inter: rounded a + alt 6/9 */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
a { color: var(--mn-navy); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Numeric columns (dollars, miles, counts) align cleanly */
.numeric, .submission-totals, .day-distance, .total-miles, .total-owed,
.payroll-row-numbers, .kpi-value, td.right, th.right {
  font-variant-numeric: tabular-nums;
}

/* Headings inherit Inter and tighten up */
h1, h2, h3, h4 {
  color: var(--mn-text-strong);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.25;
}

/* App header */
.app-header {
  background: var(--mn-navy);
  color: white;
  padding: var(--mn-space-3) var(--mn-space-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky; top: 0; z-index: 10;
}
.app-header h1 { margin: 0; font-size: 18px; font-weight: 600; }
/* user-meta is a link to the user's profile page. Styled to match the
   adjacent btn-ghost buttons (Show me around / Sign out) so the three
   header affordances read as a uniform cluster — same padding, same
   border-radius, same translucent fill on hover. The .user-meta--static
   variant turns off the hover affordance for the profile page itself,
   where the link points at the page you're already on. */
.app-header .user-meta {
  font-family: inherit;
  font-size: 13px;
  font-weight: inherit;
  color: inherit;
  opacity: .85;
  background: none;
  border: 0;
  padding: 6px 10px;
  border-radius: var(--mn-radius-sm);
  cursor: pointer;
  letter-spacing: inherit;
  text-decoration: none;
  transition: background-color 120ms ease, opacity 120ms ease;
}
.app-header .user-meta:hover {
  opacity: 1;
  background: rgba(255, 255, 255, 0.14);
}
.app-header .user-meta:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.6);
  outline-offset: 2px;
}
.app-header .user-meta--static { cursor: default; }
.app-header .user-meta--static:hover { background: none; opacity: .85; }
.app-header .actions { display: flex; gap: var(--mn-space-2); align-items: center; }

/* Brand lockup in the app header (logo + role label) */
.app-brand {
  display: flex;
  align-items: center;
  gap: var(--mn-space-3);
  margin: 0;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: white;
}
.app-brand img {
  display: block;
  height: 28px;
  width: auto;
}
.app-brand .role-label {
  font-size: 14px;
  font-weight: 500;
  opacity: 0.9;
  padding-left: var(--mn-space-3);
  border-left: 1px solid rgba(255, 255, 255, 0.25);
}
/* Brand wraps an anchor so clicking the logo returns to the role's home
   page — important on the profile screen where there's otherwise no
   obvious way back to the dashboard except the small back link. The
   negative margin offsets the padding so the click area is generous
   without shifting the visual position of the logo. */
.app-brand a {
  display: inline-flex;
  align-items: center;
  gap: var(--mn-space-3);
  color: white;
  text-decoration: none;
  padding: 4px 8px;
  margin: -4px -8px;
  border-radius: var(--mn-radius-sm);
  transition: background-color 120ms ease;
}
.app-brand a:hover { background: rgba(255, 255, 255, 0.14); }
.app-brand a:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.6);
  outline-offset: 2px;
}

/* Mobile header: collapse the role descriptor and the action button text
   labels so the brand, user name, and two icon buttons fit cleanly on a
   phone-width viewport. font-size: 0 hides the text node while the SVG
   icons keep their explicit width/height attributes (and we bump them
   up to 18px so they read as proper touch-target icons). */
@media (max-width: 640px) {
  .app-header {
    padding: var(--mn-space-3);
  }
  .app-header .actions { gap: var(--mn-space-1); }
  .app-header .user-meta { margin-right: var(--mn-space-2); }
  .app-brand .role-label { display: none; }
  .app-header #tour-btn,
  .app-header #sign-out-btn {
    font-size: 0;
    gap: 0;
    padding: 8px;
  }
  .app-header #tour-btn svg,
  .app-header #sign-out-btn svg {
    width: 18px;
    height: 18px;
  }

  /* Filter / people tab strips: switch from multi-row wrap to a single
     swipe-scrollable row. Keeps every option reachable without eating
     three rows of vertical space on a phone. Scrollbar is hidden for a
     clean look; scroll-snap nudges each pill into place when flicked. */
  .filter-tabs, .people-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
  }
  .filter-tabs::-webkit-scrollbar,
  .people-tabs::-webkit-scrollbar {
    display: none;
  }
  .filter-tab, .people-tab {
    flex-shrink: 0;
    scroll-snap-align: start;
  }

  /* Mobile-only touch-target bump for the month nav buttons. 38px is fine
     for desktop pointers; mobile thumbs need ≥44 per Apple HIG / WCAG. */
  .month-nav-btn {
    width: 44px;
    height: 44px;
  }

  /* Admin submission cards: allow the right-side cluster (totals + badges
     + chevron) to wrap so labels like "Cleared for Payment" don't get
     truncated by the card's overflow:hidden. */
  .submission-header { flex-wrap: wrap; }
  .submission-meta-right { flex-wrap: wrap; }

  /* Calculator hero: stack the rate + button vertically on phone. */
  .calc-hero { flex-direction: column; align-items: stretch; }
  .calc-hero-actions { align-self: flex-start; }

  /* Composition list: collapse the wide row into stacked rows on phone
     so categories, amounts, and formulas stay readable. */
  .calc-composition-item {
    grid-template-columns: 14px 1fr auto;
    grid-template-areas:
      "swatch label   amount"
      ".      share   permile"
      ".      formula formula";
    row-gap: 2px;
  }
  .calc-composition-item .calc-composition-share   { text-align: left; min-width: 0; }
}

/* Honor the user's OS-level reduced-motion preference. Disables transitions,
   animations, and CSS-driven smooth-scroll. JS-driven scrollIntoView /
   scrollTo calls also check this media query at call time and pass
   behavior:"auto" instead of "smooth". */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Logo on the sign-in / claim cards */
.login-logo {
  display: block;
  height: 72px;
  width: auto;
  margin: 0 auto var(--mn-space-4);
}

/* Container */
.container { max-width: 1100px; margin: 0 auto; padding: var(--mn-space-4); }
.container--narrow { max-width: 560px; }

/* Card */
.card {
  background: var(--mn-card);
  border-radius: var(--mn-radius);
  box-shadow: var(--mn-shadow-card);
  padding: var(--mn-space-4);
  margin-bottom: var(--mn-space-4);
}

/* Form controls */
label {
  display: block;
  font-size: 13px;
  font-weight: 500;
  color: var(--mn-text-muted);
  margin-bottom: var(--mn-space-1);
  letter-spacing: 0.01em;
}
input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="date"], select, textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius-sm);
  font: inherit;
  background: white;
  color: var(--mn-text);
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
input:hover, select:hover, textarea:hover {
  border-color: var(--mn-border-strong);
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--mn-navy);
  box-shadow: var(--mn-ring);
}
/* Sighted cue for the fields JS marks aria-invalid (e.g. the end-odometer
   input). The :focus rule has to be repeated in danger colours or the border
   goes navy again the moment the user clicks back into the bad field. */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-color: var(--mn-danger);
}
input[aria-invalid="true"]:focus, select[aria-invalid="true"]:focus, textarea[aria-invalid="true"]:focus {
  border-color: var(--mn-danger);
  box-shadow: var(--mn-ring-danger);
}
.field { margin-bottom: var(--mn-space-3); }
.field-row { display: flex; gap: var(--mn-space-3); flex-wrap: wrap; }
.field-row > .field { flex: 1 1 140px; }

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--mn-space-2);
  padding: 9px 16px;
  border-radius: var(--mn-radius-sm);
  border: 1px solid var(--mn-border);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  background: white;
  color: var(--mn-text);
  transition: background-color 120ms ease, border-color 120ms ease,
              box-shadow 120ms ease, transform 60ms ease;
}
.btn:hover { background: var(--mn-bg-subtle); border-color: var(--mn-border-strong); }
.btn:active { transform: translateY(0.5px); }
/* Focus indicator.
   The soft ring alone was ~1.4:1 against the page, well under the 3:1 minimum for
   a visible focus indicator, and `outline: none` removed the only fallback — so
   keyboard users had no reliable idea where they were. The ring is kept as the
   soft halo it was designed to be, and a real 2px navy outline carries the
   contrast (navy on Paper is ~9:1). Offset so it reads outside the button edge
   rather than merging with the border. */
.btn:focus-visible {
  outline: 2px solid var(--mn-navy);
  outline-offset: 2px;
  box-shadow: var(--mn-ring);
}
.btn-primary { background: var(--mn-navy); color: white; border-color: var(--mn-navy); }
.btn-primary:hover { background: var(--mn-navy-dark); border-color: var(--mn-navy-dark); }
.btn-danger  { color: var(--mn-danger); border-color: var(--mn-danger); }
.btn-danger:hover { background: var(--mn-danger-bg); border-color: var(--mn-danger); }
.btn-danger:focus-visible { outline-color: var(--mn-danger); box-shadow: var(--mn-ring-danger); }
.btn-ghost   { background: transparent; border-color: transparent; color: white; }
.btn-ghost:hover { background: rgba(255,255,255,.14); border-color: transparent; }

/* Light focus outline for controls sitting on a navy surface, where the navy
   outline above is invisible. White on navy is ~9.9:1.
   Scoped by CONTAINER, not by button variant. Keying this off .btn-ghost was
   wrong: that variant is also used on the page background (profile.html's Back
   link), where a white outline measures 1.07:1 — worse than the low-contrast
   ring it was meant to replace. What decides the outline colour is what is
   behind the control, not which variant it is. */
.app-header .btn:focus-visible,
.summary .btn:focus-visible,
.payroll-footer .btn:focus-visible {
  outline-color: white;
}
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn[disabled]:hover { background: white; border-color: var(--mn-border); }
.btn-block { width: 100%; }
.btn-sm { padding: 6px 10px; font-size: 13px; }

/* Badges - subtle pill with colored status dot */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px 3px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 500;
  background: var(--mn-bg-subtle);
  color: var(--mn-text);
  border: 1px solid var(--mn-border);
  text-transform: capitalize;
  letter-spacing: 0;
  white-space: nowrap;
  line-height: 1.4;
}
.badge::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--mn-text-muted);
  flex-shrink: 0;
}
.badge-draft::before              { background: #929497; }
.badge-submitted::before          { background: var(--mn-navy); }
.badge-approved::before           { background: var(--mn-success); }
.badge-flagged::before            { background: var(--mn-warn); }
.badge-rejected::before           { background: var(--mn-danger); }
.badge-paid::before               { background: #6b46c1; }
.badge-ready_for_payroll::before  { background: #0891b2; }
.badge-admin_review::before       { background: #ea580c; }
.badge-reopen::before             { background: #d97706; }
.badge-supplemental::before       { background: #4f46e5; }

/* Banners */
.banner {
  border-radius: var(--mn-radius-sm);
  padding: var(--mn-space-3) var(--mn-space-4);
  margin-bottom: var(--mn-space-4);
  border: 1px solid transparent;
  font-size: 14px;
}
.banner-warn  { background: var(--mn-warn-bg);   border-color: #f6d089; color: var(--mn-warn); }
.banner-info  { background: var(--mn-info-bg);   border-color: #b9cde9; color: var(--mn-navy); }
.banner-error { background: var(--mn-danger-bg); border-color: #f1b3b1; color: var(--mn-danger); }
.banner strong { display: block; margin-bottom: var(--mn-space-1); }
.banner .banner-link {
  color: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.banner .banner-link:hover { text-decoration-thickness: 2px; }

/* The .pwd-dialog rules that used to sit here were removed with
   assets/js/password-change.js (2026-07-21). That modal was never wired into any
   page; the live change-password flow is the inline expand/collapse form in
   profile.html driven by profile.js:wirePasswordForm. */

/* Reopen request — tech-form card + manager/admin banner */
.reopen-card {
  border-left: 4px solid var(--mn-info);
}
.reopen-card h3 { color: var(--mn-navy); }
.reopen-banner .row { flex-wrap: wrap; gap: var(--mn-space-2); }

/* Submission picker — tech form chip row for switching between regular
   and supplemental submissions in the same month. */
#submission-picker {
  background: var(--mn-card);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius);
  padding: var(--mn-space-3) var(--mn-space-4);
  margin-bottom: var(--mn-space-4);
}
.submission-picker {
  display: flex;
  align-items: center;
  gap: var(--mn-space-2);
  flex-wrap: wrap;
}
.submission-picker-label {
  font-size: 12px;
  color: var(--mn-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
  margin-right: var(--mn-space-2);
}
.submission-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: white;
  border: 1px solid var(--mn-border);
  border-radius: 999px;
  padding: 6px 12px;
  font: inherit;
  cursor: pointer;
  color: var(--mn-text);
}
.submission-pill:hover { background: #f1f2f4; }
.submission-pill.is-active {
  background: var(--mn-navy);
  color: white;
  border-color: var(--mn-navy);
}
.submission-pill.is-active .badge {
  background: rgba(255, 255, 255, 0.2);
  color: white;
}
.submission-pill.is-add {
  border-style: dashed;
  color: var(--mn-navy);
}
.submission-pill.is-add:hover {
  background: var(--mn-info-bg);
}

/* Sibling-locked day cards (already claimed by another submission for
   this same tech-month). Compact, read-only, dimmed. */
.day-card.is-sibling-locked {
  background: #fafafb;
  border-style: dashed;
  opacity: 0.85;
}
.day-card.is-sibling-locked .day-header {
  margin-bottom: 0;
}
.day-card.is-sibling-locked .sibling-tag {
  font-size: 12px;
  color: var(--mn-text-muted);
  font-weight: 400;
  margin-left: 4px;
}

/* Day cards (technician form) */
.day-list { display: flex; flex-direction: column; gap: var(--mn-space-3); }
.day-card {
  background: var(--mn-card);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius);
  padding: var(--mn-space-3) var(--mn-space-4);
}
.day-card.is-empty { opacity: .9; border-style: dashed; }
.day-card.is-locked { background: #f5f6f7; }

/* Month nav: prev/next buttons flanking the month select (YNAB-style).
   Buttons share the form's rounded-square aesthetic for visual cohesion
   with the native <select> they wrap. */
.month-nav {
  display: flex;
  align-items: stretch;
  gap: var(--mn-space-2);
}
.month-nav-select {
  flex: 1;
  min-width: 0;
}
.month-nav-btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  background: white;
  color: var(--mn-navy);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius-sm);
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
.month-nav-btn:hover:not(:disabled) {
  background: var(--mn-bg-subtle);
  border-color: var(--mn-border-strong);
}
.month-nav-btn:disabled {
  color: var(--mn-text-muted);
  background: var(--mn-bg-subtle);
  cursor: not-allowed;
  opacity: 0.5;
}

/* Back-to-top floating action button. Sits above the sticky reimbursement
   bar so it never overlaps the Submit button. */
.back-to-top {
  position: fixed;
  /* Sits above the sticky summary bar, whose height is measured at runtime and
     published as --mn-summary-h (see technician.js). The old hard-coded 80px was
     the desktop height of that bar; on phones it stacks into totals + save-state
     + a full-width Submit and grows well past that, so the button landed on top
     of the reimbursement total. The 80px fallback keeps the previous behaviour if
     the measurement has not run yet. */
  bottom: calc(var(--mn-space-3) + var(--mn-summary-h, 80px));
  right: var(--mn-space-4);
  z-index: 100;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 999px;
  background: var(--mn-navy);
  color: white;
  border: 1px solid var(--mn-navy);
  box-shadow: var(--mn-shadow-elev);
  cursor: pointer;
  transition: background-color 120ms ease, transform 120ms ease;
}
.back-to-top:hover {
  background: var(--mn-navy-dark);
  border-color: var(--mn-navy-dark);
  transform: translateY(-2px);
}
.back-to-top.hidden { display: none; }
/* Today indicator — inset shadow keeps the card's footprint stable
   instead of nudging the layout when the marker appears/disappears. */
.day-card.is-today { box-shadow: inset 3px 0 0 var(--mn-navy); }
.day-today-pill {
  display: inline-block;
  margin-left: var(--mn-space-2);
  padding: 1px 8px;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: white;
  background: var(--mn-navy);
  border-radius: 999px;
  vertical-align: 2px;
}
.day-card .day-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: var(--mn-space-2);
  gap: var(--mn-space-3);
}
.day-card .day-title { font-weight: 600; }
.day-card .day-title .dow { color: var(--mn-text-muted); margin-right: var(--mn-space-2); font-weight: 400; }
.day-card .day-distance {
  color: var(--mn-text-muted);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.day-card .day-body { display: none; }
.day-card.is-open .day-body { display: block; }

/* Saved + collapsed day: compact, read-only summary with an Edit affordance. */
.day-card.is-collapsed .day-header { margin-bottom: 0; }
.day-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--mn-space-3);
  margin-top: var(--mn-space-2);
}
.day-summary-detail {
  font-size: 13px;
  color: var(--mn-text-muted);
  min-width: 0;
  overflow-wrap: anywhere;
}
.day-summary .day-edit-btn { flex: 0 0 auto; }

/* Field-level odometer error — calm validation: shown on blur / Save, cleared
   the instant the readings become consistent. */
.day-error {
  margin-top: var(--mn-space-2);
  padding: var(--mn-space-2) var(--mn-space-3);
  font-size: 13px;
  color: var(--mn-danger);
  background: var(--mn-danger-bg);
  border-radius: var(--mn-radius-sm);
}
/* The day error and day warning slots are ARIA live regions, so they must stay in
   the accessibility tree even while empty. `display: none` and `visibility: hidden`
   remove a node from that tree entirely, so a slot hidden either way is not
   registered while it is hidden.

   Why that is fatal HERE specifically, and not for the app's other banners: the
   rule is politeness-dependent. A role="alert" (assertive) region IS announced when
   it enters the tree already populated, which is why showBanner's set-text-then-
   unhide pattern works on #error-banner. A role="status" (polite) region is NOT
   reliably announced that way; it has to be registered first and changed after. The
   day-warning slot is polite by design (an anomaly is advisory and must not
   interrupt a tech mid-keystroke), so it can only ever announce if it is already in
   the tree when the text arrives. These collapse geometrically to guarantee that,
   and neither slot may carry the global .hidden class.

   Do not "tidy" this into display:none. The markup would still look correct and the
   warning would silently stop announcing. */
.day-error:empty,
.day-warning:empty {
  margin: 0;
  padding: 0;
  border: 0;
  height: 0;
  overflow: hidden;
}

/* Save-state chip in the sticky summary bar (auto-save feedback). Lives on the
   navy bar, so light text; failure uses a soft light-red for contrast. */
.summary-actions { display: flex; flex-direction: column; align-items: flex-end; gap: var(--mn-space-1); }
.save-state { font-size: 12px; color: rgba(255, 255, 255, 0.72); min-height: 15px; text-align: right; }
.save-state.is-failed { color: #ffd9d6; font-weight: 500; }
/* Unfinished day kept in local storage. A light amber, NOT var(--mn-warn) (#a35d00):
   that token is a dark amber meant for paper backgrounds and fails contrast on this
   navy bar — the same trap documented at renderRateEstimateNote. */
.save-state.is-draft { color: #ffe3b3; font-weight: 500; }

/* Payroll history (audit trail on the admin Payroll tab). */
.payroll-history { margin-top: var(--mn-space-4); }
.payroll-history-title { margin: 0 0 4px; font-size: 16px; }
.payroll-history-sub { margin: 0 0 12px; font-size: 13px; max-width: 70ch; }
.payroll-history-scroll { overflow-x: auto; }
.payroll-history-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.payroll-history-table th, .payroll-history-table td {
  text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--mn-border); white-space: nowrap;
}
.payroll-history-table th {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--mn-text-muted); font-weight: 600;
}
.payroll-history-table td.num, .payroll-history-table th.num {
  text-align: right; font-variant-numeric: tabular-nums;
}
.payroll-history-table tr:last-child td { border-bottom: 0; }
.payroll-event-entered { background: var(--mn-success-bg); color: var(--mn-success); }
.payroll-event-cleared { background: var(--mn-bg-subtle); color: var(--mn-text-muted); }

/* Payroll history — one collapsible summary row per submission. */
.ph-list { display: flex; flex-direction: column; gap: 8px; max-height: 460px; overflow-y: auto; padding-right: 2px; }
.ph-row { border: 1px solid var(--mn-border); border-radius: var(--mn-radius-sm); background: var(--mn-card); }
.ph-head {
  width: 100%; display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  padding: 10px 12px; background: none; border: 0; font: inherit; text-align: left; cursor: pointer;
  border-radius: var(--mn-radius-sm);
}
.ph-head:hover { background: #fafafb; }
.ph-head:focus-visible { outline: 2px solid var(--mn-navy); outline-offset: -2px; }
.ph-worker { font-weight: 600; }
.ph-month { font-size: 13px; color: var(--mn-text-muted); }
.ph-amount { font-variant-numeric: tabular-nums; font-weight: 500; }
.ph-meta { font-size: 12.5px; color: var(--mn-text-muted); margin-left: auto; }
.ph-chev { color: var(--mn-text-muted); transition: transform .15s ease; }
.ph-row.is-open .ph-chev { transform: rotate(90deg); }
.ph-detail { display: none; padding: 0 12px 10px; overflow-x: auto; }
.ph-row.is-open .ph-detail { display: block; }
.ph-detail .payroll-history-table td, .ph-detail .payroll-history-table th { padding: 6px 10px; }

/* Audit trails (admin Audit tab, plus the day-change block inside an expanded
   submission card). Prefix ae-, because audit-trail / audit-list / audit-note
   are already taken by the per-submission approvals list further down this file
   and those two surfaces are different things.

   Deliberately its own block rather than extra selectors bolted onto the .ph-*
   rules above. The visual language is the same on purpose (same card, same
   collapsible row, same table), but the payroll rules are commented as being
   about payroll and one of the two will need to move eventually. Around forty
   lines of duplication is a cheaper debt than a rule that silently governs two
   unrelated screens. */
.audit-toolbar-card { display: flex; align-items: flex-start; gap: var(--mn-space-4); }
.ae-lead { margin: 0; font-size: 13px; max-width: 80ch; }
.audit-toolbar-card .btn { flex: 0 0 auto; }

.ae-card { margin-bottom: var(--mn-space-4); }
.ae-title { margin: 0 0 4px; font-size: 16px; }
.ae-sub { margin: 0 0 12px; font-size: 13px; max-width: 80ch; }
.ae-none { margin: 12px 0 0; font-size: 13px; }
.ae-fine { font-size: 12px; margin-top: 2px; }
/* A recorded system write is a real value, not a missing one, so it reads as
   ordinary muted text rather than as the em-dash empty-cell placeholder. */
.ae-actor-system { color: var(--mn-text-muted); font-style: italic; }

.ae-scroll { overflow-x: auto; }
.ae-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.ae-table th, .ae-table td {
  text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--mn-border);
  vertical-align: top;
}
.ae-table th {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--mn-text-muted); font-weight: 600; white-space: nowrap;
}
.ae-table tr:last-child td { border-bottom: 0; }
/* Only the timestamp is pinned to one line. The change and reason columns carry
   sentences and a diff list, and nowrapping those is what turns an audit table
   into a horizontal scroll nobody reads. */
.ae-table td.ae-when { white-space: nowrap; color: var(--mn-text-muted); }
.ae-table td.ae-note { max-width: 42ch; }
/* pre-wrap so a doubled space inside a note shows as one; collapsed whitespace
   made "up  parts -> up parts" print identical on both sides. */
.ae-diff { font-variant-numeric: tabular-nums; white-space: pre-wrap; }
.ae-diff + .ae-diff { margin-top: 2px; }

.ae-reopen-granted::before { background: var(--mn-success); }
.ae-reopen-denied::before  { background: var(--mn-danger); }

/* One collapsible row per changed day, inside the submission detail. */
.ae-list { display: flex; flex-direction: column; gap: 8px; max-height: 460px; overflow-y: auto; padding-right: 2px; }
.ae-row { border: 1px solid var(--mn-border); border-radius: var(--mn-radius-sm); background: var(--mn-card); }
.ae-head {
  width: 100%; display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  padding: 10px 12px; background: none; border: 0; font: inherit; text-align: left; cursor: pointer;
  border-radius: var(--mn-radius-sm);
}
.ae-head:hover { background: #fafafb; }
.ae-head:focus-visible { outline: 2px solid var(--mn-navy); outline-offset: -2px; }
.ae-day { font-weight: 600; font-variant-numeric: tabular-nums; }
.ae-meta { font-size: 12.5px; color: var(--mn-text-muted); margin-left: auto; }
.ae-chev { color: var(--mn-text-muted); transition: transform .15s ease; }
.ae-row.is-open .ae-chev { transform: rotate(90deg); }
.ae-detail { display: none; padding: 0 12px 10px; overflow-x: auto; }
.ae-row.is-open .ae-detail { display: block; }
.ae-detail .ae-table td, .ae-detail .ae-table th { padding: 6px 10px; }

/* A run of autosaves drawn as one change (collapseSaveBursts in admin-audit.js):
   the span under the timestamp, and the individual saves behind a <details>. */
.ae-burst-span { font-size: 12px; margin-top: 2px; }
.ae-burst { margin-top: 6px; }
.ae-burst summary { cursor: pointer; font-size: 12.5px; color: var(--mn-navy); }
.ae-burst summary:focus-visible { outline: 2px solid var(--mn-navy); outline-offset: 2px; }
.ae-burst-list { margin: 6px 0 0; padding-left: 20px; }
.ae-burst-list li + li { margin-top: 6px; }
.ae-burst-time { font-size: 12px; color: var(--mn-text-muted); font-variant-numeric: tabular-nums; }

/* The day-change block sits inside an expanded submission card, below the
   approvals trail, so it takes the same inset treatment .audit-trail does. */
.ae-block {
  margin-top: var(--mn-space-4);
  padding: var(--mn-space-3) var(--mn-space-4);
  background: white;
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius-sm);
}
.ae-block-title {
  margin: 0 0 var(--mn-space-2);
  color: var(--mn-text-muted);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.unit-toggle { display: inline-flex; border: 1px solid var(--mn-border); border-radius: var(--mn-radius-sm); overflow: hidden; }
.unit-toggle button {
  background: white; border: 0; padding: 8px 14px; cursor: pointer; font: inherit;
  border-right: 1px solid var(--mn-border);
}
.unit-toggle button:last-child { border-right: 0; }
.unit-toggle button.is-active { background: var(--mn-navy); color: white; }

.customer-row {
  display: flex;
  gap: var(--mn-space-2);
  margin-bottom: var(--mn-space-2);
  align-items: flex-start;
}
.customer-row input { flex: 1 1 auto; }
.customer-row input.ticket { flex: 0 1 140px; }
.customer-row button { flex: 0 0 auto; }
.customer-name-col { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0; }
.customer-name-wrap { position: relative; }
.customer-name-wrap input { width: 100%; }

.day-actions { display: flex; gap: var(--mn-space-2); margin-top: var(--mn-space-2); }
.day-actions .spacer { flex: 1; }

/* Sticky summary */
.summary {
  position: sticky; bottom: 0;
  background: var(--mn-navy);
  color: white;
  padding: var(--mn-space-3) var(--mn-space-4);
  /* Clear the iOS home indicator when the page opts into viewport-fit=cover. */
  padding-bottom: calc(var(--mn-space-3) + env(safe-area-inset-bottom));
  border-radius: var(--mn-radius);
  margin-top: var(--mn-space-4);
  display: flex; align-items: center; justify-content: space-between; gap: var(--mn-space-3);
  box-shadow: 0 -4px 16px rgba(22, 50, 88, .25);
}
.summary .totals { display: flex; gap: var(--mn-space-5); flex-wrap: wrap; }
.summary .totals .label { font-size: 12px; opacity: .8; text-transform: uppercase; letter-spacing: .04em; }
.summary .totals .value { font-size: 18px; font-weight: 600; font-variant-numeric: tabular-nums; }

/* Login screen */
.login-screen { min-height: 100dvh; display: flex; align-items: center; justify-content: center; padding: var(--mn-space-4); }
.login-card { background: white; border-radius: var(--mn-radius); box-shadow: var(--mn-shadow-card); padding: var(--mn-space-5); width: 100%; max-width: 380px; }
.login-card h1 { margin: 0 0 var(--mn-space-2); color: var(--mn-navy); font-size: 22px; }
.login-card .subtitle { margin: 0 0 var(--mn-space-4); color: var(--mn-text-muted); font-size: 14px; }

/* Utility */
.muted { color: var(--mn-text-muted); }
.spacer { flex: 1; }
.row { display: flex; align-items: center; gap: var(--mn-space-3); }
.hidden { display: none !important; }
.center { text-align: center; }

/* Segmented control - shared by filter-tabs and people-tabs */
.filter-tabs, .people-tabs {
  display: inline-flex;
  background: var(--mn-bg-subtle);
  border: 1px solid var(--mn-border);
  border-radius: 8px;
  padding: 3px;
  gap: 0;
  flex-wrap: wrap;
  max-width: 100%;
}
.filter-tab, .people-tab {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 5px 12px;
  font: inherit;
  font-weight: 500;
  font-size: 13px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--mn-text-muted);
  transition: background-color 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.filter-tab:hover, .people-tab:hover {
  color: var(--mn-text);
}
.filter-tab.is-active, .people-tab.is-active {
  background: var(--mn-card);
  color: var(--mn-text-strong);
  border-color: var(--mn-border);
  box-shadow: 0 1px 2px rgba(14, 20, 34, 0.06);
}
.filter-tab .count, .people-tab .count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 18px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--mn-bg);
  color: var(--mn-text-muted);
  font-size: 11px;
  font-weight: 600;
}
.filter-tab.is-active .count, .people-tab.is-active .count {
  background: var(--mn-info-bg);
  color: var(--mn-navy);
}

/* Manager queue — submission cards */
.submission-card {
  background: var(--mn-card);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius);
  margin-bottom: var(--mn-space-3);
  overflow: hidden;
  transition: box-shadow 0.15s ease;
}
.submission-card.is-expanded { box-shadow: var(--mn-shadow-card); }

.submission-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--mn-space-3);
  padding: var(--mn-space-3) var(--mn-space-4);
  cursor: pointer;
  user-select: none;
}
.submission-header:hover { background: #fafafb; }
.submission-header:focus-visible { outline: 2px solid var(--mn-navy); outline-offset: -2px; }
.submission-meta { flex: 1; min-width: 0; }
.submission-meta-right { display: flex; align-items: center; gap: var(--mn-space-3); }
.submission-totals { font-variant-numeric: tabular-nums; white-space: nowrap; }
.submission-submitted { white-space: nowrap; }
.expand-icon {
  color: var(--mn-text-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.expand-icon svg { display: block; }

/* Generic inline icon helper */
.icon { display: inline-block; vertical-align: middle; flex-shrink: 0; }
svg.icon { color: currentColor; }

/* Skeleton loaders */
@keyframes skeleton-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}
.skeleton {
  display: block;
  background: var(--mn-bg-subtle);
  border-radius: 6px;
  height: 14px;
  animation: skeleton-pulse 1.4s ease-in-out infinite;
}
.skeleton + .skeleton { margin-top: var(--mn-space-2); }
.skeleton-card {
  background: var(--mn-card);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius);
  padding: var(--mn-space-4);
  margin-bottom: var(--mn-space-3);
}
.skeleton-row {
  background: var(--mn-card);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius);
  padding: var(--mn-space-3) var(--mn-space-4);
  margin-bottom: var(--mn-space-2);
}
.skeleton-list { display: block; }
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* Typeahead dropdown */
.typeahead-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 50;
  list-style: none;
  margin: 0;
  padding: 4px;
  background: var(--mn-card);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius-sm);
  box-shadow: var(--mn-shadow-elev);
  max-height: 260px;
  overflow-y: auto;
  font-size: 14px;
}
.typeahead-item {
  padding: 7px 10px;
  border-radius: 4px;
  cursor: pointer;
  color: var(--mn-text);
  /* Wrap, don't truncate: long "Customer - Location" names differ only at the end. */
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.typeahead-item:hover,
.typeahead-item.is-active {
  background: var(--mn-info-bg);
  color: var(--mn-text-strong);
}
.typeahead-item mark {
  background: transparent;
  color: inherit;
  font-weight: 600;
}

/* Fuzzy-match suggestion (Did you mean...?) */
.fuzzy-suggest {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  padding: 6px 10px;
  background: var(--mn-warn-bg);
  border: 1px solid #f6d089;
  border-radius: var(--mn-radius-sm);
  font-size: 13px;
  color: var(--mn-warn);
}
.fuzzy-suggest button {
  background: transparent;
  border: 1px solid var(--mn-warn);
  color: var(--mn-warn);
  border-radius: 4px;
  padding: 2px 8px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
}
.fuzzy-suggest button:hover { background: rgba(163, 93, 0, 0.08); }
.fuzzy-suggest .fuzzy-dismiss {
  margin-left: auto;
  border: 0;
  background: transparent;
  color: var(--mn-warn);
  cursor: pointer;
  padding: 0 4px;
  font-size: 16px;
  line-height: 1;
}

/* Guided tour overlay */
.tour-backdrop {
  /* On spotlighted steps, the cutout's box-shadow does the dimming and
     this backdrop just blocks pointer events. On centered steps (no
     spotlight target), we add `.tour-no-target` and dim the backdrop
     itself so the welcome/centered tooltip still reads as a focused modal. */
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: transparent;
  pointer-events: auto;
  cursor: not-allowed;
}
.tour-backdrop.tour-no-target {
  background: rgba(14, 20, 34, 0.55);
}
.tour-cutout {
  position: fixed;
  z-index: 9001;
  border-radius: 8px;
  pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(14, 20, 34, 0.55);
  transition: top 200ms ease, left 200ms ease, width 200ms ease, height 200ms ease;
}
.tour-tooltip {
  position: fixed;
  z-index: 9002;
  background: var(--mn-card);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius);
  box-shadow: var(--mn-shadow-modal);
  padding: var(--mn-space-4) var(--mn-space-4) var(--mn-space-3);
  width: 360px;
  max-width: calc(100vw - 32px);
  font-family: var(--mn-font-sans);
  color: var(--mn-text);
  transition: top 200ms ease, left 200ms ease;
}
.tour-tooltip.tour-tooltip-centered {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.tour-counter {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--mn-text-muted);
  margin-bottom: var(--mn-space-2);
}
.tour-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--mn-text-strong);
  margin: 0 0 var(--mn-space-2);
  letter-spacing: -0.01em;
}
.tour-body {
  font-size: 14px;
  line-height: 1.5;
  color: var(--mn-text);
  margin: 0 0 var(--mn-space-4);
}
.tour-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--mn-space-2);
}
.tour-nav {
  display: flex;
  gap: var(--mn-space-2);
  margin-left: auto;
}
.tour-skip,
.tour-back,
.tour-next {
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  padding: 6px 12px;
  border-radius: var(--mn-radius-sm);
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}
.tour-skip {
  background: transparent;
  border: 0;
  color: var(--mn-text-muted);
}
.tour-skip:hover { color: var(--mn-text); text-decoration: underline; }
.tour-back {
  background: white;
  border: 1px solid var(--mn-border);
  color: var(--mn-text);
}
.tour-back:hover { background: var(--mn-bg-subtle); border-color: var(--mn-border-strong); }
.tour-next {
  background: var(--mn-navy);
  border: 1px solid var(--mn-navy);
  color: white;
}
.tour-next:hover { background: var(--mn-navy-dark); border-color: var(--mn-navy-dark); }

/* Empty states */
.empty-state {
  background: var(--mn-card);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius);
  padding: var(--mn-space-6) var(--mn-space-4);
  text-align: center;
  margin-bottom: var(--mn-space-3);
}
.empty-state-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--mn-bg-subtle);
  color: var(--mn-text-muted);
  margin-bottom: var(--mn-space-3);
}
.empty-state-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--mn-text-strong);
  margin: 0 0 var(--mn-space-1);
  letter-spacing: -0.01em;
}
.empty-state-body {
  font-size: 13px;
  color: var(--mn-text-muted);
  margin: 0 auto;
  max-width: 360px;
  line-height: 1.5;
}

.submission-detail {
  border-top: 1px solid var(--mn-border);
  padding: var(--mn-space-4);
  background: #fafafb;
}

/* Manager queue — entries table */
.entries-table-wrap {
  overflow-x: auto;
  background: white;
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius-sm);
  margin-bottom: var(--mn-space-3);
}
.entries-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.entries-table th, .entries-table td {
  padding: 8px 12px;
  text-align: left;
  border-bottom: 1px solid var(--mn-border);
  white-space: nowrap;
}
.entries-table th {
  background: #f1f2f4;
  font-weight: 600;
  color: var(--mn-text-muted);
  text-transform: uppercase;
  font-size: 12px;
  letter-spacing: 0.04em;
}
.entries-table tbody tr:last-child td { border-bottom: 0; }
.entries-table .right { text-align: right; font-variant-numeric: tabular-nums; }
.entries-table td:last-child { white-space: normal; }

/* Manager queue — actions */
.submission-actions {
  display: flex;
  gap: var(--mn-space-2);
  margin-top: var(--mn-space-3);
}

.flag-form {
  margin-top: var(--mn-space-3);
  padding: var(--mn-space-3);
  background: white;
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius-sm);
}

/* Right-align utility (used by tables) */
.right { text-align: right; }

/* Per-day inline validation warnings (technician form) */
.day-warning { margin-bottom: var(--mn-space-3); }
.day-warning-item {
  border-radius: var(--mn-radius-sm);
  padding: 6px 10px;
  margin-bottom: 4px;
  font-size: 13px;
  border: 1px solid transparent;
}
.day-warning-item.is-error {
  background: var(--mn-danger-bg);
  color: var(--mn-danger);
  border-color: #f1b3b1;
}
.day-warning-item.is-warn {
  background: var(--mn-warn-bg);
  color: var(--mn-warn);
  border-color: #f6d089;
}

/* Manager view — anomaly indicators on entries table */
.anomaly-banner { margin-bottom: var(--mn-space-3); }
.anomaly-banner .anomaly-list {
  margin: var(--mn-space-2) 0 0 0;
  padding-left: 20px;
  font-size: 13px;
}
.anomaly-banner .anomaly-list li { margin-bottom: 2px; }

.entries-table tr.has-warning {
  background: var(--mn-warn-bg);
}
.entries-table tr.has-warning td {
  border-bottom-color: #f6d089;
}
.entries-table .warning-icon {
  color: var(--mn-warn);
  cursor: help;
  margin-right: 6px;
  display: inline-flex;
  align-items: center;
  vertical-align: -2px;
}
.entries-table .warning-icon svg { display: block; }

/* Admin top-level tabs - workflow (left) + Manage (right), each as a labeled segmented control */
.admin-tabs {
  display: flex;
  gap: var(--mn-space-5);
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
}
.admin-tabs-group {
  display: inline-flex;
  align-items: center;
  gap: var(--mn-space-3);
}
.admin-tabs-pill {
  display: inline-flex;
  align-items: center;
  background: var(--mn-bg-subtle);
  border: 1px solid var(--mn-border);
  border-radius: 8px;
  padding: 3px;
  flex-wrap: wrap;
  gap: 0;
}
.admin-tabs-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--mn-text-muted);
  font-weight: 600;
  line-height: 1;
  user-select: none;
}
@media (max-width: 720px) {
  .admin-tabs { justify-content: flex-start; }
}
.admin-tab {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 6px 14px;
  font: inherit;
  font-weight: 500;
  font-size: 13px;
  cursor: pointer;
  color: var(--mn-text-muted);
  transition: background-color 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.admin-tab:hover { color: var(--mn-text); }
.admin-tab.is-active {
  background: var(--mn-card);
  color: var(--mn-text-strong);
  border-color: var(--mn-border);
  box-shadow: 0 1px 2px rgba(14, 20, 34, 0.06);
}

/* Admin signals banner — info-styled (uses .banner-info colors via the
   shared rule above; this is just a placeholder hook for future tweaks). */
.admin-signals-banner { /* uses .banner-info defaults */ }
.admin-signals-banner .anomaly-list {
  margin: var(--mn-space-2) 0 0 0;
  padding-left: 20px;
  font-size: 13px;
}

/* People sub-tabs (techs / managers / admins) intentionally share the segmented-
   control styling of the Submissions filter tabs — see the combined
   `.filter-tabs, .people-tabs` and `.filter-tab, .people-tab` rules above. No
   separate override here, so the two tab rows look identical. */

.people-toolbar { display: flex; align-items: center; flex-wrap: wrap; }

.people-list { display: flex; flex-direction: column; gap: var(--mn-space-3); }

.person-card {
  background: var(--mn-card);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius);
  padding: var(--mn-space-3) var(--mn-space-4);
}
.person-card.is-inactive { opacity: 0.7; background: var(--mn-bg-subtle); }

/* Collapsible "Deactivated" section at the bottom of the people list */
.deactivated-section {
  margin-top: var(--mn-space-4);
  padding-top: var(--mn-space-3);
  border-top: 1px dashed var(--mn-border);
}
.deactivated-header {
  display: flex;
  align-items: center;
  gap: var(--mn-space-2);
  width: 100%;
  background: transparent;
  border: 0;
  padding: var(--mn-space-2) var(--mn-space-3);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--mn-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  cursor: pointer;
  border-radius: var(--mn-radius-sm);
  transition: background-color 120ms ease, color 120ms ease;
}
.deactivated-header:hover {
  background: var(--mn-bg-subtle);
  color: var(--mn-text);
}
/* Same treatment as .btn, .ph-head and .submission-header: the ring alone was
   ~1.4:1. This is a real focusable button (the People tab's "Deactivated (n)"
   collapsible) but carries no .btn class, so the fix there did not reach it. */
.deactivated-header:focus-visible {
  outline: 2px solid var(--mn-navy);
  outline-offset: 2px;
  box-shadow: var(--mn-ring);
}
.deactivated-header svg { color: var(--mn-text-muted); }
.deactivated-content {
  display: flex;
  flex-direction: column;
  gap: var(--mn-space-3);
  margin-top: var(--mn-space-2);
}

.person-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--mn-space-3);
  flex-wrap: wrap;
}
.person-meta { flex: 1; min-width: 0; }
.person-meta-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  flex-shrink: 0;
}
.person-badges {
  display: flex;
  gap: var(--mn-space-2);
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.person-last-signin {
  font-size: 12px;
  color: var(--mn-text-muted);
  font-variant-numeric: tabular-nums;
}
.person-last-signin.is-never {
  color: var(--mn-warn);
  font-weight: 500;
}

/* "X users have never signed in" summary, top of the People tab */
.people-summary {
  display: flex;
  align-items: flex-start;
  gap: var(--mn-space-2);
  padding: var(--mn-space-3) var(--mn-space-4);
  background: var(--mn-info-bg);
  border: 1px solid #b9cde9;
  border-radius: var(--mn-radius);
  color: var(--mn-navy);
  font-size: 14px;
  margin-bottom: var(--mn-space-3);
}
.people-summary svg { flex-shrink: 0; margin-top: 2px; }

.person-actions {
  display: flex;
  gap: var(--mn-space-2);
  margin-top: var(--mn-space-3);
  flex-wrap: wrap;
}

.person-edit-form {
  margin-top: var(--mn-space-3);
  padding-top: var(--mn-space-3);
  border-top: 1px solid var(--mn-border);
}

/* Reports & analytics */
.reports-filters {
  display: flex;
  gap: var(--mn-space-3);
  flex-wrap: wrap;
  align-items: flex-end;
}
.reports-filters .field { flex: 1 1 180px; margin-bottom: 0; }
.reports-filters .reports-print-field { flex: 0 0 auto; }

.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--mn-space-3);
  margin-bottom: var(--mn-space-4);
}
.kpi-tile {
  background: var(--mn-card);
  border-radius: var(--mn-radius);
  box-shadow: var(--mn-shadow-card);
  padding: var(--mn-space-4);
}
.kpi-tile .kpi-label {
  font-size: 11px;
  color: var(--mn-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
  margin-bottom: 6px;
}
.kpi-tile .kpi-value {
  font-size: 26px;
  font-weight: 700;
  color: var(--mn-navy);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.kpi-tile .kpi-sublabel {
  font-size: 12px;
  color: var(--mn-text-muted);
  margin-top: 4px;
}

.report-card { padding: var(--mn-space-4); }
.report-section-title {
  margin: 0 0 var(--mn-space-3);
  color: var(--mn-navy);
  font-size: 16px;
}

.chart-wrap {
  position: relative;
  height: 320px;
  width: 100%;
}

.report-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius-sm);
}
.report-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.report-table th, .report-table td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid var(--mn-border);
}
.report-table thead th {
  background: #f1f2f4;
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--mn-text-muted);
  white-space: nowrap;
}
.report-table tbody tr:last-child td { border-bottom: 0; }
.report-table .right { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.report-table .report-row { cursor: pointer; transition: background 0.1s ease; }
.report-table .report-row:hover { background: #fafafb; }
.report-table .report-row.is-expanded { background: var(--mn-info-bg); }
.report-table .expand-icon { color: var(--mn-text-muted); display: inline-flex; align-items: center; width: 16px; height: 16px; vertical-align: -3px; margin-right: 4px; }

.drilldown-row { background: #fafafb; }
.drilldown-cell {
  padding: var(--mn-space-3) !important;
  border-bottom: 0 !important;
}

.submission-mini {
  background: white;
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius-sm);
  margin-bottom: var(--mn-space-2);
}
.submission-mini.is-expanded { box-shadow: 0 1px 4px rgba(22, 50, 88, 0.08); }
.submission-mini-header {
  padding: 8px 12px;
  display: flex;
  gap: var(--mn-space-3);
  align-items: center;
  cursor: pointer;
  flex-wrap: wrap;
}
.submission-mini-header:hover { background: #fafafb; }
.submission-mini-header .sm-month { font-weight: 600; }
.submission-mini-header .sm-totals {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}
.submission-mini-detail {
  padding: var(--mn-space-3);
  border-top: 1px solid var(--mn-border);
  background: #fafafb;
}
/* Reports now draws its submission drill-down with the shared entries table
   (submission-detail.js), which brings its own .entries-table-wrap card: white
   fill, border, radius. Here that card lands on the grey .submission-mini-detail
   panel, which is itself inside the bordered white .submission-mini card — a
   third nested surface the Submissions tab and manager queue don't have, where
   the wrap sits directly on one grey panel. Flatten it so the table reads as
   part of the panel. overflow-x is deliberately not touched: the wrap still
   scrolls a wide table instead of stretching the drill-down. */
.submission-mini-detail .entries-table-wrap {
  background: transparent;
  border: 0;
  border-radius: 0;
  margin-bottom: 0;
}

.customer-drilldown-summary {
  margin: 0 0 var(--mn-space-2);
  font-size: 13px;
}

/* Rate calculator */
.calc-recommend-row {
  display: flex;
  align-items: center;
  gap: var(--mn-space-3);
  flex-wrap: wrap;
  margin-bottom: var(--mn-space-3);
  padding-bottom: var(--mn-space-3);
  border-bottom: 1px dashed var(--mn-border);
}
.calc-recommend-row .muted {
  flex: 1 1 320px;
  font-size: 13px;
  line-height: 1.5;
}
.calc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--mn-space-3);
}
.calc-grid .field { margin-bottom: 0; }

.calc-breakdown-table td { padding: 10px 12px; }

/* Calculator hero card (display mode): big current-rate display + Edit button. */
.calc-hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--mn-space-4);
  flex-wrap: wrap;
}
.calc-hero-info { flex: 1; min-width: 0; }
.calc-hero-label {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--mn-text-muted);
  margin-bottom: var(--mn-space-1);
}
.calc-hero-rate {
  font-size: 36px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--mn-text-strong);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.calc-hero-meta { margin-top: var(--mn-space-1); font-size: 14px; }
.calc-hero-actions { flex-shrink: 0; }

/* Composition card: total caption + horizontal stacked bar + labeled list. */
.calc-composition-total {
  background: var(--mn-bg-subtle);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius-sm);
  padding: var(--mn-space-3);
  margin-bottom: var(--mn-space-3);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  line-height: 1.6;
}
.calc-composition-bar {
  display: flex;
  width: 100%;
  height: 28px;
  border-radius: var(--mn-radius-sm);
  overflow: hidden;
  background: var(--mn-bg-subtle);
  margin-bottom: var(--mn-space-3);
}
.calc-composition-segment {
  height: 100%;
  cursor: default;
  transition: opacity 120ms ease;
}
.calc-composition-segment:hover { opacity: 0.85; }
.calc-composition-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--mn-space-2);
}
.calc-composition-item {
  display: grid;
  grid-template-columns: 14px 1fr auto auto auto;
  grid-template-areas:
    "swatch label   amount  share   permile"
    ".      formula formula formula formula";
  align-items: center;
  gap: 2px var(--mn-space-3);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  padding: var(--mn-space-1) 0;
}
.calc-composition-swatch {
  grid-area: swatch;
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 3px;
  align-self: center;
}
.calc-composition-label { grid-area: label; color: var(--mn-text); }
.calc-composition-amount { grid-area: amount; color: var(--mn-text-strong); font-weight: 500; }
.calc-composition-share { grid-area: share; font-size: 13px; min-width: 48px; text-align: right; }
.calc-composition-permile { grid-area: permile; font-size: 13px; min-width: 90px; text-align: right; }
.calc-composition-formula {
  grid-area: formula;
  font-size: 12px;
  color: var(--mn-text-muted);
  line-height: 1.3;
}

/* Cost-category color palette — muted, distinguishable, brand-aligned. */
.calc-color-fuel        { background: #1D4375; }
.calc-color-insurance   { background: #3a7ec0; }
.calc-color-licensing   { background: #4ca6c9; }
.calc-color-service     { background: #4ca87f; }
.calc-color-repairs     { background: #d28e54; }
.calc-color-tires       { background: #7e8694; }
.calc-color-depreciation { background: #8b7aae; }

/* Revert button on history rows. */
.calc-revert-btn { font-size: 12px; padding: 4px 10px; }

.calc-breakdown-table .calc-row-highlight {
  background: var(--mn-info-bg);
  font-size: 16px;
}
.calc-breakdown-table .calc-row-highlight td { padding: 14px 12px; }

/* Reports-specific print rules are bundled with the shared print stylesheet
   below — see the @media print block. */

/* Payroll batch */
.payroll-toolbar {
  display: flex;
  gap: var(--mn-space-4);
  align-items: flex-start;
  flex-wrap: wrap;
}
.payroll-toolbar .field { flex: 0 0 220px; }
.payroll-toolbar-hint {
  flex: 1 1 320px;
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
}

.payroll-row {
  display: flex;
  align-items: center;
  gap: var(--mn-space-3);
  padding: var(--mn-space-3) var(--mn-space-4);
  background: var(--mn-card);
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius);
  margin-bottom: var(--mn-space-2);
}
.payroll-section-header {
  margin: var(--mn-space-4) 0 var(--mn-space-2);
  padding: var(--mn-space-2) var(--mn-space-3);
  border-left: 4px solid var(--mn-warn);
  background: var(--mn-warn-bg);
  border-radius: 0 var(--mn-radius) var(--mn-radius) 0;
}
.payroll-section-header strong {
  display: block;
  font-size: 14px;
  color: var(--mn-warn);
}
.payroll-section-header p {
  margin: 4px 0 0;
  font-size: 13px;
}
.payroll-row.is-entered {
  background: var(--mn-success-bg);
  border-color: #b9d8b9;
}
.payroll-row-checkbox {
  display: flex;
  align-items: center;
}
.payroll-row-checkbox input[type="checkbox"] {
  width: 22px;
  height: 22px;
  cursor: pointer;
  accent-color: var(--mn-success);
}
.payroll-row-meta { flex: 1; min-width: 0; }
.payroll-row-numbers {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.payroll-row-numbers .miles { color: var(--mn-text-muted); font-size: 13px; }
.payroll-row-numbers .dollars { font-weight: 600; font-size: 18px; }
.payroll-row-status {
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  color: var(--mn-success);
}

.payroll-footer {
  position: sticky;
  bottom: 0;
  background: var(--mn-navy);
  color: white;
  padding: var(--mn-space-3) var(--mn-space-4);
  /* Clear the iOS home indicator when the page opts into viewport-fit=cover. */
  padding-bottom: calc(var(--mn-space-3) + env(safe-area-inset-bottom));
  border-radius: var(--mn-radius);
  margin-top: var(--mn-space-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--mn-space-3);
  flex-wrap: wrap;
  box-shadow: 0 -4px 16px rgba(22, 50, 88, .25);
}
.payroll-footer-info { font-size: 16px; font-variant-numeric: tabular-nums; }
.payroll-footer-info .muted { color: rgba(255, 255, 255, 0.75); }

/* Rate-unavailable notice in the technician summary bar.
   .summary is navy, so this needs light text for the same reason
   .payroll-footer-info .muted above does. It deliberately does NOT use .muted:
   #5C5F63 on #1D4375 is about 1.55:1, i.e. invisible, and a notice nobody can read
   is worse than no notice because the code looks like it handled the case. */
.rate-estimate-note { font-size: 12px; margin-top: 2px; color: rgba(255, 255, 255, 0.85); font-weight: 600; }
.payroll-footer-actions { display: flex; gap: var(--mn-space-2); }

/* ── Print summary (filed for 5-year retention) ─────────────────────── */
.print-summary {
  display: none;
  padding: 24px;
  font-family: var(--mn-font-sans);
  color: #000;
  background: white;
}
.print-header {
  border-bottom: 2px solid var(--mn-navy);
  padding-bottom: 8px;
  margin-bottom: 20px;
}
.print-brand {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--mn-navy);
}
.print-doctitle {
  font-size: 14px;
  font-weight: 500;
  color: #444;
  margin-top: 2px;
}
.print-meta {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 24px;
  font-size: 13px;
}
.print-meta th {
  text-align: left;
  font-weight: 600;
  color: #555;
  padding: 4px 12px 4px 0;
  white-space: nowrap;
}
.print-meta td { padding: 4px 24px 4px 0; }
.print-table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 18px;
  font-size: 13px;
}
.print-table th, .print-table td {
  padding: 8px 12px;
  text-align: left;
  border-bottom: 1px solid #ddd;
}
.print-table thead th {
  border-top: 2px solid var(--mn-navy);
  border-bottom: 2px solid var(--mn-navy);
  background: #f1f2f4;
  font-weight: 600;
}
.print-table tfoot th {
  border-top: 2px solid var(--mn-navy);
  border-bottom: 2px solid var(--mn-navy);
  background: #f1f2f4;
}
.print-table .right { text-align: right; font-variant-numeric: tabular-nums; }
.print-rate {
  font-size: 12px;
  color: #555;
  margin-bottom: 36px;
}
.print-signatures {
  display: flex;
  gap: 60px;
  margin-bottom: 24px;
}
.print-sig { flex: 1; }
.sig-line {
  border-top: 1px solid #444;
  height: 0;
  margin-top: 32px;
  margin-bottom: 4px;
}
.sig-label {
  font-size: 11px;
  color: #666;
}
.print-footer {
  font-size: 10px;
  color: #777;
  text-align: center;
  border-top: 1px solid #ddd;
  padding-top: 8px;
}

@media print {
  /* Shared print resets */
  body { background: white !important; color: #000 !important; }
  .container { padding: 0 !important; max-width: none !important; }
  @page { size: letter portrait; margin: 0.6in; }

  /* Payroll print mode — show only the generated summary card */
  body.printing-payroll .app-header,
  body.printing-payroll .admin-tabs,
  body.printing-payroll #panel-submissions,
  body.printing-payroll #panel-people,
  body.printing-payroll #panel-reports,
  body.printing-payroll #panel-audit,
  body.printing-payroll .payroll-toolbar-card,
  body.printing-payroll #payroll-list,
  body.printing-payroll .payroll-footer,
  body.printing-payroll #payroll-history,
  body.printing-payroll #error-banner,
  body.printing-payroll #info-banner { display: none !important; }
  body.printing-payroll #panel-payroll { display: block !important; }
  body.printing-payroll .print-summary { display: block !important; padding: 0; }

  /* Reports print mode — show the dashboard content, hide chrome + drill-downs */
  body.printing-reports .app-header,
  body.printing-reports .admin-tabs,
  body.printing-reports .reports-filters-card,
  body.printing-reports #reports-error,
  body.printing-reports #panel-submissions,
  body.printing-reports #panel-people,
  body.printing-reports #panel-payroll,
  body.printing-reports #panel-audit,
  body.printing-reports .drilldown-row,
  body.printing-reports .submission-mini,
  body.printing-reports .expand-icon { display: none !important; }
}

/* Audit trail */
.audit-trail {
  margin-top: var(--mn-space-4);
  padding: var(--mn-space-3) var(--mn-space-4);
  background: white;
  border: 1px solid var(--mn-border);
  border-radius: var(--mn-radius-sm);
}
.audit-trail h4 {
  margin: 0 0 var(--mn-space-2);
  color: var(--mn-text-muted);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.audit-list {
  margin: 0;
  padding-left: 20px;
  font-size: 14px;
}
.audit-list li { margin-bottom: var(--mn-space-2); }
.audit-list li strong {
  text-transform: capitalize;
  color: var(--mn-navy);
}
.audit-list .audit-note {
  font-style: italic;
  margin-top: 2px;
  font-size: 13px;
}

/* Mobile */
@media (max-width: 640px) {
  .container { padding: var(--mn-space-3); }
  .summary { flex-direction: column; align-items: stretch; }
  .summary .totals { justify-content: space-between; }
  .summary .btn { width: 100%; }
  .field-row { flex-direction: column; }

  /* Manager view */
  .submission-header {
    flex-direction: column;
    align-items: stretch;
    gap: var(--mn-space-2);
  }
  .submission-meta-right { justify-content: space-between; }
  .submission-submitted { display: none; }
  .submission-actions { flex-direction: column; }
  .submission-actions .btn { width: 100%; }

  /* Prevent iOS Safari auto-zoom on focus: form controls must be >= 16px. */
  input, select, textarea { font-size: 16px; }

  /* Give the customer name field a usable width instead of letting the fixed
     ticket + Remove controls crush it. */
  .customer-row { flex-wrap: wrap; }
  .customer-row > .customer-name-col { flex: 1 1 100%; }
  .customer-row input.ticket { flex: 1 1 auto; }

  /* Reliable tap targets on the daily entry screen (>= 44px). */
  .day-card .btn-sm, .unit-toggle button { min-height: 44px; }

  /* Two controls the rule above does not reach, both routine rather than rare.
     The payroll checkbox is the admin's per-row "entered into payroll" tick, and
     the near-duplicate Use / dismiss pair appears while a tech types a customer
     name. Both were roughly 16-29px tall, well under the 44px this file already
     sets as its own minimum. */

  /* Grow the hit box, not the control: the checkbox itself stays 22px so the
     visual density of the payroll table is unchanged. */
  .payroll-row-checkbox {
    min-width: 44px;
    min-height: 44px;
    justify-content: center;
    margin: -11px 0;   /* absorb the added height so row rhythm is unaffected */
  }

  .fuzzy-suggest button {
    min-height: 44px;
    padding: 6px 12px;
  }
  .fuzzy-suggest .fuzzy-dismiss {
    min-height: 44px;
    min-width: 44px;
    padding: 0 12px;
  }

  /* Beyond audit finding #48, but the same rule and found while measuring it:
     the header rule above collapses these to icon-only, leaving a ~36px box.
     Sign out is the only way off every page, so it should not be the smallest
     target in the app. */
  .app-header #tour-btn,
  .app-header #sign-out-btn {
    min-height: 44px;
    min-width: 44px;
  }

  /* The third control in the same header cluster, and the only route to the
     profile page on a phone. Width stays text-driven. */
  .app-header .user-meta {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* Small buttons everywhere, not just inside a day card. The rule above already
     covered .day-card .btn-sm; the same 33px control is also "Download receipt
     (PDF)" and "Request reopen" on the technician screen, which are exactly the
     kind of one-handed taps this minimum exists for. */
  .btn-sm { min-height: 44px; }
}
