/* ============================================================================
   parity-time.css — CLUSTER 30 · Time + Money (the WORKER's side).
   Loaded by js/views/_time.js `ensureTimeCss()` (index.html is owned elsewhere).

   Every value here is an existing backline.css token. No new palette, no inline
   hex, no new fonts. Colour discipline for this cluster:
     --teal    a clock that is RUNNING, credit that is CONFIRMED
     --warn    overrun, too-early, pending, blocked, over-capacity,
               and the PAID / PTO / OVERRIDE pills (never --gold: gold is
               Platinum-only and this is the money screen, which is exactly
               where the reach for gold would happen)
     --violet  every interactive control, without exception
     --bad     the live dot and a HARD block only (Record Red is an alarm)
     --gold    NOT USED IN THIS FILE.

   Sections
     1  · shared shell + banners
     2  · the segmented TRACK (the cluster's signature primitive)
     3  · clock: hero, phase cards, controls
     4  · my day: ring, task rows
     5  · shifts: rota rows, open-shift board cards
     6  · earnings + credits
     7  · forms (W-9, time off, engineer hours)
     8  · check-in
     9  · desktop lanes (>=1024) and reduced motion
   ========================================================================== */

/* --- 1 · shared shell + banners -------------------------------------------- */

/* Every figure in this cluster is a number people compare down a column. */
.pt-num, .pt-money, .pt-elapsed, .pt-hero-fig, .pt-clockstr {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.2px;
}

/* One consistent focus ring for everything this cluster makes interactive.
   backline.css sets `outline: none` on some inputs; nothing here does. */
.pt-tap:focus-visible,
.pt-btn:focus-visible,
.pt-input:focus-visible,
.pt-select:focus-visible,
.pt-textarea:focus-visible,
/* The W-9 picker is a 1px visually-hidden <input type=file> with a <label> that
   looks like the button. Focus lands on the input, which has nothing to show, so
   the ring is drawn on the label instead. Without this the only focusable
   control on that screen is invisible to a keyboard. */
#w9-file:focus-visible + label,
#w9-file:focus-visible ~ label {
  outline: 2px solid var(--violet2);
  outline-offset: 2px;
}
.pt-chip:focus-visible,
.pt-card-tap:focus-visible {
  outline: 2px solid var(--violet2);
  outline-offset: 2px;
  border-radius: 12px;
}

/* Mobile hit targets are 44px; desktop may relax to 28. */
.pt-btn {
  min-height: 44px;
  padding: 12px 18px;
  border-radius: 13px;
  border: 1px solid var(--violetStroke);
  background: var(--violetSoft);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: background .14s ease, border-color .14s ease, opacity .14s ease;
}
.pt-btn:hover:not(:disabled) { background: var(--violetStroke2); }
.pt-btn:disabled { opacity: .45; cursor: not-allowed; }
.pt-btn.full { width: 100%; }
/* The clock buttons on the Today bodies are real anchors, so the router's
   back-swipe and middle-click both work. Strip the browser's link chrome. */
a.pt-btn { text-decoration: none; }
.pt-btn.quiet { background: var(--surf2); border-color: var(--line2); color: var(--ink2); font-weight: 600; }
.pt-btn.quiet:hover:not(:disabled) { background: var(--surf3); }
.pt-btn.danger { background: var(--badSoft); border-color: var(--redStroke); color: var(--bad); }
.pt-btn.sm { min-height: 36px; padding: 8px 13px; font-size: 12.5px; border-radius: 11px; }

/* A locked control states its reason instead of vanishing. */
.pt-btn.locked {
  background: var(--surf2);
  border-color: var(--amberStroke);
  color: var(--warn);
  cursor: not-allowed;
}

.pt-row-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* Banners: one shape, four tones. Always says what happened, never just a colour. */
.pt-banner {
  display: flex; align-items: flex-start; gap: 9px;
  width: 100%;
  padding: 11px 13px;
  border-radius: 13px;
  border: 1px solid var(--line2);
  background: var(--surf2);
  font-size: 12.5px; font-weight: 500; line-height: 1.45;
  color: var(--ink2);
}
.pt-banner .pt-banner-body { flex: 1 1 0; min-width: 0; }
.pt-banner.warn { border-color: var(--amberStroke); background: var(--warnSoft); color: var(--warn); }
.pt-banner.ok   { border-color: var(--okStroke);    background: var(--okSoft);   color: var(--ok); }
.pt-banner.bad  { border-color: var(--redStroke);   background: var(--badSoft);  color: var(--bad); }
.pt-banner.teal { border-color: var(--tealStroke);  background: var(--tealSoft); color: var(--teal); }

/* The full-view explanatory panel: 403, not_assistant, not_engineer, signed out.
   A 403 is not a 401, so this is what renders instead of a login bounce. */
.pt-panel {
  width: 100%;
  padding: 22px 20px;
  border-radius: 18px;
  border: 1px solid var(--line);
  background: var(--surf);
  display: flex; flex-direction: column; gap: 10px;
}
.pt-panel .pt-panel-t {
  font-family: var(--serif); font-size: 20px; font-weight: 600;
  color: var(--ink); line-height: 1.15; letter-spacing: -0.2px;
}
.pt-panel .pt-panel-b { font-size: 13px; font-weight: 500; color: var(--mut); line-height: 1.55; }
.pt-panel.warn { border-color: var(--amberStroke); }
.pt-panel.ok { border-color: var(--okStroke); background: var(--okSoft); }
/* The one confirmation mark on the W-9 screen. House stroke icon at display
   size, not an emoji: it is read once, at the end, beside no sibling. */
.pt-panel .pt-panel-fig { display: flex; color: var(--ok); line-height: 1; }
.pt-panel .pt-panel-fig svg { flex-shrink: 0; }

/* Small inline "this bit is unavailable" note, for a section that failed alone. */
.pt-note {
  font-size: 11.5px; font-weight: 500; color: var(--mut);
  line-height: 1.45; padding: 9px 11px;
  border: 1px dashed var(--line2); border-radius: 11px;
}
.pt-foot {
  font-size: 11px; font-weight: 500; color: var(--mut);
  line-height: 1.5; padding: 2px 2px 6px;
}
.pt-foot a { color: var(--violet2); }

.pt-head-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 10px; width: 100%; }
.pt-head-row > .pt-head-mid { min-width: 0; }

/* --- 2 · the segmented TRACK (signature primitive) ------------------------- */
/* One track, three readings:
     .pt-track.mile   Clock — progress to the next $5 on the credit rail
     .pt-track.cap    My Day — assigned work against the shift you have left
     .pt-track.day    My Hours — a 24h day with bookable windows drawn on it
   The segment is absolutely positioned by left/width percentages set inline by
   the view (a real measured value), never a decorative fill. */
.pt-track {
  position: relative;
  width: 100%;
  height: 8px;
  border-radius: 999px;
  background: var(--surf3);
  border: 1px solid var(--hair);
  overflow: hidden;
}
.pt-track.day { height: 12px; }
.pt-track .pt-seg {
  position: absolute; top: 0; bottom: 0;
  background: var(--teal);
  opacity: .82;
}
.pt-track .pt-seg.warn { background: var(--warn); }
.pt-track .pt-seg.over { background: var(--warn); opacity: .95; }
.pt-track .pt-seg.mut  { background: var(--dim); opacity: .5; }
/* the now-marker on a 24h day track */
.pt-track .pt-now {
  position: absolute; top: -2px; bottom: -2px; width: 2px;
  background: var(--bad);
}
.pt-track-legend {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; width: 100%;
  font-family: var(--mono); font-size: 9.5px; font-weight: 600;
  letter-spacing: 0.7px; color: var(--mut); text-transform: uppercase;
}
.pt-track-legend .warn { color: var(--warn); }
.pt-track-legend .teal { color: var(--teal); }

/* --- 3 · clock ------------------------------------------------------------- */

.pt-clock-wrap { display: flex; flex-direction: column; gap: 12px; width: 100%; }

/* The hero is the biggest thing on the page and it is the MONEY, not the button. */
.pt-hero {
  width: 100%;
  padding: 20px 18px 18px;
  border-radius: 20px;
  border: 1px solid var(--line);
  background: var(--surf);
  display: flex; flex-direction: column; gap: 12px;
}
.pt-hero.running { border-color: var(--tealStroke); }
.pt-hero.over    { border-color: var(--amberStroke); }
.pt-hero.frozen  { border-color: var(--line2); }
.pt-hero-key {
  display: flex; align-items: center; gap: 7px;
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  letter-spacing: 1.2px; text-transform: uppercase; color: var(--mut);
}
.pt-hero-key .pt-live {
  width: 7px; height: 7px; border-radius: 999px; background: var(--bad);
  animation: pt-pulse 1.9s ease-in-out infinite;
}
@keyframes pt-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .28; } }
.pt-hero-fig {
  font-size: 46px; font-weight: 600; line-height: .98; color: var(--ink);
}
.pt-hero.running .pt-hero-fig { color: var(--teal); }
.pt-hero-note { font-size: 12px; font-weight: 500; color: var(--mut); line-height: 1.45; }
.pt-hero-rate {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 11.5px; font-weight: 600; color: var(--ink2); letter-spacing: 0.2px;
}
.pt-hero-rate.dflt { color: var(--mut); }

/* the phase pill: one line above everything that says where you are in the
   shift. Tones mirror iOS's StatePill; the dot only appears where a clock is
   genuinely running, so it is a status and never a decoration. */
.pt-phase-strip { display: flex; align-items: center; gap: 10px; width: 100%; }
.pt-phase-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: 999px;
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: 1.1px; text-transform: uppercase;
  background: var(--surf2); border: 1px solid var(--line2); color: var(--mut);
}
.pt-phase-pill.live { background: var(--tealSoft); border-color: var(--tealStroke); color: var(--teal); }
.pt-phase-pill.ok   { background: var(--okSoft);   border-color: var(--okStroke);   color: var(--ok); }
.pt-phase-pill.warn { background: var(--warnSoft); border-color: var(--amberStroke); color: var(--warn); }
.pt-phase-pill.bad  { background: var(--badSoft);  border-color: var(--redStroke);  color: var(--bad); }
.pt-phase-pill .pt-live {
  width: 6px; height: 6px; border-radius: 999px; background: currentColor;
  animation: pt-pulse 1.9s ease-in-out infinite;
}
.pt-strip-rate {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 11.5px; font-weight: 600; color: var(--ink2); letter-spacing: 0.2px;
}
.pt-strip-rate.dflt { color: var(--mut); }

/* elapsed strip under the hero: the second-biggest number on the screen */
.pt-elapsed-strip {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding-top: 2px; border-top: 1px solid var(--hair); margin-top: 2px;
}
/* "In at 6:02 PM" — the fact that makes the elapsed figure checkable. */
.pt-inat {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 11px; font-weight: 600; color: var(--mut); letter-spacing: 0.2px;
}
.pt-elapsed { font-size: 24px; font-weight: 600; color: var(--ink); line-height: 1; }
.pt-elapsed.frozen { color: var(--mut); }
.pt-elapsed-lbl {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: 1.1px; text-transform: uppercase; color: var(--mut);
}

/* the phase headline is the ONE serif line on the screen */
.pt-phase-title {
  font-family: var(--serif); font-size: 24px; font-weight: 600;
  letter-spacing: -0.3px; color: var(--ink); line-height: 1.12;
}
.pt-phase-sub { font-size: 13px; font-weight: 500; color: var(--mut); line-height: 1.5; }

/* session context rows on in_window */
.pt-sess-row {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 4px;
}
.pt-sess-row + .pt-sess-row { border-top: 1px solid var(--hair); }
.pt-sess-time {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 11.5px; font-weight: 700; color: var(--teal);
  flex-shrink: 0; min-width: 96px;
}
.pt-sess-mid { flex: 1 1 0; min-width: 0; }
.pt-sess-t {
  font-size: 13px; font-weight: 700; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pt-sess-s {
  font-size: 11px; font-weight: 500; color: var(--mut);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* minutes stepper for the extend / early asks */
.pt-stepper { display: flex; align-items: center; gap: 10px; }
.pt-stepper .pt-step-val {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 18px; font-weight: 700; color: var(--ink); min-width: 74px; text-align: center;
}
.pt-stepper .pt-btn { min-width: 44px; padding: 10px 12px; }

/* rail picker */
.pt-rails { display: flex; gap: 8px; flex-wrap: wrap; }

/* --- 4 · my day ------------------------------------------------------------ */

.pt-ring-row { display: flex; align-items: center; gap: 14px; width: 100%; }
.pt-ring { flex-shrink: 0; width: 62px; height: 62px; }
.pt-ring circle { fill: none; stroke-width: 7; }
.pt-ring .pt-ring-bg { stroke: var(--surf3); }
.pt-ring .pt-ring-fg {
  stroke: var(--teal); stroke-linecap: round;
  transform: rotate(-90deg); transform-origin: 50% 50%;
  transition: stroke-dashoffset .3s ease;
}
.pt-ring.over .pt-ring-fg { stroke: var(--warn); }
.pt-ring-mid { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.pt-ring-count {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 19px; font-weight: 700; color: var(--ink); line-height: 1;
}
.pt-ring-line { font-size: 12px; font-weight: 500; color: var(--mut); line-height: 1.45; }
.pt-ring-line.over { color: var(--warn); font-weight: 600; }

.pt-task {
  display: flex; align-items: flex-start; gap: 11px;
  padding: 11px 4px;
}
.pt-task + .pt-task { border-top: 1px solid var(--hair); }
.pt-task .pt-tick {
  flex-shrink: 0; width: 24px; height: 24px; margin-top: 1px;
  border-radius: 8px; border: 1px solid var(--line2); background: var(--surf2);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--dim); cursor: pointer;
  transition: background .14s ease, border-color .14s ease, color .14s ease;
}
.pt-task .pt-tick.on { background: var(--tealSoft); border-color: var(--tealStroke); color: var(--teal); }
.pt-task .pt-tick.blocked { background: var(--warnSoft); border-color: var(--amberStroke); color: var(--warn); }
.pt-task .pt-tick:disabled { cursor: not-allowed; opacity: .5; }
.pt-task-mid { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.pt-task-t { font-size: 13.5px; font-weight: 600; color: var(--ink); line-height: 1.35; }
.pt-task.done .pt-task-t { color: var(--mut); text-decoration: line-through; }
.pt-task-s { font-size: 11.5px; font-weight: 500; color: var(--mut); line-height: 1.45; }
.pt-task-est {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 10.5px; font-weight: 600; color: var(--mut); flex-shrink: 0;
}

/* the up-next card carries its two real verbs */
.pt-upnext { border-color: var(--violetStroke); }
.pt-upnext .pt-task { padding-top: 0; }

/* a handoff note is an attributed, dated quote, never folded into notes */
.pt-quote {
  border-left: 2px solid var(--warn);
  padding: 8px 0 8px 12px;
  font-size: 12.5px; font-weight: 500; color: var(--ink2); line-height: 1.55;
  font-style: italic;
}
.pt-quote .pt-quote-by {
  display: block; margin-top: 5px; font-style: normal;
  font-family: var(--mono); font-size: 9.5px; font-weight: 600;
  letter-spacing: 0.8px; text-transform: uppercase; color: var(--mut);
}
/* The same quote when it IS the instruction rather than an aside: the note on a
   W-9 that a director sent back. Same component, read first instead of last, so
   it is sized above the app's own sentence under it and not below it. */
.pt-quote.lead {
  font-size: 14.5px; color: var(--ink); line-height: 1.5;
  overflow-wrap: anywhere;
}
.pt-quote.lead .pt-quote-by { font-variant-numeric: tabular-nums; }

/* --- 5 · shifts + the open-shift board ------------------------------------- */

.pt-shift {
  display: flex; align-items: stretch; gap: 12px;
  padding: 13px 14px;
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--surf);
  width: 100%;
}
.pt-shift.mine  { border-color: var(--tealStroke); }
.pt-shift.filled { opacity: .62; }
.pt-shift.pending { border-color: var(--amberStroke); }
/* the desk said no. Record Red, and no clock affordance anywhere on the card. */
.pt-shift.rejected { border-color: var(--redStroke2); }
/* the deep-link ring: ?openShiftId= highlights one card for 6s */
.pt-shift.hi { outline: 2px solid var(--violet2); outline-offset: 2px; }

.pt-date-tile {
  flex-shrink: 0; width: 46px;
  border-radius: 12px; border: 1px solid var(--line2); background: var(--surf2);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 7px 0; gap: 1px;
}
.pt-date-tile .d {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 18px; font-weight: 700; color: var(--ink); line-height: 1;
}
.pt-date-tile .m {
  font-family: var(--mono); font-size: 9px; font-weight: 700;
  letter-spacing: 0.9px; text-transform: uppercase; color: var(--mut);
}
.pt-shift-mid { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.pt-shift-t {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 14px; font-weight: 700; color: var(--ink); letter-spacing: -0.2px;
}
.pt-shift-s { font-size: 11.5px; font-weight: 500; color: var(--mut); line-height: 1.45; }
.pt-shift-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.pt-shift-right {
  flex-shrink: 0; display: flex; flex-direction: column;
  align-items: flex-end; justify-content: center; gap: 7px;
}
.pt-rate {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 13px; font-weight: 700; color: var(--teal);
}
.pt-rate.unset { color: var(--mut); font-size: 10.5px; font-weight: 600; letter-spacing: 0.3px; }
/* why a slot cannot be taken, where its button would have been */
.pt-shift-s.pt-why { max-width: 190px; }

/* next-shift hero with a status rail down the left edge */
.pt-next {
  position: relative; padding-left: 16px;
}
.pt-next::before {
  content: ''; position: absolute; left: 0; top: 10px; bottom: 10px;
  width: 3px; border-radius: 999px; background: var(--teal);
}
.pt-next.pending::before { background: var(--warn); }
.pt-next.rejected::before { background: var(--bad); }

/* the day line above the clock string: "Today" / "Tomorrow" / "Every Tuesday" */
.pt-shift-d {
  font-size: 14px; font-weight: 700; color: var(--ink); letter-spacing: -0.1px;
}

/* Rota rows carry the same three-toned rail as the hero, so the shape of the
   week reads before a single word does. */
.pt-earn-row.pt-rota { position: relative; padding-left: 13px; align-items: flex-start; }
.pt-earn-row.pt-rota::before {
  content: ''; position: absolute; left: 0; top: 11px; bottom: 11px;
  width: 3px; border-radius: 999px; background: var(--ok);
}
.pt-earn-row.pt-rota.pending::before  { background: var(--warn); }
.pt-earn-row.pt-rota.rejected::before { background: var(--bad); }
.pt-earn-row.pt-rota .pt-earn-mid { display: flex; flex-direction: column; gap: 3px; }

/* pills this cluster adds. PAID / PTO / OVERRIDE are --warn, never --gold. */
.pill.pt-paid,
.pill.pt-pto,
.pill.pt-override {
  background: var(--warnSoft); border: 1px solid var(--amberStroke); color: var(--warn);
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.8px;
}
.pill.pt-posted   { background: var(--tealSoft); border: 1px solid var(--tealStroke); color: var(--teal); }
.pill.pt-pending  { background: var(--warnSoft); border: 1px solid var(--amberStroke); color: var(--warn); }
.pill.pt-approved { background: var(--okSoft);   border: 1px solid var(--okStroke);   color: var(--ok); }
.pill.pt-reversed { background: var(--badSoft);  border: 1px solid var(--redStroke);  color: var(--bad); }
.pill.pt-neutral  { background: var(--surf2);    border: 1px solid var(--line);       color: var(--mut); }
.pill.pt-rejected { background: var(--badSoft);  border: 1px solid var(--redStroke);  color: var(--bad); }

/* --- 6 · earnings + credits ------------------------------------------------ */

.pt-money-hero {
  width: 100%;
  padding: 20px 18px;
  border-radius: 20px;
  border: 1px solid var(--line);
  background: var(--surf);
  display: flex; flex-direction: column; gap: 8px;
}
.pt-money-hero.credit { border-color: var(--tealStroke); }
.pt-money { font-size: 42px; font-weight: 600; line-height: 1; color: var(--ink); }
.pt-money.teal { color: var(--teal); }
.pt-money-split { display: flex; gap: 22px; flex-wrap: wrap; padding-top: 4px; }
.pt-money-split .pt-ms-k {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: 1.1px; text-transform: uppercase; color: var(--mut);
}
.pt-money-split .pt-ms-v {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 17px; font-weight: 700; color: var(--ink2); margin-top: 2px;
}
.pt-money-split .pt-ms-v.teal { color: var(--teal); }
.pt-money-split .pt-ms-v.warn { color: var(--warn); }

.pt-earn-row {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 4px;
}
.pt-earn-row + .pt-earn-row { border-top: 1px solid var(--hair); }
.pt-earn-mid { flex: 1 1 0; min-width: 0; }
.pt-earn-amt {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 14px; font-weight: 700; color: var(--ink); flex-shrink: 0; text-align: right;
}
.pt-legend {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  font-family: var(--mono); font-size: 9.5px; font-weight: 600;
  letter-spacing: 0.8px; text-transform: uppercase; color: var(--mut);
}
.pt-legend .arw { color: var(--dim); }

/* --- 7 · forms ------------------------------------------------------------- */

.pt-field { display: flex; flex-direction: column; gap: 6px; width: 100%; }
.pt-label {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: 1.1px; text-transform: uppercase; color: var(--mut);
}
.pt-input, .pt-select, .pt-textarea {
  width: 100%;
  /* 16px so iOS Safari never zooms the viewport on focus. */
  font-size: 16px;
  font-family: var(--sans);
  font-weight: 500;
  color: var(--ink);
  background: var(--surf2);
  border: 1px solid var(--line2);
  border-radius: 12px;
  padding: 12px 13px;
  min-height: 46px;
  transition: border-color .14s ease;
}
.pt-textarea { min-height: 92px; line-height: 1.45; resize: vertical; }

/* A field label with its hold-to-talk mic on the same line. The mic's own
   styles come from voice-mic.js; this only places it. */
.pt-sheet-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; width: 100%; min-height: 44px;
}
/* The composer mic is 36px, which is fine beside a send button and too small
   for a thumb on a studio floor. This one is a primary input, so it takes the
   mobile target. */
.pt-sheet-head .mic-btn { height: 44px; min-width: 44px; }
@media (min-width: 1024px) { .pt-sheet-head .mic-btn { height: 36px; min-width: 36px; } }
.pt-input::placeholder, .pt-textarea::placeholder { color: var(--mut); }
.pt-input:focus, .pt-select:focus, .pt-textarea:focus { border-color: var(--violetStroke); }
.pt-select { appearance: none; padding-right: 30px; cursor: pointer; }
.pt-input.bad, .pt-select.bad { border-color: var(--redStroke); }
.pt-label.warn { color: var(--warn); }
.pt-label.teal { color: var(--teal); }
.pt-label.bad  { color: var(--bad); }

.pt-help { font-size: 11.5px; font-weight: 500; color: var(--mut); line-height: 1.45; }
.pt-help.warn { color: var(--warn); }
.pt-help.bad  { color: var(--bad); }
.pt-help.teal { color: var(--teal); }
.pt-help.ok   { color: var(--ok); }
.pt-help.boxed { padding: 10px 12px; border-radius: 12px; border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent); background: color-mix(in srgb, var(--warn) 7%, transparent); }
/* the handoff gate modal */
.ho-tasks { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; border-radius: 12px; background: var(--surf2); border: 1px solid var(--hair); }
.ho-task { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--ink); }
.ho-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--warn); flex-shrink: 0; }
.ho-note { width: 100%; resize: vertical; min-height: 96px; font: inherit; font-size: 14px; line-height: 1.45; color: var(--ink); background: var(--surf); border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; }
.ho-note:focus { outline: none; border-color: var(--violet); }

/* an explicit yes/no, not a checkbox that defaults to no */
.pt-yesno { display: flex; gap: 8px; }
.pt-chip {
  min-height: 40px; padding: 9px 15px;
  border-radius: 12px; border: 1px solid var(--line2); background: var(--surf2);
  color: var(--ink2); font-size: 13px; font-weight: 600; cursor: pointer;
  font-family: var(--sans);
  transition: background .14s ease, border-color .14s ease, color .14s ease;
}
.pt-chip.on { background: var(--violetSoft); border-color: var(--violetStroke); color: var(--ink); }
.pt-chip:disabled { opacity: .5; cursor: not-allowed; }

.pt-attest {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 13px; border-radius: 14px;
  border: 1px solid var(--line2); background: var(--surf2);
}
.pt-attest input[type="checkbox"] {
  width: 22px; height: 22px; flex-shrink: 0; margin-top: 1px;
  accent-color: var(--violet); cursor: pointer;
}
.pt-attest .pt-attest-b { flex: 1 1 0; min-width: 0; font-size: 12.5px; font-weight: 500; color: var(--ink2); line-height: 1.5; }

/* engineer hours: a day row with its 24h track */
.pt-day {
  display: flex; flex-direction: column; gap: 9px;
  padding: 13px 14px; border-radius: 16px;
  border: 1px solid var(--line); background: var(--surf);
}
.pt-day.on { border-color: var(--tealStroke2); }
.pt-day-head { display: flex; align-items: center; gap: 10px; }
.pt-day-name {
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  letter-spacing: 1.1px; text-transform: uppercase; color: var(--ink2);
  min-width: 42px;
}
.pt-day.on .pt-day-name { color: var(--teal); }
.pt-day-win { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.pt-day-win .pt-select { min-height: 40px; padding: 8px 10px; font-size: 15px; width: auto; }
.pt-day-off { font-size: 12px; font-weight: 500; color: var(--mut); }

/* --- 8 · check-in ---------------------------------------------------------- */

/* The scan card is the loud path and gets the room it deserves. */
.pt-scan {
  width: 100%; padding: 18px;
  border-radius: 18px;
  border: 1px solid var(--violetStroke);
  background: var(--violetSoft);
  display: flex; flex-direction: column; gap: 11px;
}
.pt-or {
  display: flex; align-items: center; gap: 11px; width: 100%;
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: 1.2px; text-transform: uppercase; color: var(--mut);
}
.pt-or::before, .pt-or::after {
  content: ''; flex: 1 1 0; height: 1px; background: var(--hair);
}
.pt-person {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 12px; border-radius: 14px;
  border: 1px solid var(--line); background: var(--surf);
}
.pt-person.done { border-color: var(--okStroke); background: var(--okSoft); }
.pt-person.dupe { border-color: var(--amberStroke); background: var(--warnSoft); }
.pt-person-mid { flex: 1 1 0; min-width: 0; }
.pt-person-n {
  font-size: 13.5px; font-weight: 700; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pt-person-s {
  font-size: 11.5px; font-weight: 500; color: var(--mut);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pt-person-err { font-size: 11.5px; font-weight: 600; color: var(--bad); line-height: 1.4; }

/* The label over the typed-code field, so the code path is never mistaken for a
   search box once the camera button sits above it. */
.pt-code-label {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: 1.1px; text-transform: uppercase; color: var(--mut);
  margin-top: 2px;
}
.pt-qr-open { width: 100%; justify-content: center; gap: 8px; }

/* The event header: name left, the live figure right. The figure is DERIVED from
   the rows under it, so it moves the instant a name is ticked. */
.pt-ev-head { display: flex; align-items: center; gap: 12px; width: 100%; }
.pt-ev-count { display: flex; align-items: baseline; gap: 6px; flex-shrink: 0; }
.pt-ev-in {
  font-family: var(--serif); font-size: 26px; font-weight: 600; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--ok);
}
.pt-ev-of {
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--mut);
}

/* A refresh that failed with a list already on screen. The list stays. */
.pt-refresh-err {
  display: flex; align-items: center; gap: 11px; width: 100%;
  border-color: var(--redStroke); background: var(--badSoft);
}
.pt-refresh-err-mid { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.pt-refresh-err-t { font-size: 12.5px; font-weight: 700; color: var(--ink); line-height: 1.4; }
.pt-refresh-err-s { font-size: 11.5px; font-weight: 500; color: var(--mut); line-height: 1.45; }
.pt-refresh-err .btn-glass { flex-shrink: 0; }

/* --- the QR viewfinder ------------------------------------------------------
   Built on the house scrim (.pch-modal-scrim). The camera stays live after a
   scan; the result sits over the picture so the next card can go straight up. */
body.pt-qr-lock { overflow: hidden; }
.pt-qr-scrim { padding: 12px; }
.pt-qr-sheet {
  display: flex; flex-direction: column; gap: 12px;
  width: 100%; max-width: 520px;
  max-height: 100%; overflow-y: auto;
  padding: 14px 14px calc(14px + env(safe-area-inset-bottom));
  overscroll-behavior: contain;
  /* Opaque on its own account. The scrim behind it leans on backdrop-filter,
     which some engines skip, and the screen under this one must never be
     readable through the header of the one on top of it. */
  background: var(--bg2);
  border: 1px solid var(--line);
  border-radius: 20px;
  box-shadow: 0 24px 60px -20px #00000099;
}
.pt-qr-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.pt-qr-close { flex-shrink: 0; }

.pt-qr-view {
  position: relative; width: 100%; aspect-ratio: 3 / 4;
  border-radius: 18px; overflow: hidden;
  background: var(--bg); border: 1px solid var(--line2);
}
.pt-qr-video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* The framing square. Decorative, so it is aria-hidden and never carries state. */
.pt-qr-frame {
  position: absolute; inset: 18% 14%;
  border: 2px solid var(--violetStroke); border-radius: 20px;
  box-shadow: 0 0 0 9999px color-mix(in srgb, var(--bg) 46%, transparent);
}
.pt-qr-hint {
  position: absolute; left: 12px; right: 12px; bottom: 12px;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 12px; border-radius: 12px;
  background: var(--surf); border: 1px solid var(--line2);
  font-size: 12.5px; font-weight: 600; color: var(--ink);
}
.pt-qr-result {
  position: absolute; left: 12px; right: 12px; bottom: 12px;
  display: flex; flex-direction: column; gap: 2px;
  padding: 12px 13px; border-radius: 14px;
  background: var(--surf); border: 1px solid var(--line2);
  border-left-width: 4px;
}
.pt-qr-result.ok   { border-left-color: var(--ok); }
.pt-qr-result.warn { border-left-color: var(--warn); }
.pt-qr-result.bad  { border-left-color: var(--bad); }
.pt-qr-result-t {
  font-size: 15px; font-weight: 700; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pt-qr-result-s { font-size: 12.5px; font-weight: 500; color: var(--ink2); line-height: 1.4; }

.pt-qr-fail {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  text-align: center; padding: 40px 20px;
  border-radius: 18px; background: var(--surf); border: 1px solid var(--line);
}
.pt-qr-fail-t { font-size: 13px; font-weight: 500; color: var(--ink2); line-height: 1.5; max-width: 320px; }

.pt-qr-foot { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.pt-qr-count {
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  font-variant-numeric: tabular-nums; letter-spacing: 0.4px; color: var(--ink2);
}

/* --- 9 · desktop lanes + reduced motion ------------------------------------ */

/* --- 9 · classes the profile + check-in screens reach for -------------------
   Eight selectors that were used in the views before they had rules. All of
   them are token-only; nothing here introduces a colour. */

/* A wrapping bed of chips: interest groups, the tonight-event picker. */
.pt-chips { display: flex; flex-wrap: wrap; gap: 7px; }

/* Group heading above a chip bed. Tracked mono, the house eyebrow at label size. */
.pt-group-label {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: 1.1px; color: var(--mut); margin: 2px 0 1px;
}

/* Key/value line inside a card: label left, figure right, tabular so a column
   of hours lines up on the decimal. */
.pt-key-line {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; min-width: 0; padding: 5px 0;
}
.pt-key-line + .pt-key-line { border-top: 1px solid var(--hair); }
.pt-key-k {
  font-size: 12px; font-weight: 500; color: var(--mut);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pt-key-v {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 13px; font-weight: 700; color: var(--ink); flex-shrink: 0;
}

/* The done state on a check-in result row. Reads as confirmation, not a button. */
.pt-done {
  display: inline-flex; align-items: center; gap: 5px; flex-shrink: 0;
  padding: 5px 10px; border-radius: 999px;
  background: var(--okSoft); border: 1px solid var(--okStroke); color: var(--ok);
  font-size: 11px; font-weight: 700;
}
.pt-done svg { flex-shrink: 0; }

/* The scan card's heading block. The loud path at the door gets the room. */
.pt-scan-head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.pt-scan-t {
  font-family: var(--serif); font-size: 17px; font-weight: 600;
  letter-spacing: -0.2px; color: var(--ink); line-height: 1.2;
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}

/* --- 10 · Today role-fork cards -------------------------------------------
   The SA and contractor Today bodies, plus the walkie pill on the hub. */
.pt-linkrow {
  display: flex; align-items: center; gap: 11px; cursor: pointer;
  text-decoration: none; color: inherit;
}
.pt-linkrow:hover { border-color: var(--line2); }
.pt-linkrow .pt-linkrow-mid { flex: 1 1 0; min-width: 0; }
.pt-linkrow .pt-linkrow-t {
  font-size: 13.5px; font-weight: 700; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pt-linkrow > svg { flex-shrink: 0; color: var(--violet); }

/* The walkie unread pill: a count, not a decorative dot. */
.pt-unread {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px;
  background: var(--badSoft); border: 1px solid var(--redStroke); color: var(--bad);
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 10.5px; font-weight: 700; flex-shrink: 0;
}

/* The stale-data amber banner shared by the SA gate views. */
.pt-tasklist { display: flex; flex-direction: column; gap: 7px; }

@media (min-width: 1024px) {
  /* Clock and Earnings are two-lane on desktop: the instrument on the left, the
     supporting context on the right. Everything else stays a reading column. */
  .content.pt-wide {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(300px, 1fr);
    grid-auto-rows: min-content;
    column-gap: 24px; row-gap: 18px;
    align-items: start;
  }
  .content.pt-wide > .pt-span { grid-column: 1 / -1; }
  .content.pt-wide > .pt-lane-a { grid-column: 1; min-width: 0; display: flex; flex-direction: column; gap: 12px; }
  .content.pt-wide > .pt-lane-b { grid-column: 2; min-width: 0; display: flex; flex-direction: column; gap: 12px; position: sticky; top: 8px; }

  .pt-hero-fig { font-size: 54px; }
  .pt-money { font-size: 48px; }
  .pt-btn { min-height: 40px; }
  .pt-chip { min-height: 36px; }
  /* the open-shift board reads as a two-up grid in the wide lane */
  .pt-board-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; }
}

@media (min-width: 1440px) {
  .content.pt-wide { grid-template-columns: minmax(0, 1.6fr) 360px; column-gap: 30px; }
}

@media (prefers-reduced-motion: reduce) {
  .pt-hero-key .pt-live,
  .pt-phase-pill .pt-live { animation: none; opacity: 1; }
  .pt-btn, .pt-chip, .pt-input, .pt-select, .pt-textarea,
  .pt-task .pt-tick, .pt-ring .pt-ring-fg { transition: none; }
}

/* --- 10 · clock-in correction ("Started earlier?") -------------------------- */
/* THE ONE NEW ACCENT IN THIS CLUSTER IS --blue, and it is not a new colour: it is
   backline.css's own --blue, which this file had never reached for. The register
   was already spoken for everywhere else — teal is a clock that is RUNNING and
   credit that is CONFIRMED, amber is waiting/blocked, violet is every control,
   bad is the live dot and a hard block, and gold is Platinum-only. A thing you
   may ASK for needed the one voice left. Strokes are mixed off --blue exactly as
   parity-comms.css does for .pc-bubble.mine: backline.css ships no
   --blueSoft/--blueStroke pair and a second hardcoded blue would be one more
   thing to keep in sync. */

.pt-label.blue { color: var(--blue); }

/* the one-line way in, when nothing is on file yet */
.pt-corr-open {
  display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: 60px; padding: 12px 14px; text-align: left;
  border-radius: 14px; cursor: pointer;
  background: color-mix(in srgb, var(--blue) 7%, var(--surf));
  border: 1px solid color-mix(in srgb, var(--blue) 26%, transparent);
  font-family: var(--sans); color: var(--ink);
  transition: background .14s ease, border-color .14s ease;
}
.pt-corr-open:hover { background: color-mix(in srgb, var(--blue) 12%, var(--surf)); }
.pt-corr-open-ic { font-size: 19px; line-height: 1; flex-shrink: 0; }
.pt-corr-open-mid { display: flex; flex-direction: column; gap: 2px; flex: 1 1 0; min-width: 0; }
.pt-corr-open-t { font-size: 14px; font-weight: 700; color: var(--ink); }
.pt-corr-open-s { font-size: 11.5px; font-weight: 500; color: var(--mut); line-height: 1.4; }
.pt-corr-open svg { color: var(--dim); flex-shrink: 0; }

/* the ask */
.pt-corr-card { border-color: color-mix(in srgb, var(--blue) 30%, transparent); }
.pt-corr-prompt { font-size: 14px; font-weight: 600; color: var(--ink2); }

/* Five cells: two nudges, the readout, two nudges. Earlier is to the LEFT and
   later to the right, so the row reads the same direction as the tape below it. */
.pt-corr-dial {
  display: grid; grid-template-columns: repeat(4, 1fr);
  align-items: stretch; gap: 6px;
  padding: 10px 8px 8px; border-radius: 14px;
  background: var(--surf2); border: 1px solid var(--hair);
}
.pt-corr-nudge {
  min-height: 44px; padding: 8px 4px;
  border-radius: 10px; border: 1px solid var(--line2); background: var(--surf);
  color: var(--ink2); cursor: pointer;
  font-family: var(--mono); font-size: 11.5px; font-weight: 600; letter-spacing: -0.2px;
  transition: border-color .14s ease, color .14s ease;
}
.pt-corr-nudge:hover:not(:disabled) { border-color: color-mix(in srgb, var(--blue) 40%, transparent); color: var(--ink); }
.pt-corr-nudge:disabled { opacity: .4; cursor: not-allowed; }
.pt-corr-readout { grid-column: 1 / -1; display: flex; align-items: center; justify-content: center; min-width: 0; padding-bottom: 4px; }
/* The hero of this card, and the ONE serif line on it. */
.pt-corr-time {
  font-family: var(--serif); font-variant-numeric: tabular-nums;
  font-size: 32px; font-weight: 600; letter-spacing: -0.5px; color: var(--ink);
  line-height: 1.05; white-space: nowrap;
}
@media (max-width: 359px) { .pt-corr-time { font-size: 27px; } }

.pt-corr-delta {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 12px; font-weight: 600; color: var(--blue); letter-spacing: -0.1px;
}
.pt-corr-owed { font-size: 12.5px; font-weight: 500; color: var(--ink2); }

/* the reach-back tape — the clock-in pinned right, the claim running left */
.pt-corr-tape-wrap { display: flex; flex-direction: column; gap: 5px; width: 100%; }
.pt-corr-tape {
  position: relative; height: 10px; width: 100%;
  border-radius: 999px; background: var(--surf3, var(--surf2));
  border: 1px solid var(--hair); overflow: hidden;
}
.pt-corr-tape-fill {
  position: absolute; inset: 0 auto 0 auto; right: 0; height: 100%;
  border-radius: 999px;
  background: color-mix(in srgb, var(--blue) 55%, transparent);
  border-left: 2px solid var(--blue);
}
.pt-corr-tape-lbls { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; width: 100%; }
.pt-corr-tape-lbl {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 10px; font-weight: 600; color: var(--blue); white-space: nowrap;
}
.pt-corr-tape-lbl.mut { color: var(--mut); }

.pt-corr-chips { display: flex; gap: 7px; flex-wrap: wrap; }
.pt-corr-chips .pt-chip { flex: 1 1 0; min-width: 72px; text-align: center; }

/* Small controls hug the RIGHT edge: the app's floating chat bubble sits in the
   bottom-left of every screen, and a pill on that side is a pill under a bubble. */
.pt-corr-actionrow, .pt-corr-cancelrow { display: flex; justify-content: flex-end; width: 100%; }
.pt-corr-actionrow .pt-btn, .pt-corr-cancelrow .pt-btn { min-height: 44px; padding: 10px 18px; }

/* the answer, when there is one */
.pt-corr-title {
  font-size: 15.5px; font-weight: 700; color: var(--ink); line-height: 1.3;
  font-variant-numeric: tabular-nums;
}

@media (min-width: 1024px) {
  .pt-corr-time { font-size: 34px; }
  .pt-corr-actionrow .pt-btn, .pt-corr-cancelrow .pt-btn { min-height: 38px; }
  .pt-corr-nudge { min-height: 40px; }
}

@media (prefers-reduced-motion: reduce) {
  .pt-corr-open, .pt-corr-nudge { transition: none; }
}

/* --- 10 · offline: the network strip and the punches this phone is holding --
   Colour discipline is the cluster's, unchanged: --warn for a punch nobody has
   confirmed (the same amber as "waiting on a MOD"), --teal only once the door
   has actually taken it. No new palette, no new font. */

.netbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;                      /* over the sticky topbar (30) and the tab bar (40), under a modal (60) */
  display: flex; align-items: center; gap: 12px;
  padding: calc(10px + env(safe-area-inset-top, 0px)) 16px 10px;
  font-family: var(--sans);
  font-size: 13px; font-weight: 550; line-height: 1.35;
  border-bottom: 1px solid var(--hair);
  background: var(--surf2);
  color: var(--ink2);
}
.netbar-txt { flex: 1 1 0; min-width: 0; }
.netbar.off  { background: var(--warnSoft); border-bottom-color: var(--amberStroke); color: var(--warn); }
.netbar.send { background: var(--tealSoft); border-bottom-color: var(--tealStroke); color: var(--teal); }
.netbar.done { background: var(--tealSoft); border-bottom-color: var(--tealStroke); color: var(--teal); }
/* A link that no longer points anywhere is not a fault and not a success — it is
   the app telling somebody where they ended up. Muted, on the same strip. */
.netbar.stale { background: var(--surf2); border-bottom-color: var(--hair); color: var(--ink2); }

.netbar-btn {
  flex: 0 0 auto;
  min-height: 44px; padding: 8px 14px;
  border-radius: 12px;
  border: 1px solid var(--violetStroke);
  background: var(--violetSoft);
  color: var(--ink);
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  cursor: pointer;
}
.netbar-btn:hover { border-color: var(--violet2); }
.netbar-btn:focus-visible { outline: 2px solid var(--violet2); outline-offset: 2px; }
@media (min-width: 1024px) {
  .netbar { padding-left: calc(var(--sidebar-w) + 20px); }
  .netbar-btn { min-height: 34px; padding: 6px 13px; }
}

/* the held-punch card on the clock screen */
.pt-held {
  border-color: var(--amberStroke);
  background: color-mix(in srgb, var(--warn) 7%, transparent);
}
.pt-held-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.pt-held-top .pt-label { color: var(--warn); }
.pt-held-count {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 26px; font-weight: 600; color: var(--warn); line-height: 1;
}
.pt-held-title { font-size: 15.5px; font-weight: 700; color: var(--ink); line-height: 1.3; }
.pt-held .pt-btn { align-self: flex-start; }

/* THIS PERIOD */
.pt-per-host:empty { display: none; }
.pt-per-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.pt-per-span {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 11px; font-weight: 600; color: var(--mut); white-space: nowrap;
}
.pt-per-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.pt-per-grid > :only-child { grid-column: 1 / -1; }
.pt-per-cell { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.pt-per-fig {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 24px; font-weight: 600; letter-spacing: -0.4px; color: var(--ink); line-height: 1.05;
}
.pt-per-cap { font-size: 11.5px; font-weight: 550; color: var(--mut); }

@media (prefers-reduced-motion: reduce) {
  .netbar, .netbar-btn, .pt-held { transition: none; }
}

/* --- the time fix, on any shift of your own (2026-09-08) --------------------
   The on-shift card above moves ONE end with nudges. This is the form for a
   shift that is over: two real time inputs, both pre-filled with what the clock
   recorded, both free to move either way, and the new total figured live under
   them. Same --blue register as the rest of the correction rail, same .pt-input
   the app's other forms use — nothing new to keep in sync. */
.pt-fix { width: 100%; }
.pt-fix-times { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; width: 100%; }
@media (max-width: 419px) { .pt-fix-times { grid-template-columns: 1fr; } }
/* Times are figures a person compares, so they line up: tabular, monospaced,
   and never smaller than the 16px that keeps iOS Safari from zooming on focus. */
.pt-fix-time {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  letter-spacing: -0.2px;
}
.pt-fix-time:disabled { opacity: .55; cursor: not-allowed; }
.pt-fix-sum {
  display: flex; flex-direction: column; gap: 3px; width: 100%;
  padding: 11px 12px; border-radius: 12px;
  background: color-mix(in srgb, var(--blue) 6%, var(--surf2));
  border: 1px solid color-mix(in srgb, var(--blue) 22%, transparent);
}
.pt-fix-total {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 15px; font-weight: 700; color: var(--ink); letter-spacing: -0.3px;
}
.pt-fix-delta {
  font-size: 11.5px; font-weight: 600; color: var(--blue); line-height: 1.45;
  font-variant-numeric: tabular-nums;
}
.pt-fix.sent { border-color: var(--tealStroke); }
/* The form drops in UNDER the row it belongs to, inside the same card. */
.pt-fix-host { padding: 4px 0 12px; width: 100%; }
.pt-fix-times-line { font-variant-numeric: tabular-nums; }
.pt-fix-chip {
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  letter-spacing: -0.1px; padding: 6px 10px; border-radius: 999px;
  background: color-mix(in srgb, var(--warn) 14%, transparent); color: var(--warn);
  white-space: nowrap;
}
.pt-fix-none { font-size: 11px; font-weight: 500; color: var(--dim); white-space: nowrap; }

/* --- CLUSTER 71 · MY TIME CLOCKS (#/my/timeclock) --------------------------
   The screen's one addition to this cluster: rows are banded by the PAY PERIOD
   they will be paid in, and the band heading carries that period's own totals.
   Everything else on the screen is `pt-earn-row.pt-rota` and the pills above,
   unchanged, because a punch row should read the same wherever it appears. */
.pt-tc-band {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 14px 2px 5px;
}
.pt-tc-band-name {
  font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  letter-spacing: 1.1px; text-transform: uppercase; color: var(--mut);
  flex: 1 1 auto; min-width: 0;
}
.pt-tc-band-figs { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.pt-tc-fig {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 13px; font-weight: 700; color: var(--ink2); letter-spacing: -0.2px;
}
.pt-tc-cap {
  font-family: var(--mono); font-size: 9.5px; font-weight: 600;
  letter-spacing: 0.8px; text-transform: uppercase; color: var(--mut);
}
/* The decision on a correction, under the row it belongs to and inside the same
   card. Tone is the answer, not decoration: amber is still waiting, teal is
   moved, red is refused. */
.pt-tc-decision {
  font-size: 11.5px; font-weight: 500; line-height: 1.45;
  padding: 8px 11px 10px 13px; margin: 0 0 4px;
  border-left: 3px solid var(--warn); color: var(--ink2);
  background: color-mix(in srgb, var(--warn) 7%, transparent);
  border-radius: 0 10px 10px 0;
}
.pt-tc-decision.ok  { border-left-color: var(--teal); background: color-mix(in srgb, var(--teal) 7%, transparent); }
.pt-tc-decision.bad { border-left-color: var(--bad);  background: color-mix(in srgb, var(--bad) 7%, transparent); }
/* The correction control is the primary action on this screen and it is tapped
   with a thumb. `.pt-btn.sm` is 36px app-wide, which is right for a secondary
   control and short of the 44px target here. Scoped, so no other screen reflows.
   The waiting CHIP beside it is not a target and deliberately keeps its size. */
.pt-btn.sm.pt-tc-fix { min-height: 44px; padding: 11px 14px; }

/* The row's action bar. On a phone it drops under the punch span so the span
   keeps the full width and "11:12 PM" cannot wrap; from 520px it tucks right and
   the row is one line again. */
.pt-tc-row { flex-wrap: wrap; row-gap: 8px; }
.pt-tc-row .pt-earn-mid { flex: 1 1 100%; }
.pt-tc-row .pt-fix-times-line { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pt-tc-act {
  flex: 1 1 100%; display: flex; align-items: center; justify-content: space-between;
  gap: 10px; min-width: 0;
}
@media (min-width: 520px) {
  .pt-tc-row .pt-earn-mid { flex: 1 1 0; }
  .pt-tc-act { flex: 0 0 auto; justify-content: flex-end; gap: 12px; }
}

/* --- 10 · the clock-in location gate ---------------------------------------
   Greg's rule, 2026-09-12: no location, no punch. The refusal is therefore the
   whole column, not a toast, and it carries the taps that undo it. Tokens only:
   --warn family for the hold, --violet for the one control, --mono for the
   step numbers. No new palette. */
.pt-locgate {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 14px;
  border-color: var(--amberStroke);
  background: linear-gradient(160deg, var(--warnSoft), var(--surf) 62%);
  padding: 18px;
}
.pt-locgate-head { display: flex; align-items: flex-start; gap: 13px; }
.pt-locgate-pin {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 12px;
  background: var(--warnSoft);
  border: 1px solid var(--amberStroke);
  color: var(--warn);
}
.pt-locgate-head .col { min-width: 0; }
.pt-locgate-title {
  margin: 2px 0 0;
  font-family: var(--serif);
  font-size: 21px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink);
  letter-spacing: -0.2px;
}
.pt-locgate-body {
  margin: 0;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.55;
  color: var(--ink2);
}
.pt-locgate-steps {
  border: 1px solid var(--line2);
  border-radius: 13px;
  background: var(--surf2);
  padding: 14px 15px;
}
.pt-locgate-steps-key {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--warn);
  margin-bottom: 9px;
}
.pt-locgate-list {
  margin: 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.pt-locgate-list li {
  font-size: 14px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink2);
}
.pt-locgate-list li::marker {
  font-family: var(--mono);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--violet2);
}
.pt-locgate .pt-btn { width: 100%; min-height: 48px; }

@media (max-width: 520px) {
  .pt-locgate { padding: 16px 14px; }
  .pt-locgate-title { font-size: 19px; }
  /* A person reading this is standing at a door on their own phone. Nothing in
     it drops below 16px, so iOS never zooms the page out from under them. */
  .pt-locgate-body, .pt-locgate-list li { font-size: 16px; }
}

/* --- the off-site fence (2026-09-15) ---------------------------------------
   The second door, beside the location gate, and deliberately its twin: it reuses
   .pt-locgate's amber shell so two refusals of the same punch read as one problem
   one step on, not as two products. Everything below is either a token from
   backline.css or a scoped fix to an existing primitive. No new palette.
     --warn family  the hold (waiting on a manager), same as the gate
     --violet       the one control that goes forward (.pt-btn, unchanged)
     --mono         the counter, tabular so it does not jitter as it counts
   --bad is NOT used on the ask: the shift does open. It appears only on the
   badge's "not approved", which is money that will not arrive. */

.pt-offsite-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  margin: 0;
}
.pt-offsite-form .pt-btn { width: 100%; min-height: 48px; }

/* The label and its counter share a line, so the counter arrives where the eye
   already is instead of under a field it is talking about. */
.pt-offsite-lblrow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  min-width: 0;
}
.pt-offsite-lblrow .pt-label { min-width: 0; }
.pt-offsite-count {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 600;
  color: var(--warn);
}
/* .pt-offsite-count sets no display of its own, so [hidden] still hides it; this
   is here so a later display rule cannot quietly un-hide the silent state. */
.pt-offsite-count[hidden], .pt-offsite-err[hidden] { display: none; }

/* 16px comes from .pt-textarea and is load-bearing on iOS: anything smaller zooms
   the viewport the moment somebody taps into it, on a phone, standing outside. */
.pt-offsite-ta { min-height: 104px; }
.pt-offsite-err { margin-top: 2px; }

/* The way past the gate. Quieter than the retry above it by construction: .quiet is
   surface-on-surface where the primary is violet. */
.pt-offsite-esc { font-size: 13px; }

/* The badge on a shift the fence let through. One rule, three registers, used on
   the running clock and on every punch-history row so a shift never reads two ways. */
.pt-offsite-badge {
  width: 100%;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--ink2);
  padding: 9px 12px;
  border-radius: 12px;
  border: 1px solid var(--amberStroke);
  background: var(--warnSoft);
}
.pt-offsite-badge.warn { border-color: var(--amberStroke); background: var(--warnSoft); }
.pt-offsite-badge.teal { border-color: var(--tealStroke); background: var(--tealSoft); }
.pt-offsite-badge.bad  { border-color: var(--redStroke);  background: var(--badSoft); }

/* Inside a punch-history card the badge is a row in a stack of rows, not a floating
   pill: it takes the row's left rule the correction decision already uses. */
.pt-tc-offsite {
  margin: 0 0 4px;
  border-radius: 0 10px 10px 0;
  border: 0;
  border-left: 3px solid var(--warn);
  background: color-mix(in srgb, var(--warn) 7%, transparent);
  padding: 8px 11px 10px 13px;
}
.pt-tc-offsite.teal { border-left-color: var(--teal); background: color-mix(in srgb, var(--teal) 7%, transparent); }
.pt-tc-offsite.bad  { border-left-color: var(--bad);  background: color-mix(in srgb, var(--bad) 7%, transparent); }

@media (max-width: 520px) {
  /* Same reason as the gate above: nothing a person reads at a door drops below 16px. */
  .pt-offsite-badge { font-size: 14px; }
}
