/* Form Fields editor — the page on the left, the field list on the right.
   Shell motion matches the redact/sign editor family exactly: editorOverlayIn +
   editorBoxIn on open, editorOverlayOut + editorBoxOut on close (keyframes are
   defined once in app.css). The global reduced-motion collapse in main.css
   covers every finite entrance here; the local block below only holds the
   highlight's transform end-state, which a duration alone would not settle. */

.fields-empty-note { margin: 14px 0 0; font-size: 13px; }

.fields-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(8, 10, 16, 0.88);
  display: flex;
  animation: editorOverlayIn .2s ease;
}
.fields-overlay.closing {
  animation: editorOverlayOut .2s ease forwards;
  pointer-events: none;
}
/* "A suggestion is waiting" needs a third colour beside --primary and --success,
   and the palette has no shared amber. It lives here, scoped to this editor, in
   two tones: an edge tone for tints (free to be bright) and a text
   tone dark enough on white / light enough on near-black to stay readable. */
.fields-editor {
  --fields-amber: #92400e;
  --fields-amber-edge: #d97706;
}
html[data-theme="dark"] .fields-editor {
  --fields-amber: #fbbf24;
  --fields-amber-edge: #f59e0b;
}

.fields-editor {
  position: relative;   /* the walk's completion toast is absolute inside it */
  background: var(--bg-elev);
  display: flex;
  flex-direction: column;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  animation: editorBoxIn .32s cubic-bezier(.2, .7, .3, 1);
}
.fields-overlay.closing .fields-editor {
  animation: editorBoxOut .2s ease forwards;
}

/* ---- toolbar ---- */
.fields-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
}
.fields-toolbar-left,
.fields-toolbar-right { display: flex; align-items: center; gap: 8px; min-width: 0; }
.fields-toolbar-left strong { font-size: 14px; }
.fields-count { font-size: 12px; color: var(--text-soft); }
/* The page-prefix option sits among the ghost buttons and wears their shape:
   same border, padding and hover, with the focus ring on the label when the box
   inside it has keyboard focus. */
.fields-check {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 10px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: border-color .15s, background-color .15s, box-shadow .15s;
}
.fields-check:hover { background: var(--bg-soft); border-color: var(--border-strong); }
.fields-check:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }
.fields-check input { margin: 0; width: 14px; height: 14px; accent-color: var(--primary); cursor: pointer; }

/* ---- body ---- */
.fields-body {
  flex: 1;
  display: flex;
  min-height: 0;
}
/* The stage wrap anchors the floating zoom pill (.pf-zoom-float, app.css) to
   the page area's bottom-right corner, clear of the field list whichever side
   the list is on. */
.fields-stage-wrap {
  position: relative;
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
}
.fields-stage {
  flex: 1;
  min-width: 0;
  overflow: auto;
  /* Reserve the scrollbar's space so clientWidth does not flip as the bar
     toggles at fit-page (the toggle would re-fit, which re-toggles the bar). */
  scrollbar-gutter: stable;
  /* Column flex + auto margins on the inner box: a page that fits sits in the
     middle; a page that overflows resolves its margins to zero, so the top and
     left edges are never clipped the way justify-content:center clips them. */
  display: flex;
  flex-direction: column;
  padding: 24px;
  background: var(--bg);
}
.fields-stage:focus { outline: none; }
.fields-stage-inner { position: relative; margin: auto; flex: none; }
/* The fit chips carry icons, not the text labels the shared pill sizes for. */
.fields-zoom-fit { width: 42px; padding: 0; }
.fields-canvas {
  display: block;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .28);
  border-radius: 3px;
}

/* The outline layer sits ON TOP of the canvas with its own stacking context, so
   a mark is never painted under the page it describes (the invisible-overlay
   class of bug the thumbnail marks hit once). */
.fields-marks {
  position: absolute;
  inset: 0;
  z-index: 2;
}
.fields-mark {
  position: absolute;
  margin: 0;
  padding: 0;
  background: rgba(14, 116, 144, .10);
  border: 1.5px dashed var(--primary);
  border-radius: 2px;
  cursor: pointer;
  z-index: 1;
  transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.fields-mark:hover { background: rgba(14, 116, 144, .18); }
.fields-mark:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.fields-mark.active {
  /* The active widget must beat every sibling outline, including the dashed
     boxes drawn after it in DOM order. */
  z-index: 3;
  background: rgba(14, 116, 144, .26);
  border-style: solid;
  border-width: 2px;
  box-shadow: 0 0 0 3px rgba(14, 116, 144, .28);
  animation: kpRise .26s cubic-bezier(.2, .7, .3, 1);
}
/* During the walk the spotlight band glides to the mark and measures it as it
   goes. The rise runs under a translate, so the band would read the mark 12px
   low and then hop up to it once the transform ends. The glide is the step's
   motion; the mark itself just lands. */
.fields-marks.reviewing .fields-mark.active { animation: none; }

/* ---- the Review walk ---- */
/* While the walk runs every mark but the focused one recedes (softer outline,
   no fill), so the field under the bar is the one thing that reads. Same
   transitions as the mark itself; reverts the moment the walk ends. */
.fields-marks.reviewing .fields-mark:not(.active) {
  border-color: color-mix(in srgb, var(--primary) 40%, transparent);
  background: transparent;
}
/* The line-band spotlight, the redact editor's (.redact-spotlight) verbatim: it
   lives in the stage WRAP (the stage's offset parent, pinned to the viewport,
   not the scrolling content), the controller sizes it to the stage and paints
   the dim / clear / dim gradient inline, and it sits under the zoom pill and the
   floating bar. Opacity is the only motion; the global reduced-motion gate
   makes it instant. */
.fields-spotlight {
  position: absolute;
  pointer-events: none;
  z-index: 5;
  opacity: 0;
  transition: opacity .3s cubic-bezier(.2, .7, .3, 1);
}
.fields-spotlight.show { opacity: 1; }

/* ---- the list ---- */
.fields-aside {
  width: 340px;
  flex: 0 0 340px;
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--bg-elev);
  animation: kpRise .3s cubic-bezier(.2, .7, .3, 1);
}
.fields-aside-head {
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 13px;
  font-weight: 600;
}
.fields-hint { font-weight: 400; font-size: 12px; color: var(--text-soft); }
.fields-list {
  flex: 1;
  overflow: auto;
  padding: 6px;
}
.fields-list:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

.fields-row {
  padding: 8px 10px;
  border: 1px solid transparent;
  border-radius: 8px;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.fields-row:hover { border-color: var(--border); background: var(--bg); }
.fields-row.active {
  border-color: var(--primary);
  background: var(--bg);
  box-shadow: 0 0 0 2px rgba(14, 116, 144, .18);
}
/* No colour-coded edge on a row: the redact editor's list carries state in the
   row's own content, and a stripe per state turns a long list into a barcode.
   A changed name shows its "was X" line and a Revert button; a waiting
   suggestion shows its tinted diff line. The classes stay as state hooks. */
.fields-row-main {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
.fields-row-name {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  word-break: break-all;
}
.fields-row-type { font-size: 11px; color: var(--text-soft); flex: none; }
.fields-row-was {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--text-soft);
  margin-top: 2px;
  flex-wrap: wrap;
  word-break: break-all;
}
/* Undo is quiet until you go looking for it: full strength on hover and focus,
   never louder than Accept. */
.fields-revert {
  margin-left: auto;
  flex: none;
  padding: 1px 7px;
  font-size: 11px;
  opacity: .75;
  transition: opacity .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.fields-revert:hover,
.fields-revert:focus-visible { opacity: 1; }

.fields-row-input {
  width: 100%;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  padding: 2px 6px;
  border: 1px solid var(--primary);
  border-radius: 5px;
  background: var(--bg-elev);
  color: var(--text);
}
.fields-row-input:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

.fields-row-diff {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 6px;
  padding: 4px 6px;
  border-radius: 6px;
  /* A faint wash of the same amber ties the offer to the row's left edge. */
  background: color-mix(in srgb, var(--fields-amber-edge) 12%, transparent);
  font-size: 12px;
  animation: kpRise .26s cubic-bezier(.2, .7, .3, 1);
}
/* Old names are long PDF paths with no spaces (topmostSubform[0].Page1[0]...):
   let them break anywhere so they never push the pane wider than it is. */
.fields-diff-old { color: var(--text-soft); text-decoration: line-through; word-break: break-all; min-width: 0; }
.fields-diff-arrow { color: var(--text-soft); }
.fields-diff-new {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--fields-amber);
  font-weight: 600;
  word-break: break-all;
}
.fields-accept { margin-left: auto; flex: none; }

/* ---- the entry offer ---- */
/* Floats over the top of the page area rather than pushing the layout: it is a
   question about the list, and the page under it should stay put. */
.fields-prompt {
  position: absolute;
  z-index: 6;
  top: 16px;
  /* Centred by auto margins, not translateX: kpRise animates transform, and a
     transform used for layout would be thrown away for the length of the run. */
  left: 0;
  right: 0;
  margin: 0 auto;
  width: min(420px, calc(100% - 32px));
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-elev);
  box-shadow: var(--shadow-lg);
  animation: kpRise .3s cubic-bezier(.2, .7, .3, 1);
}
.fields-prompt.closing { animation: kpFadeDown .18s ease-in forwards; }
.fields-prompt-title { display: block; font-size: 14px; }
.fields-prompt-body { margin: 4px 0 12px; font-size: 12px; color: var(--text-soft); }
.fields-prompt-actions { display: flex; flex-wrap: wrap; gap: 8px; }

@media (max-width: 820px) {
  .fields-body { flex-direction: column; }
  .fields-aside { width: auto; flex: 0 0 44%; border-left: 0; border-top: 1px solid var(--border); }
}

@media (prefers-reduced-motion: reduce) {
  /* The global gate collapses durations. The active highlight also animates a
     transform, so pin its end-state rather than let a 0.01ms run land it. */
  .fields-mark.active,
  .fields-aside,
  .fields-prompt,
  .fields-row-diff { animation: none; transform: none; }
}
