/* Blackbar. One stylesheet, no framework, no webfont — the page has to work
   offline from a folder on disk, so everything it needs is in the folder. */

:root {
  --ink: #14161a;
  --ink-soft: #565c66;
  --line: #dfe3ea;
  --bg: #f6f7f9;
  --card: #ffffff;
  --accent: #1f6feb;
  --warn: #8a4b00;
  --warn-bg: #fff6e6;
  --danger: #b3261e;
  --radius: 10px;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

/* An author `display` beats the user agent's `[hidden] { display: none }`, so
   any element styled with a display value would ignore its own hidden
   attribute. This keeps `hidden` meaning hidden everywhere. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.55 var(--sans);
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 1180px; margin: 0 auto; padding: 0 20px; }

/* ---------- header ---------- */

/* The header is pinned: it is the only thing on screen that says what this
   tool is and that the file is not going anywhere, and a reviewer scrolling a
   hundred-page document should not have to scroll back up to see it. It is
   kept thin for the same reason — pinned space is space the document does not
   get.

   Its height is a variable because three other things are measured from it:
   the padding that stops the page starting underneath it, and the offset and
   height of the sticky panel beside it. */
:root { --top-h: 46px; --front-width: 760px; }

.top {
  position: fixed; top: 0; left: 0; right: 0; z-index: 20;
  background: #0d1117; color: #fff;
}
/* No wrapping: a header that grows a second line no longer matches the space
   reserved for it, and the top of the document disappears behind it. */
.top-inner {
  display: flex; align-items: center; gap: 14px; flex-wrap: nowrap;
  height: var(--top-h);
}
body { padding-top: var(--top-h); }
.mark {
  font-size: 17px; font-weight: 650; letter-spacing: -0.01em;
  display: flex; align-items: center; gap: 8px; flex: none;
}
/* Named, because .bar is also the progress bar in the overlay and the two
   had nothing to do with each other beyond a word. */
.markmark { display: block; width: 26px; height: 15px; flex: none; fill: currentColor; }
.claim {
  margin: 0; color: #9aa4b2; font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
/* Narrow enough that the tagline would crowd the name out of its own bar. */
@media (max-width: 640px) { .claim { display: none; } }

a.mark { color: inherit; text-decoration: none; }
/* The two doors between the tool and its answers, wearing the same coat: the
   header's black, white, bold. In the header it reads as part of the bar; at
   the foot of a white page it is the one dark thing on it, which is where the
   eye goes looking for the way back. */
.top-link, .faqbackbtn {
  font: inherit; font-size: 13px; font-weight: 700;
  background: #0d1117; color: #fff; border: 1px solid #0d1117;
  border-radius: var(--radius); padding: 5px 11px;
  text-decoration: none; cursor: pointer;
}
.top-link:hover, .faqbackbtn:hover { background: #222a35; border-color: #222a35; }
/* The group is pushed right, not each button, or the second one would be
   shoved off on its own. */
.top-actions { margin-left: auto; flex: none; display: flex; gap: 8px; }

/* ---------- drop ---------- */

.view { padding: 28px 0 40px; }

/* The drop box and the cards under it are one column: the box used to run the
   full width of the wrapper while the cards were capped, so its edges sat
   outside theirs. One variable holds the width so they cannot drift apart
   again. */
.drop {
  max-width: var(--front-width); margin-left: auto; margin-right: auto;
  border: 2px dashed var(--line);
  background: var(--card);
  border-radius: 14px;
  padding: 34px 24px;
  text-align: center;
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.drop:hover, .drop:focus-visible, .drop.over { border-color: var(--accent); background: #f2f7ff; outline: none; }
.drop-lead { margin: 0 0 6px; font-size: 20px; font-weight: 600; }
.drop-sub { margin: 0; color: var(--ink-soft); font-size: 14px; }
/* Deliberately quiet. Carrying on from a draft is a thing you do on your
   second visit, and it should not compete with the thing you do on your
   first. */
.drop-faint { margin: 5px 0 0; color: #9aa4b2; font-size: 12.5px; }
.link { color: var(--accent); text-decoration: underline; }

.error {
  color: var(--danger); margin: 14px auto 0; font-weight: 500;
  max-width: var(--front-width);
}

/* ---------- front page ---------- */

.hero { max-width: 680px; margin: 8px auto 26px; text-align: center; }
.hero h1 {
  font-size: clamp(28px, 4.4vw, 40px); line-height: 1.12; letter-spacing: -0.022em;
  margin: 0 0 12px; font-weight: 680;
}
.lede { margin: 0; font-size: 16.5px; line-height: 1.55; color: var(--ink-soft); }
.lede em { font-style: normal; color: var(--ink); font-weight: 600; }

.drop-icon { width: 34px; height: 34px; color: var(--ink-soft); margin-bottom: 10px; }
.drop:hover .drop-icon, .drop.over .drop-icon { color: var(--accent); }

.features {
  list-style: none; padding: 0; margin: 30px auto 0; max-width: var(--front-width);
  display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.features li {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px 17px;
}
.features h3 {
  margin: 0 0 6px; font-size: 14.5px; font-weight: 650;
  display: flex; align-items: center; gap: 9px;
}
.features .ico {
  flex: none; width: 26px; height: 26px; border-radius: 7px; padding: 4px;
  background: #0d1117; color: #fff;
}
.features p { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-soft); }
.features code {
  font-size: 12px; background: #eef1f6; padding: 1px 4px; border-radius: 4px; color: var(--ink);
}

.busy-line { margin: 0; display: flex; align-items: center; gap: 9px; }

/* Progress, where there is progress to report. A run whose length is not
   known keeps the spinner and shows no bar, rather than showing a bar that
   does not move. */
/* One row per leg of the job. Both are drawn from the start, so the shape of
   the work is visible before it begins — and when a run is paused, which part
   of it got how far. */
.leg { margin-top: 12px; }
.leg-label {
  margin: 0 0 5px; display: flex; justify-content: space-between;
  gap: 12px; font-size: 12.5px; font-weight: 500; color: var(--ink-soft);
}
.leg-count { font-variant-numeric: tabular-nums; }

.bar {
  height: 6px; border-radius: 999px;
  background: #e6eaf1; overflow: hidden;
}
.bar > i {
  display: block; height: 100%; width: 0;
  background: var(--accent); border-radius: inherit;
  transition: width 140ms linear;
}
.busy-note {
  margin: 12px 0 0; font-size: 12px; line-height: 1.45;
  color: var(--ink-soft); font-weight: 400;
}
#busy-pause { margin-top: 12px; width: 100%; }

/* Places the reader was unsure of. Amber, not red: red is "this will be
   covered", and these are "this might need covering, and nothing has decided
   yet". Using the same colour for both would make a warning look like a
   promise. */
.doubthint { color: #7a4100; }

/* ---------- review ---------- */

.review { display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: 22px; align-items: start; }
@media (max-width: 900px) { .review { grid-template-columns: 1fr; } }

.panel {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  position: sticky;
  /* Below the pinned header, not underneath it. */
  top: calc(var(--top-h) + 16px);
  max-height: calc(100vh - var(--top-h) - 56px);
  overflow-y: auto;
}
.panel-head {
  /* The file name sits on its own line above the buttons. Side by side, a
     long name and five controls fought over one row and the name lost, being
     the half that was ellipsised away. */
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
  padding: 12px 14px; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: var(--card); z-index: 2;
}
.panel-head h2 {
  font-size: 13.5px; margin: 0; font-weight: 650;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------- the tools ---------- */
/*
   Four icons, joined into one bar: move, mark, undo, open another file.
   They were words before, and words did not fit — a 320px panel against five
   labelled controls meant the row overflowed and the reviewer had to scroll
   sideways to reach the last of them. Icons of a fixed size cannot overflow,
   so the row is sized by construction rather than by hoping the labels stay
   short: four 38px cells is 152px whatever language the tooltips are in.

   Every one keeps its text for a screen reader, and carries a title so the
   pointer explains it too.
*/
.tools { display: flex; flex: none; align-self: flex-start; }
.tool {
  width: 38px; height: 34px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--card); color: var(--ink);
  border: 1px solid var(--line); border-right-width: 0;
  cursor: pointer;
}
.tool:last-child { border-right-width: 1px; }
.tool:first-child { border-radius: var(--radius) 0 0 var(--radius); }
.tool:last-child { border-radius: 0 var(--radius) var(--radius) 0; }
.tool svg {
  width: 19px; height: 19px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
/* Dividers between the three kinds: what dragging does, how big the pages
   are, and the two that do something once. Seamless is not the same as
   undifferentiated. */
#zoom-out, #undo { border-left: 1px solid var(--line); }

/* Not the selected one. Hover is a pseudo-class and beat the attribute
   selector below on specificity, so pointing at the tool already in use
   turned it grey — which reads as deselecting it. */
/* Not the stack: it is two buttons sharing a cell, and greying the cell would
   answer a pointer that is only over one of them. */
.tool:hover:not(:disabled):not([aria-pressed="true"]):not(.toolstack) { background: #eef1f6; }
/* Selected is darkened, not tinted: the reviewer has to be able to tell at a
   glance which of the two dragging means, and a pale highlight on a pale
   panel does not carry that. */
.tool[aria-pressed="true"] {
  background: var(--accent); border-color: var(--accent); color: #fff;
  position: relative; z-index: 1;
}
/* Still blue under the pointer, a shade down: it is already the one in use,
   and the only thing hover has to say is that it is a button. */
.tool[aria-pressed="true"]:hover:not(:disabled) {
  background: #1a5fd0; border-color: #1a5fd0;
}
/* Two buttons in one icon's worth of room: the top half and the bottom half.
   The cell keeps the toolbar's own border and size so the row stays seamless,
   and the halves inside it carry nothing but their arrow. */
/* The stack is a div holding two buttons, so it misses the rounding every
   other icon gets from being a button — which left one square-cornered cell in
   a row of rounded ones. It is stated here rather than inherited.

   overflow keeps a half's hover inside those corners, so the grey follows the
   icon's shape instead of squaring off its outer edge. */
.toolstack {
  flex-direction: column; padding: 0;
  border-radius: 8px; overflow: hidden;
}
.toolstack .half {
  flex: 1; width: 100%; min-height: 0; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; color: inherit; cursor: pointer;
}
.toolstack .half svg { width: 17px; height: 11px; }
.toolstack .half:hover:not(:disabled) { background: #eef1f6; }
.toolstack .half:disabled { color: var(--ink-soft); opacity: .55; cursor: default; }
.toolstack .half:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.tool:disabled { color: var(--ink-soft); opacity: .55; cursor: default; }
.tool:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; z-index: 2; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- collapsible sections ---------- */
/*
   The panel used to be one long column of controls, each with a paragraph
   explaining itself. Everything was visible at once and most of it was prose,
   so the part you wanted was always somewhere below the part you did not.
   Sections group it, the explanations moved to the front page, and what is
   left of them hides behind a "?" until asked for.
*/

.sect { border-bottom: 1px solid var(--line); }
.sect:last-of-type { border-bottom: 0; }
.sect > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 8px;
  padding: 11px 14px; font-size: 13px; font-weight: 600;
}
.sect > summary::-webkit-details-marker { display: none; }
.sect > summary::before {
  content: ''; flex: none; width: 7px; height: 7px; margin-right: 1px;
  border-right: 1.6px solid var(--ink-soft); border-bottom: 1.6px solid var(--ink-soft);
  transform: rotate(-45deg); transition: transform .15s;
}
.sect[open] > summary::before { transform: rotate(45deg); }
.sect > summary:hover { background: #f7f9fc; }
.s-title { flex: 1; }
.s-note {
  font-weight: 500; font-size: 11.5px; color: var(--ink-soft);
  background: #eef1f6; border-radius: 20px; padding: 1px 8px;
}
.s-note:empty { display: none; }
.s-note.on { background: #e8f0fe; color: var(--accent); }
.s-body { padding: 2px 14px 14px; }

/* A hint you ask for rather than one you have to read past. */
.why {
  flex: none; width: 16px; height: 16px; border-radius: 50%; padding: 0;
  background: #e6eaf1; color: var(--ink-soft); border: 0;
  font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
  cursor: help; margin-left: 2px;
}
.why:hover, .why[aria-expanded="true"] { background: var(--accent); color: #fff; }
.why:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* One shared bubble, positioned from script. A tooltip parented to the
   control it explains gets clipped by the scrolling panel it lives in, so
   this one is a child of <body> and placed in viewport coordinates. */
.tipbubble {
  position: fixed; z-index: 60; max-width: 260px;
  background: #0d1117; color: #fff; font-size: 12.5px; line-height: 1.45;
  padding: 8px 10px; border-radius: 8px;
  box-shadow: 0 6px 20px rgba(9, 14, 24, 0.28);
}

.field { margin-bottom: 16px; }
.field > label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; }
textarea {
  width: 100%; font: 13px/1.5 var(--mono); padding: 8px 9px;
  border: 1px solid var(--line); border-radius: 8px; resize: vertical; background: #fff; color: var(--ink);
}
textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }
.hint { margin: 6px 0 0; font-size: 12.5px; color: var(--ink-soft); }
/* Directly under the tools it describes. It used to sit at the foot of the
   panel, below every section, which put the sentence explaining what dragging
   does a long scroll away from the buttons that change it. */
.tip { margin: 0; font-size: 12.5px; color: var(--ink-soft); }

.check { display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; margin-top: 10px; }
.check input { margin: 0; flex: none; }

.kinds { display: flex; flex-direction: column; gap: 1px; }
.kind { display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: 7px; cursor: pointer; }
.kind:hover { background: #f2f4f8; }
.kind input { flex: none; margin: 0; }
.kind .name { flex: 1; font-size: 13px; }
.kind .n { font-variant-numeric: tabular-nums; font-size: 11.5px; color: var(--ink-soft); background: #eef1f6; border-radius: 20px; padding: 1px 8px; }
.kind.empty { opacity: .45; cursor: default; }

.counts {
  font-size: 12.5px; color: var(--ink-soft);
  border-top: 1px solid var(--line); padding: 12px 14px;
}
.counts strong { color: var(--ink); }
.counts:empty { display: none; }

/* ---------- pages ---------- */

.stage { min-width: 0; }
/* --zoom is what the two magnifier buttons move. The pages are laid out at
   the width of the column and then scaled from there, so zooming is a
   property of the view and never of the canvases: the pixels a redaction is
   measured against do not change when the reviewer leans in. */
.pages {
  display: flex; flex-direction: column; gap: 18px; align-items: flex-start;
  --zoom: 1;
}
.page { width: calc(100% * var(--zoom)); flex: none; }
.page {
  position: relative; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; box-shadow: 0 1px 3px rgba(16, 22, 32, .06);
}
/* The wrapper owns the shape — its aspect-ratio comes from the page — so a
   canvas that has given up its bitmap does not collapse the document under
   the reviewer's scroll position. */
.page canvas {
  display: block; width: 100%; height: 100%;
  cursor: crosshair; touch-action: none;
}
/* Moving, not marking: the pointer says so before anything is dragged. */
.tool-pan .page canvas { cursor: grab; }
.tool-pan .page canvas:active { cursor: grabbing; }
.page .num {
  position: absolute; top: 8px; left: 8px; background: rgba(13,17,23,.75); color: #fff;
  font-size: 11px; padding: 2px 7px; border-radius: 20px; pointer-events: none;
}

.textview {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 18px; margin: 0; font: 13.5px/1.7 var(--mono); white-space: pre-wrap;
  word-break: break-word; max-height: 70vh; overflow: auto;
}
.textview mark { background: #14161a; color: #14161a; border-radius: 2px; }
.textview mark.off { background: #ffe9a8; color: var(--ink); }

/* ---------- export ---------- */

.exportbar {
  position: sticky; bottom: 0; margin-top: 20px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 16px; display: flex; justify-content: flex-end; align-items: center;
  gap: 16px; flex-wrap: wrap; box-shadow: 0 -2px 10px rgba(16,22,32,.05);
}
.exportgo { display: flex; align-items: center; gap: 14px; }

button { font: inherit; cursor: pointer; border-radius: 8px; }
.primary { background: var(--accent); color: #fff; border: 1px solid var(--accent); padding: 9px 18px; font-weight: 600; }
.primary:hover { background: #1a5fd0; }
.primary:disabled { background: #9db8e6; border-color: #9db8e6; cursor: not-allowed; }
.ghost { background: transparent; border: 1px solid var(--line); color: var(--ink-soft); padding: 5px 10px; font-size: 12.5px; }
.ghost:hover { border-color: var(--ink-soft); color: var(--ink); }

/* The one action in the panel that starts something, rather than adjusting
   what is already there, so it does not read as another grey control. */
.accent {
  background: var(--accent); color: #fff; border: 1px solid var(--accent);
  font-weight: 600; font-size: 13px; padding: 5px 10px;
}
.accent:hover { filter: brightness(1.08); }
.accent.on, .accent:active { filter: brightness(0.94); }

/* ---------- busy ---------- */

.busy { position: fixed; inset: 0; background: rgba(246,247,249,.86); display: grid; place-items: center; z-index: 20; }
.busy-inner {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 22px; font-weight: 500; min-width: 260px; max-width: 360px;
}
.spinner { width: 16px; height: 16px; border: 2px solid var(--line); border-top-color: var(--accent); border-radius: 50%; animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2.4s; } }

.foot { padding: 26px 20px 40px; color: var(--ink-soft); font-size: 13px; }
.foot p { margin: 0; max-width: 720px; }
.foot-links {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.foot-links a {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--ink); font-weight: 600; text-decoration: none;
}
.foot-links a:hover { color: var(--accent); text-decoration: underline; }
.ghico { width: 16px; height: 16px; flex: none; }
/* The separator is decoration between two items that wrap independently. */
.foot-sep { color: var(--line); }

/* ---------- terms feedback and image matching ---------- */

/* ---------- adding a word ---------- */
/*
   A one-line box, and the word is added when the reviewer says so rather than
   as they type. The list below is then a list of decisions, not a running
   transcript of the keyboard — which is what a textarea made it, and why the
   tally used to flicker through the matches for every prefix of a name.
*/
.termadd { display: flex; gap: 0; }
.termadd input {
  flex: 1; min-width: 0; font: inherit; font-size: 14px;
  padding: 9px 11px; background: #fff; color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius) 0 0 var(--radius);
}
.termadd input:focus {
  outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent);
  position: relative; z-index: 1;
}
.termadd button {
  flex: none; width: 40px; display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff; border: 1px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0; margin-left: -1px; cursor: pointer;
}
.termadd button:hover { background: #1a5fd0; }
.termadd button:disabled { background: #b9c3d2; border-color: #b9c3d2; cursor: default; }
.termadd button svg {
  width: 18px; height: 18px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.termempty { margin: 8px 0 0; font-size: 12.5px; color: var(--ink-soft); }

/* The same shape as the box you type a word into, because it asks the same
   kind of question — name a thing to redact. A full-width slab of blue said
   "this is the important one", and it is not: most documents are redacted by
   typing. */
.pickrow {
  display: flex; width: 100%; padding: 0; margin-top: 2px;
  background: none; border: 0; cursor: pointer; text-align: left;
}
.pickfield {
  flex: 1; min-width: 0; font-size: 14px; color: var(--ink-soft);
  padding: 9px 11px; background: #fff;
  border: 1px solid var(--line); border-right: 0;
  border-radius: var(--radius) 0 0 var(--radius);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pickgo {
  flex: none; width: 40px; display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff; border: 1px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.pickgo svg {
  width: 18px; height: 18px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round;
}
.pickrow:hover .pickgo { background: #1a5fd0; }
.pickrow:focus-visible .pickfield { outline: 2px solid var(--accent); outline-offset: -1px; }
/* While picking, the row is the way out of it. */
body.picking .pickfield { color: var(--ink); font-weight: 600; }
/* The plus turns into a cross, and a cross that undoes something is red. In
   black it read as another button in the row rather than the way out. */
body.picking .pickgo { background: var(--danger); border-color: var(--danger); }
body.picking .pickrow:hover .pickgo { background: #8f1d17; border-color: #8f1d17; }
body.picking .pickgo svg { transform: rotate(45deg); }

/* ---------- picking a logo: everything else gets out of the way ---------- */
/*
   Drawing a box around a logo is the one thing in this tool that happens on
   the document rather than in the panel, and the instruction for it used to be
   a sentence nobody read. Dimming says it instead: what is lit is what you can
   use — the page, and the section you started from.
*/
body.picking::before {
  content: ''; position: fixed; inset: 0; z-index: 40;
  background: rgba(13, 17, 23, 0.55);
}
body.picking .stage,
body.picking #imagesect { position: relative; z-index: 41; }
body.picking #imagesect { background: var(--card); border-radius: var(--radius); }
/* The zoom buttons stay usable while a box is being drawn, so the toolbar has
   to come up through the dimming with the document and the Images section.
   Enabled but under a sheet is not usable. */
/* The head is sticky with a z-index of its own, which makes it a stacking
   context — so raising the toolbar inside it got the toolbar no further than
   the top of the head. The head is what has to come up. */
body.picking .panel-head { z-index: 41; }
body.picking .tools {
  position: relative;
  background: var(--card); border-radius: var(--radius);
}
/* ---------- the sample slide on the front page ---------- */
/*
   Someone deciding whether to trust this with a confidential document should
   be able to see what it produces without handing one over first.
*/
.sample { max-width: var(--front-width); margin: 34px auto 0; }
.sample h2 { font-size: 19px; margin: 0 0 6px; letter-spacing: -0.01em; }
.sample-lede { margin: 0 0 14px; color: var(--ink-soft); line-height: 1.6; font-size: 14px; }
.sample-shot {
  display: block; width: 100%; padding: 0; position: relative;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; cursor: zoom-in;
}
.sample-shot img { display: block; width: 100%; height: auto; }
.sample-shot:hover { border-color: #b9c3d2; }
.sample-shot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sample-zoom {
  position: absolute; right: 10px; bottom: 10px;
  background: rgba(13, 17, 23, 0.82); color: #fff;
  font-size: 11.5px; padding: 4px 9px; border-radius: 999px;
}
/* The slide is wide and detailed; on a phone it is a thumbnail of itself and
   the point is the tap that makes it big. */
@media (max-width: 640px) { .sample-zoom { right: 8px; bottom: 8px; } }

/* A width, not a maximum. The overlay centres its box on its contents, and an
   image asked to be 100% of a box that is sizing itself to the image settles
   at whatever the image's own minimum happens to be — which on a wide screen
   left the slide far smaller than the room it had. */
.sampleinner {
  min-width: 0; width: min(1100px, 96vw); max-width: none;
  max-height: 94vh; overflow-y: auto;
}
.samplestage {
  margin: 10px 0; background: #eef1f6; border: 1px solid var(--line);
  border-radius: var(--radius); padding: 8px; overflow: auto;
}
/* Big enough to read the small print, and scrollable when the screen is not.
   On a phone that means it starts wider than the window, which is the whole
   reason for opening it. */
#samplebig { display: block; width: 100%; min-width: 680px; height: auto; }

/* Confirming a pick. The crop is shown big, because the whole point is to see
   what was actually caught — at the size it sits on the page a logo is a few
   dozen pixels and a box a little too wide looks exactly like a box that
   fits. */
/* Never taller than the screen, whatever shape the pick is: the buttons at the
   foot are how the dialog is answered, and a tall pick used to push them off
   the bottom of a phone. */
.cropinner {
  min-width: 0; max-width: min(560px, 94vw);
  max-height: 92vh; overflow-y: auto;
}
.cropstage {
  margin: 10px 0 6px; display: flex; justify-content: center; align-items: center;
  background: #eef1f6; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 8px; overflow: hidden;
}
/* The canvas is sized to fit in script, so nothing here needs to clamp it —
   and a clamp on one side only is what squashed the mark. If one ever applies,
   height: auto keeps the shape. */
#cropview {
  max-width: 100%; height: auto;
  touch-action: none; cursor: crosshair; display: block;
}
#cropsize { margin: 0 0 2px; font-variant-numeric: tabular-nums; }

/* The way out of picking, sitting over the document. Red, because it undoes
   the thing that is happening; above the dimming, because everything dimmed
   is unreachable and this must not be. */
/* Only on a phone. On a laptop the way out of picking is the Cancel in the
   panel, which is right there and never covered — a second cross floating over
   the document was one more thing to explain. */
.pickstop { display: none; }
@media (max-width: 900px) {
.pickstop[data-show="yes"] { display: flex; }
}
.pickstop {
  position: fixed; z-index: 45; top: calc(var(--top-h) + 12px); left: 14px;
  width: 38px; height: 38px; padding: 0;
  align-items: center; justify-content: center;
  background: var(--danger); color: #fff; border: 0; border-radius: 999px;
  box-shadow: 0 2px 10px rgba(13, 17, 23, 0.35);
}
.pickstop:hover { background: #8f1d17; }
.pickstop svg {
  width: 20px; height: 20px; fill: none; stroke: currentColor;
  stroke-width: 2.4; stroke-linecap: round;
}

/* Above the dimming, not under it. A full-size look at a picked image is
   opened from the one section picking leaves lit, and it was being drawn
   behind the very overlay that section is sitting on top of. */
/* Dialogs go above the dimming, not under it. The crop box always opens while
   picking, so without this the button to accept a pick sits behind the sheet
   that picking puts over the page and cannot be pressed at all. */
#imagebox, #cropbox, #passbox { z-index: 60; }

/* A word in the list is a thing the reviewer put there, so it reads as an
   object with a way to take it off, not as a line of text. */
.termcounts li.word {
  background: #f4f6fa; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 6px 6px 6px 11px; margin-bottom: 6px; gap: 8px;
}
.termcounts li.word .t { font-weight: 550; }
.termdrop {
  flex: none; width: 24px; height: 24px; padding: 0; border: 0; background: none;
  color: var(--ink-soft); cursor: pointer; border-radius: 6px; font-size: 16px;
  line-height: 1; display: flex; align-items: center; justify-content: center;
}
.termdrop:hover { background: #e3e8f0; color: var(--ink); }

.termcounts, .templates { list-style: none; margin: 8px 0 0; padding: 0; }
.termcounts li, .templates li {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; padding: 3px 0; color: var(--ink-soft);
}
.termcounts .t, .templates .t { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
/* ---------- where a word actually is ---------- */
/*
   The tally is a button: the number answers "how many", and pressing it
   answers "where". Red for what the reading found, amber for what the shape
   check turned up — the same two colours they are drawn in on the page, since
   a mark the reading found and one a matcher guessed at do not deserve equal
   trust.
*/
.termcounts .n:disabled { cursor: default; }
.termcounts button.n, .templates button.n { font: inherit; border: 0; cursor: pointer; }
.templates button.n:disabled, .termcounts .n:disabled { cursor: default; }
.termcounts button.n[aria-expanded="true"] { background: var(--accent); color: #fff; }

/* A list of page numbers is a reference, not reading: it is scanned for the
   one that is wanted and then left. Small and tight, so twenty of them are a
   list to run an eye down rather than a scroll.

   Named for both sections, because .templates li below sets a padding and a
   border and lands later in the file — so the same dropdown under a picked
   image came out taller, with a rule between every page. */
.termcounts li.tally, .templates li.tally { display: block; padding: 0 0 6px; border: 0; }
.tallywhere { list-style: none; margin: 0; padding: 0 0 0 2px; }
.termcounts .tallywhere li, .templates .tallywhere li { display: block; padding: 0; border: 0; }
.tallyspot {
  display: flex; align-items: center; gap: 7px; width: 100%;
  font: inherit; font-size: 11.5px; line-height: 1.25; text-align: left;
  background: none; border: 0; border-radius: 5px;
  padding: 2px 6px; color: var(--ink-soft); cursor: pointer;
}
.tallyspot:hover { background: #eef1f6; color: var(--ink); }
.tallyspot .dot {
  width: 7px; height: 7px; border-radius: 2px; flex: none;
  background: #118a4e;
}
.tallyspot.shape .dot { background: #d98b1f; }
.tallyspot .how { margin-left: auto; font-size: 10.5px; color: var(--ink-soft); }

.termcounts .n, .templates .n {
  font-variant-numeric: tabular-nums; background: #eef1f6;
  border-radius: 20px; padding: 1px 8px; flex: none;
}

/* Circles, and two of them.
   Green is what the reading found, amber what the comprehensive check added —
   the same two colours they are drawn in on the page, so the panel and the
   document agree about which is which. A round badge rather than a pill
   because it holds a count, not a label. */
.termcounts .n, .templates .n {
  min-width: 24px; height: 24px; border-radius: 999px;
  padding: 0 6px; display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 650; box-sizing: border-box;
}
.termcounts .n.dot-green, .templates .n.dot-green { background: #e3f3ea; color: #0f6b3d; }
.termcounts .n.dot-shape { background: #fdf0dc; color: #9a5b06; }
.termcounts .n.dot-green:not(:disabled):hover, .templates .n.dot-green:not(:disabled):hover { background: #cfe9db; }
.termcounts .n.dot-shape:not(:disabled):hover { background: #f7e3c2; }
.termcounts .n.dot-green[aria-expanded="true"], .templates .n.dot-green[aria-expanded="true"] { background: #118a4e; color: #fff; }
.termcounts .n.dot-shape[aria-expanded="true"] { background: #d98b1f; color: #fff; }
/* The same mark the panel draws, shown inline in the sentence that counts
   them. Not a description of a red circle but the red circle. */
.qmark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 999px;
  background: #fdecea; color: #d92d20; font-weight: 650; font-size: 12px;
  /* Centred on the text it sits in, not hung off the baseline. A fixed
     nudge in pixels is a guess about one font at one size, and it read as a
     mark that had slipped. */
  vertical-align: middle; margin: 0 2px;
}
/* And the line it sits in keeps its height, so the sentence does not jump
   when the mark appears. */
#exportnote { line-height: 1.5; }

/* A term that matched nothing is the one thing in this panel a reviewer must
   not skim past: it looks identical to a term that worked. */
/* Not "nothing found" but "nothing has looked yet" — red, because it marks
   the one thing on the panel that is not an answer. */
.termcounts .n.unknown, .templates .n.unknown,
.termcounts .n.dot-green.unknown {
  background: #fdecea; color: #d92d20; font-weight: 650;
}
.termcounts li.none .n.dot-green { background: var(--warn-bg); color: var(--warn); }
.termcounts li.none .t { color: var(--warn); }

.templates li { padding: 5px 0; border-bottom: 1px solid var(--line); }
.templates li:last-child { border-bottom: 0; }
.templates canvas {
  width: 42px; height: 28px; object-fit: contain; flex: none;
  border: 1px solid var(--line); border-radius: 4px; background: #fff;
}
/* The × that drops a picked image. Named, because "the button in the row"
   used to mean this one and now also means the tally beside it and every
   page number in the list it opens — all of which this was quietly
   restyling to 15px. */
.templatedrop {
  border: 0; background: transparent; color: var(--ink-soft);
  font-size: 15px; line-height: 1; padding: 2px 5px; flex: none;
}
.templatedrop:hover { color: var(--danger); }

button.wide { width: 100%; padding: 8px; }
button.wide.on { background: var(--accent); color: #fff; border-color: var(--accent); }

.senshead {
  display: flex; align-items: center; gap: 4px;
  margin: 12px 0 0; font-size: 11.5px; color: var(--ink-soft);
}

/* The bar belongs to one picked image, so it lives on that image's row,
   between the thumbnail that says which image and the tally that says how
   many. It took the caption's place, which was empty: a picture of the logo
   needs no label saying "picked image". */
.rowsens { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; }
.rowsens input { flex: 1; min-width: 42px; margin: 0; }
.rowsens .v {
  flex: none; font-variant-numeric: tabular-nums; font-size: 11.5px;
  color: var(--ink-soft);
}

/* While picking, the page invites a different kind of drag. A crosshair, not
   the thick cell cross: the thing being aimed at is a box corner, and the fine
   lines say where it will land. */
.page.picking canvas { cursor: crosshair; }
.page.picking { outline: 2px solid var(--accent); outline-offset: -1px; }

/* A hint that has turned into a warning — a search that found nothing. */
.warnhint {
  background: var(--warn-bg); color: var(--warn);
  border-left: 3px solid #d98b1f; padding: 8px 10px;
  border-radius: 0 6px 6px 0; margin-top: 8px;
}

#undo:disabled { opacity: .45; cursor: not-allowed; }



/* ---------- placeholder labels and the legend ---------- */

.legend { list-style: none; margin: 8px 0; padding: 0; }
.legend li {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 0; border-bottom: 1px solid var(--line);
}
.legend li:last-child { border-bottom: 0; }

.labelinput {
  font: 600 11.5px/1.3 var(--mono);
  width: 118px; flex: none; padding: 4px 6px;
  border: 1px solid var(--line); border-radius: 6px; background: #fff; color: var(--ink);
}
.labelinput:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }
.labelinput.edited { border-color: var(--accent); background: #f2f7ff; }

.legend .what {
  flex: 1; min-width: 0; font-size: 12.5px; color: var(--ink-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.legend .n {
  flex: none; font-size: 11.5px; font-variant-numeric: tabular-nums;
  background: #eef1f6; border-radius: 20px; padding: 1px 8px; color: var(--ink-soft);
}


code {
  font: 11.5px var(--mono); background: #eef1f6;
  padding: 1px 4px; border-radius: 4px;
}

/* The key download is the one control here that can undo everything the tool
   just did, so it does not look like the others. */
.hint.danger {
  color: var(--danger); background: #fdf2f1;
  border-left: 3px solid var(--danger);
  padding: 8px 10px; border-radius: 0 6px 6px 0; margin-top: 8px;
}
#downloadkey { margin-top: 12px; border-color: #e6c9c6; color: var(--danger); }
#downloadkey:hover { border-color: var(--danger); }

/* ---------- marking up, then redacting ---------- */

/* Redact is the action; Export only becomes the action once it has been run. */
.primary.ghostly {
  background: transparent; color: var(--accent); border-color: #bcd3f5;
}
.primary.ghostly:hover:not(:disabled) { background: #f2f7ff; border-color: var(--accent); }
.primary.ghostly:disabled { background: transparent; color: #9db8e6; border-color: #dbe6f8; }

/* Red while there are still question marks in the panel, which is what the
   button is there to answer. It turns blue for the decision to cover what was
   found, and green once it is covered. */
.primary.hunt { background: #d92d20; border-color: #d92d20; }
.primary.hunt:hover { background: #b42318; border-color: #b42318; }

/* Once applied the button says so in green, and stays pressable: "Redacted" is
   a state the reviewer can step back out of for another look at what a bar is
   covering, not a dead end. */
.primary.done, .primary.done:hover {
  background: #e8f3ec; color: #1a6b3c; border-color: #bfe0cb;
}
.primary.done:hover { background: #d9ebe1; }

.templates .waiting { color: var(--warn); font-style: italic; }

/* A pending mark in a text document mirrors a pending box on a page: outlined
   in green and still readable. */
.textview mark.pending {
  background: rgba(17, 138, 78, .13); color: var(--ink);
  box-shadow: inset 0 0 0 1.5px #118a4e; border-radius: 2px;
}

#sweepbox {
  margin-top: 10px; padding: 10px 11px;
  background: var(--warn-bg); border-left: 3px solid #d98b1f;
  border-radius: 0 var(--radius) var(--radius) 0;
}
#sweepbox .hint { margin: 0 0 8px; }

/* ---------- the thorough check, running in the background ---------- */
/*
   Deliberately not the overlay every other long pass uses. Those block the
   document because nothing sensible can be done while they run; this one is a
   second opinion on a redaction that already exists, so the reviewer can carry
   on reading while it works. A bar in the panel says how far it has got.
*/
.sweepbar {
  height: 5px; border-radius: 3px; background: var(--line);
  overflow: hidden; margin: 10px 0 6px;
}
.sweepbar span {
  display: block; height: 100%; width: 0;
  background: var(--accent); transition: width .2s linear;
}

/* ---------- reviewing: a fixed frame, two scrolling columns ---------- */
/*
   While a document is open the page itself does not scroll. The header and
   the export bar are always where they were, and the panel and the document
   each scroll on their own — so reaching the Redact button never means
   scrolling past the document, and scrolling the document never takes the
   controls away with it.

   The front page is left alone: it is an ordinary page and reads like one.
*/
/* 100dvh, not 100vh.
   On a phone the visible viewport is shorter than 100vh for as long as the
   browser's own bar is showing, so a frame built to 100vh puts its bottom —
   the Search and Export buttons — underneath that bar. The vh line stays as a
   fallback for browsers without dvh. */
body.reviewing { height: 100vh; height: 100dvh; overflow: hidden; }
body.reviewing > main.wrap {
  height: calc(100vh - var(--top-h));
  height: calc(100dvh - var(--top-h));
  display: flex; flex-direction: column; min-height: 0;
}
body.reviewing > footer.foot { display: none; }
body.reviewing #view-review {
  flex: 1; min-height: 0; display: flex; flex-direction: column;
  padding: 18px 0 0;
}
body.reviewing .review { flex: 1; min-height: 0; align-items: stretch; }
body.reviewing .panel {
  position: static; max-height: none; height: 100%;
  overflow-y: auto; overflow-x: hidden;
}
body.reviewing .stage {
  height: 100%; overflow: auto;
  /* Room for the shadow the export bar casts, so the last page does not sit
     flush against it. */
  padding-bottom: 4px;
}
body.reviewing .exportbar { position: static; flex: none; margin: 14px 0 18px; }

/* ---------- questions ---------- */
.faqmain { padding: 30px 20px 60px; max-width: 760px; }
.faqtitle { font-size: 30px; letter-spacing: -0.02em; margin: 0 0 6px; }
.faq { border-top: 1px solid var(--line); padding: 20px 0 4px; }
.faq h2 { font-size: 17px; margin: 0 0 8px; letter-spacing: -0.01em; }
.faq p { margin: 0 0 12px; color: var(--ink-soft); line-height: 1.6; }
.faq .ph {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px;
  background: #eef1f6; border-radius: 4px; padding: 1px 5px; color: var(--ink);
}
.faqlink a, .faqback a { color: var(--accent); text-decoration: none; font-weight: 600; }
.faqlink a:hover, .faqback a:hover { text-decoration: underline; }
.faqlink a { display: inline-flex; align-items: center; gap: 7px; }
.faqback { margin-top: 28px; border-top: 1px solid var(--line); padding-top: 20px; }

/* ---------- naming the file on the way out ---------- */
/*
   A file called "Project Falcon - KAG term sheet.pdf" undoes a redaction the
   moment it is attached to an email, and nothing inside the document is to
   blame. So the name is offered for editing before anything is saved, with
   anything that was covered inside the document taken out of it first.
*/
/* Tinted rather than white: it sits on top of a white document, and a white
   card on a white page reads as part of it. */
.nameinner {
  max-width: 460px; text-align: left;
  background: #f4f6fa; border: 1px solid #dfe4ec;
}
.nameopt { margin-top: 14px; font-size: 13px; align-items: flex-start; }
.namefaint { color: var(--ink-soft); }
.nameinput { background: #fff; }
.namehead { margin: 0 0 14px; font-size: 17px; letter-spacing: -0.01em; }
.namelabel { display: block; font-size: 12.5px; color: var(--ink-soft); margin-bottom: 6px; }
.nameinput {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 14px;
  padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--radius);
  background: #fff; color: var(--ink);
}
.nameinput:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }
.namego { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; }

/* ---------- asking before something is thrown away ---------- */
/*
   Opening another file discards the one on screen, and unlike a reload the
   browser cannot offer to stop it: nothing is navigating, so beforeunload
   never fires. The tool has to ask for itself.
*/
.confirmbody { margin: 0; color: var(--ink-soft); font-size: 13.5px; line-height: 1.55; }
.primary.danger { background: #d92d20; border-color: #d92d20; }
.primary.danger:hover { background: #b42318; }

/* A draft is a few kilobytes of marks, not the document, so it is worth
   saying what was and was not saved. */
.drafthint {
  margin: 0; font-size: 12.5px; color: var(--accent);
  background: #eef4ff; border-radius: var(--radius); padding: 8px 10px;
}

/* ---------- the picked image, full size ---------- */
/*
   The thumbnail is 42 pixels wide, which is enough to tell two picks apart and
   not enough to check that the right thing was picked. Clicking it shows what
   was actually cut out.
*/
.imageinner { max-width: 560px; text-align: left; background: #f4f6fa; border: 1px solid #dfe4ec; }
.imageframe {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px; display: flex; align-items: center; justify-content: center;
  max-height: 60vh; overflow: auto;
}
#imagefull { max-width: 100%; height: auto; display: block; image-rendering: auto; }
.templates canvas { cursor: zoom-in; }

/* ---------- one thing at a time, on a small screen ---------- */
/*
   Side by side, the panel and the document each got about 300 pixels of a
   844-pixel phone: too little to read a page in and too little to work the
   controls in. So on a narrow screen one of them is open and the other is a
   strip down the side — tapped or swiped to trade places.

   A strip rather than nothing at all, because a pane that vanishes is a pane
   you have to remember is there. The toolbar sits above both, since which
   half is open has no bearing on wanting to undo something or zoom in.
*/
.peek { display: none; }

@media (max-width: 900px) {
  body.reviewing #view-review { padding-top: 12px; }
  body.reviewing .review {
    position: relative; display: flex; gap: 8px;
    grid-template-columns: none;
  }
  body.reviewing .panel, body.reviewing .stage {
    min-width: 0; transition: flex-basis .18s ease;
  }

  /* The open half takes what is left; the shut one is a strip, and its
     contents are clipped rather than reflowed — a panel squeezed to 46 pixels
     would spend the animation rearranging itself. */
  body.reviewing[data-pane="edit"] .panel { flex: 1 1 auto; }
  body.reviewing[data-pane="edit"] .stage { flex: 0 0 46px; overflow: hidden; }
  body.reviewing[data-pane="doc"] .stage { flex: 1 1 auto; }
  body.reviewing[data-pane="doc"] .panel { flex: 0 0 46px; overflow: hidden; }

  /* Nothing inside a shut pane is touchable: the tap belongs to the strip. */
  body.reviewing[data-pane="edit"] .stage > *,
  body.reviewing[data-pane="doc"] .panel > * { pointer-events: none; }

  .peek {
    /* Above the shut pane, not beside it: a page number badge is positioned
       inside that pane and would otherwise show through the strip. */
    display: block; position: absolute; top: 0; bottom: 0; width: 46px; z-index: 3;
    background: var(--card); border: 1px solid var(--line);
    border-radius: var(--radius); cursor: pointer; padding: 0;
    font: inherit; font-size: 12.5px; font-weight: 600; color: var(--ink-soft);
    writing-mode: vertical-rl; text-orientation: mixed;
    display: flex; align-items: center; justify-content: center;
  }
  .peek[hidden] { display: none; }
  .peek:hover { color: var(--ink); background: #eef1f6; }
  #peek-edit { left: 0; }
  #peek-doc { right: 0; }

  /* The toolbar is lifted out of the panel and sits above both halves, so it
     is there whichever one is open. */
  body.reviewing .panel-head.afloat {
    position: static; border: 1px solid var(--line); border-radius: var(--radius);
    background: var(--card); margin-bottom: 10px; flex: none;
  }

  .exportbar { padding: 10px 12px; gap: 10px; flex-wrap: nowrap; }
  .exportbar .exportgo { flex: 1; gap: 10px; }
  #exportnote { display: none; }
  .exportbar .primary { flex: 1; white-space: nowrap; padding: 10px 12px; }

  /* Pinch is how anyone zooms anything on a phone, and on the document it
     means the document. Handing the gesture to the browser zoomed the whole
     app instead — panel, toolbar and header swelling together, with the page
     no more readable than before. The canvas keeps every touch and the
     two-finger one drives the document's own zoom. */
  .page canvas { touch-action: none; }

  /* Room for a thumb. The zoom and tool buttons are 34px on a desktop, which
     is a comfortable click and an awkward tap. */
  .tool { width: 44px; height: 40px; }
  .termadd input, .termadd button { min-height: 44px; }
  .termdrop { width: 32px; height: 32px; }
}
