/* ===================================================================
   common/_visit_gauge.css — the live visit clock, shared by every portal
   that shows it: the contractor doing the work, the office watching, the
   homeowner being billed, and the tenant whose home it is.

   One stylesheet for all four on purpose. They show the same clock to
   every party to the same visit, and the moment they look like different
   components someone will "improve" one of them and the customer's screen
   will stop matching the technician's.

   The layout is ONE centred clock with the agreed terms underneath, not a
   two-pane split. The split gave equal visual weight to a column that was
   structurally empty on any job without an hourly rate — a large em-dash
   beside the number people actually open this to read.

   Everything is token-driven (common/_tokens.css), so an org's theme and
   its paid brand_color reach the gauge without this file knowing any of
   them exist. The one hard-coded family is the state colours: a green
   ring means "inside what you agreed" on every theme, and letting a
   brand repaint that would make the reassurance meaningless.
   =================================================================== */

.visit-gauge {
  /* One centred clock, not two panes. The two-column version left an
     empty column on any job without an hourly rate, sitting at the same
     visual weight as the number people actually open this to read. */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 20px 16px 16px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--white);
  text-align: center;
}

.visit-gauge__sub,
.visit-gauge__foot {
  margin: 0;
  font-size: 12px;
  color: var(--text-secondary, var(--text-tertiary));
  line-height: 1.35;
}

.visit-gauge__foot { font-variant-numeric: tabular-nums; }
.visit-gauge__foot:empty { display: none; }

/* ── the ring ─────────────────────────────────────────────────────── */

.visit-gauge__ring { position: relative; width: 168px; height: 168px; }
.visit-gauge__ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }

.visit-gauge__track { fill: none; stroke: var(--teal-pale); stroke-width: 8; }

.visit-gauge__progress {
  fill: none;
  stroke: var(--success);
  stroke-width: 8;
  stroke-linecap: round;
  /* Set from JS every tick; the transition would fight a 1s cadence and
     make the arc permanently lag the number in the middle of it. */
  transition: stroke 200ms ease;
}

/* Past the included hour the ring is full and the story is now the money
   below, so it stops reading as "progress" and starts reading as "over". */
.visit-gauge[data-state="over"] .visit-gauge__progress { stroke: var(--warning); }
.visit-gauge[data-state="paused"] .visit-gauge__progress { stroke: var(--text-tertiary); }

.visit-gauge__readout {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
}

.visit-gauge__elapsed {
  margin: 0;
  font-size: 30px;
  font-weight: 700;
  color: var(--ink);
  /* Without this the digits jitter the whole block sideways once a second,
     which on a number someone is watching is maddening. */
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.visit-gauge__elapsed-label {
  margin: 0;
  font-size: 11.5px;
  color: var(--text-secondary, var(--text-tertiary));
}

/* ── what was agreed, under the clock ─────────────────────────────── */

.visit-gauge__terms {
  margin: 6px 0 0;
  width: 100%;
  border-top: 1px solid var(--border);
  padding-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.visit-gauge__terms > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  text-align: start;
}

.visit-gauge__terms dt {
  font-size: 12.5px;
  color: var(--text-secondary, var(--text-tertiary));
  flex-shrink: 0;
}

.visit-gauge__terms dd {
  margin: 0;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
  text-align: end;
}

/* ── the accruing charge ──────────────────────────────────────────── */

/* The one term that changes while you watch, so it's sized to be read at a
   glance — but still smaller than the clock, which is what the card is
   for. */
.visit-gauge__terms dd.visit-gauge__amount {
  font-size: 19px;
  font-variant-numeric: tabular-nums;
}

.visit-gauge[data-state="over"] .visit-gauge__amount { color: var(--warning-deep); }

/* ── the status banner ────────────────────────────────────────────── */

.visit-status {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-top: 10px;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid transparent;
  font-size: 13px;
  line-height: 1.4;
}

.visit-status i { font-size: 18px; flex-shrink: 0; margin-top: 1px; }
.visit-status p { margin: 0; }
.visit-status strong { display: block; }

/* The ground is a translucent green, so it composites onto the card and
   flips with it; the ink was a frozen #1D7A33 and fell to 2.96:1 there.
   --status-good-fg is the app's one "inside what you agreed" green and
   carries both schemes — still not the org's brand, which is the point
   this file's header makes about the state colours. */
.visit-status--ok {
  background: rgba(44, 179, 74, 0.09);
  border-color: rgba(44, 179, 74, 0.28);
  color: var(--status-good-fg);
}

.visit-status--warn {
  background: rgba(255, 176, 32, 0.12);
  border-color: rgba(255, 176, 32, 0.34);
  color: var(--warning-deep);
}

.visit-status--paused {
  background: var(--bg-subtle);
  border-color: var(--border);
  color: var(--text-secondary, var(--text-tertiary));
}

/* All three banners are rendered and the state hides two of them, so the
   copy stays in the template where it can be read and translated rather
   than being assembled in JavaScript. The ticker only flips data-state on
   the gauge; these selectors do the rest, which also means the right
   banner is already showing on first paint with JS still parsing. */
.visit-gauge[data-state="ok"] ~ .visit-status:not(.visit-status--ok),
.visit-gauge[data-state="over"] ~ .visit-status:not(.visit-status--warn),
.visit-gauge[data-state="paused"] ~ .visit-status:not(.visit-status--paused) {
  display: none;
}

/* ── contractor controls ──────────────────────────────────────────── */

.visit-controls { display: flex; gap: 10px; margin-top: 12px; }
.visit-controls > * { flex: 1; }
.visit-action-hint { margin: 8px 0 0; }

/* The job's two live actions stay above the contractor navigation and
   safe-area inset while the rest of the long form scrolls underneath.

   Not gated on a viewport width, and that gate was a bug: .bottom-nav is
   position: fixed at every width — the field portal is a bottom-nav app
   on a tablet exactly as much as on a phone — so a max-width: 768px here
   left the bar in the flow of the card on every iPad, scrolling away
   under the Timeline while the nav it was meant to sit above stayed put.
   Nothing in the rule needs a width: inset-inline tracks .app-shell's own
   cap the same way .bottom-nav's left: 50% + max-width does, so the bar
   is already correct on a wide screen. */
.visit-action-bar {
  position: fixed;
  z-index: 24;
  inset-inline: max(8px, calc((100vw - var(--app-max-width, 900px)) / 2 + 8px));
  bottom: calc(var(--bottomnav-total-h, 64px) + env(safe-area-inset-bottom, 0px) + 8px);
  margin: 0;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--paper);
  box-shadow: 0 8px 24px rgba(14, 31, 45, 0.18);
}
.visit-action-hint { padding-bottom: 74px; }

/* Pause and "Finish & price" sit side by side, and neither is
   destructive: pause is reversible and Finish & price only reveals the
   pricing step further down the page. Nothing here ends the visit —
   completing needs the hours and parts that live under that step, which
   is why the finish ACTION is down there and not in this card. So both
   take their plain contractor-portal styling: the forward action is the
   primary .btn-block every other step in this flow uses, pause is
   .btn-block--secondary beside it.

   This rule used to paint the finish link in --danger, left over from
   when it really was the Complete button. It stopped ending anything and
   kept the colour, so the one control that just scrolls the contractor
   onward was the reddest thing on the screen. */

/* ===================================================================
   The live-visit banner — partials/_live_visit_banner.html.

   Lives in this file rather than each portal's own stylesheet because
   the customer and tenant layouts both render it and they must not
   drift. It is a BANNER, sitting with the impersonation and
   add-to-home-screen ones: a fact that is true wherever you are in the
   app, not a card on one screen.
   =================================================================== */

.live-visit-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  text-decoration: none;
  background: var(--teal-pale);
  border-bottom: 1px solid var(--teal);
}

.live-visit-banner__avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  flex-shrink: 0;
  object-fit: cover;
  background: var(--teal);
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 13.5px;
}

.live-visit-banner__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.live-visit-banner__body strong {
  font-size: 14px;
  color: var(--ink);
  line-height: 1.3;
}

.live-visit-banner__body span {
  font-size: 12px;
  color: var(--text-secondary, var(--text-tertiary));
  /* One line. The request title can be long and this is a banner, not a
     card — truncation is correct here, the full text is one tap away. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A live dot, not a spinner: the visit is ongoing, nothing is loading. */
.live-visit-banner__pulse {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--success);
  animation: live-visit-pulse 2s ease-in-out infinite;
}

.live-visit-banner__go { color: var(--teal-deep); font-size: 18px; flex-shrink: 0; }

@keyframes live-visit-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

/* Respect a stated preference for less motion — a pulsing dot is
   decoration, and the banner reads exactly the same without it. */
@media (prefers-reduced-motion: reduce) {
  .live-visit-banner__pulse { animation: none; }
}

/* The money half of the terms list — set apart from the time rows above
   it, because it's the figure the reader is actually watching. */
.visit-gauge__terms-money { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--border); }
