/* ----------------------------------------------------------------------
 * TallerPro DS components — ported from Ivan's prototype (app.css,
 * 2026-08-15), expressed against the tokens application.css already
 * defines so there is exactly ONE source of color truth.
 *
 * This file is the Bootstrap-replacement vocabulary, adopted screen by
 * screen: a page opts in by using these classes; pages that don't are
 * untouched. Work Orders is the first. Nothing here overrides a
 * Bootstrap selector — every class is new — so load order vs
 * application.css doesn't matter, which is what makes the Propshaft
 * glob (stylesheet_link_tag :app serves everything in this folder,
 * alphabetically) safe.
 *
 * Three local tokens cover the proto values the app tokens don't carry:
 * the proto's slate-200 border, its slate-600 secondary text, and its
 * slate-50 muted surface — each with the proto's own dark value.
 * ---------------------------------------------------------------------- */
:root {
  --ds-border:  #e2e8f0;   /* proto --color-border-default (slate-200) */
  --ds-text-2:  #475569;   /* proto --color-text-secondary (slate-600, AA 6.9:1) */
  --ds-muted:   #f8fafc;   /* proto --color-surface-muted (slate-50) */
}
[data-theme="dark"] {
  --ds-border: #334155;    /* slate-700 */
  --ds-text-2: #cbd5e1;    /* slate-300 */
  --ds-muted:  #0f172a;    /* slate-900 */
}

/* ── Page header ──────────────────────────────────────────────────── */
.page-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; margin-bottom: 20px; flex-wrap: wrap;
}
.page-head-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.page-title {
  font-size: 24px; line-height: 32px; font-weight: 700;
  letter-spacing: -0.02em; margin: 0; color: var(--text-strong);
}
.page-sub { margin: 4px 0 0; color: var(--ds-text-2); font-size: 14px; }

/* ── Buttons ──────────────────────────────────────────────────────── */
.btn-ds {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 8px; height: 36px; padding: 0 12px;
  border-radius: 8px; border: 1px solid transparent;
  font-family: inherit; font-size: 14px; font-weight: 600; line-height: 1;
  cursor: pointer; background: transparent; color: var(--text-strong);
  text-decoration: none; white-space: nowrap;
  transition: background-color .12s, border-color .12s, color .12s;
}
.btn-ds:hover { color: var(--text-strong); text-decoration: none; }
.btn-ds:focus-visible { outline: 2px solid var(--pr); outline-offset: 2px; }
.btn-ds i { font-size: 1rem; line-height: 1; }

.btn-ds-primary { background: var(--pr); color: #fff; }
.btn-ds-primary:hover:not(:disabled) { background: var(--pr-hover); color: #fff; }
.btn-ds-primary:disabled {
  /* Proto note kept: NOT pale blue — that failed contrast at 1.80:1. */
  background: var(--ds-border); color: var(--ds-text-2); cursor: default;
}

.btn-ds-secondary {
  background: var(--bg-card); color: var(--text-strong);
  border-color: var(--ds-border);
}
.btn-ds-secondary:hover:not(:disabled) { background: var(--ds-muted); }
/* PR-26: in dark the border (--ds-border #334155 on #1e293b) was 1.38:1 — the button had no edge. */
[data-theme="dark"] .btn-ds-secondary { border-color: #94a3b8; }

.btn-ds-ghost { color: var(--ds-text-2); }
.btn-ds-ghost:hover:not(:disabled) { background: var(--ds-muted); color: var(--text-strong); }

.btn-ds-sm { height: 32px; padding: 0 10px; font-size: 13px; }
.btn-ds-lg { height: 40px; padding: 0 16px; }

/* ── Card ─────────────────────────────────────────────────────────── */
.card-ds {
  background: var(--bg-card);
  border: 1px solid var(--ds-border);
  border-radius: var(--radius-card, 12px);
  box-shadow: var(--shadow-card);
}

/* ── Notification feed rows ───────────────────────────────────────── */
/* Unread used to be an inline #eff6ff — invisible-text territory in
   dark mode. Explicit pair instead, like the cal-dot family. */
.notif-unread { background: #eff6ff; }
[data-theme="dark"] .notif-unread { background: #1e293b; }
.notif-row:hover { background: var(--ds-muted); }
.notif-link { color: inherit; text-decoration: none; }
.notif-link:hover { color: inherit; }

/* Amber "read this" callout — replaces the frozen #fffbeb inline pair,
   which is unreadable in dark mode. Card surface from tokens, accent
   from the amber border alone. */
.callout-ds {
  background: var(--bg-card);
  border: 1px solid var(--ds-border);
  border-left: 4px solid #f59e0b;
  border-radius: var(--radius-card, 12px);
  box-shadow: var(--shadow-card);
  padding: 20px;
}

/* ── Table ────────────────────────────────────────────────────────── */
.table-ds-wrap { overflow: auto; border-radius: inherit; }
.table-ds { width: 100%; border-collapse: collapse; margin: 0; }
.table-ds th {
  height: 40px; padding: 0 12px; text-align: left;
  font-size: 12px; font-weight: 600; color: var(--ds-text-2);
  border-bottom: 1px solid var(--ds-border);
  background: var(--bg-card-header);
  white-space: nowrap;
}
.table-ds td {
  height: 48px; padding: 0 12px;
  border-bottom: 1px solid var(--ds-border);
  font-size: 14px; color: var(--text-strong);
  white-space: nowrap; vertical-align: middle;
}
.table-ds tbody tr:last-child td { border-bottom: 0; }
.table-ds tbody tr:hover td { background: var(--ds-muted); }
.table-ds .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ── Row context menu (PR-06) ─────────────────────────────────────── */
.row-menu-cell { width: 1%; text-align: right; white-space: nowrap; }
/* PR-23: the settings save bar rides the bottom of the viewport */
.settings-sticky-bar { position: sticky; bottom: 0; z-index: 10; background: var(--bg-card); border-top: 1px solid var(--ds-border);
                       padding: 12px 24px; margin: 8px -24px -24px; display: flex; align-items: center; }
/* PR-12: the KB drag handle */
.kb-handle { cursor: grab; user-select: none; }
.kb-handle:active { cursor: grabbing; }
tr.is-dragging { opacity: .5; }
.row-menu__toggle { width: 32px; padding: 0; justify-content: center; }
.row-menu .dropdown-item { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.row-menu .dropdown-item i { width: 1rem; text-align: center; }
.row-menu__form { display: block; }
.toolbar-tools .dropdown-item { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.toolbar-tools .dropdown-item i { width: 1rem; text-align: center; }
.toolbar-tools__form { display: block; }
.toolbar-tools__form .dropdown-item { width: 100%; border: 0; background: transparent; text-align: left; }
.row-menu__form .dropdown-item { width: 100%; border: 0; background: transparent; text-align: left; }

/* ── Quiet filters (search + selects in one row) ──────────────────── */
.quiet-filters {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin: 12px 0 16px;
}
.search-wrap { position: relative; flex: 0 1 320px; min-width: 200px; }
.search-wrap > i {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  color: var(--ds-text-2); pointer-events: none; font-size: .9rem;
}
.input-ds {
  height: 36px; padding: 0 12px;
  border-radius: 8px; border: 1px solid var(--ds-border);
  background: var(--bg-input); color: var(--text-strong);
  font-family: inherit; font-size: 14px; width: 100%;
}
.input-ds:focus,
.input-ds:focus-visible { outline: 2px solid var(--pr); outline-offset: 0; border-color: var(--pr); }
.input-ds-search { padding-left: 34px; }
select.input-ds { width: auto; padding-right: 28px; }

/* ── Segmented control (proto seg-ds) — view toggles ──────────────── */
.seg-ds {
  display: inline-flex; height: 34px; padding: 2px;
  background: var(--ds-muted);
  border: 1px solid var(--ds-border);
  border-radius: 8px;
}
.seg-ds > a, .seg-ds > button {
  border: 0; background: transparent; color: var(--ds-text-2);
  font-family: inherit; font-size: 13px; font-weight: 600;
  padding: 0 12px; border-radius: 6px; cursor: pointer; height: 28px;
  display: inline-flex; align-items: center; gap: 4px; text-decoration: none;
}
.seg-ds > a:hover, .seg-ds > button:hover { color: var(--text-strong); }
.seg-ds > .is-on {
  background: var(--bg-card); color: var(--text-strong);
  box-shadow: 0 1px 2px rgba(15, 23, 42, .08);
}
.seg-ds > a:focus-visible, .seg-ds > button:focus-visible {
  outline: 2px solid var(--pr); outline-offset: -2px;
}

/* ── KPI tiles + card headers + goal bar (proto) ──────────────────── */
.kpi-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin: 16px 0;
}
.kpi-row-3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 767.98px) {
  .kpi-row, .kpi-row-3 { grid-template-columns: repeat(2, 1fr); }
}
.kpi-ds { padding: 12px 16px; }
/* PR-08: a kpi tile that is also a link keeps the tile look, no blue/underline */
.kpi-ds-link { display: block; text-decoration: none; color: inherit; }
.kpi-ds-link:hover { background: var(--ds-muted); color: inherit; }
.kpi-ds .k { font-size: 12px; font-weight: 600; color: var(--ds-text-2); }
.kpi-ds .sub { font-size: .72rem; color: var(--ds-text-2); margin-top: .2rem; line-height: 1.25; }
.kpi-ds .v {
  font-size: 20px; line-height: 28px; font-weight: 700;
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em; margin-top: 2px;
  color: var(--text-strong);
}

.card-ds-head {
  padding: 12px 16px;
  border-bottom: 1px solid var(--ds-border);
  background: var(--bg-card-header);
  border-radius: var(--radius-card, 12px) var(--radius-card, 12px) 0 0;
  font-size: 14px; font-weight: 600; color: var(--text-strong);
}

/* Goal progress (commissions): quiet track, brand fill, green once met. */
.progress-ds {
  height: 6px;
  background: var(--ds-border);
  border-radius: 999px;
  overflow: hidden;
  min-width: 70px;
}
.progress-ds > span { display: block; height: 100%; background: var(--pr); border-radius: inherit; }
.progress-ds.is-met > span { background: #15803d; }

/* ── Photo capture grid (WO show) — square tiles + circle rail ────── */
.photo-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.photo-slot {
  border: 1px solid var(--ds-border); border-radius: 10px; padding: 10px;
  display: flex; flex-direction: column; background: var(--bg-card);
}
.photo-slot.is-done { border-color: color-mix(in srgb, var(--ok, #16a34a) 45%, transparent); }
.photo-drop-over { outline: 2px dashed var(--pr, #2563eb); outline-offset: 2px; }
/* Two reserved lines keep every head the same height — uniform tiles are
   the whole point (the old grid's slots each picked their own height). */
.photo-slot-head { font-size: 12px; font-weight: 600; line-height: 1.25; min-height: 30px; }
.photo-slot-media { position: relative; aspect-ratio: 1 / 1; border-radius: 8px; overflow: hidden; background: var(--ds-muted); }
.photo-slot-img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Offline queue: the just-taken photo previewed ON TOP of the picker (the
   square stays tappable) until the server's stream swaps the tile. */
.photo-slot-preview { position: absolute; inset: 0; opacity: .85; pointer-events: none; }
.photo-slot-pill { position: absolute; left: .4rem; bottom: .4rem; pointer-events: none; }
.photo-add-tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; width: 100%; height: 100%; margin: 0; cursor: pointer;
  border: 1.5px dashed var(--ds-border); border-radius: 8px;
  color: var(--ds-text-2); font-size: 12px; text-align: center;
}
.photo-add-tile:hover { border-color: var(--pr, #2563eb); color: var(--pr, #2563eb); }
.photo-add-tile.is-static { cursor: default; }
.photo-add-tile.is-static:hover { border-color: var(--ds-border); color: var(--ds-text-2); }
.photo-dots { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.photo-dot {
  width: 24px; height: 24px; border-radius: 50%;
  border: 1px solid var(--ds-border);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 600; color: var(--ds-text-2); text-decoration: none;
}
.photo-dot.is-done { background: var(--pr, #2563eb); border-color: var(--pr, #2563eb); color: #fff; }
.photo-dot.is-skip { background: var(--ds-muted); }
.photo-extra { width: 34px; height: 34px; border-radius: 6px; overflow: hidden; display: block; }
.photo-extra img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* PR-28: photos outside the seven steps, folded under the grid. */
.photo-extra-tile { aspect-ratio: 1 / 1; border-radius: 8px; overflow: hidden; background: var(--ds-muted); }

/* Timeline-card status dot: the .status-* class supplies the status COLOR
   (its text-emphasis value); currentColor turns it into the fill. Declared
   here (ds.css loads after application.css) so it wins the specificity tie
   with the badge classes' pale backgrounds. */
.cal-card__statusdot {
  position: absolute;
  bottom: 4px;
  right: 4px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .6);
}

/* A .btn-ds that is CURRENTLY ON (Today while viewing today, the map toggle
   while the panel is open). The class was being set with no rule behind it. */
.btn-ds.is-on {
  background: var(--bs-primary-bg-subtle);
  border-color: var(--pr);
  color: var(--pr);
}

/* ── Metric tiles (proto metric-ds) — clickable headline counts ────── */
.metric-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 16px; max-width: 640px; }
.metric-ds {
  display: flex; flex-direction: column; gap: 4px;
  padding: 12px 16px;
  background: var(--bg-card);
  border: 1px solid var(--ds-border);
  border-radius: var(--radius-card, 12px);
  box-shadow: var(--shadow-card);
  text-decoration: none;
  color: inherit;
  text-align: left;
}
.metric-ds:hover { background: var(--ds-muted); color: inherit; }
.metric-ds .k { font-size: 12px; font-weight: 600; color: var(--ds-text-2); }
.metric-ds .v { font-size: 24px; line-height: 32px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; color: var(--text-strong); }
.metric-ds.is-active { border-color: var(--pr); box-shadow: inset 0 0 0 1px var(--pr); }

/* ── Definition grid (proto dl-ds): 120px muted labels, aligned values ── */
.dl-ds { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 6px 12px; margin: 0; }
.dl-ds dt { font-size: 12px; font-weight: 600; color: var(--ds-text-2); }
.dl-ds dd { margin: 0; font-size: 14px; }

/* ── Conversation chat view (proto): turns, not a monospace log ────── */
.convo-turns { display: flex; flex-direction: column; gap: 10px; }
.convo-turn {
  max-width: 85%;
  padding: 8px 12px;
  border-radius: 10px;
  background: var(--ds-muted);
  border: 1px solid var(--ds-border);
}
.convo-turn.is-ai {
  align-self: flex-end;
  background: var(--bs-primary-bg-subtle);
  border-color: var(--bs-primary-border-subtle);
}
.convo-turn__head { display: flex; gap: 8px; align-items: baseline; margin-bottom: 2px; }
.convo-turn__who { font-size: 12px; font-weight: 700; }
.convo-turn__time { font-size: 11px; color: var(--ds-text-2); font-variant-numeric: tabular-nums; }
.convo-turn__text { font-size: 13.5px; line-height: 1.5; white-space: pre-wrap; }

/* ── Confirmation dialog (PR-09) — native <dialog>, top layer ─────── */
.confirm-ds { border: 1px solid var(--ds-border); border-radius: 12px; padding: 0; width: min(440px, calc(100vw - 32px)); background: var(--bg-card, #fff); color: var(--text-strong, inherit); box-shadow: 0 20px 60px rgba(15, 23, 42, .25); }
.confirm-ds::backdrop { background: rgba(15, 23, 42, .55); }
.confirm-ds-body { padding: 20px 20px 8px; }
.confirm-ds-title { font-size: 17px; font-weight: 700; margin: 0 0 8px; }
.confirm-ds-effect { color: var(--ds-text-2); font-size: 14px; margin: 0 0 12px; }
.confirm-ds-typed { margin: 8px 0 12px; }
.confirm-ds-foot { display: flex; gap: 8px; justify-content: flex-end; padding: 12px 20px; border-top: 1px solid var(--ds-border); }
.btn-ds.is-danger { background: #b91c1c; color: #fff; border-color: #b91c1c; }
.btn-ds.is-danger:disabled, .btn-ds.is-danger[disabled] { background: var(--ds-border); border-color: var(--ds-border); color: var(--ds-text-2); cursor: not-allowed; }

