/* =========================================================================
   Logro workspace overlay -- the light Logro brand (D-0214)
   -------------------------------------------------------------------------
   Loaded AFTER style.css on every page, but every workspace rule is scoped
   under `body.ws2-fullpage`, so it is inert outside the workspace shell.
   (Section 12 is the sign-in / partner-setup look, scoped under
   `body.auth-page`; it is separate and keeps its own treatment.)

   This overlay puts the conversation workspace on the light Logro brand
   (docs/reference/logro-brand-guide.md): a flat grey page, white panels with
   line borders, navy for the work (primary buttons, selected states), brand
   blue as the one accent (links, icons, focus edges), green and red for
   status, no orange anywhere, no gradients, no blur, no card shadows (only a
   floating layer -- a menu or a modal -- takes --shadow-float), 6px corners
   and the Figtree family. Every colour is a logro-brand.css token.

   It works by (1) remapping the ws2 CSS custom properties that every
   existing ws2 rule already consumes (the base set lives in style.css, "WS2
   FULLPAGE MODE"; this file adds the rest) and (2) restyling the components
   that carry their own colours. The file keeps its old name so the <link>
   in the shells did not change; rollback = remove that link (or set body
   without the ws2-fullpage class); nothing else references this file.
   ========================================================================= */

/* --- 1. Tokens this overlay adds (the base ws2 remap is in style.css) ---- */
body.ws2-fullpage {
  /* Primary fills are navy with white text (16:1). Brand blue is never a
     fill; --ws2-accent-text is the blue for text and links (5.3:1 on white,
     4.8:1 on the grey, 4.6:1 on the select tint). */
  --ws2-accent-fill: var(--navy);
  --ws2-on-accent: var(--canvas);
  --ws2-accent-text: var(--brand-blue);
  /* A control's own edge (fields, selects): 3.3:1 on white. */
  --ws2-control: var(--control);
  --ws2-elevated: var(--canvas); /* cards, composer, tables */
  /* Flat look: no blur, no specular edge; the rim is a plain line. */
  --ws2-blur: none;
  --ws2-specular: none;
  --ws2-rim: 0 0 0 1px var(--line);
  /* Attention ("waiting on you", flagged, pending approval): navy text and
     edge on the select tint. No orange or amber anywhere. */
  --ws2-highlight: var(--navy);
  --ws2-highlight-soft: var(--select);

  /* Ambient text colour for the whole shell, so anything that does not name
     its own colour reads as body text. */
  color: var(--ws2-text-primary);

  /* A flat grey page: no gradient, no aura. */
  background: var(--page) !important;
}

/* Form controls take the brand family, not the browser default. */
body.ws2-fullpage button,
body.ws2-fullpage input,
body.ws2-fullpage select,
body.ws2-fullpage textarea {
  font-family: var(--sans);
}

/* --- 2. Columns: flat panels with a line between them ------------------ */
body.ws2-fullpage .ws2-thread-list-panel {
  background: var(--ws2-bg-sidebar);
  border-right: 1px solid var(--ws2-border);
  box-shadow: none;
}
body.ws2-fullpage .ws2-canvas-panel {
  background: var(--ws2-bg-canvas);
  border-left: 1px solid var(--ws2-border);
  box-shadow: none;
}
body.ws2-fullpage .ws2-conversation-panel {
  background: var(--ws2-bg-content);
  box-shadow: none;
}

/* --- 3. Thread list items --------------------------------------------- */
/* The list is the grey --sub: a hovered row lifts to white, the open one is
   the select tint with a navy edge. */
body.ws2-fullpage .ws2-thread-item {
  border-radius: var(--radius);
}
body.ws2-fullpage .ws2-thread-item:hover {
  background: var(--canvas);
}
body.ws2-fullpage .ws2-thread-item-active,
body.ws2-fullpage .ws2-thread-item-active:hover {
  background: var(--ws2-active);
  box-shadow: inset 3px 0 0 var(--navy);
}

/* New-conversation button in the left header: the tinted secondary button,
   navy on hover. */
body.ws2-fullpage .ws2-new-thread-btn {
  background: var(--btn-tint) !important;
  color: var(--navy) !important;
  transition: all 0.12s ease !important;
}
body.ws2-fullpage .ws2-new-thread-btn:hover {
  background: var(--ws2-accent-fill) !important;
  color: var(--ws2-on-accent) !important;
}

/* --- 4. Message bubbles: flat, 6px corners, a line border -------------- */
/* Team / admin (incoming): the grey fill, left. */
body.ws2-fullpage .ws-message-team .ws-message-body,
body.ws2-fullpage .ws-message-admin .ws-message-body {
  background: var(--sub);
  border: 1px solid var(--ws2-border);
  border-radius: var(--radius);
}
/* Client / user (outgoing): the select tint, right. */
body.ws2-fullpage .ws-message-client .ws-message-body,
body.ws2-fullpage .ws-message-user .ws-message-body {
  background: var(--select);
  border: 1px solid var(--ws2-border);
  border-radius: var(--radius);
}

/* --- 5. Composer + inputs: white bar, control edge, navy send --------- */
body.ws2-fullpage .ws2-reply-bar {
  background: var(--canvas);
  border-top: 1px solid var(--ws2-border);
}
/* Round 2 fix: the "box" look moved from the textarea itself up to
   `.ws2-reply-input-row`, which is now the single rounded container
   holding attach + textarea + send (see the layout rules in style.css) --
   so this overlay must theme the ROW, not the textarea, or the textarea
   would repaint its own competing box on top and defeat the merge. The
   textarea stays transparent/borderless so it reads as part of the row. */
body.ws2-fullpage .ws2-reply-input-row {
  background: var(--ws2-elevated);
  border: 1px solid var(--ws2-control);
  box-shadow: none;
}
body.ws2-fullpage .ws2-reply-input-row .ws2-reply-textarea {
  /* One field, not a box in a box: out-specifies the generic textarea and
     .form-control rules below (both !important). */
  background: transparent !important;
  border: 1px solid transparent !important;
  box-shadow: none;
}
/* Send button: navy fill, white mark. */
body.ws2-fullpage .ws2-reply-submit {
  background: var(--ws2-accent-fill);
  color: var(--ws2-on-accent);
}
body.ws2-fullpage .ws2-reply-submit:hover {
  background: var(--navy-hover);
}
/* Attach button: ghost/quiet (no fill, no border) -- ghost until hover, so
   it never reads as competing with the navy send button beside it. */
body.ws2-fullpage .ws2-reply-attach-btn {
  background: transparent;
  border: none;
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .ws2-reply-attach-btn:hover {
  background: var(--sub);
  color: var(--ws2-text-primary);
}
/* Drag-drop overlay: blue edge on the select tint. */
body.ws2-fullpage .ws2-reply-drop-overlay {
  border-color: var(--ws2-accent);
  background: var(--select);
  color: var(--ws2-text-primary);
}
/* Drop zones honour the blue edge on hover/drag. */
body.ws2-fullpage .ws-drop-zone.ws2-dropzone:hover,
body.ws2-fullpage .ws-drop-zone.ws2-dropzone.ws-drag-over {
  border-color: var(--ws2-accent);
  background: var(--select);
}
/* Resize handle grab highlight. */
body.ws2-fullpage .ws2-resize-handle:hover,
body.ws2-fullpage .ws2-resize-handle.dragging {
  background: var(--ws2-accent);
}

/* --- 6. Avatars: neutralized (no override needed) ----------------------- */

/* --- 7. Canvas cards: white, line border, flat ------------------------ */
body.ws2-fullpage .ws2-canvas-slot {
  background: var(--ws2-elevated);
  border: 1px solid var(--ws2-border);
  box-shadow: none;
  border-radius: var(--radius);
}
body.ws2-fullpage .ws2-canvas-download-item a {
  color: var(--ws2-accent-text);
  background: var(--select);
  border: 1px solid var(--ws2-border);
  border-radius: var(--radius);
  padding: 4px 10px;
}

/* --- 8. Banners: attention is navy on the select tint ------------------ */
body.ws2-fullpage .ws2-flagged-banner {
  background: var(--ws2-highlight-soft);
  border: 1px solid var(--ws2-highlight);
  color: var(--ws2-highlight);
}
body.ws2-fullpage .ws2-pushback-banner {
  background: var(--select);
  border: 1px solid var(--ws2-border);
  border-radius: var(--radius);
  color: var(--ws2-text-primary);
}
body.ws2-fullpage .ws2-pushback-banner strong {
  color: var(--ws2-accent-text);
}
/* The tool prompt asks the client to answer in the chat, so it stays in view
   while the timeline sits scrolled to the latest message. The select tint is
   opaque, so messages do not show through as they scroll under it. */
body.ws2-fullpage #ws2-tool-tag-pushback-banner:not([hidden]) {
  position: sticky;
  top: 0;
  z-index: 2;
}

/* .alert-warn (2026-08-25 design-system audit, SHOULD-FIX finding #2): used
   by the benchmark + geo canvas summary fragments but never defined
   anywhere. Same attention treatment as .ws2-flagged-banner just above.
   Color set on the container so the unstyled <strong>/<p> children inherit
   it. */
body.ws2-fullpage .alert-warn {
  background: var(--ws2-highlight-soft);
  border: 1px solid var(--ws2-highlight);
  color: var(--ws2-highlight);
}

/* --- 9. Scrollbars: neutral greys from the line tokens ----------------- */
body.ws2-fullpage ::-webkit-scrollbar {
  width: 9px;
  height: 9px;
}
body.ws2-fullpage ::-webkit-scrollbar-thumb {
  background: var(--line);
  border-radius: 8px;
}
body.ws2-fullpage ::-webkit-scrollbar-thumb:hover {
  background: var(--control);
}

/* --- 10. Reply-composer drop zone + file-attachment pills ------------- */
/* These classes use unscoped root light-theme tokens; pin them to the
   workspace set (grey tile, control-weight dashed edge). */
body.ws2-fullpage .ws-drop-zone,
body.ws2-fullpage .ws2-dropzone {
  background: var(--sub);
  border: 1.5px dashed var(--ws2-control);
  color: var(--ws2-text-secondary);
  border-radius: var(--radius);
}
body.ws2-fullpage .ws-drop-zone:hover,
body.ws2-fullpage .ws2-dropzone:hover,
body.ws2-fullpage .ws2-dropzone.ws-drag-over {
  background: var(--select);
  border-color: var(--ws2-accent);
  color: var(--ws2-accent-text);
}
body.ws2-fullpage .ws-file-item {
  background: var(--sub);
  border: 1px solid var(--ws2-border);
  color: var(--ws2-text-secondary);
  border-radius: var(--radius);
}
body.ws2-fullpage .ws-file-item-name {
  color: var(--ws2-text-primary);
}
body.ws2-fullpage .ws-file-item-size {
  color: var(--ws2-text-tertiary);
}
body.ws2-fullpage .ws-file-item-remove {
  color: var(--ws2-text-tertiary);
  background: transparent;
}
body.ws2-fullpage .ws-file-item-remove:hover {
  color: var(--ws2-text-primary);
}

/* --- 11a. Thread-list Q&A type chip ------------------------------------ */
/* .ws2-legacy-qa-chip: the original override here was fully shadowed by
   the identical-specificity §13 "Legacy QA chip in thread header" rule
   below (same selector, later in source order, both !important) -- it
   never actually applied. Removed as dead CSS (2026-07-21 QA pass);
   §13 remains the single source of truth for this selector. */

/* --- 11b. "N waiting on you" pill: navy on the select tint ------------- */
body.ws2-fullpage .ws2-filter-link.ws2-awaiting-pill {
  background: var(--ws2-highlight-soft);
  border: 1px solid var(--ws2-highlight);
  border-radius: var(--radius-tag);
  color: var(--ws2-highlight);
}
body.ws2-fullpage .ws2-filter-link.ws2-awaiting-pill:hover {
  background: var(--btn-tint);
  color: var(--ws2-highlight);
  text-decoration: none;
}

/* --- 12. Auth pages: glass login card (was §11) ----------------------- */
body.auth-page {
  /* The dark-shell text/link tokens the sign-in pages use (the full set
     lives on body.ws2-fullpage above, which the sign-in shell does not
     carry). Same values. */
  --ws2-text-primary: #ececee;
  --ws2-text-tertiary: rgba(236, 236, 238, 0.72);
  --ws2-accent-text: #8cc0ea;
  --ws2-elevated: rgba(68, 68, 78, 0.58);
  --ws2-blur: blur(56px) saturate(140%);
  --ws2-specular: inset 0 1px 0 rgba(255, 255, 255, 0.14);
  --ws2-rim: 0 0 0 1px rgba(0, 0, 0, 0.35);
  background:
    radial-gradient(
      1100px 760px at 12% -8%,
      rgba(74, 120, 190, 0.1),
      transparent 60%
    ),
    radial-gradient(
      950px 680px at 104% 108%,
      rgba(214, 120, 74, 0.06),
      transparent 55%
    ),
    linear-gradient(180deg, #313136 0%, #2b2b30 52%, #262629 100%) !important;
  background-attachment: fixed;
  color: #ececee;
}

body.auth-page .auth-card h1 {
  color: #ececee;
}
body.auth-page .auth-form label {
  color: rgba(236, 236, 238, 0.72);
}
body.auth-page .auth-card p {
  color: rgba(236, 236, 238, 0.72);
}

body.auth-page .auth-card {
  background: rgba(44, 44, 52, 0.65);
  -webkit-backdrop-filter: var(--ws2-blur);
  backdrop-filter: var(--ws2-blur);
  border: 1px solid rgba(255, 255, 255, 0.09);
  box-shadow:
    var(--ws2-specular),
    0 8px 48px rgba(0, 0, 0, 0.35),
    var(--ws2-rim);
}

body.auth-page .auth-form input,
body.auth-page .auth-form select,
body.auth-page .auth-form textarea {
  /* background-color, not background, so the SVG chevron from style.css survives */
  background-color: rgba(68, 68, 78, 0.58);
  border: 1px solid rgba(255, 255, 255, 0.09);
  color: #ececee;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
body.auth-page .auth-form input::placeholder,
body.auth-page .auth-form textarea::placeholder {
  color: rgba(236, 236, 238, 0.35);
}
/* Gray out the "—" placeholder when no real option is selected */
body.auth-page .auth-form select:has(option[value=""]:checked) {
  color: rgba(236, 236, 238, 0.35);
}
body.auth-page .auth-form input:focus,
body.auth-page .auth-form textarea:focus {
  border-color: #5b9bd5;
  box-shadow:
    0 0 0 3px rgba(91, 155, 213, 0.18),
    inset 0 1px 0 rgba(255, 255, 255, 0.06);
  outline: none;
}

body.auth-page .btn-primary {
  background: #5b9bd5;
  color: #0f1620;
  border: none;
}
body.auth-page .btn-primary:hover {
  background: #4a86c4;
}

/* Setup submit button: larger text for a full-width action control. It keeps
   the dark-on-blue pairing of the login button above: this used to override
   to white, which is 2.96:1 on the blue fill (WCAG 1.4.3). */
body.auth-page .setup-intake-form .btn-primary {
  font-size: var(--text-base);
  letter-spacing: 0.025em;
  min-height: 52px;
}

/* Opaque on purpose: the base header is position:sticky, so on any auth-page
   long enough to scroll (the partner /setup form) a translucent bar let the
   form show through underneath it. #2b2b31 is the old 55% tint pre-composited
   over the page's top background, so the look is unchanged at rest. */
body.auth-page header {
  background: #2b2b31;
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
}
body.auth-page header a,
body.auth-page header .logo {
  color: #ececee;
}

/* This shell's nav has just the logo, no links/user menu -- the shared
   `nav { max-width:1120px; margin:0 auto }` rule (written for the
   multi-item platform header) centers that single item as a block on wide
   viewports, reading as a floating centered logo instead of a pinned
   top-left brand mark. Un-cap and left-align here only; the platform nav
   elsewhere is untouched. */
body.auth-page nav {
  max-width: none;
  margin: 0;
  justify-content: flex-start;
}

body.auth-page footer {
  color: rgba(236, 236, 238, 0.4);
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}

body.auth-page .auth-error {
  background: rgba(201, 59, 59, 0.15);
  border-color: rgba(201, 59, 59, 0.3);
  color: #f99;
}
body.auth-page .auth-info {
  background: rgba(26, 138, 92, 0.15);
  border-color: rgba(26, 138, 92, 0.3);
  color: #6efab2;
}

/* Partner SFTP setup form elements in dark mode (2026-09-22: pruned down
   to only the surviving simplified-form classes -- direction chooser and
   submit note. See claude/memory/project_logro_partner_sftp_setup_guide.md
   before restoring the removed chip/radio/connect-block/details rules.
   2026-10-01: re-added overrides for the direction-scoped detail blocks,
   section titles, hints, and tier tags that the one-and-done form added). */
body.auth-page .setup-submit-note {
  background: rgba(68, 68, 78, 0.35);
  border-color: rgba(255, 255, 255, 0.08);
  color: rgba(236, 236, 238, 0.76);
}

body.auth-page .setup-section-title {
  color: #ececee;
  border-top-color: rgba(255, 255, 255, 0.09);
}
body.auth-page .setup-hint {
  color: rgba(236, 236, 238, 0.72);
}
body.auth-page .setup-hint code {
  color: rgba(236, 236, 238, 0.78);
}
body.auth-page .setup-tier {
  color: rgba(236, 236, 238, 0.72);
}
body.auth-page .setup-intake-form .setup-choice {
  color: #ececee;
}

/* Logro IP widget (masked + Show/Copy) on the dark card. */
body.auth-page .setup-ip-label {
  color: rgba(236, 236, 238, 0.72);
}
body.auth-page .setup-ip-value {
  background: rgba(68, 68, 78, 0.58);
  border-color: rgba(255, 255, 255, 0.09);
  color: #ececee;
}
body.auth-page .setup-intake-form .setup-ip-btn {
  border-color: rgba(255, 255, 255, 0.16);
  color: rgba(236, 236, 238, 0.82);
}
body.auth-page .setup-intake-form .setup-ip-btn:hover {
  border-color: #5b9bd5;
  color: #7ab4e3;
}

/* Direction chooser ("How will the files flow?") -- legend reads
   var(--text-secondary) directly, same gap as every other <legend>/<span>
   label on this page. */
body.auth-page .setup-direction-group legend,
body.auth-page .setup-field-group legend {
  color: rgba(236, 236, 238, 0.72);
}

/* direction-option selectable control sets color: var(--text) and
   border: 1px solid var(--border) in style.css -- near-black text and a
   light border on the dark card. Give it the same dark surface treatment
   as .setup-submit-note above, and raise the checked-state accent tint
   from style.css's 0.08 alpha (tuned for a light background) to 0.22 so
   selected vs. unselected stays obvious at a glance against the dark
   card. */
body.auth-page .setup-direction-option {
  color: #ececee;
  border-color: rgba(255, 255, 255, 0.16);
  background: rgba(68, 68, 78, 0.5);
}
body.auth-page .setup-direction-option:hover {
  border-color: rgba(255, 255, 255, 0.3);
}
body.auth-page .setup-direction-option:has(input:checked) {
  border-color: #5b9bd5;
  background: rgba(91, 155, 213, 0.16);
  box-shadow: 0 0 0 1px #5b9bd5;
}
body.auth-page .setup-direction-desc {
  color: rgba(236, 236, 238, 0.72);
}

body.auth-page .auth-footer-links {
  border-top-color: rgba(255, 255, 255, 0.09);
}
body.auth-page .auth-footer-links a {
  color: #5b9bd5;
}
body.auth-page .auth-footer-links a:hover {
  color: #7ab4e3;
}

/* --- 13. Tool badge + thread header elements ------------------------------ */
body.ws2-fullpage .ws2-tool-badge {
  background: var(--select) !important;
  border: 1px solid var(--ws2-border) !important;
  color: var(--ws2-accent-text) !important;
}

/* Canvas job-status chip: the 3-state indicator (In Progress / Needs Input /
   Resolved) that replaced the old ticket stepper/pill on the Canvas panel.
   In progress is the blue accent on the select tint, needs input is the
   navy attention edge, resolved is green. */
body.ws2-fullpage .ws2-canvas-state-chip-in-progress {
  background: var(--select) !important;
  color: var(--brand-blue) !important;
}
body.ws2-fullpage .ws2-canvas-state-chip-needs-input {
  background: var(--canvas) !important;
  color: var(--ws2-highlight) !important;
}
body.ws2-fullpage .ws2-canvas-state-chip-resolved {
  background: var(--green-tint) !important;
  color: var(--green) !important;
}

/* Legacy QA chip in thread header */
body.ws2-fullpage .ws2-legacy-qa-chip {
  background: var(--tile) !important;
  border: 1px solid var(--ws2-border) !important;
  color: var(--ws2-text-secondary) !important;
}

/* Feedback/question tags in message headers */
body.ws2-fullpage .ws2-feedback-tag,
body.ws2-fullpage .ws2-question-tag,
body.ws2-fullpage .ws2-update-tag {
  background: var(--select) !important;
  border: 1px solid var(--ws2-border) !important;
  color: var(--ws2-accent-text) !important;
  border-radius: var(--radius-tag) !important;
  /* 9px -> 11px (2026-08-25 design-system audit, finding #8): 9px was
     off-scale/illegible compared to the rest of the UI's small-label
     convention (.ws2-canvas-slot-label uses 0.7rem = 11.2px). !important
     dropped: this rule is body.ws2-fullpage-scoped (0,2,1) which already
     outranks the plain-class base rule in style.css (0,1,0) on
     specificity alone, so !important was never needed for font-size here. */
  font-size: var(--text-sm);
  letter-spacing: 0.05em !important;
  text-transform: uppercase !important;
}

/* --- 14. Canvas panel: buttons + inputs ------------------------------------- */
/* Secondary buttons: the tinted brand secondary (light navy tint, no border
   colour; the transparent border keeps the button the same size). */
body.ws2-fullpage button.btn-secondary {
  background: var(--btn-tint) !important;
  border: 1px solid transparent !important;
  color: var(--navy) !important;
}
body.ws2-fullpage button.btn-secondary:hover {
  background: var(--btn-tint-hover) !important;
  color: var(--navy) !important;
}

/* Text input field in link job form */
body.ws2-fullpage input[type="text"],
body.ws2-fullpage input[type="email"],
body.ws2-fullpage input[type="number"],
body.ws2-fullpage input[type="password"],
body.ws2-fullpage input[type="search"],
body.ws2-fullpage textarea {
  background: var(--canvas) !important;
  border: 1px solid var(--ws2-control) !important;
  color: var(--ws2-text-primary) !important;
}
body.ws2-fullpage input::placeholder {
  color: var(--ws2-text-tertiary) !important;
}
/* Focus: a navy edge; the keyboard ring (box-shadow) comes from the shell's
   own input:focus-visible rule in style.css. */
body.ws2-fullpage input:focus,
body.ws2-fullpage textarea:focus {
  border-color: var(--navy) !important;
  outline: none !important;
}

/* Form control style normalization inside ws2 */
body.ws2-fullpage .form-control {
  background: var(--canvas) !important;
  border: 1px solid var(--ws2-control) !important;
  color: var(--ws2-text-primary) !important;
}
body.ws2-fullpage .form-control::placeholder {
  color: var(--ws2-text-tertiary) !important;
}
body.ws2-fullpage .form-control:focus {
  border-color: var(--navy) !important;
  outline: none !important;
}

/* --- 14-tokens. ER-U15 / UX-15: one token set for the canvas controls ------
   Three canvas controls once resolved the unscoped light-shell tokens
   (--bg, --text, --border, --bg-elevated, --text-secondary, --text-muted)
   instead of the workspace's own set. The workspace is on the light brand
   now, but it still keeps ONE token set (--ws2-*, mapped to the brand) so a
   control cannot drift from the panel it sits in:
   - <select> pickers (geo census/roster, disruption, proposal): style.css
     `.field select` paints --bg, --text and --border.
   - <a class="btn btn-secondary"> (View Interactive Map): the override above
     is `button.btn-secondary` only, so the link variant kept --bg-elevated /
     --text-secondary.
   - Feedback textarea placeholder: --text-muted at --text-base, larger than
     the canvas's --text-sm body copy.
   - The pickers also ran at the light shell's --text-base (49px tall next
     to --text-sm labels), and style.css's chevron image is the light
     shell's --text-muted grey.
   ws2 tokens only, with one documented exception: the chevron. As in
   style.css's own chevron, custom properties cannot resolve inside a
   data-URI SVG, so it carries the resolved --ink-2 of logro-brand.css (#444e62
   = rgb(68,78,98); keep in sync, a test pins it). A token-coloured gradient
   caret was tried and rejected: the static a11y gate (rightly, worst case)
   reads gradient stops as the text's backdrop. */
body.ws2-fullpage .field select {
  background-color: var(--ws2-elevated);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M2.5 4.5L6 8L9.5 4.5' stroke='rgb(68,78,98)' stroke-opacity='1' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-position: right 12px center;
  border: 1px solid var(--ws2-control);
  color: var(--ws2-text-primary);
  color-scheme: light;
  font-size: var(--text-sm);
  min-height: var(--control-h-sm);
  padding: var(--sp-2) 36px var(--sp-2) var(--sp-3);
}
body.ws2-fullpage .field select:focus {
  border-color: var(--ws2-accent);
}
/* Thread-list tool pills: white pill with a line, navy-filled when active
   (aria-current), using the contrast-checked accent tokens. */
body.ws2-fullpage .ws2-tool-pill {
  background: var(--ws2-elevated);
  border-color: var(--ws2-border);
  border-radius: var(--radius);
  color: var(--ws2-text-primary);
}
body.ws2-fullpage .ws2-tool-pill:hover {
  background: var(--btn-tint);
}
body.ws2-fullpage .ws2-tool-pill[aria-current="true"] {
  background: var(--ws2-accent-fill);
  border-color: var(--ws2-accent-fill);
  color: var(--ws2-on-accent);
}
body.ws2-fullpage .ws2-tool-pill:focus-visible {
  outline: 2px solid var(--ws2-accent-text);
  outline-offset: 2px;
}
body.ws2-fullpage a.btn-secondary {
  background: var(--btn-tint);
  border: 1px solid transparent;
  color: var(--navy);
}
body.ws2-fullpage a.btn-secondary:hover {
  background: var(--btn-tint-hover);
  color: var(--navy);
}
body.ws2-fullpage .ws2-canvas-repricing-fb-form textarea,
body.ws2-fullpage .ws2-canvas-repricing-fb-reply-form textarea {
  font-size: var(--text-sm);
  line-height: 1.5;
}
body.ws2-fullpage textarea::placeholder {
  color: var(--ws2-text-tertiary);
}

/* --- 14a. 2026-07-21 canvas QA pass: additional targeted fixes --- */

/* Thread-search magnifying-glass icon inherits the global --text-muted
   token. Scoped override only; the global token itself is untouched. */
body.ws2-fullpage .ws2-thread-search-icon {
  color: var(--ws2-text-tertiary) !important;
}

/* Compose "Send" button: the base (unscoped) workspace_v2_new.css rule paints
   the accent fill; in the workspace the primary fill is navy with white text.
   Higher-specificity scoped override wins regardless of stylesheet load order. */
body.ws2-fullpage .ws2-new-submit {
  background: var(--ws2-accent-fill);
  border-radius: var(--radius);
  color: var(--ws2-on-accent);
}
body.ws2-fullpage .ws2-new-submit:hover {
  background: var(--navy-hover);
}

/* Canvas job-status text: remap the inherited light-theme tokens
   (--text-secondary / --text-muted) to the ws2 text scale. */
body.ws2-fullpage .ws2-canvas-job-name {
  color: var(--ws2-text-primary);
}
body.ws2-fullpage .ws2-canvas-job-message {
  color: var(--ws2-text-secondary);
}

/* Canvas form labels (Census file, Provider roster, custom standards, the
   disruption and proposal pickers): style.css gives them the light-theme
   --text-secondary (#4b5060); the ws2 secondary text token keeps them on the
   one workspace scale (7:1 here). */
body.ws2-fullpage .ws2-canvas-role-form .field label {
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .ws2-canvas-job-meta {
  color: var(--ws2-text-tertiary);
}
body.ws2-fullpage .ws2-canvas-download-meta {
  color: var(--ws2-text-tertiary);
}
body.ws2-fullpage .ws2-canvas-job-format,
body.ws2-fullpage .ws2-canvas-job-hint,
body.ws2-fullpage .ws2-canvas-repricing-fb-hint {
  color: var(--ws2-text-tertiary);
}
body.ws2-fullpage .ws2-canvas-job-revision {
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .ws2-canvas-job-accepted {
  color: var(--green);
}

/* Canvas meta-status pills: the light-theme status colours, pinned to the
   brand set (blue accent while running, green done, red failed). */
body.ws2-fullpage .meta-status-status-queued,
body.ws2-fullpage .meta-status-status-running,
body.ws2-fullpage .meta-status-status-processing,
body.ws2-fullpage .meta-status-status-pending_phase1 {
  color: var(--ws2-accent-text);
}
body.ws2-fullpage .meta-status-status-completed {
  color: var(--green);
}
body.ws2-fullpage .meta-status-status-failed {
  color: var(--red);
}

/* --- 15. QA-confirmed visual defects: D1 legacy-qa-banner, D2/D6/D7 links,
          D4 modal, D5 session-banner, D8 login footer ------- */

/* D1: legacy Q&A banner was rendering with light gray body background */
body.ws2-fullpage .ws2-legacy-qa-banner {
  background: var(--sub) !important;
  border: 1px solid var(--ws2-border) !important;
  color: var(--ws2-text-secondary) !important;
}

/* D2 + D6 + D7: browser-default blue links in workspace */
body.ws2-fullpage
  a:not(.btn):not(.btn-download):not(.ws2-new-thread-btn):not(
    [class*="button"]
  ):not(.ws2-thread-item):not(.ws2-filter-link):not(
    .ws2-user-footer-name-link
  ):not(.ws2-user-footer-settings-btn):not(.ws2-tool-pill) {
  color: var(--ws2-accent-text) !important;
}
body.ws2-fullpage
  a:not(.btn):not(.btn-download):not(.ws2-new-thread-btn):not(
    [class*="button"]
  ):not(.ws2-thread-item):not(.ws2-filter-link):not(
    .ws2-user-footer-name-link
  ):not(.ws2-user-footer-settings-btn):not(.ws2-tool-pill):hover {
  color: var(--navy) !important;
  text-decoration: underline !important;
}

/* D4: platform modal / Bootstrap modal: a white floating layer */
body.ws2-fullpage .platform-modal,
body.ws2-fullpage .modal-content,
body.ws2-fullpage .modal-dialog {
  background: var(--canvas) !important;
  border: 1px solid var(--ws2-border) !important;
  color: var(--ws2-text-primary) !important;
  box-shadow: var(--shadow-float) !important;
}
body.ws2-fullpage .platform-modal .btn-secondary,
body.ws2-fullpage .modal-footer .btn:not(.btn-primary):not(.btn-danger) {
  background: var(--btn-tint) !important;
  border: 1px solid transparent !important;
  color: var(--navy) !important;
}

/* D5: session banner was light pink (Bootstrap alert-warning bleeds through);
   it is an error state, so it takes the brand red. */
body.ws2-fullpage .ws-session-banner {
  background: var(--red-tint) !important;
  border: 1px solid var(--red-line) !important;
  color: var(--red) !important;
}
body.ws2-fullpage .ws-session-banner a,
body.ws2-fullpage .ws-session-banner button {
  color: var(--red) !important;
  border-color: var(--red-line) !important;
}

/* D8: login page footer was white on the dark auth-page background */
body.auth-page footer {
  background-color: transparent !important;
  border-top-color: rgba(255, 255, 255, 0.08) !important;
  color: rgba(236, 236, 238, 0.62) !important;
}
body.auth-page footer a {
  color: rgba(91, 155, 213, 0.7) !important;
}

/* D9 (2026-08-25 design-system audit, BLOCKER finding #1): the threadless
   single-job view (_workspace_v2_conversation.html {% elif single_job %})
   deliberately reuses the classic per-tool job-page classes -- .card,
   .processing-banner, .error-detail, .status-help-text, .btn-download,
   .alert/.alert-error, .feedback-divider/.feedback-section/.feedback-history/
   .feedback-item/.feedback-status-* -- none of which had a ws2-scoped
   override. Same treatment as D1-D8 above: remap to --ws2-* tokens. */
body.ws2-fullpage .card {
  background: var(--ws2-elevated);
  border: 1px solid var(--ws2-border);
  box-shadow: none;
}
body.ws2-fullpage .card h3 {
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .card h3:not(:first-child) {
  border-top-color: var(--ws2-border);
}

body.ws2-fullpage .processing-banner {
  background: var(--ws2-elevated);
  border: 1px solid var(--ws2-border);
  border-left: 3px solid var(--ws2-accent);
}
body.ws2-fullpage .processing-banner-text strong {
  color: var(--ws2-text-primary);
}
body.ws2-fullpage .processing-banner-text span {
  color: var(--ws2-text-secondary);
}

/* .error-detail has zero base-theme CSS anywhere (grep-confirmed) -- it
   otherwise just inherits ambient text color, which reads as low-emphasis
   body text instead of an error. Give it the brand red used by the
   session-banner (D5) and other error states in this file. */
body.ws2-fullpage .error-detail {
  color: var(--red);
}

body.ws2-fullpage .status-help-text {
  color: var(--ws2-text-secondary);
}

/* .btn-download's light-theme default is solid orange; the brand has no
   orange and a primary fill is navy with white text, the same as every other
   primary action in the shell. */
body.ws2-fullpage .btn-download {
  background: var(--ws2-accent-fill);
  color: var(--ws2-on-accent);
  box-shadow: none;
}
body.ws2-fullpage .btn-download:hover {
  background: var(--navy-hover);
  color: var(--ws2-on-accent);
  box-shadow: none;
}

/* Every other primary action in the shell (Start analysis, Download report,
   Build a proposal from this, the chat-intro submit): navy fill, white text,
   the same pairing as .btn-download above. */
body.ws2-fullpage .btn-primary,
body.ws2-fullpage .btn-primary:hover {
  color: var(--ws2-on-accent);
}
body.ws2-fullpage .btn-primary {
  background: var(--ws2-accent-fill);
  border-color: transparent;
}
body.ws2-fullpage .btn-primary:hover {
  background: var(--navy-hover);
}

/* The D2 link-recolor rule (above) paints every <a> in the shell the link
   blue, so .btn-download is excluded from it and the primary keeps its own
   label colour (--ws2-on-accent, above). The secondary buttons (anonymized /
   executive / analyst) are outlined, not filled: transparent background,
   navy label and border, select tint on hover. This must out-specify the
   filled `body.ws2-fullpage .btn-download` rule above. */
body.ws2-fullpage .btn-download.btn-download-secondary {
  background: transparent;
  color: var(--navy);
  border: 1px solid var(--navy);
  box-shadow: none;
}
body.ws2-fullpage .btn-download.btn-download-secondary:hover {
  background: var(--ws2-active);
  color: var(--navy);
  box-shadow: none;
}

/* .alert itself carries no color (padding/radius/margin/font-size only) --
   nothing to override there. .alert-error does. */
body.ws2-fullpage .alert-error {
  background: var(--red-tint);
  border: 1px solid var(--red-line);
  color: var(--red);
}

body.ws2-fullpage .feedback-divider-label {
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .feedback-divider-rule {
  background: var(--ws2-border);
}
body.ws2-fullpage .feedback-history-label {
  border-top: 1px solid var(--ws2-border);
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .feedback-item {
  background: var(--sub);
  border: 1px solid var(--ws2-border);
}
body.ws2-fullpage .feedback-item .feedback-meta {
  border-bottom: 1px solid var(--ws2-border);
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .feedback-item .feedback-status-submitted {
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .feedback-item .feedback-status-resolved {
  color: var(--green);
}
body.ws2-fullpage .feedback-item .feedback-meta-sep {
  color: var(--ws2-text-tertiary);
}
body.ws2-fullpage .feedback-item .feedback-auto-badge {
  background: var(--tile);
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .feedback-item .feedback-text {
  color: var(--ws2-text-primary);
}
body.ws2-fullpage .resolution {
  color: var(--green);
}

/* D10 (2026-08-25 design-system audit, SHOULD-FIX finding #3): .data-table
   (used by the benchmark + geo canvas summary fragments) has zero dedicated
   CSS -- it only picked up the generic light-theme `table`/`thead th`/
   `tbody td` element selectors from style.css, and .metric-good/-warn/-bad
   have no CSS anywhere at all. Table surface uses the same
   --ws2-elevated/--ws2-border pair as the .card override above so both
   surfaces read as one consistent "content card" family; zebra striping on
   the grey tint makes a wide table easier to track across. */
body.ws2-fullpage table {
  background: var(--ws2-elevated);
  border: 1px solid var(--ws2-border);
  box-shadow: none;
}
body.ws2-fullpage thead th {
  border-bottom: 2px solid var(--ws2-border);
  color: var(--ws2-text-secondary);
  background: var(--tile);
}
body.ws2-fullpage tbody td {
  border-bottom: 1px solid var(--line-soft);
  color: var(--ws2-text-primary);
}
body.ws2-fullpage tbody tr:nth-child(even) > :is(td, th[scope="row"]) {
  background: var(--sub);
}
body.ws2-fullpage tbody tr:hover > :is(td, th[scope="row"]) {
  background: var(--select);
}
body.ws2-fullpage tbody td a {
  color: var(--ws2-accent-text);
}

/* Metric colours: good is the brand green, bad the brand red, and the middle
   band stays navy (the number carries it; no amber in this brand). Contrast
   on the white table surface: green 6.5:1, red 7.5:1, navy 16:1. */
body.ws2-fullpage .metric-good {
  color: var(--green);
}
body.ws2-fullpage .metric-warn {
  color: var(--navy);
}
body.ws2-fullpage .metric-bad {
  color: var(--red);
}

/* D11 (2026-08-25 design-system audit, SHOULD-FIX finding #4): .spinner
   (used by .processing-banner above, and elsewhere) uses light-theme
   var(--border)/var(--accent) for its ring; pin it to the ws2 line and
   the brand blue edge. */
body.ws2-fullpage .spinner {
  border-color: var(--ws2-border);
  border-top-color: var(--ws2-accent);
}

/* 2026-07-21 canvas QA pass (inspectors A/B/C) -- fixed, see §14a
   above + the two inline edits noted below:
   - Resolved-pill contrast (thread list + conversation header)
   - Thread-search placeholder contrast -- input::placeholder alpha
   - Thread-search magnifying-glass icon color
   - Compose Send button label colour (.ws2-new-submit)
   - Canvas job-status text tokens (job-name/message/meta/download-meta)
   - Canvas meta-status pill colors (queued/running/processing/pending_phase1/completed/failed)
   - Canvas download-item chip
   - Job-ID link-job input cramped layout (no form-control base match) */

/* ── Section 16: User footer (left panel) ─────────────────────── */
body.ws2-fullpage .ws2-user-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 14px;
  border-top: 1px solid var(--ws2-border);
  background: var(--canvas);
  flex-shrink: 0;
}

body.ws2-fullpage .ws2-user-footer-identity {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  overflow: hidden;
}

body.ws2-fullpage .ws2-user-footer-name {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ws2-text-primary);
  white-space: normal;
  overflow-wrap: anywhere;
}

body.ws2-fullpage .ws2-user-footer-role {
  font-size: var(--text-sm);
  color: var(--ws2-text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

body.ws2-fullpage .ws2-user-footer-logout-form {
  flex-shrink: 0;
  margin: 0;
}

body.ws2-fullpage .ws2-user-footer-logout-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px; /* PU-05 */
  height: 44px;
  border-radius: var(--radius);
  border: 1px solid var(--ws2-border);
  background: var(--canvas);
  color: var(--ws2-text-secondary);
  cursor: pointer;
  transition:
    background 0.15s,
    color 0.15s;
  padding: 0;
}

body.ws2-fullpage .ws2-user-footer-logout-btn:hover {
  background: var(--red-tint);
  border-color: var(--red-line);
  color: var(--red);
}

/* LOGRO_WS_SETTINGS_NAV -- trailing icon cluster (cogwheel + sign-out)
   grouped together on the right so `justify-content: space-between` on the
   footer treats them as one block instead of centering the cogwheel. */
body.ws2-fullpage .ws2-user-footer-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

/* LOGRO_WS_SETTINGS_NAV -- cogwheel link to /account, sitting inline just
   left of the sign-out button in the same trailing icon cluster. */
body.ws2-fullpage .ws2-user-footer-settings-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px; /* PU-05 */
  height: 44px;
  border-radius: var(--radius);
  border: 1px solid var(--ws2-border);
  background: var(--canvas);
  color: var(--ws2-text-secondary);
  cursor: pointer;
  transition:
    background 0.15s,
    color 0.15s;
  padding: 0;
  flex-shrink: 0;
  text-decoration: none;
}

body.ws2-fullpage .ws2-user-footer-settings-btn:hover {
  background: var(--sub);
  border-color: var(--ws2-control);
  color: var(--ws2-accent);
}

/* App menu -- role-gated links (Guide, Account, Admin, Users, ...) that
   replaced the old global sidebar's navigation. The trigger sits in the same
   icon cluster as the cogwheel + sign-out; the panel opens upward over the
   thread list, anchored to the footer (.ws2-user-menu is position:static so
   the absolute panel resolves against .ws2-user-footer). */
body.ws2-fullpage .ws2-user-footer {
  position: relative;
}

body.ws2-fullpage .ws2-user-menu-trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px; /* PU-05 */
  height: 44px;
  border-radius: var(--radius);
  border: 1px solid var(--ws2-border);
  background: var(--canvas);
  color: var(--ws2-text-secondary);
  cursor: pointer;
  transition:
    background 0.15s,
    color 0.15s;
  padding: 0;
  flex-shrink: 0;
}

body.ws2-fullpage .ws2-user-menu-trigger:hover,
body.ws2-fullpage .ws2-user-menu-trigger[aria-expanded="true"] {
  background: var(--sub);
  border-color: var(--ws2-control);
  color: var(--ws2-text-primary);
}

body.ws2-fullpage .ws2-user-menu-trigger:focus-visible,
body.ws2-fullpage .ws2-user-menu-item:focus-visible {
  outline: 2px solid var(--ws2-accent);
  outline-offset: -2px;
}

body.ws2-fullpage .ws2-user-menu-panel {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: calc(100% + 6px);
  z-index: 120;
  max-height: 70vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px;
  background: var(--canvas);
  border: 1px solid var(--ws2-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-float);
}

body.ws2-fullpage .ws2-user-menu-panel[hidden] {
  display: none;
}

body.ws2-fullpage .ws2-user-menu-label {
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ws2-text-tertiary);
  padding: 8px 8px 4px;
  margin-top: 4px;
  border-top: 1px solid var(--line-soft);
}

body.ws2-fullpage .ws2-user-menu-item {
  display: block;
  box-sizing: border-box;
  min-height: 44px;
  padding: 12px 10px;
  border-radius: var(--radius);
  color: var(--ws2-text-primary);
  font-size: var(--text-sm);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background 0.1s;
}

body.ws2-fullpage .ws2-user-menu-item:hover {
  background: var(--ws2-hover);
}

/* LOGRO_WS_SETTINGS_NAV -- user name becomes a link to /account. */
body.ws2-fullpage .ws2-user-footer-name-link {
  text-decoration: none;
  cursor: pointer;
  color: var(--ws2-text-primary);
  /* A 44px hit area without moving the footer: padding grows the target, an
     equal negative margin cancels it. */
  display: inline-block;
  padding: 13px 8px;
  margin: -13px -8px;
}

body.ws2-fullpage .ws2-user-footer-name-link:hover {
  color: var(--ws2-text-primary);
  text-decoration: underline;
}

/* =========================================================================
   Compose mode (body.ws2-fullpage + compose_mode=True in the shell).
   The new-conversation form lives in .ws2-compose-body inside the middle
   panel. Base style.css chips/dropzone/file-list use the unscoped light
   tokens; these overrides pin them to the ws2 set for this container.
   workspace_v2_new.css only supplies the form's structural (non-color)
   rules, plus the plain field styles re-pinned below.
   ========================================================================= */

body.ws2-fullpage .ws2-compose-body {
  padding: 20px 24px;
  overflow-y: auto;
  flex: 1;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}

body.ws2-fullpage .ws2-compose-body .ws2-chip {
  border: 1px solid var(--ws2-border);
  background: var(--canvas);
  color: var(--ws2-text-secondary);
  border-radius: var(--radius);
}

body.ws2-fullpage .ws2-compose-body .ws2-chip:hover {
  background: var(--sub);
  color: var(--ws2-text-primary);
}

body.ws2-fullpage .ws2-compose-body .ws2-chip-selected,
body.ws2-fullpage .ws2-compose-body .ws2-chip-selected:hover {
  background: var(--ws2-accent-fill);
  border-color: var(--ws2-accent-fill);
  color: var(--ws2-on-accent);
}

body.ws2-fullpage .ws2-compose-body .ws2-new-dropzone {
  border: 2px dashed var(--ws2-control);
  border-radius: var(--radius);
  padding: 24px 18px;
  text-align: center;
  color: var(--ws2-text-secondary);
  background: var(--sub);
  transition:
    border-color 0.12s,
    background 0.12s;
  cursor: pointer;
}

body.ws2-fullpage .ws2-compose-body .ws2-new-dropzone:hover,
body.ws2-fullpage .ws2-compose-body .ws2-new-dropzone.ws-drag-over {
  border-color: var(--ws2-accent);
  background: var(--select);
}

body.ws2-fullpage .ws2-compose-body .ws2-new-file-list .ws-file-item {
  background: var(--sub);
  border: 1px solid var(--ws2-border);
  border-radius: var(--radius);
  color: var(--ws2-text-primary);
}

body.ws2-fullpage .ws2-compose-body .ws2-new-file-list .ws-file-item-size {
  color: var(--ws2-text-tertiary);
}

body.ws2-fullpage .ws2-compose-body .ws-file-remove {
  color: var(--ws2-text-tertiary);
}

body.ws2-fullpage .ws2-compose-body .ws-file-remove:hover {
  color: var(--red);
}

/* The plain field styles in workspace_v2_new.css: a white field with the
   control edge, a red required mark, the navy edge on focus. */
body.ws2-fullpage .ws2-new-label-required {
  color: var(--red);
}
body.ws2-fullpage .ws2-new-input {
  background: var(--canvas);
  border-color: var(--ws2-control);
  border-radius: var(--radius);
}
body.ws2-fullpage .ws2-new-input:focus {
  background: var(--canvas);
  border-color: var(--navy);
}

/* No focus highlight on reply textarea -- keep identical focused or not (simple UI).
   Moved to end of file so it appears AFTER the general textarea:focus rule and
   wins the cascade when both have !important. */
body.ws2-fullpage .ws2-reply-textarea:focus {
  border-color: transparent !important;
  box-shadow: none !important;
  outline: none !important;
}

/* --- Keyboard-only focus indicators (composer + thread search) --------
   The rule above made the reply textarea identical focused or not on
   purpose (no ring on a plain mouse click) -- but that also made
   Tab-focus on it, the send/attach buttons, and the thread-list search
   input completely invisible to a keyboard user, since there was no
   :focus-visible rule to still show *something*. :focus-visible is the
   fix: it only engages for genuine keyboard/programmatic focus (mouse
   clicks on buttons never match it), so a keyboard user gets a clear
   indicator while the "no ring on click" decision above is preserved.
   Neutral token (--ws2-text-secondary), not --ws2-accent, so it reads as
   "you are here" rather than an accent-colored active/selected state.
   Placed at the very end of this file (same convention as the :focus rule
   above) with matching selector specificity + !important where a
   competing !important rule exists, so it reliably wins the cascade. */
body.ws2-fullpage .ws2-reply-textarea:focus-visible {
  border-color: var(--ws2-text-secondary) !important;
  box-shadow: 0 0 0 2px var(--ws2-text-secondary) !important;
  outline: none !important;
}
body.ws2-fullpage .ws2-reply-submit:focus-visible,
body.ws2-fullpage .ws2-reply-attach-btn:focus-visible {
  outline: 2px solid var(--ws2-text-secondary);
  outline-offset: 2px;
}
body.ws2-fullpage .ws2-reply-attach-btn:focus-visible {
  border-color: var(--ws2-text-secondary);
}
/* Deliberately NOT extended to .ws2-thread-search-input: the generic
   `body.ws2-fullpage input:focus` rule near the top of this file already
   paints a navy edge (and the shell's ring) on it, so keyboard users are
   served. Suppressing that for mouse focus (to mirror the composer's no-ring
   decision) was tried and reverted -- clicking into a search box with zero
   visual feedback is worse, and the composer's no-ring rule is specific to
   the always-focused reply textarea, not a house-wide input convention. */

/* --- Spacing sweep (2026-10-19): shared edges + rhythm (desktop) ----------
   One left/right edge down each column. 16px is the shell's gutter: the
   header, the message column, the composer pill and the thread rows all
   start on it, so nothing steps in or out as you scan down. Phone
   overrides live in the phone block below. */
/* Search box: same 16px edges as the thread rows beneath it (was 13.5px,
   so the box stuck out 2.5px each side of the list). */
body.ws2-fullpage .ws2-thread-search {
  padding: 8px 16px;
}
body.ws2-fullpage .ws2-thread-search-icon {
  left: 24px;
}
/* The search box already carries its own bottom padding, so the list body
   only needs a small top inset (was 16px on top of that: a 25px gap under
   the box against 9px above it). */
body.ws2-fullpage .ws2-thread-list-panel .ws2-panel-body {
  padding-top: 4px;
}
/* Message column on the same 16px edges as the header title and the
   composer pill (was 28px: messages sat 12px inside both). */
body.ws2-fullpage .ws2-conversation-body {
  padding-left: 16px;
  padding-right: 16px;
}
/* Footer identity + icon buttons on the same 16px edges as the brand row,
   the search box and the thread rows above (was 14px: name and buttons sat
   2px outside every other row in the column). */
body.ws2-fullpage .ws2-user-footer {
  padding-left: 16px;
  padding-right: 16px;
}
/* Author/time label a full 8px above its bubble (was 4px, crowded). */
body.ws2-fullpage .ws-message-header {
  margin-bottom: 8px;
}
/* Attachment chips 8px below the bubble they belong to. The base margin-top
   is swallowed by `clear: both` (clearance), so it needs padding to hold. */
body.ws2-fullpage .ws-message-attachments {
  padding-top: 8px;
}
/* Composer: the pill (.ws2-reply-input-row) is the one box; the global
   `body.ws2-fullpage textarea` glass fill above is !important and was
   painting a second bordered box inside it (the focus rule above keeps it
   quiet on focus too). */
body.ws2-fullpage .ws2-reply-textarea {
  background: transparent !important;
  border-color: transparent !important;
  /* One line to start, centred on the 44px attach/send buttons (rows="3"
     made a 95px box with the text top-left and both buttons bottom-aligned,
     so the three never shared a centre line); grows with the text where
     field-sizing is supported, scrolls at the max-height cap elsewhere. The
     phone block below does the same. */
  height: 44px;
  min-height: 44px;
  padding: 9px 4px;
}
@supports (field-sizing: content) {
  body.ws2-fullpage .ws2-reply-textarea {
    height: auto;
    field-sizing: content;
  }
}
/* The staged-file list is a 0px-tall flex item when nothing is staged, but
   it still brought its 9px margin and the form's 6px gap: 15px of dead space
   under the drop zone (29px below the pill row against 12px above it). It
   reappears as soon as a file is staged. */
body.ws2-fullpage .ws-file-list:not(:has(*)) {
  display: none;
}

/* --- Mobile single-pane (<= 900px) -------------------------------------
   The desktop shell is three fixed columns. On a phone it used to just stack
   them (list, then chat, then files) in one long scrolling page: the composer
   sat below the fold and every pane was a cramped strip. Now the shell is
   pinned to the viewport and shows ONE pane at a time:
     - no conversation open  -> thread list
     - body.ws2-has-conversation -> the conversation, with a back arrow
     - body.ws2-canvas-open -> the work-product canvas as a full-screen sheet
   Back arrow, Files button and canvas close button are display:none above
   900px (see _workspace_v2_mobile_nav.html and the shell script). Sizes aim
   for 44px tap targets and 16px form text (iOS zooms inputs below 16px). */
.ws2-mobile-back,
.ws2-mobile-work-btn,
.ws2-mobile-canvas-close {
  display: none;
}

@media (max-width: 900px) {
  body.ws2-fullpage .ws2-shell,
  body.ws2-fullpage.ws2-canvas-collapsed .ws2-shell {
    position: fixed;
    inset: 0;
    height: 100vh;
    height: 100dvh; /* the URL bar shrinks 100vh on phones; dvh tracks it */
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
  }
  body.ws2-fullpage .ws2-resize-handle {
    display: none;
  }
  body.ws2-fullpage .ws2-panel {
    height: 100%;
    min-width: 0;
    min-height: 0;
  }
  body.ws2-fullpage .ws2-conversation-panel,
  body.ws2-fullpage .ws2-canvas-panel {
    display: none;
  }
  body.ws2-fullpage.ws2-has-conversation .ws2-thread-list-panel {
    display: none;
  }
  body.ws2-fullpage.ws2-has-conversation .ws2-conversation-panel {
    display: flex;
  }
  body.ws2-fullpage.ws2-has-conversation.ws2-canvas-open .ws2-canvas-panel {
    display: flex;
    position: fixed;
    inset: 0;
    z-index: 250;
    height: 100dvh;
    background: var(--ws2-bg-canvas);
  }
  /* The desktop collapse state hides the canvas body; the sheet ignores it. */
  body.ws2-fullpage.ws2-canvas-collapsed .ws2-canvas-panel .ws2-panel-body {
    display: block;
  }
  body.ws2-fullpage.ws2-canvas-collapsed .ws2-canvas-panel-title-text {
    display: inline;
  }
  body.ws2-fullpage .ws2-canvas-toggle {
    display: none;
  }
  body.ws2-fullpage .ws2-canvas-panel .ws2-panel-header {
    justify-content: flex-start;
    gap: 4px;
  }
  body.ws2-fullpage .ws2-conversation-body {
    max-height: none;
  }

  /* Headers: back arrow + title, tighter side padding (12px, the same gutter
     as the panel body and the composer, so header controls line up with the
     content under them). */
  body.ws2-fullpage .ws2-panel-header {
    padding: 0 12px;
  }
  body.ws2-fullpage .ws2-mobile-back,
  body.ws2-fullpage .ws2-mobile-canvas-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    margin-left: -6px;
    padding: 0;
    border: none;
    border-radius: var(--radius);
    background: transparent;
    color: var(--ws2-text-primary);
    cursor: pointer;
    text-decoration: none;
  }
  body.ws2-fullpage .ws2-mobile-work-btn {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 14px;
    border: 1px solid var(--ws2-border);
    border-radius: var(--radius);
    background: var(--ws2-hover);
    color: var(--ws2-text-primary);
    font: inherit;
    font-size: var(--text-sm);
    font-weight: 600;
    cursor: pointer;
  }
  body.ws2-fullpage .ws2-header-titlewrap {
    flex: 1 1 auto;
  }
  /* Title-only headers (New Conversation, Conversation) sit next to the back
     arrow instead of being pushed right by space-between. */
  body.ws2-fullpage .ws2-conversation-panel .ws2-panel-header > .ws2-conversation-title {
    margin-right: auto;
  }

  /* Thread list: tap-sized rows, 16px search, 44px header actions. */
  body.ws2-fullpage .ws2-thread-item {
    min-height: 64px;
  }
  body.ws2-fullpage .ws2-thread-search-input {
    font-size: 16px;
    min-height: 44px; /* PU-05 */
  }
  body.ws2-fullpage .ws2-new-thread-btn {
    width: 44px;
    height: 44px;
  }
  body.ws2-fullpage .ws2-tool-pill {
    min-height: 44px; /* PU-05 */
  }
  body.ws2-fullpage .ws2-user-footer-settings-btn,
  body.ws2-fullpage .ws2-user-footer-logout-btn,
  body.ws2-fullpage .ws2-user-menu-trigger {
    width: 44px;
    height: 44px;
  }
  body.ws2-fullpage .ws2-user-footer {
    padding: 8px 12px;
  }

  /* Conversation body + messages: use the width, not the desktop gutters. */
  body.ws2-fullpage .ws2-panel-body {
    padding: 12px;
  }
  body.ws2-fullpage .ws-message-body {
    overflow-wrap: anywhere;
  }
  /* Wide result tables / code in the canvas and messages scroll inside their
     own box instead of widening the whole page. */
  body.ws2-fullpage .ws2-panel-body {
    overflow-x: hidden;
  }
  body.ws2-fullpage .ws2-panel-body table,
  body.ws2-fullpage .ws2-panel-body pre {
    display: block;
    max-width: 100%;
    overflow-x: auto;
  }

  /* Composer: 44px send/attach, 16px text, safe-area aware. The dashed
     "drag files here" strip is meaningless on a touch screen and the attach
     button already opens the picker, so it is dropped to win the space back. */
  body.ws2-fullpage .ws2-reply-bar {
    padding: 8px 12px calc(10px + env(safe-area-inset-bottom, 0px));
  }
  body.ws2-fullpage .ws2-reply-textarea {
    font-size: 16px;
    /* rows="3" makes the box ~95px tall; a phone needs the room for the
       thread. One line to start, growing with the text where supported
       (field-sizing), scrolling at the cap elsewhere. */
    height: 44px;
    min-height: 44px;
    max-height: 120px;
    padding: 10px 4px;
    background: transparent !important;
    border-color: transparent !important;
  }
  @supports (field-sizing: content) {
    body.ws2-fullpage .ws2-reply-textarea {
      height: auto;
      field-sizing: content;
    }
  }
  body.ws2-fullpage .ws2-reply-submit,
  body.ws2-fullpage .ws2-reply-attach-btn {
    width: 44px;
    height: 44px;
  }
  body.ws2-fullpage .ws2-reply-drop-zone,
  body.ws2-fullpage .ws-drop-zone.ws2-dropzone.ws2-reply-drop-zone {
    display: none;
  }
  /* Staged-attachment rows: a tappable remove control, not a 10px "x". */
  body.ws2-fullpage .ws-file-remove {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  /* Thread-list search on the phone's 12px gutter (the desktop rule above
     uses the 16px one), so it lines up with the rows below it. */
  body.ws2-fullpage .ws2-thread-search {
    padding-left: 12px;
    padding-right: 12px;
  }
  body.ws2-fullpage .ws2-thread-search-icon {
    left: 20px;
  }
}

/* --- Phone polish (<= 900px) -------------------------------------------
   Defect-only pass from the 2026-10-09 enterprise-readiness audit, measured
   at 390x844, 360x740 and 768x1024. It sits on top of the single-pane phone
   shell above, which already covers the 16px form text and the 44px composer,
   remove and list-header controls; this block only adds what that pass left
   out. Nothing here changes the layout or the brand. Desktop (> 900px) is
   untouched. Kept after the single-pane block so it wins the cascade. */
@media (max-width: 900px) {
  /* A long staged-file list grew the page without bound (eleven files made
     the new-conversation page 2371px tall and squeezed the message list to
     134px). Cap it and scroll inside the composer instead. */
  body.ws2-fullpage .ws-file-list {
    max-height: 30vh;
    max-height: 30dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  /* Message attachment chips were 34px tall. A min-height keeps the 44px
     target while a long name wraps to more lines instead of being clipped. */
  body.ws2-fullpage .ws-attachment-link {
    box-sizing: border-box;
    min-height: 44px;
    padding-top: 10px;
    padding-bottom: 10px;
    line-height: 1.4;
  }
  /* The signed-in name link is a 29x19 target. Grow the hit area with
     padding and cancel it with an equal negative margin so the footer
     layout does not move. */
  body.ws2-fullpage .ws2-user-footer-name-link {
    display: inline-block;
    padding: 13px 8px;
    margin: -13px -8px;
  }
  /* Tool-pick and action buttons in the Work Product panel were 41px. */
  body.ws2-fullpage .ws2-canvas-panel .btn {
    min-height: 44px;
  }
  /* The composer and thread-search placeholders stay on the tertiary text
     token (5.8:1 or better on the bar and the grey list), the same on every
     width. */
  body.ws2-fullpage .ws2-reply-textarea::placeholder,
  body.ws2-fullpage .ws2-thread-search-input::placeholder {
    color: var(--ws2-text-tertiary) !important;
  }
  /* A long thread title wraps in full (see the unconditional rule at the end
     of this file); nothing is clamped or ellipsised. */
  body.ws2-fullpage .ws2-conversation-panel .ws2-panel-header .ws2-conversation-title {
    line-height: 1.25;
  }
  /* Sign-in / reset pages: "Forgot password?" and the other footer links
     were 132x19 targets. Same padding/negative-margin trick as above so the
     card does not grow. */
  body.auth-page .auth-footer-links a {
    display: inline-block;
    padding: 13px 10px;
    margin: -13px -10px;
  }
}

/* Short phones (360x740): with the shell pinned to the viewport, ten staged
   files at the 30dvh cap (222px) leave the message list only a sliver. 22dvh
   (163px, still three full 44px rows plus a peek) gives it room back. 390x844
   and taller are untouched. */
@media (max-width: 900px) and (max-height: 780px) {
  body.ws2-fullpage .ws-file-list {
    max-height: 22vh;
    max-height: 22dvh;
  }
}

/* --- prefers-reduced-motion (2026-08-25 design-system audit, SHOULD-FIX
   finding #7): this file (and the ws2-scoped animations in style.css --
   the processing-banner pulse, spinner rotation, hover/focus transitions)
   had no reduced-motion accommodation at all. Placed last in the file, as
   a universal `*` override, so it wins the cascade over every specific
   animation/transition declared above regardless of selector specificity. */
@media (prefers-reduced-motion: reduce) {
  body.ws2-fullpage *,
  body.ws2-fullpage *::before,
  body.ws2-fullpage *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- 16. WCAG 2.1 AA text remaps (2026-10-08, UX audit UX-09) ------------
   Small chrome text that was once painted at low alpha: avatars, the "Unseen"
   chip, the tool chips, the footer role line. They use --ws2-text-tertiary
   (--ink-3, 5.4:1 or better on every surface here), and the tool badge uses
   the brand blue. Colour only: size, weight and layout are untouched. The
   static contrast check in tests/web/test_a11y_static.py pins these. */
body.ws2-fullpage .ws2-avatar-in-progress,
body.ws2-fullpage .ws2-avatar-responded,
body.ws2-fullpage .ws2-avatar-resolved,
body.ws2-fullpage .ws2-avatar-received,
body.ws2-fullpage .ws-new-chip,
body.ws2-fullpage .ws2-legacy-qa-chip,
body.ws2-fullpage .ws2-user-footer-role {
  color: var(--ws2-text-tertiary);
}
body.ws2-fullpage .ws2-tool-badge {
  color: var(--ws2-accent-text) !important;
}

/* The single-job panel's header meta line (p.meta: "Completed · Claims
   Repricing & Savings · ...") kept the light-theme --text-secondary, #4b5060;
   the ws2 secondary token keeps it on the workspace scale. */
body.ws2-fullpage p.meta {
  color: var(--ws2-text-secondary);
}


/* --- Replaced messages (D-0300) ---------------------------------------------
   A message the team has since replaced reads as replaced: no bubble, a one-
   line "Updated below" link and the original text behind a "Show original"
   toggle. Its correction carries the "Update" tag and a link back. Colours
   come from the --ws2-* tokens; no opacity dimming (it would lower the text
   contrast the accessibility gate checks). */
body.ws2-fullpage .ws-superseded-link,
body.ws2-fullpage .ws-update-link {
  display: block;
  clear: both;
  margin-bottom: 4px;
  font-size: var(--text-sm);
  color: var(--ws2-accent-text);
  text-decoration: underline;
}
body.ws2-fullpage .ws-message-client .ws-superseded-link,
body.ws2-fullpage .ws-message-client .ws-update-link,
body.ws2-fullpage .ws-message-client .ws-superseded-original {
  text-align: right;
}
body.ws2-fullpage .ws-superseded-original {
  display: flow-root;
  clear: both;
  font-size: var(--text-sm);
}
body.ws2-fullpage .ws-superseded-original > summary {
  display: inline-block;
  cursor: pointer;
  color: var(--ws2-text-secondary);
  padding: 4px 0;
}
body.ws2-fullpage .ws-superseded-original[open] > .ws-message-body {
  margin-top: 4px;
  border-style: dashed;
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .ws-message-superseded .ws-message-header strong,
body.ws2-fullpage .ws-message-superseded .ws-message-time {
  color: var(--ws2-text-secondary);
}
@media (max-width: 640px) {
  body.ws2-fullpage .ws-superseded-link,
  body.ws2-fullpage .ws-update-link,
  body.ws2-fullpage .ws-superseded-original > summary {
    min-height: 44px;
    padding: 12px 0;
    box-sizing: border-box;
  }
}

/* --- 17. Output-only canvas: plain header tool tag + chat hint (2026-10-19) -
   The canvas shows results only; the header shows the recognised tool as a
   plain tag (_workspace_v2_thread_tool_badge.html) and a wrong tool is
   corrected by telling the chat (D-0307). --ws2-* tokens only. */
body.ws2-fullpage .ws2-thread-tool {
  display: inline-flex;
  align-items: center;
}
body.ws2-fullpage .ws2-thread-tool[hidden] {
  display: none;
}
body.ws2-fullpage .ws2-canvas-chat-hint {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  margin: var(--sp-3) 0 0;
}
body.ws2-fullpage .ws2-canvas-chat-hint-btn {
  font-size: var(--text-sm);
  padding: var(--sp-1) var(--sp-3);
}
body.ws2-fullpage .ws2-canvas-chat-hint-text,
body.ws2-fullpage .ws2-single-job-chat-pointer {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .ws2-single-job-chat-pointer {
  margin-bottom: var(--sp-3);
}

/* D-0293: a long conversation title wraps in full at every width instead of
   being ellipsised or clamped. The header grows past 52px (and the controls
   wrap below the title when there is no room) so the tool tag and
   status pill stay visible. A short title stays one line, vertically centred. */
body.ws2-fullpage .ws2-conversation-panel > .ws2-panel-header {
  height: auto;
  min-height: 52px;
  padding-top: 4px;
  padding-bottom: 4px;
  flex-wrap: wrap;
}
body.ws2-fullpage .ws2-conversation-panel .ws2-panel-header .ws2-header-titlewrap {
  flex: 1 1 12rem;
  min-width: 0;
}
body.ws2-fullpage .ws2-conversation-panel .ws2-panel-header .ws2-conversation-title,
body.ws2-fullpage .ws2-conversation-panel .ws2-panel-header .ws2-qa-context-subtitle {
  display: block;
  overflow: visible;
  white-space: normal;
  overflow-wrap: anywhere;
  text-overflow: clip;
  -webkit-line-clamp: unset;
  line-clamp: unset;
}

/* Canvas "Ready to run" block: the read-only list of what a run will use (the
   client sets each by telling the chat), the "Tell the chat ..." prompts, and
   the reason a declined canvas tap shows above the slots. 4px grid. */
body.ws2-fullpage .ws2-canvas-ready {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}
body.ws2-fullpage .ws2-canvas-ready-title {
  margin: 0;
  font-weight: 600;
  color: var(--ws2-text-primary);
}
body.ws2-fullpage .ws2-canvas-ready-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
  color: var(--ws2-text-primary);
  overflow-wrap: anywhere;
}
body.ws2-fullpage .ws2-canvas-ready-label {
  color: var(--ws2-text-tertiary);
}
body.ws2-fullpage .ws2-canvas-tell-chat {
  color: var(--ws2-text-tertiary);
}
body.ws2-fullpage .ws2-canvas-action-error {
  margin: 0 0 12px;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--red-tint);
  border: 1px solid var(--red-line);
  color: var(--red);
  font-size: var(--text-sm);
}

/* "Get a progress update" bar above the composer (standing Daily update
   thread only). The button is the shell's own .btn-primary, so its colours
   are the accent tokens above; the status line uses the secondary text token. */
body.ws2-fullpage .ws2-update-request {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  padding: 10px 16px 0 16px;
}
body.ws2-fullpage .ws2-update-request-status {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--ws2-text-secondary);
}
body.ws2-fullpage .ws2-update-request-btn:focus-visible {
  outline: 2px solid var(--ws2-text-secondary);
  outline-offset: 2px;
}
