/*
 * ════════════════════════════════════════════════════════════════════════
 *  THE WIZARD — the signals around the composer
 * ════════════════════════════════════════════════════════════════════════
 *
 * Companion to wizard_composer.css, which owns the rail, the paper and the
 * composer itself. This file owns the smaller pieces that outlived the
 * redesign because they were never about the layout: the change bar in the
 * document's margin, the "Gemt" pill, the paginated page stack, the
 * genvejskort and the person picker.
 *
 * WHAT LEFT WHEN THE COMPOSER ARRIVED: the horizontal strip of named chips
 * and its vertical variant (the rail is a track of segments now, and the
 * names live in the popover it opens), the read-ahead card, the folded
 * `<details>` behind "Hvorfor spørger vi?" (a real popover, dismissible with
 * Escape), the pane's own toolbar (the document tabs and the zoom control
 * are in the rail) and the "Udkast opdateret" chip that used to hang off it.
 *
 * Load order is alphabetical under Propshaft's bulk `stylesheet_link_tag
 * :app`: notarium.css, then this, then wizard_composer.css. So a tie between
 * this sheet and the composer's is won by the composer, with no `!important`
 * anywhere.
 *
 * Every custom property referenced here is defined in notarium.css sections
 * 1–3. An undefined `var(--nt-…)` invalidates the whole declaration and does
 * not fall back, so nothing is invented locally.
 */

/* ══════════════════════════════════════════════════════════════════════
   3. "THE DRAFT JUST CHANGED"

   Three signals, because one was not landing: the paragraph washes seal and
   grows a change bar in the margin, the pane scrolls it into view, and a chip
   pinned to the top of the paper says so in words — the changed paragraph is
   usually below the fold while the customer is still looking at the question.

   What was REMOVED here is as important: the whole sheet used to dip to 0.35
   opacity on every answer as a "crossfade". With no outgoing node to fade
   against that is not a crossfade, it is the page blinking, and it was half of
   "the page kinda blinks when I change options". Two renders of a document
   that barely changed are almost identical pixels; swapping them plainly is
   invisible, which is exactly what a swap should be.
   ══════════════════════════════════════════════════════════════════════ */

/* A CHANGE BAR IN THE MARGIN — the redline mark a jurist already reads as
   "this is what moved", pulled out into the sheet's own gutter so it never
   pushes a line of the document sideways. Longer and firmer than the 600 ms
   wash it replaces: a highlight nobody notices is not a highlight.

   `.nt-doc-flash` is deliberately left alone. It is declared in notarium.css
   and one animation with two owners is how a highlight quietly changes
   behaviour when somebody reorders a file. */
.nt-doc-sheet .nt-wz-changed {
  position: relative;
  border-radius: 2px;
  animation: nt-wz-changed 1400ms var(--nt-ease) 1 both;
}

.nt-doc-sheet .nt-wz-changed::before {
  content: "";
  position: absolute;
  left: -0.85rem;
  top: -0.15rem;
  bottom: -0.15rem;
  width: 3px;
  border-radius: 2px;
  background: var(--nt-seal);
  animation: nt-wz-changed-bar 1400ms var(--nt-ease) 1 both;
}

@keyframes nt-wz-changed {
  0% { background-color: transparent; }
  10% { background-color: color-mix(in srgb, var(--nt-seal) 15%, transparent); }
  55% { background-color: color-mix(in srgb, var(--nt-seal) 15%, transparent); }
  100% { background-color: transparent; }
}

@keyframes nt-wz-changed-bar {
  0% { opacity: 0; transform: scaleY(0.4); }
  12% { opacity: 1; transform: scaleY(1); }
  62% { opacity: 1; transform: scaleY(1); }
  100% { opacity: 0; transform: scaleY(1); }
}

/* ── "Gemt", made legible ───────────────────────────────────────────────
   It was 11px tertiary text next to a 2.5mm dot, and the customer's answer to
   "did that save?" should not require squinting. Same three states, same
   ordering promise (idle → saving → saved, and a failure never decays into
   "Gemt") — it just carries its own pill now. The padding is on the base rule
   so the footer does not shift when the state changes. */
.nt-autosave {
  padding: 0.16rem 0.6rem 0.16rem 0.5rem;
  border: 1px solid transparent;
  border-radius: var(--nt-radius-full);
  font-weight: 600;
  transition:
    opacity var(--nt-duration) var(--nt-ease),
    background-color var(--nt-duration) var(--nt-ease),
    border-color var(--nt-duration) var(--nt-ease);
}

.nt-autosave[data-state="saving"] {
  background: var(--nt-surface-sunken);
  border-color: var(--nt-border-subtle);
  color: var(--nt-text-secondary);
}

.nt-autosave[data-state="saved"] {
  background: var(--nt-ok-soft);
  border-color: var(--nt-ok-border);
}

.nt-autosave[data-state="failed"] {
  background: var(--nt-danger-soft);
  border-color: var(--nt-danger-border);
}


/* ══════════════════════════════════════════════════════════════════════
   4d. REAL PAGES

   The paginator (lib/paginate.js) replaces the single endless sheet with one
   .nt-doc-page per PRINTED page, each carrying "Side n af N". A document that
   fits on one page never reaches these rules at all — it stays exactly the
   .nt-doc-sheet the server rendered.
   ══════════════════════════════════════════════════════════════════════ */

.nt-doc-stack {
  display: flex;
  flex-direction: column;
  /* Enough air that two pages read as two sheets on a desk rather than as one
     document with a rule through it. */
  gap: var(--nt-space-6);
  width: 100%;
  max-width: var(--nt-doc-width);
}

/* ZOOM-TO-FIT uses `zoom`, not `transform: scale`.
   A transform leaves the layout box at full size, so a stack of four pages
   scaled to 45% would sit above three pages' worth of empty desk. `zoom`
   reflows, so the stack closes up and the pane scrolls exactly as far as
   there is document. The ratio is computed by document_preview_controller —
   one page in the pane, never above 1:1. */
.nt-wz-stage[data-zoom="fit"] .nt-doc-sheet { zoom: var(--nt-doc-zoom, 1); }

/* ══════════════════════════════════════════════════════════════════════
   4e. THE GENVEJSKORT

   A plain <dialog>: Escape, the backdrop and the focus trap are the
   platform's, and the card is rendered once outside every swapped region so
   ⌘Enter's own help survives the swap ⌘Enter causes.
   ══════════════════════════════════════════════════════════════════════ */

.nt-shortcuts {
  margin: auto;
  padding: var(--nt-space-6);
  max-width: 24rem;
  border: 1px solid var(--nt-border-subtle);
  border-radius: var(--nt-radius-lg);
  background: var(--nt-surface);
  color: var(--nt-text);
  box-shadow: var(--nt-shadow-3);
}

.nt-shortcuts::backdrop { background: rgb(0 0 0 / 0.35); }

.nt-shortcuts-title {
  font-family: var(--nt-font-display);
  font-size: var(--nt-text-lg);
  font-weight: 600;
  margin-bottom: var(--nt-space-4);
}

.nt-shortcuts-list { display: grid; gap: var(--nt-space-3); margin-bottom: var(--nt-space-5); }

.nt-shortcuts-list > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--nt-space-4);
}

.nt-shortcuts-list dt { flex: none; color: var(--nt-text-secondary); }
.nt-shortcuts-list dd { text-align: right; color: var(--nt-text); }

.nt-shortcuts kbd {
  display: inline-block;
  min-width: 1.6rem;
  padding: 0.1rem 0.35rem;
  border: 1px solid var(--nt-border);
  border-bottom-width: 2px;
  border-radius: var(--nt-radius-xs);
  background: var(--nt-surface-sunken);
  font-family: var(--nt-font-mono);
  font-size: var(--nt-text-xs);
  text-align: center;
}


/* ══════════════════════════════════════════════════════════════════════
   REDUCED MOTION

   Not "turn it off" — "arrive already finished". The change bar still
   HAPPENS: "which paragraph did my answer just change" is information, not
   decoration, and a reader who asked for less motion still needs it. What
   goes is the travel.
   ══════════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  /* THE CHANGE BAR STOPS BEING TIMED AND STARTS BEING A STATE.
     notarium.css's reduced-motion block clamps every animation to 1 ms, so a
     1400 ms wash under this preference is not "instant" — it is invisible,
     and the customer loses the one answer to "which paragraph did I just
     change". Here the mark simply stays: no fade in, no fade out, painted
     until the next answer re-renders the preview and takes the class with
     it. */
  .nt-doc-sheet .nt-wz-changed {
    animation: none;
    background-color: color-mix(in srgb, var(--nt-seal) 12%, transparent);
  }

  .nt-doc-sheet .nt-wz-changed::before {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   6. THE PERSON PICKER

   Every `stakeholder` answer. It replaced a datalist combobox, and the reason
   was not visual: a datalist stores what you TYPED, so the answer was a display
   name, and everything downstream that treats it as an identity — the § check
   on "you cannot sell what you do not own", the ejerbogspostering, the signer
   list — read nil in silence. The control posts a stakeholder id now, and the
   list has to be good enough that nobody wants to type past it.

   Three sizes of the same thing: the standalone field, a row of a
   `stakeholder_list`, and a cell of a `table`. Only the last one changes shape.
   ══════════════════════════════════════════════════════════════════════ */

.nt-wz-person {
  position: relative;
  max-width: 26rem;
}

/* A repeater row lays its picker and its remove button out with flex, and the
   picker is the part that should take the space — ALL of it: capped at 26rem
   the row stopped halfway across the composer and the dead right half read
   as a rendering fault. `.nt-repeat-row .nt-input` used to do this when the
   input WAS the row's child. */
.nt-repeat-row .nt-wz-person { flex: 1 1 auto; max-width: none; }

.nt-wz-person-input { width: 100%; }

/* THE LIST AND THE TRAY ARE POPOVERS, and that is the whole fix.

   They used to be `position: absolute` inside the field, which meant every
   scrolling ancestor clipped them: the composer's own control area cut the
   dropdown off two rows in, and a table's horizontal scroller cut it off at the
   bottom edge of the grid. There was a class that made the grid stop clipping
   while a picker was open; it fixed one container and could never fix the rest.

   A `[popover]` paints in the browser's TOP LAYER, which no ancestor can clip
   at any depth. The UA gives popovers `position: fixed` and a border and
   padding of its own, so the coordinates are the viewport's — set by
   wizard_person_controller from the input's rectangle, flipping above the box
   when the tray it lives in sits at the bottom of the screen. */
.nt-wz-person-list,
.nt-wz-person-tray {
  position: fixed;
  inset: auto;
  /* The search box's own width, published by the controller. */
  min-width: var(--nt-person-anchor-width, 12rem);
  z-index: var(--nt-z-dropdown);
  max-height: 15rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  margin: 0;
  padding: 0.25rem;
  background: var(--nt-surface-overlay);
  border: 1px solid var(--nt-border-subtle);
  border-radius: var(--nt-radius);
  box-shadow: var(--nt-shadow-3);
}

.nt-wz-person-list { list-style: none; }

.nt-wz-person-option {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.45rem 0.55rem;
  border-radius: var(--nt-radius-sm);
  cursor: pointer;
}

/* Initials, so a list of five Danish names reads as PEOPLE and not as text.
   Rendered by the partial and mirrored in #addOption. */
.nt-wz-person-avatar {
  flex: none;
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: var(--nt-radius-full);
  background: var(--nt-surface-sunken);
  color: var(--nt-text-secondary);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.nt-wz-person-avatar-new {
  background: color-mix(in srgb, var(--nt-seal) 10%, var(--nt-surface));
  color: var(--nt-seal-text);
}

/* Hover and keyboard land on the SAME mark. A dropdown where the mouse lights
   one row and the arrow keys light another is a dropdown you cannot trust. */
.nt-wz-person-option:hover,
.nt-wz-person-option.nt-wz-person-active {
  background: var(--nt-surface-sunken);
}

.nt-wz-person-name {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--nt-text);
  font-size: var(--nt-text-sm);
  overflow-wrap: anywhere;
}

/* "Kapitalejer", "Direktør" — the line that makes five Danish names
   choosable. The same human can be both, and the customer picking a dirigent
   needs to see which record they are pointing at. */
.nt-wz-person-role {
  flex: none;
  color: var(--nt-text-tertiary);
  font-size: var(--nt-text-xs);
}

.nt-wz-person-none {
  padding: 0.4rem 0.55rem;
  color: var(--nt-text-tertiary);
  font-size: var(--nt-text-xs);
}

/* Creating a person is a real write, so it does not look like one more name on
   the list. Seal-toned and set apart, the way every other "this does
   something" affordance in the wizard is. */
.nt-wz-person-new {
  margin-top: 0.2rem;
  border-top: 1px solid var(--nt-border-subtle);
  border-radius: 0 0 var(--nt-radius-sm) var(--nt-radius-sm);
  padding-top: 0.5rem;
  color: var(--nt-seal-text);
}

.nt-wz-person-new .nt-wz-person-name { color: var(--nt-seal-text); }

.nt-wz-person-error {
  margin-top: var(--nt-space-1);
  color: var(--nt-danger-text);
  font-size: var(--nt-text-xs);
}

/* ── the tray: a new person, and everything we need about them ───────── */

/* Minting a person used to be one POST of one name, and the person came out
   with no e-mail — so the signing round later filed them under "vi mangler en
   e-mail" and somebody had to go back and find them. The tray asks once, here,
   while the customer is thinking about that human anyway. */
/* `display` ONLY WHEN OPEN. The UA sheet closes a popover with
   `[popover]:not(:popover-open) { display: none }`, and any author `display`
   outranks it — a bare `.nt-wz-person-tray { display: grid }` left the whole
   tray sitting open on the screen from the moment the page loaded. */
.nt-wz-person-tray:popover-open {
  display: grid;
  gap: var(--nt-space-3);
  padding: var(--nt-space-4);
  min-width: max(19rem, var(--nt-person-anchor-width, 19rem));
}

/* A card, not a fragment: floating over the composer with the composer's own
   surface and a hairline border, the tray read as a stray rectangle. */
.nt-wz-person-tray {
  border-radius: var(--nt-radius-lg);
  box-shadow: var(--nt-shadow-3), 0 18px 44px -18px rgb(15 12 8 / 0.3);
}

.nt-wz-person-tray-title {
  margin: 0;
  font-family: var(--nt-font-display);
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--nt-text);
}

/* Person or virksomhed. Only rendered where the PACK says a selskab may answer
   the question — a stifter may be a holdingselskab, a direktør may not. */
.nt-wz-person-kinds {
  display: flex;
  gap: 0.25rem;
  padding: 0.15rem;
  background: var(--nt-surface-sunken);
  border-radius: var(--nt-radius-sm);
}

.nt-wz-person-kind {
  flex: 1;
  padding: 0.38rem 0.5rem;
  border: 0;
  border-radius: calc(var(--nt-radius-sm) - 0.1rem);
  background: transparent;
  color: var(--nt-text-secondary);
  font: inherit;
  font-size: var(--nt-text-sm);
  cursor: pointer;
}

.nt-wz-person-kind[aria-pressed="true"] {
  background: var(--nt-surface);
  box-shadow: var(--nt-shadow-1);
  color: var(--nt-text);
}

.nt-wz-person-row {
  display: grid;
  gap: 0.2rem;
}

.nt-wz-person-row-label {
  color: var(--nt-text-secondary);
  font-size: var(--nt-text-xs);
}

/* What the register answered, under the CVR box. */
.nt-wz-person-note {
  color: var(--nt-text-tertiary);
  font-size: var(--nt-text-xs);
  min-height: 1em;
}

.nt-wz-person-hint {
  margin: 0;
  color: var(--nt-text-tertiary);
  font-size: var(--nt-text-xs);
}

.nt-wz-person-actions {
  display: flex;
  gap: var(--nt-space-2);
  justify-content: flex-end;
}

/* ── inside a table cell ─────────────────────────────────────────────── */

.nt-wz-person-compact { max-width: none; min-width: 11rem; }
/* A table cell is narrower than a list of Danish names can be read in, so the
   cell's own width is a floor and not the answer. */
.nt-wz-person-compact .nt-wz-person-list { min-width: max(13rem, var(--nt-person-anchor-width, 13rem)); }

@media (prefers-reduced-motion: reduce) {
  .nt-wz-person-list { animation: none; }
}
