: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 · bench · side. The tools are no longer a column: they open as a panel
     over the bench, so the canvas keeps its width whether they are showing or
     not and the work never has to shuffle sideways to make room for them. 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 minmax(0, 1fr) 300px;
  gap: 18px;
  padding: 18px 24px 28px;
  align-items: start;
  /* Full width on purpose: Browse belongs against one edge of the window and
     the side panel against the other, with the canvas taking whatever is
     between them. Centring this on a measure boxed the whole bench into a
     band and left both columns floating. */
  /* 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;
}

/* 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 { grid-template-columns: 208px minmax(0, 1fr); }
  .side { grid-column: 1 / -1; flex-direction: row; }
  .side > * { flex: 1; }
}
@media (max-width: 860px) {
  main { 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 ---------------------------------------------------------- */

/* The launcher. It floats over the bottom of the bench, above the canvas and
   clear of the page, so the tools are one click away from wherever the eye
   already is - on the file - instead of a column away. */
.rail-fab {
  position: fixed;
  /* Against the right-hand panel's inner edge, not the middle of the window:
     centred, it and the sheet above it sat squarely over the thumbnails they
     are there to let you judge. */
  right: 336px;
  bottom: 22px;
  z-index: 60;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 12px 20px;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 10px 28px rgba(35, 33, 29, 0.28), 0 2px 6px rgba(35, 33, 29, 0.16);
  transition: background 0.15s, box-shadow 0.15s, transform 0.15s;
}
.rail-fab:hover { background: var(--accent-deep); box-shadow: 0 14px 34px rgba(35, 33, 29, 0.32); }
.rail-fab:active { transform: translateY(1px); }
.rail-fab[hidden] { display: none; }
/* While the panel is up the button is its handle, and says so. */
.rail-fab[aria-expanded="true"] { background: var(--accent-deep); }
.rail-fab-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.24);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.rail-fab-count[hidden] { display: none; }

/* The panel. Fixed above the button, capped so it can never grow past the
   window, and scrolling inside itself: the bench underneath keeps its
   scroll position, so closing the panel puts you back exactly where you were. */
.rail {
  position: fixed;
  right: 336px;
  bottom: 78px;
  z-index: 61;
  width: min(400px, calc(100vw - 32px));
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 16px;
  max-height: min(70vh, calc(100vh - 150px));
  overflow-y: auto;
  overscroll-behavior: contain;
  box-shadow: 0 18px 50px rgba(35, 33, 29, 0.22), 0 4px 12px rgba(35, 33, 29, 0.1);
}
.rail[hidden] { display: none; }
.rail-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 0 0 14px;
  /* The heading stays put while the controls under it scroll, so on a long
     panel you can always see which tools you are looking at. */
  position: sticky;
  top: -16px;
  padding: 16px 0 10px;
  margin-top: -16px;
  background: var(--panel);
  z-index: 1;
}
.rail-title {
  font-size: 17px;
  font-weight: 600;
  margin: 0;
}
.rail-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex: none;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel-2);
  color: var(--text-2);
  cursor: pointer;
}
.rail-close:hover { background: var(--line-soft); color: var(--text); }

/* Below the fold of a phone the panel is a sheet: full width, off the bottom
   edge, with the launcher tucked to the right so it does not sit over a
   thumbnail in the middle of the grid. */
/* The right-hand panel drops below the bench here, so there is nothing left to
   clear: both come back to the window's own edge. */
@media (max-width: 1200px) {
  .rail-fab, .rail { right: 24px; }
}

@media (max-width: 620px) {
  .rail-fab { right: 16px; }
  .rail {
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    border-radius: 20px 20px 0 0;
    max-height: 72vh;
    /* The consent badge parks itself in the bottom-left corner. The last
       control in the sheet should not end up underneath it. */
    padding-bottom: 72px;
  }
}
.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; }
/* Every control in the panel runs the full width - except the chrome,
   which is a 30px circle and would otherwise stretch across the head. */
.rail button:not(.rail-close) { 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);
  text-align: center;
  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. The block of columns is centred under the footer
   like everything else in it; the links inside each column stay left-aligned,
   because a column of links reads badly centred. */
.footer-nav {
  display: flex; flex-wrap: wrap; gap: 56px;
  margin: 0 auto 30px; text-align: left;
  justify-content: center;
}
.footer-col h3 {
  margin: 0 0 11px; font-size: 11.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted);
  display: flex; align-items: center; gap: 7px;
}
/* The category icons, in the same colours they carry in the nav and the rail,
   so a column is recognisable before the heading is read. */
.footer-icon { display: inline-flex; flex: none; }
.footer-icon.kind-pdf { color: var(--kind-pdf); }
.footer-icon.kind-image { color: var(--kind-image); }
.footer-icon.kind-video { color: var(--kind-video); }
.footer-icon.kind-audio { color: var(--kind-audio); }
.footer-icon.kind-convert { color: var(--kind-convert); }
.footer-icon.kind-inspect { color: var(--kind-inspect); }
.footer-icon.kind-ebook { color: #b85cd6; }
/* "Coming next" is not available yet, and its icon says so with the label. */
.footer-col h3 .footer-icon.kind-ebook { opacity: .55; }
.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 tools panel is not in this list: it floats over the bench rather than
   standing beside it, so it has no top edge to line up with. */
body[data-scope] .sidenav,
body[data-scope] .side { margin-top: var(--crumbs-drop); }
@media (max-width: 1200px) {
  body[data-scope] .sidenav,
  body[data-scope] .side { 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: center; }
.footer-legal a {
  font-size: 0.875rem;
  color: var(--muted);
  text-decoration: none;
}
.footer-legal a:hover { color: var(--text); text-decoration: underline; }

/* A tool page narrows the rail to the job it is named after. This is the way
   back to everything else, so a control that is merely hidden does not read as
   a missing feature. */
/* `display: flex` on these beats the [hidden] attribute's own display:none,
   so a scoped tool page could hide a bar and still see it on screen. State it
   once, with enough weight to win, rather than per rule. */
.rail [hidden],
.rail .actionbar[hidden],
.rail .actionbar-secondary[hidden],
.rail .field[hidden] { display: none !important; }

.rail-widen {
  margin: 4px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
}
.rail-widen a { color: var(--accent-deep); }

/* Tools driven from the canvas - trimming, merging, grabbing a frame - have no
   control in the rail. Rather than leave it blank, say where the tool is. */
.rail-hint {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--text-2);
}
.rail-hint.is-unbuilt { color: var(--muted); }

/* The cookie table on the cookie policy page. */
.doc-table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 1.25rem;
  font-size: 0.9rem;
}
.doc-table th,
.doc-table td {
  text-align: left;
  padding: 0.55rem 0.7rem;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
  line-height: 1.5;
}
.doc-table th {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom-color: var(--line);
}
.doc-table td { color: var(--text-2); }
@media (max-width: 560px) {
  .doc-table, .doc-table tbody, .doc-table tr, .doc-table td { display: block; }
  .doc-table thead { display: none; }
  .doc-table tr { padding: 0.6rem 0; border-bottom: 1px solid var(--line-soft); }
  .doc-table td { border: 0; padding: 0.1rem 0; }
  .doc-table td:first-child { font-weight: 600; color: var(--text); }
}

/* The width slider, under the number box it mirrors. It is a second way to set
   the same value, so it carries no label of its own. */
.resize-slider-field { padding-top: 2px; }
.resize-slider-field input[type="range"] { width: 100%; }

/* A checkbox in the rail sits next to its label rather than under it, unlike
   the sliders and selects the .field rule is written for. */
.rail .field.checkbox-field {
  flex-direction: row;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}
.rail .field.checkbox-field input[type="checkbox"] {
  flex: none;
  width: auto;
  margin: 0;
  accent-color: var(--accent);
}

/* The footer columns are <details> so a phone can fold them. On a wide screen
   they are always open, and the summary is nothing but the heading it wraps. */
.footer-col > summary { list-style: none; display: block; }
.footer-col > summary::-webkit-details-marker { display: none; }
.footer-col > summary h3 { margin: 0 0 12px; }

/* --- The phone ----------------------------------------------------------- */
/* A phone has one column and no hover, so the desktop furniture cannot simply
   be narrowed: three columns of panels stacked end to end put the tool itself
   four screens down. Below 860px everything that is navigation rather than
   work collapses behind a control the reader opens on purpose - the categories
   into a menu off the header, Browse and the footer index into disclosures -
   so the first screen is the bench and nothing else.
   All of it is <details>/<summary> and a checkbox-free <button> toggled by the
   one listener in main.js: the menu must work on a page whose JavaScript has
   not arrived yet, because the tool underneath it does. */

/* The hamburger only exists on a narrow screen; on a wide one the same
   categories are already spelled out along the header. */
.nav-toggle-btn { display: none; }
/* The sheet is a phone control; a resize must not leave it on screen. */
.mobile-menu { display: none; }
/* Browse folds only on a phone. On a wide screen it is a column, so its
   disclosure is not just hidden by the script - it has no meaning here. */
.sidenav-toggle { display: none; }

@media (max-width: 860px) {
  /* --- Header: brand, then one button ------------------------------------ */
  .topbar {
    flex-wrap: nowrap;
    gap: 10px;
    padding: 10px 16px;
    /* The way back to the top of the site, always reachable with a thumb. */
    position: sticky; top: 0; z-index: 40;
  }
  .brand { flex: 1; min-width: 0; }
  .brand h1, .brand-name { font-size: 16.5px; }
  .brand-link { min-width: 0; }

  /* The category strip becomes the menu's contents, not a row that scrolls
     four of its six items off the edge with nothing to say so. */
  .topbar > .topnav { display: none; }

  .nav-toggle-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    flex: none; height: 40px; padding: 0 13px;
    border: 1px solid var(--line); border-radius: 12px;
    background: var(--panel-2); color: var(--text);
    font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .nav-toggle-btn[aria-expanded="true"] {
    background: var(--accent-soft); border-color: #f6d3c0; color: var(--accent-deep);
  }
  /* Two glyphs in one button: the bars turn into a cross when it is open. */
  .nav-toggle-btn .icon-close { display: none; }
  .nav-toggle-btn[aria-expanded="true"] .icon-open { display: none; }
  .nav-toggle-btn[aria-expanded="true"] .icon-close { display: inline-flex; }

  /* The menu itself: a sheet under the header rather than a full-screen
     takeover, so the page behind it stays visible and the reader keeps their
     place. */
  .mobile-menu.is-open {
    position: fixed; left: 0; right: 0; top: var(--topbar-h, 60px); bottom: 0;
    z-index: 39;
    display: block;
    padding: 10px 16px 28px;
    background: var(--bg);
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  body.menu-open { overflow: hidden; }

  .mobile-menu .topnav {
    position: static; transform: none; max-width: none; margin: 0;
    display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px;
    overflow: visible;
  }
  .mobile-menu .topnav-link {
    flex-direction: row; justify-content: flex-start; gap: 11px;
    padding: 14px 14px; border-radius: 13px;
    border: 1px solid var(--line); background: var(--panel);
    font-size: 14.5px; font-weight: 600; color: var(--text);
    min-height: 52px;
  }
  .mobile-menu .topnav-link.is-current {
    background: var(--accent-soft); border-color: #f6d3c0; color: var(--accent-deep);
  }
  .menu-section-title {
    margin: 20px 2px 9px;
    font-size: 11.5px; font-weight: 700; letter-spacing: .08em;
    text-transform: uppercase; color: var(--muted);
  }
  .menu-links { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
  .menu-links a {
    display: block; padding: 12px 12px; border-radius: 11px;
    font-size: 14.5px; color: var(--text-2); text-decoration: none;
  }
  .menu-links a:active { background: var(--panel-2); color: var(--text); }

  /* --- The bench comes first --------------------------------------------- */
  /* Source order puts Browse before the bench, because on a desktop it is the
     left column. On a phone it is a menu, so the work moves to the top and the
     panels that report on it follow underneath in the order they are used. */
  main {
    display: flex; flex-direction: column;
    /* The desktop grid sets align-items:start, which in a column makes every
       panel shrink to its content instead of spanning the screen. */
    align-items: stretch;
    gap: 14px;
    padding: 12px 16px 24px;
  }
  main > .bench { order: 1; }
  main > .side { order: 2; }
  main > .sidenav { order: 3; }

  /* Browse: the full map, folded away. The header menu is the fast path; this
     stays for anyone who has scrolled to the bottom of the page. */
  .sidenav {
    position: static; max-height: none; overflow: visible;
    padding: 0; border: 0; background: none; border-radius: var(--radius);
  }
  .sidenav-title { display: none; }
  .sidenav .nav-list {
    display: none;
    flex-direction: column; padding: 4px 10px 12px; gap: 2px;
  }
  .sidenav.is-open .nav-list { display: flex; }
  .sidenav .nav-item { flex: none; }
  .sidenav .nav-link { padding: 12px 10px; font-size: 15px; }
  /* The promise is worth reading, but not above the tool it describes. */
  .nav-why { display: none; }
  .sidenav.is-open .nav-why { display: block; margin: 0 14px 14px; }

  .sidenav-toggle {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    /* The script un-hides it; until then the list underneath is the nav. */
    width: 100%; padding: 14px 14px;
    border: 1px solid var(--line); border-radius: var(--radius);
    background: var(--panel); color: var(--text);
    font: inherit; font-size: 14.5px; font-weight: 600; text-align: left;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
  }
  .sidenav-toggle .disclosure { transition: transform .15s ease; color: var(--muted); }
  .sidenav-toggle[aria-expanded="true"] .disclosure { transform: rotate(90deg); }

  /* --- The tools panel and the side panels -------------------------------- */
  /* The panel stays fixed - it is a bottom sheet here, not a block in the page
     - and only loses the padding it does not have room for. Making it static
     put it below everything else, off the bottom of a phone screen. */
  .rail { padding: 16px; }
  .side { position: static; flex-direction: column; gap: 14px; }
  .side > * { flex: none; }
  .stack, .tools-panel { padding: 18px; }

  /* "Type what you need" is not built yet, and a disabled box is not what a
     phone screen should spend its height on. */
  .ask { display: none; }

  /* --- The bench ---------------------------------------------------------- */
  /* The dropzone was sized to stand level with a desktop sidebar. Beside
     nothing, that is most of a phone screen of empty dashes. */
  .dropzone { min-height: 0; padding: 30px 18px; gap: 14px; }
  .dropzone-icons { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .crumbs { margin-bottom: 10px; font-size: 12.5px; }
  .bench-crumbs { margin-bottom: 10px; }

  /* --- The reading matter under the bench --------------------------------- */
  .lede { margin: 6px auto 18px; }
  .lede-title { font-size: 28px; }
  .lede-sub { font-size: 16px; margin-top: 12px; }
  .seo-body { padding-inline: 0; }
  .why-grid { grid-template-columns: 1fr; }
  .sub-cols { grid-template-columns: 1fr; }

  /* --- The footer index --------------------------------------------------- */
  /* Six categories times seven links is a wall of forty underlined phrases at
     the bottom of every page. Folded, it is six lines. */
  .footer-nav { display: block; }
  .footer-col { padding: 0; border-bottom: 1px solid var(--line-soft); }
  .footer-col summary {
    display: flex; align-items: center;
    padding: 4px 2px; cursor: pointer;
    list-style: none; -webkit-tap-highlight-color: transparent;
  }
  .footer-col summary::-webkit-details-marker { display: none; }
  .footer-col summary h3 { margin: 0; padding: 10px 0; }
  .footer-col summary::after {
    content: "+"; margin-left: auto;
    font-size: 19px; font-weight: 400; color: var(--muted); line-height: 1;
  }
  .footer-col[open] summary::after { content: "\2212"; }
  .footer-col ul { padding: 0 2px 16px; gap: 2px; }
  .footer-col li a, .footer-col .soon { display: block; padding: 9px 0; font-size: 14.5px; }

  .footer-legal { gap: 6px 18px; }
  .footer-legal a { padding: 6px 0; }
}

/* Very narrow: one category per row, because two 14px labels in 160px wrap
   into two lines each and the grid stops reading as a list of six things. */
@media (max-width: 400px) {
  .mobile-menu .topnav { grid-template-columns: 1fr; }
  .mobile-menu .topnav-link { min-height: 48px; padding: 12px 14px; }

  /* The name is three words and the button beside it is fixed, so on the
     narrowest phones the name wraps and doubles the header. One line, cut
     with an ellipsis: the logo already says which site this is. */
  .topbar { gap: 8px; padding-inline: 12px; }
  .brand h1, .brand-name {
    font-size: 15.5px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .brand { gap: 9px; }
  .nav-toggle-btn { padding: 0 11px; }
}

/* A phone is touched, not pointed at. Hover styling that sticks after a tap
   makes a link look selected when it is only the last thing pressed. */
@media (hover: none) {
  a.cat-card:hover { transform: none; box-shadow: none; }
}
