/* Mobile-first. No framework. Clean, big tap targets. */

:root {
  --bg: #f6f5f1;
  --card: #ffffff;
  --ink: #1a1a1a;
  --ink-soft: #555;
  --line: #e4e2dc;
  --line-strong: #d0ccc2;
  --accent: #2a6f4b;
  /* RGB triplet of --accent. Component styles that need a translucent
     accent tint use rgba(var(--accent-rgb), <alpha>) instead of a
     hardcoded rgba() — that way the tradie theme override below re-tints
     every focus ring / selected-row / pill background in one place. */
  --accent-rgb: 42, 111, 75;
  --accent-hover: #225a3c;
  --danger: #b1442b;
  --danger-soft: #fff0ec;
  --radius: 10px;
  --gap: 12px;
}

/* ---- Tradie colour theme ----
   Applied when auth-guard.js sets <html data-account-type="TRADIE"> after
   reading /api/me. Stripe-inspired: white-dominant, neutral grey + black,
   with a premium dark-navy ACCENT (WashBot brand) — it appears only on
   primary action buttons, links, the active nav tab, focused input
   borders and form accents (checkboxes/toggles). Everything else is
   white / grey / black. Cards are white, defined by a thin grey border
   rather than a fill. accent tints (rgba(var(--accent-rgb), …)) are
   deliberately kept at very low opacity so backgrounds stay near-white.
   Builder keeps the green palette in :root. Tweak the values below. */
[data-account-type="TRADIE"] {
  --bg: #ffffff;            /* pure white page background */
  --card: #ffffff;          /* white cards — defined by border, not fill */
  --ink: #1a1a1a;           /* near-black — headings, primary text */
  --ink-soft: #6b7280;      /* medium grey — secondary text, labels */
  --line: #e5e7eb;          /* light grey — borders, dividers */
  --line-strong: #d1d5db;   /* slightly darker grey — emphasis borders */
  --accent: #1e3a5f;        /* dark navy — buttons, links, active nav, focus ONLY */
  --accent-rgb: 30, 58, 95;
  --accent-hover: #162d4d;  /* darker navy — hover / pressed only */
  --danger: #dc2626;        /* universal red — kept */
  --danger-soft: #fef2f2;   /* light red tint */
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  line-height: 1.4;
  -webkit-text-size-adjust: 100%;
}

main {
  max-width: 720px;
  margin: 0 auto;
  /* Top: 12px breathing room above the page H1 (the topbar that used to
     occupy this space was removed in the mobile-first redesign).
     Bottom: clear the fixed bottom-nav (~64px) PLUS the iPhone home-indicator
     safe area, so the last card never sits under the tab bar. */
  padding: 12px 16px calc(76px + env(safe-area-inset-bottom));
}

/* Template editor pages don't have a bottom-nav but DO have a sticky save
   bar (~80px) — bump the bottom padding so the last form row clears it. */
body.has-sticky-save main {
  padding-bottom: calc(96px + env(safe-area-inset-bottom));
}

/* Project detail page now keeps the bottom of the screen clean by
   default — Save as template and Select moved into the header, so the
   only fixed UI at the bottom is the global bottom-nav. The floating
   bulk-delete bar appears only when at least one job is checked; while
   it's visible we add `body.has-bulk-bar` so main's bottom padding
   grows enough that the last job row doesn't tuck under the bar. */
body.has-bulk-bar.has-bottom-nav main {
  padding-bottom: calc(160px + env(safe-area-inset-bottom));
}

header {
  margin-bottom: 24px;
}

header h1 {
  margin: 0 0 4px;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.subtitle {
  margin: 0;
  color: var(--ink-soft);
  font-size: 15px;
}

/* ---- Fields ---- */

.field {
  display: flex;
  flex-direction: column;
  margin-bottom: var(--gap);
}
/* `.field` sets display:flex, which beats the UA [hidden] rule — so a
   hidden field row would still show. This restores `hidden` for any
   .field element (account-type-conditional form rows rely on it). */
.field[hidden] { display: none; }

.field-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 6px;
}

.optional {
  color: var(--ink-soft);
  font-weight: 400;
}

input[type="text"],
input[type="number"],
input[type="search"],
input[type="email"],
input[type="tel"],
input[type="date"] {
  font: inherit;
  padding: 12px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  min-height: 48px; /* tap target */
  width: 100%;
}

/* Date input on iOS Safari renders a tiny native picker that visually
   doesn't match the other inputs — adding `appearance: none` + a
   trailing calendar icon would over-engineer the styling, so we just
   match the surrounding inputs and let the native picker open on tap. */
input[type="date"] {
  -webkit-appearance: none;
  appearance: none;
  /* Date inputs on iOS Safari ignore some text-input padding tweaks; the
     min-height + padding above is the right combination to land vertically
     centred next to a sibling text input. */
}

input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.18);
}

input.has-error {
  border-color: var(--danger);
  background: var(--danger-soft);
}

.field-error {
  display: none;
  color: var(--danger);
  font-size: 13px;
  margin-top: 6px;
}

.field-error.visible { display: block; }

/* Inline checkbox row — used for the per-step "📦 Delivery" toggle in the
   template editor. Tap target stays at 48px so it's thumb-friendly. */
.field-checkbox {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: var(--gap);
  padding: 10px 4px;
  font-size: 14px;
  cursor: pointer;
  user-select: none;
}
.field-checkbox input[type="checkbox"] {
  width: 22px;
  height: 22px;
  margin: 0;
  flex: 0 0 auto;
  accent-color: var(--accent);
  cursor: pointer;
}
.field-checkbox span {
  color: var(--ink);
  font-weight: 600;
}

/* Bulk day-offset controls at the top of the step list. Sit above the rows
   in their own panel so they don't get visually swallowed by the rows. */
.bulk-offset {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 12px;
  margin: 8px 0 12px;
}
.bulk-offset-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
}

/* Tiny pill buttons reused by bulk-offset + per-row "shift from here". */
.btn-tiny {
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  padding: 6px 10px;
  min-height: 32px;
  width: auto;
  border-radius: 6px;
  border: 1px solid var(--line-strong);
  background: var(--card);
  color: var(--ink);
  cursor: pointer;
}
.btn-tiny:hover,
.btn-tiny:focus {
  background: rgba(0, 0, 0, 0.04);
  border-color: var(--ink-soft);
  outline: none;
}

/* Brief flash applied to a step's day input when the bulk-offset shift runs.
   Pure visual feedback — confirms the click landed when the value change
   could otherwise be missed on a long step list. */
.day-flash {
  animation: day-flash 600ms ease-out;
}
@keyframes day-flash {
  0%   { background: rgba(var(--accent-rgb), 0.30); }
  100% { background: var(--card); }
}

/* Per-step "shift from here" popover. Tapping a day cell opens this inline
   panel — applies a +/- shift to THIS step and every step below it. */
.step-shift {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 6px 0 0;
  padding: 6px 8px;
  background: rgba(var(--accent-rgb), 0.08);
  border: 1px solid rgba(var(--accent-rgb), 0.25);
  border-radius: 6px;
  font-size: 12px;
}
.step-shift-label {
  color: var(--ink-soft);
  font-weight: 600;
  margin-right: 4px;
}

/* Delivery rows look distinct so a glance over the editor surfaces which
   steps are 0-day deliveries vs real work days. */
.row.is-delivery {
  background: #fffbe6;
  border-color: #e6dfb8;
}
.row.is-delivery [data-end-day-field] {
  display: none;
}

/* Pair of narrow fields side-by-side (Start Day / End Day). */
.field-pair {
  display: flex;
  gap: var(--gap);
}

.field-pair .field {
  flex: 1;
  min-width: 0;
}

/* ---- Rows ---- */

.rows { margin-top: 8px; }

#rows-container > .row {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: var(--gap);
}

.row-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.row-number {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.row-delete {
  background: transparent;
  border: 1px solid var(--line-strong);
  color: var(--ink-soft);
  width: 36px;
  height: 36px;
  border-radius: 50%;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.row-delete:hover,
.row-delete:focus {
  background: var(--danger-soft);
  border-color: var(--danger);
  color: var(--danger);
  outline: none;
}

/* ---- Buttons ---- */

.btn {
  font: inherit;
  font-weight: 600;
  padding: 14px 20px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
  min-height: 48px;
  width: 100%;
  transition: background-color 120ms, border-color 120ms, color 120ms;
}

.btn-primary {
  background: var(--accent);
  color: #fff;
  margin-top: 16px;
}

.btn-primary:hover,
.btn-primary:focus { background: var(--accent-hover); outline: none; }

.btn-primary:disabled {
  background: var(--line-strong);
  cursor: not-allowed;
}

/* Loading state. Keep the primary colour so the button stays recognisable
   (the previous greyed-out state read like "broken"); just dim slightly
   and swap in a spinner. is-loading is set by JS — see template/apply.js. */
.btn-primary.is-loading {
  background: var(--accent);
  color: #fff;
  opacity: 0.72;
  cursor: progress;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.btn-primary.is-loading:hover { background: var(--accent); }

.btn-spinner {
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 2px solid rgba(255, 255, 255, 0.45);
  border-top-color: #fff;
  border-radius: 50%;
  animation: btn-spin 700ms linear infinite;
  flex: 0 0 auto;
}
.btn-loading-label {
  font-weight: 600;
  letter-spacing: 0.01em;
}

@keyframes btn-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.btn-secondary {
  background: transparent;
  color: var(--accent);
  border-color: var(--accent);
  margin-top: 4px;
}

.btn-secondary:hover,
.btn-secondary:focus {
  background: rgba(var(--accent-rgb), 0.08);
  outline: none;
}

/* ---- Status / messages ---- */

#form-message {
  margin-top: 16px;
  font-size: 14px;
  min-height: 1.2em;
}

#form-message.success {
  color: var(--accent);
  font-weight: 600;
}

#form-message.error {
  color: var(--danger);
  font-weight: 600;
}

/* ---- Wider screens: put fields side-by-side where space allows ---- */

@media (min-width: 640px) {
  main { padding: 28px 24px 80px; }

  header h1 { font-size: 30px; }

  .row-grid-wide .row > .field:not(.field-full),
  #rows-container > .row .field-pair { /* keep start/end paired */ }

  /* Save button doesn't need to be full-width on tablet+ */
  .btn-primary {
    width: auto;
    min-width: 220px;
    display: inline-block;
  }
  .btn-secondary { width: auto; display: inline-block; }
}

/* ---- Shared nav header (every template page) ---- */

.nav {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 0 16px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 16px;
}

.nav-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 8px 14px;
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}
.nav-back:hover,
.nav-back:focus {
  background: rgba(0, 0, 0, 0.04);
  border-color: var(--ink-soft);
  outline: none;
}

.nav-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink-soft);
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}

/* Legacy back-link (kept so old markup still renders OK) */
.back-link {
  display: inline-block;
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 14px;
  margin-bottom: 12px;
}
.back-link:hover { color: var(--ink); }

.header-actions {
  margin-top: 12px;
}

/* ---- Flash/toast (shown on /templates after create/edit/delete) ---- */

.flash {
  padding: 12px 16px;
  border-radius: var(--radius);
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 16px;
  background: rgba(var(--accent-rgb), 0.12);
  color: var(--accent-hover);
  border: 1px solid rgba(var(--accent-rgb), 0.28);
  animation: flash-in 180ms ease-out;
}
.flash.error {
  background: var(--danger-soft);
  color: var(--danger);
  border-color: rgba(177, 68, 43, 0.35);
}
@keyframes flash-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---- Template list page ---- */

.template-list {
  list-style: none;
  padding: 0;
  margin: 16px 0 0;
}

.template-item {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: var(--gap);
}

.template-item-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
  flex-wrap: wrap;
}

.template-item-name {
  font-size: 18px;
  font-weight: 700;
  margin: 0;
  color: var(--ink);
}

.template-item-meta {
  color: var(--ink-soft);
  font-size: 13px;
}

.template-item-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.template-item-actions .btn {
  width: auto;
  padding: 10px 14px;
  min-height: 40px;
  font-size: 14px;
  flex: 1 1 auto;
}

@media (min-width: 640px) {
  .template-item-actions .btn { flex: 0 0 auto; }
}

.btn-danger {
  background: transparent;
  color: var(--danger);
  border-color: var(--danger);
}
.btn-danger:hover,
.btn-danger:focus {
  background: var(--danger-soft);
  outline: none;
}

.empty-state {
  text-align: center;
  padding: 40px 20px;
  color: var(--ink-soft);
}
.empty-state a { color: var(--accent); }

/* ---- Apply page summary ---- */

.apply-summary {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-top: 16px;
}

.apply-summary h2 {
  margin: 0 0 8px;
  font-size: 16px;
}

.apply-summary ul {
  margin: 0;
  padding-left: 20px;
  font-size: 14px;
  color: var(--ink-soft);
}
.apply-summary li { margin-bottom: 4px; }

/* ---- Loading state ---- */
.loading {
  color: var(--ink-soft);
  font-size: 14px;
  padding: 20px 0;
}

/* ---- Auth guard: hide body until /api/me resolves ----
   Prevents a flash of protected content before the 401 redirect fires.
   The guard script toggles this class off as soon as the probe returns. */
html.auth-pending body { visibility: hidden; }

/* ---- Settings page ---- */

.settings-section {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: var(--gap);
}

.settings-section-title {
  margin: 0 0 12px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.settings-row {
  display: flex;
  flex-direction: column;
  padding: 10px 0;
  border-top: 1px solid var(--line);
  gap: 4px;
}
.settings-row:first-of-type { border-top: none; padding-top: 0; }

.settings-label {
  font-size: 12px;
  color: var(--ink-soft);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.settings-value {
  font-size: 16px;
  color: var(--ink);
  word-break: break-word;
}

.settings-hint {
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 400;
}

/* ---- First-run checklist (top of /templates) ---- */

.checklist {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 20px;
}

.checklist-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 12px;
}

.checklist-title {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
}

.checklist-progress {
  font-size: 13px;
  color: var(--ink-soft);
  font-weight: 600;
}

.checklist-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid var(--line);
}
.checklist-item:first-of-type { border-top: none; padding-top: 4px; }

.checklist-num {
  flex: 0 0 28px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--bg);
  border: 1px solid var(--line-strong);
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 2px;
}

.checklist-item.is-done .checklist-num {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
.checklist-item.is-done .checklist-num::after {
  content: '✓';
}
.checklist-item.is-done .checklist-num-text { display: none; }
.checklist-item.is-done .checklist-action { display: none; }

.checklist-body {
  flex: 1;
  min-width: 0;
}

.checklist-item-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 2px;
}

.checklist-item-desc {
  font-size: 13px;
  color: var(--ink-soft);
  margin: 0 0 6px;
}

.checklist-action {
  display: inline-block;
  color: var(--accent);
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
}
.checklist-action:hover,
.checklist-action:focus { text-decoration: underline; outline: none; }

.checklist-item.is-done .checklist-item-title {
  color: var(--ink-soft);
  text-decoration: line-through;
}

/* ---- Top bar: brand + tabs + account ---- */
/* Layout:
     mobile (<800px): brand + account on row 1, tabs full-width on row 2
     desktop (>=800px): brand | tabs | account all on a single row
   Built with flex-wrap + flex-basis switching at the breakpoint, no JS. */

.topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  margin: 0 -16px 16px;
  padding: 6px 16px 0;
  border-bottom: 1px solid var(--line);
}

.topbar-brand {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--accent);
  text-decoration: none;
  padding: 6px 0;
}
.topbar-brand:hover { color: var(--accent-hover); }

.topbar-account {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

.topbar-user {
  font-weight: 600;
  color: var(--ink);
}

.topbar-logout-form { margin: 0; }

.topbar-logout {
  background: transparent;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: 13px;
  color: var(--ink-soft);
  cursor: pointer;
  text-decoration: none;
}
.topbar-logout:hover { color: var(--danger); }

/* ---- Section tabs (Templates | Vendors | Contacts | Projects | Settings) ---- */

.tabs {
  display: flex;
  gap: 0;
  border-bottom: 0;        /* topbar's border-bottom owns the horizontal rule */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  flex-basis: 100%;        /* full-width row on mobile (under .topbar wrap) */
  margin: 0 -16px;
  padding: 0 8px;
}

.tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 10px 12px;
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 15px;
  font-weight: 500;        /* inactive: 500 weight per brief */
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  white-space: nowrap;
}

.tab:hover,
.tab:focus {
  color: var(--ink);
  outline: none;
}

.tab.is-active {
  color: var(--ink);
  font-weight: 600;        /* active: 600 weight per brief */
  border-bottom-color: var(--accent);
}

/* Tradie theme: filter tabs are navigation, not an action — the active
   tab gets a neutral dark underline (+ the bold weight above), never the
   aqua accent. Aqua stays reserved for buttons / links / active nav. */
[data-account-type="TRADIE"] .tab.is-active {
  border-bottom-color: var(--ink);
}

/* Standalone tabs row (no surrounding topbar) — e.g. /projects status filter.
   Restores the bleeding-edge horizontal margin + bottom border behaviour the
   tabs USED to have when they were the page's primary nav. */
.tabs-standalone {
  margin: 0 -16px 16px;
  padding: 0 16px;
  border-bottom: 1px solid var(--line);
}

@media (min-width: 800px) {
  .topbar {
    flex-wrap: nowrap;
    margin: 0 0 24px;
    padding: 0;
  }
  .tabs {
    flex: 1 1 auto;
    flex-basis: auto;
    margin: 0 16px;
    padding: 0;
  }
  .tabs-standalone {
    margin: 0 0 20px;
    padding: 0;
  }
}

/* ---- Type pill (Company / Individual) ---- */

.pill {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: rgba(0, 0, 0, 0.06);
  color: var(--ink-soft);
  margin-left: 8px;
  vertical-align: middle;
}
.pill.pill-company    { background: rgba(var(--accent-rgb), 0.14); color: var(--accent-hover); }
.pill.pill-individual { background: rgba(66, 108, 168, 0.14); color: #2c4b77; }

/* ---- Select dropdown (vendor picker) ---- */

select {
  font: inherit;
  padding: 12px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  min-height: 48px;
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23555' d='M6 8L0 0h12z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  padding-right: 40px;
}
select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.18);
}

textarea {
  font: inherit;
  padding: 12px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  width: 100%;
  min-height: 96px;
  resize: vertical;
}
textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.18);
}

/* ---- Vendor combobox ---- */
/* Searchable dropdown that wraps an existing <input data-field="vendor_name">
   and adds a panel below. See public/template/vendor-combobox.js for the
   behaviour. Pure positioning + visuals here. */

.combobox {
  position: relative;
  width: 100%;
}

.combobox-input {
  /* Inherits the existing input[type="text"] styling — no override needed. */
}

.combobox-panel {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 50;
  max-height: 280px;
  overflow-y: auto;
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
}

.combobox-list {
  list-style: none;
  margin: 0;
  padding: 4px 0;
}

.combobox-item {
  display: flex;
  flex-direction: column;
  padding: 10px 14px;
  cursor: pointer;
  border-bottom: 1px solid var(--line);
}
.combobox-item:last-child { border-bottom: none; }

.combobox-item.is-active,
.combobox-item:hover {
  background: rgba(var(--accent-rgb), 0.08);
}

.combobox-item-name {
  font-size: 15px;
  color: var(--ink);
}

.combobox-item-trade {
  font-size: 13px;
  color: var(--ink-soft);
  margin-top: 2px;
}

.combobox-empty {
  padding: 14px;
  color: var(--ink-soft);
  font-size: 14px;
  text-align: center;
  list-style: none;
}

.combobox-add-new {
  padding: 12px 14px;
  cursor: pointer;
  font-size: 14px;
  color: var(--accent);
  background: rgba(var(--accent-rgb), 0.04);
  border-top: 1px solid var(--line);
  list-style: none;
}
.combobox-add-new.is-active,
.combobox-add-new:hover {
  background: rgba(var(--accent-rgb), 0.12);
}
.combobox-add-icon {
  display: inline-block;
  width: 18px;
  text-align: center;
  font-weight: 700;
  margin-right: 4px;
}

/* ---- Inline-create section (shown after clicking "+ Add new vendor") ---- */

.combobox-create {
  padding: 12px 14px;
  background: var(--card);
}

.combobox-create-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 10px;
}

.combobox-create-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.combobox-create-label {
  flex: 0 0 56px;
  font-size: 13px;
  color: var(--ink-soft);
}

.combobox-create-row input {
  flex: 1 1 auto;
  padding: 8px 10px;
  font-size: 14px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background: var(--card);
  color: var(--ink);
}

.combobox-create-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 8px;
}

.combobox-create-error {
  font-size: 13px;
  color: var(--danger);
  margin-top: 6px;
  min-height: 1em;
}

.btn-tiny {
  padding: 6px 12px;
  font-size: 13px;
  width: auto;
}

/* ---- Projects page (Round 2) ---- */
/* Renders each project as a card with name + status pill, address, dates,
   activity-context line, and an inline button row to flip status. Most
   styles below are scoped under .project-card to avoid collision with the
   shared .template-item used elsewhere. */

.projects-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin: 12px 0 16px;
}

.projects-controls input[type="search"] {
  flex: 1 1 220px;
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  font: inherit;
  -webkit-appearance: none;
}
.projects-controls input[type="search"]:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.18);
}

.sort-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--ink-soft);
}

.sort-label select {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
}

/* Lower-prominence tab variant — used for the Archived filter so it visibly
   sits apart from the everyday Active/Paused/Complete tabs. */
.tab-quiet {
  opacity: 0.55;
}
.tab-quiet:hover,
.tab-quiet.is-active {
  opacity: 1;
}

/* Card container. Wider footprint than .template-item — needs room for the
   activity-context line + a four-button action row. */
.project-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 10px;
  list-style: none;
}

.project-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.project-name {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.project-address {
  font-size: 13px;
  color: var(--ink-soft);
}

/* Customer name on a job card — tradie accounts only (projects.js gates
   rendering on account type). Slightly emphasised vs the address so the
   "whose job is this" reads at a glance. */
.project-customer {
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  margin-top: 2px;
}

/* Editable Customer Name field on the project detail header — tradie
   accounts only (detail.js unhides it). Extra top margin separates it
   from the status/dates meta row above. */
.customer-name-field {
  margin-top: 14px;
}
.customer-name-field[hidden] { display: none; }

.project-meta {
  font-size: 13px;
  color: var(--ink-soft);
}

.project-context {
  margin-top: 8px;
  font-size: 14px;
  color: var(--ink);
  line-height: 1.45;
}
.project-context a {
  color: var(--accent);
  text-decoration: underline;
}

/* Status pills. Colour-coded per status. Sized to sit inline next to the
   project name without dominating the card. */
.status-pill {
  display: inline-block;
  padding: 2px 10px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 999px;
  background: #ececea;
  color: var(--ink);
  vertical-align: middle;
  letter-spacing: 0.01em;
}
/* ---- Apply-template success card ----
   Replaces the old raw bullet-list of every booked job. The headline
   (count + delivery count + project name) is the lead; everything else
   is supporting context. Two stacked-on-mobile buttons sit at the bottom,
   primary action ("Go to project") sized for thumb tap. */

.success-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 28px 20px 20px;
  margin-top: 16px;
  text-align: center;
}

.success-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: rgba(var(--accent-rgb), 0.15);
  color: var(--accent);
  font-size: 32px;
  font-weight: 700;
  margin: 0 auto 16px;
  line-height: 1;
}

.success-headline {
  margin: 0 0 6px;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.success-range {
  margin: 0;
  color: var(--ink-soft);
  font-size: 14px;
  font-weight: 500;
}

.success-note {
  margin-top: 12px;
  padding: 10px 12px;
  background: #fff8eb;
  border: 1px solid #f0d8a0;
  border-radius: var(--radius);
  color: #6a4900;
  font-size: 13px;
}

.success-details {
  text-align: left;
  margin-top: 14px;
  padding: 10px 12px;
  background: rgba(0, 0, 0, 0.03);
  border-radius: var(--radius);
  font-size: 13px;
}
.success-details summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--ink);
}
.success-details ul {
  margin: 8px 0 0;
  padding-left: 18px;
  color: var(--ink-soft);
}
.success-sub-head {
  margin: 10px 0 4px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
}
.success-sub-note {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--ink-soft);
}

.success-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 20px;
}
.success-btn-primary,
.success-btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  margin-top: 0;     /* override .btn-primary's 16px top */
  width: 100%;
}

@media (min-width: 640px) {
  .success-actions {
    flex-direction: row;
    justify-content: center;
  }
  .success-btn-primary,
  .success-btn-secondary {
    width: auto;
    min-width: 180px;
  }
}

/* The project-head wrapper is a tappable link on the projects list page —
   strip default link styling so the card content keeps its mobile look. */
.project-head-link {
  display: block;
  text-decoration: none;
  color: inherit;
  border-radius: var(--radius);
}
.project-head-link:hover .project-name,
.project-head-link:focus .project-name {
  text-decoration: underline;
}

/* ---- Project detail page (job list) ----
   The detail page reuses the dashboard typography + bottom nav. Job rows
   are mobile-first cards with three lines (head, meta, foot) so the most
   important info — what + who + when — reads at a glance on phone. */

.project-meta-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  flex-wrap: wrap;
}

.job-list {
  list-style: none;
  padding: 0;
  margin: 12px 0 0;
}

.job-row {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 10px;
  position: relative;
}

.job-row.is-delivery {
  background: #fffbe6;
  border-color: #e6dfb8;
  padding: 10px 14px;     /* slightly tighter — deliveries read as
                             attached anchors, not headline jobs */
  font-size: 14px;
}
.job-row.is-delivery .job-description {
  font-weight: 600;
}

.job-row-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.job-emoji {
  font-size: 18px;
  line-height: 1;
  flex: 0 0 auto;
}

.job-row-headlines {
  flex: 1 1 auto;
  min-width: 0;
}

.job-description {
  font-weight: 700;
  font-size: 15px;
  color: var(--ink);
}


.job-day-badge {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  background: rgba(var(--accent-rgb), 0.1);
  padding: 3px 8px;
  border-radius: 999px;
}

.job-row-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 6px;
  font-size: 13px;
  color: var(--ink-soft);
}
.job-trade  { font-style: italic; }
.job-meta-sep { color: var(--line-strong); }

/* Vendor pill — tappable. Shows a faint pencil icon on hover/focus to
   signal interactivity. 48px min tap target on mobile. Same dashed-border
   visual family as the date pill so the row's interactive elements feel
   uniform. */
.job-vendor-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  background: transparent;
  border: 1px dashed var(--line-strong);
  padding: 10px 12px;
  min-height: 40px;
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.job-vendor-pill:hover,
.job-vendor-pill:focus {
  background: rgba(var(--accent-rgb), 0.06);
  border-color: var(--accent);
  outline: none;
}
.job-vendor-text { font-weight: 700; }
.job-vendor-edit-hint {
  font-size: 12px;
  color: var(--ink-soft);
  opacity: 0;
  transition: opacity 100ms ease-out;
}
.job-vendor-pill:hover .job-vendor-edit-hint,
.job-vendor-pill:focus .job-vendor-edit-hint {
  opacity: 1;
}
/* Touch devices don't have a hover state to reveal the pencil — show it
   permanently at slightly lower contrast so the affordance still reads. */
@media (hover: none) {
  .job-vendor-edit-hint { opacity: 0.5; }
}

/* Inline vendor picker, anchored under the row. Wide enough to host a
   full combobox (input + dropdown panel). Max-height + scroll on
   constrained viewports so the panel doesn't push the bottom-nav off
   screen. */
.job-vendor-popover {
  margin-top: 10px;
  padding: 12px;
  background: rgba(var(--accent-rgb), 0.06);
  border: 1px solid rgba(var(--accent-rgb), 0.25);
  border-radius: 8px;
}
.job-vendor-actions {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  justify-content: flex-end;
}
.job-vendor-input {
  width: 100%;
}

/* Multi-day badge moved to its own row below the description headline.
   Subtle pill — supplementary info, not headline material. */
.job-multi-row {
  margin-top: 4px;
}
.job-multi {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: rgba(0, 0, 0, 0.04);
  padding: 2px 8px;
  border-radius: 999px;
}

.job-row-foot {
  margin-top: 10px;
}

/* Date pill — plain tappable button. No invisible-input overlay any
   more (that pattern was unreliable across re-renders); detail.js
   spawns a fresh <input type="date">.showPicker() on demand inside
   the user-gesture click handler. Visual tier mirrors the duration +
   vendor pills for a uniform foot row. */
.job-date-pill {
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  background: transparent;
  border: 1px dashed var(--line-strong);
  padding: 12px 14px;
  min-height: 48px;
  border-radius: 8px;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  display: inline-flex;
  align-items: center;
  text-align: left;
}
.job-date-pill:hover,
.job-date-pill:focus {
  background: rgba(var(--accent-rgb), 0.06);
  border-color: var(--accent);
  outline: none;
}
.job-date-display {
  /* Plain inline span — no pointer-events trick needed now that the
     pill is a button. Kept as a separate element for future styling. */
}

/* ---- Date pill action sheet ----
   Inline panel that appears below the row when the date pill is tapped.
   Two stacked tap-target buttons: "Change date" (opens native picker) +
   "Shift from here" (opens the local stepper). Designed to be obvious
   and large enough for thumb-tapping on phones. */
.job-date-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
  padding: 6px;
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.06);
}
.job-date-action-btn {
  display: flex;
  align-items: center;
  gap: 12px;
  font: inherit;
  text-align: left;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 10px 12px;
  min-height: 56px;
  cursor: pointer;
  color: var(--ink);
  -webkit-tap-highlight-color: transparent;
}
.job-date-action-btn:hover,
.job-date-action-btn:focus {
  background: rgba(var(--accent-rgb), 0.06);
  border-color: var(--accent);
  outline: none;
}
.job-date-action-icon {
  font-size: 20px;
  width: 28px;
  text-align: center;
  flex: 0 0 auto;
  color: var(--ink-soft);
}
.job-date-action-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 auto;
  min-width: 0;
}
.job-date-action-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
}
.job-date-action-sub {
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft);
}

/* ---- Shift-from-here panel ----
   Replaces the action sheet when the supervisor picks "Shift from here".
   Same stepper visual family as the global bulk-shift, scoped to a
   single row + the jobs after it. Sits inside the row so it scrolls
   with the row context. */
.job-shift-from {
  margin-top: 10px;
  padding: 12px;
  background: rgba(var(--accent-rgb), 0.06);
  border: 1px solid rgba(var(--accent-rgb), 0.25);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.job-shift-from-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.job-shift-from-actions {
  display: flex;
  justify-content: flex-end;
}
.job-shift-from .shift-actions {
  /* Same flex 1 1 140px treatment as the global stepper so both buttons
     share the row on tablet but stack on phone via wrap. */
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.job-shift-from .shift-action-btn {
  flex: 1 1 140px;
}

/* Duration pill — work-job rows only. Lives next to the date pill in the
   foot row; tapping opens the +/- editor. Static "delivery" tag uses the
   same visual but is non-interactive (deliveries are zero-duration). */
.job-duration-btn,
.job-duration-static {
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  padding: 8px 12px;
  border-radius: 8px;
  border: 1px solid var(--line-strong);
  background: var(--card);
  color: var(--ink);
  margin-left: 6px;
}
.job-duration-btn { cursor: pointer; }
.job-duration-btn:hover,
.job-duration-btn:focus {
  background: rgba(var(--accent-rgb), 0.06);
  border-color: var(--accent);
  outline: none;
}
.job-duration-static {
  color: var(--ink-soft);
  background: rgba(0, 0, 0, 0.03);
  cursor: default;
}

/* Per-row delete button — small but tap-target-safe (40px square). Sits
   in the row head so it lines up with the description, doesn't compete
   with foot actions. */
.job-delete-btn {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--ink-soft);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 8px;
}
.job-delete-btn:hover,
.job-delete-btn:focus {
  background: var(--danger-soft);
  border-color: var(--danger);
  color: var(--danger);
  outline: none;
}

/* Inline duration editor below the foot row. Same visual family as the
   shift-from-here popover — both are row-scoped accent panels. */
.job-duration-popover {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding: 8px 10px;
  background: rgba(var(--accent-rgb), 0.08);
  border: 1px solid rgba(var(--accent-rgb), 0.25);
  border-radius: 8px;
  font-size: 13px;
  flex-wrap: wrap;
}
.job-duration-pop-label {
  color: var(--ink-soft);
  font-weight: 600;
}
.job-duration-pop-value {
  font-weight: 700;
  color: var(--ink);
  min-width: 40px;
  text-align: center;
}
.btn-tiny.btn-primary-tiny {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
  margin-left: auto;
}

/* Add-job button + collapsible form. Button is full-width on mobile to
   match the dashed "+ Add row" pattern in the template editor; form sits
   in a card so it visually separates from the existing job list. */
.add-job-btn {
  display: block;
  width: 100%;
  margin-top: 12px;
}
.add-job-form {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-top: 12px;
}
.add-job-title {
  margin: 0 0 12px;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
}
.add-job-actions {
  display: flex;
  gap: 10px;
  margin-top: 12px;
  flex-wrap: wrap;
}
.add-job-actions .btn {
  flex: 1 1 auto;
  margin-top: 0;
  width: auto;
}

/* ---- Bulk-shift stepper (project detail) ----
   Two-row block:
     [◀ −]  [N]  [+ ▶]              ← stepper picks the day count
     [◀ Back N days]  [Forward N days ▶] ← action buttons execute
   Big tap targets (48px+) — tradies on phones, gloves possibly on. */
.shift-stepper-wrap {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px 14px;
  margin: 8px 0 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.shift-stepper-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
}
.shift-stepper {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
}
.shift-step-btn {
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  cursor: pointer;
  min-width: 64px;
  min-height: 48px;
  padding: 8px 14px;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.shift-step-btn:hover:not(:disabled),
.shift-step-btn:focus:not(:disabled) {
  background: rgba(var(--accent-rgb), 0.08);
  border-color: var(--accent);
  outline: none;
}
.shift-step-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.shift-step-value {
  font-size: 28px;
  font-weight: 800;
  color: var(--ink);
  letter-spacing: -0.01em;
  min-width: 56px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.shift-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.shift-action-btn {
  flex: 1 1 140px;
  min-height: 48px;
  width: auto;
  margin-top: 0;
  padding: 12px 16px;
  font-size: 14px;
  font-weight: 700;
  background: var(--card);
  color: var(--ink);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
}
.shift-action-btn:hover:not(:disabled),
.shift-action-btn:focus:not(:disabled) {
  background: rgba(var(--accent-rgb), 0.06);
  border-color: var(--accent);
  outline: none;
}
.shift-action-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ---- Header actions row (project detail) ----
   Save as template + Select live here as small inline buttons in the
   project header, NOT as standalone toolbar cards or persistent sticky
   bars. The bottom of the screen stays clean by default. The red
   floating bulk-delete bar appears only while at least one job is
   checked (see .floating-bulk-bar above). */
.project-actions-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}
.project-action-btn {
  width: auto;
  margin-top: 0;
  min-height: 40px;
  padding: 8px 16px;
}

/* ---- Floating bulk-delete bar ----
   Pinned to the bottom (above the bottom-nav, same `.above-bottom-nav`
   offset rule the sticky-save-bar uses). Visible only when select mode
   has at least one selected job. Big red button so the destructive
   intent is unmistakable. Hides the save-as-template sticky-save-bar
   while it's up — JS toggles their hidden state in lockstep. */
.floating-bulk-bar[hidden] { display: none !important; }
.floating-bulk-bar {
  position: fixed;
  inset: auto 0 calc(56px + env(safe-area-inset-bottom)) 0;
  z-index: 105;
  display: flex;
  justify-content: center;
  background: var(--card);
  border-top: 1px solid var(--line);
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
.btn-danger-floating {
  background: var(--danger);
  color: #fff;
  border: 1px solid var(--danger);
  border-radius: var(--radius);
  font-size: 16px;
  font-weight: 700;
  width: 100%;
  max-width: 480px;
  min-height: 52px;
  padding: 14px 20px;
  margin-top: 0;
  cursor: pointer;
  letter-spacing: 0.01em;
  box-shadow: 0 2px 6px rgba(177, 68, 43, 0.25);
}
.btn-danger-floating:hover,
.btn-danger-floating:focus {
  filter: brightness(0.92);
  outline: none;
}
.btn-danger-floating:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* ---- Projects page header + new-project form ---- */
.projects-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.projects-header > div { min-width: 0; }
.projects-new-btn {
  width: auto;
  margin-top: 4px;
  padding: 10px 16px;
  min-height: 40px;
  flex: 0 0 auto;
}
.new-project-form {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 16px;
}
.new-project-title {
  margin: 0 0 12px;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
}
.new-project-actions {
  display: flex;
  gap: 10px;
  margin-top: 12px;
  flex-wrap: wrap;
}
.new-project-actions .btn {
  flex: 1 1 auto;
  width: auto;
  margin-top: 0;
}
/* Make <select> look like the rest of the form fields. The template
   dropdown sits next to text inputs and shouldn't read as foreign. */
.new-project-form select {
  font: inherit;
  padding: 12px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  min-height: 48px;
  width: 100%;
  -webkit-appearance: none;
  appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ink-soft) 50%),
    linear-gradient(135deg, var(--ink-soft) 50%, transparent 50%);
  background-position:
    calc(100% - 18px) center,
    calc(100% - 13px) center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 36px;
}
.new-project-form select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.18);
}

/* Reuse the status-btn-spinner styles for the new-project save button —
   same compact spinner, same loading copy convention. */
.btn.is-loading {
  cursor: wait;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

/* ---- Status button loading state (projects page) ----
   The clicked status button (Active/Pause/Complete/Archive) swaps to a
   spinner + "Working…" / "Archiving and clearing calendar…" copy while
   the API call runs. Sibling buttons stay disabled but keep their text
   so the supervisor can read the row without it shifting. */
.status-btn.is-loading {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  cursor: wait;
}
.status-btn-spinner {
  display: inline-block;
  width: 12px;
  height: 12px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: status-btn-spin 700ms linear infinite;
  opacity: 0.7;
}
@keyframes status-btn-spin {
  to { transform: rotate(360deg); }
}

/* Per-row selection checkbox. Always in the DOM; visible only while
   body.is-select-mode is set. Sized for a 48px tap target without
   shifting the row layout when it appears. */
.job-select-wrap {
  display: none;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-right: 4px;
  cursor: pointer;
  flex: 0 0 auto;
}
body.is-select-mode .job-select-wrap { display: inline-flex; }
.job-select {
  width: 22px;
  height: 22px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
/* Dim per-row delete + dotted-border date / vendor pills while in select
   mode so the supervisor knows the row is in selection state, not edit
   state. Tapping row controls is still possible — we don't disable them —
   but the visual hierarchy makes the checkbox the primary affordance. */
body.is-select-mode .job-row { background: var(--card); }
body.is-select-mode .job-row.is-selected { background: rgba(var(--accent-rgb), 0.08); }

/* ---- Progress toast (long-running operations) ----
   Persistent (no auto-fade). Adds a small spinning ring next to the
   message; replaced by the regular check/cross toast on completion. */
.save-toast.is-progress .save-toast-inner {
  background: rgba(20, 20, 20, 0.92);
}
.save-toast-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, 0.32);
  border-top-color: #fff;
  border-radius: 50%;
  animation: save-toast-spin 700ms linear infinite;
  margin-right: 6px;
  vertical-align: -2px;
}
@keyframes save-toast-spin {
  to { transform: rotate(360deg); }
}

/* While a long operation is in flight, dim non-toast content and
   change the cursor — visual cue that taps are queued / discouraged.
   Doesn't disable pointer-events globally (would break Cancel buttons in
   any open modal), just fades + sets cursor. */
body.is-busy main {
  opacity: 0.85;
  cursor: progress;
}
body.is-busy .sticky-save-bar { pointer-events: none; }

.delivery-badge {
  display: inline-block;
  padding: 1px 8px;
  margin-left: 6px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  background: #fffbe6;
  color: #6a4900;
  border: 1px solid #e6dfb8;
  vertical-align: 1px;
}
.status-pill-active   { background: #d8eede; color: #1d4f33; }
.status-pill-paused   { background: #fff0c2; color: #6a4900; }
.status-pill-complete { background: #e3e3df; color: #4a4a44; }
.status-pill-archived { background: #ececea; color: #888;    }

/* Inline status buttons. Currently-set status renders disabled with the
   accent fill so it visually anchors as "this is the current state." */
.project-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
}

.status-btn {
  font: inherit;
  font-size: 13px;
  padding: 6px 12px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background: var(--card);
  color: var(--ink);
  cursor: pointer;
  -webkit-appearance: none;
}
.status-btn:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}
.status-btn.is-current {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  cursor: default;
}
.status-btn:disabled:not(.is-current) {
  opacity: 0.5;
  cursor: progress;
}

/* ---- Batch B polish (cross-page) ---- */

/* Tabular numerics in dashboard cards — keeps job counts + day counters
   from re-flowing as digits change. Scoped narrowly so it doesn't override
   inputs or body copy. */
.project-meta,
.project-context,
.template-item-meta,
.status-pill,
.status-btn { font-variant-numeric: tabular-nums; }

/* Subtle hover lift on project cards — answers Round-2 brief 3
   (consistent card padding, border radius, hover state). Same shadow
   token kept conservative; tradies on phone won't see hover anyway, this
   is for the desktop review pass. */
.project-card {
  transition: transform 120ms ease-out, box-shadow 120ms ease-out, border-color 120ms ease-out;
}
@media (hover: hover) {
  .project-card:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
    border-color: var(--line-strong);
  }
}

/* Template editor: zebra-tint even rows so a long step list is easier to
   scan. Tint is 1.5% black on a parchment bg — barely perceptible, just
   enough to break up uniform whitespace. */
#rows-container > .row:nth-child(even) {
  background: rgba(0, 0, 0, 0.015);
}

/* Tighter day-pair grouping — visually links Day Of Build + Last Day as a
   single concept. Smaller gap so they read as one input pair. */
.field-pair {
  gap: 8px;
}

/* Add Row button: clearer affordance — slightly more prominent than
   secondary, but still secondary-class. Centred + dashed border to read
   as "+ append" rather than a primary action. */
#add-row {
  border-style: dashed;
  margin-top: 4px;
}

/* ---- Sticky save bar (template editor only) ---- */
/* Always-visible save button so the supervisor never has to scroll a long
   step list to find Save. Lives outside <main> so the form's max-width
   doesn't constrain it. Pinned to the viewport bottom; honours the iPhone
   home-indicator safe area the same way .bottom-nav does on dashboard
   pages. The button inside uses form="template-form" so the existing
   submit handler still fires (incl. Enter-in-input). */
.sticky-save-bar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 100;
  display: flex;
  justify-content: center;
  background: var(--card);
  border-top: 1px solid var(--line);
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

/* Modifier — when a page also has the global .bottom-nav fixed at
   bottom: 0 (project detail being the only such page right now), the
   sticky save bar shifts UP by the bottom-nav height so they don't
   overlap. The .bottom-nav still owns the safe-area padding for the
   iPhone home-indicator; the save bar just sits on top of it. */
.sticky-save-bar.above-bottom-nav {
  inset: auto 0 calc(56px + env(safe-area-inset-bottom)) 0;
}

.sticky-save-bar .btn-primary,
.sticky-save-bar .btn-secondary {
  /* Override the default .btn 16px top margin — the bar's own padding
     handles spacing. Keeps the button vertically centred. */
  margin-top: 0;
  width: 100%;
  max-width: 480px;
}

/* ---- Save-as-template inline form (project detail page) ----
   Toggled visible when the supervisor taps "Save as template" in the
   sticky bar. Same visual family as the add-job form, dropped at the
   bottom of <main> so it doesn't collide with the existing job list. */
.save-as-template-form {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-top: 12px;
}
.save-as-template-form .field {
  margin-bottom: 0;
}
.save-as-template-title {
  margin: 0 0 8px;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
}
.save-as-template-hint {
  margin: 0 0 12px;
  font-size: 13px;
  color: var(--ink-soft);
}
.save-as-template-actions {
  display: flex;
  gap: 10px;
  margin-top: 12px;
  flex-wrap: wrap;
}
.save-as-template-actions .btn {
  flex: 1 1 auto;
  margin-top: 0;
  width: auto;
}

/* Inline success card after save — small green panel pointing at the new
   template, replaces the form so the supervisor doesn't have to choose
   "what next" from a half-collapsed UI. */
.save-as-template-success {
  background: rgba(var(--accent-rgb), 0.08);
  border: 1px solid rgba(var(--accent-rgb), 0.3);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-top: 12px;
  font-size: 14px;
}
.save-as-template-success a {
  color: var(--accent-hover);
  font-weight: 700;
}

/* ---- Auto-save toast ----
   Floating pill near the bottom of the viewport, above the bottom-nav.
   Fades in for 2s after every successful mutation, fades out. Compact —
   not a blocking dialog, just confirmation. Position is tuned so it
   sits ABOVE the sticky-save-bar AND bottom-nav on the project detail
   page (highest fixed UI tier on this surface).
   `aria-live="polite"` so assistive tech announces it without
   interrupting the current screen-reader flow. */
.save-toast {
  position: fixed;
  /* Bottom: bottom-nav (~64px) + sticky-save-bar (~80px) + safe-area
     so the toast clears both fixed bars on the project detail page.
     On pages with no sticky-save-bar, the offset is excessive — but
     this toast is currently only used on detail.html. */
  inset: auto 0 calc(160px + env(safe-area-inset-bottom)) 0;
  z-index: 110;
  display: flex;
  justify-content: center;
  pointer-events: none;
}
.save-toast-inner {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: rgba(20, 20, 20, 0.92);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  padding: 9px 16px;
  border-radius: 999px;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  animation: save-toast-in 180ms ease-out;
  pointer-events: auto;
  max-width: calc(100% - 32px);
}
.save-toast.is-error .save-toast-inner {
  background: rgba(177, 68, 43, 0.96);
}
.save-toast.is-leaving .save-toast-inner {
  animation: save-toast-out 220ms ease-in forwards;
}
@keyframes save-toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes save-toast-out {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(8px); }
}

/* Sticky-top breadcrumb modifier. Used by the project detail page so
   the project name + back link stay visible while the supervisor scrolls
   through the job list. Same visual as .nav, with stuck-position fixes
   (background to avoid see-through, blur to soften the scroll edge). */
.nav.is-sticky {
  position: sticky;
  top: 0;
  z-index: 90;
  background: var(--bg);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  /* Pull the top edge to the viewport edge — main's 12px top padding
     would otherwise leave a gap of background visible above the bar
     when scrolled. Negative margin offsets that for a clean stick. */
  margin-top: -12px;
  padding-top: 12px;
}

/* ---- Mobile-first bottom navigation ---- */
/* Persistent fixed bar across all 5 dashboard pages. Mirrors the Instagram /
   Apple Messages / banking-app pattern Trav already has muscle memory for.
   Same markup on every page; only the .is-active class differs. Sits OUTSIDE
   <main> so it's not constrained by the 720px content max-width. */

.bottom-nav {
  position: fixed;
  inset: auto 0 0 0;            /* bottom: 0; left/right: 0 */
  z-index: 100;
  display: flex;
  background: var(--card);
  border-top: 1px solid var(--line);
  /* Honour iPhone home indicator. The padding keeps the tap targets clear
     of the gesture bar; the inner -tab gives them tap-target height. */
  padding-bottom: env(safe-area-inset-bottom);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

/* Tradie accounts don't manage vendors (they ARE the vendor), so the
   Vendors tab is removed from the bar entirely. CSS-driven so there's no
   flash — auth-guard.js sets data-account-type before the page reveals.
   The remaining 4 tabs re-flow to fill the bar via flex: 1 1 0. */
[data-account-type="TRADIE"] .bottom-nav .bn-tab[href="/vendors"] {
  display: none;
}

/* Tradies live on the Jobs page (formerly Projects) — pull that tab to
   the leftmost slot. order:-1 beats the default 0 on every other tab;
   source order breaks ties for the rest (Templates, Contacts, Settings). */
[data-account-type="TRADIE"] .bottom-nav .bn-tab[href="/projects"] {
  order: -1;
}

.bn-tab {
  flex: 1 1 0;                  /* equal width across the bar */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 56px;             /* > 48px brief floor + 4px breathing */
  padding: 6px 4px;
  text-decoration: none;
  color: var(--ink-soft);
  font-weight: 500;
  /* Hint to mobile browsers that this is interactive — kills the 300ms
     tap-delay and bumps tap responsiveness on iOS Safari. */
  touch-action: manipulation;
}

.bn-tab.is-active {
  color: var(--accent);
  font-weight: 600;
}

.bn-icon {
  font-size: 22px;
  line-height: 1;
  /* Slightly desaturate emoji on inactive tabs for a calmer bar. Active
     tabs render at full saturation. */
  filter: grayscale(0.55);
  transition: filter 100ms ease-out;
}
.bn-tab.is-active .bn-icon { filter: none; }

.bn-label {
  font-size: 11px;
  letter-spacing: 0.01em;
}

/* Active tab indicator — thin accent bar at the top of the active tab.
   Sits inside the tab, anchored top-edge, full-width minus a few pixels
   so it doesn't touch the dividers. Cleaner than an underline-on-label. */
.bn-tab.is-active::before {
  content: '';
  position: absolute;
  top: 0;
  left: 12%;
  right: 12%;
  height: 2px;
  background: var(--accent);
  border-radius: 0 0 2px 2px;
}
.bn-tab { position: relative; }

/* Tap feedback. Desktop hover: subtle ink shift. Mobile (no hover): the
   active-press flash from the browser is enough. */
@media (hover: hover) {
  .bn-tab:not(.is-active):hover { color: var(--ink); }
  .bn-tab:not(.is-active):hover .bn-icon { filter: grayscale(0.2); }
}

/* ---- Per-status button colours on the projects page ---- */
/* Round 2's .status-btn was uniform — currently-set rendered green
   regardless of the state. The new hierarchy ties each button to its
   semantic colour so Mark Paused reads amber, Mark Complete reads grey,
   Archive reads quiet/tertiary. data-status attribute is already on every
   button (see public/projects.js renderStatusButtons), so this is CSS-only.
   !! Keep colour tokens aligned with the .status-pill-* palette above. !! */

.status-btn[data-status="Active"]:hover:not(:disabled) {
  border-color: #2a6f4b; color: #2a6f4b;
}
.status-btn[data-status="Paused"]:hover:not(:disabled) {
  border-color: #b88500; color: #6a4900;
}
.status-btn[data-status="Complete"]:hover:not(:disabled) {
  border-color: #4a4a44; color: #4a4a44;
}
.status-btn[data-status="Archived"]:hover:not(:disabled) {
  border-color: var(--danger); color: var(--danger);
}

.status-btn.is-current[data-status="Active"]   { background: #2a6f4b; border-color: #2a6f4b; color: #fff; }
.status-btn.is-current[data-status="Paused"]   { background: #b88500; border-color: #b88500; color: #fff; }
.status-btn.is-current[data-status="Complete"] { background: #4a4a44; border-color: #4a4a44; color: #fff; }
.status-btn.is-current[data-status="Archived"] { background: #888;    border-color: #888;    color: #fff; }

/* Tradie theme: status badges.
   - Base pill border → neutral grey (the shared .status-pill rule uses a
     khaki border that clashes with the white/grey Stripe look).
   - Active = the default state, so it stays QUIET: light-grey fill, dark
     text — no aqua, no attention-grab.
   - Paused keeps its amber (inherited, indicates a held state).
   - Complete goes green — a state change worth signalling, and green is
     the universal "done" colour.
   The status-btn "Active" overrides re-skin the hardcoded-green button
   (#2a6f4b) to the aqua accent — that's an action control, so aqua is
   appropriate there. */
[data-account-type="TRADIE"] .status-pill {
  border-color: var(--line);
}
[data-account-type="TRADIE"] .status-pill-active {
  background: #f3f4f6;
  color: #374151;
}
[data-account-type="TRADIE"] .status-pill-complete {
  background: #ecfdf5;
  color: #047857;
}
[data-account-type="TRADIE"] .status-btn[data-status="Active"]:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}
[data-account-type="TRADIE"] .status-btn.is-current[data-status="Active"] {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* Archive button = tertiary/quiet by default (lower visual weight than
   the three primary status flips). Reads as "demote, less common." */
.status-btn[data-status="Archived"]:not(.is-current):not(:hover) {
  opacity: 0.65;
}

/* ---- /template/apply project-picker section ---- */

.apply-section {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 16px;
}

.apply-section-label {
  display: block;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 10px;
  color: var(--ink);
}

/* "Selected: Coast Rd — 99 Coast Rd" confirmation row, shown after the
   user picks a project from the combobox. The Change button toggles back
   to the search input. */
.picked-project {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  background: rgba(var(--accent-rgb), 0.06);
  border: 1px solid rgba(var(--accent-rgb), 0.25);
  border-radius: 8px;
  margin-bottom: 8px;
}

.picked-project-text {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 6px;
  align-items: baseline;
  min-width: 0;
}

.picked-project-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--accent-hover);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.picked-project-name {
  font-weight: 600;
  color: var(--ink);
}

.picked-project-address {
  color: var(--ink-soft);
  font-size: 14px;
}

.picked-project-change {
  background: transparent;
  border: 0;
  padding: 4px 8px;
  margin: -4px -4px -4px 0;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}
.picked-project-change:hover { color: var(--accent-hover); }

/* "+ Start a new project" / "← Pick existing" toggle link. Reads as a
   tertiary action — small, accent-coloured, no border. */
.apply-toggle-link {
  background: transparent;
  border: 0;
  padding: 6px 0;
  margin: 4px 0 0;
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--accent);
  cursor: pointer;
  text-align: left;
}
.apply-toggle-link:hover { color: var(--accent-hover); }

/* Existing-jobs warning callout. Amber, deliberately non-blocking — Trav
   sees it, clicks Apply anyway, the backend interprets the projectId+click
   pairing as forceDuplicate=true.
   !! Don't add `display: block` — it would override the [hidden] attribute
   (`display: none` from the UA stylesheet) on class-selector specificity,
   leaving an empty amber box visible when scheduled_job_count is 0.
   apply.js relies on warningEl.hidden = true to fully hide this. !! */
.apply-warning {
  padding: 12px 14px;
  margin-bottom: 14px;
  background: #fff8e1;
  border: 1px solid #f1c200;
  border-left-width: 4px;
  border-radius: 8px;
  font-size: 14px;
  line-height: 1.45;
  color: #5a3d00;
}
.apply-warning[hidden] { display: none; }
.apply-warning strong { color: #3a2700; }

/* Mon/Tue/.../Sun checkbox row. Used by both the admin supervisor edit
   form and the customer /settings briefing form. Each pill is touch-target
   sized so thumbs can reliably tap on mobile; pills wrap to a second row
   when the card is narrow. The native checkbox is hidden but stays in
   DOM for form-state + a11y; the visible :checked styling comes from
   the sibling span. */
.admin-day-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}
.admin-day-pill {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  user-select: none;
  min-height: 36px;
}
.admin-day-pill input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.admin-day-pill span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 600;
}
.admin-day-pill input:checked + span {
  background: var(--ink);
  color: var(--card);
  border-color: var(--ink);
}
.admin-day-pill input:focus-visible + span {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ---- Inline calendar (custom date picker) ----
   Floating month-grid popover that replaces the native <input type="date">
   on the project detail page. detail.js appends it to <body> and absolutely
   positions it directly below the tapped pill, so no overflow:hidden
   ancestor can clip it. Fully themeable — the selected-day fill + today ring
   use var(--accent), so both the BUILDER (green) and TRADIE (navy) palettes
   render correctly with no per-theme overrides. */
.cal-popover {
  position: absolute;
  z-index: 200;
  width: 300px;
  max-width: calc(100vw - 16px);
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.16);
  padding: 10px;
  animation: cal-in 140ms ease-out;   /* smooth appearance, no pop-in */
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}
@keyframes cal-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.cal-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.cal-nav {
  font: inherit;
  font-size: 20px;
  line-height: 1;
  font-weight: 700;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  width: 36px;
  height: 36px;
  padding: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  touch-action: manipulation;
}
.cal-nav:hover,
.cal-nav:focus {
  background: rgba(var(--accent-rgb), 0.08);
  border-color: var(--accent);
  outline: none;
}

.cal-dow-row,
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.cal-dow-row { margin-bottom: 4px; }
.cal-dow-cell {
  text-align: center;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding: 4px 0;
}

.cal-day {
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  height: 40px;                /* 40px square on desktop */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  font-variant-numeric: tabular-nums;
}
.cal-day:hover,
.cal-day:focus {
  background: rgba(var(--accent-rgb), 0.10);
  outline: none;
}
/* Days spilling in from the prev/next month — muted but still selectable. */
.cal-day.is-outside { color: var(--line-strong); }
/* Weekends in lighter text so the working week reads first; still tappable. */
.cal-day.is-weekend { color: var(--ink-soft); }
.cal-day.is-outside.is-weekend { color: var(--line-strong); }
/* Today: subtle ring, no fill (so it doesn't compete with the selection). */
.cal-day.is-today {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
/* Selected date: accent fill, white text — wins over today + weekend
   (declared last so equal-specificity rules above don't override it). */
.cal-day.is-selected,
.cal-day.is-selected:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  box-shadow: none;
}

/* Touch / small screens: bump day cells + nav arrows to the 44px tap-target
   floor and widen the popover so the larger cells fit. */
@media (max-width: 640px) {
  .cal-popover { width: 320px; padding: 12px; }
  .cal-day { height: 44px; font-size: 15px; }
  .cal-nav { width: 44px; height: 44px; }
}

/* ---- "or … Pick a date" affordance (shift controls) ----
   Sits under the stepper action buttons in both the global bulk-shift block
   and the per-row shift-from-here panel, offering the inline calendar as an
   alternative to nudging the day count up and down. */
.shift-or {
  text-align: center;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}
.shift-pick-date-btn {
  width: 100%;
  margin-top: 0;
  min-height: 48px;
  padding: 12px 16px;
  font-size: 14px;
  font-weight: 700;
  background: var(--card);
  color: var(--accent);
  border: 1px dashed var(--accent);
  border-radius: var(--radius);
  cursor: pointer;
}
.shift-pick-date-btn:hover,
.shift-pick-date-btn:focus {
  background: rgba(var(--accent-rgb), 0.08);
  outline: none;
}

/* ============================================================================
   GLASSMORPHIC UPGRADE
   ----------------------------------------------------------------------------
   Layered over the base styles above via the cascade (same selectors, declared
   later → they win at equal specificity). PURELY VISUAL: no markup, IDs,
   classes or behaviour change. Works for BOTH themes — every tint is built from
   rgba(var(--accent-rgb), …) / translucent white, so the BUILDER (green) and
   TRADIE (navy) palettes both get correctly-tinted glass. Subtle, Apple-ish —
   not a rave. Mobile keeps its single-column, native feel; the grids only kick
   in at the tablet/desktop breakpoints.
   ============================================================================ */

/* ---- Glass tokens ---- */
:root {
  --glass-bg: rgba(255, 255, 255, 0.7);
  --glass-border: rgba(255, 255, 255, 0.3);
  --glass-shadow: 0 4px 30px rgba(0, 0, 0, 0.05);
  --glass-shadow-hover: 0 10px 40px rgba(0, 0, 0, 0.1);
  --radius-card: 16px;
  --radius-control: 12px;
}

/* Slightly more line-height for a more spacious feel (was 1.4). */
body { line-height: 1.45; }

/* ---- 2. Page background: subtle theme gradient ---- */
/* Builder = warm green wash; tradie = cool blue wash. min-height keeps the
   gradient covering short pages (empty states). background-attachment:fixed is
   desktop-only — mobile Safari is flaky with fixed backgrounds, and a normal
   gradient already covers the body there. */
body {
  min-height: 100vh;
  background: linear-gradient(135deg, #f0f4f0 0%, #e8efe8 50%, #f5f7f5 100%);
}
[data-account-type="TRADIE"] body {
  background: linear-gradient(135deg, #f0f4f8 0%, #e8eef5 50%, #f5f7fa 100%);
}

/* ---- 5. Page-load fade-in on main content ---- */
main { animation: page-fade-in 0.2s ease-out; }
@keyframes page-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ---- 1 + 3. Cards: glass surface + lift on hover ---- */
.project-card,
.template-item,
.job-row,
.settings-section,
.checklist,
#rows-container > .row,
.new-project-form,
.add-job-form,
.save-as-template-form,
.apply-section,
.apply-summary,
.success-card {
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-card);
  box-shadow: var(--glass-shadow);
}

/* Hover lift — pointer devices only (no sticky :hover on touch). */
.project-card,
.template-item,
.job-row {
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
@media (hover: hover) {
  .project-card:hover,
  .template-item:hover,
  .job-row:hover {
    transform: translateY(-2px);
    box-shadow: var(--glass-shadow-hover);
  }
}

/* Roomier card padding (≈24px vs the old 16px). 20px on phones so small
   screens don't feel hollow; 24px from tablet up. */
.project-card,
.template-item { padding: 20px 22px; }

/* ---- 4. Typography refresh ---- */
header h1 { font-weight: 600; }                 /* was 700 — lighter, modern */
.project-name,
.template-item-name { font-weight: 600; }       /* card titles */
.project-meta,
.template-item-meta,
.project-address { font-size: 13px; }           /* metadata: small + muted */

/* ---- 1. Buttons — primary (frosted accent) ---- */
.btn { transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; }
.btn-primary {
  background: var(--accent);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-radius: var(--radius-control);
  box-shadow: 0 2px 15px rgba(var(--accent-rgb), 0.3);
}
.btn-primary:hover,
.btn-primary:focus {
  background: var(--accent-hover);
  box-shadow: 0 6px 22px rgba(var(--accent-rgb), 0.4);
  transform: translateY(-1px);
}
.btn-primary:active { transform: scale(0.98); }
.btn-primary:disabled { box-shadow: none; transform: none; }

/* ---- 1. Buttons — secondary / outline (frosted white) ---- */
.btn-secondary {
  background: rgba(255, 255, 255, 0.5);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(var(--accent-rgb), 0.2);
  border-radius: var(--radius-control);
}
.btn-secondary:hover,
.btn-secondary:focus {
  background: rgba(var(--accent-rgb), 0.08);
  border-color: rgba(var(--accent-rgb), 0.4);
  transform: translateY(-1px);
}
.btn-secondary:active { transform: scale(0.98); }

/* ---- 1. Status pills / badges — refined frosted pills ---- */
.status-pill {
  font-size: 11px;
  padding: 3px 10px;
  border-radius: 20px;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
/* Builder tints (low-opacity, colour-matched). Tradie keeps its own near-white
   overrides defined earlier (higher specificity), so it's untouched here. */
.status-pill-active   { background: rgba(42, 111, 75, 0.14);  color: #1d4f33; }
.status-pill-paused   { background: rgba(184, 133, 0, 0.16);  color: #6a4900; }
.status-pill-complete { background: rgba(74, 74, 68, 0.12);   color: #4a4a44; }
.status-pill-archived { background: rgba(136, 136, 136, 0.16); color: #777; }

.delivery-badge,
.pill {
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border-radius: 20px;
}

/* Status flip buttons on project cards: tighter group, pill-shaped. */
.project-actions { gap: 8px; }
.status-btn { border-radius: 999px; }
.status-btn:active:not(:disabled) { transform: scale(0.95); }

/* ---- 1. Inputs — frosted fields with an accent focus glow ---- */
/* NOTE: background-COLOR only (never the `background` shorthand) so the custom
   <select> dropdown-arrow background-image survives. */
input[type="text"],
input[type="number"],
input[type="search"],
input[type="email"],
input[type="tel"],
input[type="date"],
.projects-controls input[type="search"],
select,
textarea {
  background-color: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: var(--radius-control);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
input:focus,
select:focus,
textarea:focus,
.projects-controls input[type="search"]:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.15);
}

/* ---- 1. Filter tabs — segmented glass pills ---- */
/* Drop the per-tab underline in favour of a frosted accent pill on the active
   tab (the .tabs-standalone bottom divider stays as the row separator). */
.tab {
  border-radius: 999px;
  border-bottom: 0;
  margin-bottom: 0;
  padding: 8px 14px;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.tab.is-active {
  background: rgba(var(--accent-rgb), 0.12);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: var(--ink);
}

/* ---- 1 + 5. Bottom nav — heavy frost, soft top shadow, active icon pop ---- */
.bottom-nav {
  background: rgba(255, 255, 255, 0.85);
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
  border-top: 1px solid rgba(255, 255, 255, 0.3);
  box-shadow: 0 -4px 30px rgba(0, 0, 0, 0.05);
}
.bn-icon { transition: transform 0.15s ease, filter 0.15s ease; }
.bn-tab.is-active .bn-icon { transform: scale(1.12); }

/* ---- 3. Empty states — more whitespace ---- */
.empty-state { padding: 56px 24px; }

/* ============================================================================
   2. RESPONSIVE LAYOUT — fill the screen on tablet/desktop
   ============================================================================ */

/* ---- Tablet (≥768px): wider shell + 2-column card grids ---- */
@media (min-width: 768px) {
  main { max-width: 900px; }

  /* The projects, templates AND contacts lists all share .template-list. */
  .template-list {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;
    align-items: start;
  }
  .template-list > * { margin-bottom: 0; }

  /* Project detail job list → 2 columns. Inline editors still expand inside
     their own grid cell; the body-mounted calendar is unaffected. */
  .job-list {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 14px;
    align-items: start;
  }
  .job-list > .job-row { margin-bottom: 0; }

  /* Even card heights so a 2-up grid reads tidy; push the action row to the
     bottom of each card. */
  .project-card,
  .template-item {
    display: flex;
    flex-direction: column;
    min-height: 150px;
    padding: 24px;
  }
  .project-card .project-actions,
  .template-item .template-item-actions { margin-top: auto; }

  .job-row { padding: 22px; }
}

/* ---- Desktop (≥1024px): full-width shell, header reflow, 3-col contacts ---- */
@media (min-width: 1024px) {
  main {
    max-width: 1200px;
    padding-left: 32px;
    padding-right: 32px;
    padding-bottom: calc(90px + env(safe-area-inset-bottom));
  }

  /* Fixed gradient reads as a calm backdrop the glass blurs against. */
  body { background-attachment: fixed; }

  header h1 { font-size: 32px; }

  /* Generic page header (templates / contacts): title + subtitle flow on the
     left, the "+ New" action pins to the top-right of the same band. The
     projects page already does this via .projects-header (flex). */
  header { position: relative; }
  .header-actions {
    position: absolute;
    top: 0;
    right: 0;
    margin-top: 0;
  }

  .template-list { gap: 20px; }

  /* Contacts get a third column on wide screens (cards are compact). */
  #contact-list { grid-template-columns: repeat(3, 1fr); }

  /* Search + sort: a touch more breathing room on one row. */
  .projects-controls { gap: 16px; }
}

/* ---- Graceful fallback where backdrop-filter is unsupported ---- */
/* Bump opacity so frosted surfaces stay legible instead of see-through. */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .project-card,
  .template-item,
  .job-row,
  .settings-section,
  .checklist,
  #rows-container > .row,
  .new-project-form,
  .add-job-form,
  .save-as-template-form { background: rgba(255, 255, 255, 0.94); }
  .bottom-nav { background: rgba(255, 255, 255, 0.97); }
  .btn-secondary { background: rgba(255, 255, 255, 0.9); }
  input[type="text"],
  input[type="number"],
  input[type="search"],
  input[type="email"],
  input[type="tel"],
  input[type="date"],
  select,
  textarea { background-color: rgba(255, 255, 255, 0.92); }
}

/* ---- Respect reduced-motion: kill transforms + the page fade ---- */
@media (prefers-reduced-motion: reduce) {
  main { animation: none; }
  .project-card,
  .template-item,
  .job-row,
  .btn,
  .btn-primary,
  .btn-secondary,
  .bn-icon { transition: none; }
  .project-card:hover,
  .template-item:hover,
  .job-row:hover { transform: none; }
}

