/* =============================================================================
   ANJ Construction — single stylesheet for every page. Plain CSS, no build step.

   DESIGN LANGUAGE — "warm, premium, calm":
   A softly blushed warm canvas, white cards floating on soft layered shadows,
   and a confident red brand accent. The look is deliberately spacious and
   unhurried — generous whitespace, a real type scale, and quiet motion — so it
   reads as considered, not busy. Money meaning never changes: profit is always
   green, debt/overdraw always red (the brand red and the money red share a
   family on purpose; green stays the only "good" signal).

   HOW THIS FILE IS ORGANIZED (top to bottom):
     1. Design tokens          — every color / space / radius / shadow as a var
     2. Base + reset           — body, typography baseline, animations
     3. App navigation         — the shared top bar
     4. Buttons + focus        — the shared interaction model
     5. Page scaffolding       — container, page headings, toolbars
     6. Jobs list              — summary strip + table + status pills
     7. Job detail             — header, summary cards, line-item sections
     8. Forms + dialogs        — inputs, native <dialog>, fields
     9. Invoice                — on-screen + @media print
    10. Login                  — the centered card
    11. Reportes               — filter bar + chart cards
    12. Worker payments        — weekly cards
    13. Toasts + confirm modal — the ui.js feedback layer
    14. Mobile layer           — one breakpoint that adapts everything
    15. Reduced motion         — accessibility opt-out

   The single source of truth for any value is its token in :root. We never
   hard-code a color further down — change the token once, the whole app follows.
   ============================================================================= */

/* Type. Plus Jakarta Sans gives the UI a little more character than the system
   default without ever sacrificing legibility. We always list a full system
   fallback after it, so if the font fails to load (offline) the app still looks
   intentional rather than broken. The <link> that fetches it lives in each
   page's <head>. */

/* ---------------------------------------------------------------------------
   1. DESIGN TOKENS
   --------------------------------------------------------------------------- */
:root {
  /* — Surfaces: a warm, layered neutral stack (darkest canvas → brightest card),
       tinted a breath toward the red brand so the neutrals feel chosen */
  --bg:           #f7efec;   /* page canvas — warm blush sand, not a cold grey */
  --bg-deep:      #f1e5e0;   /* used in gradients to give the canvas depth */
  --surface:      #ffffff;   /* cards, nav, table bodies */
  --surface-2:    #fbf6f3;   /* table headers, hovers, quiet panels */
  --surface-sunk: #f8f0ec;   /* inset wells (e.g. inline add-row forms) */
  --border:       #ecddd6;   /* warm hairline border */
  --border-strong:#ddc9c0;   /* a heavier divider when one hairline isn't enough */

  /* — Ink: warm-toned text so it sits naturally on the warm canvas */
  --text:         #2b2421;   /* near-black, warm */
  --text-muted:   #74655f;   /* secondary text, labels */
  --text-subtle:  #7e6d66;   /* placeholders, faint captions — kept dark enough
                                to clear WCAG AA (~4.8:1 on white) since these
                                placeholders carry the only hint on inline forms */

  /* — Brand: a warm true red. --primary is deep enough to pass AA with white
       text on buttons; --accent is the brighter decorative version for edges,
       icons, and tints where text contrast doesn't apply. */
  --primary:       #c0231d;
  --primary-hover: #a31d18;
  --primary-press: #8c1914;
  --accent:        #e03a30;
  --accent-soft:   #fce8e6;   /* red wash for tinted backgrounds / active pills */
  --accent-ring:   rgba(224, 58, 48, 0.16); /* focus glow */
  --gold:          #c98a3a;   /* warm secondary, used sparingly (brand mark) */

  /* — Semantic money colors (meaning is fixed; never restyle these away) */
  --positive:      #1f7a46;
  --positive-soft: #e7f3ec;
  --negative:      #b3261e;
  --negative-soft: #fbe9e6;

  /* — Status badge palettes (warm-compatible tints) */
  --warn-bg:    #fbeccb;  --warn-text:    #8a5a12;
  --info-bg:    #dde8f4;  --info-text:    #2f5a8f;
  --success-bg: #dcefe2;  --success-text: #1c6b3f;
  --neutral-bg: #ece0da;  --neutral-text: #6e5c55;

  /* — Spacing scale (4px base). Using a fixed scale keeps rhythm consistent and
       is the main lever behind the "spacious, not cluttered" feel. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* — Radii: a touch larger than before for a softer, modern silhouette */
  --radius-sm:  9px;
  --radius:     13px;
  --radius-lg:  18px;
  --radius-pill: 999px;

  /* — Elevation: soft, warm-tinted, layered. Three resting depths + a focus glow.
       Warm shadow color (not pure black) keeps cards sitting on the blush canvas. */
  --shadow-xs: 0 1px 2px rgba(66, 32, 26, 0.05);
  --shadow-sm: 0 1px 2px rgba(66, 32, 26, 0.04), 0 3px 10px rgba(66, 32, 26, 0.05);
  --shadow-md: 0 4px 14px rgba(66, 32, 26, 0.08), 0 14px 32px rgba(66, 32, 26, 0.07);
  --shadow-lg: 0 10px 30px rgba(66, 32, 26, 0.12), 0 30px 64px rgba(66, 32, 26, 0.12);

  /* — Motion: two curves. --ease for color/opacity, --spring for transforms so
       hovers feel a little alive without being bouncy or slow. */
  --ease:   170ms cubic-bezier(0.4, 0, 0.2, 1);
  --spring: 240ms cubic-bezier(0.34, 1.3, 0.5, 1);

  --font-sans: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
               Roboto, "Helvetica Neue", Arial, sans-serif;

  --nav-height: 66px;
}

/* ---------------------------------------------------------------------------
   2. BASE + RESET
   --------------------------------------------------------------------------- */
* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

/* The `hidden` attribute must always win — even over a component's own display.
   Lots of elements here (the summary strips, the reportes grid, the optional-
   fields toggle, the user pill) are shown/hidden by flipping .hidden in JS.
   Because we give those components an explicit display (flex / grid / inline-
   flex), that author rule would otherwise override the browser's [hidden]
   styling and they'd never actually hide. This one line keeps toggling robust. */
[hidden] { display: none !important; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font-sans);
  color: var(--text);
  font-size: 15px;
  line-height: 1.6;
  letter-spacing: -0.003em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* A barely-there warm glow at the top of the canvas adds depth without
     reading as decoration — the kind of quiet polish that lifts the whole app. */
  background:
    radial-gradient(1200px 600px at 50% -280px, var(--surface-2) 0%, transparent 70%),
    linear-gradient(180deg, var(--bg) 0%, var(--bg-deep) 100%);
  background-attachment: fixed;
}

h1, h2, h3, h4 { font-weight: 700; }

/* Numbers (money, dates) line up in columns when they share these utilities. */
.money { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }
.positive { color: var(--positive); font-weight: 700; }
.negative { color: var(--negative); font-weight: 700; }

/* — Entrance motion. Content rises and fades in gently so each page feels like
     it arrives rather than blinks into place. */
@keyframes fade-in-up {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ---------------------------------------------------------------------------
   3. APP NAVIGATION — the shared top bar (index / job-detail / reportes /
   trabajadores). It is sticky and lightly frosted so it stays available while
   the page scrolls, which keeps navigation a constant rather than something you
   scroll back up to find.
   --------------------------------------------------------------------------- */
.app-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: var(--space-5);
  height: var(--nav-height);
  padding: 0 clamp(16px, 4vw, 40px);
  background: rgba(255, 255, 255, 0.82);
  border-bottom: 1px solid var(--border);
  /* Frosted-glass effect — pure progressive enhancement. Browsers without it
     just get the solid-ish white above, which is perfectly fine. */
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
}

/* Brand lockup — the mark + wordmark act as one "home" link back to the jobs list. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  color: inherit;
  flex-shrink: 0;
}
.brand-mark {
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 11px;
  /* Terracotta → clay → warm gold gives the tile real depth; the inner ring
     (inset shadow) and drop shadow make it read as a crafted object, not a box. */
  background: linear-gradient(140deg, var(--accent) 0%, var(--primary) 55%, #8f2d1d 100%);
  box-shadow: 0 4px 12px rgba(176, 42, 30, 0.34),
              inset 0 1px 0 rgba(255, 255, 255, 0.28);
  color: #fff;
}
.brand-mark svg { display: block; width: 22px; height: 22px; }

.brand-word {
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--text);
  white-space: nowrap;
}
.brand-word b { color: var(--primary); font-weight: 800; }

/* The primary destinations. Centered between brand and the user area. */
.nav-links {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin: 0 auto;
}
.nav-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 15px;
  border-radius: var(--radius-pill);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-muted);
  text-decoration: none;
  transition: color var(--ease), background var(--ease);
}
.nav-link svg { width: 17px; height: 17px; opacity: 0.85; }
.nav-link:hover { color: var(--text); background: var(--surface-2); }
/* The current page is marked with aria-current="page" in each page's HTML —
   styling hangs off that attribute so the markup stays semantic. */
.nav-link[aria-current="page"] {
  color: var(--primary);
  background: var(--accent-soft);
}

/* Right-hand cluster: an optional back link + the user pill. */
.nav-right {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-shrink: 0;
}

/* Back link used on drill-in pages (job detail, invoice). */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
  transition: color var(--ease), gap var(--ease);
}
.back-link:hover { color: var(--primary); gap: 9px; }

/* User identity + logout, shown at the right edge of the nav. */
.user-pill {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--text-muted);
}
.user-pill .user-email {
  font-weight: 600;
  color: var(--text);
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.user-pill .logout-link {
  color: var(--primary);
  text-decoration: none;
  font-weight: 700;
  padding: 5px 11px;
  border-radius: var(--radius-pill);
  transition: background var(--ease);
}
.user-pill .logout-link:hover { background: var(--accent-soft); }

/* ---------------------------------------------------------------------------
   4. BUTTONS + FOCUS — one shared interaction model: lift a hair on hover,
   press back down on click, and always show a crisp focus ring for keyboards.
   --------------------------------------------------------------------------- */
button { font: inherit; cursor: pointer; }

.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  background: linear-gradient(180deg, #be4530 0%, var(--primary) 100%);
  color: #fff;
  border: none;
  padding: 10px 18px;
  border-radius: var(--radius-sm);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: -0.01em;
  box-shadow: 0 1px 2px rgba(131, 42, 27, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.18);
  transition: transform var(--spring), box-shadow var(--ease), filter var(--ease);
}
.btn-primary:hover {
  filter: brightness(1.05);
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(131, 42, 27, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.btn-primary:active { transform: translateY(0); box-shadow: 0 1px 2px rgba(131, 42, 27, 0.3); }

.btn-secondary {
  display: inline-flex;            /* so <a> and <button> secondaries line up identically */
  align-items: center;
  justify-content: center;
  gap: 7px;
  text-decoration: none;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  padding: 9px 16px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 600;
  box-shadow: var(--shadow-xs);
  transition: background var(--ease), border-color var(--ease), transform var(--spring), box-shadow var(--ease);
}
.btn-secondary:hover {
  background: var(--surface-2);
  border-color: var(--text-subtle);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}
.btn-secondary:active { transform: translateY(0); box-shadow: var(--shadow-xs); }

/* Small transparent icon button (edit / delete in line tables). */
.btn-icon {
  background: transparent;
  border: none;
  color: var(--text-muted);     /* actionable icons stay clearly visible at rest */
  font-size: 16px;
  line-height: 1;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  transition: background var(--ease), color var(--ease), transform var(--ease);
}
.btn-icon:hover { background: var(--surface-2); color: var(--text); transform: translateY(-1px); }
.btn-icon[data-action^="delete"]:hover { background: var(--negative-soft); color: var(--negative); }

/* Outline danger button (delete whole job). Fills in on hover to signal weight. */
.btn-danger {
  background: transparent;
  color: var(--negative);
  border: 1px solid #e6b8b3;
  padding: 9px 18px;
  border-radius: var(--radius-sm);
  font: inherit;
  font-weight: 700;
  font-size: 14px;
  transition: background var(--ease), color var(--ease), border-color var(--ease), transform var(--spring);
}
.btn-danger:hover {
  background: var(--negative);
  color: #fff;
  border-color: var(--negative);
  transform: translateY(-1px);
}
.btn-danger:active { transform: translateY(0); }

/* One consistent keyboard-focus ring everywhere. :focus-visible only fires for
   keyboard navigation, so mouse users never see it but tab users always do. */
button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------------------------------------------------------------------------
   5. PAGE SCAFFOLDING — the centered column, page headings, toolbars
   --------------------------------------------------------------------------- */
.container {
  max-width: 1120px;
  margin: 0 auto;
  padding: var(--space-6) clamp(16px, 4vw, 40px) var(--space-8);
  animation: fade-in-up 360ms ease both;
}

/* Page heading row: a title (+ optional subtitle) on the left, a primary action
   on the right. The generous margin below it is deliberate breathing room. */
.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
}
.page-title {
  margin: 0;
  font-size: 27px;
  font-weight: 800;
  letter-spacing: -0.025em;
}
.page-subtitle {
  margin: 5px 0 0;
  color: var(--text-muted);
  font-size: 14.5px;
}

/* Breadcrumb / back row above a drill-in page's content. */
.crumb {
  margin-bottom: var(--space-4);
}

.toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}

.search-input {
  flex: 1;
  max-width: 420px;
  padding: 11px 15px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 14.5px;
  background: var(--surface);
  box-shadow: var(--shadow-xs);
  transition: border-color var(--ease), box-shadow var(--ease);
}
.search-input::placeholder { color: var(--text-subtle); }
.search-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-ring);
}

/* ---------------------------------------------------------------------------
   6. JOBS LIST — summary strip, table, status pills, empty state
   --------------------------------------------------------------------------- */

/* At-a-glance totals above the table. */
.list-summary {
  display: flex;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.list-summary-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: var(--space-4) var(--space-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  position: relative;
  overflow: hidden;
}
/* A soft accent bar down the left edge — a quiet brand echo. */
.list-summary-item::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: linear-gradient(180deg, var(--accent), var(--primary));
}
.list-summary-label {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  font-weight: 700;
}
.list-summary-value {
  font-size: 25px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.jobs-table {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;            /* clip row hovers to the rounded corners */
  box-shadow: var(--shadow-sm);
}
.jobs-table th,
.jobs-table td {
  text-align: left;
  padding: 15px 18px;
  border-bottom: 1px solid var(--border);
}
.jobs-table th {
  background: var(--surface-2);
  font-weight: 700;
  font-size: 11.5px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.jobs-table tbody tr {
  cursor: pointer;
  transition: background var(--ease);
}
.jobs-table tbody tr:hover { background: var(--accent-soft); }
.jobs-table tbody tr:last-child td { border-bottom: none; }

/* The job name is a real <a>, so the list is keyboard-navigable (Tab + Enter),
   not only mouse-clickable. It reads as plain strong text until hover/focus. */
.job-link {
  color: var(--text);
  font-weight: 600;
  text-decoration: none;
  border-radius: 4px;
}
.job-link:hover { color: var(--primary); }

/* Empty / no-results state — friendly and roomy rather than a bare line. */
.empty-state {
  text-align: center;
  padding: var(--space-8) var(--space-5);
  color: var(--text-muted);
  background: var(--surface);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
}
.empty-state p:first-child {
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 6px;
}
.empty-state p { margin: 0; }

/* Status pill. The leading dot (inherits the text color via currentColor) makes
   the status scannable before you even read the word. */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: var(--radius-pill);
  font-size: 12px;
  font-weight: 700;
  background: var(--neutral-bg);
  color: var(--neutral-text);
}
.status-badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.status-quoted      { background: var(--warn-bg);    color: var(--warn-text); }
.status-in_progress { background: var(--info-bg);    color: var(--info-text); }
.status-completed   { background: var(--success-bg); color: var(--success-text); }
.status-cancelled   { background: var(--neutral-bg); color: var(--neutral-text); }

/* ---------------------------------------------------------------------------
   7. JOB DETAIL — header, summary cards, line-item sections
   --------------------------------------------------------------------------- */
.detail-header {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5) var(--space-6);
  margin-bottom: var(--space-5);
  box-shadow: var(--shadow-sm);
}
.detail-header-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;             /* action buttons drop below on narrow screens */
}
.detail-header-actions {
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
}
.detail-header h2 {
  margin: 0 0 6px;
  font-size: 25px;
  font-weight: 800;
  letter-spacing: -0.025em;
}
.detail-header .client-line {
  color: var(--text-muted);
  font-size: 14.5px;
}
.detail-header .status-row {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.summary-grid {
  display: grid;
  /* auto-fit + minmax = cards reflow on their own as the screen narrows; no
     media query needed for this part. */
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.summary-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  box-shadow: var(--shadow-sm);
  transition: transform var(--spring), box-shadow var(--ease);
}
.summary-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}
.summary-card .label {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  font-weight: 700;
  margin-bottom: 8px;
}
.summary-card .value {
  font-size: 22px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* Profit is the number this whole app exists to surface. It gets a green wash,
   a green accent edge, and a larger value so the eye lands on it first — the
   styling itself says "this is the one that matters." */
.summary-card.is-primary {
  border-color: #bfe0cb;
  background: linear-gradient(165deg, var(--positive-soft) 0%, var(--surface) 72%);
  box-shadow: 0 1px 2px rgba(31, 122, 70, 0.08), 0 10px 26px rgba(31, 122, 70, 0.1);
}
.summary-card.is-primary .label { color: var(--positive); }
.summary-card.is-primary .value { font-size: 27px; }

/* A content section (costs, payments, a weekly group). */
.section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5) var(--space-6);
  margin-bottom: var(--space-5);
  box-shadow: var(--shadow-sm);
}
.section h3 {
  margin: 0 0 var(--space-4);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  /* Terracotta tick to the left of every section title — small brand echo. */
  padding-left: 12px;
  border-left: 3px solid var(--accent);
}

/* Line-item tables inside sections (costs, payments, weekly worker payments). */
.line-table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: var(--space-3);
}
.line-table th,
.line-table td {
  text-align: left;
  padding: 11px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
.line-table th {
  font-weight: 700;
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.line-table tbody tr { transition: background var(--ease); }
.line-table tbody tr:hover { background: var(--surface-2); }
.line-table tbody tr:last-child td { border-bottom: none; }
.line-table td.amount { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; }
.line-table td.actions { text-align: right; width: 88px; white-space: nowrap; }
.line-table .empty-row td {
  text-align: center;
  color: var(--text-muted);
  font-style: italic;
  padding: var(--space-5);
}
.line-table .empty-row:hover { background: transparent; }

/* Inline "add a row" form sitting in a sunk well below each table, so adding a
   cost/payment feels like part of the table rather than a separate panel. */
.add-row-form {
  display: grid;
  /* First column holds a native date input — needs ~150px for MM/DD/YYYY plus
     the calendar icon without clipping. */
  grid-template-columns: 150px 140px 150px 1fr auto;
  gap: var(--space-2);
  align-items: center;
  margin-top: var(--space-4);
  padding: var(--space-3);
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.add-row-form input,
.add-row-form select,
.wp-form input,
.wp-form select {
  padding: 10px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 14px;
  background: var(--surface);
  transition: border-color var(--ease), box-shadow var(--ease);
}
.add-row-form input:focus,
.add-row-form select:focus,
.wp-form input:focus,
.wp-form select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-ring);
}

/* Status dropdown in the detail header. */
select.status-select {
  padding: 8px 12px;
  font-size: 13.5px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-weight: 700;
  color: var(--text);
  transition: border-color var(--ease), box-shadow var(--ease);
}
select.status-select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-ring);
}

/* Danger zone — set apart with space, centered, low-key until hovered. */
.danger-zone {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
  text-align: center;
}

/* ---------------------------------------------------------------------------
   8. FORMS + DIALOGS — native <dialog>, fields, the small text-link toggle
   --------------------------------------------------------------------------- */
dialog {
  border: none;
  border-radius: var(--radius-lg);
  padding: 0;
  box-shadow: var(--shadow-lg);
  max-width: 480px;
  width: 92%;
  color: var(--text);
  background: var(--surface);
}
dialog::backdrop {
  background: rgba(42, 28, 16, 0.4);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
/* Dialog + its backdrop scale and fade in instead of popping. */
dialog[open] { animation: dialog-in 200ms cubic-bezier(0.34, 1.2, 0.5, 1) both; }
@keyframes dialog-in {
  from { opacity: 0; transform: translateY(10px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

.dialog-body { padding: var(--space-6); }
.dialog-body h2 {
  margin: 0 0 var(--space-5);
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.02em;
}

.field { margin-bottom: var(--space-4); }
.field label {
  display: block;
  font-size: 13px;
  font-weight: 700;
  margin-bottom: 6px;
  color: var(--text);
}
.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 14.5px;
  background: var(--surface);
  color: var(--text);
  transition: border-color var(--ease), box-shadow var(--ease);
}
.field textarea {
  font-family: inherit;
  resize: vertical;
  min-height: 110px;
  line-height: 1.5;
}
.field input::placeholder,
.field textarea::placeholder { color: var(--text-subtle); }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-ring);
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-5);
}

/* Text-link styled button used to reveal optional form fields. */
.toggle-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: none;
  border: none;
  padding: 0;
  margin-bottom: var(--space-4);
  color: var(--primary);
  font-size: 13px;
  font-weight: 700;
  text-align: left;
}
.toggle-link:hover { text-decoration: underline; }

/* ---------------------------------------------------------------------------
   9. INVOICE — clean document on screen; @media print strips it to paper
   --------------------------------------------------------------------------- */
.invoice-body {
  min-height: 100vh;
  padding: var(--space-5) 0 var(--space-7);
}
.invoice-toolbar {
  max-width: 800px;
  margin: 0 auto var(--space-4);
  padding: 0 var(--space-4);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
}
.invoice-toolbar-actions {
  display: flex;
  gap: var(--space-2);
}
.email-hint {
  margin: 0 0 var(--space-4);
  font-size: 12.5px;
  color: var(--text-muted);
  font-style: italic;
}
.email-error {
  background: var(--negative-soft);
  color: #8f1c16;
  border: 1px solid #f3c6c1;
  border-radius: var(--radius-sm);
  padding: 11px 13px;
  font-size: 13px;
  margin-bottom: var(--space-4);
}
.invoice-paper {
  max-width: 800px;
  margin: 0 auto;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: clamp(28px, 6vw, 56px);
  box-shadow: var(--shadow-md);
  font-size: 14px;
  color: var(--text);
  animation: fade-in-up 360ms ease both;
}
.invoice-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-5);
  padding-bottom: var(--space-5);
  border-bottom: 2px solid var(--text);
  margin-bottom: var(--space-6);
}
.invoice-brand {
  margin: 0;
  font-size: 25px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--primary);
}
.invoice-meta { text-align: right; }
.invoice-title {
  margin: 0 0 8px;
  font-size: 17px;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: var(--text-muted);
}
.invoice-meta-row {
  font-size: 13px;
  color: var(--text);
  margin-bottom: 2px;
  font-variant-numeric: tabular-nums;
}
.invoice-parties {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-6);
  margin-bottom: var(--space-6);
}
.invoice-section h3 {
  margin: 0 0 8px;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  font-weight: 700;
}
.invoice-strong {
  font-weight: 700;
  font-size: 15px;
  margin-bottom: 3px;
}
.invoice-amounts { margin-top: var(--space-6); }
.invoice-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 11px 0;
}
.invoice-label { font-size: 14px; color: var(--text); font-weight: 500; }
.invoice-value { font-variant-numeric: tabular-nums; font-size: 15px; font-weight: 600; }
.invoice-row.subtotal {
  border-top: 1px solid var(--border-strong);
  margin-top: 8px;
  padding-top: var(--space-3);
  font-weight: 700;
}
.invoice-row.total {
  border-top: 2px solid var(--text);
  margin-top: var(--space-4);
  padding-top: var(--space-4);
}
.invoice-row.total .invoice-label,
.invoice-row.total .invoice-value {
  font-size: 19px;
  font-weight: 800;
}
.invoice-payments-block {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}
.invoice-payments-block h4 {
  margin: 0 0 8px;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  font-weight: 700;
}
/* Horizontal-scroll guard so the payments table never forces the whole invoice
   to side-scroll on a narrow phone. It stays a real table (the PDF needs that),
   it just scrolls inside this wrapper if the screen is too narrow. */
.table-scroll { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.invoice-payments-table { width: 100%; border-collapse: collapse; }
.invoice-payments-table th,
.invoice-payments-table td {
  text-align: left;
  padding: 7px 8px;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
}
.invoice-payments-table th {
  font-weight: 700;
  color: var(--text-muted);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.invoice-payments-table td.amount {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.invoice-empty {
  font-style: italic;
  color: var(--text-muted);
  padding: 9px 0;
}

/* Print: render through these instead of the on-screen styles. Strip every
   shadow / border / background so it reads as a document, not a web page. */
@media print {
  .no-print { display: none !important; }

  body, .invoice-body {
    background: #fff !important;
    padding: 0 !important;
    margin: 0 !important;
  }
  .invoice-paper {
    max-width: none !important;
    margin: 0 !important;
    padding: 0 !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    animation: none !important;
  }
  @page { size: letter; margin: 0.75in; }
}

/* ---------------------------------------------------------------------------
   10. LOGIN — a single centered card on the warm canvas
   --------------------------------------------------------------------------- */
.login-body {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  background:
    radial-gradient(820px circle at 50% -8%, var(--accent-soft) 0%, transparent 58%),
    linear-gradient(165deg, var(--bg) 0%, var(--bg-deep) 100%);
}
.login-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-7) var(--space-6) var(--space-6);
  width: 100%;
  max-width: 400px;
  box-shadow: var(--shadow-lg);
  animation: fade-in-up 420ms ease both;
}
/* The brand mark, enlarged and centered above the wordmark. */
.login-mark {
  width: 60px;
  height: 60px;
  margin: 0 auto var(--space-4);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 17px;
  background: linear-gradient(140deg, var(--accent) 0%, var(--primary) 55%, #8f2d1d 100%);
  box-shadow: 0 6px 20px rgba(176, 42, 30, 0.36), inset 0 1px 0 rgba(255, 255, 255, 0.3);
  color: #fff;
}
.login-mark svg { width: 32px; height: 32px; display: block; }
.login-brand {
  margin: 0 0 6px;
  font-size: 23px;
  font-weight: 800;
  text-align: center;
  letter-spacing: -0.02em;
  color: var(--text);
}
.login-brand b { color: var(--primary); }
.login-subtitle {
  margin: 0 0 var(--space-6);
  text-align: center;
  color: var(--text-muted);
  font-size: 14.5px;
}
.login-submit {
  width: 100%;
  margin-top: var(--space-2);
  padding: 13px;
  font-size: 15px;
}
.login-submit:disabled { opacity: 0.65; cursor: progress; }
.login-error {
  background: var(--negative-soft);
  color: #8f1c16;
  border: 1px solid #f3c6c1;
  border-radius: var(--radius-sm);
  padding: 11px 13px;
  font-size: 13px;
  margin-bottom: var(--space-4);
}
.login-toggle {
  margin: var(--space-5) 0 0;
  text-align: center;
  font-size: 13px;
  color: var(--text-muted);
}
.login-toggle a {
  color: var(--primary);
  text-decoration: none;
  margin-left: 4px;
  font-weight: 700;
}
.login-toggle a:hover { text-decoration: underline; }

/* ---------------------------------------------------------------------------
   11. REPORTES — filter bar + chart cards
   --------------------------------------------------------------------------- */
.filter-bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
  width: fit-content;
}
.filter-bar label {
  font-size: 13px;
  color: var(--text-muted);
  font-weight: 700;
}
.filter-bar select {
  padding: 9px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 14px;
  background: var(--surface);
  font-weight: 600;
  color: var(--text);
  transition: border-color var(--ease), box-shadow var(--ease);
}
.filter-bar select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-ring);
}

.reportes-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-5);
  margin-bottom: var(--space-5);
}
.chart-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5) var(--space-6);
  box-shadow: var(--shadow-sm);
  transition: transform var(--spring), box-shadow var(--ease);
}
.chart-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}
.chart-card h3 {
  margin: 0 0 var(--space-4);
  font-size: 16px;
  font-weight: 700;
  padding-left: 12px;
  border-left: 3px solid var(--accent);
}
.chart-card .chart-wrap {
  position: relative;
  height: 280px;             /* fixed height; Chart.js (maintainAspectRatio:false) fills it */
}

/* ---------------------------------------------------------------------------
   12. WORKER PAYMENTS (trabajadores.html)
   --------------------------------------------------------------------------- */

/* Inline "register payment" form — 6 controls in a row on desktop. Shares the
   input styling of .add-row-form above. */
.wp-form {
  display: grid;
  grid-template-columns: 1.3fr 150px 130px 130px 1.4fr auto;
  gap: var(--space-2);
  align-items: center;
  margin-top: var(--space-2);
  padding: var(--space-3);
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.wp-hint {
  margin: var(--space-3) 0 0;
  font-size: 13px;
  color: var(--text-muted);
}

/* Each week is a card with a header pairing the week label and its subtotal. */
.week-group { margin-bottom: var(--space-4); }
.week-group-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}
.week-group-title { margin: 0; }                /* override .section h3 margin */
.week-group-total {
  font-size: 18px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* Worker list inside the "Administrar Trabajadores" dialog. */
.workers-list {
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: 0;
  max-height: 300px;
  overflow-y: auto;
}
.worker-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 11px 2px;
  border-bottom: 1px solid var(--border);
}
.worker-row:last-child { border-bottom: none; }
.worker-name { font-weight: 600; }
.worker-rename { padding: 5px 12px; font-size: 12.5px; }
.worker-row-empty {
  padding: var(--space-4) 2px;
  color: var(--text-muted);
  font-style: italic;
}

/* ---------------------------------------------------------------------------
   13. TOASTS + CONFIRM MODAL — the feedback layer injected by ui.js.
   Replaces the browser's native alert()/confirm()/prompt() with on-brand,
   non-blocking UI. ui.js creates the container and the dialog; these are the
   styles they hang off.
   --------------------------------------------------------------------------- */

/* Toast stack — bottom-right, newest on top, never blocks interaction. */
.toast-stack {
  position: fixed;
  right: clamp(12px, 3vw, 28px);
  bottom: clamp(12px, 3vw, 28px);
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: min(360px, calc(100vw - 24px));
  pointer-events: none;       /* clicks pass through the gaps between toasts */
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 13px 15px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--text-subtle);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  pointer-events: auto;       /* but the toast itself is interactive (dismiss) */
  animation: toast-in 280ms cubic-bezier(0.34, 1.2, 0.5, 1) both;
}
.toast.is-leaving { animation: toast-out 200ms ease both; }
.toast__icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.toast__icon svg { width: 20px; height: 20px; }
.toast__msg { flex: 1; line-height: 1.45; }
.toast__close {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--text-subtle);
  font-size: 17px;
  line-height: 1;
  padding: 1px 3px;
  border-radius: 5px;
  transition: color var(--ease), background var(--ease);
}
.toast__close:hover { color: var(--text); background: var(--surface-2); }

.toast--success { border-left-color: var(--positive); }
.toast--success .toast__icon { color: var(--positive); }
.toast--error   { border-left-color: var(--negative); }
.toast--error   .toast__icon { color: var(--negative); }
.toast--info    { border-left-color: var(--accent); }
.toast--info    .toast__icon { color: var(--accent); }

@keyframes toast-in {
  from { opacity: 0; transform: translateX(16px) scale(0.98); }
  to   { opacity: 1; transform: translateX(0)    scale(1); }
}
@keyframes toast-out {
  from { opacity: 1; transform: translateX(0); }
  to   { opacity: 0; transform: translateX(16px); }
}

/* Confirm / prompt modal — reuses the <dialog> + .dialog-body shell, with a
   little extra structure for an icon, message, and optional input. */
.ui-modal__body { padding: var(--space-6); }
.ui-modal__row {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
}
.ui-modal__icon {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-pill);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-soft);
  color: var(--primary);
}
.ui-modal__icon svg { width: 24px; height: 24px; }
.ui-modal--danger .ui-modal__icon { background: var(--negative-soft); color: var(--negative); }
.ui-modal__text { flex: 1; padding-top: 2px; }
.ui-modal__title {
  margin: 0 0 6px;
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.02em;
}
.ui-modal__message {
  margin: 0;
  color: var(--text-muted);
  font-size: 14.5px;
  line-height: 1.5;
  white-space: pre-line;      /* honor \n in confirm messages */
}
.ui-modal__input {
  width: 100%;
  margin-top: var(--space-4);
  padding: 11px 13px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 14.5px;
  background: var(--surface);
  color: var(--text);
}
.ui-modal__input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-ring);
}
.ui-modal__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-5);
}

/* ---------------------------------------------------------------------------
   14. MOBILE LAYER — everything above is the desktop design; this adapts it for
   phones. One breakpoint (720px) is enough because the summary grids already
   reflow on their own via auto-fit.
   --------------------------------------------------------------------------- */
@media (max-width: 720px) {
  /* Nav: brand + user stay on the top line, the links wrap to a scrollable row
     beneath. No hamburger — only three short destinations, so keeping them all
     visible is simpler for a non-technical user than hiding them in a menu. */
  .app-nav {
    height: auto;
    flex-wrap: wrap;
    gap: var(--space-3);
    padding: 12px clamp(14px, 4vw, 20px);
    position: static;          /* not sticky on mobile, to reclaim vertical room */
  }
  .nav-links {
    order: 3;
    width: 100%;
    margin: 0;
    gap: 6px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 2px;
  }
  .nav-link { flex-shrink: 0; }
  .nav-right { margin-left: auto; }
  .user-pill .user-email { max-width: 130px; }

  .container { padding: var(--space-5) clamp(14px, 4vw, 20px) var(--space-7); }
  .page-title { font-size: 23px; }

  .page-head { align-items: stretch; }
  .page-head .btn-primary { width: 100%; }

  /* Toolbar stacks; the search box uses the full width. */
  .toolbar { flex-direction: column; align-items: stretch; }
  .search-input { max-width: none; }

  /* Summary strip stacks vertically. */
  .list-summary { flex-direction: column; gap: var(--space-3); }

  .detail-header { padding: var(--space-5); }

  /* --- Jobs table → cards ------------------------------------------------
     A 6-column table can't fit a phone, so each <tr> becomes a stacked card
     and each <td> becomes a label/value row. The label text comes from the
     data-label="" attribute set in app.js; content: attr(data-label) pulls it
     in. (This is why those attributes exist — don't remove them.) */
  .jobs-table { border: none; background: transparent; box-shadow: none; }
  .jobs-table thead { display: none; }
  .jobs-table tbody,
  .jobs-table tr,
  .jobs-table td { display: block; width: 100%; }

  .jobs-table tr {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 6px 16px;
    margin-bottom: var(--space-3);
    position: relative;
    overflow: hidden;
  }
  .jobs-table tr::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: linear-gradient(180deg, var(--accent), var(--primary));
  }
  .jobs-table td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-4);
    padding: 9px 0;
    border-bottom: 1px solid var(--border);
    text-align: right !important;
  }
  .jobs-table tr td:last-child { border-bottom: none; }
  .jobs-table td::before {
    content: attr(data-label);
    font-weight: 700;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    text-align: left;
  }

  /* --- Line tables → cards (same technique) ------------------------------ */
  .line-table { border: none; }
  .line-table thead { display: none; }
  .line-table tbody,
  .line-table tr,
  .line-table td { display: block; width: 100%; }

  .line-table tbody tr {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 4px 14px;
    margin-bottom: var(--space-3);
  }
  .line-table td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-4);
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
    text-align: right !important;
  }
  .line-table tr td:last-child { border-bottom: none; }
  .line-table td::before {
    content: attr(data-label);
    font-weight: 700;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    text-align: left;
  }
  /* The actions cell has no label — just right-align its buttons. */
  .line-table td.actions { width: auto; justify-content: flex-end; }
  .line-table td.actions::before { content: none; }
  /* The "no rows yet" message shouldn't look like a card. */
  .line-table .empty-row td {
    border: none;
    text-align: center !important;
    padding: var(--space-4) 0;
  }
  .line-table .empty-row td::before { content: none; }

  /* --- Multi-column inline forms collapse to one column ------------------- */
  .add-row-form,
  .wp-form { grid-template-columns: 1fr; }
  .add-row-form button,
  .wp-form button { width: 100%; }

  /* Weekly group header stacks the label above the subtotal. */
  .week-group-header { flex-direction: column; align-items: flex-start; gap: 4px; }

  /* Detail header actions go full width and split the row. */
  .detail-header-actions { width: 100%; }
  .detail-header-actions .btn-secondary { flex: 1; }

  /* Invoice + reportes adapt. */
  .invoice-header { flex-direction: column; gap: var(--space-3); }
  .invoice-meta { text-align: left; }
  .invoice-parties { grid-template-columns: 1fr; gap: var(--space-4); }
  .reportes-grid { grid-template-columns: 1fr; }
  .filter-bar { width: auto; }
}

/* ---------------------------------------------------------------------------
   15. REDUCED MOTION — if the OS asks to minimize animation (an accessibility
   setting), honor it: cut every transition and animation to near-instant.
   --------------------------------------------------------------------------- */
@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;
  }
}

/* ---------------------------------------------------------------------------
   16. GASTOS + RECEIPTS — the company-wide expense page (gastos.html) and the
   receipt-photo widget (receipt-ui.js) it shares with job-detail. Appended
   after the mobile layer, so anything phone-specific here carries its own
   @media block at the bottom.
   --------------------------------------------------------------------------- */

/* The add-expense form: row 1 is date/category/amount/description (mirrors
   job-detail's add-row-form), row 2 is job + receipt + submit. */
.gasto-form {
  display: grid;
  grid-template-columns: 150px 160px 140px 1fr;
  gap: var(--space-2);
  align-items: center;
}
.gasto-form input,
.gasto-form select {
  padding: 10px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font: inherit;
  background: var(--surface);
  min-width: 0;
}
.gasto-form input:focus,
.gasto-form select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-ring);
}
.gasto-form .gf-job     { grid-column: 1 / span 2; }
.gasto-form .gf-receipt { grid-column: 3; }
.gasto-form .gf-submit  { grid-column: 4; justify-self: end; }

/* job-detail's add-cost form: six controls don't fit one row, so it uses the
   same two-row shape as the gastos form — inputs on row 1, photo picker and
   submit on row 2. */
.add-row-form.has-photo { grid-template-columns: 150px 140px 150px 1fr; }
.add-row-form.has-photo .receipt-field { grid-column: 1 / 3; }
.add-row-form.has-photo button[type="submit"] { grid-column: 4; justify-self: end; }

/* Small pill buttons used by the receipt widget and the "Ver" cell. */
.btn-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 120ms ease, background 120ms ease;
}
.btn-chip:hover { border-color: var(--accent); color: var(--accent); }
.btn-chip:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-ring);
}
.btn-chip--danger:hover { border-color: #b3261e; color: #b3261e; }

/* The widget's container: chips sit in a row and wrap if cramped. */
.receipt-field {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  min-width: 0;
}
.receipt-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--accent-ring);
  color: var(--primary);
  font-size: 13px;
  font-weight: 600;
  max-width: 100%;
}
.receipt-chip__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 160px;
}
.receipt-note { font-size: 13px; color: var(--text-muted); }

/* Table cell with the "Ver" button — don't let it stretch. */
.line-table td.receipt-cell .btn-chip { padding: 4px 10px; }
.muted { color: var(--text-muted); }

/* Receipt lightbox — the photo, a close button, nothing else. */
.receipt-lightbox {
  border: none;
  border-radius: var(--radius-lg);
  padding: 0;
  background: var(--surface);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.35);
  max-width: min(92vw, 720px);
}
.receipt-lightbox::backdrop { background: rgba(30, 24, 18, 0.55); }
.receipt-lightbox__frame { position: relative; padding: var(--space-3); }
.receipt-lightbox img {
  display: block;
  max-width: 100%;
  max-height: 78vh;
  border-radius: var(--radius-sm);
  margin: 0 auto;
}
.receipt-lightbox__loading {
  margin: 0;
  padding: var(--space-6);
  text-align: center;
  color: var(--text-muted);
}
.receipt-lightbox__close {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 1;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 50%;
  background: rgba(30, 24, 18, 0.6);
  color: #fff;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.receipt-lightbox__close:hover { background: rgba(30, 24, 18, 0.8); }

/* Insights card on Reportes — sentences, not numbers to decode. */
.insights-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5) var(--space-6);
  margin-bottom: var(--space-5);
  box-shadow: var(--shadow-sm);
}
.insights-card h3 {
  margin: 0 0 var(--space-3);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  padding-left: 12px;
  position: relative;
}
.insights-card h3::before {
  content: "";
  position: absolute;
  left: 0;
  top: 3px;
  bottom: 3px;
  width: 4px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--accent), var(--primary));
}
.insights-card ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-2);
}
.insights-card li {
  font-size: 15px;
  line-height: 1.55;
  padding-left: 22px;
  position: relative;
}
.insights-card li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 9px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
}

@media (max-width: 720px) {
  .gasto-form { grid-template-columns: 1fr; }
  .gasto-form .gf-job,
  .gasto-form .gf-receipt,
  .gasto-form .gf-submit { grid-column: 1; justify-self: stretch; }
  .gasto-form .gf-submit { width: 100%; }
  .add-row-form.has-photo { grid-template-columns: 1fr; }
  /* The receipt cell in card view: keep label left, button right. */
  .line-table td.receipt-cell { justify-content: space-between; }
}

/* Filter bar wraps on narrow phones instead of pushing past the edge. */
@media (max-width: 720px) {
  .filter-bar { flex-wrap: wrap; row-gap: var(--space-2); }
  .filter-bar select { max-width: 100%; }
}

/* iOS Safari zooms the whole page when a focused control's font-size is
   under 16px — disorienting for non-technical users. On phones, every
   text-entry control gets exactly 16px so focus never triggers the zoom. */
@media (max-width: 720px) {
  input,
  select,
  textarea {
    font-size: 16px;
  }
}

/* "Ver todos / Mostrar más" — the reveal button under long tables. Tables
   show a manageable slice by default (job-detail: newest 8; gastos: pages of
   30) so a busy job never turns the page into an endless scroll; totals are
   always computed over the full data set, never the visible slice. */
.table-more {
  display: block;
  width: 100%;
  margin-top: var(--space-3);
  padding: 9px 12px;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
}
.table-more:hover { color: var(--accent); border-color: var(--accent); }
.table-more:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-ring);
}

/* On phones the two-row cost form collapses to one column — undo the
   desktop column spans or the grid grows a phantom second column. */
@media (max-width: 720px) {
  .add-row-form.has-photo .receipt-field,
  .add-row-form.has-photo button[type="submit"] {
    grid-column: 1;
    justify-self: stretch;
  }
}

/* Payroll form with the optional job link: inputs on row 1, job + note +
   submit on row 2 (same two-row shape as the cost forms). */
.wp-form.has-job { grid-template-columns: 1.3fr 150px 130px 130px; }
.wp-form.has-job .wpf-job    { grid-column: 1; }
.wp-form.has-job .wpf-note   { grid-column: 2 / 4; }
.wp-form.has-job .wpf-submit { grid-column: 4; justify-self: end; }

/* Quiet hint under the payroll form. */
.wp-hint {
  margin: var(--space-2) 0 0;
  font-size: 13px;
  color: var(--text-muted);
}

/* "auto" tag on app-maintained cost rows (weekly payroll). Replaces the
   edit/delete buttons — the row is derived data, edited via Trabajadores. */
.auto-tag {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--neutral-bg);
  color: var(--neutral-text);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  cursor: help;
}

@media (max-width: 720px) {
  .wp-form.has-job { grid-template-columns: 1fr; }
  .wp-form.has-job .wpf-job,
  .wp-form.has-job .wpf-note,
  .wp-form.has-job .wpf-submit { grid-column: 1; justify-self: stretch; }
}

/* Submit button in the payroll form: never let the label wrap to two lines. */
.wp-form .wpf-submit { white-space: nowrap; padding-left: 14px; padding-right: 14px; }

/* --- Mobile nav: always show all four destinations ------------------------
   The scrollable pill row hid "Reportes" past the right edge with no visual
   hint that it scrolls. On phones the links become a 4-up grid — icon above
   a small label — so every page is one visible tap, like app tabs. */
@media (max-width: 720px) {
  .nav-links {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 4px;
    overflow: visible;
    padding-bottom: 0;
  }
  .nav-link {
    flex-direction: column;
    justify-content: center;
    gap: 3px;
    padding: 7px 2px;
    font-size: 11.5px;
    border-radius: var(--radius-sm);
    text-align: center;
  }
  .nav-link svg { width: 19px; height: 19px; }
}

/* On narrow phones the account email forced the header onto a third row.
   The "Salir" link stays; who's signed in still shows on tablets and up. */
@media (max-width: 480px) {
  .user-pill .user-email { display: none; }
}

/* Section heading with an action beside it (e.g. "Repetir semana pasada"). */
.section-head-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}
.section-head-row h3 { margin: 0; }

/* Delete button inside the manage-workers dialog rows. */
.worker-row .worker-delete { flex-shrink: 0; }

/* --- Job progress vs the quote -------------------------------------------
   One bar: how much of the quoted amount has been collected. Collected money
   is "good", so the fill uses the money-green, never the brand red. */
.job-progress {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-5);
}
.progress-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.progress-label {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  flex-shrink: 0;
}
.progress-track {
  flex: 1;
  height: 10px;
  border-radius: var(--radius-pill);
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  width: 0;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, #2a8f54, var(--positive));
  transition: width 400ms cubic-bezier(0.4, 0, 0.2, 1);
}
.progress-value {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.over-budget-warning {
  margin: var(--space-3) 0 0;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  background: var(--negative-soft);
  color: var(--negative);
  font-size: 14px;
  font-weight: 600;
}
@media (max-width: 720px) {
  .progress-row { flex-wrap: wrap; }
  .progress-value { width: 100%; text-align: right; }
}

/* --- Invoice document, branded like the official ANJ logo -----------------
   The lockup is pure text so html2pdf renders it razor-sharp. Widths/sizes
   are tuned so the four lines align flush like the real logo. */
.invoice-logo { line-height: 1; }
.logo-anj {
  font-size: 58px;
  font-weight: 800;
  letter-spacing: 0.06em;
  margin-right: -0.06em;   /* trailing tracking would unbalance the lockup */
  color: var(--primary);
  line-height: 0.9;
}
.logo-company {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 17.5px;
  letter-spacing: 0.135em;
  margin-right: -0.135em;
  color: #23201d;
  text-transform: uppercase;
  margin-top: 9px;
}
.logo-rule {
  height: 1px;
  background: #c9c2ba;
  margin: 9px 0 8px;
}
.logo-tagline {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.09em;
  margin-right: -0.09em;
  color: var(--primary);
  text-transform: uppercase;
}
.logo-trades {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  margin-right: -0.18em;
  color: #23201d;
  text-transform: uppercase;
  margin-top: 5px;
}
/* Keep the lockup no wider than its own text so the rule matches the logo,
   and center the lines within it — same composition as the official lockup. */
.invoice-logo { display: inline-block; text-align: center; }

/* Header: the brand red carries the divider; INVOICE title echoes the ink. */
.invoice-header { border-bottom: 3px solid var(--primary); align-items: flex-end; }
.invoice-title { color: #23201d; font-size: 24px; letter-spacing: 0.18em; }

/* Balance Due is the one number the client acts on — it gets the brand red. */
.invoice-row.total { border-top: 2px solid var(--primary); }
.invoice-row.total .invoice-value { color: var(--primary); }

.invoice-footer {
  margin-top: var(--space-7);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  text-align: center;
}
.invoice-thanks {
  font-family: Georgia, 'Times New Roman', serif;
  font-style: italic;
  font-size: 14.5px;
  color: #23201d;
  margin-bottom: 6px;
}
.invoice-pay {
  font-size: 12.5px;
  color: #23201d;
  margin-bottom: 8px;
}
.invoice-contact {
  font-size: 11.5px;
  color: var(--text-muted);
  letter-spacing: 0.02em;
}
@media (max-width: 720px) {
  .logo-anj { font-size: 44px; }
  .invoice-header { align-items: flex-start; }
}

/* --- Progress photos (job detail) ----------------------------------------- */
.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: var(--space-3);
}
.photo-card {
  position: relative;
  margin: 0;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--surface-sunk);
}
.photo-card img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  cursor: zoom-in;
}
.photo-card figcaption {
  font-size: 10.5px;
  color: var(--text-muted);
  padding: 4px 7px;
  font-variant-numeric: tabular-nums;
}
.photo-delete {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 24px;
  height: 24px;
  border: none;
  border-radius: 50%;
  background: rgba(43, 36, 33, 0.65);
  color: #fff;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.photo-delete:hover { background: var(--primary); }

/* --- Cobros --------------------------------------------------------------- */
.row-link { color: var(--text); font-weight: 600; text-decoration: none; }
.row-link:hover { color: var(--primary); text-decoration: underline; }
.btn-small { padding: 6px 12px; font-size: 12.5px; text-decoration: none; display: inline-flex; align-items: center; }
.cobro-balance { font-weight: 800; color: var(--primary); }
.cobro-stale td:first-child { border-left: 3px solid var(--accent); }
.unpriced-list { margin: 0; padding-left: 18px; }
.unpriced-list li { padding: 4px 0; }

/* --- Presupuestos --------------------------------------------------------- */
.status-draft    { background: var(--neutral-bg); color: var(--neutral-text); }
.status-sent     { background: var(--info-bg);    color: var(--info-text); }
.status-accepted { background: var(--success-bg); color: var(--success-text); }
.status-rejected { background: var(--warn-bg);    color: var(--warn-text); }
.quote-actions { white-space: nowrap; }
.page-head-actions { display: flex; gap: var(--space-2); align-items: center; }

/* --- Estimate document ----------------------------------------------------- */
.quote-scope {
  margin: 6px 0 0;
  font-size: 13.5px;
  line-height: 1.65;
  white-space: pre-line;   /* the scope keeps its typed line breaks */
}
.quote-validity {
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 8px;
}

/* --- Mobile nav now holds five tabs ---------------------------------------
   auto-fit keeps every page's tab row filling the width whatever the count;
   the tighter type keeps "Trabajadores" on one line at 390px wide. */
@media (max-width: 720px) {
  .nav-links { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }
  .nav-link { font-size: 10.8px; padding-left: 1px; padding-right: 1px; }
  .page-head-actions { width: 100%; flex-direction: column; align-items: stretch; }
  .page-head-actions .btn-secondary { justify-content: center; }
}
