/* Submit a quest: the composer on one side, what has already gone on
   the other, and one column with the composer first on a phone. Form
   fields, hints, pills, buttons and the O/I rocker are shared in
   ../assets/site.css; only what is particular to this page is here. */

.sub-page {
  /* One indent for every code chip on the page: the picker's matches,
     the score sheet's lines, the submissions list and the numerals in
     What happens next all start on it, so a column has two left edges
     rather than five. In rem, so it grows with the text-size ladder —
     at the 200% stop a code set in a 58px track ran into the words
     beside it. */
  --sub-chip: 3.65rem;
  --sub-gap: 12px;
}

/* ---------------- the board ----------------
   The page's name on the sign. The plate starts where the nav's stripe
   ends, the way the home and messages pages do it: a band of paper
   between two blacks at the top of the page reads as a fault.

   The same band every other page's name sits in: .hero runs 30px above
   and below its title and this ran 34, which made the one title on the
   site sitting in a taller black box read as a different size. */
.sub-board {
  margin-top: calc(var(--shell-top, 32px) * -1);
  padding-top: 30px;
  padding-bottom: 30px;
}

/* `.themed h1` paints the page's ink, which on the sign would leave
   the title black on black. */
.sub-board h1 { color: var(--sign-ink); }

/* ---------------- Submit / Compress ----------------
   Two views of one page, and a control on the paper under the board
   rather than a second black band joined onto it. Drawn as a band it
   was black type on black from the top of the screen to the bottom of
   the row, and in the app layout, where the board is gone and the
   page's name is in the bar, it was a stripe of black under the bar
   with nothing above it to belong to. A row that picks one of two is a
   control, and this page's controls are on the paper.

   Sticky, because the bar on the view you are not looking at is the
   only report a run in it makes — which is also why it takes a ground
   and a hairline: stuck over the page, it has to be something the
   content passes under rather than through. */
.sub-tabs {
  position: sticky;
  top: var(--nav-h, 64px);
  z-index: 1050;
  /* Full bleed, measured off the shell the way .plate does it: --gutter
     is the grid's column gap rather than the shell's inset, and using
     it overhangs the viewport either side. */
  margin: 0 calc(50% - 50vw) 10px;
  padding: 14px calc(50vw - 50%);
  /* The bar's ground, not the page's: stuck under the top bar it is the
     same object continued, and on the page's own paper it read as a
     strip of nothing between two whites. --bar-edge is the hairline
     that boundary uses everywhere else. */
  background: var(--bar-bg);
  border-bottom: 1px solid var(--bar-edge);
}
/* The app layout spaces the body by the bar's height already, so there
   `top: 0` is immediately under it; on the web the body has no padding
   and the bar is fixed over it, so there the offset is the bar's own
   height. */
html.is-pwa .sub-tabs {
  top: 0;
  margin-top: calc(var(--shell-top, 32px) * -1);
}

/* The row goes with the top bar: a downward scroll takes both away and
   an upward flick brings both back, on the bar's own clock. It has to
   clear its own height AND the bar's, because it is stuck under the
   bar rather than at the top of the screen; overshooting costs nothing
   once it is off the edge. The run's bar on the view you are not
   looking at goes with it, which is the one thing given up here — the
   same flick that brings the chrome back brings it too. */
.sub-tabs { transition: transform var(--chrome-slide); }
html.nav-up .sub-tabs {
  transform: translateY(calc(-100% - var(--nav-h, 64px) - env(safe-area-inset-top, 0px)));
}

/* Centred where the page's name is centred — in the bar above it. On a
   desktop the name is on the page's own left edge and so is everything
   under it, so the row stays there. */
@media (max-width: 840px) {
  .sub-tabs-inner { margin-left: auto; margin-right: auto; }
}

.sub-tabs-inner {
  display: grid;
  /* Equal tracks: a block that fills one of them has to be the same
     size on either side, and the labels are position markers that never
     move. */
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  /* It is a control, not two banners: given the whole of a wide page it
     reads as a pair of them. Left, on the page's own edge, like
     everything else. */
  max-width: 420px;
}

/* Two chips, drawn the way the quest list draws its category chips —
   the site already has one answer to picking one of a set, and it is
   one that works in both themes. Half of an outlined box filled black
   does not: in the dark theme the sign's black is #0c0c0c against the
   paper's #1b1b19, so the picked half came out a shade DARKER than its
   neighbour and the grey lines of the box ran round both. What the
   chip does instead is give up its outline when it is picked, and that
   is the signal that survives the theme. */
.sub-tab {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 11px 14px;
  border: 1px solid var(--border-strong);
  border-radius: 2px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: var(--t-small);
  font-weight: 800;
  cursor: pointer;
  /* the run's bar stops at the chip's own edge */
  overflow: hidden;
}
.sub-tab:active { transform: translate(1px, 1px); }

/* The view you are in is a filled black chip: the strongest signal
   there is, and the one a thumb can read without stopping. It is the
   sign's black rather than the accent, because green on this page means
   the action — Send, Choose a video, Use as proof — and a picked tab is
   not one.

   It does not slide across. A block that travels is the site's rocker,
   but the rocker's thumb carries no words: here the label under the
   arriving block is dark on black for the length of the journey, and
   every way of timing the two around each other is a way of getting it
   wrong later. The switch is instant, which for two segments reads as
   crisp rather than cheap. */
.sub-tab[aria-selected="true"] {
  background: var(--sign-bg);
  border-color: var(--sign-bg);
  color: var(--sign-ink);
}

/* The share of a run, where there is one to report. Tabular so the
   figure does not jitter as it counts, and a floor under it so the
   label does not slide sideways when it appears. */
.sub-tab-pct {
  min-width: 2.6em;
  text-align: left;
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 700;
}
.sub-tab-pct:empty { display: none; }

/* The bar. No groove behind it — the segment's own edge is the groove,
   and a groove would have to be two colours to show on both halves. */
.sub-tab-track {
  position: absolute;
  left: 4px;
  right: 4px;
  bottom: 3px;
  height: 3px;
  overflow: hidden;
  opacity: 0;
  transition: opacity var(--duration-quick) var(--ease-in-out);
}
.sub-tab-track.is-on { opacity: 1; }
.sub-tab-track > span {
  display: block;
  width: 0;
  height: 100%;
  background: var(--accent-solid);
  transition: width var(--duration-fast) var(--ease-smooth-out);
}
/* Nothing to count yet — fetching the engine, reading a file in. The
   block shuttles instead of standing at zero, which reads as stopped. */
.sub-tab-track.is-waiting > span {
  width: 34%;
  animation: sub-tab-shuttle 1.5s var(--ease-in-out) infinite;
  transition: none;
}
@keyframes sub-tab-shuttle {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(194%); }
}
@media (prefers-reduced-motion: reduce) {
  .sub-tab-track,
  .sub-tab-track > span { transition: none; }
  .sub-tab-track.is-waiting > span { animation: none; width: 100%; }
}

/* ---------------- signing in ---------------- */
#sub-login { margin-top: 56px; }
.sub-signin { max-width: 560px; }
.sub-signin .sub-error { margin-bottom: 0; }

/* The one action of each half of the page is a bar the width of what
   it acts on: the strongest control the page has, and the only thing
   on it shaped like the thing you press. */
.sub-bar-btn {
  display: flex;
  width: 100%;
  justify-content: center;
  padding: 16px 20px;
  font-size: var(--t-lede);
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* ---------------- the two columns ----------------
   Six of the site's twelve columns each, so the halves land on the
   page's own verticals rather than on a grid of this page's own. */
#sub-main { margin-top: 56px; }
#sub-uploads,
#sub-resume { margin: 0 0 26px; }
.sub-cols { margin-top: 0; }
.sub-col-send { grid-column: 1 / 7; }
.sub-col-sent { grid-column: 7 / -1; }
.sub-col > .section:first-child { margin-top: 0; }

@media (max-width: 900px) {
  .sub-col-send,
  .sub-col-sent { grid-column: 1 / -1; }
  .sub-col-sent { margin-top: 56px; }
}

/* ---------------- quest picker ----------------
   Every match is listed; past a screen's worth the list scrolls.

   One box with a list in it, not a stack of boxes. A bordered button
   per row drew an edge round every quest, so a search for two letters
   read as a pile of cards rather than a list of quests. The rows are
   rows, told apart by the hairline between them — the same way the
   fullscreen map's search panel lists the same quests. It sits in the
   column under the box it belongs to and carries no shadow: it is part
   of the form rather than something opened over it. */
.sub-matches {
  margin: -6px 0 12px;
  max-height: min(46vh, 420px);
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--border);
  border-radius: 2px;
  background: var(--surface);
}
.sub-matches[hidden] { display: none; }
.sub-matches button {
  display: grid;
  /* the indent is a floor, not a cap: a seven-character code is wider
     than it, and a fixed track put the code over the name */
  grid-template-columns: minmax(var(--sub-chip), max-content) minmax(0, 1fr);
  gap: var(--sub-gap);
  align-items: baseline;
  min-width: 0; /* a grid item's default minimum is its content, which let long names push past the edge */
  width: 100%;
  margin: 0;
  padding: 11px 12px;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background var(--duration-quick) var(--ease-smooth-out);
}
.sub-matches button + button { border-top: 1px solid var(--border); }
.sub-matches button:hover,
.sub-matches button:focus-visible { background: var(--page-bg); }
.sub-matches button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.sub-matches .sub-match-code { justify-self: start; }
.sub-matches .sub-match-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* nothing found is a line in the same box, not an empty one */
.sub-matches .sub-none {
  margin: 0;
  padding: 11px 12px;
  color: var(--muted);
}

/* The quest's claim: the one black object the composer spends, on the
   line under the control that sets it. */
.sub-picked {
  margin: -4px 0 14px;
  padding: 12px 16px;
  background: var(--sign-bg);
  color: var(--sign-ink);
  border-radius: 2px;
  font-weight: 800;
  display: flex;
  gap: 14px;
  align-items: baseline;
  flex-wrap: wrap;
}
.sub-picked a {
  color: var(--sign-ink);
  font-weight: 700;
  margin-left: auto;
  text-decoration: none;
  border-bottom: 2px solid currentColor;
}
.sub-picked .code { background: var(--sign-ink); color: var(--sign-bg); }

/* ---------------- the quest's answer box ----------------
   A count, a line, places or codes. On the paper with the rest of the
   fields, between two hairlines rather than in a box of its own: the
   quest asked the question, so it is part of the form and not an
   aside. */
.sub-answer {
  margin: 0 0 14px;
  padding: 14px 0 4px;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.sub-answer .sub-hint { margin-top: 0; }
.sub-answer .sub-check { margin: 10px 0 0; }
.sub-answer .sub-field:last-child { margin-bottom: 10px; }
.sub-pick-results { margin: 0 0 8px; }

/* a count: one control, with the minus and the plus a thumb can hit */
.sub-step {
  display: grid;
  grid-template-columns: 52px minmax(84px, 1fr) 52px;
  max-width: 220px;
  height: 52px;
  border: 1px solid var(--border-strong);
  border-radius: 2px;
  background: var(--surface);
  overflow: hidden;
}
.sub-step-btn {
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: var(--t-lede);
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
}
.sub-step-btn:hover { background: var(--page-bg); }
.sub-field .sub-step input {
  width: 100%;
  height: 100%;
  border: 0;
  border-left: 1px solid var(--border-strong);
  border-right: 1px solid var(--border-strong);
  border-radius: 0;
  background: transparent;
  text-align: center;
  font-weight: 800;
  font-variant-numeric: tabular-nums lining-nums;
}

.sub-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
.sub-chip {
  border: 1px solid var(--border-strong);
  border-radius: 2px;
  background: var(--surface);
  color: var(--text);
  padding: 4px 10px;
  font: inherit;
  font-size: var(--t-small);
  font-weight: 700;
  cursor: pointer;
}
.sub-chip::after { content: ' \00d7'; color: var(--muted); }
.sub-chip:hover { border-color: var(--accent); }

/* ---------------- the files waiting to go ----------------
   A row per file: the name in a box to type over with the extension
   fixed after it, and what it weighs. */
.sub-files { list-style: none; margin: 0 0 4px; padding: 0; }
.sub-files li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  column-gap: var(--sub-gap);
  row-gap: 4px;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.sub-files li:last-child { border-bottom: 0; }
.sub-files .sub-file-nudge {
  grid-column: 1 / -1;
  color: var(--muted);
  font-size: var(--t-small);
}
.sub-files .sub-file-size {
  color: var(--muted);
  font-size: var(--t-small);
  text-align: right;
  font-variant-numeric: tabular-nums lining-nums;
}
.sub-files .sub-file-name { display: flex; align-items: baseline; min-width: 0; }
.sub-field-note { margin-top: 18px; }
.sub-files .sub-file-rename {
  flex: 1;
  min-width: 0;
  padding: 7px 8px;
  border: 1px solid var(--border);
  border-radius: 2px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
}
.sub-files .sub-file-rename:focus { outline: none; border-color: var(--accent); }
.sub-files .sub-file-ext { color: var(--muted); flex: none; padding-left: 2px; }

/* Taking a file back off. The picker replaces its own selection, so
   this only has something to do since the compressor started adding
   files to a list the picker did not make. */
.sub-files .sub-file-drop {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 2px;
  background: none;
  color: var(--muted);
  cursor: pointer;
}
.sub-files .sub-file-drop svg { width: 16px; height: 16px; }
.sub-files .sub-file-drop:hover { border-color: var(--border-strong); color: var(--text); }
.sub-files .sub-file-drop:active { transform: translate(1px, 1px); }
.sub-files li.is-too-big,
.sub-files li.is-too-big .sub-file-size { color: var(--alert-ink); font-weight: 700; }

/* the action, and the thin bar that counts the request's own bytes */
.sub-actions { display: grid; gap: 10px; margin-top: 18px; }
.sub-actions .sub-progress { max-width: none; }

/* ---------------- picking an interrupted upload back up ---------- */
.sub-resume-row {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 14px;
}
.sub-resume-row .sub-resume-label { flex: 1; min-width: 200px; }
.sub-resume-row .sub-up-quest { align-self: center; }

/* ---------------- the team's own score ----------------
   Two figures on the paper over the lines behind them, not two boxes:
   a row is a name and a value on a hairline. */
.sub-score-stats {
  margin: 0 0 20px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
  border-top: 1px solid var(--border);
  padding-top: 14px;
}
.sub-score-stats .stat {
  border: 0;
  background: transparent;
  padding: 0;
}
.sub-score-stats .stat-value { font-variant-numeric: tabular-nums lining-nums; }
.sub-score-name { margin-left: 10px; font-weight: 400; }
.sub-score-num { white-space: nowrap; font-variant-numeric: tabular-nums lining-nums; }
#sub-score-pending { margin-top: 10px; }

/* ---------------- the two lists ----------------
   One grammar: heads on a hairline, rows on hairlines, numbers to the
   right, and the code chip on the page's own indent.

   Already sent has five facts to a row and they need more line than a
   phone has, so a row is three storeys at every width: the chip and
   what was claimed, then when it went and what the tab team said, then
   the files themselves. The score sheet has three and keeps them in
   columns on a wide page, where a reader compares figures down one;
   under 560px it goes to two storeys as well. Nothing is cut short and
   nothing scrolls sideways. */
.sub-table table.nice { display: block; min-width: 0; width: 100%; }
.sub-table table.nice thead,
.sub-table table.nice tbody { display: block; }
/* the same label the rest of the page uses: uppercase, 0.72rem, muted.
   `table.nice th` is a step off that in size and weight, which reads as
   a second voice for one job. */
.sub-table table.nice th {
  padding: 0 0 7px;
  font-size: var(--t-micro);
  font-weight: 800;
  border-bottom: 1px solid var(--text);
}
.sub-table table.nice td {
  padding: 0;
  border: 0;
  vertical-align: baseline;
}

/* the score sheet: one grid for the whole table, so the heads sit over
   the figures they name rather than over a grid of their own */
#sub-score-table table.nice {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  column-gap: 14px;
}
#sub-score-table thead,
#sub-score-table tbody,
#sub-score-table tr { display: contents; }
#sub-score-table th:nth-child(n + 2) { text-align: right; }
#sub-score-table table.nice td {
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
#sub-score-table table.nice tr:last-child td { border-bottom: 0; }

/* already sent: the heads have nothing to head once a row is three
   storeys, and the row says what each part is by where it sits */
#sub-mine table.nice thead { display: none; }
#sub-mine table.nice tbody tr {
  display: grid;
  /* fit-content, not auto, on the last track: a track sized to its
     content takes what it asks for before a flexible one gets anything,
     and at the large end of the text ladder the time squeezed the quest
     column to nothing and the words ran over each other. Capped at a
     share of the row, the time wraps instead. */
  grid-template-columns: minmax(var(--sub-chip), max-content) minmax(0, 1fr) fit-content(42%);
  column-gap: var(--sub-gap);
  row-gap: 6px;
  align-items: baseline;
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}
#sub-mine table.nice tbody tr:last-child { border-bottom: 0; }
/* the quest, and what was claimed for it */
#sub-mine-rows td:nth-child(1) {
  grid-column: 1 / 3;
  grid-row: 1;
  display: grid;
  grid-template-columns: minmax(var(--sub-chip), max-content) minmax(0, 1fr);
  column-gap: var(--sub-gap);
  align-items: baseline;
}
/* the chip keeps its own width and starts on the indent: stretched to
   the track it reads as a bar, and a long code would overrun it */
#sub-mine-rows td:nth-child(1) .code { justify-self: start; }
/* when it went */
#sub-mine-rows td:nth-child(2) {
  grid-column: 3;
  grid-row: 1;
  justify-self: end;
  text-align: right;
  color: var(--muted);
  font-size: var(--t-small);
  font-variant-numeric: tabular-nums lining-nums;
}
/* what the tab team said, with the reason under it */
#sub-mine-rows td:nth-child(4) { grid-column: 2; grid-row: 2; }
/* the files, or their count when the worker sent no list */
#sub-mine-rows td:nth-child(3) { grid-column: 2 / -1; grid-row: 3; }
#sub-mine-rows td.sub-count-only {
  color: var(--muted);
  font-size: var(--t-small);
  font-variant-numeric: tabular-nums lining-nums;
}
#sub-mine-rows td.sub-count-only::before { content: 'Files: '; }
/* the gallery switch */
#sub-mine-rows td:nth-child(5) {
  grid-column: 3;
  grid-row: 2;
  justify-self: end;
}

.sub-answer-text { display: block; color: var(--muted); font-size: var(--t-small); }

/* why a submission was turned down — red as words, on its own line
   under the verdict */
.sub-reason {
  display: block;
  color: var(--alert-ink);
  font-size: var(--t-small);
  line-height: 1.45;
  margin-top: 4px;
}

/* the per-row gallery rocker sits flush in its cell */
.sub-gal { margin: 0; }

/* ---------------- proof thumbnails ---------------- */
.sub-thumbs { display: flex; flex-wrap: wrap; gap: 6px; }
.sub-thumb-btn { border: 0; padding: 0; background: transparent; font: inherit; cursor: pointer; }
.sub-thumb {
  display: block;
  width: 44px;
  height: 44px;
  object-fit: cover;
  border: 1px solid var(--border-strong);
  border-radius: 2px;
  background: var(--page-bg);
}
/* a video is a black plate with the play glyph on it — the markup is a
   button, so this cannot be written against `a` */
.sub-thumb-vid {
  display: flex;
  align-items: center;
  justify-content: center;
  border-color: var(--sign-bg);
  background: var(--sign-bg);
  color: var(--sign-ink);
  text-decoration: none;
  font-size: var(--t-small);
}
.sub-thumb-up {
  display: grid;
  place-items: center;
  color: var(--muted);
  border: 1px dashed var(--border-strong);
  font-size: var(--t-body);
}

/* ---------------- what happens next ----------------
   One numeral a step, muted, on the indent the codes make. */
.sub-next ol {
  counter-reset: sub-step;
  list-style: none;
  margin: 0;
  padding: 0;
}
.sub-next li {
  counter-increment: sub-step;
  display: grid;
  grid-template-columns: var(--sub-chip) minmax(0, 1fr);
  column-gap: var(--sub-gap);
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
  line-height: 1.5;
}
.sub-next li:last-child { border-bottom: 0; }
.sub-next li::before {
  content: counter(sub-step, decimal-leading-zero);
  font-weight: 800;
  color: var(--muted);
  font-variant-numeric: tabular-nums lining-nums;
}

/* ---------------- who is sending ----------------
   The last thing on the page, because it is who the proof goes out as
   and it is what closes the page. */
.sub-who {
  display: flex;
  gap: 16px;
  align-items: baseline;
  flex-wrap: wrap;
  margin: 56px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--border);
  color: var(--muted);
}
.sub-who strong { color: var(--text); font-weight: 800; }
/* left, beside the name: the floating button sits in the bottom right
   corner of every page and would cover a sign-out put there */
.sub-who a {
  color: var(--text);
  font-weight: 800;
  text-decoration: none;
  border-bottom: 2px solid currentColor;
}

/* ---------------- what is going up right now ----------------
   A large upload used to say so in one line of status text beside the
   Send button, which is easy to miss and says nothing about what is in
   flight — so after closing the page and coming back, choosing the
   file again looked like it had done nothing. This box is the answer:
   it appears while anything is uploading, names the quest and the file,
   and counts the slices. The warm fill is the same one the quest sheet
   uses for something asking to be looked at — a flat colour laid
   inside the box on ::before, over its own border so the edge warms
   with it, never a shadow outside it. */
.sub-uploads { position: relative; z-index: 0; }
.sub-uploads::before {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: -1;
  border: 1px solid var(--glow-edge);
  border-radius: 2px;
  background: var(--glow-fill);
  opacity: 0.7;
  transition: opacity var(--duration-slow) var(--ease-in-out);
  pointer-events: none;
}
/* finished, it is a receipt rather than something asking to be looked
   at: the same light, turned down. Where it is does not move. */
.sub-uploads.is-settled::before { opacity: 0.28; }
.sub-up-title {
  margin: 0 0 12px;
  font-size: var(--t-micro);
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
/* min-width: 0 all the way down, or a long file name stops the row
   shrinking and pushes the bar past the edge of a phone */
.sub-up-list { display: grid; gap: 14px; min-width: 0; }
.sub-up-row { display: grid; gap: 5px; min-width: 0; }
.sub-up-head { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; min-width: 0; }
.sub-up-quest {
  flex: none;
  background: var(--sign-bg);
  color: var(--sign-ink);
  border-radius: 2px;
  padding: 2px 7px;
  font-size: var(--t-micro);
  font-weight: 800;
  letter-spacing: 0.04em;
}
.sub-up-name {
  min-width: 0;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 800;
}
/* the bar is the shared one, full width and a little taller here */
.sub-up-row .sub-progress { max-width: none; height: 12px; }
.sub-up-count {
  margin: 0;
  font-size: var(--t-small);
  color: var(--muted);
  font-variant-numeric: tabular-nums lining-nums;
}
.sub-up-row.is-done .sub-up-count { color: var(--accent-dark); }
.sub-up-warn { margin: 16px 0 0; font-size: var(--t-small); line-height: 1.5; }

/* ---------------- a phone ---------------- */
@media (max-width: 560px) {
  .sub-page { --sub-chip: 3.25rem; --sub-gap: 10px; }
  .sub-score-stats { grid-template-columns: 1fr; gap: 14px; }
  .sub-step { max-width: none; }
  /* the sign-out on its own line and hard left: the floating button is
     fixed in the bottom right corner and covered the end of the row */
  .sub-who {
    margin-top: 44px;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
  /* the name goes on its own line: "600 MB, uploads in the background"
     is wider than the box to type the name into at this width, and the
     two beside each other left the box a stub. The cross stays beside
     the name — a full-width row for one small button reads as an
     action on the whole list. */
  .sub-files li { grid-template-columns: minmax(0, 1fr) auto; }
  .sub-files .sub-file-name { grid-column: 1; grid-row: 1; }
  .sub-files .sub-file-drop { grid-column: 2; grid-row: 1; }
  .sub-files .sub-file-size { grid-column: 1 / -1; grid-row: 2; text-align: left; }

  /* the score lines go two storeys here as well, for the reason the
     submissions list does: three columns and a quest name do not fit
     one line at this width, and at the large end of the text ladder
     the name ran under the figures */
  #sub-score-table table.nice { display: block; }
  #sub-score-table thead { display: none; }
  #sub-score-table tbody { display: block; }
  #sub-score-table tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: var(--sub-gap);
    row-gap: 2px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
  }
  #sub-score-table tr:last-child { border-bottom: 0; }
  #sub-score-table table.nice td { padding: 0; border-bottom: 0; }
  #sub-score-rows td:nth-child(1) { grid-column: 1 / -1; grid-row: 1; }
  #sub-score-rows td:nth-child(2) {
    grid-column: 1;
    grid-row: 2;
    color: var(--muted);
    font-size: var(--t-small);
  }
  #sub-score-rows td:nth-child(3) { grid-column: 2; grid-row: 2; justify-self: end; font-weight: 800; }
}

/* ---------------- Compress a video ----------------
   The second view of the page. There is no design study for it. The
   language is study 12's; the specifics come from the submit page's
   own studies, since both halves are the same job — someone picks a
   file, watches something happen to it and gets a result. From there:
   a choice is a row on a hairline rather than a chip, figures are
   tabular and sit in a column of their own, the thing that is still
   changing sits on the amber field with its percentage as the largest
   type in it, and the lesser action is a bold word with a hard
   underline rather than a second box.

   Black is spent on the nav, the board and the tab row and nowhere
   else: the result's video well is black because that is what a video
   sits in, not because it is a sign. The selected option is marked by
   a keyline rather than by colour, because green already has a job
   here and a second use of it would make the palette mean two things.

   Four type sizes: 0.72rem uppercase labels, 0.85rem for what a row
   notes about itself, 1rem for everything that is read, and --t-head
   for the section rules, the running percentage and the result. The
   percentage and the result never appear together, so there is one
   large figure on screen in any state. */

.sub-page {
  --cp-w: 860px;      /* one right edge for the lede, the form and the list */
  /* The two fixed columns of an option row. They are in rem so they
     grow with the text-size setting, and capped so that at 200% the
     three tracks still add up to less than the row they sit in —
     without the cap the figure column was pushed off the page. */
  --cp-c1: min(4.6rem, 88px);   /* the option's own name */
  --cp-c3: 5rem;                /* what it comes to; each list sets its own */
}

.cp-lede {
  max-width: var(--cp-w);
  margin: 56px 0 0;
  line-height: 1.6;
}

.cp-tool { max-width: var(--cp-w); }
.cp-tool { margin-top: 26px; }

.cp-cap {
  font-size: var(--t-micro);
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---- the file ---- */

.cp-file-input { display: none; }

.cp-meta {
  display: grid;
  gap: 4px;
  margin: 0 0 16px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.cp-meta-cap { margin: 0 0 2px; }
.cp-meta strong { font-weight: 800; line-height: 1.4; overflow-wrap: anywhere; }
.cp-meta span {
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.5;
  font-variant-numeric: tabular-nums lining-nums;
}

/* Once there is a file, changing it is a lesser action: it keeps a box
   a thumb can hit but gives up the green and the width. */
.cp-pick {
  display: flex;
  align-items: center;
  gap: 10px;
  width: max-content;
  max-width: 100%;
  min-height: 44px;
  padding: 10px 16px;
  border: 2px solid var(--text);
  border-radius: 2px;
  background: var(--surface);
  color: var(--text);
  font-weight: 700;
  cursor: pointer;
  transition: transform var(--duration-quick) var(--ease-smooth-out),
    box-shadow var(--duration-quick) var(--ease-smooth-out);
}
.cp-pick svg { width: 22px; height: 22px; flex: none; }
.cp-pick:hover { transform: translateY(-1px); box-shadow: var(--shadow-hover); }
.cp-pick:active { transform: translate(1px, 1px); box-shadow: none; }

/* With nothing chosen this is the only thing to press, so it is the
   green one and it takes the measure. */
.cp-tool[data-stage="idle"] .cp-pick {
  justify-content: center;
  width: 100%;
  min-height: 56px;
  padding: 14px 18px;
  border-color: var(--accent);
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 850;
  box-shadow: var(--shadow);
}

/* ---- the two choices ---- */

.cp-card { margin-top: 22px; padding: 22px; }

.cp-choices {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 26px 32px;
}

.cp-chead {
  margin: 0 0 2px;
  padding: 0 10px 7px;
  border-bottom: 1px solid var(--text);
}

/* A row of options, not a row of chips: the name, what it notes about
   itself, and the figure it comes to, each on its own edge down the
   column. */
#cp-scales { --cp-c3: min(7.4rem, 190px); }
#cp-sizes { --cp-c3: min(3.6rem, 110px); }

.cp-size {
  display: grid;
  grid-template-columns: var(--cp-c1) minmax(0, 1fr) var(--cp-c3);
  column-gap: 12px;
  align-items: baseline;
  width: 100%;
  padding: 11px 10px;
  border: 0;
  border-bottom: 1px solid var(--border);
  border-radius: 2px;
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background var(--duration-quick) var(--ease-smooth-out),
    box-shadow var(--duration-quick) var(--ease-smooth-out);
}
.cp-size-name { font-weight: 800; }
.cp-size small {
  display: block;
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.cp-size-fig {
  text-align: right;
  font-weight: 700;
  font-variant-numeric: tabular-nums lining-nums;
}
.cp-size:hover:not(.is-selected) { box-shadow: inset 0 0 0 1px var(--border-strong); }

/* The one that is picked closes into a box. No layout moves, because
   the keyline is an inset shadow rather than a border. */
.cp-size.is-selected {
  background: var(--page-bg);
  box-shadow: inset 0 0 0 2px var(--text);
}
.cp-size.is-selected .cp-size-fig { font-weight: 850; }

/* ---- what it should come to, and the action ---- */

.cp-guess { margin: 18px 0 0; line-height: 1.6; }
.cp-guess b { font-weight: 850; font-variant-numeric: tabular-nums lining-nums; }

.cp-run {
  display: block;
  width: 100%;
  min-height: 56px;
  margin-top: 16px;
  padding: 14px 18px;
  border: 2px solid var(--accent);
  border-radius: 2px;
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-weight: 850;
  box-shadow: var(--shadow);
  cursor: pointer;
  transition: transform var(--duration-quick) var(--ease-smooth-out),
    box-shadow var(--duration-quick) var(--ease-smooth-out),
    opacity var(--duration-quick) var(--ease-smooth-out);
}
.cp-run:hover { transform: translateY(-1px); box-shadow: var(--shadow-hover); }
.cp-run:active { transform: translate(1px, 1px); box-shadow: none; }
.cp-run[disabled] { opacity: 0.45; pointer-events: none; box-shadow: none; }

/* Once it is running, the amber field is the thing to watch; once
   there is a result, the green is on using it. Either way the run
   button steps down to a plain control. */
.cp-tool[data-stage="busy"] .cp-run,
.cp-tool[data-stage="done"] .cp-run {
  border-color: var(--text);
  background: var(--surface);
  color: var(--text);
  box-shadow: none;
}

/* ---- running ---- */

/* The one field on the page asking to be looked at: the amber is
   painted inside the box and --glow-edge warms the border. */
.cp-progress {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 14px;
  row-gap: 12px;
  align-items: baseline;
  margin-top: 18px;
  padding: 13px 14px 15px;
  border: 2px solid var(--glow-edge);
  border-radius: 2px;
  background: var(--glow-fill);
}
.cp-stage { margin: 0; }
.cp-pct {
  margin: 0;
  text-align: right;
  font-size: var(--t-head);
  font-weight: 850;
  letter-spacing: -0.035em;
  line-height: 1;
  font-variant-numeric: tabular-nums lining-nums;
}
.cp-track {
  grid-column: 1 / -1;
  display: block;
  height: 10px;
  border-radius: 2px;
  background: var(--border);
  overflow: hidden;
}
.cp-track span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--text);
  transition: width var(--duration-fast) var(--ease-smooth-out);
}

/* ---- the result ---- */

.cp-result { margin-top: 36px; }
.cp-result-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
  font-variant-numeric: tabular-nums lining-nums;
}
.cp-was,
.cp-arrow { color: var(--muted); font-weight: 800; }
.cp-now { font-weight: 850; }
.cp-result-note { margin: 8px 0 0; color: var(--muted); line-height: 1.55; }
.cp-result.is-over .cp-result-note { color: var(--alert-ink); }

.cp-result video {
  display: block;
  width: 100%;
  max-height: 52vh;
  margin-top: 18px;
  border: 1px solid var(--border);
  border-radius: 2px;
  background: var(--sign-bg);
}

.cp-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 24px;
  margin-top: 18px;
}

/* The green is on the one that carries the result over to the other
   view, because that is what the page is for. Saving it out keeps a
   box a thumb can hit and gives up the colour. */
.cp-use,
.cp-save {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 52px;
  padding: 12px 20px;
  border: 2px solid var(--text);
  border-radius: 2px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-weight: 850;
  cursor: pointer;
  transition: transform var(--duration-quick) var(--ease-smooth-out),
    box-shadow var(--duration-quick) var(--ease-smooth-out);
}
.cp-use {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: var(--shadow);
}
.cp-use svg,
.cp-save svg { width: 20px; height: 20px; flex: none; }
.cp-use:hover,
.cp-save:hover { transform: translateY(-1px); box-shadow: var(--shadow-hover); }
.cp-use:active,
.cp-save:active { transform: translate(1px, 1px); box-shadow: none; }

.cp-again {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.cp-again span { font-weight: 800; border-bottom: 2px solid currentColor; }

/* ---- the view's one status line ---- */

.cp-status {
  margin: 16px 0 0;
  color: var(--muted);
  line-height: 1.55;
  min-height: 1.55em;
}
.cp-tool[data-stage="failed"] .cp-status { color: var(--alert-ink); font-weight: 700; }
/* Nothing is ever said here before a file is chosen, so it does not
   hold a line open. Once there is one it does, or the page jumps every
   time the line changes. */
.cp-tool[data-stage="idle"] .cp-status { margin: 0; min-height: 0; }

@media (max-width: 760px) {
  .cp-choices { grid-template-columns: minmax(0, 1fr); }
  /* One column, so the cap is a share of the screen rather than a
     fixed width */
  .sub-page { --cp-c1: min(4.6rem, 21vw); }
  #cp-scales { --cp-c3: min(7.4rem, 36vw); }
  #cp-sizes { --cp-c3: min(3.6rem, 22vw); }
}

@media (max-width: 560px) {
  .cp-card { padding: 16px; }
}
