/* This file sits on top of system.css (loaded first by team-clean.html and
   employees.html). system.css is the ONLY place a colour, a font or a weight is
   typed; everything below reads a --sys-* token through the crew's own older
   names, so a rule written against `--ink` or `--green` is already on the Apple
   contract Mario approved on 2026-09-05 (Tokens / Main boards) without being
   rewritten. The fallbacks are the contract values too, so a shell that somehow
   loads this sheet without system.css still paints the same app. */
:root {
  /* The crew's names for the system's colours. Aliases, not copies: change a
     value in system.css and both apps move together, which is the point.

     --green is a STATUS colour (Staged, paid, done) and nothing else: never a
     button, never a link, never an active tab. Anything that used to borrow the
     brand green as the app's accent reads --blue / --sys-accent now.
     --gold / --gold-soft are the crew's old names for the watch / packing /
     pending tint; they alias --sys-orange so the warning strip on a Crew Day
     card and the "Packing" chip on a manager card are the same colour. */
  --bg: var(--sys-page, #F5F5F7);
  --surface: var(--sys-panel, #FFFFFF);
  --surface-2: var(--sys-fill-2, #EFEFF2);
  --ink: var(--sys-ink, #1D1D1F);
  --muted: var(--sys-muted, #636366);
  --line: var(--sys-line, rgba(0, 0, 0, .08));
  --green: var(--sys-green, #1E7B3A);
  --green-soft: var(--sys-green-soft, #E6F6EA);
  --blue: var(--sys-accent, #0068D6);
  --blue-soft: var(--sys-accent-soft, #E5F1FC);
  --gold: var(--sys-orange, #A85900);
  --gold-soft: var(--sys-orange-soft, #FFF1E0);
  --red: var(--sys-red-ink, #B3261E);   /* text-weight red (see system.css --sys-red-ink) */
  --red-soft: var(--sys-red-soft, #FFECEB);

  /* --shadow used to be declared TWICE in this file, 950 lines apart, at identical
     specificity, and which card shadow the crew app rendered was decided by source
     order. One declaration, and it is the system's card shadow: cards have no
     border, and this hairline is what lifts a white card off the grey ground. */
  --shadow: var(--sys-shadow-card, 0 1px 2px rgba(0, 0, 0, .04));

  /* The phone's own font. No webfont, no Inter — the fallback must not name it
     either, or a shell without system.css would ask for a face it never loads. */
  font-family: var(--sys-font, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif);

  /* WEIGHTS. Four, and only four: 400 / 500 / 600 / 700 (system.css, TYPE). The
     system font has a real face at each, so what is written is what renders. This
     file used to ask for 650, 800 and 950 in places — on the webfont those were
     synthesised or clamped, on the system font they would render as-is, heavier
     than anything on the boards. Every weight below is on the scale now. */

  /* ONE number for the bottom nav, so every bar that has to sit on its top edge
     stops guessing. The nav is the frosted pill system.css paints for BOTH apps
     (section "THE NAV"): --sys-nav-h (64) tall, floating --sys-nav-gap (14) off
     the bottom edge, paying env(safe-area-inset-bottom) in its own `bottom:` and
     nowhere else. So this token is the pill's box PLUS its float gap, WITHOUT the
     inset — 64 + 14 = 78 at every width — and every consumer (.detail-sticky-
     actions, .form .bottom-bar, .toast, #crewUndo) adds the env() itself and
     lands on the pill's top edge.
     Before this, the two sticky bars were hard-coded to 92px against a 71px nav,
     so on every phone, at every inset, a 20px band of live scrolling list showed
     between two translucent bars. That gap is most of what the owner meant by
     "el menú se ve mal".
     DERIVED, never typed: there used to be a second `:root{--crew-nav-h:84px}` in
     a tablet branch further down this file, and the tablet branch is gone from
     system.css too — every width gets the same 64/14 pill. Declared exactly once
     (qa:layout-contract pins that). If system.css is ever missing, the fallbacks
     give the same geometry. */
  --crew-nav-h: calc(var(--sys-nav-h, 64px) + var(--sys-nav-gap, 14px));

  /* Keyboard height. Published by employee-field-app.js from window.visualViewport
     onto <html> as --sys-kb — the system's name, so the manager shell's bars can
     read the same publisher instead of the crew growing a private copy of it (this
     app had --crew-kb, inventory had --inv-kb, and the extension modules had two
     more byte-similar lifts, all measuring the same keyboard).
     Read by exactly one thing, the Add work Submit bar in the KEYBOARD block at the
     foot of this file, which has to be lifted over the keyboard in the shells where
     the viewport does not shrink by itself. 0px is the default so that rule is
     correct before the JS runs, or if it never does — 0 is the right answer in the
     shells where the webview resizes itself. */
  --crew-kb: var(--sys-kb, 0px);
}

* {
  box-sizing: border-box;
}

/* The grey ground behind white cards, in both apps (system.css --sys-page). No
   gradients anywhere in this design. */
html,
body {
  margin: 0;
  min-height: 100%;
  color: var(--ink);
  background: var(--bg);
}

html,
body {
  overflow-x: hidden;
  /* clip (modern browsers) instead of hidden: hidden turns body into a scroll
     container that never scrolls, which silently disables EVERY position:sticky
     inside the app (the OS2 tab bar, the form bottom bars). clip clips without
     creating a scroll container; older browsers ignore it and keep hidden. */
  overflow-x: clip;
  /* Stop iOS from auto-inflating text (Larger Text / its own heuristic), which blows out
     the fixed-width cards and causes the whole screen to overflow horizontally. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

button,
input,
select,
textarea {
  font: inherit;
}

button,
a {
  -webkit-tap-highlight-color: transparent;
}

button {
  cursor: pointer;
}

/* dvh, never svh — the same fix 795ba1d made to the manager app, finally applied
   to the crew app.
   mobile/capacitor.config.json runs the WKWebView with ios.contentInset "always".
   In that mode 100svh is the FULL webview height while window.innerHeight, 100dvh
   and the fixed-position viewport are that height MINUS the safe-area insets. So
   `min-height:100svh` made every crew screen 81-127px taller than the glass:
   nothing fell off (nothing is anchored to the bottom of these boxes and .nav is
   position:fixed), but every short screen — Home, an empty Jobs list, More, the
   login — rubber-banded into scroll that had nothing in it, and the login card,
   centred inside that too-tall box, sat ~40px below true centre. A page that
   slides when there is nothing to slide is a big part of "se siente frágil".
   No browser can see the difference: there svh == dvh == innerHeight. */
.field-app {
  width: min(100%, 520px);
  min-height: 100dvh;
  margin: 0 auto;
  background: var(--bg);
}

.loading-screen {
  min-height: 100dvh;
  display: grid;
  align-content: center;
  gap: 16px;
  padding: 28px;
}

/* THE SIGN-IN'S FRAME, and only the frame (2026-09-30). Everything inside it — the
   mark, the fields, the button, the links — is system.css `.sys-signin`, the one
   block the manager's sign-in and /join draw from too. This used to be a grey page
   with a left-aligned logo and a white card; the manager's was a white page with
   everything centred. Same ground and same centring now: white, the column in the
   middle. The manager's frame is #loginModal.open in index.html. */
.login-screen {
  min-height: 100dvh;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 24px;
  background: var(--sys-panel);
}

.loading-screen img {
  width: 78px;
  height: auto;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  padding: 10px;
  box-shadow: var(--shadow);
}

.loading-screen strong {
  margin: 0;
  font-size: var(--sys-t-large-title, 32px);
  font-weight: var(--sys-w-bold);
  line-height: 1.05;
  letter-spacing: -.03em;
}

/* ---- what this phone already knows, while there is no signal (2026-09-22) ----
   On one bar at the door Home was a spinner for a minute and a half and then a
   toast, while today's address and lockbox were already on the phone and read by
   nobody. This sits under the spinner — never instead of it, the app is still
   trying — and says plainly what it is and how old. No buttons: it is the last
   thing this phone was told, not the truth. */
.oj {
  display: grid;
  gap: 10px;
  text-align: left;
  padding: 14px;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
}
.oj-h {
  font-size: var(--sys-t-small);
  font-weight: var(--sys-w-semibold);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}
.oj-row { display: grid; gap: 2px; }
.oj-row + .oj-row { border-top: 1px solid var(--sys-line); padding-top: 10px; }
.oj-a { font-size: var(--sys-t-lead); font-weight: var(--sys-w-semibold); }
.oj-d { font-size: var(--sys-t-body); color: var(--muted); }
.oj-lb { font-size: var(--sys-t-body); color: var(--ink); }
.oj-lb b { font-weight: var(--sys-w-bold); letter-spacing: .06em; }
.oj-f { margin: 0; font-size: var(--sys-t-body); color: var(--muted); line-height: 1.35; }

.loading-screen span,
.muted {
  color: var(--muted);
  font-weight: var(--sys-w-regular);
}

/* The way off a loading screen that never finishes. Loading has no end of its
   own: a request on one bar of signal can hang with no answer and no error, and
   if this file fails to arrive at all the static copy in team-clean.html is all
   there is. Inside the iOS app there is no reload button of the browser's, so
   that screen was one you could only leave by killing the app. Hidden for the
   first 10 seconds — a normal slow start never shows it — then a plain
   secondary button. `visibility`, not opacity, so it cannot take a tap before it
   is visible. The rule is here AND inline in team-clean.html, because the static
   copy has to work when this sheet is the thing that did not load. */
.loading-screen .loading-reload {
  justify-self: start;
  visibility: hidden;
  animation: loading-reload-in 0s 10s forwards;
}

@keyframes loading-reload-in {
  to { visibility: visible; }
}

/* 2026-09-17 (W91): something on the loading screen moves. It was the logo, the
   name and "Loading Lauren..." and nothing else, identical at one second and at
   four — on one bar of signal that is a screen that looks frozen, and the only
   animation on it was the 10-second wait before Reload. A 20px ring in the accent
   on the progress track's grey, turning. Reduce Motion stops the turn and fades
   the arc in and out instead: no movement, and still not a still picture. */
.crew-spin {
  display: inline-block;
  width: 20px;
  height: 20px;
  margin-right: 10px;
  vertical-align: -4px;
  box-sizing: border-box;
  border: 2px solid var(--sys-track, #E5E5EA);
  border-top-color: var(--sys-accent, #0068D6);
  border-radius: 50%;
  animation: crew-spin .8s linear infinite;
}

@keyframes crew-spin {
  to { transform: rotate(360deg); }
}

@keyframes crew-spin-fade {
  50% { border-top-color: var(--sys-track, #E5E5EA); }
}

@media (prefers-reduced-motion: reduce) {
  .crew-spin { animation: crew-spin-fade 1.6s ease-in-out infinite; }
}

/* The .app-shell rule that used to be here (min-height:100dvh; display:grid;
   grid-template-rows:auto 1fr) is deleted. It never applied: the .app-shell rule
   further down this file re-declares the same selector at the same specificity
   with display:block, and later wins — so the grid template was describing a
   layout the browser never built. Deleted rather than left looking live, because a
   dead rule that reads like the real one is how the next person "fixes" the
   padding in the copy nobody renders. The live rule is the one below. */

.app-top {
  position: static;
  z-index: 20;
  padding: calc(12px + var(--sys-safe-t)) 14px 10px;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

.top-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 10px;
  align-items: center;
}

/* Buttons (contract section 2). Primary: the accent, white text, a pill.
   Secondary: a white pill, accent text, a soft shadow. Text action ("Edit"):
   accent, 15/500, nothing behind it. No borders on any of them. */
.icon-btn,
.small-btn,
.primary-btn,
.secondary-btn,
.link-btn,
.chip {
  min-height: var(--sys-tap, 44px);
  border: 0;
  border-radius: var(--sys-r-pill);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--sys-t-lead);
  font-weight: var(--sys-w-semibold);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0 18px;
}

.icon-btn {
  width: 44px;
  padding: 0;
  font-size: 20px;
}

.primary-btn {
  background: var(--blue);
  color: #fff;
}

.secondary-btn {
  background: var(--surface);
  color: var(--blue);
  box-shadow: var(--sys-shadow-btn);
}

.link-btn {
  background: transparent;
  color: var(--blue);
  font-weight: var(--sys-w-medium);
  padding-inline: 4px;
}

.top-title {
  min-width: 0;
}

.top-title span {
  display: block;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
  text-transform: none;
  letter-spacing: 0;
}

.top-title strong {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: var(--sys-t-display);
  font-weight: var(--sys-w-bold);
  letter-spacing: -.02em;
}

/* No env() at the bottom here. .content sits INSIDE .app-shell, which owns the
   clearance for the nav, and <body> owns the home indicator — so a third copy of
   the inset on this element was 34px of dead scroll at the foot of every screen
   that uses it, on top of the two that were already being charged. Its own 24px is
   real: that is this screen's breathing room under its last row, and it stays. */
.content {
  min-width: 0;
  padding: 16px 14px 24px;
}
/* The Home = Team Home board renders its own header instead of the app header,
   so it must carry the status-bar safe area itself (iPhone notch). */
.content.th-crew-content {
  /* The TOP inset stays — this board draws its own header instead of .app-top, so
     nothing above it has paid for the notch. The bottom one goes, for the same
     reason as .content above: the shell and the body have already paid it. */
  padding: calc(8px + var(--sys-safe-t)) 12px 24px;
}

.screen {
  display: grid;
  gap: 16px;
}

/* A card: white, no border, the hairline shadow, 18px corners, 16px padding. */
.hero {
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
  padding: 16px;
}

.hero h2 {
  margin: 0;
  font-size: var(--sys-t-large-title, 32px);
  font-weight: var(--sys-w-bold);
  line-height: 1.05;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}

.hero p {
  margin: 8px 0 0;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
}

/* My pay: Submitted / Approved / Paid. Three cards, so three columns — it was four,
   from when there was a fourth card, which left a hole on the right and made each
   card 83px wide on a 393px phone. See the phone rule below for why that mattered. */
.stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.stat {
  min-width: 0;
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
  padding: 14px 12px;
}

.stat strong {
  display: block;
  font-size: var(--sys-t-hero, 26px);
  font-weight: var(--sys-w-bold);
  line-height: 1;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}

.stat span {
  display: block;
  margin-top: 4px;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
  text-transform: none;
  letter-spacing: 0;
}

/* Segmented control (contract section 2): a grey track, 2px of padding, and a
   white segment with a soft shadow for the active item. Items are 44px tall —
   every tap target in this app is at least --sys-tap. */
.segment {
  position: static;
  z-index: 15;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 2px;
  padding: 2px;
  border: 0;
  border-radius: var(--sys-r-segment-outer, 10px);
  background: var(--sys-seg-track);
}

.segment button {
  min-height: var(--sys-tap, 44px);
  border: 0;
  border-radius: var(--sys-r-segment, 8px);
  background: transparent;
  color: var(--ink);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-medium);
}

.segment button.active {
  background: var(--surface);
  color: var(--ink);
  font-weight: var(--sys-w-semibold);
  box-shadow: var(--sys-shadow-segment);
}

.section-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: end;
}

.section-head h3 {
  margin: 0;
  font-size: var(--sys-t-headline);
  font-weight: var(--sys-w-semibold);
  letter-spacing: -.01em;
}

.section-head span {
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
  font-variant-numeric: tabular-nums;
}

.card-list {
  display: grid;
  gap: 10px;
}

/* The pay week over a run of Pay cards (UI-086): the week Team payouts pays by,
   its hours and its money. A quiet sub-head inside the list, not a new card. */
.pay-week-head {
  margin: 6px 2px 0;
  flex-wrap: wrap;
}
.pay-week-head h4 {
  margin: 0;
  font-size: var(--sys-t-lead);
  font-weight: var(--sys-w-semibold);
}

.compact-job-list {
  display: grid;
  gap: 8px;
}

.compact-job {
  width: 100%;
  min-height: 68px;
  display: grid;
  grid-template-columns: 74px minmax(0, 1fr);
  grid-template-areas:
    "date address"
    "date meta";
  column-gap: 12px;
  align-items: center;
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  color: var(--ink);
  padding: 11px 13px;
  text-align: left;
  box-shadow: var(--shadow);
}

.compact-job span {
  grid-area: date;
  display: grid;
  place-items: center;
  min-height: 46px;
  border-radius: var(--sys-r-control);
  background: var(--sys-fill, #F5F5F7);
  color: var(--ink);
  font-size: var(--sys-t-small);
  font-weight: var(--sys-w-semibold);
  font-variant-numeric: tabular-nums;
}

.compact-job strong {
  grid-area: address;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 15px;
}

.compact-job small {
  grid-area: meta;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
}

.job-card,
.pay-card,
.info-card,
.work-row,
.room-card {
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
}

.job-card {
  overflow: hidden;
}

.job-main {
  width: 100%;
  min-height: 0;
  color: inherit;
  text-align: left;
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr);
  gap: 12px;
  padding: 14px;
}

.date-tile {
  min-height: 78px;
  border-radius: 18px;
  background: var(--surface-2);
  display: grid;
  align-content: center;
  justify-items: center;
}

.date-tile.outside {
  background: var(--blue-soft);
  color: var(--blue);
}

.date-tile span {
  color: var(--muted);
  font-size: var(--sys-t-caption);
  font-weight: var(--sys-w-semibold);
}

.date-tile strong {
  font-size: var(--sys-t-hero, 26px);
  font-weight: var(--sys-w-bold);
  line-height: 1;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}

.job-copy {
  min-width: 0;
}

/* Chips: 11/600, a pill, sentence case — never uppercase (contract section 2).
   A plain .eyebrow is a LABEL ("Next Job", "Submit work"), so it is accent-tinted;
   the status colours are the modifiers. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  border-radius: var(--sys-r-pill);
  background: var(--blue-soft);
  color: var(--blue);
  padding: 4px 9px;
  font-size: var(--sys-t-caption);
  font-weight: var(--sys-w-semibold);
  line-height: 1.2;
  text-transform: none;
  letter-spacing: 0;
}

.eyebrow.blue {
  background: var(--blue-soft);
  color: var(--blue);
}

.eyebrow.gold {
  background: var(--gold-soft);
  color: var(--gold);
}

.eyebrow.red {
  background: var(--red-soft);
  color: var(--red);
}

.job-copy h4 {
  margin: 8px 0 2px;
  overflow-wrap: anywhere;
  font-size: var(--sys-t-headline);
  font-weight: var(--sys-w-semibold);
  line-height: 1.2;
}

.address-button {
  appearance: none;
  width: 100%;
  min-height: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: inherit;
  padding: 0;
  text-align: left;
  font: inherit;
  font-weight: var(--sys-w-semibold);
  line-height: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  overflow-wrap: anywhere;
  /* The address IS the button that opens maps, and one line of text is 24px tall —
     a 24px target for a person standing at a truck with gloves on. The app's own
     expander pattern (.jz-scope, .os2-mini-btn, .msg-x) gives it 44px of hit box
     without moving a pixel of layout: measured in the running crew app, not caught
     by a suite, because the strip is full-width and only its HEIGHT is short.
     2026-09-06 wave 2. */
  position: relative;
}

.address-button::after {
  content: "";
  position: absolute;
  inset: -10px 0;
}

.address-button.large {
  font-size: inherit;
  letter-spacing: inherit;
}

/* HIS ADDRESS SHEET, IN THIS APP (2026-10-12). The address on a Houses card and on
   a job's page opens Mario's sheet (address-actions.js, the file his page loads):
   Open Google Maps, Open Apple Maps, Copy Address. The crew's own panel of the same
   three under the job's title is gone. His sheet draws its buttons with his page's
   .button / .button.primary, which this app has no rule for, so they are given his
   Apple look here (bento.css html[data-ui="bento"] .button): a white pill with the
   accent as text and the small shadow, the primary the accent itself, each a 44pt
   target, the words at 16px. */
.address-action-sheet .button {
  min-height: var(--sys-tap, 44px);
  border: 0;
  border-radius: var(--sys-r-pill);
  background: var(--sys-panel);
  color: var(--sys-accent);
  box-shadow: var(--sys-shadow-btn);
  font-family: var(--sys-font);
  font-size: var(--sys-t-lead);
  font-weight: var(--sys-w-semibold);
  padding: 0 16px;
  cursor: pointer;
}

.address-action-sheet .button.primary {
  background: var(--sys-accent);
  color: #fff;
  box-shadow: none;
}

.job-copy p {
  margin: 0;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
}

.card-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  padding: 0 14px 14px;
}

.card-actions.three {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.card-actions .small-btn,
.card-actions .primary-btn,
.card-actions .secondary-btn {
  min-height: 46px;
  font-size: var(--sys-t-body-lg);
}

.pill-row,
.photo-row,
.room-list {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

.pill {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  border-radius: var(--sys-r-pill);
  background: var(--surface-2);
  color: var(--muted);
  padding: 0 10px;
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-medium);
}

.gold-pill {
  background: var(--gold-soft);
  color: var(--gold);
}

.photo-row a {
  flex: 1 1 130px;
}

.detail-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.info-card,
.room-card,
.pay-card {
  padding: 14px;
}

.info-card span,
.form-field label,
.room-card span {
  display: block;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-medium);
  text-transform: none;
  letter-spacing: 0;
}

.info-card strong,
.room-card strong {
  display: block;
  margin-top: 5px;
  overflow-wrap: anywhere;
}

.wide {
  grid-column: 1 / -1;
}

.bottom-bar {
  position: static;
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
}

.form .bottom-bar {
  position: sticky;
  /* Sits ON the nav's top edge (same offset as .detail-sticky-actions) — with
     overflow-x:clip the sticky actually engages now, so 0 would pin the bar
     BEHIND the nav. It used to be a hard-coded 92px, which left a 20px slot of
     scrolling form showing between this bar and the nav at every inset. */
  bottom: calc(var(--crew-nav-h) + env(safe-area-inset-bottom));
  /* --sys-z-raised: the tier for a sticky row or header inside a scroller.
     Was 24. Nothing real sits between the two on any screen this element appears
     on (.app-top:20 and .segment:15 are both position:static, where z-index does
     nothing at all), so the stacking order is unchanged — what changes is that
     "how do I sit above the list" now has an answer instead of a fresh number. */
  z-index: var(--sys-z-raised, 24);
  margin: 4px -4px 0;
  padding: 10px;
  border: 0;
  border-radius: var(--sys-r-card);
  /* Frosted, like the nav pill it docks on: the blur is in the SAME rule as the
     translucent white (qa:layout-contract accepts a see-through bar only then). */
  background: rgba(255,255,255,.94);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  box-shadow: var(--sys-shadow-pill);
}

.bottom-bar.two {
  grid-template-columns: 1fr 1fr;
}

.bottom-bar button,
.bottom-bar a {
  min-height: 50px;
}

.form {
  display: grid;
  gap: 14px;
}

.form-field {
  display: grid;
  gap: 7px;
}

/* Inputs (contract section 2): the quiet fill, no border, 12px corners, 16px
   type — under 16px iOS zooms the page in on focus and stays there. */
input,
select,
textarea {
  width: 100%;
  min-height: var(--sys-tap, 44px);
  border: 0;
  border-radius: var(--sys-r-control);
  background: var(--sys-fill, #F5F5F7);
  color: var(--ink);
  font-size: var(--sys-t-field, 16px);
  outline: none;
  padding: 0 14px;
}

input::placeholder,
textarea::placeholder {
  color: var(--sys-placeholder, #8E8E93);
}

textarea {
  min-height: 96px;
  padding: 13px 14px;
  resize: vertical;
}

input:focus,
select:focus,
textarea:focus {
  box-shadow: 0 0 0 2px var(--blue);
}

/* 2026-09-17: A FIELD STANDING ON THE PAGE IS WHITE. The quiet fill above is
   --sys-fill (#F5F5F7), the same grey as the page (--sys-page), so a field that
   sits straight on the page — More's three password fields, Add work's date and
   role, Submit Hours — had no edge at all (1.00:1): three labels over blank space,
   and a date that read as plain text. On the page a field takes the card's white
   and the card's shadow, the way every card on this page already reads; inside a
   white card (a task row) it keeps the grey fill. The shadow is only for a field
   that is not focused, so the blue focus ring above still wins. */
.form > .form-field :is(input, select, textarea),
.detail-grid > .form-field :is(input, select, textarea) {
  background: var(--sys-panel);
}

.form > .form-field :is(input, select, textarea):not(:focus),
.detail-grid > .form-field :is(input, select, textarea):not(:focus) {
  box-shadow: var(--sys-shadow-card);
}

.work-row {
  display: grid;
  gap: 12px;
  padding: 14px;
}

.work-row-head {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: center;
}

.work-row-head strong {
  font-size: var(--sys-t-headline);
  font-weight: var(--sys-w-semibold);
}

/* 2026-09-17 (W52): "Remove" takes a task row and the hours typed into it off the
   form. It was the same blue as every harmless link. Destructive words are the red
   that may be text (--sys-red-ink, 6.54:1 on white); the tap asks first whenever
   the row holds something typed (employee-field-app.js, [data-remove-task]). */
.work-row-head [data-remove-task] {
  color: var(--sys-red-ink);
}

/* The same segmented control as .segment: grey track, white active segment. */
.pay-toggle {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 2px;
  padding: 2px;
  border: 0;
  border-radius: var(--sys-r-segment-outer, 10px);
  background: var(--sys-seg-track);
}

.pay-toggle button {
  min-height: var(--sys-tap, 44px);
  border: 0;
  border-radius: var(--sys-r-segment, 8px);
  background: transparent;
  color: var(--ink);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-medium);
}

.pay-toggle button.active {
  background: var(--surface);
  color: var(--ink);
  font-weight: var(--sys-w-semibold);
  box-shadow: var(--sys-shadow-segment);
}

.field-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

/* A number, not a status: the quiet fill, ink, tabular figures. */
.work-total {
  border: 0;
  border-radius: var(--sys-r-control);
  background: var(--sys-fill, #F5F5F7);
  color: var(--ink);
  padding: 14px;
  font-size: var(--sys-t-lead);
  font-weight: var(--sys-w-semibold);
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.empty {
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
  padding: 24px;
  color: var(--muted);
  font-size: var(--sys-t-lead);
  font-weight: var(--sys-w-regular);
  text-align: center;
}

/* THE NAV IS NOT PAINTED HERE. The bottom nav is the one component the manager
   and the crew must render identically, so system.css paints it ONCE for both
   selectors (section "THE NAV": `html[data-ui="bento"] .bento-nav, .field-app
   .nav`) — position, size, the frosted white, the border, the shadow, the
   buttons, the active colour and the 22px icons. `.field-app .nav` is (0,2,0),
   so nothing a bare `.nav` rule in this file says can win, and nothing here
   tries: this file keeps only its layout hooks for the nav — the keyboard
   fade in the KEYBOARD block at the foot, and the icon slot below.
   qa:touch-targets forbids a see-through .nav background anywhere in this file;
   the frosted pill lives in system.css, where the blur is in the same rule. */
.nav button strong {
  font-size: 17px;
  line-height: 1;
  /* the icon slot: an inline SVG (employee-field-app.js NAV_ICON), sized by
     system.css's `.field-app .nav button svg` at 22px like the manager's. */
  display: grid;
  place-items: center;
}

.toast {
  position: fixed;
  left: var(--sys-center-x);
  /* ABOVE the nav, not across it. At 18px this pill covered 62 of its own 64px
     with the bottom nav and hung 2px off the glass — so every confirmation the
     crew gets ("Work submitted", "Everything's pulled") and every error was drawn
     on top of Home/Jobs/Pay/More. It is the app's whole error vocabulary; it has
     to land somewhere you can read it. */
  /* Left in --crew-nav-h + 12 + env() spelling on purpose, and it is worth saying
     why: this resolves to exactly --sys-bar-bottom (nav-top + --sys-bar-air, and
     bar-air IS this 12px — it is where system.css got the number), but the live
     qa:safe-area suite pins this literal shape for the three crew bars, so
     rewriting it would break a green guard for zero pixels of difference. The
     value is on the system either way, because --crew-nav-h now is. When the
     system's own guard lands, the two get reconciled in one commit. */
  bottom: calc(var(--crew-nav-h) + 12px + env(safe-area-inset-bottom));
  /* The legacy toast value (200000), not --sys-z-toast (600). 600 is the right
     tier on a migrated stack, and the crew's is not migrated: "Fix your hours"
     is at 10001, the photo viewer 9999, the gallery 9998 and the upload card
     100000, so at 600 every one of them painted OVER the pill. Save with the
     hours cleared raised "Add your hours." underneath the sheet and the button
     looked dead — a sheet that seems to do nothing is one people kill the app
     to get out of. This is the number system.css keeps for exactly this, and the
     manager's toast already rides it; it is still below the Face ID guard and
     the native recovery screen, which are meant to beat a toast. When the
     neighbourhood migrates, this goes back to var(--sys-z-toast). */
  z-index: var(--sys-z-toast-legacy, 200000);
  transform: translateX(-50%) translateY(20px);
  opacity: 0;
  pointer-events: none;
  max-width: calc(100vw - 28px);
  /* The dark pill stays (contract section 2): it is the app's error vocabulary. */
  border-radius: var(--sys-r-pill);
  background: var(--ink);
  color: #fff;
  padding: 12px 16px;
  font-size: var(--sys-t-lead);
  font-weight: var(--sys-w-semibold);
  box-shadow: var(--sys-shadow-sheet);
  transition: .18s ease;
}

.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.error {
  color: var(--red);
  font-weight: var(--sys-w-semibold);
}

/* HER PAY IS NEVER CUT OFF (2026-09-30). On a phone the three figures are rows, one
   under the other, each as wide as the screen. This rule used to stop at 390px — the
   iPhone 12/13/14 — so a 393px iPhone 15/16 and every Plus/Max got the columns, where
   a 26px "$1,462.50" is 126px wide in a card with 59px of room: the number ran over
   the next card and read "$1,462" with the cents under "Paid". 520px is past every
   phone held upright and short of a tablet, which has the room for columns. */
@media (max-width: 520px) {
  .stats {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 390px) {
  .hero h2 {
    font-size: 31px;
  }

  .job-main {
    grid-template-columns: 62px minmax(0, 1fr);
  }

  .date-tile {
    min-height: 68px;
  }

  .date-tile strong {
    font-size: 23px;
  }

  .field-grid,
  .detail-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 430px) {
  .field-app {
    width: 100%;
  }
  /* There was an .app-shell{padding-bottom:calc(92px + env(...))} here, written to
     give phones extra room under the fixed nav. It never once applied: the v3
     .app-shell rule further down the file sets the same property at the same
     specificity, and later wins — a media query adds none. Deleted rather than
     left to look like it does something; the real clearance is that one rule,
     and it is now derived from --crew-nav-h. */
}

@media (max-width: 414px) {
  .quick-grid {
    gap: 8px;
  }

  .quick-grid button,
  .quick-grid a {
    min-height: 86px;
    font-size: 11px;
  }
}

@media (max-width: 375px) {
  .content {
    padding-inline: 12px;
  }

  .summary {
    min-height: 98px;
    padding: 12px 10px;
  }

  .summary strong {
    font-size: 29px;
  }

  .compact-job {
    grid-template-columns: 62px minmax(0, 1fr);
    padding-inline: 10px;
  }
}

@media (max-width: 320px) {
  .top-row {
    grid-template-columns: 46px minmax(0, 1fr) 42px;
    gap: 8px;
  }

  .app-logo,
  .icon-btn {
    width: 42px;
    height: 42px;
    border-radius: 14px;
  }

  .top-title strong {
    font-size: 21px;
  }

  .segment {
    gap: 4px;
    padding: 4px;
  }

  .segment button {
    font-size: 10px;
  }
}

@media (min-width: 720px) {
  body {
    padding: 22px var(--sys-safe-r) 22px var(--sys-safe-l);
  }

  .field-app {
    min-height: calc(100dvh - 44px);
    border: 1px solid var(--line);
    border-radius: 34px;
    overflow: clip;
    box-shadow: var(--sys-shadow-sheet);
  }

  /* UI-019: not on the sign-in. At iPad width it sat in this rounded, bordered panel
     on the grey page while the manager's sign-in is the white page itself; they are
     one design. The class is set by employee-field-app.js paintScreen. */
  body.crew-signin {
    padding: 0 var(--sys-safe-r) 0 var(--sys-safe-l);
    background: var(--sys-panel);
  }
  body.crew-signin .field-app {
    min-height: 100dvh;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: var(--sys-panel);
  }
}

/* Employee dashboard v3.
   This used to be a SECOND, complete :root palette, then a stub of six names
   (--faint, --fill, --fill-2, --accent, --accent-soft, --accent-shadow) that no
   rule in this file ever read. Gone: the one palette is the block at the top of
   the file, and every name in it is an alias of system.css. A second :root block
   here — even an unused one — is the two-copies trap this file was bitten by. */

html,
body {
  background: var(--bg);
}

.field-app {
  width: min(100%, 430px);
  background: var(--bg);
}

.app-shell {
  position: relative;
  min-height: 100dvh;
  display: block;
  /* The one clearance rule for the whole crew app: the nav's top edge plus air.
     --sys-scroll-clear IS that arithmetic — nav box + float gap + the home
     indicator + --sys-scroll-air (16px here, the crew's own number, which
     system.css keeps distinct from the manager's 28px precisely so adopting the
     system does not quietly move every manager list 12px).
     It resolves to exactly what the hand-written calc() resolved to: 71 + 0 + env
     + 16 on a phone, 70 + 14 + env + 16 on a tablet.
     Note that the env() is GONE from this line, fallback included. That is the
     point, and it is checkable: a rule that reads --sys-scroll-clear may not also
     write env(safe-area-inset-bottom), because the token already contains it. The
     fallback therefore gives up the inset rather than re-adding it — if system.css
     ever fails to load, the crew app is 34px short of clearance at the foot of a
     list, which is a blemish; paying the inset twice is the bug. */
  padding-bottom: var(--sys-scroll-clear, calc(var(--crew-nav-h) + 16px));
}

/* There is deliberately NO `html.native-app .app-shell` override here.
   There used to be one: it dropped the inset on the shell's side, because
   native-feel.css pays it on <body> and the crew was being charged twice. But
   native-feel.css is loaded by team-clean.html and NOT by employees.html, so an
   override that assumes it always shipped the crew's second route with no inset at
   all — and when native-feel.css was separately taught to stop paying for the crew,
   BOTH routes lost it and the last row of the Jobs hub sat flush on the nav pill.
   --sys-scroll-clear above already contains the home indicator exactly once and is
   identical in both routes, so it is the only owner and needs no companion. */

.app-top {
  padding: calc(18px + var(--sys-safe-t)) 18px 4px;
  background: var(--bg);
  border-bottom: 0;
  backdrop-filter: none;
}

.top-row {
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr) 48px;
  gap: 14px;
  align-items: center;
}

.app-logo {
  width: 56px;
  height: 56px;
  object-fit: contain;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  padding: 7px;
  box-shadow: var(--shadow);
}

.top-title span {
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
  text-transform: none;
  letter-spacing: 0;
}

/* The page title: 32/700, tight (contract section 2). */
.top-title strong {
  margin-top: 2px;
  font-size: var(--sys-t-large-title, 32px);
  font-weight: var(--sys-w-bold);
  line-height: 1.05;
  letter-spacing: -.03em;
}

/* The round white "back" button on the Main board: 44px, the hairline shadow,
   the accent for its glyph. */
.icon-btn {
  width: 44px;
  height: 44px;
  border-radius: var(--sys-r-pill);
  background: var(--surface);
  color: var(--blue);
  box-shadow: var(--sys-shadow-card);
}

.primary-btn {
  background: var(--blue);
  color: #fff;
}

.secondary-btn {
  background: var(--surface);
}

.content {
  padding: 14px 18px 0;
}

.screen {
  gap: 16px;
}

.today-hero {
  display: flex;
  justify-content: space-between;
  align-items: start;
  gap: 14px;
  padding: 16px;
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
}

.today-hero span,
.section-title {
  display: block;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-medium);
  letter-spacing: 0;
  text-transform: none;
}

.today-hero h2 {
  margin: 4px 0 0;
  font-size: var(--sys-t-large-title, 32px);
  font-weight: var(--sys-w-bold);
  line-height: 1.05;
  letter-spacing: -.03em;
}

.today-hero p {
  margin: 8px 0 0;
  color: var(--muted);
  font-weight: var(--sys-w-regular);
}

.section-title {
  margin-top: 12px;
}

.summary-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}

.summary {
  min-height: 112px;
  display: grid;
  align-content: space-between;
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
  padding: 15px 13px;
}

.summary span {
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-medium);
}

.summary strong {
  font-size: 28px;
  font-weight: var(--sys-w-bold);
  line-height: 1;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}

.summary.pickup span {
  color: var(--blue);
}

.summary.danger span {
  color: var(--red);
}

.wide-action {
  width: 100%;
  min-height: 50px;
  font-size: var(--sys-t-lead);
}

.week-strip {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 7px;
}

.week-day {
  min-height: 94px;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 4px;
  border: 0;
  border-radius: var(--sys-r-control);
  background: var(--surface);
  box-shadow: var(--shadow);
  text-align: center;
}

.week-day.active {
  background: var(--blue);
  color: #fff;
}

.week-day span {
  font-size: var(--sys-t-caption);
  font-weight: var(--sys-w-semibold);
  color: inherit;
  opacity: .74;
}

.week-day strong {
  font-size: var(--sys-t-title);
  font-weight: var(--sys-w-bold);
  font-variant-numeric: tabular-nums;
}

.week-day small {
  font-size: var(--sys-t-caption);
  font-weight: var(--sys-w-semibold);
  color: inherit;
  opacity: .7;
}

.dots {
  min-height: 8px;
  display: flex;
  gap: 4px;
  justify-content: center;
}

.dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--blue);
}

.dot.staging {
  background: var(--green);
}

.dot.danger {
  background: var(--gold);
}

.quick-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
}

.quick-grid button,
.quick-grid a {
  min-height: 92px;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 8px;
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--ink);
  padding: 10px 6px;
  text-align: center;
  text-decoration: none;
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-medium);
}

.quick-grid strong {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: var(--sys-r-control);
  background: var(--blue-soft);
  color: var(--blue);
  font-size: var(--sys-t-small);
}

.instruction-card {
  width: 100%;
  min-height: 78px;
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr);
  gap: 12px;
  align-items: center;
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  color: var(--ink);
  padding: 14px 16px;
  text-align: left;
  box-shadow: var(--shadow);
}

.instruction-card > strong {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: var(--sys-r-control);
  background: var(--sys-fill, #F5F5F7);
  font-size: 22px;
  /* 2026-09-17 (W83): drawn glyphs in the accent (were ℹ️ 📦 🔒), as on a job's
     call and message buttons: the same grey tile, the same blue line. */
  color: var(--blue);
}

.instruction-card b,
.instruction-card small {
  display: block;
}

.instruction-card b {
  font-size: var(--sys-t-headline);
  font-weight: var(--sys-w-semibold);
  line-height: 1.2;
}

.instruction-card small {
  margin-top: 4px;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
}

.instructions-hero h2 {
  font-size: var(--sys-t-large-title, 32px);
}

.instruction-panel {
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  padding: 16px;
  box-shadow: var(--shadow);
}

.instruction-list {
  margin: 14px 0 0;
  padding-left: 22px;
  color: var(--ink);
  display: grid;
  gap: 10px;
  font-size: var(--sys-t-lead);
  font-weight: var(--sys-w-regular);
  line-height: 1.35;
}

.instruction-list li::marker {
  color: var(--blue);
  font-weight: var(--sys-w-semibold);
}

.instruction-panel.help {
  background: var(--gold-soft);
}

.instruction-panel.help strong {
  display: block;
  margin-top: 10px;
  font-size: var(--sys-t-headline);
  font-weight: var(--sys-w-semibold);
}

.instruction-panel.help p {
  margin: 6px 0 0;
  color: var(--muted);
  font-weight: var(--sys-w-regular);
}

.segment {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  position: static;
}

/* (.segment button.active is declared once, in the base block above: a white
   segment on the grey track. Green is a status colour, never an active tab.) */

.section-head {
  align-items: center;
}

.job-card,
.pay-card,
.info-card,
.work-row,
.room-card,
.outside-card {
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
}

.job-card {
  padding: 16px;
}

.job-row {
  display: flex;
  gap: 14px;
  align-items: flex-start;
}

.date-block {
  flex: 0 0 72px;
  min-width: 72px;
  height: 104px;
  display: grid;
  align-content: center;
  justify-items: center;
  border-radius: var(--sys-r-card);
  background: var(--sys-fill, #F5F5F7);
  color: var(--ink);
  text-align: center;
}

.date-block.pickup {
  background: var(--blue-soft);
  color: var(--blue);
}

.date-block.danger {
  background: var(--red-soft);
  color: var(--red);
}

.date-block span {
  color: var(--muted);
  font-size: var(--sys-t-caption);
  font-weight: var(--sys-w-semibold);
}

.date-block strong {
  font-size: 28px;
  font-weight: var(--sys-w-bold);
  line-height: 1;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}

.job-main {
  display: block;
  min-width: 0;
  padding: 0;
}

/* Status chips (contract section 2): 11/600, a pill, 4px 9px, sentence case.
   .badge is a STATUS (its default, "Active", is the green pair); .eyebrow is a
   label and keeps the accent pair from the base block. */
.badge,
.eyebrow {
  display: inline-flex;
  align-items: center;
  border-radius: var(--sys-r-pill);
  background: var(--green-soft);
  color: var(--green);
  padding: 4px 9px;
  font-size: var(--sys-t-caption);
  font-weight: var(--sys-w-semibold);
  line-height: 1.2;
  text-transform: none;
  letter-spacing: 0;
}

.eyebrow {
  background: var(--blue-soft);
  color: var(--blue);
}

.badge.pickup,
.eyebrow.blue {
  background: var(--blue-soft);
  color: var(--blue);
}

.badge.danger,
.eyebrow.red {
  background: var(--red-soft);
  color: var(--red);
}

.badge.gold,
.eyebrow.gold {
  background: var(--gold-soft);
  color: var(--gold);
}

/* A card's primary line: the address, 17/600 (contract section 1). */
.job-main h2 {
  margin: 8px 0 4px;
  font-size: var(--sys-t-headline);
  font-weight: var(--sys-w-semibold);
  line-height: 1.2;
  letter-spacing: -.01em;
}

.address-button {
  color: inherit;
  font-size: inherit;
}

.job-main p {
  margin: 4px 0;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
}

.chips,
.pill-row,
.room-list {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 11px;
}

.chips.compact {
  margin-top: 10px;
}

.chip,
.pill {
  min-height: 28px;
  border-radius: var(--sys-r-pill);
  background: var(--surface-2);
  color: var(--muted);
  padding: 0 10px;
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-medium);
}

.job-actions {
  display: grid;
  grid-template-columns: 1fr 1.25fr;
  gap: 9px;
  padding: 15px 0 0;
}

.job-actions.three {
  grid-template-columns: 1fr 1.2fr 1fr;
}

.job-actions.two {
  grid-template-columns: 1fr 1fr;
}

.job-actions .primary-btn,
.job-actions .secondary-btn {
  min-height: 48px;
  padding: 0 8px;
  font-size: var(--sys-t-body-lg);
}

/* "I worked here": colour only — the accent, like every primary button. */
.worked {
  background: var(--blue);
}

.outside-card {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr);
  gap: 14px;
  padding: 18px;
}

.outside-icon {
  width: 56px;
  height: 56px;
  display: grid;
  place-items: center;
  border-radius: var(--sys-r-card);
  background: var(--sys-purple-soft, #F5EAFB);
  /* 2026-09-17 (W46): the text purple, 5.19:1 on this tint (#AF52DE was 3.55). */
  color: var(--sys-purple-ink, #8944AB);
  font-weight: var(--sys-w-semibold);
}

.outside-copy h3 {
  margin: 8px 0 4px;
  font-size: var(--sys-t-headline);
  font-weight: var(--sys-w-semibold);
}

.outside-copy p {
  margin: 0;
  color: var(--muted);
  font-weight: var(--sys-w-regular);
}

.outside-actions {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 1fr 1.25fr;
  gap: 9px;
}

.detail-hero {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 16px;
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
}

.detail-heading {
  min-width: 0;
}

/* The house title: 22/700 with its status chip beside it (contract section 2). */
.detail-heading h2 {
  margin: 8px 0 4px;
  font-size: var(--sys-t-display);
  font-weight: var(--sys-w-bold);
  line-height: 1.1;
  letter-spacing: -.02em;
}

.detail-heading p {
  margin: 0;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
}

.detail-actions {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.detail-grid {
  gap: 10px;
}

.bottom-bar.two {
  grid-template-columns: 1fr 1.25fr;
}

/* (The fixed .nav rule, its button rule and the tablet pill that used to be here
   are gone: system.css "THE NAV" positions and paints the one frosted pill for
   both apps at every width — 64px tall, floating 14px, paying the home indicator
   in its own `bottom:`. --crew-nav-h at the top of this file is that pill's box
   plus its float gap, so the bars that dock on it still land on its top edge.) */

@media (max-width: 390px) {
  .content {
    padding-inline: 14px;
  }

  .summary-grid {
    gap: 8px;
  }

  .summary {
    min-height: 102px;
    padding: 13px 10px;
  }

  .quick-grid {
    gap: 7px;
  }

  .quick-grid button,
  .quick-grid a {
    min-height: 86px;
    font-size: 11px;
  }

  .date-block {
    flex-basis: 64px;
    min-width: 64px;
    height: 92px;
  }

  .date-block strong {
    font-size: 29px;
  }

  .job-main h2 {
    font-size: 19px;
  }
}

/* Employee UX action dashboard */
.compact-home-hero {
  padding: 18px;
}

.compact-home-hero h2 {
  font-size: 32px;
}

.next-job-card {
  display: grid;
  gap: 16px;
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  padding: 16px;
  box-shadow: var(--shadow);
}

.next-job-card h2 {
  margin: 10px 0 6px;
  overflow-wrap: anywhere;
  font-size: var(--sys-t-display);
  font-weight: var(--sys-w-bold);
  line-height: 1.1;
  letter-spacing: -.02em;
}

.next-job-card p {
  margin: 0;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
}

.next-job-actions {
  display: grid;
  grid-template-columns: 1.15fr .85fr;
  gap: 8px;
}

.next-job-actions .primary-btn,
.next-job-actions .secondary-btn {
  min-height: 54px;
}

.submit-hours-card {
  display: grid;
  gap: 14px;
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  padding: 16px;
  box-shadow: var(--shadow);
}

.submit-hours-card h2 {
  margin: 10px 0 6px;
  font-size: var(--sys-t-display);
  font-weight: var(--sys-w-bold);
  line-height: 1.1;
  letter-spacing: -.02em;
}

.submit-hours-card p {
  margin: 0;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
}

.submit-hours-card .primary-btn {
  min-height: 54px;
}

.submit-type-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.submit-type-grid button,
.submit-house-option,
.selected-work-target {
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--ink);
  padding: 16px;
  text-align: left;
}

.submit-type-grid button {
  min-height: 112px;
}

/* The chosen option: an accent ring, the accent's soft tint. */
.submit-type-grid button.active,
.submit-house-option.active {
  background: var(--blue-soft);
  box-shadow: var(--shadow), inset 0 0 0 1.5px var(--blue);
}

.submit-type-grid strong,
.selected-work-target strong {
  display: block;
  overflow-wrap: anywhere;
}

.submit-type-grid span,
.selected-work-target span {
  display: block;
  margin-top: 6px;
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
}

/* 10 apart, as his cards are. */
.submit-house-list {
  display: grid;
  gap: 10px;
}

/* A house to pick is the Houses card (2026-10-06): Mario's card — pill, address,
   names, next-step line — without the bar and the buttons, and the whole card is
   the button. Its insides are the .jz-job rules at the Jobs hub block; this is the
   box: his card's 16 padding, a block, not the tile-and-words row it was. The ring
   and the tint above still say which one she picked. */
.submit-house-option {
  display: block;
  width: 100%;
  min-height: var(--sys-tap);
  padding: 16px;
  font: inherit;
  text-align: left;
}

/* The picked card is the accent's soft tint — the very colour of the blue Upcoming
   pill, which on it was blue words with no pill around them. White there, like the
   card it sits on everywhere else; the other colours stand out on the tint. */
.submit-house-option.active .pill.p-blue {
  background: var(--sys-panel);
}

.recent-activity {
  display: grid;
  gap: 8px;
}

.recent-activity article {
  display: grid;
  gap: 3px;
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--surface);
  box-shadow: var(--shadow);
  padding: 12px 16px;
}

.recent-activity span {
  color: var(--blue);
  font-size: var(--sys-t-caption);
  font-weight: var(--sys-w-semibold);
  text-transform: none;
}

.recent-activity strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.recent-activity small {
  color: var(--muted);
  font-weight: var(--sys-w-regular);
}

.job-search {
  display: grid;
  gap: 7px;
}

.job-search span {
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-medium);
  text-transform: none;
  letter-spacing: 0;
}

/* The Jobs filter strips: the same segmented control as .segment. */
.scope-toggle,
.job-filters {
  display: grid;
  gap: 2px;
  padding: 2px;
  border: 0;
  border-radius: var(--sys-r-segment-outer, 10px);
  background: var(--sys-seg-track);
}

.scope-toggle {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.job-filters {
  grid-template-columns: repeat(5, minmax(0, 1fr));
}

.scope-toggle button,
.job-filters button {
  min-height: var(--sys-tap, 44px);
  border: 0;
  border-radius: var(--sys-r-segment, 8px);
  background: transparent;
  color: var(--ink);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-medium);
}

.scope-toggle button.active,
.job-filters button.active {
  background: var(--surface);
  color: var(--ink);
  font-weight: var(--sys-w-semibold);
  box-shadow: var(--sys-shadow-segment);
}

.outside-mini-action {
  width: 100%;
  display: grid;
  gap: 4px;
  border: 0;
  border-radius: var(--sys-r-card);
  background: var(--blue-soft);
  color: var(--ink);
  padding: 16px;
  text-align: left;
}

.outside-mini-action strong {
  font-size: var(--sys-t-headline);
  font-weight: var(--sys-w-semibold);
}

.outside-mini-action span {
  color: var(--muted);
  font-size: var(--sys-t-body);
  font-weight: var(--sys-w-regular);
}

.detail-sticky-actions {
  position: sticky;
  /* Docked on the nav's top edge. At 92px against a 71px nav this bar floated
     with a 20px band of live, scrolling list visible between two translucent
     blurred surfaces — two half-transparent slabs sliding over the same content
     is what reads as "los botones tapando la pantalla" even where the geometry
     is clear. One number now, and it comes from the nav itself. */
  bottom: calc(var(--crew-nav-h) + env(safe-area-inset-bottom));
  /* --sys-z-raised: the tier for a sticky row or header inside a scroller.
     Was 24. Nothing real sits between the two on any screen this element appears
     on (.app-top:20 and .segment:15 are both position:static, where z-index does
     nothing at all), so the stacking order is unchanged — what changes is that
     "how do I sit above the list" now has an answer instead of a fresh number. */
  z-index: var(--sys-z-raised, 24);
  margin: 6px -4px 0;
  padding: 10px;
  border: 0;
  border-radius: var(--sys-r-card);
  /* Frosted like the nav it docks on; blur in the SAME rule as the rgba. */
  background: rgba(255,255,255,.94);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  box-shadow: var(--sys-shadow-pill);
}

.detail-sticky-actions .primary-btn {
  font-size: var(--sys-t-lead);
}

@media (max-width: 390px) {
  .next-job-actions,
  .submit-type-grid {
    grid-template-columns: 1fr;
  }

  .job-filters {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (max-width: 340px) {
  .job-filters {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ===== Jobs hub redesign (jz-) — compact list-first Home/Jobs, 2026-07 ===== */
/* The hub's own names are aliases of the system's tokens, like the block at the
   top of the file. The font is the phone's own (no Inter, and none of Inter's
   stylistic-set feature flags). */
.jz-shell{--jz-green:var(--sys-green);--jz-ink:var(--sys-ink);--jz-gray:var(--sys-muted);--jz-bg:var(--sys-page);--jz-line:var(--sys-line);--jz-amber:var(--sys-orange);--jz-amber-bg:var(--sys-orange-soft);--jz-blue:var(--sys-accent);--jz-blue-bg:var(--sys-accent-soft);--jz-red:var(--sys-red-ink);--jz-red-bg:var(--sys-red-soft)}
.jz-shell{
  font-family:var(--sys-font);font-feature-settings:"tnum";
  background:var(--jz-bg);min-height:100dvh;font-size:var(--sys-t-body-lg);color:var(--jz-ink)}
/* The Jobs hub is the one crew screen that does NOT render appHeader(), so .jz-head
   is the topmost element and nothing above it pays the status-bar inset — the
   greeting, the Mine/All toggle and the avatar drew under the Dynamic Island in
   the iOS app. Same arithmetic .app-top already uses. env() is 0 on desktop. */
/* Frosted over the list like the nav pill (the ground colour at .86, blurred in
   the same rule); sticky at the TOP, so the see-through rules for bottom bars do
   not apply, and the list scrolling under a header is what a header is for. */
.jz-head{position:sticky;top:0;z-index:var(--sys-z-raised,30);background:rgba(245,245,247,.86);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);border-bottom:1px solid var(--jz-line);padding:calc(10px + var(--sys-safe-t)) 14px 10px}
.jz-head-row{display:flex;justify-content:space-between;align-items:center;gap:10px}
.jz-hi{font-size:var(--sys-t-body);color:var(--jz-gray);font-weight:var(--sys-w-regular);margin:0}
/* The page title, 32/700 (Home board). */
.jz-title{font-size:var(--sys-t-large-title);font-weight:var(--sys-w-bold);letter-spacing:-.03em;line-height:1.05;margin:1px 0 0}
.jz-head-right{display:flex;align-items:center;gap:8px}
/* His Houses header's calendar icon (2026-10-12; bento.css .bento-icon-btn): a 44pt
   white circle on the card shadow, the drawn page in ink. */
.jz-hd-cal{flex:none;display:grid;place-items:center;width:var(--sys-tap,44px);height:var(--sys-tap,44px);padding:0;border:0;border-radius:var(--sys-r-pill);background:var(--sys-panel);box-shadow:var(--sys-shadow-card);color:var(--jz-ink);cursor:pointer}
.jz-hd-cal svg{display:block;width:20px;height:20px}
/* Mine / All: a small segmented control. */
.jz-scope{display:inline-flex;gap:2px;background:var(--sys-seg-track);border:0;border-radius:var(--sys-r-segment-outer);padding:2px}
.jz-scope button{border:0;background:transparent;font:inherit;font-size:var(--sys-t-body);font-weight:var(--sys-w-medium);color:var(--jz-ink);padding:5px 11px;border-radius:var(--sys-r-segment);min-height:28px;position:relative}
.jz-scope button.on{background:var(--sys-panel);font-weight:var(--sys-w-semibold);box-shadow:var(--sys-shadow-segment)}
/* 28px is what Mine/All looks like; 44 is what it is. Same trick .pl-edit already
   uses — an invisible expander costs no layout, and growing the pill itself would
   push the greeting and the avatar around. -2px sideways so the two halves meet
   in the middle instead of stealing from each other.
   That leaves the real hit box 40px wide, not 44, and it stays that way on
   purpose. The two buttons touch — .jz-scope is an inline-flex with no gap — so
   any sideways growth here overlaps its neighbour, and "All" (later in the DOM)
   would sit on top of the right edge of "Mine". A control covering another
   control is the bug this whole wave is about; 4px of width is not worth buying
   one back. The centre of each half is clean, which is what a thumb needs. */
.jz-scope button::after{content:"";position:absolute;inset:-8px -2px}
/* 44 and white, the same circle as the manager's .bento-avatar (bento.css) —
   a tap target at its real size, lifted off the grey ground by the card shadow
   instead of being a small accent dot. The accent is for actions, not identity. */
.jz-avatar{width:var(--sys-tap,44px);height:var(--sys-tap,44px);border-radius:var(--sys-r-pill);border:0;background:var(--sys-panel);color:var(--jz-ink);font-weight:var(--sys-w-semibold);font-size:14px;display:grid;place-items:center;box-shadow:var(--sys-shadow-card)}
/* The Houses filters are separate white pills, each count in a small badge, and
   the one she is on is the accent with white words (mockup v2, 2026-10-05; it was
   a grey segmented track). Six filters are wider than any phone, so the row
   scrolls sideways; it runs to the screen's edges (the -14px gives back .jz-head's
   gutter) so a pill slides out under the edge instead of being cut 14px in, and the
   padding keeps the pills' shadows from being clipped by the scroller. */
.jz-chips{display:flex;gap:8px;overflow-x:auto;margin:10px -14px 0;padding:2px 14px 4px;-webkit-overflow-scrolling:touch;scrollbar-width:none}
.jz-chips::-webkit-scrollbar{display:none}
/* More filters past the right edge (UI-192): the edge fades, so the cut reads as "scroll". */
.jz-chips.more{-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 44px),transparent);mask-image:linear-gradient(to right,#000 calc(100% - 44px),transparent)}
/* 44, not 34: these are the filters on the screen the crew lands on. */
.jz-chip{flex:0 0 auto;border:0;background:var(--sys-panel);border-radius:var(--sys-r-pill);box-shadow:var(--sys-shadow-btn);font:inherit;font-size:var(--sys-t-body-lg);font-weight:var(--sys-w-semibold);color:var(--jz-ink);padding:0 12px 0 14px;min-height:44px;display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
/* The badge is sized by its padding, not a height: it is the count inside a 44pt
   control, not a control of its own. */
.jz-chip b{font-size:var(--sys-t-small);font-weight:var(--sys-w-bold);line-height:1.34;padding:2px 7px;border-radius:var(--sys-r-pill);background:var(--sys-fill-2);color:var(--jz-gray);font-variant-numeric:tabular-nums}
/* White on the accent, and the badge turns over: the accent on white reads at
   5.3:1 where white on a see-through white over the accent did not reach 4.5. */
.jz-chip.on{background:var(--jz-blue);color:#fff;box-shadow:none}
.jz-chip.on b{background:var(--sys-panel);color:var(--jz-blue)}
.jz-tools{display:flex;gap:7px;margin-top:9px}
/* A white pill on the grey ground, exactly like the manager's .bento-search
   input: --sys-fill IS --sys-page here, so the fill treatment made the field
   disappear into the page. The card surface is what makes it a field. */
.jz-search{flex:1;display:flex;align-items:center;gap:7px;background:var(--sys-panel);border:0;border-radius:var(--sys-r-pill);box-shadow:var(--sys-shadow-card);padding:0 14px;color:var(--jz-gray)}
/* 16px, and it is not a style choice. Safari zooms the whole page in on any input
   under 16px and never zooms back out — and team-clean.html's viewport tag has no
   maximum-scale, so in Safari and the home-screen PWA the page stays pinchable. So
   a crew member tapping this box at 13px got the entire app magnified and stuck
   that way. (2026-09-17: not inside the App Store app, on purpose: native-enhance.js
   pins the viewport there and nobody can pinch; see system.css section 4.)
   min-width:0 because a flex item's default min-width:auto is the text
   width: at 16px the box refused to shrink and pushed the sort button off the
   right edge, which is a sideways scroll on the app's busiest screen. */
.jz-search input{flex:1;min-width:0;border:0;background:transparent;font:inherit;font-size:16px;min-height:44px;outline:none;color:var(--jz-ink)}
.jz-sort{display:inline-flex;align-items:center;gap:5px;border:0;background:var(--sys-panel);border-radius:var(--sys-r-pill);box-shadow:var(--sys-shadow-btn);font:inherit;font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);color:var(--jz-blue);padding:0 14px;min-height:44px}
/* The comment that used to sit here said the Jobs hub "does not use .app-shell, so
   it has to reserve the nav's room itself". That stopped being true: jzHubScreen()
   renders <div class="app-shell jz-shell"> and .jz-main is INSIDE it. So the hub —
   the crew's home screen, the longest list in the app — was reserving the whole
   nav clearance twice, once on the shell and once here, plus <body>'s inset in the
   native shell on top of that. About 174px + three insets of nothing at the foot of
   the list you scroll most.
   The shell owns the nav clearance now (see .app-shell). This is just the hub's own
   bottom padding, matching its 10px top. */
.jz-main{padding:10px 14px}
.jz-outside{width:100%;display:flex;align-items:center;gap:10px;border:0;background:var(--sys-panel);border-radius:var(--sys-r-card);box-shadow:var(--sys-shadow-card);padding:10px 16px;font:inherit;text-align:left;margin-bottom:8px;min-height:52px}
/* 2026-09-17 (W83): a drawn truck, not the 🚚 emoji; flex so the SVG sits centred, not on a text baseline. */
.jz-outside-ic{display:inline-flex;flex:0 0 auto;font-size:16px;color:var(--jz-ink)}
.jz-outside-t{flex:1;min-width:0}
.jz-outside-t b{display:block;font-size:var(--sys-t-lead);font-weight:var(--sys-w-semibold)}
.jz-outside-t small{display:block;font-size:var(--sys-t-body);color:var(--jz-gray);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.jz-outside-add{flex:0 0 auto;display:inline-flex;align-items:center;font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);color:var(--jz-blue);border:0;background:var(--jz-blue-bg);border-radius:var(--sys-r-pill);padding:0 12px;min-height:44px}
.jz-outside-chev{color:var(--jz-gray);font-size:16px}
.jz-count{font-size:var(--sys-t-body);color:var(--jz-gray);font-weight:var(--sys-w-regular);margin:2px 2px 8px}
/* The footer that explains a job she cannot see any more. Quiet — it is a note,
   not an alert — but the button is a full 44pt target, because it is the only
   way back to a job somebody may be standing in front of. */
.jz-stale{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:10px 2px 4px;padding:10px 16px;border-radius:var(--sys-r-card);background:var(--sys-panel);border:0;box-shadow:var(--sys-shadow-card)}
.jz-stale span{font-size:var(--sys-t-body);line-height:1.35;color:var(--jz-gray);font-weight:var(--sys-w-regular)}
.jz-stale button{flex:0 0 auto;min-height:44px;padding:0 14px;border:0;background:transparent;color:var(--jz-blue);font-weight:var(--sys-w-medium);font-size:var(--sys-t-lead);line-height:1}
/* THE HOUSES LIST IS MARIO'S LIST (2026-10-06). The tile design was "muy grandes…
   visualmente heavy y horrible", two light row lists were "Ninguna … como mi app",
   so each house is his own Houses card (bento.css section 8, .job) in the crew's
   version (jzCard). This shell does not load bento.css, so the rules it needs are
   here, his values on the shared tokens, scoped to .jz-job — the Houses card and
   Submit Hours' house rows (submitHouseButton) are both .jz-job. Where a value here
   differs from his, the line says why.
   The card: white, no border, 18 corners, the hairline shadow, 16 padding, 10 apart. */
.jz-card{display:block;background:var(--sys-panel);border:0;border-radius:var(--sys-r-card);box-shadow:var(--sys-shadow-card);padding:16px;margin-bottom:10px;cursor:pointer}
/* The row under the keyboard's ↑/↓ (keyboard-shortcuts.js, the open Duo or an iPad): a ring
   only for a keyboard, never for a tap. Same ring as the manager's .job:focus-visible. 2026-10-24. */
.jz-card:focus-visible{outline:2px solid var(--jz-blue);outline-offset:2px}
/* Status pill row: the pill and "Furniture pulled", wrapping, never clipped. */
.jz-job .r1{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:8px}
/* His status chip, 11/600, sentence case. min-height:0 gives back the 28px floor the
   app-wide .pill (a <span> label on the job page) sets; his has none. */
.jz-job .pill{display:inline-flex;align-items:center;min-height:0;font-size:var(--sys-t-caption);font-weight:var(--sys-w-semibold);letter-spacing:0;text-transform:none;border-radius:var(--sys-r-pill);padding:4px 9px;white-space:nowrap}
.jz-job .pill.p-green{color:var(--sys-green);background:var(--sys-green-soft)}
.jz-job .pill.p-amber{color:var(--sys-orange);background:var(--sys-orange-soft)}
.jz-job .pill.p-blue{color:var(--sys-accent);background:var(--sys-accent-soft)}
/* Purple is --sys-purple-ink, the token made for purple TEXT: his --sys-purple on its
   soft tint reads 3.6:1, under the 4.5 every word in this app keeps (W46). Same hue. */
.jz-job .pill.p-purple{color:var(--sys-purple-ink);background:var(--sys-purple-soft)}
.jz-job .pill.p-gray{color:var(--sys-muted);background:var(--sys-fill-2)}
.jz-job .r1 .pull-chip{display:inline-flex;align-items:center;font-size:var(--sys-t-caption);font-weight:var(--sys-w-semibold);letter-spacing:0;text-transform:none;border-radius:var(--sys-r-pill);padding:4px 9px;white-space:nowrap}
.jz-job .r1 .pull-chip.ok{color:var(--sys-green);background:var(--sys-green-soft)}
.jz-job .r1 .pull-chip.warn{color:var(--sys-orange);background:var(--sys-orange-soft)}
/* The address is the headline: 17/600, the whole address, three lines before it is
   cut — his card cuts at two. The crew's card used to give the city its own line
   under the street; with the whole address in one heading, two lines at 320 wide
   cut "…Apartment 305, Littleton, CO" before Littleton (review of 2026-10-06). A
   street and city that fit in two lines look exactly as his.
   On Houses it is a button (it opens the house, like the rest of the card) and gets
   his 44pt treatment: the growth is a TRANSPARENT BORDER, so the clamp still clips
   at the text (bento.css explains the measurement). Submit Hours' rows draw it the
   same, so the two lists space alike. */
.jz-job .hd{display:block;min-width:0}
.jz-job .adr{display:block;margin:0;font-size:var(--sys-t-headline);font-weight:var(--sys-w-semibold);letter-spacing:-.01em;line-height:1.22;color:var(--sys-ink);max-width:100%;text-align:left;overflow-wrap:anywhere}
.jz-job .adr > span,.jz-job span.adr,.jz-job .adr > .address-action{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden;max-width:100%;box-sizing:border-box;border-top:11px solid transparent;border-bottom:11px solid transparent;min-height:var(--sys-tap);cursor:pointer}
/* Since 2026-10-12 the address on a Houses card is his address button (it opens his
   address sheet; the rest of the card opens the house). Dressed as his card dresses
   it (bento.css .job .adr .adr-btn): the heading's own type and colour, no underline —
   the hero stays clean — and his transparent-border 44pt above. */
.jz-job .adr > .address-action{width:100%;padding:0;border-left:0;border-right:0;background:none;color:inherit;font:inherit;letter-spacing:inherit;line-height:inherit;text-align:left;text-decoration:none}
/* Who is on the job, where his card has the agent: his .cl (13/500, muted). It wraps
   where his ellipsizes — the names are the point of the line, and an ellipsis cut
   the last one. His .asg role letters in ink, bold, as his card draws them. */
.jz-job .cl{display:block;font-size:var(--sys-t-body);font-weight:var(--sys-w-medium);color:var(--sys-muted);margin-top:3px;overflow-wrap:anywhere}
.jz-job .cl b{color:var(--sys-ink);font-weight:var(--sys-w-semibold)}
/* ONE next-step line: quiet label, bold date, countdown capsule. */
.jz-job .dts{display:block;margin-top:10px}
.jz-job .step{display:inline-flex;align-items:center;flex-wrap:wrap;gap:7px;font-size:var(--sys-t-body);color:var(--sys-ink)}
.jz-job .step i{font-style:normal;font-size:var(--sys-t-body);font-weight:var(--sys-w-regular);letter-spacing:0;text-transform:none;color:var(--sys-muted)}
.jz-job .step b{color:var(--sys-ink);font-weight:var(--sys-w-semibold);letter-spacing:-.01em}
.jz-job .step .cd{font-size:var(--sys-t-caption);font-weight:var(--sys-w-semibold);color:var(--sys-muted);background:var(--sys-fill-2);border-radius:var(--sys-r-pill);padding:3px 8px;white-space:nowrap}
.jz-job .step .cd.b{color:var(--sys-red-ink);background:var(--sys-red-soft)}
.jz-job .step .cd.w{color:var(--sys-orange);background:var(--sys-orange-soft)}
.jz-job .step.step-sched i,.jz-job .step.step-sched b{color:var(--sys-green)}
.jz-job .step.step-sched .cd{color:var(--sys-green);background:var(--sys-green-soft)}
.jz-job .step.step-empty{color:var(--sys-orange);font-weight:var(--sys-w-semibold);font-size:var(--sys-t-body)}
.jz-job .step.step-muted,.jz-job .step.step-muted b{color:var(--sys-muted)}
.jz-job .step .stage-time{color:var(--sys-accent);white-space:nowrap}
/* The stay so far: 4px, the grey track, the accent; orange from 10 days left, red past it. */
.jz-job .prog{margin-top:8px;height:4px;border-radius:var(--sys-r-pill);background:var(--sys-track);overflow:hidden}
.jz-job .prog i{display:block;height:100%;border-radius:var(--sys-r-pill);background:var(--sys-accent)}
.jz-job .prog.warn i{background:var(--sys-orange)}
.jz-job .prog.over i{background:var(--sys-red-ink)}
.jz-job .jz-property-banner{margin-top:10px}
/* His action row: quiet capsules left, ONE accent primary pinned right, 44 tall and
   10 apart, allowed to wrap rather than shrink a target. Directions is a link (it
   leaves for Google Maps), so the two quiet ones are inline-flex to centre their
   words in the 44 the same way. */
.jz-job .act{display:flex;gap:10px;margin-top:12px;flex-wrap:wrap;align-items:center}
.jz-job .btn-s{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;font-weight:var(--sys-w-semibold);font-size:13px;font-family:var(--sys-font);border:0;background:var(--sys-panel);box-shadow:var(--sys-shadow-btn);border-radius:var(--sys-r-pill);padding:8px 12px;min-height:var(--sys-tap);cursor:pointer;color:var(--sys-accent);white-space:nowrap;text-decoration:none;-webkit-tap-highlight-color:transparent}
/* A lockbox is free text ("Front door 4417 · Garage 9921 · Gate #5521"). On one
   line it ran 62px past the card at 320 and 15 at 393, the end of the code off the
   screen where nothing scrolls to it (review of 2026-10-06). It wraps inside the
   card instead, left-aligned like a note; a short code is one line, as before. */
.jz-job .btn-s.btn-lock{color:var(--sys-muted);font-feature-settings:"tnum";max-width:100%;white-space:normal;overflow-wrap:anywhere;text-align:left}
.jz-job .btn-s.btn-lock.copied{color:var(--sys-green)}
.jz-job .btn-p{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;font-weight:var(--sys-w-semibold);font-size:13px;font-family:var(--sys-font);border:none;background:var(--sys-accent);color:#fff;border-radius:var(--sys-r-pill);padding:8px 16px;min-height:var(--sys-tap);cursor:pointer;margin-left:auto;-webkit-tap-highlight-color:transparent}
.jz-job .btn-s:active,.jz-job .btn-p:active{transform:scale(.97)}
/* 375px-class phones: the TEXT gets tighter, the target does not. */
@media (max-width:385px){
  .jz-job .act{gap:8px}
  .jz-job .btn-s{font-size:12px;padding:8px 10px}
  .jz-job .btn-p{padding:8px 13px}
}
/* 2026-09-17 (W46): "No lockbox" was --sys-faint text, 1.68:1 on white — a token
   meant for borders and disabled states, on words the crew has to read at the door.
   The faint stays on the border, where it belongs; the words are muted (5.99:1). */
.jz-lock--none{border-style:solid;border-color:var(--sys-faint);color:var(--sys-muted);font-weight:var(--sys-w-medium)}
/* "I worked here": the accent, like every primary button. */
.jz-work{margin-left:auto;border:0;background:var(--jz-blue);color:#fff;font:inherit;font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);border-radius:var(--sys-r-pill);padding:0 14px;min-height:44px}
.jz-empty{text-align:center;color:var(--jz-gray);font-size:var(--sys-t-lead);padding:34px 20px}
/* (The Jobs hub no longer touches .nav at all: the pill is painted once, in
   system.css, and measures the same on every tab.) */

/* (The "Forest Glass" block that used to be here — a gradient ground, translucent
   blurred cards with !important, a repaint of .nav and a green active tab — is
   gone. The ground is --sys-page, cards are opaque white with the hairline
   shadow, the nav is system.css's, and green is a status colour only.) */

/* ---- Collaboration (optional): assignments + notes thread ---- */
/* (Her own jobs had a 2px blue edge until 2026-10-06; the card names who is on it
   now, as Mario's does, and his has no ring — jzCard.) */
/* (Today's house was a blue card until 2026-10-06; it is a white card like the rest
   now, as in Mario's list, and its next-step line says "today".) */
.jz-property-banner { margin: 6px 0 0; padding: 8px 12px; border: 0; border-radius: var(--sys-r-control); background: var(--gold-soft); color: var(--gold); font-size: var(--sys-t-body); font-weight: var(--sys-w-semibold); line-height: 1.35; }
.jz-property-banner.detail { margin: 0 0 12px; font-size: var(--sys-t-lead); }
.collab-roles { display: grid; gap: 0; padding: 6px 14px; }
.collab-role-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 9px 0; }
.collab-role-row + .collab-role-row { border-top: 1px solid var(--line); }
.collab-role-name { font-size: var(--sys-t-body); font-weight: var(--sys-w-medium); color: var(--muted); text-transform: none; letter-spacing: 0; min-width: 104px; }
.collab-role-chips { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.collab-pill { display: inline-flex; align-items: center; gap: 4px; }
.collab-pill button { border: 0; background: none; color: inherit; font-size: 13px; line-height: 1; padding: 0 1px; cursor: pointer; opacity: .6; }
/* 2026-09-17: the remove × was a 10x13 target. `.room-card span { display: block }`
   (the info-card label rule) outranks the two rules above, so the chips stacked
   flush on a 28px pitch and a thumb aimed at a name landed on the × beside it.
   Scoped one class deeper to win: the chips sit inline beside Leave / I'm in as
   first drawn, each name is a 44pt pill, and its × is the full height of the pill
   and 44 wide — no expander, so a × never reaches into the next chip. */
.collab-roles .collab-role-chips { display: flex; }
.collab-roles .collab-pill { display: inline-flex; align-items: center; min-height: 44px; padding-right: 0; }
.collab-roles .collab-pill button { align-self: stretch; min-width: 44px; font-size: 17px; }
/* Her own chip has no × (Leave is beside it, UI-069), so it keeps the pill's own right padding. */
.collab-roles .collab-pill.self { padding-right: 10px; }
.collab-join { display: inline-flex; align-items: center; border: 1px dashed var(--sys-faint); border-radius: var(--sys-r-pill); background: transparent; color: var(--blue); font-size: var(--sys-t-body); font-weight: var(--sys-w-semibold); padding: 0 11px; cursor: pointer; min-height: 44px; }
.collab-join.leave { color: var(--muted); }
/* "＋ Assign" (2026-10-12): his picker on her roles, in Join's clothes. The list it
   turns into (.collab-add-select) is dressed by team-roster.js, the same in both apps. */
.collab-roles .collab-add-select { flex: 0 1 auto; min-width: 0; }
/* "Crew hours here" (2026-10-12): his Team tab card — a person, their hours, and
   how many entries. Spans are inline here: .room-card span is the info card's
   stacked label. */
.crew-hours { display: grid; gap: 0; padding: 6px 14px; }
.crew-hours .crew-hours-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 10px 0; color: var(--sys-ink); font-size: var(--sys-t-lead); }
.crew-hours .crew-hours-row + .crew-hours-row { border-top: 1px solid var(--line); }
.crew-hours .crew-hours-row span { display: inline; min-width: 0; color: inherit; font-size: inherit; font-weight: var(--sys-w-medium); overflow-wrap: anywhere; }
.crew-hours .crew-hours-row span + span { flex: none; color: var(--muted); font-size: var(--sys-t-body); font-weight: var(--sys-w-regular, 400); font-variant-numeric: tabular-nums; white-space: nowrap; }
.crew-hours .crew-hours-empty { padding: 8px 0; color: var(--muted); font-size: var(--sys-t-body); }
/* MORE › TEAM (2026-10-12): his Team page's grid, dressed by team-grid.js; the
   screen's own padding is the page edge, so the first row sits flush under the title. */
.crew-team-page .tg-tools:first-child { margin-top: 0; }
.crew-team-page .empty[hidden] { display: none; }
/* MORE › ACTIVITY (2026-10-12): his Activity lines (manager-alerts-auth-fix.js
   activityCardHtml), in his Bento clothes (bento.css 13b) on her tokens. */
.crew-activity .manager-notification-list { display: grid; gap: 8px; }
.crew-activity .manager-notification-list:empty { display: none; }
.crew-activity .manager-notification-card { display: flex; gap: 12px; align-items: flex-start; min-width: 0; padding: 13px 16px; border: 0; border-radius: var(--sys-r-card); background: var(--surface); box-shadow: var(--shadow); }
.crew-activity .manager-notification-card > div { min-width: 0; }
.crew-activity .manager-notification-icon { width: 34px; height: 34px; flex: none; display: grid; place-items: center; border-radius: var(--sys-r-control); background: var(--sys-fill-2); color: var(--sys-ink); }
.crew-activity .manager-notification-card strong { display: block; color: var(--sys-ink); font-size: var(--sys-t-lead); font-weight: var(--sys-w-semibold); }
.crew-activity .manager-notification-card p { margin: 2px 0 0; color: var(--muted); font-size: var(--sys-t-body); line-height: 1.45; overflow-wrap: anywhere; }
.crew-activity .manager-notification-card small { display: block; margin-top: 4px; color: var(--muted); font-size: var(--sys-t-caption); }
.crew-activity .manager-notification-card.house .manager-notification-icon { background: var(--sys-green-soft); color: var(--sys-green); }
.crew-activity .manager-notification-card.warning .manager-notification-icon { background: var(--sys-orange-soft); color: var(--sys-orange); }
.crew-activity .manager-notification-card.failed .manager-notification-icon { background: var(--sys-red-soft); color: var(--sys-red-ink); }
.crew-activity .manager-notification-card.texts .manager-notification-icon,
.crew-activity .manager-notification-card.labor .manager-notification-icon { background: var(--sys-accent-soft); color: var(--sys-accent); }
.crew-activity .manager-notification-card.login .manager-notification-icon { background: var(--sys-purple-soft); color: var(--sys-purple-ink, #8E3DB8); }
/* Something new on Activity: a dot on More (his is on the Activity tab) and on the row. */
.field-app .nav button .nav-dot { position: absolute; top: 4px; right: calc(50% - 15px); width: 7px; height: 7px; border-radius: 50%; background: var(--sys-red); }
.instruction-card .crew-unread-dot { display: inline-block; width: 8px; height: 8px; margin-left: 8px; border-radius: 50%; background: var(--sys-red); vertical-align: middle; }
.collab-thread { display: grid; gap: 8px; }
/* 16px for the same reason as .jz-search input: under 16px iOS zooms the page
   in on focus and does not zoom back out. */
.collab-compose textarea { width: 100%; box-sizing: border-box; border: 0; border-radius: var(--sys-r-control); background: var(--sys-fill); padding: 10px 12px; font: inherit; font-size: 16px; min-height: 58px; resize: vertical; }
.collab-compose-row { display: flex; align-items: center; gap: 6px; margin-top: 7px; flex-wrap: wrap; }
/* min-width since "📌 Pin" became "Pin" (2026-10-04, T150): the word alone painted
   43.4 wide, under the 44pt floor its height already keeps. */
.collab-flag { display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: var(--sys-r-pill); background: var(--surface-2); color: var(--muted); font-size: var(--sys-t-body); font-weight: var(--sys-w-medium); padding: 0 12px; cursor: pointer; min-height: 44px; min-width: var(--sys-tap, 44px); }
.collab-flag.on { background: var(--blue); color: #fff; }
.collab-flag.warn.on { background: var(--gold); }
.collab-send { display: inline-flex; align-items: center; margin-left: auto; border: 0; border-radius: var(--sys-r-pill); background: var(--blue); color: #fff; font-size: var(--sys-t-lead); font-weight: var(--sys-w-semibold); padding: 0 18px; cursor: pointer; min-height: 44px; }
.collab-note { border: 0; border-radius: var(--sys-r-control); background: var(--sys-fill); padding: 9px 12px; }
.collab-note.property { background: var(--gold-soft); }
.collab-note.pinned { box-shadow: inset 0 0 0 1px var(--sys-faint); }
.collab-note-meta { margin: 0 0 3px; display: flex; align-items: center; gap: 7px; font-size: var(--sys-t-small); color: var(--muted); }
.collab-note-meta strong { color: var(--ink); font-size: var(--sys-t-body); }
.collab-note-meta button { margin-left: auto; border: 0; background: none; color: var(--blue); font-size: var(--sys-t-body); font-weight: var(--sys-w-medium); cursor: pointer; }
/* Edit was an 18px-tall link (UI-189): the finger gets 44pt from an expander, so the
   meta line itself keeps its height. */
.collab-note-meta button { position: relative; }
/* 44pt reach on any font: the word is 17-18px tall depending on the platform, so the
   invisible reach is 14px above and below, never 13. */
.collab-note-meta button::after { content: ""; position: absolute; inset: -14px -12px; }
/* Delete on every note (2026-10-12), red like his. Beside Edit it keeps a gap wider
   than the two expanders (12px each), so a thumb on one never lands on the other. */
.collab-note-meta .collab-note-del { color: var(--sys-red-ink, #b3261e); }
.collab-note-meta button + .collab-note-del { margin-left: 20px; }
.collab-note .collab-compose { margin-top: 4px; }
.collab-note .collab-compose textarea { background: var(--sys-panel); }
.collab-note-text { margin: 0; font-size: var(--sys-t-lead); line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }

/* ================= The open iPhone Duo: two panes (system.css: 600px, --sys-pane-w) =================
   Houses → job. employee-field-app.js wraps the Houses hub in .duo-list and draws
   the job's .app-shell beside it, and puts .duo-split on #app while both are up.
   The list is its own scroller the height of the glass; the job scrolls with the
   page as it always has. One nav: the list's, where the nav always is; the job's
   own copy is hidden. This replaced the min-width:760px branch that spread
   the crew app over a desktop as a card grid. */
@media (min-width: 600px) {
  /* Every crew screen uses the whole display here, not only Houses → job: Home,
     Pay, More and the calendar were a 430px column centred in 585 (2026-10-25). */
  .field-app { width: 100%; }
  .field-app.duo-split {
    width: 100%;
    max-width: none;
    display: flex;
    align-items: flex-start;
  }
  .field-app.duo-split > .duo-list {
    flex: none;
    width: var(--sys-pane-w);
    position: sticky;
    top: 0;
    height: 100dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    border-right: 1px solid var(--line);
  }
  /* The list's header is the hub's: title, calendar, +, Mine | All. In 260px the
     toggle drops to its own line rather than running off the pane. */
  .field-app.duo-split > .duo-list .jz-head-row,
  .field-app.duo-split > .duo-list .jz-head-right { flex-wrap: wrap; }
  /* The nav keeps its place on the glass: five buttons do not fit a 236px pill
     under the list, and the job clears the nav at its foot as it always has. */
  .field-app.duo-split > .app-shell { flex: 1; min-width: 0; }
  .field-app.duo-split > .app-shell > .nav { display: none; }
  /* The job that is open, marked in the list. */
  .field-app.duo-split > .duo-list .jz-card.duo-on { outline: 2px solid var(--jz-blue); outline-offset: -2px; }
  /* Seven tabs need ~342px and the job pane gives the strip 289: it scrolls, as it
     does under 375 on a phone (the .tight block below, repeated here for the pane).
     Without this the strip ran 35px past the pane, under the status column. */
  .field-app.duo-split > .app-shell .os2c-tabs.tight { min-width: 0; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; }
  .field-app.duo-split > .app-shell .os2c-tabs.tight::-webkit-scrollbar { display: none; }
  .field-app.duo-split > .app-shell .os2c-tabs.tight button { flex-shrink: 0; }
}

/* Optional staging time chip on the job card (useful when two houses stage the
   same day — the crew sees the order/time). */
.jz-time {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: auto;
  border-radius: var(--sys-r-pill);
  background: var(--blue-soft);
  color: var(--blue);
  font: inherit;
  font-size: var(--sys-t-caption);
  font-weight: var(--sys-w-semibold);
  font-feature-settings: "tnum";
  padding: 4px 9px;
  white-space: nowrap;
}

/* ---- Prep pipeline on a crew card -----------------------------------------
   The component ships its own CSS (prep-pipeline.js); this only retints it to the
   jz- scale so it belongs to this app, and lets the card grow past its 120px floor
   for Upcoming jobs. The "Forest Glass" rule paints .jz-card with an !important
   translucent background, so the roles chips use a solid tint that survives it. */
.jz-card .prep {
  --pp-ink: var(--jz-ink);
  --pp-muted: var(--jz-gray);
  --pp-line: var(--jz-line);
  --pp-amber: var(--jz-amber);
  --pp-amber-soft: var(--jz-amber-bg);
  --pp-blue: var(--jz-blue);
  --pp-blue-soft: var(--jz-blue-bg);
  --pp-purple: var(--sys-purple);
  --pp-purple-soft: var(--sys-purple-soft);
}
.jz-card .prep-role { background: var(--sys-fill); }

/* ---- House Sheet (crew mirror of the manager detail redesign) ---- */
.jd-alerts{display:flex;gap:6px;flex-wrap:wrap;margin:0 14px 10px}
.jd-al{font-size:var(--sys-t-caption);font-weight:var(--sys-w-semibold);border-radius:var(--sys-r-pill);padding:4px 9px;color:var(--gold);background:var(--gold-soft)}
.jd-al.info{color:var(--blue);background:var(--blue-soft)}
.jd-tl{background:var(--surface);border-radius:var(--sys-r-card);padding:13px 16px 11px;margin:0 14px 10px;box-shadow:var(--shadow)}
.jd-tl .t-cap{display:flex;justify-content:space-between;align-items:baseline}
.jd-tl .t-cap .t-t{font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);letter-spacing:0;text-transform:none;color:var(--muted)}
.jd-tl .t-cap .t-d{font-size:var(--sys-t-body);font-weight:var(--sys-w-medium);color:var(--blue);font-variant-numeric:tabular-nums}
/* The progress bar: the track, an accent fill; orange when the job is behind. */
.jd-tl .t-bar{position:relative;height:4px;border-radius:var(--sys-r-pill);background:var(--sys-track);margin:11px 2px 9px}
.jd-tl .t-fill{position:absolute;left:0;top:0;bottom:0;border-radius:var(--sys-r-pill);background:var(--blue)}
.jd-tl.warn .t-fill{background:var(--gold)}
.jd-tl .t-dot{position:absolute;top:50%;width:12px;height:12px;border-radius:50%;background:var(--blue);border:2.5px solid var(--surface);transform:translate(-50%,-50%);box-shadow:0 1px 4px rgba(0,0,0,.25)}
.jd-tl.warn .t-dot{background:var(--gold)}
.jd-tl .t-row{display:flex;justify-content:space-between;gap:6px}
.jd-tl .t-col{text-align:center;font-size:var(--sys-t-small);color:var(--muted)}
.jd-tl .t-col:first-child{text-align:left}
.jd-tl .t-col:last-child{text-align:right}
.jd-tl .t-col b{display:block;font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);color:var(--ink);font-variant-numeric:tabular-nums}
.jd-facts{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:0 14px 10px}
.jd-fact{background:var(--surface);border-radius:var(--sys-r-card);padding:12px 16px;box-shadow:var(--shadow)}
.jd-fact.wide{grid-column:1/-1}
.jd-fact .f-l{display:block;font-size:var(--sys-t-body);font-weight:var(--sys-w-medium);letter-spacing:0;text-transform:none;color:var(--muted);margin-bottom:7px}
.jd-fact .f-empty{font-size:var(--sys-t-body);color:var(--gold);font-weight:var(--sys-w-semibold)}
.jd-code{display:inline-flex;align-items:center;gap:8px;background:var(--sys-fill);border:none;border-radius:var(--sys-r-control);padding:7px 12px;font-weight:var(--sys-w-bold);font-size:var(--sys-t-headline);line-height:1;letter-spacing:.12em;color:var(--ink);font-variant-numeric:tabular-nums;cursor:pointer;-webkit-tap-highlight-color:transparent;min-height:44px}
.jd-code span{font-size:var(--sys-t-caption);letter-spacing:0;color:var(--blue);font-weight:var(--sys-w-semibold)}
.jd-contact{display:flex;align-items:center;gap:10px}
.jd-who{flex:1;min-width:0}
.jd-who b{display:block;font-size:var(--sys-t-lead);font-weight:var(--sys-w-semibold);color:var(--ink);letter-spacing:-.01em}
.jd-who span{font-size:var(--sys-t-body);color:var(--muted)}
.jd-cbtns{display:flex;gap:7px}
/* 44, not 34: Call / Text are tap targets, and the ground rule is 44. */
.jd-cbtn{width:44px;height:44px;border-radius:50%;background:var(--sys-fill);color:var(--blue);display:flex;align-items:center;justify-content:center;font-size:15px;text-decoration:none}

/* ---- House OS (crew): atmosphere hero + big number + boarding pass ---- */
/* Flat status tints, no gradients: the accent's soft tint for an upcoming job,
   green (a status) for one that is staged, orange for a pickup on the calendar. */
.os-hero{border-radius:var(--sys-r-card);padding:18px 16px 16px;text-align:center;margin:0 14px 10px;position:relative;overflow:hidden}
.os-hero.k-upcoming{background:var(--blue-soft)}
.os-hero.k-active{background:var(--green-soft)}
.os-hero.k-scheduled{background:var(--gold-soft)}
/* A finished job (on the crew's phone the week after its pickup): the grey of its
   Completed chip and pill, as the manager's ticket (k-past). */
.os-hero.k-past{background:var(--sys-fill-2)}
.os-cap{display:inline-block;font-size:var(--sys-t-caption);font-weight:var(--sys-w-semibold);letter-spacing:0;text-transform:none;padding:4px 9px;border-radius:var(--sys-r-pill);background:var(--surface);color:var(--muted)}
.os-big{margin-top:11px;line-height:.95}
/* A number: bold, tight, tabular (Tokens board). */
.os-big b{font-size:48px;font-weight:var(--sys-w-bold);letter-spacing:-.03em;color:var(--ink);font-variant-numeric:tabular-nums}
.os-big span{display:block;font-size:var(--sys-t-body);font-weight:var(--sys-w-medium);letter-spacing:0;text-transform:none;color:var(--muted);margin-top:6px}
.os-frase{margin-top:9px;font-size:var(--sys-t-body);color:var(--muted)}
.os-frase b{color:var(--ink);font-weight:var(--sys-w-semibold)}
.os-pass{margin-top:12px;background:var(--surface);border-radius:var(--sys-r-card);box-shadow:var(--shadow);overflow:hidden;text-align:left}
.os-route{padding:13px 16px 11px;display:flex;align-items:center;gap:11px}
.os-pt{text-align:left}
.os-pt.r{text-align:right}
.os-pt b{display:block;font-size:var(--sys-t-headline);font-weight:var(--sys-w-semibold);letter-spacing:-.01em;color:var(--ink);font-variant-numeric:tabular-nums}
.os-pt span{font-size:var(--sys-t-caption);font-weight:var(--sys-w-medium);letter-spacing:0;text-transform:none;color:var(--muted)}
.os-pt .os-time{display:block;letter-spacing:0;text-transform:none;font-size:var(--sys-t-small);color:var(--blue);font-weight:var(--sys-w-semibold)}
.os-line{flex:1;position:relative;height:2px;background:repeating-linear-gradient(90deg,var(--sys-faint) 0 6px,transparent 6px 12px)}
.os-line i{position:absolute;top:50%;transform:translate(-50%,-56%);font-style:normal;font-size:13px}
.os-tear{border-top:2px dashed var(--line);margin:0 12px;position:relative}
.os-tear::before,.os-tear::after{content:"";position:absolute;top:-10px;width:18px;height:18px;border-radius:50%}
.os-tear::before{left:-22px}.os-tear::after{right:-22px}
.k-upcoming .os-tear::before,.k-upcoming .os-tear::after{background:var(--blue-soft)}
.k-active .os-tear::before,.k-active .os-tear::after{background:var(--green-soft)}
.k-scheduled .os-tear::before,.k-scheduled .os-tear::after{background:var(--gold-soft)}
.k-past .os-tear::before,.k-past .os-tear::after{background:var(--sys-fill-2)}
.os-codebar{display:flex;align-items:center;justify-content:space-between;padding:11px 16px 13px}
.os-cl{font-size:var(--sys-t-caption);font-weight:var(--sys-w-medium);letter-spacing:0;text-transform:none;color:var(--muted)}
.os-code{display:block;font-family:var(--sys-font-mono);font-size:23px;font-weight:var(--sys-w-bold);letter-spacing:.3em;color:var(--ink);margin-top:2px}
.os-code.add{font-family:inherit;font-size:var(--sys-t-body);letter-spacing:0;font-weight:var(--sys-w-semibold);color:var(--gold)}
/* Copy: a secondary button — white, accent text, the soft shadow. */
.os-copy{display:inline-flex;align-items:center;font-weight:var(--sys-w-semibold);font-size:var(--sys-t-body);line-height:1;border:none;padding:0 16px;min-height:44px;border-radius:var(--sys-r-pill);background:var(--surface);color:var(--blue);box-shadow:var(--sys-shadow-btn);cursor:pointer}

/* ---- Crew Day: personal "your day" home ---- */
#crewDay{padding:4px 2px 6px}
/* 2026-10-05 (Mario's approved Home): the date small and uppercase, "Hi, Jesus"
   under it as the page title, on the page itself. The tinted band the date sat on
   (.cd-sky, by time of day) is gone: on the mockup he approved there is none, and
   the colour on this screen now belongs to the four counts. The manager's ‹ (UI-029)
   still sits left of it. */
.cd-hi{display:flex;align-items:center;gap:11px;padding:4px 4px 14px}
.cd-hi > .icon-btn{flex:none}
.cd-hit{min-width:0}
.cd-hi b{display:block;font-size:var(--sys-t-large-title);font-weight:var(--sys-w-bold);line-height:1.1;letter-spacing:-.02em;color:var(--ink);overflow-wrap:anywhere}
.cd-date{display:block;margin-bottom:2px;font-size:var(--sys-t-small);font-weight:var(--sys-w-semibold);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
/* Flat tints, no gradients. */
.cd-hero{border-radius:var(--sys-r-card);background:var(--blue-soft);padding:16px;margin-bottom:10px}
.cd-cap{display:inline-block;font-size:var(--sys-t-caption);font-weight:var(--sys-w-semibold);letter-spacing:0;text-transform:none;padding:4px 9px;border-radius:var(--sys-r-pill);background:var(--surface);color:var(--blue)}
.cd-what{font-size:var(--sys-t-headline);font-weight:var(--sys-w-semibold);letter-spacing:-.01em;margin-top:11px;line-height:1.25;color:var(--ink)}
.cd-sub{font-size:var(--sys-t-body);color:var(--muted);margin-top:5px}
.cd-pass{width:100%;box-sizing:border-box;margin-top:11px;background:var(--surface);border:none;border-radius:var(--sys-r-card);box-shadow:var(--shadow);display:flex;align-items:center;justify-content:space-between;padding:10px 16px;cursor:pointer;font:inherit;text-align:left;min-height:52px}
.cd-cl{display:block;font-size:var(--sys-t-caption);font-weight:var(--sys-w-medium);letter-spacing:0;text-transform:none;color:var(--muted)}
.cd-code{display:block;font-family:var(--sys-font-mono);font-size:21px;font-weight:var(--sys-w-bold);letter-spacing:.2em;color:var(--ink);margin-top:1px}
.cd-copy{font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);padding:8px 14px;border-radius:var(--sys-r-pill);background:var(--surface-2);color:var(--blue)}
.cd-btns{display:flex;gap:8px;margin-top:10px}
/* Primary = the accent; secondary = white, accent text, the soft shadow.
   2026-09-17 (W55): 52 tall, not 44. These are the buttons pressed one-handed at
   the truck (Directions, I'm on my way, start the clock, Wrap up), and they sit
   mid-screen where a thumb reaches them least well; 44 is the floor, not the
   size for the screen's main actions. The hero grows 24px. */
.cd-b1,.cd-b2{flex:1;display:flex;align-items:center;justify-content:center;min-height:52px;text-align:center;font-weight:var(--sys-w-semibold);font-size:var(--sys-t-lead);line-height:1;padding:0 12px;border-radius:var(--sys-r-pill);border:none;cursor:pointer;text-decoration:none}
.cd-b1{background:var(--blue);color:#fff}
.cd-b2{background:var(--surface);color:var(--blue);box-shadow:var(--sys-shadow-btn)}
/* A Home strip is a STATE with an icon and a colour (Copy board): orange for
   watch / pending, red for not-saved. 15/600, the control's own corners. */
.cd-nudge{display:flex;align-items:center;gap:10px;width:100%;box-sizing:border-box;text-align:left;margin:0 0 8px;font-weight:var(--sys-w-semibold);font-size:var(--sys-t-lead);line-height:1.3;padding:10px 12px;border-radius:var(--sys-r-control);background:var(--gold-soft);color:var(--gold);border:none;cursor:pointer;min-height:44px}
.cd-nudge.red{background:var(--red-soft);color:var(--red)}
.cd-nudge-ic{width:18px;height:18px;flex:none;display:block}
.cd-nudge span{margin-left:auto;opacity:.6}
.cd-nudge.soft{cursor:default}
/* HOME AS A SUMMARY (2026-10-05, Mario's approved mockup). The list of every
   address coming up is gone from Home — he could not tell one from another in it —
   and these say what he asked for instead: this week's pay, how many houses are in
   each state, and her one next job. White cards on the page, the soft tints only on
   the four counts, every tap at least --sys-tap. */
.cd-pay{width:100%;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:var(--sys-tap);padding:14px 16px;border:0;border-radius:var(--sys-r-card);background:var(--surface);box-shadow:var(--shadow);color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.cd-pay-m{display:block;min-width:0}
.cd-pay-l{display:block;font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);color:var(--muted)}
.cd-pay-n{display:block;margin-top:1px;font-size:var(--sys-t-large-title);font-weight:var(--sys-w-bold);line-height:1.1;letter-spacing:-.02em;color:var(--ink);font-variant-numeric:tabular-nums}
.cd-pay-s{display:block;margin-top:2px;font-size:var(--sys-t-body-lg);color:var(--muted);font-variant-numeric:tabular-nums}
.cd-chev{flex:none;font-size:22px;line-height:1;color:var(--sys-faint)}
/* "HOUSES": a section label, as the offline list's heading is set. */
.cd-sec{margin:20px 4px 8px;font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);line-height:1.2;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.cd-tiles{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px}
.cd-tile{display:flex;flex-direction:column;justify-content:space-between;align-items:flex-start;gap:8px;min-width:0;min-height:92px;box-sizing:border-box;padding:13px 14px;border:0;border-radius:var(--sys-r-card);font:inherit;text-align:left;cursor:pointer}
.cd-tile b{font-size:var(--sys-t-large-title);font-weight:var(--sys-w-bold);line-height:1;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.cd-tile span{font-size:var(--sys-t-lead);font-weight:var(--sys-w-semibold);line-height:1.2}
/* Each state in the colour the app already gives it: Staged green (a state, and green
   is for state), Upcoming the accent, and — since the Houses card became Mario's
   (2026-10-06) — his pill's colours for the other two: Destaging soon orange, Waiting
   purple. The tiles had the old card's (purple Pick up, orange Waiting), so a tap on
   the orange "Waiting" opened a list of purple Waiting pills and the purple
   "Destaging soon" a list of orange ones (review of 2026-10-06). Purple as words is
   --sys-purple-ink, never --sys-purple. */
.cd-tile.st{background:var(--green-soft);color:var(--green)}
.cd-tile.up{background:var(--blue-soft);color:var(--blue)}
.cd-tile.pk{background:var(--gold-soft);color:var(--gold)}
.cd-tile.wt{background:var(--sys-purple-soft);color:var(--sys-purple-ink, #8944AB)}
/* HIS CALENDAR TILE (2026-10-12; bento-shell.js [data-tile="calendar"]): under the
   counts, a white card like This week, the word and this week and next as two rows
   of seven, a staging green, a pickup orange, a preview blue, today ringed — his
   .bt-minical's colours. The whole card is the one button. */
.cd-cal{display:block;width:100%;box-sizing:border-box;margin-top:12px;min-height:var(--sys-tap);padding:12px 16px 14px;border:0;border-radius:var(--sys-r-card);background:var(--surface);box-shadow:var(--shadow);color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.cd-cal-h{display:flex;align-items:center;gap:8px}
.cd-cal-h b{flex:1;min-width:0;font-size:var(--sys-t-lead);font-weight:var(--sys-w-semibold)}
.cd-cal-ic{display:grid;place-items:center;width:28px;height:28px;border-radius:8px;background:var(--sys-orange-soft);color:var(--sys-orange)}
.cd-minical{display:grid;grid-template-columns:repeat(7,1fr);gap:3px;margin-top:10px}
.cd-minical i{display:block;height:14px;border-radius:4px;background:var(--sys-fill-2)}
.cd-minical i.ev-g{background:var(--sys-green)}
.cd-minical i.ev-a{background:var(--sys-orange)}
.cd-minical i.ev-b{background:var(--sys-blue)}
.cd-minical i.today{outline:1.5px solid var(--sys-accent);outline-offset:1px;background:var(--sys-panel)}
/* Her next job, small: the day and what it is over the street, Directions beside. */
.cd-next{display:flex;align-items:center;gap:12px;margin-top:12px;padding:12px 12px 12px 16px;border-radius:var(--sys-r-card);background:var(--surface);box-shadow:var(--shadow);cursor:pointer}
.cd-next-m{display:block;flex:1;min-width:0}
.cd-next-w{display:block;font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);line-height:1.3;color:var(--muted)}
.cd-next-a{display:block;margin-top:2px;font-size:var(--sys-t-headline);font-weight:var(--sys-w-semibold);line-height:1.25;letter-spacing:-.01em;color:var(--ink);overflow-wrap:anywhere}
.cd-dir{flex:none;display:inline-flex;align-items:center;justify-content:center;min-height:var(--sys-tap);padding:0 16px;border-radius:var(--sys-r-pill);background:var(--blue);color:#fff;font-size:var(--sys-t-lead);font-weight:var(--sys-w-semibold);line-height:1;text-decoration:none}
/* The running clock's card (a clock started before 2026-10-04) stands where the next
   job's would; the hours come after either. */
.cd-tiles + .cd-hero{margin-top:12px}
#crewDay > .mv-stack,#crewDay > .submit-hours-card{margin-top:12px}
/* On Home, Submit Hours is the button alone (approved mockup): the white card round
   it was one more box on a screen that is now cards and tiles. Same button, same tap. */
#crewDay > .submit-hours-card{padding:0;background:none;box-shadow:none}
/* Blue stages a house, purple picks it up — the same two colours the Weekly report
   uses for the same two things. --sys-purple-ink, never --sys-purple: this is text. */
.cd-k{font-weight:var(--sys-w-semibold)}
.cd-k.st{color:var(--blue)}
.cd-k.pk{color:var(--sys-purple-ink, #8944AB)}
/* (.th-slim, the empty board's one-row composer, is drawn in team-home.css now —
   the board is one component in both apps, and its rule lived only here, so the
   manager's copy of the same button had no style at all. 2026-09-30.) */

/* ---- Crew Day ULTRA: ring, leave-by pill, session ----
   (The time-of-day band over the date went on 2026-10-05; see .cd-hi.) */
.cd-ring{position:relative;width:46px;height:46px;flex:none;display:block}
.cd-ring b{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:var(--sys-t-caption);font-weight:var(--sys-w-bold);font-variant-numeric:tabular-nums}
/* The "on site" / "leave by" pill is the ink pill — the toast vocabulary. */
.cd-pill{display:flex;align-items:center;gap:8px;margin:0 2px 10px;background:var(--ink);color:#fff;border-radius:var(--sys-r-pill);padding:10px 15px;min-height:44px;font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);box-shadow:var(--sys-shadow-sheet)}
.cd-pill-t{flex:1;min-width:0;line-height:1.3}
.cd-pill i{font-style:normal;color:rgba(255,255,255,.6);margin-left:auto;font-weight:var(--sys-w-medium);font-size:var(--sys-t-caption);white-space:nowrap}
.cd-dot{width:7px;height:7px;border-radius:50%;background:var(--blue);flex:none;animation:cdpl 1.6s infinite}
.cd-pill.on .cd-dot{background:var(--green)}
@keyframes cdpl{0%,100%{opacity:1}50%{opacity:.35}}
.cd-start{width:100%;margin-top:9px;min-height:52px;font-weight:var(--sys-w-semibold);font-size:var(--sys-t-lead);line-height:1;padding:12px 0;border-radius:var(--sys-r-pill);border:1.5px dashed var(--blue);background:transparent;color:var(--blue);cursor:pointer}
.cd-hero.live{background:var(--green-soft)}
.cd-hero.live .cd-cap.ok{color:var(--green)}
.cd-timer{font-size:44px;font-weight:var(--sys-w-bold);letter-spacing:-.03em;margin-top:6px;line-height:1;font-variant-numeric:tabular-nums;color:var(--ink)}
.cd-timer small{font-size:var(--sys-t-lead);font-weight:var(--sys-w-semibold);color:var(--green)}
/* "Wrap up" is a button, so it is the accent — green is a status, never a button. */
.cd-hero.live .cd-b1.ok,.cd-b1.ok{background:var(--blue);color:#fff;border:none;cursor:pointer;font-weight:var(--sys-w-semibold);font-size:var(--sys-t-lead);line-height:1;padding:0 12px;min-height:52px;border-radius:var(--sys-r-pill);flex:1;text-align:center}
/* 2026-09-17 (W76): the "on the clock" dot pulsed for as long as the screen was
   open, with Reduce Motion on too. Under it it holds still at full colour and the
   pill's words still say the clock is running. (The you-are-here stop it used to
   name went with the Today route, 2026-09-21.) */
@media (prefers-reduced-motion: reduce){.cd-dot{animation:none}}

/* (Crew Day's coloured time buckets went with the buckets themselves, 2026-09-21 —
   Today / Tomorrow / This week / Next week are one list now, and the two colours
   that remain are on the words Stage and Pick up. See .cd-list above.) */

/* ---- 2026-09-18: the mover's hours card (Home, movers only) ----
   Mario's approved mockup, screen 1: one card to log a line — day, hours, rate,
   note — then that day's lines and the week, Monday to Sunday. White cards on the
   page, the system fill for the fields, the accent for the one button, green only
   for a status (Paid). Every field is 16px or more (under 16, iOS zooms the page
   in and stays there) and every control is 44pt or more to a thumb. Everything is
   prefixed mv- so nothing here can land on a rule that already exists. */
.mv-stack,.mv-lists{display:flex;flex-direction:column;gap:10px}
.mv-stack{margin:0 0 10px}
.mv-card{background:var(--surface);border-radius:var(--sys-r-card);box-shadow:var(--shadow);padding:14px;display:flex;flex-direction:column;gap:10px;min-width:0}
.mv-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.mv-head h2{margin:0;font-size:var(--sys-t-headline);font-weight:var(--sys-w-semibold);letter-spacing:-.01em;line-height:1.25;color:var(--ink)}
.mv-chip{display:inline-flex;align-items:center;padding:4px 9px;border-radius:var(--sys-r-pill);background:var(--blue-soft);color:var(--blue);font-size:var(--sys-t-caption);font-weight:var(--sys-w-semibold);white-space:nowrap}
.mv-form{display:flex;flex-direction:column;gap:8px;margin:0}
.mv-label{font-size:var(--sys-t-caption);font-weight:var(--sys-w-semibold);line-height:1.2;color:var(--muted)}
/* The day reads "Today · Wed, Sep 9 ›"; the real date input lies over it, clear, so
   the tap opens the phone's own picker. Its ring is drawn on the row it covers. */
.mv-day{position:relative;display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:var(--sys-tap, 44px);padding:0 14px;border-radius:var(--sys-r-control);background:var(--sys-fill);color:var(--ink);font-size:var(--sys-t-field);font-weight:var(--sys-w-medium);cursor:pointer}
.mv-day:focus-within{box-shadow:0 0 0 2px var(--blue)}
.mv-chev{color:var(--muted)}
.mv-day .mv-day-input{position:absolute;inset:0;width:100%;height:100%;min-height:0;margin:0;padding:0;border-radius:inherit;opacity:0;cursor:pointer;box-shadow:none}
.mv-two{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:8px}
.mv-cell{display:flex;flex-direction:column;gap:6px;min-width:0}
.mv-big{min-height:64px;padding:0 14px;font-size:30px;font-weight:var(--sys-w-bold);letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.mv-money{position:relative;display:block}
.mv-money i{position:absolute;left:14px;top:50%;transform:translateY(-50%);font-style:normal;font-size:30px;font-weight:var(--sys-w-bold);line-height:1;color:var(--muted);pointer-events:none}
.mv-money .mv-big{padding-left:36px}
.mv-hint{margin:0;font-size:var(--sys-t-small);line-height:1.4;color:var(--muted)}
.mv-save{min-height:52px;padding:12px 16px;border:0;border-radius:var(--sys-r-pill);background:var(--blue);color:#fff;font-size:var(--sys-t-lead);font-weight:var(--sys-w-semibold);line-height:1.2;font-variant-numeric:tabular-nums}
.mv-save:disabled{opacity:.6}
.mv-row{display:flex;align-items:baseline;justify-content:space-between;gap:10px;min-width:0}
.mv-row > span:first-child{min-width:0;overflow-wrap:anywhere}
.mv-top b{font-weight:var(--sys-w-semibold);color:var(--ink)}
.mv-num{flex:none;white-space:nowrap;font-variant-numeric:tabular-nums;color:var(--muted)}
.mv-num b{color:var(--ink)}
.mv-list{display:flex;flex-direction:column}
.mv-entry{padding:10px 0;border-top:1px solid var(--line)}
.mv-entry:first-child{padding-top:0;border-top:0}
.mv-entry .mv-row{font-size:var(--sys-t-lead);color:var(--ink)}
/* Status (and note) on the left, Fix / Delete on the right of the same line: two
   lines an entry, not three, so a day with four entries still fits on the glass. */
.mv-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:2px}
.mv-entry .he-actions{flex:none;margin-top:0}
.mv-meta{display:flex;flex-wrap:wrap;gap:4px 8px;min-width:0;font-size:var(--sys-t-small);line-height:1.35;color:var(--muted)}
.mv-st{font-weight:var(--sys-w-semibold)}
.mv-st.sub,.mv-st.wait{color:var(--gold)}
.mv-st.ok{color:var(--blue)}
.mv-st.paid{color:var(--green)}
.mv-note-tx{overflow-wrap:anywhere}
.mv-empty{margin:0;font-size:var(--sys-t-body);color:var(--muted)}
/* Seven days across the card. The strip reaches into the card's padding so each
   day is ~45pt wide on a 375pt phone; 52pt tall. */
.mv-days{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:3px;margin:0 -8px}
.mv-dcell{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;min-height:52px;padding:6px 0;border:0;border-radius:var(--sys-r-control);background:var(--sys-fill);color:var(--ink);line-height:1.1}
.mv-dcell span{font-size:var(--sys-t-caption);font-weight:var(--sys-w-medium);color:var(--muted)}
.mv-dcell b{font-size:var(--sys-t-lead);font-weight:var(--sys-w-semibold);font-variant-numeric:tabular-nums}
.mv-dcell.today{box-shadow:inset 0 0 0 2px var(--blue)}
.mv-dcell.on{background:var(--blue-soft)}
.mv-dcell.on b{color:var(--blue)}
.mv-dcell:disabled{opacity:.45;cursor:default}

/* Clear "Back" pill on detail screens (was a bare caret): white, no border,
   the hairline shadow, the accent for the glyph and the word. */
.app-shell .icon-btn[data-action="back"]{display:inline-flex;align-items:center;gap:4px;width:auto;padding:7px 14px 7px 10px;border-radius:var(--sys-r-pill);background:var(--surface);border:0;box-shadow:var(--sys-shadow-card);font-size:18px;color:var(--blue)}
.app-shell .icon-btn[data-action="back"]::after{content:"Back";font-size:var(--sys-t-lead);font-weight:var(--sys-w-medium);letter-spacing:-.01em}

/* A <button> now, not an <a href> at the storage URL — reset to look identical. */
#cmViewer .cm-slide--vid{flex-direction:column;gap:10px}
#cmViewer .cm-slide--vid video{max-height:72vh;width:100%;background:#000}
/* 2026-09-21: the one line that explains a video that will not play out here. Amber,
   not red: the file is fine and it plays on Wi-Fi, so this is a condition, not a fault.
   Wraps to two lines on a small phone rather than being cut. */

/* ============================================================
   HOUSE OS 2.0 (crew) — the four-tab job detail
   Overview | Work | Team | Media (employee-field-app.js detailScreen).
   Mirrors the manager's House OS 2.0 (bento.css "HOUSE OS 2.0" section);
   the styles are copied here because the crew pages load
   employee-field-app.css, not bento.css.
   ============================================================ */

/* ---- head: code chip + status chips + tappable address ---- */
.os2c-head-top{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.os2c-addr{margin:7px 0 0;font-size:var(--sys-t-display);font-weight:var(--sys-w-bold);line-height:1.1;letter-spacing:-.02em}
/* the address IS the maps button — but a 2-line underline reads as noise, so the
   manager look wins: plain heavy type, his address sheet on tap (2026-10-12) */
.os2c-addr .address-button{color:inherit;font:inherit;font-weight:700;text-align:left;text-decoration:none}

/* ---- sticky segmented control (the manager's #os2Tabs, contract section 2) ---- */
/* The contract's track is rgba(118,118,128,.12); composited over the page ground
   (#F5F5F7) that is #E6E6E9 — one unit off --sys-track (#E5E5EA), which is what
   is written here, because this bar is STICKY over the list and qa:touch-targets
   refuses a translucent value on it in any rule: at 94% over an 85% ring the rows
   slid visibly through it and a room's "Add a piece" field, sitting underneath,
   hit-tested to the tab bar. Same colour, opaque. The ring is the page ground. */
.os2c-tabs{position:sticky;top:calc(6px + var(--sys-safe-t));z-index:var(--sys-z-raised,26);display:flex;gap:2px;background:var(--sys-track,#E5E5EA);border-radius:var(--sys-r-segment-outer,10px);padding:2px;box-shadow:0 0 0 6px var(--bg,#F5F5F7)}
/* 2026-09-17: while the iOS shell has already put the page below the status bar
   (html.ni-top, set live by native-inset.js), env() here paid the notch a second
   time: the stuck tabs hung at 68 and covered the top of the pull sheet's Undo strip
   (W69, stuck at 64 under the same class). At 6 they end above it. The browser and
   the PWA never get the class, so env() stays theirs. */
html.ni-top .os2c-tabs{top:6px}
/* 44 tall, like every segment in this app (system.css .sys-seg): the contract's
   8px padding alone gives 31, and a segment is a tap target. */
.os2c-tabs button{flex:1;min-height:var(--sys-tap,44px);border:0;background:transparent;border-radius:var(--sys-r-segment,8px);padding:8px 0;font-weight:var(--sys-w-medium);font-size:var(--sys-t-body);line-height:1;color:var(--ink);cursor:pointer;-webkit-tap-highlight-color:transparent;position:relative}
.os2c-tabs button.on{background:var(--surface);color:var(--ink);font-weight:var(--sys-w-semibold);box-shadow:var(--sys-shadow-segment)}
/* SIX TABS (2026-09-30). The strip was built for five; Items made six when the
   inventory came to the crew app, and at 393px "Overview" filled its 58px share
   edge to edge — the word touched both sides of its own pill. The manager's strip
   met the same sixth tab and tightens its type (bento.css, #os2Tabs.sys-seg-tight);
   this is the same type, and one thing more, because at 12px "Overview" still
   measured 54 of its 57: with six, each tab is as wide as its own word plus an
   equal share of what is left, so the long word gets room and "Pull" gives it up.
   No tab goes under the 44px floor, in either direction. Five tabs or fewer are
   untouched. */
.os2c-tabs.tight button{flex:1 1 auto;min-width:var(--sys-tap,44px);padding:8px 4px;font-size:var(--sys-t-small);letter-spacing:-.01em}
/* …AND SEVEN, WITH TEXTS (2026-10-01). Seven tabs need 342px. A 375pt phone gives the
   strip 347 and fits; a 360 one gives 332 and a 320 one 296, and there the strip ran
   off the side of the screen. Under 375 it scrolls sideways instead, as the
   manager's does (bento.css, #os2Tabs.sys-seg-tight): held to the screen's width
   (min-width:0), its tabs keep their size, and applyCrewTab brings the tab that is
   on fully into view. Opaque as ever — only its overflow changes. */
@media (max-width: 374px){
  .os2c-tabs.tight{min-width:0;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none}
  .os2c-tabs.tight::-webkit-scrollbar{display:none}
  .os2c-tabs.tight button{flex-shrink:0}
}

/* ---- tab panels: hidden panels leave the flow; slots are transparent ---- */
.os2c-tab{display:none}
/* ONE COLUMN, AND IT MAY NOT BE PUSHED WIDER THAN THE PANEL. This was `display:grid`
   with no template, which is an implicit `auto` column — and an auto track's base
   size is the widest AUTOMATIC MINIMUM SIZE among its items, which for a card that
   is not itself a scroll container is that card's min-content width. So one card
   with wide content and nowhere to put it made the whole panel wider than the phone,
   and nothing in this app scrolls sideways to go and get it. Measured 2026-09-09 on
   the pull sheet in EDITING: 703px of panel inside a 390px phone, with Add, the
   quantity stepper, Add room, Done editing and every row's Remove off the glass.
   `minmax(0, 1fr)` is the same single column with an honest minimum: a card that
   cannot fit clips or scrolls inside itself, which is the card's own job, instead
   of taking the screen with it. All five panels — overview, pull, work, team and
   media — are driven in real Chrome at 390 and 402 by qa:pull-glass, each holding
   a shape that pushes an implicit `auto` track off the phone; before that, the
   claim in this comment was one card's worth of evidence. */
.os2c-tab.on{display:grid;grid-template-columns:minmax(0,1fr);gap:16px;align-content:start}
/* …AND THE TEXT INSIDE THE CARDS BREAKS WHEREVER IT HAS TO. The column above is
   the honest minimum; this is the other half of the same promise, because a card
   that is allowed to be narrow still paints a token that has no break in it right
   off its own edge — and nothing in this app scrolls sideways to go and get it.
   `overflow-wrap: anywhere` was a PERMIT-LIST here: six places somebody noticed
   (an address, a house name, a room card's strong). Everything not on the list —
   the pull sheet's piece name among them — hung out silently. Measured in real
   Chrome at 390 on 2026-09-09: a 60-character one-token piece name reported
   scrollWidth 479 against clientWidth 294, and pushed the manager's whole sheet
   to 515 inside a 326px drawer. The rule is scoped to the TEXT in the five crew
   tab panels, not to the app: it never touches a button, the nav or the tab strip,
   and on text that already fits it does nothing at all. */
.os2c-tab p, .os2c-tab h2, .os2c-tab h3, .os2c-tab h4, .os2c-tab h5,
.os2c-tab strong, .os2c-tab em, .os2c-tab td, .os2c-tab th, .os2c-tab li,
.os2c-tab dd, .os2c-tab dt { overflow-wrap: anywhere; }
.os2-slot{display:contents}
.os2c .os-hero,.os2c .jd-facts{margin:0}
/* assignments live in the Team tab — the prep card keeps only the pipeline */
.os2c .detail-prep .prep-roles{display:none}

/* ---- cards + chips (the manager's os2 language, the system's tokens) ---- */
.os2-card{background:var(--surface);border:0;border-radius:var(--sys-r-card);padding:16px;box-shadow:var(--shadow)}
.os2-h3{margin:0 0 8px;font-size:var(--sys-t-body);letter-spacing:0;color:var(--muted);font-weight:var(--sys-w-semibold);text-transform:none}
.os2-chip{display:inline-block;border-radius:var(--sys-r-pill);padding:4px 9px;font-size:var(--sys-t-caption);font-weight:var(--sys-w-semibold);letter-spacing:0;line-height:1.2;text-transform:none;background:var(--surface-2);color:var(--muted)}
.os2-chip.green{background:var(--green-soft);color:var(--green)}
.os2-chip.amber{background:var(--gold-soft);color:var(--gold)}
.os2-chip.blue{background:var(--blue-soft);color:var(--blue)}
.os2-chip.red{background:var(--red-soft);color:var(--red)}
.os2-chip.purple{background:var(--sys-purple-soft);color:var(--sys-purple-ink)}
/* A secondary button in a card header. 36px is what it looks like; the invisible
   expander makes it the 44 it has to be without growing the header. */
.os2-mini-btn{border:0;background:var(--surface);border-radius:var(--sys-r-pill);box-shadow:var(--sys-shadow-btn);padding:0 14px;min-height:36px;font-weight:var(--sys-w-semibold);font-size:var(--sys-t-body);line-height:1;color:var(--blue);cursor:pointer;-webkit-tap-highlight-color:transparent;white-space:nowrap;position:relative}
.os2-mini-btn::after{content:"";position:absolute;inset:-4px 0}
.os2-mini-btn:active{background:var(--surface-2)}

/* ---- needs attention (dot rows) ---- */
.os2-attn-item{display:flex;gap:10px;align-items:center;padding:9px 0;border-top:1px solid var(--line)}
.os2-attn-item:first-of-type{border-top:0;padding-top:2px}
.os2-dot{width:8px;height:8px;border-radius:50%;background:var(--gold);flex:none}
.os2-dot.red{background:var(--red)}
.os2-dot.ok{background:var(--green)}
.os2-dot.blue{background:var(--blue)}
.os2-attn-tx{flex:1;font-size:var(--sys-t-lead);font-weight:var(--sys-w-regular);line-height:1.3;color:var(--ink)}
.os2-attn-tx small{display:block;color:var(--muted);font-size:var(--sys-t-body);font-weight:var(--sys-w-regular);margin-top:1px}
/* Client texts on a job — HIS card (public/client-texts-card.js draws it in both
   apps since 2026-10-12), in the crew's sheet: bento.css "client texts on a job",
   rule for rule on the crew's tokens. The words in full in a quiet box, what is still
   to come above what already happened, and his two buttons under a waiting text —
   "Send this" in the accent, "Don't send" in red ink, each a full 44pt tap. */
/* The card's name reads as every crew card's heading does (.os2-h3). */
#crewClientTexts .os2-ct-h{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;margin:0 0 8px;font-size:var(--sys-t-body);color:var(--muted)}
#crewClientTexts .os2-ct-h strong{font-weight:var(--sys-w-semibold)}
#crewClientTexts .os2-ct-tag{font-size:var(--sys-t-caption);font-weight:var(--sys-w-semibold);color:var(--sys-accent);background:var(--sys-accent-soft);border-radius:var(--sys-r-pill);padding:2px 8px}
#crewClientTexts .os2-ct-tag.os2-ct-stop{color:var(--sys-red-ink);background:var(--red-soft)}
#crewClientTexts .os2-ct-eyebrow,.os2c-tab .os2c-sec{font-size:var(--sys-t-caption);font-weight:var(--sys-w-semibold);letter-spacing:.08em;color:var(--muted);margin:12px 0 6px}
/* The same eyebrow as a CATEGORY LABEL on the job's Overview (DATES & ACCESS, CLIENT,
   JOB — employee-field-app.js crewSectionLabelHtml), 2026-10-01. The panel is a grid
   with a 16px gap, and a label names the card under it: so it sits 8px above that
   card and a clear 22px under the one before, inset to the cards' text like the
   manager's. */
.os2c-tab .os2c-sec{margin:6px 4px -8px}
#crewClientTexts .os2-ct-row{border:1px solid var(--line);border-radius:var(--sys-r-control);padding:11px 12px;margin-bottom:8px}
#crewClientTexts .os2-ct-top{display:flex;justify-content:space-between;gap:8px;align-items:baseline}
#crewClientTexts .os2-ct-name{font-size:var(--sys-t-lead);font-weight:var(--sys-w-semibold);color:var(--ink)}
#crewClientTexts .os2-ct-when{font-size:var(--sys-t-small);color:var(--muted);white-space:nowrap}
#crewClientTexts .os2-ct-body{margin-top:7px;padding:9px 11px;background:var(--surface-2);border-radius:var(--sys-r-control);font-size:var(--sys-t-body-lg);line-height:1.4;color:var(--ink);overflow-wrap:anywhere;white-space:pre-line}
#crewClientTexts .os2-ct-acts{display:flex;gap:8px;margin-top:9px}
#crewClientTexts .os2-ct-acts button{min-height:44px;padding:0 14px;border-radius:var(--sys-r-control);border:1px solid var(--line);background:var(--surface);font:inherit;font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);color:var(--ink);cursor:pointer;-webkit-tap-highlight-color:transparent}
#crewClientTexts .os2-ct-acts .os2-ct-send{background:var(--sys-accent);border-color:var(--sys-accent);color:#fff}
#crewClientTexts .os2-ct-acts .os2-ct-stopbtn{color:var(--sys-red-ink)}
#crewClientTexts .os2-ct-acts button[disabled]{opacity:.5;cursor:default}
#crewClientTexts .os2-ct-past{display:flex;justify-content:space-between;gap:12px;padding:9px 0;border-top:1px solid var(--line);font-size:var(--sys-t-body-lg);color:var(--muted)}
#crewClientTexts .os2-ct-past span:last-child{text-align:right}
#crewClientTexts .os2-ct-eyebrow + .os2-ct-past{border-top:0;padding-top:2px}
#crewClientTexts .os2-ct-empty p{margin:0;color:var(--muted);font-size:var(--sys-t-lead);line-height:1.4}
/* …and his one button there, "Add a phone number" — hers since crew-all (2026-10-12):
   it opens her Edit info on the client's phone. bento.css's rule, a full 44pt tap. */
#crewClientTexts .os2-ct-empty button{margin-top:10px;min-height:44px;padding:0 14px;border:0;border-radius:var(--sys-r-control);background:var(--sys-accent);color:#fff;font:inherit;font-size:var(--sys-t-body);font-weight:var(--sys-w-semibold);cursor:pointer;-webkit-tap-highlight-color:transparent}

@media (max-width: 360px){
  .os2c-tabs button{font-size:var(--sys-t-small)}
  .os2c-addr{font-size:20px}
}

/* ============================================================
   PHOTOS: compact strip on the job page + full-screen gallery
   The crew mirror of the manager's #mdGallery (manager-media.js). The job page
   shows one row per library — "Preview  33  ›" over five thumbnails — and the
   pile itself opens edge to edge with Select / Download / Delete.
   ============================================================ */
.cm-strip-head {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  background: none;
  border: 0;
  padding: 2px 0 7px;
  margin: 0;
  /* the whole way into a library, at 29px tall. It is a row, so it can afford
     the height that makes it a real target. */
  min-height: 44px;
  text-align: left;
  color: inherit;
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.cm-strip-head b { font-weight:var(--sys-w-semibold);font-size:var(--sys-t-headline);line-height:1.2; color: var(--ink); }
.cm-strip-count { font-weight:var(--sys-w-medium);font-size:var(--sys-t-lead);line-height:1.2; color: var(--muted); font-variant-numeric: tabular-nums; }
.cm-strip-chev { margin-left: auto; font-size: 20px; line-height: 1; color: var(--muted); }
.cm-strip-head:disabled { cursor: default; }
.cm-strip-head:disabled .cm-strip-chev { opacity: .35; }

/* five up, clipped: the strip is a preview, never a horizontal scroller */
.crew-media-grid.cm-strip { grid-template-columns: repeat(5, 1fr); gap: 5px; overflow: hidden; }
/* reserve the row only while it HAS tiles: an empty or failed library should not
   leave a blank box above its message */
.crew-media-grid.cm-strip:not(:empty) { min-height: 58px; }
.cm-strip .cm-cell { min-width: 0; }
.cm-strip .cm-nameinput,
.cm-strip .cm-del,
.cm-strip .cm-pick { display: none !important; }
.cm-strip .cm-name { display: none; }
.cm-more {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--sys-scrim);
  color: #fff;
  font-weight:var(--sys-w-semibold);font-size:var(--sys-t-body);line-height:1;
  font-variant-numeric: tabular-nums;
}

#cmGallery {
  position: fixed;
  inset: 0;
  /* NOT migrated to --sys-z-fullscreen (400), and that is a decision, not an
     oversight. This is one stacking neighbourhood with #cmViewer (9999),
     #crewUndo (10000) and #crewEditSheet (10001) in employee-field-app.js, plus
     media-client.js's upload overlay at 100000, prep-pipeline.js's sheet at
     2000/2001 and team-home.css's composer at 1200/1210 — every one of which can
     be on screen while this is. A neighbourhood moves in ONE commit or a migrated
     layer at 400 ends up underneath an unmigrated one at 99998, and the thing that
     disappears is a photo the crew is trying to recover. The bars in this file
     that could hide a control have been fixed; the ordering of these six has not
     been touched, so it is exactly what it was. Move them together, with the
     manager's own overlays, or not at all. */
  z-index: 9998;
  display: none;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
}
#cmGallery.open { display: flex; }
/* The ••• menu, twin of the manager's. A passing thing, not a mode: under the bar,
   dismissed by a tap anywhere else, and it cannot open inside naming. */
#cmGallery .cm-gal-more { font-size: var(--sys-t-lead); letter-spacing: 1px; }
#cmGallery .cm-menu { position: absolute; right: 12px; top: calc(var(--sys-safe-t) + 58px); z-index: 9; min-width: 196px; display: flex; flex-direction: column; padding: 6px; border-radius: var(--sys-r-card); background: var(--card); box-shadow: var(--sys-shadow-sheet); }
#cmGallery .cm-menu[hidden] { display: none; }
#cmGallery .cm-menu button { min-height: var(--sys-tap); padding: 0 12px; border: 0; border-radius: var(--sys-r-control); background: transparent; text-align: left; color: var(--ink); font-family: inherit; font-weight: var(--sys-w-medium); font-size: var(--sys-t-lead); line-height: 1; cursor: pointer; }
#cmGallery .cm-menu button:active { background: var(--sys-fill); }
#cmGallery .cm-gal-done { background: var(--sys-accent); color: #fff; }
#cmGallery .cm-gal-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  padding: calc(var(--sys-safe-t) + 10px) 14px 10px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
#cmGallery .cm-gal-back { border: 0; background: none; color: var(--blue); font-weight:var(--sys-w-medium);font-size:var(--sys-t-lead);line-height:1; padding: 8px 4px 8px 0; min-height: 44px; cursor: pointer; white-space: nowrap; -webkit-tap-highlight-color: transparent; }
#cmGallery .cm-gal-title { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
#cmGallery .cm-gal-title b { font-weight:var(--sys-w-semibold);font-size:var(--sys-t-headline);line-height:1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#cmGallery .cm-gal-title span { font-weight:var(--sys-w-regular);font-size:var(--sys-t-body);line-height:1; color: var(--muted); white-space: nowrap; }
#cmGallery .cm-gal-tools { margin-left: auto; display: flex; align-items: center; gap: 6px; flex: none; }
/* Secondary buttons — white, accent text, the soft shadow; 44 tall. */
#cmGallery .cm-gal-btn { flex: none; display: flex; align-items: center; justify-content: center; border: 0; background: var(--surface); color: var(--blue); box-shadow: var(--sys-shadow-btn); border-radius: var(--sys-r-pill); font-weight:var(--sys-w-semibold);font-size:var(--sys-t-body);line-height:1; padding: 0 12px; min-height: 44px; white-space: nowrap; cursor: pointer; -webkit-tap-highlight-color: transparent; }
@media (max-width: 400px) { #cmGallery .cm-gal-btn { padding: 0 9px; font-size: var(--sys-t-small); } #cmGallery .cm-gal-tools { gap: 4px; } }
#cmGallery .cm-gal-btn.on { background: var(--blue); color: #fff; }
#cmGallery .cm-gal-btn svg { width: 17px; height: 17px; display: block; }
#cmGallery .cm-gal-btn:disabled { opacity: .5; }

/* sticky select bar: Select all · "12 selected" · Cancel */
#cmGallery .cm-gal-sel { display: none; align-items: center; gap: 10px; flex: 0 0 auto; padding: 9px 14px; border-bottom: 1px solid var(--line); background: var(--surface-2); position: sticky; top: 0; z-index: 3; }
#cmGallery.selecting .cm-gal-sel { display: flex; }
#cmGallery .cm-gal-count { font-weight:var(--sys-w-semibold);font-size:var(--sys-t-body);line-height:1; font-variant-numeric: tabular-nums; margin: 0 auto; }
#cmGallery .cm-gal-link { border: 0; background: none; color: var(--blue); font-weight:var(--sys-w-medium);font-size:var(--sys-t-lead);line-height:1; padding: 6px 2px; min-height: 44px; cursor: pointer; white-space: nowrap; -webkit-tap-highlight-color: transparent; }

#cmGallery .cm-gal-body { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; padding: 10px 14px calc(18px + env(safe-area-inset-bottom, 0px)); }
#cmGallery .cm-gal-grid { grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); gap: 4px; margin-top: 0; }
/* Naming: a name box the width of an 88px thumbnail cut "Living room" to "Living rooı"
   (UI-063, the manager's gallery had the same). Wider cells while naming. */
#cmGallery .cm-gal-grid.editing { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
#cmGallery .cm-gal-grid .cm-tile { border-radius: 7px; }

#cmGallery .cm-gal-actions { display: none; gap: 8px; flex: 0 0 auto; padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--line); background: var(--surface); }
#cmGallery.selecting .cm-gal-actions { display: flex; }
#cmGallery .cm-gal-actions button { flex: 1; min-height: 46px; border-radius: var(--sys-r-pill); border: 0; background: var(--surface); box-shadow: var(--sys-shadow-btn); font-weight:var(--sys-w-semibold);font-size:var(--sys-t-lead);line-height:1; color: var(--blue); cursor: pointer; -webkit-tap-highlight-color: transparent; }
#cmGallery .cm-gal-actions button[disabled] { opacity: .4; }
#cmGallery .cm-gal-delete { color: var(--red); }

/* checkmark badge on the picked tiles: the tick is the accent (contract section 2) */
.cm-pick { position: absolute; top: 5px; right: 5px; width: 21px; height: 21px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, .92); background: var(--sys-scrim); display: none; align-items: center; justify-content: center; font-weight:var(--sys-w-bold);font-size:11px;line-height:1; color: transparent; z-index: 2; }
#cmGallery.selecting .cm-pick { display: flex; }
#cmGallery.selecting .cm-cell.cm-picked .cm-pick { background: var(--blue); border-color: #fff; color: #fff; }
.cm-cell.cm-picked .cm-tile { outline: 3px solid var(--blue); outline-offset: -3px; }
.cm-cell.cm-picked .cm-tile img { opacity: .8; }

/* DOCUMENTED EXCEPTION: the last hand-typed bottom offset in this file.
   86 is not the nav — inside #cmGallery (position:fixed;inset:0) there is no nav —
   it is this gallery's OWN action bar, which appears only in selection mode while
   this toast appears in both. So there is no single height to derive it from until
   .cm-gal-actions declares one, and inventing a token to describe a bar that is
   usually not there would be the wrong shape of fix. Left as it is, on purpose,
   and named here so the next person does not "tidy" it into something that lands
   the message on top of Delete. It belongs to the gallery neighbourhood (see the
   note on #cmGallery) and moves when that does. */
#cmGallery .cm-gal-toast { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(86px + env(safe-area-inset-bottom, 0px)); z-index: 6; background: var(--ink); color: #fff; border-radius: var(--sys-r-pill); padding: 11px 17px; font-weight:var(--sys-w-semibold);font-size:var(--sys-t-body);line-height:1; max-width: 84%; text-align: center; display: none; }
#cmGallery .cm-gal-toast.on { display: block; }

/* Desktop: bigger tiles and a centred column — 76px tracks are a phone size, and at
   1280px they turned the library into a mosaic of stamps. */
@media (min-width: 700px) {
  #cmGallery .cm-gal-body > * { max-width: 1040px; margin-left: auto; margin-right: auto; }
  #cmGallery .cm-gal-grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 8px; }
  #cmGallery .cm-gal-bar,
  #cmGallery .cm-gal-sel,
  #cmGallery .cm-gal-actions { padding-left: max(14px, calc(50% - 520px)); padding-right: max(14px, calc(50% - 520px)); }
  #cmGallery .cm-gal-actions { justify-content: flex-end; }
  #cmGallery .cm-gal-actions button { max-width: 260px; }
}

/* ============================================================
   THE KEYBOARD
   Nothing in the crew app used to know the keyboard was up. Every bottom-anchored
   bar held a constant offset against a viewport that had just lost 260-346px, so
   the bars walked into the middle of the screen: on a 375x667 phone the
   "Directions / I worked here" bar landed at y239-315 of a 407px viewport, on top
   of a room's "Add a piece this room needs…" field AND its Add button. Both
   hit-tested to the bar. Tapping Add opened the Submit Hours form and the typed
   text was gone. That is the whole of "parece que se va a dañar".

   Three names are published by employee-field-app.js and are a contract with that
   file — do not rename them here:
     · --sys-kb     the keyboard's height in px, from window.visualViewport. It used
                    to be published as --crew-kb; the repo had four private copies of
                    this one measurement (--crew-kb, --inv-kb and two hand-rolled
                    lifts in the extension modules) and the manager shell had none,
                    so its Save bar still hides behind the keyboard. One name now.
                    --crew-kb survives at the top of this file as an alias of it, so
                    the rules below did not have to be rewritten to adopt it;
     · html.kb-open the visual viewport shrank, i.e. Safari / the PWA;
     · html.kb-typing a control that raises a keyboard has the caret, decided in
                    JS because CSS cannot tell a text field from a date picker.

   Everything below is inert until one of those classes appears, so this is
   correct before the JS runs, on a browser with no visualViewport, and if the
   publisher is ever removed. ============================================================ */

/* WHY THIS WHOLE BLOCK IS BEHIND A POINTER QUERY, AND NOT A WIDTH ONE.
   These rules exist to get out of the way of a SOFTWARE keyboard. On a laptop
   there isn't one, so an earlier draft that hid the nav on any focused field hid
   it on a desktop too: `opacity:0` leaves the strip exactly where it was and
   `pointer-events:none` sends the tap THROUGH to whatever is behind it, so at
   1100px wide, clicking into the Jobs search made the menu vanish and a tap where
   it had been opened a house. An invisible control that eats taps is the precise
   bug this wave set out to kill, so it may not be reintroduced by the fix for it.
   hover/pointer rather than max-width because the crew app is meant to run on an
   iPad too (the open iPhone Duo and an iPad draw two panes from 600px, and an
   iPad has a keyboard). A touch device matches; a mouse never does. */
@media (hover: none) and (pointer: coarse) {

  /* WHAT COUNTS AS "THE KEYBOARD IS UP", AND WHY IT IS NOT :focus-within.
     Two publishers, because the keyboard looks completely different from the two
     places this app runs:
       · mobile Safari / the PWA keep the webview's height and shrink only the
         VISUAL viewport — that is what html.kb-open sees, from visualViewport;
       · the Capacitor shell resizes the webview itself (Capacitor's default
         KeyboardResize), so visualViewport.height ends up equal to innerHeight
         and kb-open NEVER appears. That is the shell Maria is holding.
     The second case used to be covered with :focus-within / :has(:focus), and
     that was wrong in a way that showed up immediately: those selectors can say
     that SOMETHING on the screen has focus, never WHAT. A <select> and an
     <input type="date"> open a wheel picker — they cover nothing, and on iOS they
     KEEP focus after the picker closes. So on the Add work form, the moment she
     picked her role (the first thing you do on that form) the Submit bar moved
     and stayed moved for the rest of the screen. Focusing a tab button or the
     lockbox Copy button did the same on any platform that gives a <button> focus.
     html.kb-typing is published by employee-field-app.js, which can look at the
     element and answer the real question: does this control raise a keyboard?
     It also drops the iOS 16.4 :has() requirement these rules used to carry. */

  /* Directions / I worked here stops floating and becomes what it is while you
     type: the end of the Overview tab. Neither button is something you reach for
     mid-sentence, and there IS a text field on this tab — prep-pipeline's note
     for the mover — so nothing may hover over it. The buttons are still there,
     one scroll down, where they cannot take a tap meant for something else. */
  html.kb-open .detail-sticky-actions,
  html.kb-typing .detail-sticky-actions {
    position: static;
    box-shadow: none;
  }

  /* Submit work is different, and it took a reviewer to see it: it is not a bar
     that happens to be on the screen, it is the POINT of the screen. Sending it
     off the bottom meant that from the first keystroke there was no Submit, no
     Cancel and no menu anywhere — on a form about her hours. So it stays, and
     just changes what it is clearing: the nav is hidden now, the keyboard isn't.
     This is the one consumer of --crew-kb, and the reason the JS publishes it.
     In Safari the bar is sticky inside a scrollport the keyboard did not shrink,
     so it has to be lifted by the keyboard's own height; in the resizing shell
     --crew-kb is 0 and the scrollport already ends at the keyboard, so the same
     expression lands 8px above it there too. One rule, both shells. */
  html.kb-open .form .bottom-bar,
  html.kb-typing .form .bottom-bar {
    /* This is the whole point of the system, in one line. system.css REDEFINES
       --sys-bar-bottom inside this same pointer query as
       calc(--sys-kb + 8px + --sys-safe-b) — the identical expression this rule
       used to spell out by hand — so the bar no longer has to know the keyboard
       exists, and the manager's Save bar can be built on the same token instead of
       on a fifth private copy of this arithmetic.
       Byte-for-byte the same offset as before; what changed is who owns it.
       The fallback carries no env(): --sys-bar-bottom already contains the inset,
       and a rule that reads it and then adds env() is the double payment this
       whole section exists to stop. */
    bottom: var(--sys-bar-bottom, calc(var(--crew-kb) + 8px));
  }

  /* …and give the browser room to put the focused field somewhere you can see it.
     scroll-margin is the platform's own way to say "leave this much clear when
     you scroll me into view" — above, for the sticky tab pill; below, for the bar
     that is now sitting just over the keyboard. */
  .form .form-field input,
  .form .form-field select,
  .form .form-field textarea {
    scroll-margin-top: 64px;
    scroll-margin-bottom: 110px;
  }

  /* And the nav goes. A fixed pill anchored to the bottom of a viewport the
     keyboard just shrank is 64px of navigation sitting between you and the row
     you are typing into — inventory.css:98 already hides its own nav for exactly
     this reason. opacity, not display, so it fades back the moment the keyboard
     closes and nothing reflows underneath it. Inside this media query the
     pointer-events:none has nothing to give a tap to: the keyboard is covering
     that strip. */
  html.kb-open .nav,
  html.kb-typing .nav {
    opacity: 0;
    pointer-events: none;
  }

  /* The toast follows the nav. It used to drop to a flat 12px under kb-open,
     which parked it UNDER the keyboard in the one shell where kb-open fires;
     and under kb-typing it stayed 83px up with an empty strip beneath it. Same
     expression as the Submit bar, so the two can never disagree again. */
  /* DOCUMENTED EXCEPTION to "a bar reads --sys-bar-bottom and nothing else":
     the system's keyboard offset is 8px of air, the toast has always used 12, and
     the toast is the only thing on the screen you are meant to READ rather than
     touch — 4px closer to the keyboard is a pixel move with no bug behind it.
     --crew-kb is an alias for the system's --sys-kb, so this is still the same
     keyboard measurement as everything else; only the air is local. If the toast
     ever moves to --sys-bar-bottom, it moves 4px down, and someone should decide
     that on purpose rather than inherit it from a refactor. */
  html.kb-open .toast,
  html.kb-typing .toast {
    bottom: calc(var(--crew-kb) + 12px + env(safe-area-inset-bottom));
  }
}

.nav {
  transition: opacity .18s ease;
}

/* (The nav icons are sized by system.css — `.field-app .nav button svg`, 22px,
   the same rule that sizes the manager's — so the two apps' menus match to the
   pixel. The 20px rule that used to be here lost to it anyway.) */


/* The hours form's day row (2026-09-21): two one-tap days and the calendar. */
.whenrow{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.whenrow input[type="date"]{flex:1 1 140px;min-width:0}
.whenbtn{min-height:var(--sys-tap);padding:0 14px;border-radius:var(--sys-r-pill);border:1px solid var(--sys-line);
  background:var(--sys-panel);color:var(--sys-ink);font:inherit;font-weight:var(--sys-w-semibold);flex:none}
.whenbtn.on{background:var(--sys-accent);border-color:var(--sys-accent);color:#fff}
