/*
 * PDFs page (js/app/pages/pdfs.js): upload drop zone, selected file, upload
 * progress, live status card, and the job history table (js/app/jobs-table.js,
 * also used on the overview). Loaded after style.css and app.css; only
 * feature-specific rules, colours only through tokens.
 *
 *   1. Page sections
 *   2. Uploader (drop zone, file summary, errors, progress)
 *   3. Live status card
 *   4. Jobs table (stacked below 44rem of available width)
 *   5. Motion
 *
 * States never rely on colour alone: the drag-over zone changes border style
 * and its text, errors carry an "Error:" prefix and a bar, the steps of the
 * status card say "done/current/pending" in text.
 * Contrast: drop-zone border #6B7280 on #F9FAFB 4.6:1 (non-text >= 3:1);
 * drag-over border #166534 on #DCFCE7 6.5:1; muted labels #6B7280 only on
 * #FFFFFF / #F9FAFB.
 */

/* ---------- 1. Page sections ---------- */
.pdfs-convert h2,
.pdfs-history h2 {
  margin: 0 0 0.5rem;
}

.pdfs-convert h2:focus,
.pdfs-history h2:focus {
  outline: none;
}

.pdfs-convert h2:focus-visible,
.pdfs-history h2:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}

.pdfs-convert {
  scroll-margin-top: 1rem;
}

.pdfs-convert-intro {
  margin: 0 0 1rem;
}

.pdfs-history-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin-bottom: 0.25rem;
}

.pdfs-history-header h2 {
  margin: 0;
}

/* Owner only: the view selector starts the row below the heading, Refresh stays right. */
.pdfs-history-header:has(.pdfs-history-view:not([hidden])) {
  row-gap: 0.75rem;
  margin-bottom: 0.75rem;
}

.pdfs-history-header:has(.pdfs-history-view:not([hidden])) h2 {
  flex-basis: 100%;
}

.pdfs-history-view[hidden] {
  display: none;
}

.pdfs-history-meta {
  margin: 0 0 0.75rem;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.pdfs-history-meta:empty {
  margin: 0;
}

/* ---------- 2. Uploader ---------- */
.uploader > * + * {
  margin-top: 1rem;
}

.uploader-drop {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 1.5rem 1rem;
  border: 2px dashed var(--color-text-muted);
  border-radius: var(--radius);
  background: var(--color-bg-alt);
  text-align: center;
}

.uploader-drop.is-dragover {
  border: 3px solid var(--color-primary-dark);
  background: var(--color-primary-light);
}

.uploader-icon {
  width: 2.5rem;
  height: 2.5rem;
  fill: none;
  stroke: var(--color-primary-dark);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.uploader-drop-title {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 700;
}

.uploader-or {
  margin: 0;
  color: var(--color-text-muted);
}

.uploader-drop.is-dragover .uploader-or {
  color: var(--color-text);
}

.uploader-hint {
  margin: 0;
}

.uploader-drop.is-dragover .uploader-hint {
  color: var(--color-text);
}

/*
 * The native file input stays in the tab order and in the accessibility tree
 * (it receives keyboard focus and opens the file picker); it is only visually
 * replaced by its label, which shows the focus ring.
 */
.uploader-input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.uploader-input:focus-visible + .uploader-choose {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--color-bg);
}

.uploader-input:disabled + .uploader-choose {
  background: var(--color-bg-alt);
  border-color: var(--color-border-strong);
  color: var(--color-text-muted);
  cursor: not-allowed;
}

.uploader.is-disabled .uploader-drop {
  border-style: dotted;
  border-color: var(--color-border-strong);
}

.uploader-disabled[hidden],
.uploader-file[hidden],
.uploader-progress[hidden] {
  display: none;
}

.uploader-disabled:focus {
  outline: none;
}

.uploader-disabled:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}

/* Empty while there is no error; stays in the DOM so role="alert" announces new text. */
.uploader-error:empty {
  margin-top: 0;
}

.uploader-error:not(:empty) {
  padding-left: 0.75rem;
  border-left: 4px solid var(--color-error);
}

.uploader.has-error .uploader-drop {
  border-color: var(--color-error);
  border-style: solid;
}

.uploader-file {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 1rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
}

.uploader-file-heading {
  flex-basis: 100%;
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.uploader-file-line {
  flex: 1 1 12rem;
  min-width: 0;
  margin: 0;
}

.uploader-file-name {
  font-weight: 700;
  overflow-wrap: anywhere;
}

.uploader-file-size {
  color: var(--color-text-muted);
  white-space: nowrap;
}

.uploader-progress {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
}

.uploader-progress-label {
  flex-basis: 100%;
  font-weight: 600;
}

.uploader-progress progress {
  flex: 1 1 12rem;
  min-width: 0;
  height: 0.75rem;
  accent-color: var(--color-primary-dark);
}

.uploader-actions .button {
  min-width: 10rem;
}

/* ---------- 3. Live status card ---------- */
.job-live {
  margin-top: 1.25rem;
  margin-bottom: 0;
  border-left: 4px solid var(--color-border-strong);
}

.job-live--done {
  border-left-color: var(--color-primary-dark);
}

.job-live--warning {
  border-left-width: 6px;
  border-left-color: var(--color-warning);
}

.job-live--failed {
  border-left-width: 6px;
  border-left-color: var(--color-error);
}

.job-live > * + * {
  margin-top: 0.75rem;
}

.job-live .app-notice {
  margin-bottom: 0;
}

.job-live-title {
  margin: 0;
  overflow-wrap: anywhere;
}

.job-live-title:focus {
  outline: none;
}

.job-live-title:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}

.job-live-status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  margin-bottom: 0;
}

.job-live-size,
.job-live-note {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.job-live-note {
  margin-bottom: 0;
}

.job-live-description {
  margin-bottom: 0;
}

.job-live-steps {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.25rem;
  margin: 0.75rem 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
}

.job-live-step {
  display: inline-block;
}

/* Marker shape: empty ring = pending, thick ring = current, filled = done (text says the same). */
.job-live-step::before {
  content: "";
  display: inline-block;
  margin-right: 0.375rem;
  vertical-align: -0.0625rem;
  box-sizing: border-box;
  width: 0.75rem;
  height: 0.75rem;
  border: 2px solid var(--color-text-muted);
  border-radius: 50%;
}

.job-live-step--current {
  font-weight: 700;
}

.job-live-step--current::before {
  border: 4px solid var(--color-primary-dark);
}

.job-live-step--done::before {
  border-color: var(--color-primary-dark);
  background: var(--color-primary-dark);
}

.job-live-step-state {
  color: var(--color-text-muted);
}

/* ---------- 4. Jobs table ---------- */
.jobs-table-wrap {
  container-type: inline-size;
}

.jobs-table .jobs-cell-label {
  display: none;
}

.jobs-cell--document {
  min-width: 10rem;
}

.jobs-doc-name {
  overflow-wrap: anywhere;
}

/* The document name links to the job page; it reads as a name, underlined on hover */
.jobs-doc-link {
  color: var(--color-text);
  font-weight: 600;
  text-decoration: none;
}

.jobs-doc-link:hover {
  color: var(--color-link);
  text-decoration: underline;
}

.jobs-sim-badge {
  margin-left: 0.25rem;
}

.jobs-cell--pages {
  font-variant-numeric: tabular-nums;
}

.jobs-cell--date {
  white-space: nowrap;
}

.jobs-empty,
.jobs-loading {
  margin: 0;
  padding: 1rem;
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
}

.jobs-unknown {
  color: var(--color-text-muted);
}

/*
 * Narrow containers: every row becomes a block of label/value lines, so the
 * page never scrolls horizontally (320px). Table roles are set explicitly in
 * the markup, so the semantics survive the display change.
 */
@container (max-width: 44rem) {
  .jobs-table,
  .jobs-table tbody,
  .jobs-table tr,
  .jobs-table caption {
    display: block;
  }

  .jobs-table thead {
    display: block;
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .jobs-table caption {
    padding-bottom: 0.5rem;
  }

  .jobs-table tbody tr {
    padding: 0.75rem 0;
    border-top: 1px solid var(--color-border);
  }

  .jobs-table tbody th,
  .jobs-table tbody td {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    min-width: 0;
    padding: 0.25rem 1rem;
    border-bottom: 0;
    white-space: normal;
  }

  .jobs-table tbody th {
    font-size: var(--text-base);
  }

  .jobs-table .jobs-cell-label {
    display: block;
    flex: 0 0 7.5rem;
    color: var(--color-text-muted);
    font-weight: 400;
  }

  .jobs-table .jobs-cell-value {
    flex: 1 1 auto;
    min-width: 0;
  }

  .jobs-table .jobs-cell--actions {
    padding-top: 0.5rem;
  }
}

@container (max-width: 22rem) {
  .jobs-table tbody td {
    flex-direction: column;
    gap: 0.125rem;
  }

  .jobs-table .jobs-cell-label {
    flex-basis: auto;
  }
}

/* ---------- 5. Motion ---------- */
@media (prefers-reduced-motion: no-preference) {
  .uploader-drop {
    transition: background-color 0.15s ease, border-color 0.15s ease;
  }
}
