/* uploads.css — الرفع. Scoped to #view-uploads so it cannot leak into the
   review screens; reuses the app's own variables so it stays one product. */

#view-uploads { padding: 14px 16px 40px; }

.up-note {
  padding: 8px 12px; border-radius: 8px; margin-bottom: 12px;
  background: rgba(77, 171, 247, .10); border: 1px solid rgba(77, 171, 247, .40);
  color: var(--accent); font-size: 13px;
}
.up-note.bad {
  background: rgba(240, 90, 90, .10); border-color: rgba(240, 90, 90, .45);
  color: var(--red, #f05a5a);
}

.up-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 12px; }
.up-lbl { font-size: 12px; color: var(--dim); }
.up-sel, .up-bar input, .up-field input, .up-field select {
  background: var(--panel, #12161c); color: var(--text);
  border: 1px solid var(--line); border-radius: 7px; padding: 5px 9px;
  font: inherit; font-size: 13px;
}
.up-btn {
  font: inherit; font-size: 13px; cursor: pointer; color: var(--text);
  background: none; border: 1px solid var(--line); border-radius: 7px;
  padding: 5px 12px;
}
.up-btn:hover { border-color: var(--accent); color: var(--accent); }
.up-btn.primary {
  color: var(--accent); border-color: rgba(77, 171, 247, .55);
  background: rgba(77, 171, 247, .10);
}
.up-btn:disabled { opacity: .5; cursor: default; }

.up-tabs { display: flex; gap: 6px; margin: 14px 0 10px; }
.up-tab {
  font: inherit; font-size: 13px; cursor: pointer; padding: 5px 14px;
  border-radius: 8px 8px 0 0; border: 1px solid var(--line);
  border-bottom: none; background: none; color: var(--dim);
}
.up-tab.on { color: var(--accent); border-color: rgba(77, 171, 247, .5);
  background: rgba(77, 171, 247, .08); }

.up-card {
  border: 1px solid var(--line); border-radius: 10px; padding: 14px;
  background: rgba(255, 255, 255, .015); margin-bottom: 14px;
}
.up-card h3 { margin: 0 0 8px; font-size: 14px; }
.up-hint { margin: 0 0 12px; font-size: 12px; color: var(--dim);
  line-height: 1.7; }

.up-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px; margin-bottom: 12px;
}
.up-field { display: flex; flex-direction: column; gap: 4px; }
.up-field label { font-size: 12px; color: var(--dim); }
/* MEASUREMENTS ARE TYPED LEFT-TO-RIGHT. A number input inside an RTL page
   puts the caret at the right and pushes the decimal point around as you
   type — "0.40" is genuinely hard to enter. The LABEL stays Arabic; only the
   field is flipped, which is how a bilingual form should behave. */
.up-field input[type="number"],
.up-field input[type="date"] {
  direction: ltr;
  text-align: left;
  font-variant-numeric: tabular-nums;
}

/* drop zone */
.up-drop {
  border: 2px dashed var(--line); border-radius: 10px; padding: 30px 16px;
  text-align: center; cursor: pointer; transition: border-color .15s,
  background .15s;
}
.up-drop:hover, .up-drop.over {
  border-color: var(--accent); background: rgba(77, 171, 247, .06);
}
.up-drop-t { font-size: 15px; margin-bottom: 4px; }
.up-drop-s { font-size: 12px; color: var(--dim); }

/* queue */
.up-queue { margin-top: 14px; display: flex; flex-direction: column; gap: 6px; }
.up-row {
  display: grid; grid-template-columns: 1fr auto 140px auto; gap: 10px;
  align-items: center; font-size: 12px; padding: 6px 8px; border-radius: 7px;
  border: 1px solid var(--line);
}
.up-row.ok { border-color: rgba(80, 200, 120, .4); }
.up-row.bad { border-color: rgba(240, 90, 90, .45); }
.up-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  direction: ltr; text-align: right; }
/* LTR: an RTL paragraph renders "1.0 MB" as "MB 1.0". Sizes, percentages
   and filenames are Latin-script data and read left-to-right. */
.up-size { color: var(--dim); font-variant-numeric: tabular-nums;
  direction: ltr; }
.up-prog { height: 6px; border-radius: 4px; background: rgba(255,255,255,.07);
  overflow: hidden; }
.up-fill { height: 100%; background: var(--accent); transition: width .2s; }
.up-state { color: var(--dim); white-space: nowrap; }
.up-row.ok .up-state { color: rgba(80, 200, 120, .95); }
.up-row.bad .up-state { color: var(--red, #f05a5a); }

/* tables (CSV preview, calibration list) */
.up-counts { font-size: 12px; color: var(--dim); margin: 10px 0; }
.up-table { width: 100%; border-collapse: collapse; margin-top: 10px;
  font-size: 12px; display: block; overflow-x: auto; }
.up-table th, .up-table td {
  border-bottom: 1px solid var(--line); padding: 5px 8px; text-align: right;
  white-space: nowrap;
}
.up-table th { color: var(--dim); font-weight: 500; }


/* ------------------------------------------------------- calibration bench
   The calibration take is where every measurement comes from, so this panel
   is built to be LOOKED at closely rather than skimmed. */

.up-thumbs { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 14px; }
.up-thumb {
  display: block; width: 92px; height: 92px; border-radius: 8px;
  overflow: hidden; border: 1px solid var(--line); background: #0b0e13;
}
.up-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.up-thumb:hover { border-color: var(--accent); }
.up-thumb-wrap { position: relative; }
.up-thumb-x {
  position: absolute; top: -6px; inset-inline-end: -6px;
  width: 20px; height: 20px; line-height: 1; padding: 0;
  border-radius: 50%; cursor: pointer; font-size: 14px;
  color: var(--text); background: #2a1418; border: 1px solid var(--red);
}
.up-thumb-x:hover { background: var(--red); color: var(--panel); }

.up-recalled {
  border-color: rgba(240, 180, 41, .55) !important;
  background: rgba(240, 180, 41, .07);
}
.up-recalled::placeholder { color: var(--amber); }

.up-num { direction: ltr; text-align: left; font-variant-numeric: tabular-nums; }

/* The viewport clips; the stage scales inside it. Zooming a transform rather
   than the video keeps the canvas and the frame locked together — scaling
   them separately is how an overlay drifts off the body at high zoom. */
.calib-viewport {
  position: relative; overflow: auto; max-height: 62vh;
  display: flex; justify-content: center;
  border: 1px solid var(--line); border-radius: 10px; background: #000;
  margin: 10px 0;
}
/* Sized to the FOOTAGE, not the panel. These takes are portrait, so a
   full-width stage letterboxes the body into a thin column with black either
   side — and that column is exactly what an operator wants to zoom into. */
.calib-stage {
  position: relative; transform-origin: top center;
  height: 60vh; aspect-ratio: 9 / 16; width: auto;
  margin-inline: auto;
}
.calib-stage video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; display: block;
}
.calib-stage canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none;
}

/* ---- intake: the workflow banner -------------------------------------------
   Uploading and processing used to be invisible to each other. This draws the
   whole chain so "where is it?" is answered by looking, and the tally counts
   ARTIFACTS rather than trusting that a step exited zero — four stages
   silently did nothing in one week and the only symptom was clips staying
   unmapped for days. */
.intake { margin: 14px 0; }
.intake-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.intake-head button { font-weight: 600; padding: 6px 16px; }
.intake-msg { color: var(--dim); }
.intake-msg.bad { color: var(--red); font-weight: 600; }
.intake-mins { color: var(--dim); font-variant-numeric: tabular-nums; }

.intake-steps {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin: 10px 0 0;
  padding: 0;
}
.intake-steps li {
  flex: 1 1 120px;
  min-width: 110px;
  padding: 6px 10px 6px 0;
  border-top: 3px solid var(--line);
  margin-inline-end: 6px;
}
.intake-steps .lbl { display: block; font-weight: 600; font-size: .95em; }
.intake-steps .hint { display: block; color: var(--dim); font-size: .8em; }
.intake-steps .dot { display: none; }

.intake-steps li.ok   { border-top-color: var(--green); }
.intake-steps li.ok   .lbl { color: var(--green); }
.intake-steps li.now  { border-top-color: var(--amber); }
.intake-steps li.now  .lbl { color: var(--amber); }
/* the current stage pulses, so a long stage still looks alive */
.intake-steps li.now  .lbl::after { content: " ⋯"; }
.intake-steps li.bad  { border-top-color: var(--red); }
.intake-steps li.bad  .lbl { color: var(--red); }
.intake-steps li.todo .lbl { color: var(--dim); }

.intake-tally {
  display: flex; gap: 14px; flex-wrap: wrap;
  margin-top: 10px; color: var(--dim); font-size: .9em;
}
.intake-tally b { font-variant-numeric: tabular-nums; color: var(--text); }

/* ---- what is actually in raw/inbox/ ---------------------------------------- */
.inbox-folder { margin-top: 12px; font-size: .9em; }
.inbox-folder.empty { color: var(--dim); }
.inbox-folder summary { cursor: pointer; color: var(--text); }
.inbox-folder ul { list-style: none; margin: 8px 0 0; padding: 0;
                   max-height: 260px; overflow-y: auto; }
.inbox-folder li { display: flex; justify-content: space-between; gap: 12px;
                   padding: 2px 6px; border-bottom: 1px solid var(--line); }
.inbox-folder li.side { color: var(--dim); }      /* XML sidecars, not footage */
.inbox-folder li.more { color: var(--dim); justify-content: center; }
.inbox-folder .sz { font-variant-numeric: tabular-nums; color: var(--dim); }

/* ---- how many jobs are in flight, and where ---------------------------------
   "Is it still going?" used to be answered by a mood. Zero jobs with an
   unfinished stage is a stalled run, and it says so now. */
.intake-jobs { margin-top: 10px; font-size: .9em; color: var(--text); }
.intake-jobs.none { color: var(--red); font-weight: 600; }
.intake-jobs b { font-variant-numeric: tabular-nums; }
.intake-jobs ul { list-style: none; margin: 6px 0 0; padding: 0; }
.intake-jobs li {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 2px 8px; border-inline-start: 3px solid var(--amber);
  background: color-mix(in srgb, var(--amber) 12%, var(--panel)); margin-bottom: 3px;
}
.intake-jobs .jm { color: var(--dim); font-variant-numeric: tabular-nums; }

/* ---- can the cards be wiped? ----------------------------------------------
   Asked by hand after every filming day. A stale yes is the dangerous one, so
   the age of the check and any footage shot since it are part of the answer. */
.nas { margin-top: 12px; padding: 8px 12px; border-radius: 4px;
       display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.nas.ok      { background: color-mix(in srgb, var(--green) 14%, var(--panel)); border-inline-start: 4px solid var(--green); }
.nas.bad     { background: color-mix(in srgb, var(--red) 14%, var(--panel)); border-inline-start: 4px solid var(--red); }
.nas.unknown { background: var(--panel); border-inline-start: 4px solid var(--dim); }
.nas.ok b  { color: var(--green); }
.nas.bad b { color: var(--red); }
.nas .nas-sub { color: var(--dim); font-size: .88em; }
.nas button { margin-inline-start: auto; }

/* ---- where each filming day's footage lives now -----------------------------
   "on NAS only" is the healthy end state after storage_plan.py evicts a
   verified day — but only because the NAS column beside it is populated. Both
   are shown so the one row that should never exist, neither here nor there,
   is obvious. */
.sessions-store { margin-top: 10px; font-size: .88em; }
.sessions-store summary {
  cursor: pointer;
  color: var(--dim);
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel);
  transition: border-color .12s ease;
}
.sessions-store summary:hover { border-color: var(--accent); }
.sessions-store summary b { color: var(--text); }
.sessions-store[open] summary { border-color: var(--accent); }
.sessions-store table { width: 100%; border-collapse: collapse; margin-top: 8px; }
.sessions-store th, .sessions-store td {
  text-align: start; padding: 3px 8px; border-bottom: 1px solid var(--line);
}
.sessions-store th { color: var(--dim); font-weight: 600; }
.sessions-store td.n { font-variant-numeric: tabular-nums; }
.sessions-store .both { color: var(--green); }
.sessions-store .arch { color: var(--dim); }
.sessions-store .bad  { color: var(--red); font-weight: 600; }
.sessions-store tr.split td { background: color-mix(in srgb, var(--amber) 12%, var(--panel)); }
.sessions-store .warn { color: var(--amber); }
.sessions-store .cnt { color: var(--dim); font-variant-numeric: tabular-nums; }
.sessions-store .split-note { color: var(--amber); margin: 8px 0 0; font-size: .95em; }
.sessions-store button.evict {
  font-size: .85em; padding: 1px 10px;
  border-color: var(--amber); color: var(--amber); background: var(--panel);
}
.sessions-store button.evict:disabled { opacity: .6; }
.sessions-store .disk {
  margin-inline-start: 12px; color: var(--dim);
  font-variant-numeric: tabular-nums;
}
.sessions-store .disk b { color: var(--green); }
/* above 85% an eviction stops being housekeeping and starts being urgent */
.sessions-store .disk.tight b { color: var(--amber); }

/* ---- drop-point picker (multi-site inbox) ---------------------------- */
.site-bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 0 0 10px; }
.site-pick { display: inline-flex; align-items: center; gap: 8px;
  background: var(--card); border: 1px solid var(--line); border-radius: 9px;
  padding: 6px 10px; }
.site-pick span { color: var(--dim); font-size: 13px; }
.site-pick select { background: var(--panel); color: var(--text);
  border: 1px solid var(--line); border-radius: 6px; padding: 4px 8px;
  font: inherit; max-width: 60vw; }
.site-btn { background: var(--panel); color: var(--text); font: inherit;
  border: 1px solid var(--line); border-radius: 8px; padding: 6px 12px;
  cursor: pointer; }
.site-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.site-btn:disabled { opacity: .6; cursor: default; }
.site-note { color: var(--dim); font-size: 13px; margin: 0; flex-basis: 100%; }
.site-warn { color: var(--amber); font-size: 13px; margin: 0; flex-basis: 100%; }

/* the setup-script link is a button, and <a> does not inherit button metrics */
a.site-btn { text-decoration: none; display: inline-block; line-height: 1.5; }

/* "how?" panel for the lab setup script */
.site-how { flex-basis: 100%; background: var(--card); border: 1px solid var(--line);
  border-radius: 10px; padding: 12px 16px; margin-top: 4px; }
.site-how ol { margin: 0; padding-inline-start: 20px; }
.site-how li { margin: 6px 0; line-height: 1.7; }
.site-how p { color: var(--dim); font-size: 13px; margin: 10px 0 0; }
.site-how code { background: var(--panel); border: 1px solid var(--line);
  border-radius: 4px; padding: 1px 6px; direction: ltr; unicode-bidi: embed;
  font-size: 13px; }
.site-cmd { display: flex; align-items: center; gap: 8px; margin: 6px 0;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  padding: 8px 10px; }
.site-cmd code { background: none; border: 0; padding: 0; flex: 1;
  overflow-x: auto; white-space: nowrap; }
.site-cmd button { background: var(--bg); color: var(--text); font: inherit;
  border: 1px solid var(--line); border-radius: 6px; padding: 3px 12px;
  cursor: pointer; white-space: nowrap; }
.site-cmd button:hover { border-color: var(--accent); color: var(--accent); }

/* where the lab's footage is right now */
.site-journey { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 10px;
  align-items: center; background: var(--card); border: 1px solid var(--line);
  border-radius: 9px; padding: 8px 12px; font-size: 13px; }
.site-journey b { color: var(--text); font-size: 15px; }
.site-journey span { color: var(--dim); }
.site-journey .arrow { color: var(--accent); font-size: 15px; }
.site-journey .j-note { flex-basis: 100%; font-size: 12px; }
.site-journey .j-when { margin-inline-start: auto; font-size: 12px; }
/* the puller reports every 15 min; older than that and the number is a guess */
.site-journey.stale { border-color: var(--amber); }
.site-journey.stale .j-when { color: var(--amber); }

/* which team this inbox belongs to — Mihwar mornings, KWSL 17:00–19:00 */
.team-banner { margin: 0 0 10px; padding: 10px 14px; font-size: 15px; border-radius: 10px; border: 2px solid; }
.team-banner .en { display: block; font-size: 12px; opacity: .8; }
.team-banner.mihwar { background: rgba(47,191,113,.12); border-color: #2fbf71; }
/* files the drop zone refused — loud on purpose (inbox.js addFiles) */
.up-refused { display: block; margin: 10px 0; padding: 10px 14px; border-radius: 10px;
  border: 2px solid #e5484d; background: rgba(229,72,77,.12); }
.up-refused[hidden] { display: none; }
.up-refused b { color: #e5484d; font-size: 16px; display: block; }
.up-refused span { font-size: 13px; opacity: .85; display: block; margin: 4px 0; }
.up-refused ul { margin: 6px 0 0; padding-inline-start: 20px; font-size: 13px; max-height: 160px; overflow: auto; }
