/*
 * ════════════════════════════════════════════════════════════════════════
 *  THE WIZARD — stepper, read-ahead, and the "your answer landed" signals
 * ════════════════════════════════════════════════════════════════════════
 *
 * Companion to section 26b of notarium.css, which owns the two-pane layout,
 * the field controls, the hard stop, the hand-off and the beslutning. This
 * file owns only what the wizard-experience pass added, and it is deliberately
 * a separate sheet: nothing here redeclares an `.nt-*` component the design
 * system already defines, so the two can never quietly fight over one
 * animation the way `.nt-doc-flash` once did. Everything new is namespaced
 * `.nt-wz-*`.
 *
 * Load order is alphabetical under Propshaft's bulk `stylesheet_link_tag :app`,
 * which puts this sheet last — after notarium.css and after Tailwind. So the
 * two rules below that DO reach an existing class (`.nt-autosave`) win on
 * equal specificity, with no `!important` anywhere.
 *
 * Every custom property referenced here is defined in notarium.css section 1–3.
 * An undefined `var(--nt-…)` invalidates the whole declaration and does not
 * fall back, so nothing is invented locally.
 */

/* ══════════════════════════════════════════════════════════════════════
   1. THE STEPPER

   One component where there used to be four indicators of the same number:
   a counter sentence, a percentage, a bar, and a rail of chips. What is left
   is the rail — sitting on a spine whose filled length IS the bar — plus a
   compact "5/11" for anyone who wants the figure. The counter sentence is not
   gone; it moved to the progressbar's `aria-valuetext`, which is where a
   screen reader was always going to look for it.
   ══════════════════════════════════════════════════════════════════════ */

.nt-wz-stepper {
  background: var(--nt-surface);
  border: 1px solid var(--nt-border-subtle);
  border-radius: var(--nt-radius-lg);
  padding: var(--nt-space-3) var(--nt-space-4);
}

.nt-wz-stepper-row {
  display: flex;
  align-items: center;
  gap: var(--nt-space-4);
  min-width: 0;
}

/* The rail scrolls rather than wraps. Eleven chips on two lines cannot sit on
   a spine, and the spine is the whole reason this reads as one component
   instead of a bag of pills. The current chip is scrolled into view by
   wizard_progress_controller, so the scroll is never the customer's problem. */
.nt-wz-rail {
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--nt-border) transparent;
  padding-block: var(--nt-space-1);
}

/* The edges fade only when there is something past them. CSS cannot ask
   "does this overflow", so the controller stamps the answer — without it the
   fade would sit permanently on a six-step wizard that fits, and a fade over
   nothing reads as a rendering fault rather than as "there is more". */
.nt-wz-rail[data-overflow="true"] {
  mask-image: linear-gradient(
    to right,
    transparent 0,
    #000 1.5rem,
    #000 calc(100% - 1.5rem),
    transparent 100%
  );
}

/* `width: max-content` is load-bearing: the spine is positioned against THIS
   box, and a block child of a scroller is only as wide as the window onto it.
   Without the inner wrapper the bar would stop at the visible edge and drift
   away from the chips it is measuring the moment the rail overflows. */
.nt-wz-rail-inner {
  position: relative;
  width: max-content;
  min-width: 100%;
}

.nt-wz-spine {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 2px;
  transform: translateY(-50%);
  border-radius: var(--nt-radius-full);
  background: var(--nt-border-subtle);
  overflow: hidden;
}

/* The one moving pixel in this product that does real work: it says "you
   moved". Width is set from JavaScript in two frames — see the comment in
   wizard_progress_controller.js for why a fresh node cannot transition. */
.nt-wz-spine-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: var(--nt-seal);
  transition: width var(--nt-duration-slow) var(--nt-ease);
}

.nt-wz-steps {
  position: relative;
  display: flex;
  align-items: center;
  /* Wide enough that the spine reads as a rail CONNECTING the steps. Any
     tighter and the visible segments shrink to specks between two pills. */
  gap: 0.55rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nt-wz-step { flex: none; display: flex; }

.nt-wz-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  max-width: 12rem;
  padding: 0.22rem 0.7rem 0.22rem 0.22rem;
  border: 1px solid var(--nt-border-subtle);
  border-radius: var(--nt-radius-full);
  /* Opaque, so the spine reads as a line CONNECTING the steps rather than a
     line drawn through them. */
  background: var(--nt-surface);
  color: var(--nt-text-tertiary);
  font-size: var(--nt-text-xs);
  line-height: 1.35;
  text-decoration: none;
  white-space: nowrap;
  transition:
    background-color var(--nt-duration-fast) var(--nt-ease),
    border-color var(--nt-duration-fast) var(--nt-ease),
    color var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-chip-label {
  overflow: hidden;
  text-overflow: ellipsis;
}

.nt-wz-chip-mark {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.3rem;
  height: 1.3rem;
  border: 1px solid var(--nt-border-subtle);
  border-radius: var(--nt-radius-full);
  background: var(--nt-surface-sunken);
  color: var(--nt-text-tertiary);
  font-family: var(--nt-font-mono);
  font-size: 0.62rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ── done: settled, and green means "i orden" everywhere in this product ── */
.nt-wz-step[data-state="done"] .nt-wz-chip { color: var(--nt-text-secondary); }

.nt-wz-step[data-state="done"] .nt-wz-chip-mark {
  background: var(--nt-ok);
  border-color: transparent;
  color: var(--nt-on-ok);
}

/* ── next: the question still owed an answer. Named, not shouted. ───────── */
.nt-wz-step[data-state="next"] .nt-wz-chip {
  border-color: var(--nt-seal-border);
  color: var(--nt-seal-text);
}

.nt-wz-step[data-state="next"] .nt-wz-chip-mark {
  background: var(--nt-seal-soft);
  border-color: var(--nt-seal-border);
  color: var(--nt-seal-text);
}

/* ── ahead: readable, not yet answerable. Dashed says "open, but not solid
      ground yet" without borrowing the disabled grey, which would read as
      "you cannot go there" — and you can. ─────────────────────────────── */
.nt-wz-step[data-state="ahead"] .nt-wz-chip { border-style: dashed; }

/* Opaque, like every other chip. A transparent one lets the spine run straight
   through the label and the step reads as struck out — which is the one thing
   a readable-but-not-yet-answerable step must not look like. */
.nt-wz-step[data-state="ahead"] .nt-wz-chip-mark {
  background: var(--nt-surface);
  border-style: dashed;
}

/* ── here: the one saturated moment on the rail ────────────────────────── */
.nt-wz-step[data-state="here"] .nt-wz-chip {
  background: var(--nt-seal);
  border-color: var(--nt-seal);
  color: var(--nt-on-seal);
  font-weight: 600;
  box-shadow: var(--nt-shadow-1);
}

.nt-wz-step[data-state="here"] .nt-wz-chip-mark {
  background: color-mix(in srgb, var(--nt-on-seal) 22%, transparent);
  border-color: transparent;
  color: var(--nt-on-seal);
}

/* Here AND ahead of the first unanswered question: you are standing on a step
   you can read but not answer. Outlined rather than filled — the seal is
   reserved for where the work actually is. */
.nt-wz-step[data-state="here"][data-ahead="true"] .nt-wz-chip {
  background: var(--nt-seal-soft);
  border: 1px dashed var(--nt-seal);
  color: var(--nt-seal-text);
  box-shadow: none;
}

.nt-wz-step[data-state="here"][data-ahead="true"] .nt-wz-chip-mark {
  background: var(--nt-surface);
  border: 1px solid var(--nt-seal-border);
  color: var(--nt-seal-text);
}

a.nt-wz-chip:hover {
  border-color: var(--nt-border-strong);
  color: var(--nt-text);
}

a.nt-wz-chip:hover .nt-wz-chip-mark { border-color: var(--nt-border-strong); }

/* ── the figure ─────────────────────────────────────────────────────────
   Hidden from screen readers on purpose: the progressbar beside it already
   says "Trin 5 af 11" in words, and a mono "5/11" read out as "five slash
   eleven" is noise on top of it. */
.nt-wz-count {
  flex: none;
  margin: 0;
  font-family: var(--nt-font-mono);
  font-size: var(--nt-text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--nt-text-tertiary);
}

.nt-wz-count-now { color: var(--nt-text); font-weight: 600; }
.nt-wz-count-of { opacity: 0.75; }

/* ── the live note ──────────────────────────────────────────────────────
   "Ét spørgsmål faldt væk — jeres svar gjorde det overflødigt." Collapsed to
   nothing until there is something true to say, so the card does not carry a
   permanently empty line. */
.nt-wz-note {
  margin: 0;
  font-size: var(--nt-text-xs);
  color: var(--nt-text-tertiary);
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transition:
    opacity var(--nt-duration) var(--nt-ease),
    max-height var(--nt-duration) var(--nt-ease),
    margin-top var(--nt-duration) var(--nt-ease);
}

.nt-wz-note[data-state="shown"] {
  opacity: 1;
  max-height: 3rem;
  margin-top: var(--nt-space-2);
}

/* ══════════════════════════════════════════════════════════════════════
   2. READING AHEAD

   Every step is reachable, including the ones past the first unanswered
   question. What a read-ahead cannot do is take answers — a later screen's
   prefills and predicates are computed from the earlier ones — so the fields
   arrive inside a `disabled` fieldset and the footer offers the way back
   instead of "Næste".

   This is NOT an error state. Nothing is red, nothing is a warning triangle:
   the customer did a reasonable thing (looked at what is coming) and is being
   told where the work is.
   ══════════════════════════════════════════════════════════════════════ */

.nt-wz-peek {
  display: flex;
  align-items: flex-start;
  gap: var(--nt-space-3);
  margin-bottom: var(--nt-space-5);
  padding: var(--nt-space-3) var(--nt-space-4);
  border: 1px solid var(--nt-info-border);
  border-radius: var(--nt-radius);
  background: var(--nt-info-soft);
}

.nt-wz-peek-icon { flex: none; margin-top: 0.1rem; color: var(--nt-info); }
.nt-wz-peek-title { font-weight: 600; color: var(--nt-info-text); }

.nt-wz-peek-body {
  margin-top: 0.15rem;
  font-size: var(--nt-text-sm);
  color: var(--nt-text-secondary);
}

/* One fieldset around every field, rather than a `disabled:` on each of the
   twelve control types — the HTML rule reaches every descendant, including the
   controls nested inside a field's own fieldset, and it cannot be forgotten
   when the pack grows a new type. */
.nt-wz-fields {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}

.nt-wz-fields:disabled {
  opacity: 0.6;
  /* Readable, not greyed out of legibility: the point of a read-ahead is that
     you can READ it. */
  filter: saturate(0.7);
}

.nt-wz-fields:disabled * { cursor: default; }

/* ══════════════════════════════════════════════════════════════════════
   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); }
}

/* A zero-height sticky strip. The chip hangs off it over the top edge of the
   sheet and never occupies layout, because a document that jumps a line every
   time you answer is its own kind of blink.

   It sticks BELOW the pane's own bar (the document tabs and the zoom toggle),
   which is the only thing above it — both are sticky at the top of the same
   scroller, and two things pinned to `top: 0` is one thing hidden. */
.nt-wz-pulse-slot {
  position: sticky;
  top: var(--nt-doc-bar-h, 0px);
  z-index: 2;
  height: 0;
  display: flex;
  justify-content: flex-end;
  /* Held off the pane's right edge, which is also a rounded corner and a
     scrollbar gutter — a chip flush against it reads as clipped. */
  padding-right: 0.75rem;
  pointer-events: none;
}

.nt-wz-pulse {
  position: relative;
  top: 0.5rem;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin: 0;
  padding: 0.22rem 0.7rem;
  border: 1px solid var(--nt-ok-border);
  border-radius: var(--nt-radius-full);
  background: var(--nt-ok-soft);
  color: var(--nt-ok-text);
  font-size: var(--nt-text-xs);
  font-weight: 600;
  box-shadow: var(--nt-shadow-2);
  opacity: 0;
  transform: translateY(-6px);
  transition:
    opacity var(--nt-duration) var(--nt-ease),
    transform var(--nt-duration) var(--nt-ease);
}

.nt-wz-pulse[data-state="shown"] { opacity: 1; transform: none; }

/* ── "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);
}

/* ══════════════════════════════════════════════════════════════════════
   4. "HVORFOR SPØRGER VI?"

   The pack's legal note, folded away behind the question it answers.

   It is a real <details>, not a JavaScript disclosure: the browser gives us
   the open/closed state, the keyboard, the ARIA and — on a print or a
   find-in-page — the content, for nothing. What is styled here is only the
   <summary>, into a quiet text button rather than the OS triangle.

     <details class="nt-wz-why">
       <summary>Hvorfor spørger vi?</summary>
       <p class="nt-hint">…legal_note_da…</p>
     </details>

   Closed, it is one line of secondary text under the question. Open, the body
   is the same `.nt-hint` paragraph it has always been — nothing about the note
   changes, only whether the customer asked for it. A paragraph of statute
   permanently under every screen turns a wizard into a law textbook.
   ══════════════════════════════════════════════════════════════════════ */

.nt-wz-why { margin-top: var(--nt-space-2); }

/* `display` other than `list-item` is what actually removes the marker in
   Chrome; `list-style: none` covers Firefox and the ::marker rule below
   covers the rest. All three, because a stray triangle beside a drawn chevron
   is two disclosure affordances on one control. */
.nt-wz-why > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  width: fit-content;
  padding: 0.15rem 0;
  color: var(--nt-text-secondary);
  font-size: var(--nt-text-xs);
  line-height: 1.4;
  cursor: pointer;
  list-style: none;
  user-select: none;
  transition: color var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-why > summary::-webkit-details-marker { display: none; }
.nt-wz-why > summary::marker { content: ""; }

.nt-wz-why > summary:hover,
.nt-wz-why[open] > summary { color: var(--nt-text); }

/* The chevron is drawn from two borders rather than an icon: this summary is
   only ever handed a string of Danish by the view, so the affordance has to
   come from the stylesheet. */
.nt-wz-why > summary::after {
  content: "";
  flex: none;
  width: 0.38rem;
  height: 0.38rem;
  margin-top: -0.16rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--nt-duration) var(--nt-ease);
}

.nt-wz-why[open] > summary::after {
  margin-top: 0.1rem;
  transform: rotate(-135deg);
}

/* Room between the summary and whatever it unfolded. (0,1,1) beats `.nt-hint`
   at (0,1,0), and this sheet loads after notarium.css either way. */
.nt-wz-why > :not(summary) { margin-top: var(--nt-space-2); }

/* ══════════════════════════════════════════════════════════════════════
   4b. THE VERTICAL RAIL — the same stepper, standing up

   Above 80rem of workspace column the horizontal strip of chips becomes a
   list beside the question. Nothing about the markup changes: the ORIENTATION
   IS ENTIRELY CSS, which is what lets the mobile sheet reuse the identical
   rule set from its own breakpoint later, and what lets
   wizard_progress_controller decide which axis to fill by reading the layout
   instead of guessing at a viewport width a container query never mentions.
   ══════════════════════════════════════════════════════════════════════ */

/* The event heading inside the rail — "Ordinær generalforsamling", "Udbytte".
   Hidden by default: on a horizontal strip a group label wedged between two
   chips is noise, not structure. It earns its place only in the list. */
.nt-wz-group-label { display: none; }

@container (min-width: 80rem) {
  .nt-wz-stepper { padding: var(--nt-space-4); }

  .nt-wz-stepper-row {
    flex-direction: column;
    align-items: stretch;
    gap: var(--nt-space-3);
  }

  /* Nothing to scroll sideways any more, so the overflow fade — which is a
     mask, and would clip the left edge of every chip — comes off. */
  .nt-wz-rail,
  .nt-wz-rail[data-overflow="true"] {
    overflow: visible;
    mask-image: none;
    padding-block: 0;
  }

  .nt-wz-rail-inner { width: auto; }

  .nt-wz-steps {
    flex-direction: column;
    align-items: stretch;
    gap: 0.4rem;
  }

  .nt-wz-chip {
    max-width: none;
    width: 100%;
    justify-content: flex-start;
  }

  /* The chip label may wrap to two lines here — there is a column of room for
     it, and a truncated "Godkendelse af årsrappo…" beside the question is a
     worse trade than one extra line. */
  .nt-wz-chip-label { white-space: normal; overflow: visible; }

  /* The spine turns 90°: a 2px column running down through the middle of the
     chip marks — 1px border + 0.22rem of chip padding + half of the 1.3rem
     mark — filled from the TOP by the controller writing `height`. */
  .nt-wz-spine {
    left: 0.93rem;
    right: auto;
    top: 0.4rem;
    bottom: 0.4rem;
    width: 2px;
    height: auto;
    transform: none;
  }

  .nt-wz-spine-fill {
    width: 100%;
    height: 0;
    transition: height var(--nt-duration-slow) var(--nt-ease);
  }

  .nt-wz-group-label {
    display: block;
    margin: var(--nt-space-3) 0 0.1rem 1.9rem;
    font-size: var(--nt-text-xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--nt-text-tertiary);
  }

  .nt-wz-group-label:first-child { margin-top: 0; }

  /* The count moves above the list, where it reads as a heading for it rather
     than as a figure trailing off the end of a column. */
  .nt-wz-count { order: -1; align-self: flex-start; }
}

/* ══════════════════════════════════════════════════════════════════════
   4c. THE PANE'S BAR — which document, and how big

   Two controls that belong to the PANE rather than to the document: the tabs
   (only when a run produces more than one document) and zoom-to-fit. They sit
   inside the swapped frame, because the tab list is answer-dependent — see the
   comment in _preview.html.erb.
   ══════════════════════════════════════════════════════════════════════ */

.nt-doc-pane {
  /* What .nt-wz-pulse-slot sticks below. One number, declared where both the
     bar and the chip can read it. */
  --nt-doc-bar-h: 2.9rem;
}

.nt-doc-bar {
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--nt-space-2);
  min-height: var(--nt-doc-bar-h);
  padding-bottom: var(--nt-space-2);
  /* Opaque: the paper scrolls underneath it. */
  background: var(--nt-bg);
}

/* Each tab is its own little form (button_to), so the segmented control's
   children are forms rather than labels. `display: contents` puts the buttons
   back where .nt-segmented expects them. */
.nt-doc-tabs { flex-wrap: wrap; }
.nt-doc-tab { display: contents; }

.nt-doc-tab > .nt-segment-face {
  border: 0;
  background: transparent;
  font-family: inherit;
  cursor: pointer;
  min-width: 0;
  padding: 0.34rem 0.8rem;
  font-size: var(--nt-text-sm);
}

.nt-doc-tab > .nt-segment-face[aria-pressed="true"] {
  background: var(--nt-surface);
  color: var(--nt-text);
  box-shadow: var(--nt-shadow-1);
}

.nt-doc-tab > .nt-segment-face:focus-visible { box-shadow: var(--nt-shadow-focus); }

.nt-doc-zoom {
  margin-left: auto;
  padding: 0.3rem 0.6rem;
  border: 1px solid transparent;
  border-radius: var(--nt-radius-sm);
  background: transparent;
  color: var(--nt-text-tertiary);
  font-family: inherit;
  font-size: var(--nt-text-xs);
  cursor: pointer;
}

.nt-doc-zoom:hover { color: var(--nt-text); border-color: var(--nt-border-subtle); }
.nt-doc-zoom:focus-visible { box-shadow: var(--nt-shadow-focus); }

/* ══════════════════════════════════════════════════════════════════════
   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-wizard-paper[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;
}

/* ══════════════════════════════════════════════════════════════════════
   5. REDUCED MOTION

   Not "turn it off" — "arrive already finished". The change bar and the chip
   still HAPPEN: "which paragraph did my answer just change" and "it saved" are
   information, not decoration, and a reader who asked for less motion still
   needs both. What goes is the travel: nothing slides, nothing grows, and the
   spine lands on its value instead of running to it.
   ══════════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  /* Both axes: the rail is horizontal above the question and vertical beside
     it, and the spine transitions whichever one it is filling. */
  .nt-wz-spine-fill { transition: none; }
  .nt-wz-why > summary::after { transition: none; }
  .nt-wz-rail { scroll-behavior: auto; }
  .nt-wz-pulse { transform: none; }

  /* 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
     600 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. `.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; }

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

.nt-wz-person-list {
  position: absolute;
  z-index: var(--nt-z-dropdown);
  top: calc(100% + 0.3rem);
  left: 0;
  right: 0;
  max-height: 15rem;
  overflow-y: auto;
  margin: 0;
  padding: 0.25rem;
  list-style: none;
  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-option {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--nt-space-3);
  padding: 0.4rem 0.55rem;
  border-radius: var(--nt-radius-sm);
  cursor: pointer;
}

/* 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 {
  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);
}

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

.nt-wz-person-compact { max-width: none; min-width: 11rem; }
.nt-wz-person-compact .nt-wz-person-list { min-width: 13rem; }

/* THE GRID STOPS CLIPPING WHILE A PICKER IS OPEN.
   `.nt-grid-scroll` scrolls sideways, and an element that scrolls on one axis
   clips the other — which cut the dropdown off at the bottom edge of the
   fordeling. wizard_person_controller toggles this class for exactly as long as
   the list is showing; losing horizontal scroll for those few seconds is the
   cheaper trade than a list you cannot see. */
.nt-grid-scroll.nt-wz-person-spill { overflow: visible; }

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