/* ==========================================================================
   Levers board styles - Stage-2 infeasibility relaxation UI.
   Matches route-planner conventions: global CSS vars with var() fallbacks,
   13px/600 type, radius vars, calm transitions. Light/dark aware.

   The single visual job this stage proves: GHOST-TO-BRIGHT. A ghosted row is
   dim and quiet ("checking..."); a bright row is full-opacity, sharp, and (when
   actionable) reads as a tappable button. The transition between them is a
   visible fade so even a near-instant verdict animates.
   ========================================================================== */

.levers-board {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Cause line - one plain sentence (minimal in Stage 1; real wording later). */
.levers-cause {
  margin: 0;
  font-size: 14px;
  line-height: 1.45;
  color: var(--text, #0f172a);
  font-weight: 600;
}

.levers-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* ----- a single lever row ------------------------------------------------- */
.lever-row {
  border: 1px solid var(--border, rgba(0, 0, 0, 0.1));
  border-radius: var(--radius-lg, 10px);
  background: var(--bg, #fff);
  padding: 12px 14px;
  /* ghost-to-bright: opacity + a touch of lift are the whole animation */
  opacity: 0.5;
  transform: translateY(2px);
  transition: opacity 0.35s ease, transform 0.35s ease,
              border-color 0.35s ease, box-shadow 0.2s ease;
}

.lever-main {
  display: flex;
  align-items: center;
  gap: 12px;
}

.lever-icon {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--bg-secondary, #f4f7fb);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
}
.lever-icon::before { content: '•'; color: var(--text-muted, #6b7280); }
.lever-icon-drop::before              { content: '✕'; }
.lever-icon-widen::before             { content: '↔'; }
.lever-icon-shift::before             { content: '⏱'; }
.lever-icon-reduce_service::before    { content: '⚡'; }
.lever-icon-widen_break_window::before{ content: '☕'; }
.lever-icon-shorten_break::before     { content: '☕'; }
.lever-icon-remove_break::before      { content: '☕'; }

.lever-text { flex: 1 1 auto; min-width: 0; }

.lever-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--text, #0f172a);
}

.lever-consequence {
  font-size: 12.5px;
  color: var(--text-muted, #6b7280);
  margin-top: 2px;
}

/* Widen distance-guard trade line ("Cuts lateness 30 min (+23 mi)"). The mileage
   price is the point, so it must not read as quiet grey body text - it's a real
   cost the driver is accepting. ONE consistent loud style for EVERY disclosed
   detour: no magnitude scaling, because absolute miles can't honestly rank big
   vs small (+20 mi is trivial on a national round, huge for a local round). Any
   real detour past the negligible floor is a real cost worth seeing loudly. */
.lever-cost {
  font-size: 13.5px;
  font-weight: 800;
  color: #b91c1c; /* loud red, impossible to miss */
  margin-top: 2px;
}

/* B1 served-vs-original-window warning ("25 min late - reaches Bour-3 - BH2 5LT
   at 10:40 (window closed 10:15)"). A widened stop lands outside the customer's
   ORIGINAL promised window - a real broken promise the driver must see.
   EARLY vs LATE are coloured distinctly (late-is-worse, the driver's principle):
     .served-early = AMBER - served before the window opens, the SOFTER concession.
     .served-late  = RED + bolder - served after it closed, the HARDER one.
   So the asymmetry reads at a glance (e.g. a result flipping amber->red = it moved
   from the soft direction to the hard one). Magnitude leads the wording. */
.lever-served {
  font-size: 13px;
  font-weight: 700;
  margin-top: 2px;
}
.lever-served.served-early { color: #b45309; }            /* amber-700 - softer (early) */
.lever-served.served-late  { color: #b91c1c; font-weight: 800; } /* red-700 bolder - harder (late) */

/* verdict badge */
.lever-badge {
  flex: 0 0 auto;
  font-size: 11.5px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--bg-secondary, #f4f7fb);
  color: var(--text-muted, #6b7280);
  white-space: nowrap;
}

/* ----- GHOST state -------------------------------------------------------- */
.lever-row.is-ghost {
  opacity: 0.5;
  transform: translateY(2px);
}
.lever-row.is-ghost .lever-badge {
  /* a subtle "working" shimmer so a ghosted (provisional widen) reads as live */
  animation: lever-pulse 1.2s ease-in-out infinite;
}
@keyframes lever-pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}

/* ----- BRIGHT state ------------------------------------------------------- */
.lever-row.is-bright {
  opacity: 1;
  transform: translateY(0);
}
.lever-row.is-bright .lever-badge { animation: none; }

/* Smoothly fade badge colour + row border as a ghosted lever brightens to its
   verdict (provisional -> GLS-refined), so the change reads as a transition
   rather than a jump. */
.lever-badge { transition: background-color 0.4s ease, color 0.4s ease; }
.lever-row { transition: border-color 0.4s ease, box-shadow 0.3s ease; }

/* ----- FIRMING state (background re-solve in flight) ---------------------- */
/* A bright lever being re-checked for real shows a "being checked" sheen +
   badge pulse, so the badge reads as PROVISIONAL until firmUp resolves it (an
   honest signal that the value may still sharpen - upgrade-only, never worse). */
.lever-row.is-firming {
  box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.25);
  position: relative;
  overflow: hidden;
}
.lever-row.is-firming::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 30%, rgba(37, 99, 235, 0.14) 50%, transparent 70%);
  background-size: 220% 100%;
  animation: lever-firming-sheen 1.1s linear infinite;
  pointer-events: none;
}
.lever-row.is-firming .lever-badge {
  animation: lever-pulse 1s ease-in-out infinite;
}
@keyframes lever-firming-sheen {
  0%   { background-position: 120% 0; }
  100% { background-position: -120% 0; }
}

/* verdict colours (bright only) */
.lever-row.is-bright.v-fully {
  border-color: var(--success, #10b981);
}
.lever-row.is-bright.v-fully .lever-badge {
  background: var(--success, #10b981);
  color: #fff;
}
.lever-row.is-bright.v-partial {
  border-color: var(--warning, #f59e0b);
}
.lever-row.is-bright.v-partial .lever-badge {
  background: var(--warning, #f59e0b);
  color: #fff;
}
/* no_change: settled, visible, but dimmed - transparency-for-trust */
.lever-row.is-bright.v-nochange {
  opacity: 0.62;
}
.lever-row.is-bright.v-nochange .lever-badge {
  background: var(--bg-secondary, #f4f7fb);
  color: var(--text-muted, #6b7280);
}

/* ----- tappable (actionable bright levers) -------------------------------- */
.lever-row.is-tappable {
  cursor: pointer;
}
.lever-row.is-tappable:hover {
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
  transform: translateY(-1px);
}
.lever-row.is-tappable:active {
  transform: translateY(0);
}
.lever-row.is-tappable:focus-visible {
  outline: 2px solid var(--primary, #2563eb);
  outline-offset: 2px;
}

/* ==========================================================================
   NO-CHANGE COLLAPSE (finding #4) - the dimmed "No change" levers fold behind
   one summary line so they stop burying the actionable fixes. Tap to expand
   (still rank-ordered, still dimmed, still individually visible: we DID check
   them). Mirrors the timeline's collapse-the-calm / keep-the-actionable rule.
   ========================================================================== */
.levers-nochange {
  /* sits just below the actionable list, above the status line */
  margin-top: 2px;
}
.levers-nochange-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted, #6b7280);
  background: var(--bg-secondary, #f4f7fb);
  border: 1px solid var(--border, rgba(0, 0, 0, 0.08));
  border-radius: var(--radius-lg, 10px);
  padding: 10px 14px;
  cursor: pointer;
  transition: background-color 0.15s, color 0.15s, border-color 0.15s;
}
.levers-nochange-toggle:hover {
  color: var(--text, #0f172a);
  border-color: var(--border, rgba(0, 0, 0, 0.18));
}
.levers-nochange-toggle:focus-visible {
  outline: 2px solid var(--primary, #2563eb);
  outline-offset: 2px;
}
.nc-summary { flex: 1 1 auto; min-width: 0; }
.nc-affordance {
  flex: 0 0 auto;
  font-weight: 700;
  color: var(--primary, #2563eb);
}
/* a chevron that flips when expanded, so the affordance reads at a glance */
.nc-affordance::after {
  content: ' ▾';
  display: inline-block;
  transition: transform 0.15s ease;
}
.levers-nochange.is-expanded .nc-affordance::after { transform: rotate(180deg); }

.levers-nochange-list {
  display: none;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}
.levers-nochange.is-expanded .levers-nochange-list { display: flex; }

@media (prefers-reduced-motion: reduce) {
  .nc-affordance::after { transition: none; }
}

/* ==========================================================================
   SEQUENCE TIMELINE (Stage 3) - the route in visit order, ABOVE the levers.
   Consecutive on-time stops collapse to a summary row; late stops + the break
   stay expanded. Lateness is TEXT, never a bar. The whole area is height-stable
   (a scroll past a point) so it never shoves the levers as trials re-solve.
   ========================================================================== */
.levers-timeline {
  /* Stable area: a floor so it doesn't collapse between re-solves, a ceiling so
     a big route scrolls internally instead of pushing the levers down. */
  min-height: 64px;
  max-height: 38vh;
  overflow-y: auto;
  border: 1px solid var(--border, rgba(0, 0, 0, 0.1));
  border-radius: var(--radius-lg, 10px);
  background: var(--bg-secondary, #f8fafc);
  padding: 6px;
  -webkit-overflow-scrolling: touch;
}
.levers-timeline-inner {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tl-row {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 6px 8px;
  border-radius: var(--radius-md, 8px);
}
.tl-tick {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  line-height: 1;
  background: var(--bg, #fff);
  color: var(--text-muted, #6b7280);
}
.tl-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.tl-main {
  font-size: 13px;
  font-weight: 600;
  color: var(--text, #0f172a);
}
.tl-sub {
  font-size: 12px;
  color: var(--text-muted, #6b7280);
  margin-top: 1px;
}

/* on-time rows (incl. collapsed summary) read calm and quiet */
.tl-ontime .tl-tick { color: var(--success, #10b981); }
.tl-summary .tl-main { font-weight: 600; }

/* late / conflict rows stay expanded and carry a clear (non-alarming) accent */
.tl-late {
  background: rgba(245, 158, 11, 0.08);
}
.tl-late .tl-tick {
  background: var(--warning, #f59e0b);
  color: #fff;
  font-weight: 700;
}
.tl-late-tag {
  font-size: 12px;
  font-weight: 700;
  color: var(--warning, #b45309);
  margin-top: 2px;
}

/* the placeless break row */
.tl-break { background: rgba(37, 99, 235, 0.06); }
.tl-break .tl-tick { background: transparent; font-size: 13px; }

/* ----- protect toggle + protected note (drop levers, Stage 3) ------------- */
.lever-secondary {
  margin-top: 8px;
  padding-left: 40px; /* line up under the label, past the icon */
}
.lever-row.is-ghost .lever-secondary { display: none; } /* not while checking */
.lever-protect-toggle {
  font-size: 12px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--border, rgba(0, 0, 0, 0.18));
  background: var(--bg, #fff);
  color: var(--text-muted, #6b7280);
  cursor: pointer;
  transition: background-color 0.15s, color 0.15s, border-color 0.15s;
}
.lever-protect-toggle:hover { border-color: var(--primary, #2563eb); color: var(--text, #0f172a); }
.lever-row.is-protected .lever-protect-toggle {
  border-color: var(--primary, #2563eb);
  color: var(--primary, #2563eb);
  background: rgba(37, 99, 235, 0.08);
}
.lever-protected-note {
  font-size: 12px;
  font-weight: 600;
  color: var(--primary, #2563eb);
  margin-top: 2px;
}

/* ----- status line below the list ---------------------------------------- */
.levers-status {
  margin: 2px 0 0;
  font-size: 12.5px;
  color: var(--text-muted, #6b7280);
}
.levers-status.is-working { font-style: italic; }
.levers-status.is-error { color: var(--danger, #ef4444); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .lever-row { transition: opacity 0.15s linear; transform: none; }
  .lever-row.is-ghost { transform: none; }
  .lever-row.is-bright { transform: none; }
  .lever-row.is-ghost .lever-badge { animation: none; }
}

/* ==========================================================================
   Reactive loop chrome (Stage 2): the card that wraps the levers board, the
   breadcrumb trail of the current path, and the back / start-over / accept
   controls. Mounted in #reactive-loop-mount, below the re-optimise banner.
   ========================================================================== */

.reactive-loop {
  border: 1px solid var(--warning, #f59e0b);
  border-radius: var(--radius-lg, 10px);
  background: var(--bg, #fff);
  padding: 14px;
  margin: 10px 0;
}
.reactive-loop.is-resolved {
  border-color: var(--success, #10b981);
}

/* Breadcrumb trail: "Original route -> Widened LS28 -> Dropped LS14" */
.reactive-trail {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 6px;
  font-size: 12px;
  color: var(--text-muted, #6b7280);
  margin-bottom: 10px;
}
.reactive-trail-seg {
  font-weight: 600;
  color: var(--text-muted, #6b7280);
}
.reactive-trail-seg.is-current {
  color: var(--text, #0f172a);
  background: var(--bg-secondary, #f4f7fb);
  padding: 2px 8px;
  border-radius: 999px;
}
.reactive-trail-sep { opacity: 0.5; }

/* The board itself sits between the trail and the controls. */
.reactive-board-host { margin: 4px 0 12px; }

/* "This route works now" resolved banner (feasible mid-trial). */
.reactive-resolved-msg {
  font-size: 14px;
  font-weight: 600;
  color: var(--success, #10b981);
  margin: 2px 0 12px;
}

/* Controls row: back / start over on the left, accept on the right. */
.reactive-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.reactive-controls .spacer { flex: 1 1 auto; }
.reactive-btn {
  font-size: 13px;
  font-weight: 600;
  padding: 8px 14px;
  border-radius: var(--radius-md, 8px);
  border: 1px solid var(--border, rgba(0, 0, 0, 0.12));
  background: var(--bg-secondary, #f4f7fb);
  color: var(--text, #0f172a);
  cursor: pointer;
  transition: background-color 0.15s, opacity 0.15s;
}
.reactive-btn:hover { background: rgba(37, 99, 235, 0.08); }
.reactive-btn:disabled { opacity: 0.4; cursor: default; }
.reactive-btn-accept {
  border-color: var(--success, #10b981);
  background: var(--success, #10b981);
  color: #fff;
}
.reactive-btn-accept:hover { background: #0ea271; }

/* Inline drop-confirm (drops only): a drop abandons a customer, so the tap asks
   first, in place - a beat of friction proportionate to the harm, never a block.
   Mirrors the nav-completion confirm pattern (row-swap, no modal). */
.lever-drop-confirm {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  padding: 8px 10px;
  background: #fef2f2;                 /* red-50 - matches the severity */
  border: 1px solid #fecaca;
  border-radius: 6px;
}
.lever-drop-confirm .ldc-msg {
  flex: 1 1 auto;
  font-size: 13px;
  font-weight: 700;
  color: #b91c1c;                      /* red-700 */
}
.lever-drop-confirm button {
  flex: 0 0 auto;
  font-size: 13px;
  font-weight: 700;
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid transparent;
  cursor: pointer;
}
.lever-drop-confirm .ldc-cancel { background: #fff; border-color: #cbd5e1; color: #334155; }
.lever-drop-confirm .ldc-drop   { background: #b91c1c; color: #fff; }
.lever-row.is-confirming { box-shadow: 0 0 0 2px rgba(185, 28, 28, 0.25); }
