/*
  Shared upload/processing framework styles (CC-10 Article 3.6/3.7). Reads the
  --ox-* design tokens; every product's upload widget and processing step list
  share this one stylesheet. The scoped dark "workspace" treatment (.oxu-workspace)
  reproduces the reference /audit hero as a *scoped token layer* — the same
  --ox-* variables with darker values on a subtree — never a second design
  language.
*/

/* ── Scoped dark workspace (opt-in via .oxu-workspace on a wrapper) ───────
   Unused by the 2026-08-01 redesign's own pages (white-first throughout, no
   dark hero band), but left intact and updated to the current tokens rather
   than removed, in case anything outside this task's four named pages still
   opts into it. */
.oxu-workspace {
  --ox-bg: #14231C;
  --ox-ink: #F3F5F3;
  --ox-body: #D5DED8;
  --ox-muted: #9AAAA1;
  --ox-border: #2C3B33;
  --ox-accent: #3E9A5C;
  --ox-accent-hover: #4FB56E;
  --ox-accent-tint: rgba(62, 154, 92, 0.16);
  background: var(--ox-bg);
  color: var(--ox-body);
}

/* ── Upload card ────────────────────────────────────────────────────────── */
.oxu-card {
  /* A light surface even inside the dark workspace (like a dialog): reset to
     canonical light tokens so buttons/text read as everywhere else. */
  --ox-bg: #FFFFFF;
  --ox-ink: #14181B;
  --ox-body: #14181B;
  --ox-muted: #5C6B64;
  --ox-border: #E3E8E5;
  --ox-accent: #0B4F3B;
  --ox-accent-hover: #082F23;
  --ox-accent-tint: #EAF2EE;
  display: block;
  background: var(--ox-bg);
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-radius-card);
  padding: var(--ox-s5);
  /* No drop shadows (2026-08-01 redesign principle) — a plain hairline
     border, matching every other bordered surface in the new design. */
}
.oxu-heading { margin-bottom: 2px; }
.oxu-subhead { color: var(--ox-muted); font-size: var(--ox-size-1); margin-bottom: var(--ox-s4); }
.oxu-account-note { font-size: var(--ox-size-1); color: var(--ox-body); margin-bottom: var(--ox-s4); }

.oxu-dropzone {
  min-height: 160px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border: 1.5px dashed var(--ox-border);
  border-radius: var(--ox-radius-panel);
  background: var(--ox-bg-subtle);
  cursor: pointer;
  margin-bottom: var(--ox-s4);
  transition: border-color var(--ox-transition), background var(--ox-transition);
}
.oxu-dropzone:hover,
.oxu-dropzone:focus-visible { border-style: solid; border-color: var(--ox-accent); outline: none; }
.oxu-dropzone--dragover { border-style: solid; border-color: var(--ox-accent); background: var(--ox-accent-tint); }
/* Filled/selected state reads as a plain neutral card, not an accent
   highlight — matches the design reference's "Choose another file" panel
   (a 1px solid border, same colour as idle, background reset to plain
   white rather than the idle state's tinted background). */
.oxu-dropzone--filled { border-style: solid; border-width: 1px; border-color: var(--ox-border); background: var(--ox-bg); cursor: default; }
@media (max-width: 768px) { .oxu-dropzone { min-height: 120px; } }

.oxu-drop-idle { padding: var(--ox-s5) var(--ox-s6); width: 100%; }
.oxu-drop-arrow { color: var(--ox-border); font-size: 2.5rem; line-height: 1; margin-bottom: var(--ox-s3); }
.oxu-drop-lead { color: var(--ox-body); font-weight: 500; margin-bottom: 4px; }
.oxu-drop-meta { color: var(--ox-muted); font-size: var(--ox-size-1); margin-bottom: var(--ox-s3); }
.oxu-browse { font-size: var(--ox-size-1); padding: 8px 16px; }

.oxu-drop-selected {
  /* Two-column layout — filename/size stacked on the left, "Browse files"
     pinned right — reproduced without changing the flat name/size/button DOM
     upload_client.js already selects by id. */
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: var(--ox-s4);
  padding: var(--ox-s5) var(--ox-s6);
  width: 100%;
  text-align: left;
}
.oxu-selected-name { grid-column: 1; grid-row: 1; }
.oxu-selected-size { grid-column: 1; grid-row: 2; }
.oxu-browse-again { grid-column: 2; grid-row: 1 / span 2; }
/* Equal specificity to base.css's `[hidden] { display: none; }`, loaded
   earlier — without this the flex display above wins the cascade and the
   hidden state renders anyway (the same fix FAST's and VERIFY's own upload
   pages each had to apply locally before this was fixed here once). */
.oxu-drop-selected[hidden] { display: none; }
.oxu-selected-name { color: var(--ox-body); font-weight: 500; word-break: break-word; }
.oxu-selected-size { color: var(--ox-muted); font-size: var(--ox-size-1); white-space: nowrap; }
/* No ✓ badge, no "Remove" control (founder review, 2026-07-27): the filename
   and size are the only status shown, and choosing another file replaces the
   current selection. This button reopens the file picker exactly as the idle
   state's "Browse files" does — same click handled by the dropzone's own
   listener, no separate JS wiring needed. */
.oxu-browse-again {
  color: var(--ox-accent); font-size: var(--ox-size-1); font-weight: 600;
  background: none; border: none; cursor: pointer; padding: 0;
}
.oxu-browse-again:hover { text-decoration: underline; }

.oxu-file-input { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

.oxu-error {
  margin-bottom: var(--ox-s4); padding: var(--ox-s3) var(--ox-s4);
  background: var(--ox-critical-tint); border: 1px solid var(--ox-critical);
  border-radius: var(--ox-radius); font-size: var(--ox-size-1); color: var(--ox-critical);
}

.oxu-confirm { display: flex; align-items: flex-start; gap: var(--ox-s2); font-size: var(--ox-size-1); color: var(--ox-body); margin-bottom: var(--ox-s4); }

.oxu-submit {
  width: 100%; justify-content: center;
  padding: var(--ox-s4) var(--ox-s5); font-size: var(--ox-size-2);
  background: var(--ox-border); color: var(--ox-muted); border: 1px solid var(--ox-border); cursor: pointer;
}
.oxu-submit--ready { background: var(--ox-accent); color: #fff; border-color: var(--ox-accent); }
.oxu-submit--ready:hover { background: var(--ox-accent-hover); border-color: var(--ox-accent-hover); }

.oxu-confidentiality { margin-top: var(--ox-s2); font-size: var(--ox-size-0); color: var(--ox-muted); text-align: center; line-height: 1.6; }
.oxu-trust-strip { margin-top: var(--ox-s2); border-top: 1px solid var(--ox-border); padding-top: 10px; font-size: var(--ox-size-0); color: var(--ox-muted); text-align: center; line-height: 1.6; }

/* ── Processing step list ───────────────────────────────────────────────── */
.oxu-processing { max-width: 640px; margin: 0 auto; }
.oxu-processing-heading { margin-bottom: 2px; }
.oxu-processing-filename { color: var(--ox-muted); font-size: var(--ox-size-1); margin-bottom: var(--ox-s5); word-break: break-all; }

.oxu-progress-track { width: 100%; height: 6px; border-radius: var(--ox-radius-badge); background: var(--ox-bg-subtle); overflow: hidden; margin-bottom: var(--ox-s7); }
/* Width is set inline by applyStage() (upload_client.js / verify_compare.js)
   from the real count of completed stages — never a fabricated percentage.
   Starts at 0 so a page that never receives a stage report shows no fill
   rather than a fake head start. */
.oxu-progress-fill { width: 0%; height: 100%; background: var(--ox-accent); transition: width 400ms ease-out; }

.oxu-steps { list-style: none; display: flex; flex-direction: column; gap: var(--ox-s4); margin-bottom: var(--ox-s7); }
.oxu-step { display: flex; align-items: center; gap: var(--ox-s3); }
.oxu-step-icon { flex-shrink: 0; width: 20px; text-align: center; color: var(--ox-border); }
.oxu-step-text { font-size: var(--ox-size-1); color: var(--ox-muted); }
.oxu-step--active .oxu-step-icon { color: var(--ox-accent); animation: oxu-spin 0.9s linear infinite; display: inline-block; }
.oxu-step--active .oxu-step-text { color: var(--ox-ink); font-weight: 500; }
.oxu-step--done .oxu-step-icon { color: var(--ox-accent); font-weight: 700; }
.oxu-step--done .oxu-step-text { color: var(--ox-body); }
@keyframes oxu-spin { to { transform: rotate(360deg); } }

.oxu-elapsed { color: var(--ox-muted); font-size: var(--ox-size-1); }
.oxu-elapsed span { font-weight: 500; color: var(--ox-body); }
.oxu-processing-note { color: var(--ox-muted); font-size: var(--ox-size-1); margin-top: 4px; }
.oxu-slow { color: var(--ox-caution); font-size: var(--ox-size-1); margin-top: 12px; font-weight: 500; }

@media (prefers-reduced-motion: reduce) {
  .oxu-step--active .oxu-step-icon { animation: none !important; }
}
@media print {
  .oxu-workspace, .oxu-processing { display: none !important; }
}

/* ── Results screen (completion pass, 2026-08-03) ──────────────────────────
   #oxr-results is the only thing left visible once a run completes (the
   processing wrap section above it is now hidden by product_results.js /
   verify_compare.js) — so it no longer needs `.ox-section`'s full page-rhythm
   padding, which read as a large empty band above "Audit/Assessment
   Complete". Tightened here, once, for every product that uses the shared
   results panel. */
#oxr-results {
  padding-top: var(--ox-s6);
}

/* ── Findings cards (completion pass, 2026-08-03) ───────────────────────────
   Presentation only — hierarchy, spacing, typography. product_results.js
   still decides which findings exist, how they're grouped and in what order;
   this only styles the markup it now emits with classes instead of inline
   style="" strings. Medium/low have no shared --ox-critical/--ox-caution-style
   token pair, so their colors stay literal here, same as they were inline. */
.oxr-finding-group__header {
  display: flex; align-items: center; gap: var(--ox-s3); margin: var(--ox-s6) 0 var(--ox-s3);
}
.oxr-finding-group__label {
  font-size: var(--ox-size-0); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
}
.oxr-finding-group__label--critical { color: var(--ox-critical); }
.oxr-finding-group__label--high { color: var(--ox-caution); }
.oxr-finding-group__label--medium { color: #92600A; }
.oxr-finding-group__label--low { color: var(--ox-muted); }
.oxr-finding-group__rule { flex: 1; height: 1px; background: var(--ox-border-subtle); }
.oxr-finding-group__count { color: var(--ox-muted); font-size: var(--ox-size-0); white-space: nowrap; }

.oxr-finding-group { display: flex; flex-direction: column; gap: var(--ox-s3); }

.oxr-finding-card {
  border-radius: var(--ox-radius-card); border: 1px solid; padding: var(--ox-s5);
  border-left-width: 4px;
}
.oxr-finding-card--critical { border-color: var(--ox-critical); background: var(--ox-critical-tint); }
.oxr-finding-card--high { border-color: var(--ox-caution); background: var(--ox-caution-tint); }
.oxr-finding-card--medium { border-color: #F2C94C; background: #FEF7E8; }
.oxr-finding-card--low { border-color: var(--ox-border); background: var(--ox-bg-subtle); }

.oxr-finding-card__head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--ox-s4);
  margin-bottom: var(--ox-s2);
}
.oxr-finding-card__rule { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.oxr-finding-card__id {
  font-size: var(--ox-size-0); font-weight: 600; color: var(--ox-muted); letter-spacing: 0.02em;
}
.oxr-finding-card__name { font-size: var(--ox-size-2); font-weight: 600; color: var(--ox-ink); line-height: 1.35; }
.oxr-finding-card__badge {
  flex-shrink: 0; font-size: var(--ox-size-0); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 3px 10px; border-radius: var(--ox-radius-badge); background: rgba(255, 255, 255, 0.6);
}
.oxr-finding-card--critical .oxr-finding-card__badge { color: var(--ox-critical); }
.oxr-finding-card--high .oxr-finding-card__badge { color: var(--ox-caution); }
.oxr-finding-card--medium .oxr-finding-card__badge { color: #92600A; }
.oxr-finding-card--low .oxr-finding-card__badge { color: var(--ox-muted); }

.oxr-finding-card__cell {
  display: inline-block; font-size: var(--ox-size-0); color: var(--ox-body); font-weight: 500;
  background: rgba(255, 255, 255, 0.55); padding: 2px 8px; border-radius: var(--ox-radius-code);
  margin-bottom: var(--ox-s2);
}
.oxr-finding-card__desc { font-size: var(--ox-size-1); color: var(--ox-body); line-height: 1.6; }

/* Approved narrative blocks (FIX-FAST-03) — the same "why it matters" and
   "recommended action" sentences the downloadable report prints for this rule.
   Only rendered when the product supplied them, so Audit's card is unchanged. */
.oxr-finding-card__note {
  font-size: var(--ox-size-1); color: var(--ox-body); line-height: 1.6; margin-top: var(--ox-s3);
}
.oxr-finding-card__note-label {
  display: block; font-size: var(--ox-size-0); font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ox-muted); margin-bottom: 2px;
}

/* ── Gated entry card ─────────────────────────────────────────────────────
   The upload card rendered as a link to a product's real gate (VERIFY email,
   FAST account) instead of as a live POST form — see the upload_gate_card
   macro. Identical chrome to the live card; the drop zone reads as the button
   it is, and the submit affordance is always in its ready state because there
   is no file to validate before the visitor reaches the gate. */
.oxu-card--gate { text-decoration: none; transition: border-color var(--ox-transition), box-shadow var(--ox-transition); }
.oxu-card--gate:hover { border-color: var(--ox-accent); }
.oxu-card--gate:hover .oxu-dropzone--gate { border-color: var(--ox-accent); background: var(--ox-accent-tint); }
.oxu-card--gate .oxu-submit { background: var(--ox-accent); color: #fff; border-color: var(--ox-accent); display: flex; }
.oxu-card--gate:hover .oxu-submit { background: var(--ox-accent-hover); border-color: var(--ox-accent-hover); }
.oxu-dropzone--gate { cursor: inherit; }
