:root {
  color-scheme: light;

  /* Warm paper rather than a dark editor. A tool people trust with a payslip
     should look like a workshop, not a terminal. */
  /* One shared page measure: the bench columns and the footer are centred
     on it, so their outer edges line up on any screen. */
  --measure: 1680px;
  /* The breadcrumb row above the bench: 28px line box + 12px gap. The
     columns beside the bench drop by exactly this, so Browse, Tools,
     the zoom bar and the right-hand panel all start on one line. */
  --crumbs-drop: 40px;
  --bg: #f6f3ec;
  --panel: #fffdf8;
  --panel-2: #faf7f1;
  --line: #e6e0d4;
  --line-soft: #ece6da;
  --text: #23211d;
  --text-2: #5c574e;
  --muted: #8d887c;

  /* Orange is the product; violet is the helper. Keeping them apart is what
     makes "you did this" and "the agent did this" readable at a glance. */
  --accent: #f26a2e;
  --accent-deep: #b8471a;
  --accent-soft: #fde8dd;
  --agent: #6c5ce0;
  --agent-deep: #4b3cb0;
  --agent-soft: #e8e4ff;
  --danger: #c2410c;

  /* One hue per kind of file, so the eye can sort a mixed bench without reading. */
  --kind-pdf: #f26a2e;
  --kind-pdf-soft: #fde8dd;
  --kind-image: #2e8ce8;
  --kind-image-soft: #ddeeff;
  --kind-video: #6c5ce0;
  --kind-video-soft: #e8e4ff;
  --kind-audio: #12a594;
  --kind-audio-soft: #d8f2ee;
  /* Two later arrivals. Convert is its own category because format changing is
     what people search for by name; inspect reads a file without changing it,
     which is a different promise from every other tool here. */
  --kind-convert: #d4741a;
  --kind-convert-soft: #fceadb;
  --kind-inspect: #5b7085;
  --kind-inspect-soft: #e4eaf0;

  /* One hue per document on the bench, so two PDFs read as two things without
     having to compare their names. Orange stays first: with a single document
     loaded nothing is banded at all, and the moment a second arrives the first
     keeps the colour the app already uses for a PDF. */
  --doc-0: #f26a2e;
  --doc-1: #2e8ce8;
  --doc-2: #12a594;
  --doc-3: #b85cd6;

  --radius: 16px;
  --radius-sm: 10px;
}

* { box-sizing: border-box; }

/* A column the height of the viewport, so the footer sits at the bottom of the
   screen when the bench is empty instead of riding up under the dropzone. */
body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.5 'Instrument Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 28px;
  height: 72px;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
  position: relative;
}

/* Categories in the header. The sidebar is the full map, but it scrolls away
   and it is the first thing a narrow screen drops; this stays put. */
/* Centred on the window, not on whatever space the brand and buttons leave.
   Taken out of the flex flow so a long file name on one side cannot shove the
   categories off-centre. */
.topnav {
  position: absolute; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 4px;
  max-width: min(560px, calc(100% - 460px));
  overflow-x: auto; scrollbar-width: none;
}
.topnav::-webkit-scrollbar { display: none; }
.topnav-link {
  display: inline-flex; flex-direction: column; align-items: center; gap: 4px;
  white-space: nowrap; padding: 7px 15px; border-radius: 13px;
  border: 1px solid transparent;
  font-size: 12px; font-weight: 500; color: var(--text-2); text-decoration: none;
}
.topnav-link:hover { background: var(--panel-2); color: var(--text); }
.topnav-link.is-current {
  background: var(--accent-soft); border-color: #f6d3c0;
  color: var(--accent-deep); font-weight: 600;
}
.topnav-icon { display: inline-flex; align-items: center; justify-content: center; }
.topnav-icon.kind-pdf { color: var(--kind-pdf); }
.topnav-icon.kind-image { color: var(--kind-image); }
.topnav-icon.kind-video { color: var(--kind-video); }
.topnav-icon.kind-audio { color: var(--kind-audio); }
.topnav-icon.kind-convert { color: var(--kind-convert); }
.topnav-icon.kind-inspect { color: var(--kind-inspect); }
.topnav-link.is-current .topnav-icon { color: inherit; }

@media (max-width: 1000px) {
  /* No room to centre between the brand and the buttons: let it sit in the row. */
  .topnav { position: static; transform: none; max-width: none; margin-left: 8px; flex: 1; min-width: 0; }
}
@media (max-width: 720px) {
  .topbar { padding: 0 16px; gap: 10px; }
  .topnav-link { padding: 6px 10px; font-size: 11px; }
}

.brand { display: flex; align-items: center; gap: 13px; }
.brand h1 {
  font-size: 19px;
  font-weight: 600;
  margin: 0;
  letter-spacing: -0.015em;
}

/* A padlock whose body is a toolbox: the shackle is also the handle. A lock
   alone says safe but not workshop; a toolbox alone says the opposite. */
.mark { color: var(--accent); flex-shrink: 0; }

.toolbox {
  width: 38px;
  height: 34px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
}
.toolbox-handle {
  width: 18px;
  height: 9px;
  border: 3px solid var(--accent);
  border-bottom: none;
  border-radius: 7px 7px 0 0;
  margin-bottom: -1px;
}
.toolbox-body {
  width: 34px;
  height: 23px;
  border-radius: 8px;
  background: var(--accent);
  display: grid;
  place-items: center;
}
.toolbox-body::after {
  content: "";
  width: 10px;
  height: 5px;
  border-radius: 2px;
  background: var(--panel);
}


.agent-status {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 16px;
  border-radius: 999px;
  background: var(--agent-soft);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--agent-deep);
}
/* Flex on the element itself outranks the hidden attribute, and this one
   must not claim an agent is ready in a browser that has no WebMCP. */
.agent-status[hidden] { display: none; }
.agent-dot {
  width: 8px; height: 8px; border-radius: 999px;
  background: var(--agent);
}

/* Tools on the left, the work in the middle, what changed on the right. The
   centre column belongs to the files: controls that were sitting in it were
   pushing the actual work down the page. */
main {
  display: grid;
  /* nav · rail · bench · side. The rail only exists once a file is open, so the
     columns are declared per-state rather than once. The right-hand column is
     always held: "Changes so far" is where the work accumulates, and a panel
     that appears and disappears under the cursor is worse than an empty one. */
  grid-template-columns: 232px 268px minmax(0, 1fr) 300px;
  gap: 18px;
  padding: 18px 24px 28px;
  align-items: start;
  /* A measure wide enough to leave the canvas real room on a large display,
     shared with the footer so the two are centred on the same edge. */
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  /* Not flex:1 — a page with prose underneath should let the prose follow the
     bench, not have the bench stretched to fill the window first. */
  flex: 0 0 auto;
}
main:has(#rail[hidden]) { grid-template-columns: 232px minmax(0, 1fr) 300px; }
/* The home page has nothing after the bench, so there it does take the height. */
body:not([data-scope]) main { flex: 1 0 auto; }

@media (max-width: 1200px) {
  main, main:has(#rail[hidden]) { grid-template-columns: 208px minmax(0, 1fr); }
  .side { grid-column: 1 / -1; flex-direction: row; }
  .side > * { flex: 1; }
}
@media (max-width: 860px) {
  main, main:has(#rail[hidden]) { grid-template-columns: 1fr; }
  .side { flex-direction: column; }
  .sidenav { position: static; max-height: none; }
  .nav-list { flex-direction: row; flex-wrap: wrap; }
  .nav-item { flex: 1 1 150px; }
  .nav-sub { display: none; }
}

/* --- Category navigation ------------------------------------------------- */

.sidenav {
  position: sticky;
  top: 18px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 16px 14px;
  max-height: calc(100vh - 108px);
  overflow-y: auto;
}
.sidenav-title {
  font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); margin: 2px 0 12px; padding: 0 8px;
}
.nav-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }

.nav-link {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 9px 10px; border-radius: 11px; border: 1px solid transparent;
  background: none; font: inherit; font-size: 14.5px; color: var(--text-2);
  text-decoration: none; text-align: left; cursor: pointer;
}
a.nav-link:hover, button.nav-link:hover { background: var(--panel-2); color: var(--text); }
.nav-link.is-current {
  background: var(--accent-soft); color: var(--accent-deep);
  border-color: #f6d3c0; font-weight: 600;
}
.nav-link.is-soon { cursor: default; color: var(--muted); opacity: .72; }
.nav-icon { display: inline-flex; flex: none; }
.nav-label { flex: 1; min-width: 0; }
.nav-badge {
  font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--muted); background: var(--panel-2); border: 1px solid var(--line-soft);
  padding: 2px 6px; border-radius: 999px;
}
/* Category and disclosure are two controls in one row: the name navigates,
   the caret only opens the list of single-job pages. */
.nav-row { display: flex; align-items: center; gap: 2px; border-radius: 11px; }
.nav-row:hover { background: var(--panel-2); }
.nav-row .nav-link { flex: 1; min-width: 0; }
.nav-row .nav-link:hover { background: none; }
.nav-row.is-current { background: var(--accent-soft); border: 1px solid #f6d3c0; }
.nav-row.is-current .nav-link { color: var(--accent-deep); font-weight: 600; border: 0; }
.nav-row.is-current .nav-toggle { color: var(--accent-deep); }

.nav-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; width: 30px; height: 30px; margin-right: 5px;
  border: 0; border-radius: 8px; background: none; color: var(--muted); cursor: pointer;
}
.nav-toggle:hover { background: var(--panel); color: var(--text); }
.nav-caret { transition: transform .15s ease; }
.nav-toggle[aria-expanded="true"] .nav-caret { transform: rotate(90deg); }

/* Sub-tools live inside the parent item, not in a second column: the editing
   rail already owns that side of the screen once a file is open. */
.nav-sub {
  list-style: none; margin: 2px 0 6px; padding: 0 0 0 21px;
  display: flex; flex-direction: column; gap: 1px;
  border-left: 1px solid var(--line-soft); margin-left: 19px;
}
.nav-sub a {
  display: block; padding: 7px 10px; border-radius: 8px;
  font-size: 13.5px; color: var(--text-2); text-decoration: none;
}
.nav-sub a:hover { background: var(--panel-2); color: var(--accent-deep); }

.sidenav-note {
  display: flex; align-items: flex-start; gap: 7px;
  margin: 14px 4px 2px; padding-top: 13px; border-top: 1px solid var(--line-soft);
  font-size: 11.5px; line-height: 1.45; color: var(--muted);
}
.sidenav-note svg { flex: none; margin-top: 1px; }

/* Per-kind colour, so the nav and the file badges agree. */
.nav-icon.kind-workbench, .cat-icon.kind-workbench { color: var(--text-2); }
.nav-icon.kind-pdf,   .cat-icon.kind-pdf   { color: var(--kind-pdf); }
.nav-icon.kind-image, .cat-icon.kind-image { color: var(--kind-image); }
.nav-icon.kind-video, .cat-icon.kind-video { color: var(--kind-video); }
.nav-icon.kind-audio, .cat-icon.kind-audio { color: var(--kind-audio); }
.nav-icon.kind-convert, .cat-icon.kind-convert { color: var(--kind-convert); }
.nav-icon.kind-inspect, .cat-icon.kind-inspect { color: var(--kind-inspect); }
.nav-icon.kind-ebook, .cat-icon.kind-ebook { color: #b85cd6; }

/* --- Category cards ------------------------------------------------------ */

.categories { margin-top: 34px; padding-top: 30px; border-top: 1px solid var(--line); }
.cat-head { margin-bottom: 18px; }
.cat-head h2 { margin: 0 0 6px; font-size: 19px; letter-spacing: -0.012em; color: var(--text); }
.cat-head p { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--text-2); max-width: 58ch; }

.cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(238px, 1fr)); gap: 12px; }
.cat-card {
  display: flex; align-items: center; gap: 14px;
  padding: 17px 18px; border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--panel); text-decoration: none;
}
a.cat-card:hover {
  border-color: var(--accent); background: var(--panel-2);
  transform: translateY(-1px); box-shadow: 0 4px 14px rgba(35, 33, 29, .06);
}
a.cat-card { transition: transform .14s ease, box-shadow .14s ease, border-color .14s ease; }
.cat-card.is-soon { opacity: .58; }
.cat-icon { display: inline-flex; flex: none; }
.cat-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.cat-text b { font-size: 15.5px; font-weight: 600; color: var(--text); }
.cat-text small { font-size: 12.5px; color: var(--muted); }
.cat-go { color: var(--accent); font-size: 17px; flex: none; }
.cat-badge {
  font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--muted); flex: none;
}

/* --- Tools rail ---------------------------------------------------------- */

.rail {
  position: sticky;
  top: 18px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 18px;
  max-height: calc(100vh - 108px);
  overflow-y: auto;
}
.rail[hidden] { display: none; }
.rail-title {
  font-size: 17px;
  font-weight: 600;
  margin: 0 0 14px;
}
.rail-body { display: flex; flex-direction: column; gap: 18px; }

.rail-group { display: flex; flex-direction: column; gap: 8px; }
.rail-group h3 {
  margin: 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
/* Each group takes the colour of the files it acts on. */
.rail-pdf h3 { color: var(--kind-pdf); }
.rail-image h3 { color: var(--kind-image); }
.rail-video h3 { color: var(--kind-video); }
.rail-audio h3 { color: var(--kind-audio); }
.rail-convert h3 { color: var(--kind-convert); }
.rail-inspect h3 { color: var(--kind-inspect); }

/* In the rail the bars stack rather than run across, and lose their own
   chrome: the rail is already a panel. */
.rail .actionbar,
.rail .actionbar-secondary {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  margin: 0;
  padding: 0;
  background: none;
  border: none;
}
.rail .field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
}
.rail .field select,
.rail .field input[type="number"],
.rail .field input[type="text"] { flex: 1; min-width: 0; width: auto; }
.rail .field input[type="range"] { flex: 1; width: auto; min-width: 70px; }
.rail .field input.adj { width: auto; }
.rail .sep { display: none; }
.rail .zoom-field { margin-left: 0; }
.rail .hint-inline { font-size: 12px; line-height: 1.45; }
.rail .selection-count { margin: 0; font-size: 12px; }
.rail button { width: 100%; }

h2 {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  margin: 0 0 8px;
}

.hint {
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-2);
  margin: 0 0 16px;
  text-wrap: pretty;
}

.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  /* Matched to the sidebars beside it: the three columns should read as one
     band rather than a tall pair with a letterbox slot in the middle. */
  /* Level with the sidebar beside it. Both are capped by the same viewport
     measure, so they finish on the same line at any window height. */
  min-height: min(738px, calc(100vh - 90px));
  padding: 40px 28px;
  border: 2px dashed var(--line);
  border-radius: 20px;
  background: var(--panel);
  cursor: pointer;
  text-align: center;
}
.dropzone:hover, .dropzone:focus-visible, .dropzone.is-over {
  border-color: var(--accent);
  background: #fdf9f4;
  outline: none;
}
.dropzone-main {
  margin: 0 0 3px;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.015em;
}
.dropzone-sub { margin: 0; font-size: 14px; color: var(--text-2); }

.asset-list, .op-list, .tool-list { list-style: none; margin: 16px 0 0; padding: 0; }

.asset {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin-bottom: 8px;
}
.asset-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.asset-name { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.asset-detail { font-size: 12px; color: var(--muted); }
.asset .ghost { margin-left: auto; }

.side { display: flex; flex-direction: column; gap: 20px; position: sticky; top: 18px; }
@media (max-width: 1200px) { .side { position: static; } }

.stack, .tools-panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 22px;
}

.op {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 12px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
  margin-bottom: 8px;
  transition: border-color 0.15s;
}
.op:hover { border-color: var(--line); }
.op.is-disabled { opacity: 0.62; }
.op.is-disabled .op-summary { text-decoration: line-through; color: var(--muted); }
.op-summary {
  flex: 1;
  font-size: 14px;
  line-height: 1.4;
  min-width: 0;
  text-wrap: pretty;
}
.op input[type="checkbox"] { margin-top: 2px; accent-color: var(--accent); }

.badge {
  font-size: 11px;
  padding: 3px 9px;
  border-radius: 999px;
  font-weight: 600;
  white-space: nowrap;
}
.badge-agent { background: var(--agent-soft); color: var(--agent-deep); }
.badge-user { background: var(--accent-soft); color: var(--accent-deep); }

.tool {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  padding: 8px 11px;
  border-radius: var(--radius-sm);
  background: var(--agent-soft);
  color: var(--agent-deep);
  margin-bottom: 6px;
}
.tool::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--agent);
  flex-shrink: 0;
}

.empty { color: var(--muted); font-size: 13px; padding: 8px 2px; }

button {
  font: inherit;
  cursor: pointer;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  color: var(--text);
  background: var(--panel);
}
.primary {
  width: 100%;
  margin-top: 16px;
  padding: 13px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 12px;
  font-weight: 600;
  font-size: 15px;
}
.primary:hover:not(:disabled) { background: #e05a1f; }
.primary:disabled {
  background: var(--panel-2);
  color: var(--muted);
  cursor: not-allowed;
}
.ghost {
  background: var(--panel);
  color: var(--text-2);
  padding: 6px 12px;
  font-size: 13.5px;
}
.ghost:hover:not(:disabled) {
  color: var(--text);
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* --- Page editor --------------------------------------------------------- */

.editor { margin-top: 20px; }

.actionbar {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  padding: 12px 14px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin-bottom: 12px;
}
.selection-count { font-size: 13px; color: var(--muted); margin-right: 6px; }
.sep { flex: 1; }

.danger {
  background: transparent;
  color: var(--danger);
  border-color: rgb(248 113 113 / 0.35);
  padding: 4px 12px;
  font-size: 13px;
}
.danger:hover:not(:disabled) { background: rgb(248 113 113 / 0.12); }
button:disabled { opacity: 0.4; cursor: not-allowed; }

/* --- Documents on the bench ---------------------------------------------- */
/* Each PDF gets a group of its own: a heading, and a coloured edge running down
   the side of its pages. The colour is the cheap part of the distinction, the
   heading is the honest one, and both go away when the documents become one. */

.page-group {
  --band: var(--doc-0);
  position: relative;
  padding-left: 14px;
  margin-bottom: 26px;
}
.page-group[data-band="1"] { --band: var(--doc-1); }
.page-group[data-band="2"] { --band: var(--doc-2); }
.page-group[data-band="3"] { --band: var(--doc-3); }
.page-group:last-child { margin-bottom: 0; }

/* The edge only appears when there is a heading above it, which is to say when
   there is more than one document to tell apart. */
.page-group:has(.page-group-head)::before {
  content: "";
  position: absolute;
  left: 0;
  top: 4px;
  bottom: 0;
  width: 3px;
  border-radius: 999px;
  background: var(--band);
  opacity: 0.5;
}

.page-group-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 10px;
}
.page-group-name {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.page-group-count { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* While a page is in the air every group says it will take it, because it
   will: dropping across the boundary joins the two documents. */
.page-group.is-drop-target:has(.page-group-head) {
  outline: 1px dashed var(--line);
  outline-offset: 6px;
  border-radius: var(--radius-sm);
}
.page-group.is-drop-over:has(.page-group-head) {
  outline-color: var(--band);
  outline-style: solid;
}

/* The redaction panel. It opens under the action bar rather than in a modal:
   the pages it is about are right there, and watching them turn black as the
   operation lands is the confirmation that the thing worked. */
/* display:flex would otherwise beat the hidden attribute's UA display:none,
   leaving the panel open on load. */
.blackout[hidden] { display: none; }
.blackout {
  padding: 14px 16px 16px;
  margin-bottom: 12px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.blackout-lede { margin: 0; font-size: 13px; line-height: 1.5; color: var(--text-2); max-width: 62ch; }
.blackout-row { display: flex; flex-direction: column; gap: 5px; }
.blackout-row label { font-size: 12px; font-weight: 600; color: var(--text-2); }
.blackout-row input {
  font: inherit;
  font-size: 14px;
  padding: 8px 11px;
  color: var(--text);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.blackout-row input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.blackout-cats { margin: 0; padding: 0; border: 0; display: flex; flex-wrap: wrap; gap: 6px 16px; }
.blackout-cats legend { padding: 0 0 6px; font-size: 12px; font-weight: 600; color: var(--text-2); }
.blackout-cats label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-2);
  cursor: pointer;
}
.blackout-cats input { accent-color: var(--accent); }

.blackout-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* .primary is sized for the full-width export button in the sidebar. In a row
   of controls it has to be an ordinary button again. */
.blackout-actions .primary {
  width: auto;
  margin-top: 0;
  padding: 8px 16px;
  font-size: 14px;
  border-radius: var(--radius-sm);
}
.blackout-status { font-size: 13px; color: var(--muted); flex: 1 1 12ch; }

.page-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 14px;
}

.page-cell {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  padding: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  transition: border-color 0.15s, opacity 0.15s;
}
.page-cell.is-loading { min-height: 160px; }
.page-cell.is-loading::after {
  content: "";
  position: absolute;
  inset: 8px;
  border-radius: 4px;
  background: var(--panel-2);
}
.page-cell.is-selected { border-color: var(--accent); background: var(--accent-soft); }
.page-cell.is-selected { border-color: var(--accent); }
.page-cell.is-removed { opacity: 0.32; }
.page-cell.is-removed img { filter: grayscale(1); }

/* A redacted page is showing a flattened image of itself with the black burned
   in. It reads as an ordinary page otherwise, so it says so out loud: the whole
   promise is that the covered text is gone, and that is worth confirming. */
.page-cell.is-redacted { border-color: var(--text); }
.page-cell.is-redacted .page-frame::after {
  content: "Redacted";
  position: absolute;
  bottom: 8px;
  left: 50%;
  translate: -50% 0;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--text);
  color: var(--panel);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.02em;
  pointer-events: none;
}
.page-cell.is-redacted .page-frame { position: relative; }

/* Rotation in CSS does not change the space an element reserves, so the frame
   is a square: the one shape that fits the same page at any rotation. The page
   is capped at 1/1.414 of the square (the A4 short-to-long ratio) on whichever
   axis is its long edge, so an upright page and a turned one are drawn at the
   same size, fully visible, without either escaping its cell. */
.page-frame {
  width: 100%;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  overflow: hidden;
  container-type: inline-size;
}

.page-cell img {
  max-width: 70.7cqw;
  max-height: 100cqw;
  width: auto;
  height: auto;
  border-radius: 3px;
  background: #fff;
  transition: rotate 0.2s;
}

/* Turned a quarter, the long edge runs horizontally: swap which axis is capped. */
.page-cell.is-quarter-turned img {
  max-width: 100cqw;
  max-height: 70.7cqw;
}

/* The whole card is the selection target, so it advertises that with a pointer.
   The checkbox stays as a state indicator and a keyboard affordance. */
.page-cell { cursor: pointer; user-select: none; }
.page-cell:hover { border-color: var(--muted); }

.page-check {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 1;
  width: 16px;
  height: 16px;
  cursor: pointer;
}

.page-zoom {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 1;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  padding: 0;
  font-size: 13px;
  line-height: 1;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: rgb(255 253 248 / 0.94);
  color: var(--text-2);
  opacity: 0;
  transition: opacity 0.15s, background 0.15s;
}
.page-cell:hover .page-zoom,
.page-zoom:focus-visible { opacity: 1; }
.page-zoom:hover { background: var(--accent); color: #fff; border-color: var(--accent); }

/* --- Enlarged viewer ----------------------------------------------------- */

.viewer {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-items: center;
  background: rgb(20 18 15 / 0.9);
  backdrop-filter: blur(3px);
}
.viewer[hidden] { display: none; }

.viewer-image {
  max-width: min(88vw, 900px);
  max-height: 86vh;
  border-radius: 4px;
  background: #fff;
  box-shadow: 0 20px 60px rgb(0 0 0 / 0.5);
  transition: rotate 0.2s;
}
/* Turned a quarter, the page's height spans the viewport horizontally. */
.viewer-image.is-quarter-turned {
  max-width: 86vh;
  max-height: min(88vw, 900px);
}

.viewer-caption {
  position: fixed;
  bottom: 24px;
  font-size: 13px;
  color: #cfc8bb;
  font-variant-numeric: tabular-nums;
}

.viewer-close {
  position: fixed;
  top: 18px;
  right: 22px;
  width: 36px;
  height: 36px;
  font-size: 22px;
  line-height: 1;
  background: transparent;
  color: #cfc8bb;
  border-color: transparent;
}
.viewer-close:hover { color: #fff; border-color: rgb(255 255 255 / 0.25); }

.viewer-nav {
  position: fixed;
  top: 50%;
  translate: 0 -50%;
  width: 44px;
  height: 64px;
  font-size: 30px;
  line-height: 1;
  background: transparent;
  color: #cfc8bb;
  border-color: transparent;
}
.viewer-nav:hover { color: #fff; border-color: rgb(255 255 255 / 0.25); }
.viewer-prev { left: 16px; }
.viewer-next { right: 16px; }

.page-number { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* --- Image editor -------------------------------------------------------- */

.field {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
}
.field select, .field input[type="number"] {
  font: inherit;
  padding: 3px 8px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--text);
}
.field input[type="number"] { width: 82px; }
.field input[type="range"] { width: 90px; accent-color: var(--accent); }
input[type="range"] { accent-color: var(--accent); }
#look-strength-value { font-variant-numeric: tabular-nums; min-width: 34px; }

.image-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 14px;
}
.image-cell {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.image-cell .image-name {
  font-size: 11px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Thumbnail size ------------------------------------------------------ */
/* Both grids take their column width from a variable the size slider sets, so
   one control governs however many items are on screen. */

.page-grid {
  grid-template-columns: repeat(auto-fill, minmax(var(--thumb-size, 130px), 1fr));
}
.image-grid {
  grid-template-columns: repeat(auto-fill, minmax(var(--thumb-size, 180px), 1fr));
}

.zoom-field { margin-left: auto; }
.zoom-icon { font-size: 11px; color: var(--muted); }
.zoom-field input[type="range"] { width: 110px; }

.actionbar-secondary { margin-top: -4px; }
.hint-inline { font-size: 12px; color: var(--muted); }

/* --- Image cells --------------------------------------------------------- */

.image-cell { position: relative; }
/* The frame is a fixed box and the image fills it with object-fit doing the
   letterboxing. Sizing the image by max-height instead does not work here: a
   grid item does not resolve a percentage height against a parent whose own
   height comes from aspect-ratio, so a square or portrait photo overflowed and
   was clipped, which is what made a centred mask look off-centre. */
.image-frame {
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--panel-2);
  border-radius: var(--radius-sm);
}
.image-cell img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: transparent;
}

/* --- File list ----------------------------------------------------------- */
/* A long list of files would push the previews off the screen, so past a few
   it collapses behind a summary the user can open. */

.files-summary {
  margin-top: 14px;
  padding: 9px 14px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.files-summary summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--muted);
  user-select: none;
}
.files-summary summary:hover { color: var(--text); }

.asset-list.is-collapsed { display: none; }

.viewer-expand {
  position: fixed;
  top: 18px;
  right: 68px;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  background: transparent;
  color: #cfc8bb;
  border-color: transparent;
}
.viewer-expand:hover { color: #fff; border-color: rgb(255 255 255 / 0.25); }

/* In fullscreen the overlay is the whole screen, so the page can use all of it. */
.viewer:fullscreen { background: #06070a; }
.viewer:fullscreen .viewer-image { max-width: 96vw; max-height: 94vh; }
.viewer:fullscreen .viewer-image.is-quarter-turned { max-width: 94vh; max-height: 96vw; }

.video-badge {
  position: absolute;
  bottom: 8px;
  left: 8px;
  font-size: 10px;
  color: #fff;
  background: rgb(35 33 29 / 0.8);
  border-radius: 4px;
  padding: 2px 6px;
  pointer-events: none;
}
.image-frame { position: relative; }
.image-cell.is-quarter-turned img { max-width: 70%; }

/* --- Dropzone -------------------------------------------------------------
   The accepted kinds are shown rather than described: a row of icons answers
   "what can I put here" before the text is read. */

/* One hue per kind of file, so a mixed bench can be sorted by eye without
   reading a word. The tile carries the colour; the label stays plain. */
.dropzone-icons {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin-top: 14px;
}
.dropzone-icons .kind {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 12px 10px;
  border-radius: var(--radius-sm);
  background: var(--panel-2);
  border: 1px solid var(--line-soft);
  text-align: center;
  transition: background 0.15s, border-color 0.15s;
}
.dropzone:hover .kind { border-color: var(--line); }

.kind-tile {
  width: 60px;
  height: 60px;
  border-radius: 18px;
  display: grid;
  place-items: center;
}
.kind-pdf .kind-tile { background: var(--kind-pdf-soft); color: var(--kind-pdf); }
.kind-image .kind-tile { background: var(--kind-image-soft); color: var(--kind-image); }
.kind-video .kind-tile { background: var(--kind-video-soft); color: var(--kind-video); }
.kind-audio .kind-tile { background: var(--kind-audio-soft); color: var(--kind-audio); }
.kind-convert .kind-tile { background: var(--kind-convert-soft); color: var(--kind-convert); }
.kind-inspect .kind-tile { background: var(--kind-inspect-soft); color: var(--kind-inspect); }

.dropzone-icons b {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.2;
}
.dropzone-icons small {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.25;
}
/* The tile keeps its size; the glyph inside grows into it. */
.kind-tile svg { width: 30px; height: 30px; }

@media (max-width: 900px) {
  .dropzone-icons { grid-template-columns: repeat(2, 1fr); }
}

/* --- Audio --------------------------------------------------------------- */

.audio-list { display: flex; flex-direction: column; gap: 10px; }
.audio-row {
  display: grid;
  grid-template-columns: 180px 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 10px 14px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.audio-name {
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.audio-wave { width: 100%; height: 60px; }
.audio-meta { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
@media (max-width: 700px) {
  .audio-row { grid-template-columns: 1fr; }
}

.field input[type="text"] {
  font: inherit;
  padding: 3px 8px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--text);
  width: 120px;
}
.field input.adj { width: 78px; }

/* --- Timeline ------------------------------------------------------------ */

.timeline-host { position: relative; }

/* overflow stays visible so the end handle, which sits on the last pixel of the
   track, is still grabbable rather than being clipped away. The canvas carries
   its own rounding instead. */
.timeline {
  position: relative;
  height: 76px;
  margin-top: 10px;
  cursor: crosshair;
  touch-action: none;
}
.timeline-canvas {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--panel-2);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
}

.timeline-selection {
  position: absolute;
  top: 0;
  bottom: 0;
  background: rgb(242 106 46 / 0.12);
  border-left: 1px solid var(--accent);
  border-right: 1px solid var(--accent);
  pointer-events: none;
}

.timeline-handle {
  position: absolute;
  top: -4px;
  bottom: -4px;
  width: 18px;
  margin-left: -9px;
  z-index: 2;
  cursor: ew-resize;
  background: transparent;
  touch-action: none;
}
.timeline-handle::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  width: 4px;
  height: 34px;
  border-radius: 3px;
  background: var(--accent);
  box-shadow: 0 0 0 1px rgb(0 0 0 / 0.4);
}
.timeline-handle:hover::after, .timeline-handle:focus-visible::after { height: 48px; }
.timeline-handle:focus-visible { outline: none; }

.timeline-playhead {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  background: var(--text);
  pointer-events: none;
  box-shadow: 0 0 4px rgb(0 0 0 / 0.6);
}

.audio-header {
  display: flex;
  align-items: center;
  gap: 10px;
}
.audio-header .audio-name { flex: 1; }
.play-button {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  color: var(--text);
}
.play-button:hover { background: var(--accent); color: #fff; border-color: var(--accent); }

.audio-row {
  display: block;
  padding: 12px 14px;
}

/* --- Video cells --------------------------------------------------------- */

/* auto-fit rather than auto-fill: a single clip stretches to the full width
   instead of leaving an empty column beside it. */
.video-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--thumb-size, 460px)), 1fr));
  gap: 16px;
}
.video-cell {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px;
}
.video-stage {
  display: grid;
  place-items: center;
  background: #23211d;
  border-radius: 6px;
  margin-bottom: 10px;
  overflow: hidden;
}
/* The canvas is rendered at a fixed internal resolution and scaled to fit the
   cell, so the size slider changes what is on screen without re-rendering
   every frame at a new resolution. */
.video-canvas {
  display: block;
  width: 100%;
  height: auto;
  max-height: calc(var(--thumb-size, 460px) * 1.1);
  object-fit: contain;
}
/* The stage anchors the controls that sit on the picture: the tick, and the
   view and remove buttons. Without this they position against the page. */
.video-stage { width: 100%; position: relative; }
.video-cell:hover .cell-actions,
.video-cell:focus-within .cell-actions { opacity: 1; }

.time-fields { display: flex; align-items: center; gap: 8px; }
.time-input { width: 74px; font-variant-numeric: tabular-nums; }

input[type="color"] {
  width: 30px;
  height: 26px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-2);
  cursor: pointer;
}

/* A checkerboard behind masked previews, so transparency reads as transparency
   rather than as whatever the panel colour happens to be. */
.image-frame {
  background-image:
    linear-gradient(45deg, #e9e3d6 25%, transparent 25%),
    linear-gradient(-45deg, #e9e3d6 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #e9e3d6 75%),
    linear-gradient(-45deg, transparent 75%, #e9e3d6 75%);
  background-size: 16px 16px;
  background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}

/* --- Sample files -------------------------------------------------------- */
/* A workbench with nothing on it cannot show what it does, so there is always
   a way to put something on it. The offer sits right under the doorway, and
   goes away with it once there is work on the bench. */

.demo-launcher {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
}
.demo-launcher[hidden] { display: none; }

.demo-button {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 20px;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  font-size: 13px;
  box-shadow: 0 6px 18px rgb(0 0 0 / 0.18);
  transition: translate 0.15s, box-shadow 0.15s;
}
.demo-button:hover { translate: 0 -1px; box-shadow: 0 10px 24px rgb(0 0 0 / 0.22); }
.demo-button.is-open { background: var(--text); color: var(--panel); }

/* The sets open in the page rather than over it: a list that floats can run
   off the bottom of a short window, and here there is room to spread out. */
.demo-menu {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 8px;
  width: 100%;
  padding: 14px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.demo-menu[hidden] { display: none; }
.demo-menu-heading, .demo-menu-note { grid-column: 1 / -1; }

.demo-menu-heading {
  margin: 0 0 2px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.demo-menu-note {
  margin: 2px 2px 0;
  font-size: 11px;
  line-height: 1.45;
  color: var(--muted);
}

.demo-item {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  width: 100%;
  padding: 10px;
  text-align: left;
  background: var(--panel-2);
  border: 1px solid transparent;
  color: var(--text);
}
.demo-item:hover:not(:disabled) { border-color: var(--accent); }
.demo-item.is-loading { opacity: 0.6; }
.demo-item.is-failed { border-color: var(--danger); }
.demo-item-icon { color: var(--accent); margin-top: 1px; }
.demo-item-text { display: flex; flex-direction: column; gap: 2px; }
.demo-item-text b { font-size: 13px; font-weight: 600; }
.demo-item-text small { font-size: 11px; color: var(--muted); line-height: 1.4; }

@media (max-width: 700px) {
  .demo-menu { width: min(320px, calc(100vw - 32px)); }
}

/* --- Lede ---------------------------------------------------------------- */
/* The claim is the product. It is said once, plainly, at full size, and then
   gets out of the way as soon as there is work on the bench. */

.lede {
  text-align: center;
  max-width: 800px;
  margin: 26px auto 30px;
}
.lede-title {
  font-size: 46px;
  line-height: 1.06;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--text);
  margin: 0;
  text-wrap: balance;
}
.lede-sub {
  margin: 16px auto 0;
  max-width: 560px;
  font-size: 18px;
  line-height: 1.55;
  color: var(--text-2);
  text-wrap: pretty;
}

/* Once files are loaded the headline shrinks to a label: the promise has been
   made, and the work is what matters now. */
.lede.is-compact { margin: 0 0 14px; text-align: left; }
.lede.is-compact .lede-title { font-size: 17px; letter-spacing: -0.01em; }
.lede.is-compact .lede-sub { display: none; }

@media (max-width: 900px) {
  .lede-title { font-size: 34px; }
}

/* --- Action buttons ------------------------------------------------------ */
/* Apply is where an adjustment becomes a change, so it has to look like the
   thing to press. A ghost button beside four sliders disappears. */

#apply-look, #apply-adjust, #apply-vignette, #apply-watermark, #apply-mask,
#apply-resize, #apply-format, #video-apply-look, #apply-speed, #reshuffle-blob,
#remove-blank {
  background: var(--accent-soft);
  border-color: transparent;
  color: var(--accent-deep);
  font-weight: 600;
  padding: 9px 14px;
}
#apply-look:hover:not(:disabled), #apply-adjust:hover:not(:disabled),
#apply-vignette:hover:not(:disabled), #apply-watermark:hover:not(:disabled),
#apply-mask:hover:not(:disabled), #apply-resize:hover:not(:disabled),
#apply-format:hover:not(:disabled), #video-apply-look:hover:not(:disabled),
#apply-speed:hover:not(:disabled), #reshuffle-blob:hover:not(:disabled),
#remove-blank:hover:not(:disabled) {
  background: var(--accent);
  color: #fff;
}
#apply-look:disabled, #apply-adjust:disabled, #apply-vignette:disabled,
#apply-mask:disabled {
  background: var(--panel-2);
  color: var(--muted);
  font-weight: 500;
}

/* Video and sound controls answer to their own hue, so the rail is readable at
   a glance when several kinds are loaded. */
.rail-video #video-apply-look { background: var(--kind-video-soft); color: var(--agent-deep); }
.rail-video #video-apply-look:hover { background: var(--kind-video); color: #fff; }
.rail-audio #apply-speed { background: var(--kind-audio-soft); color: #0b6b60; }
.rail-audio #apply-speed:hover { background: var(--kind-audio); color: #fff; }


/* --- Range inputs -------------------------------------------------------- */
/* accent-color alone leaves the unfilled part of the track dark, which reads as
   a hole punched in the paper. Drawn explicitly instead. */

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  height: 20px;
  background: transparent;
  cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 5px;
  border-radius: 999px;
  background: var(--line);
}
input[type="range"]::-moz-range-track {
  height: 5px;
  border-radius: 999px;
  background: var(--line);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 15px;
  height: 15px;
  margin-top: -5px;
  border-radius: 999px;
  background: var(--accent);
  border: 2px solid var(--panel);
  box-shadow: 0 1px 3px rgb(35 33 29 / 0.25);
}
input[type="range"]::-moz-range-thumb {
  width: 15px;
  height: 15px;
  border-radius: 999px;
  background: var(--accent);
  border: 2px solid var(--panel);
}

/* --- Photo grid ---------------------------------------------------------- */
/* With the controls moved out, the centre column has room: photographs can be
   looked at rather than merely identified. */
.image-grid { grid-template-columns: repeat(auto-fill, minmax(var(--thumb-size, 260px), 1fr)); }
.image-frame { aspect-ratio: 3 / 2; }
.image-cell {
  padding: 10px;
  border-radius: var(--radius);
}
.image-cell .image-name { font-size: 12.5px; padding-top: 2px; }

/* --- File chips ---------------------------------------------------------- */
/* A file is a small thing with a name and a way to close it. Once the rows are
   this size, a whole list of them fits without needing to be folded away. */

.asset-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 14px;
}
.asset {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  width: auto;
  padding: 7px 8px 7px 13px;
  margin: 0;
  border-radius: 999px;
  background: var(--panel);
  border: 1px solid var(--line);
}
.asset-info { flex-direction: row; align-items: baseline; gap: 8px; }
.asset-name { font-size: 13.5px; font-weight: 600; max-width: 210px; }
.asset-detail { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* The chip is tinted by what it holds, matching the tools rail. */
.asset::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 999px;
  flex-shrink: 0;
}
.asset-pdf::before { background: var(--kind-pdf); }
/* With several PDFs loaded the chip's dot matches its group on the bench, so
   the name at the top and the pages below it are the same document at a
   glance. A lone PDF keeps the plain PDF orange: there is nothing to tell it
   apart from. */
.asset-pdf[data-band="0"]::before { background: var(--doc-0); }
.asset-pdf[data-band="1"]::before { background: var(--doc-1); }
.asset-pdf[data-band="2"]::before { background: var(--doc-2); }
.asset-pdf[data-band="3"]::before { background: var(--doc-3); }
.asset-image::before { background: var(--kind-image); }
.asset-video::before { background: var(--kind-video); }
.asset-audio::before { background: var(--kind-audio); }
.asset-convert::before { background: var(--kind-convert); }
.asset-inspect::before { background: var(--kind-inspect); }

.asset-remove {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  margin-left: 2px;
  font-size: 16px;
  line-height: 1;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
}
.asset-remove:hover { background: var(--accent-soft); color: var(--accent-deep); }

/* --- Compact dropzone ---------------------------------------------------- */
/* Once files are loaded the doorway steps aside: one line, still a target. */

.dropzone[hidden] { display: none !important; }

.dropzone.is-compact {
  padding: 11px 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  border-style: dashed;
  background: transparent;
}
.dropzone.is-compact .dropzone-main {
  margin: 0;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--muted);
}
.dropzone.is-compact .dropzone-sub,
.dropzone.is-compact .dropzone-icons { display: none; }
.dropzone.is-compact:hover .dropzone-main { color: var(--accent-deep); }

/* --- Zoom, over the work it sizes ---------------------------------------- */

.worktools {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  margin-bottom: 10px;
}
/* Flex on the element outranks the hidden attribute, and the zoom sliders are
   parked in one slot: without this, the one belonging to a grid that is no
   longer on screen stays visible next to the current one. */
.worktools[hidden] { display: none; }
.zoom-control {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--panel);
  border: 1px solid var(--line);
}
.zoom-control input[type="range"] { width: 120px; }

/* --- Controls on the cell ------------------------------------------------ */
/* A file is removed and inspected where you are looking at it, not from a
   separate list repeating what the grid already shows. */

.cell-actions {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  gap: 5px;
  opacity: 0;
  transition: opacity 0.15s;
}
.image-cell:hover .cell-actions,
.image-cell:focus-within .cell-actions { opacity: 1; }

.cell-button {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  font-size: 17px;
  line-height: 1;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: rgb(255 253 248 / 0.95);
  color: var(--text-2);
  backdrop-filter: blur(2px);
}
.cell-button:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.cell-remove:hover { background: var(--danger); border-color: var(--danger); }

/* --- Picking files out --------------------------------------------------- */
/* Selecting narrows what the controls act on. Nothing picked means everything,
   so the ticks are quiet until one is used and unmistakable afterwards. */

.cell-tick {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: rgb(255 253 248 / 0.95);
  color: transparent;
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity 0.15s, background 0.15s, color 0.15s;
}
/* An empty tick appears on approach; a ticked one always shows, or a selection
   would be invisible the moment the pointer left. */
.image-cell:hover .cell-tick,
.image-cell:focus-within .cell-tick,
.video-cell:hover .cell-tick,
.video-cell:focus-within .cell-tick { opacity: 1; }
.cell-tick:hover { border-color: var(--accent); color: var(--accent); }

.is-picked .cell-tick {
  opacity: 1;
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* The picked file itself, so a selection is readable from across the grid
   rather than by hunting for small ticks. */
.image-cell.is-picked,
.video-cell.is-picked {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 2px var(--accent);
}
/* Everything not picked steps back, which is what makes four out of forty
   legible at a glance.
   Dimming only, never a colour filter: these cells are live previews, and
   draining the colour from one would be indistinguishable from a black-and-white
   look being applied to it. */
.image-grid:has(.is-picked) .image-cell:not(.is-picked) {
  opacity: 0.45;
  scale: 0.97;
  transition: opacity 0.15s, scale 0.15s;
}
.image-grid:has(.is-picked) .image-cell:not(.is-picked):hover {
  opacity: 0.8;
  scale: 1;
}

.row-pick {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}
.audio-row.is-picked { border-color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent); }
.audio-list:has(.is-picked) .audio-row:not(.is-picked) { opacity: 0.6; }

/* The line that says what the controls below will act on. In the rail it is a
   caption with its two actions tucked under it on one row, not a stack of
   underlined links: they are an aside to the sentence above them. */
.scope-line {
  display: flex;
  align-items: baseline;
  gap: 6px 12px;
  flex-wrap: wrap;
  width: 100%;
}
.scope-line .selection-count { margin: 0; flex: 1 1 100%; }
.scope-line .is-narrowed { color: var(--accent-deep); font-weight: 600; }
.scope-line .link-button {
  flex: 0 0 auto;
  margin-top: 0;
  width: auto;
  font-size: 12.5px;
}
.scope-line .link-button[hidden] { display: none; }

/* Dragging to reorder: order decides what a contact sheet looks like. */
.image-cell { cursor: grab; }
.image-cell.is-dragging { opacity: 0.4; cursor: grabbing; }
.image-cell.is-drop-target {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 2px var(--accent);
}

/* --- Zoom control -------------------------------------------------------- */

.zoom-control {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 6px 13px;
  border-radius: 999px;
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--muted);
  cursor: pointer;
}
.zoom-control:hover { border-color: var(--accent); color: var(--accent-deep); }
.zoom-control input[type="range"] { width: 110px; }
.zoom-control output {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
  min-width: 34px;
  text-align: right;
}

/* --- Tools rail, grouped ------------------------------------------------- */
/* Fifteen controls in a single column is a wall. Each section is a card of its
   own: a heading, its own ground, and real space between. A hairline was not
   enough to tell one idea from the next. */

.rail { padding: 18px 16px; }
.rail-body { gap: 26px; }

.rail-group { gap: 10px; padding: 0; }
.rail-group h3 { margin: 0 0 2px 2px; }

.rail .actionbar,
.rail .actionbar-secondary {
  gap: 16px;
  padding: 15px 14px 16px;
  background: var(--panel-2);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
}
.rail .actionbar + .actionbar,
.rail .actionbar + .actionbar-secondary,
.rail .actionbar-secondary + .actionbar-secondary { margin-top: 12px; }

/* The section heading sits above its own card, not squeezed against the
   control below it. */
.rail .actionbar[data-label] { position: relative; }
.rail .actionbar[data-label]::before {
  margin: -2px 0 6px;
  color: var(--text-2);
  font-size: 11.5px;
}

/* Labelled rows read as label-then-control rather than as a run of words. */
.rail .field {
  gap: 12px;
  font-size: 13px;
  color: var(--text-2);
}
.rail .field > span:first-child,
.rail .field:not(:has(select, input)) { color: var(--muted); }

/* A slider row needs vertical room too: pressed together, four of them read as
   one grey smear rather than four separate decisions. */
.rail .field:has(input[type="range"]) {
  gap: 14px;
  padding: 3px 0;
}
.rail .field input[type="range"] { min-width: 92px; }
.rail .field input[type="range"] + span { min-width: 38px; text-align: right; }

.rail .selection-count,
.rail .hint-inline {
  display: block;
  padding: 0 0 2px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.45;
}

.rail button { margin-top: 4px; }
.rail .actionbar > button + button { margin-top: -8px; }

/* Controls on a card need a lighter ground than the card, or they vanish. */
.rail .field select,
.rail .field input[type="number"],
.rail .field input[type="text"] { background: var(--panel); }

/* --- Header -------------------------------------------------------------- */

.topbar-end { display: flex; align-items: center; gap: 10px; margin-left: auto; }

/* Beside the name, where a back button lives: an arrow and the words, so each
   reads as a way out and not as a shortcut for something worse. */
.topbar-back {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: 6px;
}
.topbar-back .ghost {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px 7px 11px;
  font-size: 13.5px;
  color: var(--text-2);
}
/* Undo is the smaller retreat and is used far more often, so it leads and keeps
   the neutral hover; Start over is the one that clears the bench. */
#undo-last[hidden] { display: none; }
.start-over[hidden] { display: none; }
.start-over:hover { color: var(--danger); border-color: var(--danger); background: transparent; }

.panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}
.panel-head h2 { margin: 0; }

.link-button {
  border: none;
  background: none;
  padding: 0;
  font-size: 13px;
  color: var(--accent-deep);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.link-button:hover { color: var(--accent); }

/* --- Drop markers -------------------------------------------------------- */
/* A line in the gap says where the picture will land. Highlighting a whole
   cell instead reads as "replace that one", which is not what happens. */

.image-cell { position: relative; }
.image-cell.drop-before::before,
.image-cell.drop-after::after {
  content: "";
  position: absolute;
  top: 6px;
  bottom: 6px;
  width: 3px;
  border-radius: 999px;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.image-cell.drop-before::before { left: -9px; }
.image-cell.drop-after::after { right: -9px; }

/* Each bar announces what it governs, so the rail reads as a few ideas rather
   than a column of controls. */
.rail .actionbar[data-label]::before {
  content: attr(data-label);
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 2px;
}

/* A rule inside a card, where one kind of decision gives way to another: a
   look is a preset, brightness is a dial, and they should not read as one run
   of identical rows. */
.field-divider {
  display: block;
  height: 1px;
  margin: 4px 0 2px;
  background: var(--line);
}

/* --- Dragging a file over the window ------------------------------------- */
/* Anywhere over the app is a drop target, so the whole page answers rather
   than a strip near the top. */

body.is-file-dragging::after {
  content: "Drop to add these files";
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  font-size: 22px;
  font-weight: 600;
  color: var(--accent-deep);
  background: rgb(253 232 221 / 0.82);
  border: 3px dashed var(--accent);
  backdrop-filter: blur(2px);
  pointer-events: none;
}

/* The empty state gives the doorway real presence: there is nothing else on
   the page, so it may as well be the page. */
.bench:has(.dropzone:not([hidden])) .dropzone { padding: 56px 32px 48px; }

/* Pages reorder by dragging, with the same line-in-the-gap as photographs. */
.page-cell { cursor: grab; }
.page-cell.is-dragging { opacity: 0.4; cursor: grabbing; }
.page-cell.drop-before::before,
.page-cell.drop-after::after {
  content: "";
  position: absolute;
  top: 4px;
  bottom: 4px;
  width: 3px;
  border-radius: 999px;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  z-index: 2;
}
.page-cell.drop-before::before { left: -8px; }
.page-cell.drop-after::after { right: -8px; }

/* A PDF keeps a row because the grid below shows its pages, not the file: the
   row is where the document itself is named, removed, and joined to another.
   It needs room to read as a separate thing from the pages under it. */
.bench-head > .asset-list:not(:empty) {
  margin: 0; padding: 0; border: 0; flex: 1; min-width: 0;
}
.asset-list:not(:empty) {
  margin: 0 0 18px;
  padding-bottom: 16px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  border-bottom: 1px solid var(--line);
}
.asset { padding: 9px 10px 9px 15px; }
.asset-name { font-size: 14px; }

.asset-action { display: inline-flex; align-items: center; }
.asset-action button {
  background: var(--accent-soft);
  border-color: transparent;
  color: var(--accent-deep);
  font-weight: 600;
  padding: 9px 15px;
  border-radius: 999px;
}
.asset-action button:hover { background: var(--accent); color: #fff; }

/* --- Bench heading ------------------------------------------------------- */
/* The heading and the zoom share a line, so all three columns start level. */

.bench-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 12px;
  min-height: 38px;
}
/* The file chips move into the header row beside the zoom. Order puts the file
   first and the zoom last, and neither overlaps the other. */
.bench-head .bench-zoom { flex: none; margin-left: auto; }

/* Nothing to show until a grid opens: no empty band above the dropzone. */
.bench-head:not(:has(.bench-zoom:not([hidden]))):not(:has(.lede)) { display: none; }
.bench-head .lede:not(.is-compact) { margin: 0; }
.bench-zoom[hidden] { display: none; }
.bench-zoom .worktools { margin: 0; }

/* Centred while the bench is empty, since there is nothing else to align to. */
.bench-head:has(.lede:not(.is-compact)) {
  flex-direction: column;
  align-items: center;
  margin-bottom: 24px;
}

/* --- Footer -------------------------------------------------------------- */

/* Full-bleed: a centred column of links under a full-width app reads as though
   it is floating in the middle of nothing. */
.site-footer {
  width: 100%;
  margin: 32px 0 0;
  padding: 34px 0 30px;
  border-top: 1px solid var(--line);
  background: var(--panel);
  /* Left, like the columns above: a centred strap line under left-aligned
     columns reads as a third alignment rather than as a conclusion. */
  text-align: left;
  flex: 0 0 auto;
}
.site-footer > * { max-width: calc(var(--measure) - 48px); margin-inline: auto;
                   padding-inline: 24px; box-sizing: border-box; }

/* The footer link columns, shared with the landing pages. Left-aligned inside a
   centred footer: a column of links reads badly centred. */
.footer-nav {
  display: flex; flex-wrap: wrap; gap: 56px;
  margin: 0 auto 30px;
}
.footer-col h3 {
  margin: 0 0 11px; font-size: 11.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted);
}
.footer-col ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.footer-col a { font-size: 14px; color: var(--text-2); text-decoration: none; }
.footer-col a:hover { color: var(--accent-deep); text-decoration: underline; }
.footer-col .soon { font-size: 14px; color: var(--muted); opacity: .6; }

@media (max-width: 640px) {
  .footer-nav { gap: 32px; }
  .footer-col { flex: 1 1 130px; }
}
.footer-line {
  margin: 0 auto 8px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text-2);
  text-wrap: pretty;
}
.footer-line strong { color: var(--text); font-weight: 600; }
.footer-meta { font-size: 12.5px; color: var(--muted); }
.site-footer a { color: var(--accent-deep); text-decoration: underline; text-underline-offset: 3px; }
.site-footer a:hover { color: var(--accent); }

/* In a single column the gaps run vertically, so the marker does too. */
.image-cell.is-stacked.drop-before::before,
.image-cell.is-stacked.drop-after::after {
  top: auto;
  bottom: auto;
  left: 6px;
  right: 6px;
  width: auto;
  height: 3px;
}
.image-cell.is-stacked.drop-before::before { top: -8px; }
.image-cell.is-stacked.drop-after::after { bottom: -8px; }

/* On a phone the header items cannot all sit on one line, so the bar is
   allowed to wrap and grow instead of overflowing sideways. */
@media (max-width: 720px) {
  .topbar {
    height: auto;
    flex-wrap: wrap;
    gap: 10px 12px;
    padding: 12px 16px;
  }
  .brand h1 { font-size: 18px; }
  .start-over { margin-left: 0; }
  main { padding: 14px 16px 32px; }
  .site-footer { padding-inline: 16px; }
}


/* --- SEO body ------------------------------------------------------------ */

/* The prose under the workbench. It sits in the bench column so a tool page
   reads as one page — bench first, then the reading matter — rather than as a
   different template that happens to share a header. */
/* --- Secondary footer ---------------------------------------------------- */

/* Everything that is read rather than used sits here: one banded block above
   the real footer, so it reads as the bottom of the page instead of loose prose
   floating under the bench. */
.subfooter {
  width: 100%;
  margin-top: 40px;
  padding: 44px 0 48px;
  background: var(--panel-2);
  border-top: 1px solid var(--line);
}
.subfooter-inner {
  max-width: 1180px; margin: 0 auto; padding: 0 24px;
  display: flex; flex-direction: column; gap: 38px;
}
.sub-cols {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 38px;
}
@media (max-width: 860px) {
  .subfooter { padding: 32px 0 36px; }
  .subfooter-inner { gap: 30px; padding: 0 18px; }
}

.subfooter h2 { margin: 0 0 12px; font-size: 21px; letter-spacing: -0.012em; color: var(--text); }
.section-sub { margin: 0 0 20px; color: var(--text-2); font-size: 14.5px; }
.subfooter .rationale p, .subfooter .how-to p { margin: 0; font-size: 15.5px; line-height: 1.68; color: var(--text-2); }

.crumbs { font-size: 13px; color: var(--muted); margin: 0 0 -22px; }
.crumbs a { color: var(--text-2); text-decoration: none; }
.crumbs a:hover { color: var(--accent-deep); text-decoration: underline; }
.crumbs span[aria-hidden] { margin: 0 6px; opacity: .5; }

.upsell {
  display: flex; align-items: center; gap: 24px; flex-wrap: wrap;
  padding: 22px 24px; border-radius: var(--radius);
  background: var(--accent-soft); border: 1px solid #f6d3c0;
}
.upsell-body { flex: 1 1 340px; }
.upsell h2 { margin: 0 0 7px; font-size: 18px; color: var(--accent-deep); }
.upsell p { margin: 0; font-size: 14.5px; line-height: 1.6; color: #7a3a18; }

.cta {
  display: inline-block; padding: 11px 20px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--panel-2); color: var(--text);
  font-size: 14px; font-weight: 600; text-decoration: none; flex: none;
}
.cta-solid { background: var(--accent); border-color: var(--accent); color: #fff; }
.cta-solid:hover { background: var(--accent-deep); border-color: var(--accent-deep); color: #fff; }

.steps { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 10px; }
.steps li { font-size: 15.5px; line-height: 1.55; color: var(--text-2); }
.steps li::marker { color: var(--accent); font-weight: 700; }

.why-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 14px; }
.why-card { padding: 19px; border-radius: var(--radius-sm); background: var(--panel); border: 1px solid var(--line-soft); }
.why-card h3 { margin: 0 0 7px; font-size: 15px; color: var(--text); }
.why-card p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--text-2); }

.faq-item { border-bottom: 1px solid var(--line-soft); padding: 13px 0; }
.faq-item summary {
  cursor: pointer; font-weight: 600; font-size: 15.5px; color: var(--text);
  list-style: none; display: flex; justify-content: space-between; gap: 16px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: "+"; color: var(--accent); font-weight: 700; }
.faq-item[open] summary::after { content: "\2212"; }
.faq-item p { margin: 10px 0 2px; font-size: 14.5px; line-height: 1.65; color: var(--text-2); }

.sibling-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; }
.sibling-list a {
  display: inline-block; padding: 8px 14px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--panel);
  font-size: 14px; color: var(--text-2); text-decoration: none;
}
.sibling-list a:hover { border-color: var(--accent); color: var(--accent-deep); }
.all-link { font-weight: 600; }

.nav-sub a.is-current { background: var(--accent-soft); color: var(--accent-deep); font-weight: 600; }
.dropzone-scope { color: var(--muted); font-size: 13px; margin: 0; }
.brand-link { display: flex; align-items: center; gap: 10px; text-decoration: none; color: inherit; }
.brand-link h1 { margin: 0; }

@media (max-width: 860px) {
  .seo-body { padding: 8px 18px 32px; gap: 40px; }
}

/* The control a tool page came for. A ring rather than a colour change, so the
   button still reads as the same button it is on every other page. */
.is-focus-tool {
  box-shadow: 0 0 0 2px var(--accent), 0 0 0 5px var(--accent-soft);
  border-color: var(--accent) !important;
}


/* --- The promise, in the sidebar ---------------------------------------- */

.nav-why {
  margin: 16px 4px 2px; padding-top: 15px; border-top: 1px solid var(--line-soft);
}
.nav-why h3 {
  margin: 0 0 10px; font-size: 11.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted);
}
.nav-why dl { margin: 0; display: flex; flex-direction: column; gap: 11px; }
.nav-why dt { font-size: 12.5px; font-weight: 600; color: var(--text); }
.nav-why dd { margin: 2px 0 0; font-size: 12px; line-height: 1.5; color: var(--text-2); }

/* --- Rubber-band selection ---------------------------------------------- */

.marquee {
  position: fixed; z-index: 60; pointer-events: none;
  border: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-radius: 3px;
}
/* Shown while the band is open; the real selection lands on release. */
.page-cell.is-marqueed, .image-cell.is-marqueed {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
/* A drag that starts on the background should sweep, not select text. */
.page-grid, .image-grid { user-select: none; }

/* --- Page heading (SEO pages) -------------------------------------------- */

/* The h1 belongs to the job the page does, not to the site name, so the brand
   in the header is plain text on these pages and this is the real heading. */
.brand-name { font-size: 19px; font-weight: 600; letter-spacing: -0.015em; color: var(--text); }
.page-head h1 {
  margin: 0 0 10px; font-size: 30px; line-height: 1.16;
  letter-spacing: -0.022em; color: var(--text); text-wrap: balance;
}
.page-head p { margin: 0; font-size: 16px; line-height: 1.6; color: var(--text-2); max-width: 62ch; }

/* --- Breadcrumbs above the bench ----------------------------------------- */

/* The way back, kept in sight. A trail at the foot of the page is only useful
   to someone who has already scrolled past everything they wanted to leave. */
.bench-crumbs {
  display: flex; align-items: center; flex-wrap: wrap; gap: 2px;
  margin: 0 0 12px; font-size: 13px; color: var(--muted);
}
.bench-crumbs a {
  padding: 4px 8px; border-radius: 7px;
  color: var(--text-2); text-decoration: none; font-weight: 500;
}
.bench-crumbs a:hover { background: var(--panel); color: var(--accent-deep); }
.bench-crumbs [aria-current] { padding: 4px 8px; color: var(--text); font-weight: 600; }
.bench-crumbs [aria-hidden] { opacity: .45; }

/* --- Right-click menu ---------------------------------------------------- */

.ctx-menu {
  position: fixed; z-index: 80; min-width: 194px;
  padding: 6px; border-radius: 13px;
  background: var(--panel); border: 1px solid var(--line);
  box-shadow: 0 12px 34px rgba(35, 33, 29, .16);
  display: flex; flex-direction: column; gap: 1px;
}
.ctx-item {
  display: block; width: 100%; text-align: left;
  padding: 8px 11px; border: 0; border-radius: 8px;
  background: none; font: inherit; font-size: 13.5px; color: var(--text);
  cursor: pointer;
}
.ctx-item:hover:not(:disabled) { background: var(--accent-soft); color: var(--accent-deep); }
.ctx-item:disabled { color: var(--muted); opacity: .5; cursor: default; }
.ctx-item.is-danger:hover:not(:disabled) { background: #fde8e2; color: var(--danger); }
.ctx-sep { margin: 4px 6px; border: 0; border-top: 1px solid var(--line-soft); }

/* --- Ask box (agent, not yet wired) -------------------------------------- */

.ask {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 20px; padding: 18px;
}
.ask-head { display: flex; align-items: center; gap: 9px; margin-bottom: 9px; }
.ask-head h2 { margin: 0; font-size: 15px; font-weight: 600; color: var(--text); }
.ask-soon {
  font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--agent-deep); background: var(--agent-soft);
  padding: 3px 7px; border-radius: 999px;
}
.ask-example {
  /* No clamp: a truncated example reads as a typo in the example itself. */
  margin: 0 0 11px; padding: 9px 11px; border-radius: 9px; overflow: visible;
  background: var(--panel-2); border: 1px solid var(--line-soft);
  font-size: 12.5px; line-height: 1.45; color: var(--text-2); font-style: italic;
}
.ask-input {
  width: 100%; padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--panel-2);
  font: inherit; font-size: 13.5px; color: var(--text);
}
.ask-input:disabled { cursor: not-allowed; opacity: .75; }

.ctx-item { display: flex; align-items: center; gap: 9px; }
.ctx-icon { flex: none; color: var(--muted); }
.ctx-item:hover:not(:disabled) .ctx-icon { color: inherit; }
.ctx-item.is-danger .ctx-icon { color: var(--danger); opacity: .8; }


/* With breadcrumbs above the bench, every column beside it drops by the same
   amount so they all start level with the canvas rather than with the trail.
   The rail belongs in this list too: without it, Tools sat a row higher than
   Browse and the panel on the right. */
body[data-scope] .sidenav,
body[data-scope] .side,
body[data-scope] .rail { margin-top: var(--crumbs-drop); }
@media (max-width: 1200px) {
  body[data-scope] .sidenav,
  body[data-scope] .side,
  body[data-scope] .rail { margin-top: 0; }
}

/* Rail buttons with the menu's icons. */
.rail .ghost.has-icon, .rail .danger.has-icon {
  display: flex; align-items: center; gap: 9px; text-align: left;
}
.rail .has-icon .ctx-icon { flex: none; opacity: .8; }

/* --- Notices ------------------------------------------------------------- */

.toasts {
  position: fixed; z-index: 90; left: 50%; bottom: 26px; transform: translateX(-50%);
  display: flex; flex-direction: column; gap: 8px; align-items: center;
  pointer-events: none; width: min(520px, calc(100vw - 32px));
}
.toast {
  padding: 12px 17px; border-radius: 12px;
  background: var(--text); color: var(--panel);
  font-size: 13.5px; line-height: 1.45; text-align: center;
  box-shadow: 0 10px 30px rgba(35, 33, 29, .22);
  opacity: 1; transition: opacity .25s ease, transform .25s ease;
}
.toast-warn { background: var(--accent-deep); }
.toast.is-leaving { opacity: 0; transform: translateY(6px); }


/* The bench keeps the full height of its column once files are open, so the
   empty space under the last row is still the bench — and still right-clickable. */
body:has(.page-cell) .bench,
body:has(.image-cell) .bench { min-height: calc(100vh - 130px); }


/* --- Scoped dropzone ----------------------------------------------------- */

/* On a vertical the drop area names the one kind of file it takes, under the
   mark for that kind, so the page says what it is before anything is loaded. */
.dropzone-mark { display: inline-flex; opacity: .5; }
.dropzone-mark.kind-pdf { color: var(--kind-pdf); }
.dropzone-mark.kind-image { color: var(--kind-image); }
.dropzone-mark.kind-video { color: var(--kind-video); }
.dropzone-mark.kind-audio { color: var(--kind-audio); }
.dropzone-mark.kind-convert { color: var(--kind-convert); }
.dropzone-mark.kind-inspect { color: var(--kind-inspect); }

.dropzone-lead {
  display: block; margin-top: 6px;
  font-size: 15px; font-weight: 400; color: var(--text-2);
}
.dropzone:has(.dropzone-mark) .dropzone-main {
  font-size: 28px; letter-spacing: -0.02em; line-height: 1.2;
}

/* ---------------------------------------------------------------- documents
   The information pages (about, privacy, terms, contact). One column of
   prose, no workbench: there is no file to work on here, so the bench
   furniture and the tool rail are absent and the text gets the whole width. */
.doc-main {
  display: block;
  max-width: 44rem;
  margin: 0 auto;
  padding: 2.25rem 1rem 4rem;
}
.doc .crumbs { margin-bottom: 1.25rem; }
.doc h1 {
  font-size: clamp(1.75rem, 1.2rem + 2vw, 2.4rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0 0 0.75rem;
}
.doc-lede {
  font-size: 1.1rem;
  line-height: 1.6;
  color: var(--text-2);
  margin: 0 0 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--line);
}
.doc h2 {
  font-size: 1.16rem;
  letter-spacing: -0.01em;
  margin: 2.25rem 0 0.6rem;
}
.doc p, .doc li { line-height: 1.68; color: var(--text-2); }
.doc p { margin: 0 0 0.9rem; }
.doc strong { color: var(--text); font-weight: 600; }
.doc ul { margin: 0 0 1rem; padding-left: 1.15rem; }
.doc li { margin-bottom: 0.5rem; }
.doc a { color: var(--accent-deep); }
.doc code {
  font-size: 0.9em;
  background: var(--panel-2);
  border: 1px solid var(--line-soft);
  border-radius: 4px;
  padding: 0.1em 0.35em;
}
.doc-updated {
  margin-top: 2.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--line);
  font-size: 0.875rem;
  color: var(--muted);
}

/* The information pages, along the bottom of every page. Kept visually
   quieter than the tool columns above them: they are the small print. */
.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.25rem;
  margin-top: 0.85rem;
}
.site-footer .footer-legal { justify-content: flex-start; }
.footer-legal a {
  font-size: 0.875rem;
  color: var(--muted);
  text-decoration: none;
}
.footer-legal a:hover { color: var(--text); text-decoration: underline; }
