/* ==========================================================================
   studio.css — EditingTools.pro
   PDF Studio and (from Phase 7) Image Studio. Loaded only by the two studio
   shells, never by a landing page or a calculator.

   Same rule as everywhere else: no raw colour values, everything from tokens.
   ========================================================================== */

/* ==========================================================================
   1. FRAME
   ========================================================================== */
/* NAMED AREAS, NOT AUTO-PLACEMENT.

   Three children and, in the middle band, two columns — so auto-placement has
   a spare slot to put something in, and the slot it chooses is row 2 column 1,
   directly under a STICKY rail. That is the whole mechanism of the overlap bug
   this file has now had twice.

   Grid template areas remove the question. Every child is placed by name at
   every breakpoint, the empty cell is empty because it is named `.`, and there
   is no arrangement the browser can invent. It also makes the three layouts
   legible as three pictures rather than as a set of rules whose interaction
   you have to hold in your head. */
.studio {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: 1fr;
  grid-template-areas:
    "rail"
    "stage"
    "side";
  align-items: start;
  padding-bottom: var(--s-7);
}
/* Two columns. The controls sit under the STAGE, never under the rail —
   the rail is sticky and would slide over anything beneath it. */
@media (min-width: 900px) {
  .studio {
    grid-template-columns: 220px minmax(0, 1fr);
    grid-template-areas:
      "rail stage"
      ".    side";
  }
}
/* Three columns: the controls get their own, and can be sticky again. */
@media (min-width: 1280px) {
  .studio {
    grid-template-columns: 220px minmax(0, 1fr) 320px;
    grid-template-areas: "rail stage side";
    gap: var(--s-5);
  }
}

.studio__rail  { grid-area: rail;  min-width: 0; }
.studio__stage { grid-area: stage; min-width: 0; }
.studio__side  { grid-area: side;  min-width: 0; display: grid; gap: var(--s-4); }

/* Sticky is a property of having a column to yourself. The rail always has
   one from 900 up; the controls only get one at 1280. Written as two separate
   rules rather than one shared rule plus an undo, because the undo was where
   the bug lived: `.studio__rail, .studio__side { position: sticky }` at 900,
   then a max-width query putting the side back. Anything that broke the
   second query — a stale copy of this file, a future edit to the 1280
   breakpoint that forgot its twin — left a sticky element with nowhere safe
   to be. Now nothing has to be undone. */
@media (min-width: 900px) {
  .studio__rail {
    position: sticky;
    top: calc(var(--header-h) + var(--s-3));
    max-height: calc(100svh - var(--header-h) - var(--s-5));
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}
@media (min-width: 1280px) {
  .studio__side {
    position: sticky;
    top: calc(var(--header-h) + var(--s-3));
    max-height: calc(100svh - var(--header-h) - var(--s-5));
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}
/* THE OVERLAP BUG, TWICE, AND WHY THE FIX IS NOW A LAYOUT AND NOT AN OVERRIDE.

   FIRST TIME. Three children, and between 900 and 1279 only two columns.
   Auto-placement put the rail at row 1 column 1, the stage at row 1 column 2,
   and the controls at ROW 2 COLUMN 1 — directly beneath the rail. The rail is
   sticky, and a sticky element moves without giving up the space it came
   from, so the moment you scrolled down to reach the button the rail slid
   down over the controls. Every label in the rail was painted across the
   panel's text and across the Convert button. Reported as "it overlays the
   buttons on all pages", and it was exactly that.

   That was fixed with a `@media (min-width: 900px) and (max-width: 1279px)`
   block that un-stickied the side panel and forced it to `grid-column: 2`.
   Correct, and fragile: it was an UNDO of a rule set thirty lines above it,
   in a query bounded on both sides, that had to stay in step with the 1280
   breakpoint by hand.

   SECOND TIME it was reported it was not a CSS bug at all — the deployed
   stylesheet had the fix and the visitor's browser was still running the
   previous copy, because the service worker served stylesheets
   stale-while-revalidate. See sw.js. But a layout that renders catastrophically
   when it meets a slightly older stylesheet is a layout with too little slack
   in it, so the arrangement above was rebuilt out of named areas: every child
   is placed explicitly at every breakpoint, sticky is granted only to a child
   that owns its column, and nothing is set and then unset.

   tools/test/sticky.mjs sweeps every width from 360 to 1600 in steps of 20,
   scrolls each one, and measures actual pixel overlap between the sticky rail
   and everything else. The original sweep tested 360/480/768/1024/1440 and
   never scrolled, which is the whole reason this shipped the first time. */


/* ==========================================================================
   2. MODE RAIL
   ========================================================================== */
.rail { display: grid; gap: 2px; }
.rail__head {
  font-family: var(--font-mono); font-size: var(--fs-2xs);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
  color: var(--text-faint);
  padding: var(--s-2) var(--s-2) var(--s-3);
  border-bottom: 1px solid var(--hairline);
  margin-bottom: var(--s-2);
}
.rail__item {
  display: flex; align-items: center; gap: var(--s-3);
  min-height: 44px; padding: var(--s-2) var(--s-3);
  border: 1px solid transparent;
  border-radius: var(--r-input);
  font-size: var(--fs-xs); font-weight: 500;
  color: var(--text-muted); text-align: left; text-decoration: none;
  width: 100%;
  transition: background var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out);
}
.rail__item svg { inline-size: 18px; block-size: 18px; flex: none; color: var(--primary-text); }
.rail__item:hover { background: var(--primary-soft); color: var(--text); }
.rail__item[aria-current="true"] {
  background: var(--primary-soft);
  border-color: var(--primary);
  color: var(--text-strong);
  font-weight: 600;
}
/* Horizontal scroller on phones */
@media (max-width: 899px) {
  .rail { grid-auto-flow: column; grid-auto-columns: max-content; overflow-x: auto; gap: var(--s-2); padding-bottom: var(--s-2); }
  .rail__head { display: none; }
  .rail__item { border-color: var(--hairline); border-radius: var(--r-pill); white-space: nowrap; }
}

/* ==========================================================================
   3. STAGE — drop area, file bar, page grid
   ========================================================================== */
.stage {
  min-block-size: 420px;
  padding: var(--s-4);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
}
.stage.is-over { border-color: var(--primary); background: var(--primary-soft); }

.stage__empty {
  min-block-size: 380px;
  display: grid; place-content: center; justify-items: center; gap: var(--s-3);
  text-align: center;
  padding: var(--s-6) var(--s-4);
}
.stage__empty .dropzone__icon { margin-bottom: var(--s-1); }

.filebar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2);
  padding-bottom: var(--s-3);
  margin-bottom: var(--s-3);
  border-bottom: 1px solid var(--hairline);
}
.file-chip {
  display: inline-flex; align-items: center; gap: var(--s-2);
  min-height: 32px; padding: var(--s-1) var(--s-2) var(--s-1) var(--s-3);
  background: var(--surface-2);
  border: 1px solid var(--hairline);
  border-radius: var(--r-pill);
  font-size: var(--fs-2xs);
  max-inline-size: 100%;
}
.file-chip__name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-inline-size: 22ch;
}
.file-chip__size { font-family: var(--font-mono); color: var(--text-faint); }
.file-chip__drop {
  position: relative;
  display: grid; place-items: center;
  inline-size: 24px; block-size: 24px; border-radius: var(--r-pill);
  color: var(--text-faint);
}
/* The chip has to stay chip-sized, but a 24px close control is not a thumb
   target. The DRAWN button stays 24px and the TOUCHABLE one is 44px, which is
   the standard way to satisfy both — and it matters most in Word → PDF, where
   this is the only way to swap the document out. */
.file-chip__drop::after {
  content: ''; position: absolute;
  inset: -10px;
  border-radius: var(--r-pill);
}
.file-chip__drop:hover { background: var(--danger-soft); color: var(--danger); }
.file-chip__drop svg { inline-size: 14px; block-size: 14px; }

/* ---- selection toolbar -------------------------------------------------- */
.toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2);
  padding: var(--s-2);
  margin-bottom: var(--s-3);
  background: var(--surface-inset);
  border: 1px solid var(--hairline);
  border-radius: var(--r-input);
  position: sticky; top: calc(var(--header-h) + var(--s-2)); z-index: 5;
}
.toolbar__count {
  font-family: var(--font-mono); font-size: var(--fs-2xs);
  color: var(--text-muted); padding-inline: var(--s-2);
}
.toolbar__sep { inline-size: 1px; align-self: stretch; background: var(--hairline); }

/* ---- page grid ---------------------------------------------------------- */
.pagegrid {
  display: grid;
  gap: var(--s-3);
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
}
@media (min-width: 768px) {
  .pagegrid { grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: var(--s-4); }
}

.page-card {
  position: relative;
  display: grid; gap: var(--s-2);
  padding: var(--s-2);
  background: var(--surface-2);
  border: 1px solid var(--hairline);
  border-radius: var(--r-input);
  cursor: grab;
  transition: border-color var(--t-fast) var(--ease-out),
              box-shadow var(--t-fast) var(--ease-out),
              opacity var(--t-fast) var(--ease-out);
}
.page-card:hover { border-color: var(--hairline-firm); }
.page-card[aria-selected="true"] {
  border-color: var(--primary);
  box-shadow: 0 0 0 1px var(--primary);
  background: var(--primary-soft);
}
.page-card.is-dragging { opacity: 0.4; cursor: grabbing; }
.page-card.is-drop-before { box-shadow: -3px 0 0 var(--primary); }
.page-card.is-drop-after  { box-shadow:  3px 0 0 var(--primary); }

.page-card__frame {
  position: relative;
  display: grid; place-items: center;
  aspect-ratio: 3 / 4;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 2px;
  overflow: hidden;
}
.page-card__img {
  max-inline-size: 100%; max-block-size: 100%;
  object-fit: contain;
  transition: transform var(--t-mid) var(--ease-out);
}
.page-card__img[data-rotate="90"]  { transform: rotate(90deg)  scale(0.75); }
.page-card__img[data-rotate="180"] { transform: rotate(180deg); }
.page-card__img[data-rotate="270"] { transform: rotate(270deg) scale(0.75); }

.page-card__blank {
  display: grid; place-items: center; gap: var(--s-1);
  inline-size: 100%; block-size: 100%;
  font-family: var(--font-mono); font-size: var(--fs-2xs);
  color: var(--text-faint);
  background: repeating-linear-gradient(45deg, var(--surface-inset) 0 6px, transparent 6px 12px);
}

.page-card__foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-2);
  font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--text-faint);
}
.page-card__no { font-weight: 500; }
.page-card__src {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-inline-size: 9ch; opacity: 0.75;
}
.page-card__check {
  position: absolute; inset-block-start: var(--s-2); inset-inline-start: var(--s-2);
  inline-size: 20px; block-size: 20px;
  display: grid; place-items: center;
  border: 1px solid var(--hairline-firm);
  border-radius: 4px;
  background: var(--surface);
  color: transparent;
}
.page-card[aria-selected="true"] .page-card__check {
  background: var(--primary); border-color: var(--primary); color: var(--text-on-accent);
}
.page-card__check svg { inline-size: 12px; block-size: 12px; }

/* Skeleton while the thumbnail renders */
.page-card__frame.is-loading { background: var(--surface-inset); }

/* ==========================================================================
   4. CONTROLS PANEL
   ========================================================================== */
.panel {
  padding: var(--s-4);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  display: grid; gap: var(--s-4);
  /* Grid items default to min-width:auto, so a <select> with a long option
     ("JPG — no transparency") pushes the whole panel wider than its column and
     the right border disappears off the edge. This lets the column shrink. */
  grid-template-columns: minmax(0, 1fr);
}
.panel__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-2);
}
.panel__title { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-md); color: var(--text-strong); }
.panel__note { font-size: var(--fs-2xs); color: var(--text-muted); }

/* .choice / .choice__opt moved to components.css — the calculator pages use
   checkboxes too and do not load this stylesheet, so a checkbox there was
   rendering completely unstyled. */

.actions { display: grid; gap: var(--s-2); }
.actions .btn { width: 100%; }
.actions__row { display: flex; gap: var(--s-2); }
.actions__row .btn { flex: 1; }

/* ==========================================================================
   5. PROGRESS
   ========================================================================== */
.progress {
  display: grid; gap: var(--s-2);
  padding: var(--s-3);
  background: var(--surface-inset);
  border: 1px solid var(--hairline);
  border-radius: var(--r-input);
}
.progress[hidden] { display: none; }
.progress__row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.progress__label { font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--text-muted); }
.progress__track {
  block-size: 4px; border-radius: var(--r-pill);
  background: var(--hairline); overflow: hidden;
}
.progress__bar {
  block-size: 100%; inline-size: 0%;
  background: var(--primary);
  transform-origin: left;
  transition: width 120ms linear;
}
.progress__bar.is-indeterminate {
  inline-size: 35%;
  animation: progress-slide 1.1s var(--ease-out) infinite;
}
@media (prefers-reduced-motion: no-preference) {
  @keyframes progress-slide {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(340%); }
  }
}

/* ==========================================================================
   6. PRIVACY BANNER — the site's strongest claim, stated where the file is
   ========================================================================== */
.local-banner {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--primary-soft);
  border-left: 2px solid var(--primary);
  border-radius: 0 var(--r-input) var(--r-input) 0;
  background: var(--primary-soft);
  font-size: var(--fs-2xs);
  color: var(--text);
}
.local-banner svg { inline-size: 16px; block-size: 16px; flex: none; color: var(--primary-text); }

/* ==========================================================================
   7. TOOL PAGE BITS used by the studio landing pages
   ========================================================================== */
.steps { counter-reset: step; display: grid; gap: var(--s-4); }
.step {
  counter-increment: step;
  display: grid; grid-template-columns: 32px 1fr; gap: var(--s-3);
  align-items: start;
}
.step::before {
  content: counter(step);
  display: grid; place-items: center;
  inline-size: 32px; block-size: 32px;
  border: 1px solid var(--hairline); border-radius: var(--r-pill);
  font-family: var(--font-mono); font-size: var(--fs-2xs);
  color: var(--primary-text);
}
.step__title { display: block; font-weight: 600; font-size: var(--fs-sm); color: var(--text-strong); }
.step__body  { display: block; margin-top: 2px; font-size: var(--fs-xs); color: var(--text-muted); }

/* ==========================================================================
   8. RANGE SLIDERS — watermark opacity, angle and size
   Styled in both engines so the track and thumb read as the same instrument
   as the rest of the site rather than as OS chrome.
   ========================================================================== */
.range {
  -webkit-appearance: none;
  appearance: none;
  inline-size: 100%;
  block-size: 28px;
  background: transparent;
  cursor: pointer;
}
.range::-webkit-slider-runnable-track {
  block-size: 4px;
  border-radius: var(--r-pill);
  background: var(--hairline-firm);
}
.range::-moz-range-track {
  block-size: 4px;
  border-radius: var(--r-pill);
  background: var(--hairline-firm);
}
.range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  margin-top: -8px;
  inline-size: 20px; block-size: 20px;
  border-radius: var(--r-pill);
  background: var(--primary);
  border: 2px solid var(--surface);
  box-shadow: 0 0 0 1px var(--hairline-firm);
}
.range::-moz-range-thumb {
  inline-size: 16px; block-size: 16px;
  border-radius: var(--r-pill);
  background: var(--primary);
  border: 2px solid var(--surface);
  box-shadow: 0 0 0 1px var(--hairline-firm);
}
.range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 3px var(--primary-ring); }
.range:focus-visible::-moz-range-thumb     { box-shadow: 0 0 0 3px var(--primary-ring); }

/* The live value beside a slider's label */
.field__label .num { margin-left: auto; color: var(--text-muted); font-size: var(--fs-2xs); }
.field__label { justify-content: space-between; }

/* A file input inside a control panel should not look like a text field */
input.input[type="file"] {
  padding: var(--s-2);
  font-family: var(--font-body);
  font-size: var(--fs-2xs);
  cursor: pointer;
}

/* ==========================================================================
   9. IMAGE STUDIO — preview, fill strategies, focal point, safe zones
   ========================================================================== */
.preview {
  position: relative;
  display: grid;
  place-items: center;
  min-block-size: 320px;
  padding: var(--s-4);
  background:
    repeating-conic-gradient(var(--surface-inset) 0% 25%, var(--surface-2) 0% 50%)
    50% / 20px 20px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-input);
  overflow: hidden;
}
/* The chequerboard shows transparency honestly rather than pretending a
   PNG with a transparent background is white. */

.preview__canvas {
  display: block;
  max-inline-size: 100%;
  box-shadow: var(--elev);
  border-radius: 2px;
  transition: border-radius var(--t-mid) var(--ease-out);
}
.preview__canvas.is-circular { border-radius: var(--r-pill); }

/* Safe zone: the region a platform will not crop. */
.preview__safe {
  position: absolute;
  border: 1.5px dashed var(--primary);
  background: var(--primary-soft);
  pointer-events: none;
  border-radius: 2px;
}
.preview__safe::after {
  content: attr(data-note);
  position: absolute;
  inset-block-start: 100%;
  inset-inline-start: 0;
  margin-block-start: 4px;
  padding: 2px 6px;
  border-radius: var(--r-input);
  background: var(--primary);
  color: var(--text-on-accent);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  white-space: nowrap;
}

/* Focal point handle — drag it to choose what survives a crop. */
.preview__focal {
  position: absolute;
  inline-size: 28px; block-size: 28px;
  margin: -14px 0 0 -14px;
  border-radius: var(--r-pill);
  border: 2px solid var(--surface);
  background: var(--primary);
  box-shadow: 0 0 0 1px var(--ink, rgb(0 0 0 / 0.3)), var(--elev);
  cursor: grab;
  touch-action: none;
}
.preview__focal::after {
  content: "";
  position: absolute; inset: 8px;
  border-radius: var(--r-pill);
  background: var(--surface);
}
.preview__focal:active { cursor: grabbing; }

/* The four fill strategies, previewed side by side. */
.strategies {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-3);
  margin-bottom: var(--s-3);
}
@media (min-width: 640px) { .strategies { grid-template-columns: repeat(4, 1fr); } }

.strategy {
  display: grid;
  gap: var(--s-2);
  justify-items: center;
  padding: var(--s-2);
  border: 1px solid var(--hairline);
  border-radius: var(--r-input);
  background: var(--surface-2);
  transition: border-color var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out);
}
.strategy:hover { border-color: var(--hairline-firm); }
.strategy[aria-checked="true"] {
  border-color: var(--primary);
  background: var(--primary-soft);
  box-shadow: 0 0 0 1px var(--primary);
}
.strategy__thumb {
  display: grid; place-items: center;
  inline-size: 100%; min-block-size: 84px;
  background: var(--surface-inset);
  border-radius: 2px;
  overflow: hidden;
}
.strategy__canvas { max-inline-size: 100%; max-block-size: 110px; display: block; }
.strategy__name {
  font-size: var(--fs-2xs); font-weight: 600; color: var(--text);
  text-align: center;
}

/* Colour input, so it does not look like an OS swatch dropped into the page */
input.input[type="color"] {
  padding: 4px;
  block-size: 44px;
  cursor: pointer;
}

/* Same reason as the .panel grid fix: a control must never be the thing that
   decides how wide its container is. */
.select, .input, .textarea { min-inline-size: 0; max-inline-size: 100%; }
.field { min-inline-size: 0; }

/* ==========================================================================
   10. THE EDITOR — annotate and sign

   One page on screen with a transparent canvas over it. Two canvases stacked
   rather than one, so a pointer drag repaints the ink without re-rasterising
   the page underneath it.
   ========================================================================== */
.editor { display: grid; gap: var(--s-3); min-inline-size: 0; }

.editor__bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2);
  padding: var(--s-2);
  background: var(--surface-inset);
  border: 1px solid var(--hairline);
  border-radius: var(--r-input);
}
.editor__pos {
  font-family: var(--font-mono); font-size: var(--fs-2xs);
  color: var(--text); padding-inline: var(--s-2); min-inline-size: 9ch;
}
.editor__zoom {
  font-family: var(--font-mono); font-size: var(--fs-2xs);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
  color: var(--text-faint);
}
.editor__bar .range { inline-size: 110px; flex: none; }
/* The page arrows carry one character, so they need a width floor of their
   own — a 44px-tall button 30px wide is still not a 44px target. */
.editor__bar [data-page-step] { min-inline-size: 44px; }
.editor__meta {
  font-family: var(--font-mono); font-size: var(--fs-2xs);
  color: var(--text-faint); margin-inline-start: auto;
}

/* Zooming past the panel width must scroll INSIDE here — the page body itself
   never scrolls sideways. */
.editor__scroll {
  overflow: auto;
  overscroll-behavior-x: contain;
  padding: var(--s-3);
  background:
    repeating-conic-gradient(var(--surface-inset) 0% 25%, var(--surface-2) 0% 50%)
    50% / 20px 20px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-input);
  display: grid;
  justify-items: center;
}

.editor__paper {
  position: relative;
  flex: none;
  box-shadow: var(--elev);
  background: #FFFFFF;   /* paper is paper in both themes — it is the page */
}
.editor__page,
.editor__ink { display: block; }
.editor__ink {
  position: absolute;
  inset: 0;
  /* Without this a drag on a touchscreen scrolls the page instead of drawing. */
  touch-action: none;
}
.stage[data-editor^="annotate"] .editor__ink { cursor: crosshair; }

.editor__tip { font-size: var(--fs-2xs); color: var(--text-muted); }

/* ---- colour swatches ---------------------------------------------------- */
.swatches { display: flex; align-items: center; gap: 2px; }
.swatch {
  position: relative;
  inline-size: 44px; block-size: 44px;   /* the target, not the dot */
  padding: 0; border: 0; background: none; cursor: pointer;
  border-radius: var(--r-input);
}
.swatch::after {
  content: "";
  position: absolute; inset: 11px;
  border-radius: var(--r-pill);
  background: var(--swatch);
  box-shadow: 0 0 0 1px var(--hairline-firm);
}
.swatch:hover::after { inset: 9px; }
.swatch[aria-pressed="true"]::after {
  inset: 8px;
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--primary);
}
.swatch:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
@media (prefers-reduced-motion: no-preference) {
  .swatch::after { transition: inset var(--t-fast) var(--ease-out); }
}

/* ---- signature placement box -------------------------------------------- */
/* The signature itself is painted by the overlay canvas, so the preview and
   the export are the same code. This only supplies the affordances. */
.place {
  position: absolute;
  border: 1px dashed var(--primary);
  background: var(--primary-soft);
  cursor: grab;
  touch-action: none;
}
.place[hidden] { display: none; }
.place.is-active { cursor: grabbing; background: transparent; }
.place__hint {
  position: absolute;
  inset-block-end: 100%; inset-inline-start: 0;
  margin-block-end: 4px;
  padding: 2px 6px;
  border-radius: var(--r-input);
  background: var(--primary); color: var(--text-on-accent);
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.06em; white-space: nowrap;
  pointer-events: none;
}
.place__handle {
  position: absolute;
  inset-block-end: 0; inset-inline-end: 0;
  inline-size: 44px; block-size: 44px;      /* touch target */
  margin: 22px -22px -22px 0;
  padding: 0; border: 0; background: none;
  cursor: nwse-resize; touch-action: none;
}
.place__handle::after {
  content: "";
  position: absolute; inset: 14px;
  border-radius: var(--r-pill);
  border: 2px solid var(--surface);
  background: var(--primary);
  box-shadow: var(--elev);
}
.place__handle:focus-visible { outline: 2px solid var(--primary); outline-offset: -10px; }

/* ---- the signature pad and its preview ---------------------------------- */
.sigpad {
  display: block;
  block-size: 150px;
  border: 1px dashed var(--hairline-firm);
  border-radius: var(--r-input);
  background: var(--surface);
  background-image: linear-gradient(var(--hairline) 1px, transparent 1px);
  background-size: 100% 110px;      /* one signing line, near the bottom */
  background-repeat: no-repeat;
  background-position: 0 110px;
  overflow: hidden;
}
.sigpad__canvas {
  display: block;
  inline-size: 100%; block-size: 100%;
  touch-action: none;               /* a finger draws, it does not scroll */
  cursor: crosshair;
}

.sigview {
  display: grid; place-items: center;
  min-block-size: 84px;
  padding: var(--s-3);
  border: 1px solid var(--hairline);
  border-radius: var(--r-input);
  background:
    repeating-conic-gradient(var(--surface-inset) 0% 25%, var(--surface-2) 0% 50%)
    50% / 16px 16px;
}
/* Chequerboard because the background really is transparent, and showing it
   on white would hide the one thing worth checking before you place it. */
.sigview__img {
  max-inline-size: 100%; max-block-size: 96px;
  display: block;
}
.sigview__img[hidden] { display: none; }

/* ==========================================================================
   11. CROP, WATERMARK, BACKGROUND AND PASSPORT

   All four work ON the picture rather than on a result, so they share one
   arrangement: the source image is painted into .preview and an absolutely
   positioned overlay is laid over the canvas, sized to it in JavaScript.
   Every draggable thing gets a 44px touch target with a smaller visible dot,
   and touch-action: none so a finger drags it instead of scrolling the page.
   ========================================================================== */

/* ---- the crop rectangle -------------------------------------------------- */
.crop {
  position: absolute;
  box-sizing: border-box;
  border: 1px solid var(--surface);
  outline: 1px solid rgb(0 0 0 / 0.45);
  /* Everything outside the rectangle is dimmed by an enormous shadow rather
     than by four separate overlay elements — one box, no seams. */
  box-shadow: 0 0 0 9999px rgb(0 0 0 / 0.45);
  cursor: grab;
  touch-action: none;
}
.crop.is-dragging { cursor: grabbing; }

.crop__thirds {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--t-fast) var(--ease-out);
  background:
    linear-gradient(to right,
      transparent calc(33.333% - 0.5px), rgb(255 255 255 / 0.55) calc(33.333% - 0.5px),
      rgb(255 255 255 / 0.55) calc(33.333% + 0.5px), transparent calc(33.333% + 0.5px),
      transparent calc(66.666% - 0.5px), rgb(255 255 255 / 0.55) calc(66.666% - 0.5px),
      rgb(255 255 255 / 0.55) calc(66.666% + 0.5px), transparent calc(66.666% + 0.5px)),
    linear-gradient(to bottom,
      transparent calc(33.333% - 0.5px), rgb(255 255 255 / 0.55) calc(33.333% - 0.5px),
      rgb(255 255 255 / 0.55) calc(33.333% + 0.5px), transparent calc(33.333% + 0.5px),
      transparent calc(66.666% - 0.5px), rgb(255 255 255 / 0.55) calc(66.666% - 0.5px),
      rgb(255 255 255 / 0.55) calc(66.666% + 0.5px), transparent calc(66.666% + 0.5px));
}
.crop.is-thirds .crop__thirds { opacity: 1; }

.crop__size {
  position: absolute;
  inset-block-end: 100%; inset-inline-start: 0;
  margin-block-end: 4px;
  padding: 2px 6px;
  border-radius: var(--r-input);
  background: var(--primary); color: var(--text-on-accent);
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.06em; white-space: nowrap;
  pointer-events: none;
}

.crop__handle {
  position: absolute;
  inline-size: 44px; block-size: 44px;      /* the touch target */
  padding: 0; border: 0; background: none;
  touch-action: none;
}
.crop__handle::after {
  content: "";
  position: absolute; inset: 16px;          /* the visible dot */
  border-radius: 2px;
  border: 2px solid var(--surface);
  background: var(--primary);
  box-shadow: 0 0 0 1px rgb(0 0 0 / 0.35);
}
.crop__handle:focus-visible { outline: 2px solid var(--primary); outline-offset: -12px; }

.crop__handle--nw { inset-block-start: -22px; inset-inline-start: -22px; cursor: nwse-resize; }
.crop__handle--ne { inset-block-start: -22px; inset-inline-end: -22px;   cursor: nesw-resize; }
.crop__handle--sw { inset-block-end: -22px;   inset-inline-start: -22px; cursor: nesw-resize; }
.crop__handle--se { inset-block-end: -22px;   inset-inline-end: -22px;   cursor: nwse-resize; }
.crop__handle--n  { inset-block-start: -22px; inset-inline-start: 50%; margin-inline-start: -22px; cursor: ns-resize; }
.crop__handle--s  { inset-block-end: -22px;   inset-inline-start: 50%; margin-inline-start: -22px; cursor: ns-resize; }
.crop__handle--w  { inset-inline-start: -22px; inset-block-start: 50%; margin-block-start: -22px; cursor: ew-resize; }
.crop__handle--e  { inset-inline-end: -22px;   inset-block-start: 50%; margin-block-start: -22px; cursor: ew-resize; }

/* On a narrow screen eight 44px targets around a small rectangle overlap each
   other. The edge handles go; the corners are enough to resize with. */
@media (max-width: 520px) {
  .crop__handle--n, .crop__handle--s, .crop__handle--w, .crop__handle--e { display: none; }
}

/* ---- passport markers ---------------------------------------------------- */
.marks { position: absolute; touch-action: none; }

.marks__frame {
  position: absolute;
  border: 1.5px dashed var(--primary);
  background: rgb(255 255 255 / 0.08);
  pointer-events: none;
}
.marks__head {
  position: absolute;
  border: 1px solid rgb(255 255 255 / 0.7);
  border-radius: 50%;
  pointer-events: none;
}

.marks__line {
  position: absolute;
  inset-inline: 0;
  block-size: 44px;                          /* touch target */
  margin-block-start: -22px;
  padding: 0; border: 0; background: none;
  cursor: ns-resize; touch-action: none;
}
.marks__line::after {
  content: "";
  position: absolute;
  inset-inline: 0; inset-block-start: 21px;
  block-size: 2px;
  background: var(--primary);
  box-shadow: 0 0 0 1px rgb(0 0 0 / 0.35);
}
.marks__line:focus-visible { outline: 2px solid var(--primary); outline-offset: -18px; }
.marks__tag {
  position: absolute;
  inset-block-start: 2px; inset-inline-start: 4px;
  padding: 2px 6px;
  border-radius: var(--r-input);
  background: var(--primary); color: var(--text-on-accent);
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.04em; white-space: nowrap;
  pointer-events: none;
}

.marks__centre {
  position: absolute;
  inset-block: 0;
  inline-size: 44px;
  margin-inline-start: -22px;
  padding: 0; border: 0; background: none;
  cursor: ew-resize; touch-action: none;
}
.marks__centre::after {
  content: "";
  position: absolute;
  inset-block: 0; inset-inline-start: 21px;
  inline-size: 2px;
  background: rgb(255 255 255 / 0.75);
}
.marks__centre:focus-visible { outline: 2px solid var(--primary); outline-offset: -18px; }

/* ---- the nine-point position grid ---------------------------------------- */
.posgrid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 3px;
  inline-size: 132px;
  aspect-ratio: 4 / 3;
  padding: 3px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-input);
  background: var(--surface-inset);
}
.posgrid__cell {
  border: 0; border-radius: 2px;
  background: var(--surface-2);
  min-block-size: 22px;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out);
}
.posgrid__cell:hover { background: var(--primary-soft); }
.posgrid__cell[aria-checked="true"] { background: var(--primary); }
.posgrid__cell:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

/* ---- two-up numeric fields ----------------------------------------------- */
.pairs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); }

/* ---- the passport checks ------------------------------------------------- */
.checks {
  display: grid; gap: var(--s-2);
  padding: var(--s-3);
  border: 1px solid var(--hairline);
  border-radius: var(--r-input);
  background: var(--surface-2);
}
.checks__head {
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-faint);
}
.checks__head + .checks__row { margin-block-start: -2px; }
.checks__row {
  display: flex; gap: var(--s-2); align-items: flex-start;
  font-size: var(--fs-2xs);
}
.checks__row--ask { cursor: pointer; min-block-size: 44px; align-items: center; }
.checks__row input { margin: 0; accent-color: var(--primary); inline-size: 16px; block-size: 16px; flex: none; }
.checks__mark {
  inline-size: 16px; block-size: 16px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  font-size: 10px; font-weight: 700;
  color: var(--text-on-accent);
  background: var(--text-faint);
}
.checks__row--ok  .checks__mark { background: var(--signal); }
.checks__row--warn .checks__mark { background: var(--amber); color: var(--text-on-signal); }
.checks__row--bad .checks__mark { background: var(--danger); }
.checks__label { display: block; font-weight: 600; color: var(--text); }
.checks__note  { display: block; margin-top: 2px; color: var(--text-muted); }

/* --------------------------------------------------------------------------
   Word document summary — the stage for Word → PDF

   Not a preview of the document: a readout of what the PARSE understood, so
   it is obvious at a glance whether the headings came through as headings
   before anything is converted.
   -------------------------------------------------------------------------- */
.doclist {
  list-style: none;
  margin: 0;
  padding: var(--s-3);
  display: grid;
  gap: var(--s-2);
  max-block-size: 420px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.doclist__row {
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
  min-inline-size: 0;
  padding-block-end: var(--s-2);
  border-block-end: 1px solid var(--hairline);
}
.doclist__row:last-child { border-block-end: 0; padding-block-end: 0; }
.doclist__tag {
  flex: none;
  inline-size: 3.2em;
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
}
.doclist__tag[data-kind="heading"] { color: var(--primary-text); font-weight: 600; }
.doclist__tag[data-kind="list"]    { color: var(--amber-text); }
.doclist__text {
  min-inline-size: 0;
  font-size: var(--fs-xs);
  color: var(--text);
  overflow-wrap: anywhere;
}
.doclist__row:has(.doclist__tag[data-kind="heading"]) .doclist__text {
  font-weight: 600;
  color: var(--text-strong);
}

/* ==========================================================================
   LIVE TEXT EDITING

   The page is a rendered image and every editable run is a transparent button
   on top of it. Two things follow from that and both matter:

   · The hit areas are positioned in PERCENTAGES, so the overlay tracks the
     page at any container width. Pixels would drift the moment the window
     resized, and a hit area that has drifted is worse than none — you click a
     word and edit the one beside it.

   · The inline editor's font-size is set in `cqh` against the page's own
     container, so the text you type is the size it will be in the export
     rather than the size the browser's default happens to be.
   ========================================================================== */
.edit-surface { display: grid; gap: var(--s-5); }

.edit-page {
  container-type: size;
  position: relative;
  inline-size: 100%;
  background: #FFFFFF;
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  box-shadow: var(--elev);
  overflow: hidden;
}
.edit-page__canvas { display: block; inline-size: 100%; block-size: auto; }
.edit-page__layer { position: absolute; inset: 0; }

.edit-run {
  position: absolute;
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: transparent;
  cursor: text;
  transition: background var(--t-fast) var(--ease-out),
              box-shadow var(--t-fast) var(--ease-out);
}
/* A hint of the accent on hover, so it is discoverable that the words are
   clickable, without painting a grid of boxes over the document at rest. */
.edit-run:hover { background: color-mix(in srgb, var(--primary) 16%, transparent); }
.edit-run:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
  background: color-mix(in srgb, var(--primary) 12%, transparent);
}
/* An applied edit stays marked, so it is obvious what has been changed before
   anything is exported. */
.edit-run.is-edited {
  background: color-mix(in srgb, var(--signal) 22%, transparent);
  box-shadow: inset 0 -2px 0 var(--signal);
}

.edit-input {
  position: absolute;
  z-index: 2;
  padding: 0 2px;
  border: 2px solid var(--primary);
  border-radius: 3px;
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-body);
  line-height: 1;
  box-shadow: var(--elev-lift);
}
.edit-input:focus { outline: none; }

@media (prefers-reduced-motion: reduce) {
  .edit-run { transition: none; }
}
