/* PostWatch Refinement v6 — final correction layer
   ============================================================================
   Loads after every other stylesheet. It corrects defects that were reproduced
   in a running build across 390x844, 834x1194, 1194x834, 1366x1024 and
   1440x900, in light and dark, rather than restyling work that is already
   right. Each block states the defect it removes.

   It does not change authorization, record truth, receipts, issuer gates or
   any server contract. It is presentation only.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   1. Motion and interaction language
   ---------------------------------------------------------------------------
   The shell already defines --pw-motion-fast/base but most components hardcode
   their own durations, and press feedback is inconsistent: some controls only
   respond on release, which reads as lag. Feedback belongs on pointer-down.
   ------------------------------------------------------------------------- */

:root {
  /* Stronger than the built-in curves, which are too weak to read as
     intentional. Entering and exiting UI uses ease-out so the first frame
     moves; on-screen movement uses the symmetric in-out. */
  --pw-ease-out: cubic-bezier(.23, 1, .32, 1);
  --pw-ease-in-out: cubic-bezier(.77, 0, .175, 1);
  --pw-motion-press: 120ms;
}

/* Real controls acknowledge the press immediately. Static content never does —
   that distinction is the product's affordance contract. */
:where(button, [role="button"], a.btn, .btn, .pw4-action, .pwc-button, .pw4-bottom-item, .pw4-rail-item, .pw4-nav-item):not(:disabled):not([aria-disabled="true"]) {
  transition: transform var(--pw-motion-press) var(--pw-ease-out),
              background-color var(--pw-motion-fast, 140ms) ease,
              border-color var(--pw-motion-fast, 140ms) ease,
              color var(--pw-motion-fast, 140ms) ease;
}

:where(button, [role="button"], a.btn, .btn, .pw4-action, .pwc-button):not(:disabled):not([aria-disabled="true"]):active {
  transform: scale(.97);
}

/* Navigation is pressed hundreds of times a day; keep its feedback smaller so
   it never reads as a bounce. */
:where(.pw4-bottom-item, .pw4-rail-item, .pw4-nav-item):active {
  transform: scale(.985);
}

/* Hover states must not fire on touch, where they latch after a tap. */
@media (hover: none) {
  :where(.pw4-bottom-item, .pw4-rail-item, .pw4-nav-item, .btn, .pw4-action):hover {
    background-color: inherit;
  }
}

@media (prefers-reduced-motion: reduce) {
  :where(button, [role="button"], a.btn, .btn, .pw4-action, .pwc-button, .pw4-bottom-item, .pw4-rail-item, .pw4-nav-item):active {
    transform: none;
  }
}

/* ---------------------------------------------------------------------------
   2. Navigation keeps its labels
   ---------------------------------------------------------------------------
   Defect: responsive-v5 hides the label on every inactive destination in both
   the compact dock and the iPad rail, leaving four unlabelled glyphs and a
   tooltip that a touch device never shows. The product's own design system
   requires visible navigation labels, and the stated audience includes older
   and nontechnical staff working from shared stations. Labels return; the
   floating dock and the rail keep their shape.
   ------------------------------------------------------------------------- */

@media (max-width: 767px) {
  /* 6px padding + a 60px item + 6px padding. Sized from the item so the label
     is never clipped by the dock edge. */
  .pw4-bottom-nav {
    min-height: calc(72px + env(safe-area-inset-bottom, 0px));
    padding: 6px 6px calc(6px + env(safe-area-inset-bottom, 0px));
  }

  .pw4-bottom-item {
    height: auto;
    min-height: 60px;
    flex-direction: column;
    justify-content: center;
    gap: 3px;
    padding: 7px 2px;
    color: #b9c9da;
  }

  /* The label is part of the target, not a tooltip. Matches the specificity of
     the responsive-v5 rule that visually hid it and wins on cascade order. */
  .pw4-bottom-item:not(.is-active) > span:last-child,
  .pw4-bottom-item.is-active > span:last-child {
    min-height: 0;
    display: block;
    max-width: 100%;
    overflow: hidden;
    font-size: 13px;
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: .005em;
    white-space: nowrap;
    text-overflow: ellipsis;
    /* Undo the visually-hidden treatment from responsive-v5. */
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    clip: auto;
    clip-path: none;
  }

  .pw4-bottom-item svg {
    width: 22px;
    height: 22px;
    flex: 0 0 auto;
  }

  .pw4-bottom-item.is-active {
    color: #ffffff;
  }

  .pw4-bottom-item.is-active > span:last-child {
    font-weight: 800;
  }
}

/* iPad rail: the design system asks for a labelled rail at this breakpoint. */
@media (min-width: 768px) and (max-width: 1199px) {
  :root {
    --pw-shell-rail: 104px;
  }

  .pw4-rail-item {
    min-height: 62px;
    padding: 8px 4px;
    gap: 4px;
  }

  .pw4-rail-item:not(.is-active) > span:last-child,
  .pw4-rail-item.is-active > span:last-child {
    position: static;
    width: auto;
    max-width: 100%;
    height: auto;
    overflow: hidden;
    padding: 0;
    margin: 0;
    border: 0;
    clip: auto;
    clip-path: none;
    font-size: 12px;
    font-weight: 700;
    line-height: 1.2;
    white-space: nowrap;
    text-overflow: ellipsis;
    text-align: center;
  }

  .pw4-rail-item svg {
    width: 22px;
    height: 22px;
  }

  /* Defect: the compact product mark broke mid-word to "PostWatc / h" at 10px
     inside a 62px box. Give it room and forbid the break. */
  .pw4-rail__brand {
    width: calc(var(--pw-shell-rail) - 20px);
    min-height: 62px;
    gap: 2px;
  }

  .pw4-rail__brand strong {
    font-size: 16px;
    line-height: 1.1;
    white-space: nowrap;
  }

  .pw4-rail__brand small {
    margin-top: 3px;
    font-size: 11px;
    line-height: 1.1;
    letter-spacing: .02em;
    white-space: nowrap;
  }
}

/* ---------------------------------------------------------------------------
   3. One Assistant entry point per canvas
   ---------------------------------------------------------------------------
   Defect: "Ask PostWatch" was rendered three times at once — a rail/sidebar
   destination, a header command entry, and a floating button — and the
   floating button sat on top of the Operational Pulse card on iPad and of the
   support column on desktop. Wherever persistent navigation exists, the
   floating button is removed. It survives only on compact, where the dock may
   not carry an Assistant destination for every role, and there it clears the
   dock and the safe area.
   ------------------------------------------------------------------------- */

@media (min-width: 768px) {
  #pwc-assistant-fab,
  .pwc-assistant-fab,
  #os-assistant-fab,
  .os-assistant-fab {
    display: none !important;
  }
}

@media (max-width: 767px) {
  #pwc-assistant-fab,
  .pwc-assistant-fab {
    bottom: calc(78px + env(safe-area-inset-bottom, 0px));
    right: max(14px, env(safe-area-inset-right, 0px));
    z-index: 340; /* below the dock, never over it */
  }

  /* The Assistant route already is the Assistant; no floating shortcut to it. */
  body[data-pw-route="/ai"] #pwc-assistant-fab,
  body[data-pw-route="/ai"] .pwc-assistant-fab {
    display: none !important;
  }
}

/* ---------------------------------------------------------------------------
   4. Metrics and stat tiles
   ---------------------------------------------------------------------------
   Defect: the Operational Pulse grid held three fixed tracks inside a 445px
   support column, so each tile fell to 126px and the 34px value wrapped
   mid-word ("Not acti / ve", "83 / %"). Tiles now reflow instead of crushing,
   and the value is a single unbroken line.
   ------------------------------------------------------------------------- */

.pw4-metric-grid {
  grid-template-columns: repeat(auto-fit, minmax(152px, 1fr));
  gap: 12px;
}

.pw4-metric {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 16px 16px 18px;
}

.pw4-metric strong {
  margin-top: 6px;
  overflow-wrap: normal;
  word-break: normal;
  hyphens: none;
  font-size: clamp(22px, 1.9vw, 30px);
  line-height: 1.12;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}

.pw4-metric > .pw4-metric__label {
  min-height: 0;
  align-items: flex-start;
  color: var(--pw-text-muted, #506176);
  font-size: 14px;
  line-height: 1.35;
}

.pw4-metric small {
  margin-top: 6px;
  font-size: 14px;
  line-height: 1.4;
}

/* One tile per row: label and caption on the left, value on the right. Used on
   a phone, and in the desktop support column, where three equal tracks always
   left an orphan tile and a hole beside it. */
@media (max-width: 767px), (min-width: 1200px) {
  .pw4-metric-grid,
  .pw4-today__lower .pw4-metric-grid {
    grid-template-columns: 1fr;
    gap: 8px;
  }

  .pw4-metric {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 16px;
    padding: 14px 16px;
  }

  .pw4-metric strong {
    grid-column: 2;
    grid-row: 1 / span 2;
    margin-top: 0;
    font-size: 26px;
    text-align: right;
  }

  .pw4-metric small {
    grid-column: 1;
    margin-top: 2px;
  }
}

/* When the only priority is already promoted into the "Do now" card, the
   priorities row is not rendered at all; collapse its track so the support
   column does not float against an empty band. */
@media (min-width: 1200px) {
  .pw4-today:not(:has(.pw4-section)) {
    grid-template-areas:
      "intro intro"
      "next support"
      "activity activity";
  }
}

/* ---------------------------------------------------------------------------
   5. Today: the hero card
   ---------------------------------------------------------------------------
   Defect: the headline shared a row with the action button, so a 37px
   headline was measured into 312px — roughly eight characters a line — while
   the card kept 354px of height for five lines of content. The headline now
   owns the full measure and the action sits on its own row with the
   supporting sentence, which also gives the button a stable, predictable
   position across every card state.
   ------------------------------------------------------------------------- */

.pw4-next {
  min-height: 0;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  row-gap: 0;
  padding: clamp(24px, 3vw, 36px);
}

.pw4-next h2 {
  align-self: auto;
  max-width: 22ch;
  font-size: clamp(26px, 2.1vw, 32px);
  line-height: 1.16;
  letter-spacing: -.02em;
  text-wrap: balance;
}

.pw4-next > p {
  max-width: 62ch;
  margin-top: 10px;
}

.pw4-next > .pw4-action {
  grid-column: 1;
  grid-row: auto;
  justify-self: start;
  align-self: auto;
  min-width: 0;
  margin-top: 22px;
}

/* ---------------------------------------------------------------------------
   6. Section headers survive a narrow canvas
   ---------------------------------------------------------------------------
   Defect: "Today's Priorities" and its "3 items in working order" counter sat
   in one non-wrapping row, so both wrapped to two lines on a 390px phone and
   the heading lost its rhythm.
   ------------------------------------------------------------------------- */

@media (max-width: 599px) {
  .pw4-section__head,
  .pw4-panel__head {
    flex-wrap: wrap;
    row-gap: 2px;
  }

  .pw4-section__head > :first-child,
  .pw4-panel__head > :first-child {
    flex: 1 1 100%;
  }

  .pw4-section__head > :last-child:not(:first-child),
  .pw4-panel__head > :last-child:not(:first-child) {
    flex: 0 0 auto;
    font-size: 14px;
  }
}

/* ---------------------------------------------------------------------------
   7. Operational metadata never drops below 14px
   ---------------------------------------------------------------------------
   Defect: status pills, priority tags, coverage labels and record captions
   rendered at 10-12.5px across Staffing, Concerns, Incidents and Documents.
   The design system sets 14px as the floor for anything operational; only
   decorative marks are exempt. These are the measured offenders.
   ------------------------------------------------------------------------- */

/* Concerns and Incidents status / severity / routing pills. */
.pwc3-pill {
  min-height: 26px;
  padding: 3px 10px;
  font-size: 14px;
  line-height: 1.3;
}

/* Staffing queue rows. */
html[data-pw-workspace="hr"] #app-root .hr-ins-row__tag,
.hr-ins-row__tag {
  min-height: 28px;
  font-size: 14px;
  line-height: 1.3;
}

html[data-pw-workspace="hr"] #app-root .hr-ins-row__need-label,
.hr-ins-row__need-label {
  font-size: 14px;
  line-height: 1.3;
}

html[data-pw-workspace="hr"] #app-root .hr-ins-row__dep,
.hr-ins-row__dep {
  font-size: 14px;
  line-height: 1.35;
}

/* Documents uses a smaller scale than every sibling route (.73–.84rem where
   the others use .875rem), so its KPI captions, filter labels, segment tabs,
   record source lines and inline validation all render at 12.5–13.4px. Raise
   the whole namespace to the floor rather than patching each rule. */
.docs3-page .eyebrow,
.docs3-page small,
.docs3-page em,
.docs3-kpi small,
.docs3-record__copy small,
.docs3-record__copy em,
.docs3-search > span,
.docs3-category > span,
.docs3-create-popover span,
.docs3-segments > a {
  font-size: 14px;
  line-height: 1.4;
}

/* Segment filters are controls, not captions: give them a real target. */
.docs3-segments > a {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

/* Shared eyebrows across the other route layers. */
.pwi-eyebrow,
.pwp3-eyebrow {
  font-size: 14px;
  line-height: 1.4;
}

/* Route eyebrows used --pw-gold-600, which is the *fill* tone. As 14px text on
   the app background it measures 3.70:1, below the 4.5:1 the size requires.
   The design system already ships the right token for this exact case —
   --pw-gold-ink, "gold text/icon on neutral surfaces" — which measures 5.36:1
   in light and stays legible in dark. */
.pwc3-eyebrow,
.pwi3-eyebrow {
  color: var(--pw-gold-ink, #8a6112);
}

/* Staffing benefits summary line, and the view-mode toggle beside it, which
   was a 34px-high control carrying 13px labels. */
.hr-ins-card__meta,
.hr-benefits-summary,
.hr-ins-summary > div,
.hr-view-toggle button span {
  font-size: 14px;
  line-height: 1.45;
}

/* Documents "guided generator" hints and Accounts eyebrows/counters. */
.docs3-page span > small,
.pwaa-icon-label > span,
.pwaa-count,
.pwaa-panel p.pwaa-hint,
.pwaa-side p {
  font-size: 14px;
  line-height: 1.4;
}

/* ---------------------------------------------------------------------------
   7b. Every real control clears 44px
   ---------------------------------------------------------------------------
   Measured shortfalls: the Staffing view-mode toggle (34px), the message
   correction control (32px). Secondary and destructive controls stay visually
   quiet while still being a legitimate target.
   ------------------------------------------------------------------------- */

.hr-view-toggle button,
.hr-ins-toolbar button,
body.pw-authenticated .pwc4-enhanced .pwc-message__remove {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding-inline: 12px;
}

/* ---------------------------------------------------------------------------
   8. Conversations: Team Messages and the Assistant
   ---------------------------------------------------------------------------
   Defects, all reproduced at 1440x1400:
   - the transcript was top-anchored, so one message sat a thousand pixels
     above the composer and the pane read as broken;
   - the message row placed the avatar below the bubble instead of beside it;
   - a destructive "Remove" was rendered permanently under every message, in
     red, at the same weight as the message itself;
   - the empty state's parts drifted apart instead of reading as one block.
   ------------------------------------------------------------------------- */

body.pw-authenticated .pwc4-enhanced .pwc-transcript {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* The bottom-anchoring pattern that survives overflow: push the first child
   down with auto margin rather than justify-content, which can clip the top of
   a scrolled flex column. */
body.pw-authenticated .pwc4-enhanced .pwc-transcript > :first-child {
  margin-block-start: auto;
}

body.pw-authenticated .pwc4-enhanced .pwc-empty {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-block: auto;
  text-align: center;
}

body.pw-authenticated .pwc4-enhanced .pwc-empty > div {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 46ch;
}

/* Message row: avatar beside the message, actions on their own quiet row. */
body.pw-authenticated .pwc4-enhanced .pwc-message {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr);
  grid-template-areas:
    "avatar meta"
    "avatar bubble"
    ".      actions";
  align-items: start;
  column-gap: 10px;
  row-gap: 3px;
}

body.pw-authenticated .pwc4-enhanced .pwc4-team-avatar { grid-area: avatar; align-self: start; margin-top: 22px; }
body.pw-authenticated .pwc4-enhanced .pwc-message__meta { grid-area: meta; }
body.pw-authenticated .pwc4-enhanced .pwc-message__bubble { grid-area: bubble; }
body.pw-authenticated .pwc4-enhanced .pwc-message__actions { grid-area: actions; }

/* A destructive control is available, not advertised. It appears on hover, on
   keyboard focus, and always on touch, where there is no hover. */
@media (hover: hover) and (pointer: fine) {
  body.pw-authenticated .pwc4-enhanced .pwc-message__actions {
    opacity: 0;
    transition: opacity var(--pw-motion-fast, 140ms) var(--pw-ease-out);
  }

  body.pw-authenticated .pwc4-enhanced .pwc-message:hover .pwc-message__actions,
  body.pw-authenticated .pwc4-enhanced .pwc-message:focus-within .pwc-message__actions {
    opacity: 1;
  }
}

body.pw-authenticated .pwc4-enhanced .pwc-message__remove {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding: 4px 12px;
  font-size: 14px;
}

/* Mirrored rows keep the same structure so the two sides stay aligned. */
body.pw-authenticated .pwc4-enhanced .pwc-message--mine {
  grid-template-columns: minmax(0, 1fr) 36px;
  grid-template-areas:
    "meta   avatar"
    "bubble avatar"
    "actions .";
  justify-items: end;
}

/* ---------------------------------------------------------------------------
   9. Header echo
   ---------------------------------------------------------------------------
   Defect: the workspace panes restated the page title and subtitle that the
   page header had already given, ~90px above — "PostWatch Assistant / Ask or
   prepare an action" under "PostWatch Assistant / Ask about current
   operations…". The pane header keeps its controls and drops the echo.
   ------------------------------------------------------------------------- */

body.pw-authenticated .pwc4-enhanced .pwc4-pane-title small,
body.pw-authenticated .pwc4-enhanced .pwc-pane__header > div > span {
  display: none;
}

/* Team Messages stated the channel name and its purpose three times at once:
   the thread header, and again as "Channel" and "Purpose" in the details rail.
   The rail keeps only what the header cannot show. */
@media (min-width: 1200px) {
  body.pw-authenticated .pwc4-side-pane .pwc4-fact:has(.pwc4-team-detail-name),
  body.pw-authenticated .pwc4-side-pane .pwc4-fact:has(.pwc4-team-detail-purpose) {
    display: none;
  }
}

/* The same acknowledgement policy was printed under the channel list and again
   in the details rail. It belongs with the channel's access facts. */
body.pw-authenticated .pwc4-enhanced .pwc-team-scope__help {
  display: none;
}

/* The Assistant pane header repeated the page title and subtitle verbatim,
   about 90px below them. Team Messages keeps its toolbar copy because there it
   names the open channel, which the page header does not. */
body[data-pw-route="/ai"] .pwc-toolbar__copy {
  display: none;
}

body[data-pw-route="/ai"] .pwc-toolbar {
  min-height: 0;
  padding-block: 8px;
}

/* Suggested briefings sat above the transcript while the empty state told the
   reader to choose one "below". Move them to where the eye already is — just
   above the composer — which also matches the pattern people know from every
   other assistant they use. */
body[data-pw-route="/ai"] .pwc-surface > .pwc-suggestions {
  order: 1;
  padding-block: 10px;
  border-top: 1px solid var(--pwc4-line, var(--pw-border));
}

body[data-pw-route="/ai"] .pwc-surface > .pwc-composer { order: 2; }
body[data-pw-route="/ai"] .pwc-surface > .pwc-assistant-info { order: 3; }

/* The composer label repeated the page title and the placeholder. Keep it for
   assistive technology, drop it from the visual stack. The keyboard hint is
   revealed while the composer has focus instead of living there permanently. */
body.pw-authenticated .pwc-composer > label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  padding: 0;
  margin: -1px;
  border: 0;
  clip-path: inset(50%);
  white-space: nowrap;
}

body.pw-authenticated .pwc-composer__help > span:first-child {
  opacity: 0;
  transition: opacity var(--pw-motion-fast, 140ms) ease;
}

body.pw-authenticated .pwc-composer:focus-within .pwc-composer__help > span:first-child {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  body.pw-authenticated .pwc-composer__help > span:first-child { transition: none; }
}

/* Conversation workspaces hide the page header on a phone and in landscape to
   give the transcript the full canvas. That is the right call for space, but
   it took the page's only h1 with it: the route then had no accessible name
   and nothing for the route-change focus move to land on. Hide it visually,
   keep it in the accessibility tree. */
@media (max-width: 767px), (max-height: 700px) and (orientation: landscape) {
  body.pw-authenticated .pwc4-enhanced > .pwc-page__header {
    display: block;
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    padding: 0;
    margin: -1px;
    border: 0;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* ---------------------------------------------------------------------------
   10. Focus is always visible, including inside dark panes
   ------------------------------------------------------------------------- */

:where(a, button, input, select, textarea, summary, [tabindex]:not([tabindex="-1"])):focus-visible {
  outline: 3px solid var(--pw-focus, #2e5bff);
  outline-offset: 3px;
  border-radius: max(6px, var(--pw-radius-control, 12px));
}

/* On the deep navy hero and the rail the blue ring disappears; use the light
   focus tone there so the ring is visible on both surfaces. */
.pw4-next :where(a, button):focus-visible,
.pw4-rail :where(a, button):focus-visible,
.pw4-sidebar :where(a, button):focus-visible,
.pw4-bottom-nav :where(a, button):focus-visible {
  outline-color: #ffd489;
  box-shadow: none;
}

@media (forced-colors: active) {
  :where(a, button, input, select, textarea, summary):focus-visible {
    outline: 3px solid Highlight;
  }
}

/* ---------------------------------------------------------------------------
   10b. Inverted controls inside the intelligence lane
   ---------------------------------------------------------------------------
   Defect: responsive-v5 colours every span inside `.intelligence-lane` with
   `--pw5-lane-muted`, a light ink meant for the lane's navy surface. That
   descendant selector also reaches inside `.portfolio-priority__action`, which
   is a solid white pill — so the button's own label rendered light-on-white at
   1.31:1 and was effectively invisible. Broken in both themes; worse in dark.
   A control that paints its own surface owns its own ink.
   ------------------------------------------------------------------------- */

/* The pill already declares `color: #0f2a4a` against its literal white
   background, and that pairing must not follow the theme — the surface does
   not flip, so the ink must not either. Do not substitute a --pw-* token here:
   --pw-navy-900 inverts to a light tint in dark mode and reproduces the exact
   defect. The children simply need to stop being recoloured. */
.intelligence-lane .portfolio-priority__action :where(span, small, strong, p, svg) {
  color: inherit;
}

/* ---------------------------------------------------------------------------
   11. Long content and safe areas
   ---------------------------------------------------------------------------
   A page must never own two vertical scrollbars, and content must never sit
   under the floating dock.
   ------------------------------------------------------------------------- */

@media (max-width: 767px) {
  body.pw-authenticated #app-root,
  body.pw4-authenticated #app-root {
    padding-bottom: calc(88px + env(safe-area-inset-bottom, 0px));
  }
}

/* Wide tables and code-like content scroll inside their own container so the
   document never scrolls sideways. */
:where(.pw-scroll-x, [data-pw-scroll-x]) {
  max-width: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

/* ---------------------------------------------------------------------------
   12. Field-report corrections (2026-08-12)
   ---------------------------------------------------------------------------
   Reported against the live build. Each block names the defect it removes.
   ------------------------------------------------------------------------- */

/* 12a. Own messages reserved a 36px avatar column that never has an avatar.
   postwatch-conversations-v4.js only prepends .pwc4-team-avatar for OTHER
   people's messages, so `--mine` rows carried an empty gutter and the bubble
   was pushed off its own edge. Regression from section 8; own rows are a
   single column. */
body.pw-authenticated .pwc4-enhanced .pwc-message--mine {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "meta"
    "bubble"
    "actions";
}

/* A row whose avatar was never injected must not keep the avatar track either. */
body.pw-authenticated .pwc4-enhanced .pwc-message:not(:has(.pwc4-team-avatar)) {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "meta"
    "bubble"
    "actions";
}

/* 12b. Empty states sat flush against their container edge — "No matching
   activity" and "No DTRs match" touched the card frame with zero padding,
   because the list containers that host them have none. */
.empty-state {
  padding: clamp(28px, 4vw, 44px) clamp(20px, 3vw, 28px);
  text-align: center;
}

.empty-state > :first-child { margin-top: 0; }
.empty-state > :last-child { margin-bottom: 0; }

.empty-state p {
  max-width: 46ch;
  margin-inline: auto;
  color: var(--pw-text-muted, var(--text-muted));
}

/* The soft/inline variants used inside panels keep a smaller but non-zero inset. */
:where(.soft-empty, .pw4-soft-empty) {
  padding: 20px 18px;
}

/* 12c. Status pills rendered a Lucide glyph where the stylesheet expected a 7px
   dot, so the icon inherited no size rule and overlapped its own label. Size
   the glyph and stop it shrinking. Status is operational metadata: 14px floor. */
:where(.docs3-status, .pwc3-pill, .status-pill) {
  font-size: 14px;
  gap: 7px;
  min-height: 28px;
  padding-inline: 10px;
}

:where(.docs3-status, .pwc3-pill, .status-pill) > svg {
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
}

/* The dot variant only applies to a bare span, never to an injected icon. */
.docs3-status > span:not([class]) {
  flex: 0 0 auto;
}

/* 12d. Very long pickers (area assignment on Accounts) rendered every option at
   full height, so the dialog grew past the viewport and the primary action was
   unreachable without scrolling the whole page. Cap the option list and let it
   scroll inside itself, keeping the dialog's actions on screen. */
/* Plain class selectors, not :where() — postwatch-auth-v2.js injects its own
   <style> after this sheet, so a zero-specificity rule would lose. */
.pwauth-admin-checks,
.pwaa-area-grid,
.pwaa-assignment-grid,
.assignment-list,
.pwauth-assignment-list {
  max-height: min(46vh, 420px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: 4px;
  scrollbar-gutter: stable;
}

/* 12e. A rate-limit or validation error under a long form was easy to miss
   after scrolling. Keep it visible where the action is. */
:where(.pwaa-dialog, .pwauth-admin-form) .pwc-field-error:not(:empty),
:where(.pwaa-dialog, .pwauth-admin-form) .pwaa-error:not(:empty) {
  position: sticky;
  bottom: 0;
  z-index: 2;
  padding: 10px 12px;
  border-radius: var(--pw-radius-control, 12px);
  background: var(--pw-danger-soft, #fff0ed);
  color: var(--pw-danger-ink, #a61b12);
  font-size: 14px;
}

/* ---------------------------------------------------------------------------
   13. Old-Android compatibility layer
   ---------------------------------------------------------------------------
   The product uses color-mix() in 325 places across 24 stylesheets — 171 for
   background, 112 for borders, 19 for shadows, 4 for focus outlines. color-mix()
   needs Chrome/WebView 111 (2023). On the budget Android handsets guards
   actually carry (Android 9–11, WebView ~90–110) every one of those
   declarations is dropped by the parser. It does not error and it does not warn:
   borders vanish, form fields lose their edges, selected rows lose their tint,
   and the keyboard focus ring disappears. The app looks subtly wrong to them and
   perfect on a modern machine.

   This block runs ONLY where color-mix() is unsupported, and restores the
   structural cues from the plain-hex --pw-* tokens. It is not a re-skin; it is
   the floor beneath the tint.
   ------------------------------------------------------------------------- */

@supports not (color: color-mix(in srgb, red 50%, blue)) {

  /* 13a. Surfaces keep a visible edge. A card without a border on a near-white
     canvas is an invisible card. */
  :where(
    .card, .pw4-panel, .pw4-priority, .pw4-metric, .pw4-next,
    .pwc3-card, .pwc3-case-card, .pwc3-master, .pwc3-record-head,
    .docs3-record, .docs3-kpi, .dtr-record, .dtr-master, .dtr-detail,
    .activity-person, .activity-list-card, .activity-map-card, .activity-truth,
    .field-card, .field-summary > div, .pwauth-identity-card, .pwauth-admin-filter,
    .pw4-waiting-row, .collection-toolbar, .empty-state, .soft-empty,
    .pwc4-side-pane, .pwc-surface, .pwc-message__bubble, .report-draft,
    .finance-record, .pwi3-master, .pwi3-detail, .pwp3-area-card
  ) {
    border: 1px solid var(--pw-border, #e8e6e0);
  }

  /* 13b. Form controls must never lose their outline — an input with no border
     is indistinguishable from body copy. */
  :where(input, select, textarea, .search-field, .pwauth-admin-filter input,
         .pwauth-admin-filter select) {
    border: 1px solid var(--pw-border-strong, #d2cfc6);
  }

  /* 13c. The keyboard focus ring is an accessibility floor, not decoration. */
  :where(a, button, input, select, textarea, summary,
         [tabindex]:not([tabindex="-1"])):focus-visible {
    outline: 3px solid var(--pw-focus, #2e5bff);
    outline-offset: 3px;
  }

  /* 13d. Status tints fall back to their solid soft tokens, so "needs
     attention" still reads as attention rather than as plain surface. */
  :where(.pw4-metric--attention, .status-pill--warn, .pwc3-pill--severity-medium,
         .docs3-status--soon, .docs3-kpi--warning) {
    background: var(--pw-warning-soft, #fff3da);
    color: var(--pw-warning-ink, #7a4700);
  }

  :where(.pw4-metric--danger, .status-pill--missing, .status-pill--crit,
         .pwc3-pill--severity-high, .docs3-status--expired, .docs3-kpi--danger) {
    background: var(--pw-danger-soft, #fff0ed);
    color: var(--pw-danger-ink, #a61b12);
  }

  :where(.status-pill--ok, .pwc3-pill--resolved, .docs3-status--filed,
         .docs3-kpi--ok) {
    background: var(--pw-success-soft, #e7f6ee);
    color: var(--pw-success-ink, #12633f);
  }

  /* 13e. Grouped and selected rows keep a readable separation. */
  :where(.pw4-metric, .docs3-kpi, .pwc3-pill, .status-pill, .pw4-soft-empty,
         .activity-truth, .pwc4-fact, .pwaa-fact) {
    background: var(--pw-surface-muted, #f4f3ee);
  }

  :where(.is-active, .is-selected, [aria-current="true"], [aria-selected="true"]):where(
    .dtr-record, .docs3-record, .pwc3-case-card, .activity-person, .finance-record,
    .pwc4-history-item, .docs3-segments > a, .segmented > a
  ) {
    background: var(--pw-surface-strong, #eceae4);
    border-color: var(--pw-border-strong, #d2cfc6);
  }

  /* 13f. Depth without color-mix. */
  :where(.card, .pw4-panel, .pwc3-card, .activity-list-card, .activity-map-card,
         .pwc-surface, .pwc4-side-pane) {
    box-shadow: 0 1px 2px rgba(15, 23, 42, .06);
  }

  /* 13g. Translucent chrome becomes solid: backdrop-filter is also unsupported
     on these builds, so a semi-transparent bar would show content through it. */
  :where(.pw4-bottom-nav, .pw4-utility, .pwc-composer, .os-utility) {
    background: var(--pw-surface, #ffffff);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  .pw4-bottom-nav {
    background: #0b2037;
  }
}

/* dvh is Chrome 108+. Where a pane caps its height with dvh alone, an older
   engine drops the cap and the page scrolls instead of the pane — acceptable,
   but give the two full-height shells an explicit vh floor so they never
   collapse. */
@supports not (height: 1dvh) {
  :where(.pwc-team, .pwc-assistant, .pwc4-workspace) {
    min-height: calc(100vh - 160px);
  }
}

/* ---------------------------------------------------------------------------
   14. Coverage triage (postwatch-refinement-v6.js)
   ------------------------------------------------------------------------- */

.pw6-triage {
  margin: 0 0 20px;
  padding: clamp(18px, 2.4vw, 26px);
  border: 1px solid var(--pw-border, #e8e6e0);
  border-radius: var(--pw-radius-card, 16px);
  background: var(--pw-surface, #fff);
}

.pw6-triage__head h2 { margin: 0; font-size: clamp(20px, 1.7vw, 24px); line-height: 1.25; }
.pw6-triage__head p {
  max-width: 78ch;
  margin: 6px 0 0;
  color: var(--pw-text-muted, #6b6862);
  font-size: 15px;
  line-height: 1.55;
}

.pw6-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 10px;
  margin-top: 16px;
}

.pw6-stat {
  min-width: 0;
  padding: 14px 16px;
  border-radius: 14px;
  background: var(--pw-surface-muted, #f4f3ee);
}
.pw6-stat__label { display: block; color: var(--pw-text-muted, #6b6862); font-size: 14px; font-weight: 700; }
.pw6-stat strong {
  display: block;
  margin-top: 4px;
  font-size: clamp(22px, 1.9vw, 28px);
  line-height: 1.12;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  overflow-wrap: normal;
  word-break: normal;
}
.pw6-stat small { display: block; margin-top: 5px; color: var(--pw-text-muted, #6b6862); font-size: 14px; line-height: 1.4; }
.pw6-stat--danger { background: var(--pw-danger-soft, #fff0ed); }
.pw6-stat--danger strong { color: var(--pw-danger-ink, #a61b12); }
.pw6-stat--attention { background: var(--pw-warning-soft, #fff3da); }
.pw6-stat--attention strong { color: var(--pw-warning-ink, #7a4700); }

.pw6-triage__note {
  margin: 14px 0 0;
  padding: 12px 14px;
  border-left: 3px solid var(--pw-gold-600, #a87920);
  border-radius: 0 12px 12px 0;
  background: var(--pw-surface-muted, #f4f3ee);
  color: var(--pw-text, #14140f);
  font-size: 15px;
  line-height: 1.55;
}

.pw6-client-list { display: grid; gap: 8px; margin-top: 16px; }

.pw6-client { border: 1px solid var(--pw-border, #e8e6e0); border-radius: 14px; background: var(--pw-surface, #fff); }
.pw6-client > summary {
  min-height: 52px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
  padding: 12px 16px;
  border-radius: 14px;
  cursor: pointer;
  list-style: none;
}
.pw6-client > summary::-webkit-details-marker { display: none; }
.pw6-client > summary:hover { background: var(--pw-surface-muted, #f4f3ee); }
.pw6-client[open] > summary { border-bottom: 1px solid var(--pw-border, #e8e6e0); border-radius: 14px 14px 0 0; }
.pw6-client__name { font-size: 16px; font-weight: 750; }
.pw6-client__tally { color: var(--pw-text-muted, #6b6862); font-size: 14px; font-variant-numeric: tabular-nums; }

.pw6-area-list { margin: 0; padding: 4px 0; list-style: none; }
.pw6-area {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 16px;
  padding: 10px 16px;
  border-top: 1px solid var(--pw-border, #e8e6e0);
}
.pw6-area:first-child { border-top: 0; }
.pw6-area__name { min-width: 0; font-size: 15px; font-weight: 640; }
.pw6-area__state { color: var(--pw-text-muted, #6b6862); font-size: 14px; }
.pw6-area--never .pw6-area__state { color: var(--pw-danger-ink, #a61b12); font-weight: 700; }
.pw6-area--duplicate .pw6-area__state { color: var(--pw-warning-ink, #7a4700); font-weight: 700; }
.pw6-client__more { margin: 0; padding: 10px 16px 14px; color: var(--pw-text-muted, #6b6862); font-size: 14px; }

@media (max-width: 599px) {
  .pw6-area { flex-direction: column; gap: 2px; }
  .pw6-client__tally { flex: 1 1 100%; }
}

/* ---------------------------------------------------------------------------
   15. Audit diff tables
   ---------------------------------------------------------------------------
   The Audit Log's "changed fields" table rendered its headers and cells at
   11px. A diff is the most consequential text in the product — it is what
   proves who changed what — and it was the smallest text on screen.
   ------------------------------------------------------------------------- */

.audit-diff table,
.audit-diff th,
.audit-diff td,
.audit-diff code {
  font-size: 14px;
  line-height: 1.45;
}

.audit-diff th {
  font-weight: 750;
  text-align: left;
}

.audit-diff td,
.audit-diff th {
  padding: 8px 10px;
  vertical-align: top;
}

.audit-diff summary {
  min-height: 44px;
  display: flex;
  align-items: center;
  font-size: 14px;
}

/* Long before/after values wrap instead of forcing the table sideways. */
.audit-diff td:nth-child(2),
.audit-diff td:nth-child(3) {
  overflow-wrap: break-word;
  max-width: 32ch;
}

/* ---------------------------------------------------------------------------
   16. Daily manning check-in modal
   ---------------------------------------------------------------------------
   This is the screen inspectors use every day, usually on a phone, often
   outdoors. Its labels, status line and eyebrow rendered at 11.5–13px — the
   smallest type in the product on the most-used screen. Raised to the 14px
   operational floor. The modal's blocking behaviour is deliberate and is left
   alone; see the handoff notes.
   ------------------------------------------------------------------------- */

.mci-step-label,
.mci-eyebrow,
.mci-client-name,
.mci-status,
.mci-hint,
.mci-required {
  font-size: 14px;
  line-height: 1.45;
}

.mci-overlay :where(p, small, span, label):not(.mci-area-name):not([class*="btn"]) {
  font-size: max(14px, 1em);
}

.mci-skip-link {
  min-height: 48px;
  font-size: 16px;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---------------------------------------------------------------------------
   17. Team Activity Map — the map always draws
   ---------------------------------------------------------------------------
   Previously the map only initialised when a pin existed, so with no reported
   locations the route showed an empty bordered box. It now opens on Metro
   Manila and states the absence inside the map. The caption sits over live
   tiles, so it carries its own opaque surface rather than relying on the tile
   colour underneath — that is also what keeps it legible on a dark map.
   ------------------------------------------------------------------------- */

.activity-map {
  position: relative;
}

.activity-map-caption {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 400; /* above Leaflet panes (400 is the tile pane) */
  margin: 0;
  /* Wide enough that the sentence sets on one or two lines. The icon-language
     layer decorates role="status" with an info glyph and makes this a flex row,
     so the glyph is budgeted for here rather than fought with text-align. */
  /* Shrink-to-fit on an absolutely positioned flex box collapses this to the
     longest word, so the width is stated and then capped. */
  width: max-content;
  max-width: min(46ch, calc(100% - 2rem));
  align-items: center;
  padding: 0.75rem 1rem;
  border-radius: var(--pw-radius-control, 12px);
  border: 1px solid var(--pw-border, rgba(20, 20, 15, .14));
  background: var(--pw-surface, #fff);
  box-shadow: var(--pw-shadow-1);
  color: var(--pw-text-muted, #6b6862);
  font-size: 14px;
  line-height: 1.45;
  text-wrap: pretty;
  pointer-events: none;
}

/* Old Android: color-mix()/backdrop-filter are unsupported, and a caption over
   map tiles is exactly where a missing background would become unreadable. */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .activity-map-caption {
    background: #ffffff;
    color: #3f3f46;
    border-color: rgba(0, 0, 0, .2);
  }
}

/* ---------------------------------------------------------------------------
   18. Cascading filters — Area depends on Client
   ---------------------------------------------------------------------------
   The Daily Manning / Staffing filter bar offered one option per area in the
   whole company. At production volume that is a flat dropdown of well over a
   thousand entries: impossible to scan and slow to open on the handsets the
   team actually uses. Area is now populated from the chosen client, and states
   why it is empty rather than just appearing broken.
   ------------------------------------------------------------------------- */

#hr-filterbar label {
  min-width: 0;
}

.filter-hint {
  display: block;
  margin-top: 0.25rem;
  font-size: 14px;
  line-height: 1.35;
  color: var(--pw-text-muted, #6b6862);
}

#hr-filterbar select:disabled {
  opacity: 1;              /* the hint carries the meaning, not a faded control */
  color: var(--pw-text-muted, #6b6862);
  background: var(--pw-surface-sunken, rgba(20, 20, 15, .04));
  cursor: not-allowed;
}

@supports not (color: color-mix(in srgb, red 50%, blue)) {
  #hr-filterbar select:disabled {
    background: #f1f1ef;
    color: #52525b;
    border: 1px solid #c7c7c2;
  }
}

/* ---------------------------------------------------------------------------
   19. Bottom dock labels win their own colour
   ---------------------------------------------------------------------------
   Defect: every inactive destination label in the compact dock rendered at
   #6b6862 — the warm muted body tone — on the #0b2037 dock. That is 2.96:1 at
   13px, below the 4.5:1 the text needs, and it was the most-read text in the
   product on the cheapest handsets.

   Cause is specificity, not cascade order. postwatch-v2.css sets
   `.bottom-nav a { color: var(--text-muted) }` at (0,1,1); section 2 above
   sets `.pw4-bottom-item` at (0,1,0), so the older rule won even though it
   loads first. The selectors below carry (0,2,0) or higher and name the label
   span directly, because the label is the element that actually paints.

   #b9c9da on #0b2037 is 9.6:1. The active item keeps its dark-on-white pill.
   ------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .pw4-bottom-nav .pw4-bottom-item,
  .bottom-nav .pw4-bottom-item,
  .pw4-bottom-nav .pw4-bottom-item > span,
  .bottom-nav .pw4-bottom-item > span {
    color: #b9c9da;
  }

  /* The active destination sits on a light pill, so it takes the dock's own
     navy for contrast against the pill rather than against the dock. */
  .pw4-bottom-nav .pw4-bottom-item.is-active,
  .bottom-nav .pw4-bottom-item.is-active,
  .pw4-bottom-nav .pw4-bottom-item.is-active > span,
  .bottom-nav .pw4-bottom-item.is-active > span {
    color: #0b2037;
  }
}

/* Old Android resolves neither color-mix() nor the newer tokens; state the
   dock colours literally so the labels never fall back to the body tone. */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  @media (max-width: 767px) {
    .pw4-bottom-nav .pw4-bottom-item,
    .bottom-nav .pw4-bottom-item,
    .pw4-bottom-nav .pw4-bottom-item > span,
    .bottom-nav .pw4-bottom-item > span {
      color: #c9d8e6;
    }

    .pw4-bottom-nav .pw4-bottom-item.is-active,
    .bottom-nav .pw4-bottom-item.is-active,
    .pw4-bottom-nav .pw4-bottom-item.is-active > span,
    .bottom-nav .pw4-bottom-item.is-active > span {
      color: #0b2037;
    }
  }
}

/* ---------------------------------------------------------------------------
   20. Form controls hold the 16px floor
   ---------------------------------------------------------------------------
   Defect: the Concerns and Incidents filter selects rendered at 15px from
   `.pwc3-filter-select select` (0,2,1) in postwatch-cases-v3.css, which
   outranks responsive-v5's `:where(input, select, textarea)` — :where()
   contributes no specificity, so that safety net loses to any real selector.

   Under 16px, iOS Safari zooms the page on focus and does not zoom back, so a
   coordinator filtering concerns on a phone is left in a magnified layout.
   AGENTS.md sets the same floor.
   ------------------------------------------------------------------------- */

.pwc3-filter-select select,
.pwc3 .pwc3-filter-select select,
.pwc3 :where(input:not([type="checkbox"]):not([type="radio"]):not([type="file"]), select, textarea) {
  font-size: max(16px, 1rem);
}

/* ---------------------------------------------------------------------------
   21. Secondary captions hold the 14px floor
   ---------------------------------------------------------------------------
   The activation queue's supporting line ("Newest requests first…") rendered
   at 13.1px. Meaningful metadata is 14px minimum — this line tells a reviewer
   what ordering they are looking at and that contact details are masked, which
   is not decoration.
   ------------------------------------------------------------------------- */

.pwaa-queue__list > header p {
  font-size: 14px;
  line-height: 1.45;
}

/* ---------------------------------------------------------------------------
   22. Leaflet controls meet the product's touch target
   ---------------------------------------------------------------------------
   Leaflet ships 30x30 zoom buttons. The product's floor is 44x44, and this map
   is used one-handed in the field. Sizing the anchor rather than the bar keeps
   Leaflet's own layout maths intact.

   The zoom anchors carry href="#"; that is Leaflet's markup and it calls
   preventDefault, so no navigation happens. It is left alone rather than
   rewritten, because replacing the anchors breaks Leaflet's keyboard handling.
   ------------------------------------------------------------------------- */

.activity-map .leaflet-control-zoom a,
.activity-map .leaflet-bar a {
  width: 44px;
  height: 44px;
  min-width: 44px;
  min-height: 44px;
  line-height: 44px;
  font-size: 20px;
}

.activity-map .leaflet-touch .leaflet-bar a {
  width: 44px;
  height: 44px;
  line-height: 44px;
}

/* The attribution is a licence requirement and stays, but it should not be the
   smallest text on the page by a wide margin. */
.activity-map .leaflet-control-attribution {
  font-size: 12px;
  padding: 2px 6px;
}

.activity-map .leaflet-control-attribution a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   23. Draft evidence is a preparation check, not the headline
   ---------------------------------------------------------------------------
   The automated draft opened with five equal-weight tiles — record coverage,
   missing manning records, guard gap, open incidents, open concerns — above the
   document itself. That is internal telemetry framing a client deliverable as a
   dashboard, and it is the reason those drafts read as noise.

   The numbers stay, because the preparer needs them to decide whether the draft
   is fit to send. They now sit after the content, under a heading that says
   what they are. postwatch-reports-v3.css grids `.draft-evidence` itself, so
   that is reset here and the grid moves to the inner wrapper.
   ------------------------------------------------------------------------- */

.draft-evidence {
  display: block;
  margin-top: 1.25rem;
  padding-top: 0.875rem;
  border-top: 1px solid var(--pw-border, #e8e6e0);
}

.draft-evidence__title {
  margin: 0 0 0.625rem;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--pw-text-muted, #6b6862);
}

.draft-evidence__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 8px;
}

.draft-evidence__grid > div {
  min-height: 78px;
  padding: 11px;
  border: 1px solid var(--pw-border, #e8e6e0);
  border-radius: 12px;
  background: var(--pw-surface-sunken, #f7f6f3);
}

.draft-evidence__grid strong,
.draft-evidence__grid span { display: block; }
.draft-evidence__grid strong { font-size: 1.1rem; font-variant-numeric: tabular-nums; }
.draft-evidence__grid span { margin-top: 2px; font-size: 14px; color: var(--pw-text-muted, #6b6862); }

@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .draft-evidence { border-top: 1px solid #c7c7c2; }
  .draft-evidence__grid > div { border: 1px solid #c7c7c2; background: #f7f6f3; }
}

/* ---------------------------------------------------------------------------
   24. The mobile dock sits on the edge, and its pill is centred
   ---------------------------------------------------------------------------
   Two defects, both read by a person as "weird extra space at the bottom".

   First, responsive-v5 floats the dock with `inset: auto max(10px, safe-area)`
   on all four sides. On a handset with no home indicator that leaves a 10px
   band of page background under the bar on every route — 216 of them in the
   sweep. A five-destination bar with visible labels is a tab bar, not a
   floating pill, so it belongs on the edge.

   Second, the active destination's pill measured 7px from the top of the dock
   and 3px from the bottom: the bar is 72px, the pill 62px, and the padding was
   not splitting evenly. Asymmetry that small still reads as "off" without
   being nameable.

   The safe-area inset is still honoured — on a device with a home indicator the
   dock grows downward into it rather than hovering above it.
   ------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .pw4-bottom-nav {
    inset: auto 0 0 0;
    min-height: calc(66px + env(safe-area-inset-bottom, 0px));
    /* 5px + the 1px top border = the 6px on the other three sides, so the
       pill sits with equal space above and below. */
    padding: 5px max(6px, env(safe-area-inset-left, 0px))
             calc(6px + env(safe-area-inset-bottom, 0px))
             max(6px, env(safe-area-inset-right, 0px));
    /* A bar on the edge keeps its top corners and squares off the bottom. */
    border-radius: 20px 20px 0 0;
    border-width: 1px 0 0 0;
    align-items: center;
  }

  /* Equal space above and below the pill. */
  .pw4-bottom-nav .pw4-bottom-item {
    min-height: 54px;
    align-self: center;
  }
}

/* Content must clear the dock. Measured from the bar, not guessed. */
@media (max-width: 767px) {
  .pw4-shell-main,
  .pw4-canvas,
  main > .pwc-page,
  main > .page,
  #app-root {
    padding-bottom: calc(78px + env(safe-area-inset-bottom, 0px));
  }
}

@supports not (color: color-mix(in srgb, red 50%, blue)) {
  @media (max-width: 767px) {
    .pw4-bottom-nav { background: #0b2037; border-top: 1px solid #33475f; }
  }
}

/* ---------------------------------------------------------------------------
   25. Staffing: an inspector card is readable again
   ---------------------------------------------------------------------------
   Two defects on /hr, both from rendering an entire workload into one card.

   The card's meta line joined every distinct area name with " · ". With the
   unassigned backlog that was 374 names in a single run-on sentence, which is
   why it read as garbage next to the "?" avatar. It now names three and counts
   the rest.

   The card then rendered one row per queue item — 374 of them, a card over
   70,000px tall, which buried every other inspector below it. Rows are capped
   at 25 with the rest one tap away.
   ------------------------------------------------------------------------- */

.hr-ins-card__meta {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 14px;
  line-height: 1.45;
  color: var(--pw-text-muted, #6b6862);
  overflow-wrap: anywhere;
}

.hr-ins-card__more {
  display: block;
  width: 100%;
  min-height: 44px;
  margin: 0;
  padding: 0.625rem 1rem;
  border: 0;
  border-top: 1px solid var(--pw-border, #e8e6e0);
  border-radius: 0 0 var(--pw-radius-card, 16px) var(--pw-radius-card, 16px);
  background: var(--pw-surface-sunken, #f7f6f3);
  color: var(--pw-text, #14140f);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
  .hr-ins-card__more:hover { background: var(--pw-surface, #fff); }
}

.hr-ins-card__more:active { transform: scale(.99); }

@media (prefers-reduced-motion: reduce) {
  .hr-ins-card__more:active { transform: none; }
}

/* The need column: the number and its label share a column, so they centre on
   each other rather than the label spilling past the number's box. */
.hr-ins-row__need {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 5.5rem;
  text-align: center;
}

.hr-ins-row__need-label,
.hr-ins-row__dep {
  max-width: 100%;
  font-size: 14px;
  line-height: 1.3;
  text-align: center;
  overflow-wrap: anywhere;
}

@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .hr-ins-card__more { background: #f1f1ef; color: #14140f; border-top: 1px solid #c7c7c2; }
}

/* ---------------------------------------------------------------------------
   26. A sentence is not a flex row
   ---------------------------------------------------------------------------
   The Staffing summary reads "Verified shortage: 15 guards across 14 areas.
   359 daily manning records need completion or review…" with the figures in
   <strong>. The icon-language layer marks the line as .pwil4-feedback, which
   is `display: flex`, and the line itself is `flex-wrap: nowrap` — so every
   <strong> became its own flex item and shrank to min-content. On a 375px
   screen that rendered as narrow vertical columns of two and three characters:
   "Ve / rifi / ed / sh / or / ta / ge".

   A sentence has to flow as text. The line becomes a block and the status icon
   sits inline at its start, which also lets the numbers stay emphasised
   without becoming layout.
   ------------------------------------------------------------------------- */

.hr-summary__line {
  display: block;
  font-size: 15px;
  line-height: 1.55;
  text-wrap: pretty;
}

.hr-summary__line > .pwil4-feedback-icon {
  display: inline-grid;
  vertical-align: -3px;
  margin-right: 0.375rem;
}

.hr-summary__line strong { font-variant-numeric: tabular-nums; }

.hr-summary {
  display: block;
}

/* Any other feedback line that carries more than a single run of text is a
   sentence too. Let it wrap rather than shrink its parts into columns. */
.pwil4-feedback {
  flex-wrap: wrap;
}

.pwil4-feedback > :not(.pwil4-feedback-icon) {
  min-width: 0;
  flex: 1 1 12rem;
}

/* ---------------------------------------------------------------------------
   27. Staffing rows are scannable on a phone
   ---------------------------------------------------------------------------
   Each queue row measured 187px tall at 375px wide: the three status pills
   rendered at 17px and stacked into a 112px block, and the need column was
   pinned to 74px so "No saved entry" wrapped onto three lines. Twenty-five
   rows became ten screens of scrolling for information that fits in three.

   Pills carry status, so they stay — at the operational 14px floor, on one
   line each, with the need column wide enough for its own words.
   ------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .hr-ins-row {
    grid-template-columns: 4px minmax(0, 1fr) 96px;
    align-items: center;
  }

  .hr-ins-row__where {
    font-size: 15px;
    line-height: 1.35;
  }

  .hr-ins-row__tags {
    gap: 4px;
    margin-top: 4px;
    font-size: 14px;
  }

  .hr-ins-row__tags > * {
    padding: 2px 8px;
    font-size: 14px;
    line-height: 1.35;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
  }

  .hr-ins-row__need { min-width: 0; }
  .hr-ins-row__need-num { font-size: 22px; line-height: 1.1; }
  .hr-ins-row__need-label,
  .hr-ins-row__dep { font-size: 14px; line-height: 1.3; }
}

/* ---------------------------------------------------------------------------
   28. Containers that could not hold their contents
   ---------------------------------------------------------------------------
   Three separate overflows found by walking every route at 390/834/1440.

   The Staffing inspector card head laid out avatar + name + phone + badge in a
   row that could not wrap, so at 356px the content measured 407px and the
   badge was pushed out of the card.

   The Assistant composer's send button escaped its row by 16px on a phone: the
   row could not shrink its text field, so the button was pushed past the edge.

   Batch manning's sticky save bar sat on top of the last row's "Same as
   yesterday" control, making the final area unreachable without scrolling past
   it.
   ------------------------------------------------------------------------- */

.hr-ins-card__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.625rem;
}

.hr-ins-card__info {
  flex: 1 1 12rem;
  min-width: 0;
}

.hr-ins-card__name { overflow-wrap: anywhere; }

.hr-ins-card__badge {
  flex: 0 1 auto;
  max-width: 100%;
  white-space: normal;
}

/* The composer must be able to shrink its field before it pushes the button
   out. min-width:0 is what lets a flex item narrow below its content. */
.pwc-composer__row,
.pwc-composer__row--assistant {
  flex-wrap: wrap;
  gap: 0.5rem;
}

.pwc-composer__row > :where(input, textarea, label, .pwc-field),
.pwc-composer__row--assistant > :where(input, textarea, label, .pwc-field) {
  flex: 1 1 8rem;
  min-width: 0;
}

.pwc-composer__row > button,
.pwc-composer__row--assistant > button { flex: 0 0 auto; }

.pwc4-toolbar-actions { flex-wrap: wrap; gap: 0.5rem; min-width: 0; }

/* Clear the sticky save bar so the last row stays reachable. */
.bm-table-wrap { padding-bottom: 0.5rem; }
.bm-page > .bm-table-wrap:last-of-type { margin-bottom: 0.25rem; }
.bm-table tbody tr:last-child { scroll-margin-bottom: 6rem; }

/* ---------------------------------------------------------------------------
   29. The Assistant composer's Send button fits its column
   ---------------------------------------------------------------------------
   The composer row is a grid, not a flex row. Below 720px postwatch-v2.css
   sets `.pwc-composer .pwc-composer__row--assistant` to
   `minmax(0,1fr) 52px`, while the Send button carries a 68px min-width for its
   label — so on a phone the button overflowed its own column by 16px and sat
   past the composer's edge.

   That rule is (0,2,0), so this one matches it. The trailing column is sized
   to the button instead of to a guess, and Talk spans the full width above the
   field rather than competing with it for a track.
   ------------------------------------------------------------------------- */

.pwc-composer .pwc-composer__row--assistant,
.pwc-composer .pwc-composer__row {
  align-items: end;
}

@media (max-width: 767px) {
  /* Three rules compete for this track list: postwatch-v2.css at (0,2,0),
     conversations-v4 at (0,3,0), and the base inline sheet. Rather than tie
     and depend on load order, this one outranks all of them. */
  body.pw-authenticated .pwc4-enhanced .pwc-composer .pwc-composer__row--assistant,
  body.pw-authenticated .pwc4-enhanced .pwc-composer__row--assistant,
  .pwc-composer .pwc-composer__row--assistant {
    grid-template-columns: minmax(0, 1fr) minmax(68px, auto);
  }

  body.pw-authenticated .pwc4-enhanced .pwc-composer__row--assistant > .pwc-talk-button,
  .pwc-composer .pwc-composer__row--assistant > .pwc-talk-button {
    grid-column: 1 / -1;
  }
}

.pwc-composer .pwc-composer__row :where(textarea, input) {
  min-width: 0;
  width: 100%;
}

.pwc4-toolbar-actions { flex-wrap: wrap; gap: 0.5rem; min-width: 0; }

/* ---------------------------------------------------------------------------
   30. The daily check-in counters hold the touch floor
   ---------------------------------------------------------------------------
   index.html shrinks the manning wizard's +/− buttons to 42x42 below 480px to
   save room. They are the single most-tapped control in the product — an
   inspector uses them for every assigned area, every day, one-handed and often
   outdoors — and 42px is under the 44px floor AGENTS.md sets.

   44px costs 2px per button against the compact layout and keeps the target
   honest. Found only after the inspector's area scope was fixed, because
   before that their check-in never rendered at all.
   ------------------------------------------------------------------------- */

@media (max-width: 480px) {
  .mci-counter__up,
  .mci-counter__down {
    width: 44px;
    height: 44px;
    font-size: 1.3rem;
  }
}

/* ---------------------------------------------------------------------------
   31. Chat messages keep their own height
   ---------------------------------------------------------------------------
   Every message in every channel rendered clipped, with the next sender's name
   painted over the previous bubble. This is the "chat is cut" defect and it is
   not a scroll problem.

   .pwc-transcript is a flex column with a bounded height. A flex item's default
   `min-height: auto` normally stops it shrinking below its content — but
   conversations-v4 sets an explicit `min-height: 46px` on .pwc-message, which
   replaces that automatic minimum. With 34 messages in a 463px transcript,
   every item was squeezed to exactly 46px while its own grid rows still
   measured ~153px, so each bubble overflowed its box and the next message
   drew on top of it.

   flex-shrink: 0 restores the intent: messages keep their natural height and
   the transcript scrolls, which is what the scroll container was always for.
   ------------------------------------------------------------------------- */

.pwc-transcript > .pwc-message,
body.pw-authenticated .pwc-team.pwc4-enhanced .pwc-message {
  flex-shrink: 0;
  min-height: 0;
  height: auto;
}

/* ---------------------------------------------------------------------------
   32. Reports & Intelligence is a hub, not a stack
   ---------------------------------------------------------------------------
   The route stacked six unrelated jobs into 3.2 screens and named none of them,
   so nobody could tell which one they needed. Each is now a card that says what
   it is for and what is waiting in it, and opening one shows that job alone.

   Cards are sized for a thumb first and reflow to two and three columns as the
   window allows.
   ------------------------------------------------------------------------- */

.rh-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.75rem;
  margin: 0 0 1.25rem;
}

@media (min-width: 720px)  { .rh-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .rh-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.rh-card {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  grid-template-areas: "icon body" "icon status";
  align-items: start;
  gap: 0.25rem 0.875rem;
  min-height: 96px;
  padding: 1rem;
  border: 1px solid var(--pw-border, #e8e6e0);
  border-radius: var(--pw-radius-card, 16px);
  background: var(--pw-surface, #fff);
  color: var(--pw-text, #14140f);
  text-decoration: none;
  box-shadow: var(--pw-shadow-1);
}

.rh-card__icon {
  grid-area: icon;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--pw-surface-sunken, #f7f6f3);
  color: var(--pw-text-muted, #6b6862);
}

.rh-card__icon svg { width: 22px; height: 22px; }

.rh-card__body { grid-area: body; display: grid; gap: 0.125rem; min-width: 0; }
.rh-card__label { font-size: 1rem; font-weight: 700; line-height: 1.3; }

.rh-card__purpose {
  font-size: 14px;
  line-height: 1.45;
  color: var(--pw-text-muted, #6b6862);
  text-wrap: pretty;
}

.rh-card__status {
  grid-area: status;
  margin-top: 0.25rem;
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--pw-text, #14140f);
}

@media (hover: hover) and (pointer: fine) {
  .rh-card:hover { border-color: var(--pw-text-muted, #6b6862); box-shadow: var(--pw-shadow-2); }
}

.rh-card:active { transform: scale(.99); }

.rh-card:focus-visible {
  outline: 2px solid var(--pw-focus, #2563eb);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) { .rh-card:active { transform: none; } }

/* The way back, and the one line that says what this screen is for. */
.rh-back { display: inline-flex; min-height: 44px; align-items: center; margin-bottom: 0.5rem; }

.rh-lead {
  margin: 0 0 0.875rem;
  font-size: 15px;
  line-height: 1.5;
  color: var(--pw-text-muted, #6b6862);
  text-wrap: pretty;
}

@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .rh-card { border: 1px solid #c7c7c2; background: #ffffff; }
  .rh-card__icon { background: #f1f1ef; color: #52525b; }
}

/* [hidden] is only `display: none` from the UA sheet, so any author rule that
   sets display — `.par-panel { display: grid }` here — silently beats it and
   the "hidden" section stays on screen. State it for the sections the hub
   controls rather than relying on the attribute alone. */
.par-panel[hidden],
.intelligence-lane[hidden],
.reports-period[hidden],
.reports-layout[hidden],
.pwrs-panel[hidden],
.saved-reports[hidden] {
  display: none !important;
}

/* ---------------------------------------------------------------------------
   33. The conversation toolbar wraps instead of collapsing
   ---------------------------------------------------------------------------
   .pwc-toolbar is a two-column grid. On a phone the actions track resolved to
   0px, so .pwc4-toolbar-actions had zero width and its "Print Handoff" button
   hung 48px outside the toolbar — its whole width, sitting over the transcript.

   A channel title and its actions do not have to share one line on a 390px
   screen. The toolbar becomes a wrapping row: the title takes the width it
   needs, the actions drop beneath it and stay reachable.
   ------------------------------------------------------------------------- */

@media (max-width: 767px) {
  /* conversations-v4 sets this at (0,3,0) with
     `grid-template-columns: minmax(0,1fr) auto`. The title block filled the
     auto track, the 1fr collapsed to 0, and the actions in it had nowhere to
     go. Match that specificity rather than tie with it. */
  body.pw-authenticated .pwc4-enhanced .pwc-toolbar,
  .pwc-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 0.5rem 0.75rem;
  }

  body.pw-authenticated .pwc4-enhanced .pwc-toolbar > *,
  .pwc-toolbar > * { min-width: 0; }

  body.pw-authenticated .pwc4-enhanced .pwc4-toolbar-actions,
  .pwc4-toolbar-actions {
    flex: 1 1 100%;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    min-width: 0;
  }

  body.pw-authenticated .pwc4-enhanced .pwc4-toolbar-actions > *,
  .pwc4-toolbar-actions > * { flex: 0 0 auto; }
}
