/* ══════════════════════════════════════════════════════════════════════════
   THE COMPOSER — the wizard as a conversation that writes a document

   Three parts, one argument: a rail at the top that says where you are, a
   sheet of paper in the middle that IS the product, and a floating tray at
   the bottom that holds one question at a time.

   ONE DESIGN AT EVERY VIEWPORT, AND CSS OWNS THE HEIGHT. The tray is
   `height: auto` under two static caps (plain / roomy) and the controller
   only folds it — see the header of wizard_composer_controller.js for why
   the JS-owned detent machinery died. What changes with the viewport is only
   dressing: edge-to-edge with safe-area padding below ~40rem, a floating
   rounded tray above.

   WHY THIS IS ITS OWN FILE. Propshaft loads the stylesheets alphabetically
   under the bulk `stylesheet_link_tag :app` (shared/_head), so
   `wizard_composer.css` lands after `notarium.css`, `navbar.css` and
   `wizard.css` and wins ties without a single `!important`.

   Sections:
     1. The focus surface — what the wizard hides while it is on screen
     2. The rail
     3. The paper
     4. The composer: the tray, its fold, its two rows
     5. The controls inside it
     6. The document's own ink — anchors, targets, live slots
     7. The review and the commit bar
     8. Narrow viewports
     9. Reduced motion
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════
   1. THE FOCUS SURFACE
   ══════════════════════════════════════════════════════════════════════ */

/* THE WIZARD REPLACES THE NAVBAR. Two bars of chrome over a sheet of A4 is
   one bar too many, and the rail already carries the brand, the selskab, the
   event and the way out — which is everything the navbar was doing here.

   Done with `:has()` rather than a body class, because the layout is shared
   with forty other screens and none of them should have to know that a wizard
   exists. */
body.nt-app:has(.nt-wz) > .nt-navbar,
body.nt-app:has(.nt-wz) > .nt-mobile-scrim,
body.nt-app:has(.nt-wz) > .nt-mobile-panel { display: none; }

/* The page container gives up its measure and its padding: the stage is the
   viewport, and the paper centres itself inside it. */
body.nt-app:has(.nt-wz) > .nt-app-main { padding: 0; overflow-x: visible; }

.nt-app-column:has(.nt-wz) { max-width: none; margin: 0; }

/* The chat launcher stays in the BOTTOM RIGHT CORNER, wizard or no wizard.
   It used to be lifted 8.5rem "out of the resting tray's way" — but the tray
   is centred at 52rem and fits its content now, so the lift just parked the
   bubble in mid-air beside the tray's middle. The corner is where every chat
   bubble on the internet lives; at the rare width where the tray's corner and
   the bubble overlap, the bubble's higher z-index keeps it clickable. */

.nt-wz {
  --nt-wz-rail-h: 3rem;
  /* The paper's measure, and the composer's. They are the same number on
     purpose: a tray narrower than the sheet reads as a widget floating over a
     document, and a tray as wide as the sheet reads as the document's own
     writing surface. */
  --nt-wz-measure: 52rem;

  /* THERE ARE NO DETENTS. The tray is `height: auto` under the caps below —
     the stylesheet owns the height entirely, and the controller only folds.
     This token is the PAPER'S clearance: the stage keeps this much room at
     the bottom so the last clause of a document can be scrolled clear of the
     tallest tray a roomy screen can stand. */
  --nt-wz-clearance: min(82dvh, 46rem);

  position: relative;
  min-height: 100dvh;
  background: var(--nt-bg);
}

/* ══════════════════════════════════════════════════════════════════════
   2. THE RAIL
   ══════════════════════════════════════════════════════════════════════ */

.nt-wz-rail {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 40;
  height: var(--nt-wz-rail-h);
  display: flex;
  align-items: center;
  gap: var(--nt-space-5);
  padding: 0 var(--nt-space-4);
  /* Translucent over the paper, so the sheet visibly runs UNDER the rail
     rather than stopping at it. The document is the page; the rail is glass
     laid on top. */
  background: color-mix(in oklab, var(--nt-surface) 88%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--nt-border-subtle);
}

.nt-wz-brand {
  display: flex;
  align-items: center;
  gap: var(--nt-space-2);
  flex: none;
  min-width: 0;
  color: inherit;
  text-decoration: none;
  /* A hover pill, so the cluster reads as the LINK it is — the wizard felt
     like a surface you could not leave (Marcus). The negative margin keeps
     the mark optically where it stood before the padding. */
  padding: 0.3rem 0.55rem 0.3rem 0.4rem;
  margin-left: -0.4rem;
  border-radius: var(--nt-radius);
  transition: background var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-brand:hover { background: var(--nt-bg-accent); }

.nt-wz-brand:hover .nt-wz-brand-event { color: var(--nt-seal); }

/* The chevron says "back" before anybody hovers; on hover it leans out. */
.nt-wz-brand-back {
  display: grid;
  place-items: center;
  color: var(--nt-text-tertiary);
  transition: color var(--nt-duration-fast) var(--nt-ease),
              transform var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-brand:hover .nt-wz-brand-back { color: var(--nt-seal); transform: translateX(-2px); }

.nt-wz-brand-text { display: grid; min-width: 0; line-height: 1.15; }

.nt-wz-brand-event {
  font-size: var(--nt-text-sm);
  font-weight: 600;
  letter-spacing: 0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-brand-company {
  font-size: 0.66rem;
  color: var(--nt-text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── the track ──────────────────────────────────────────────────────────── */

/* The region's slot in the rail ROW now holds only the jump ("4/12 · Dirigent
   ▾"); the trail itself hangs below the rail's edge. */
.nt-wz-track {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
}

/* TRUE CENTRE, not flex-slot centre. The brand and the right-hand controls
   are different widths, so centring inside the leftover slot put the jump —
   and visually its popover, which is fixed at 50vw — off the document's own
   axis. Absolute against the fixed rail, the trigger, the popover and the
   paper all share one centreline. */
.nt-wz-jump {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  max-width: min(24rem, 40vw);
}

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

/* THE TRAIL — the progress strip, hugging the rail's bottom border edge to
   edge. Absolutely positioned against the fixed rail (the header is its
   containing block), so it spans the viewport whatever the region's flex slot
   measures. One button: the whole strip opens the step list, and the padding
   grows the 4px paint into a findable target. */
.nt-wz-trail {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  display: flex;
  gap: 2px;
  height: 4px;
  padding: 0 0 6px; /* invisible hit area below the paint */
  box-sizing: content-box;
  background: none;
  border: 0;
  cursor: pointer;
}

.nt-wz-trail:focus-visible { outline: none; box-shadow: var(--nt-shadow-focus); }

/* A breath of presence on approach: the strip thickens under the pointer. */
.nt-wz-trail:hover .nt-wz-seg { transform: scaleY(1.5); }

.nt-wz-seg {
  flex: 1;
  height: 4px;
  transform-origin: top;
  background: var(--nt-border-subtle);
  transition: background var(--nt-duration-slow) var(--nt-ease),
              box-shadow var(--nt-duration-slow) var(--nt-ease),
              transform var(--nt-duration-fast) var(--nt-ease);
}

/* The strip's outer corners follow the viewport, not each segment. */
.nt-wz-seg:first-child { border-radius: 0 0 0 2px; }
.nt-wz-seg:last-child { border-radius: 0 0 2px 0; }

.nt-wz-seg[data-state="done"] { background: var(--nt-seal); opacity: 0.85; }

/* The one saturated moment on the trail: "you are here" glows softly below
   its own segment. */
.nt-wz-seg[data-state="here"] {
  background: var(--nt-seal);
  box-shadow: 0 2px 8px var(--nt-seal-tint), 0 1px 3px var(--nt-seal-border);
}

/* AMBER, NEVER RED. Red in this design system means overdue; a question you
   chose not to answer is not a failure. */
.nt-wz-seg[data-state="skipped"] { background: var(--nt-warn); opacity: 0.7; }

.nt-wz-seg[data-state="next"] { background: var(--nt-seal-border); }

/* Held back for its turn in the cascade — see wizard_progress_controller. */
.nt-wz-seg[data-state="pending"] { background: var(--nt-border-subtle); }

.nt-wz-jump {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.3rem 0.6rem;
  border: 0;
  border-radius: var(--nt-radius);
  background: transparent;
  color: var(--nt-text);
  font-family: var(--nt-font-body);
  font-size: var(--nt-text-sm);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--nt-duration-fast) var(--nt-ease);
}
.nt-wz-jump:hover, .nt-wz-jump[aria-expanded="true"] { background: var(--nt-surface-raised); }
.nt-wz-jump svg { color: var(--nt-text-secondary); }
.nt-wz-jump-count {
  font-family: var(--nt-font-mono);
  font-size: 0.66rem;
  font-weight: 500;
  color: var(--nt-text-secondary);
  font-variant-numeric: tabular-nums;
}
/* The tabs wrapper is a stream REGION, not a layout box. */
.nt-wz-tabs-region { display: contents; }

/* ── the step popover ───────────────────────────────────────────────────── */

.nt-wz-steps {
  position: fixed;
  top: calc(var(--nt-wz-rail-h) + 0.4rem);
  left: 50%;
  transform: translateX(-50%);
  width: min(26rem, calc(100vw - 2rem));
  max-height: 70dvh;
  overflow: auto;
  z-index: 50;
  padding: var(--nt-space-2);
  background: var(--nt-surface-overlay);
  border: 1px solid var(--nt-border-subtle);
  border-radius: var(--nt-radius-lg);
  box-shadow: var(--nt-shadow-3);
  animation: nt-wz-pop var(--nt-duration) var(--nt-ease) both;
}

@keyframes nt-wz-pop {
  from { opacity: 0; transform: translateX(-50%) translateY(-4px); }
  to { opacity: 1; transform: translateX(-50%) translateY(0); }
}

.nt-wz-steps-group {
  font-family: var(--nt-font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--nt-text-tertiary);
  padding: var(--nt-space-3) var(--nt-space-3) var(--nt-space-1);
  margin: 0;
}

.nt-wz-steps-list { list-style: none; margin: 0; padding: 0; }

.nt-wz-step-row {
  display: flex;
  align-items: flex-start;
  gap: var(--nt-space-3);
  width: 100%;
  padding: 0.45rem var(--nt-space-3);
  border-radius: var(--nt-radius);
  font-size: var(--nt-text-sm);
  color: var(--nt-text-secondary);
  text-decoration: none;
  text-align: left;
}

.nt-wz-step-row:hover { background: var(--nt-bg-accent); color: var(--nt-text); }
.nt-wz-step-row:focus-visible { outline: none; box-shadow: var(--nt-shadow-focus); }

.nt-wz-step-mark {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  margin-top: 0.1rem;
  border-radius: var(--nt-radius-full);
  border: 1.5px solid var(--nt-border);
  display: grid;
  place-items: center;
  font-size: 0.56rem;
  font-variant-numeric: tabular-nums;
  color: var(--nt-text-tertiary);
}

.nt-wz-step-label { display: block; font-weight: 600; color: var(--nt-text); }

/* The whole question, on the second line. This is the payoff for taking the
   names off the rail: there is room here to print what was being truncated. */
.nt-wz-step-question {
  display: block;
  font-size: var(--nt-text-xs);
  color: var(--nt-text-tertiary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

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

.nt-wz-step-row[data-state="here"] {
  background: var(--nt-seal-soft);
  color: var(--nt-text);
}

.nt-wz-step-row[data-state="here"] .nt-wz-step-mark {
  border-color: var(--nt-seal);
  color: var(--nt-seal);
}

.nt-wz-step-row[data-state="skipped"] .nt-wz-step-mark {
  border-color: var(--nt-warn);
  color: var(--nt-warn-text);
  border-style: dashed;
}

.nt-wz-step-row[data-state="ahead"] .nt-wz-step-mark { border-style: dashed; }

/* ── the rail's right-hand controls ─────────────────────────────────────── */

.nt-wz-rail-right { display: flex; align-items: center; gap: var(--nt-space-1); flex: none; }

/* THE DOCUMENT SELECTOR — a dropdown, not tabs. A stiftelse produces four
   documents; four segmented tabs ate the rail, and on a phone they were
   hidden outright. The trigger names the document on screen (the step jump's
   "name ▾" idiom); the menu drops DOWN from the fixed rail. */
.nt-wz-doc { position: relative; }

.nt-wz-doc-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.55rem;
  border: 0;
  border-radius: 0.45rem;
  background: none;
  color: var(--nt-text-secondary);
  font-size: var(--nt-text-xs);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-doc-trigger:hover,
.nt-wz-doc-trigger[aria-expanded="true"] { background: var(--nt-bg-accent); color: var(--nt-text); }
.nt-wz-doc-trigger:focus-visible { outline: none; box-shadow: var(--nt-shadow-focus); }

.nt-wz-doc-label {
  max-width: 11rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nt-wz-doc-menu {
  position: absolute;
  top: calc(100% + 0.45rem);
  right: 0;
  z-index: 50;
  min-width: 15rem;
  padding: var(--nt-space-1);
  background: var(--nt-surface-overlay);
  border: 1px solid var(--nt-border-subtle);
  border-radius: var(--nt-radius-lg);
  box-shadow: var(--nt-shadow-3);
  animation: nt-wz-doc-in var(--nt-duration) var(--nt-ease) both;
}

@keyframes nt-wz-doc-in {
  from { opacity: 0; translate: 0 -4px; }
  to { opacity: 1; translate: 0 0; }
}

.nt-wz-doc-row { display: block; }

.nt-wz-doc-option {
  display: flex;
  align-items: center;
  gap: var(--nt-space-2);
  width: 100%;
  padding: 0.45rem var(--nt-space-3);
  border: 0;
  border-radius: var(--nt-radius);
  background: none;
  color: var(--nt-text-secondary);
  font-size: var(--nt-text-sm);
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}

.nt-wz-doc-option:hover { background: var(--nt-bg-accent); color: var(--nt-text); }
.nt-wz-doc-option:focus-visible { outline: none; box-shadow: var(--nt-shadow-focus); }
.nt-wz-doc-option[aria-current="true"] { color: var(--nt-text); font-weight: 600; }

/* The check column keeps the titles aligned whether or not a row carries
   the mark. */
.nt-wz-doc-mark { flex: none; width: 0.85rem; display: grid; place-items: center; color: var(--nt-seal); }

.nt-wz-zoom,
.nt-wz-close {
  display: inline-flex;
  align-items: center;
  gap: var(--nt-space-1);
  font-size: var(--nt-text-xs);
  font-weight: 500;
  color: var(--nt-text-tertiary);
  padding: 0.3rem 0.55rem;
  border: 0;
  border-radius: 0.45rem;
  background: none;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

.nt-wz-zoom:hover,
.nt-wz-close:hover { background: var(--nt-bg-accent); color: var(--nt-text); }
.nt-wz-zoom:focus-visible,
.nt-wz-close:focus-visible { outline: none; box-shadow: var(--nt-shadow-focus); }

/* "Deltagere" — the way to invite a medstifter, a revisor or an advokat into
   this one guide. Quiet, and only for a seat that may hand out a token
   (WizardParticipantPolicy delegates to WizardSessionPolicy#update?). */
.nt-wz-close .nt-wz-close-label { display: inline; }

/* THE WAY OUT. "Luk", with the X the rest of the system closes things with —
   everything is autosaved, so leaving is always safe and must always be
   findable. A hairline pill, so it reads as a control rather than as one
   more quiet word in a row of quiet words. */
.nt-wz-exit {
  border: 1px solid var(--nt-border-subtle);
  border-radius: var(--nt-radius-full);
  padding: 0.3rem 0.7rem;
  color: var(--nt-text-secondary);
}

.nt-wz-exit:hover { border-color: var(--nt-border); background: var(--nt-bg-accent); color: var(--nt-text); }

/* ══════════════════════════════════════════════════════════════════════
   3. THE PAPER — the page's only scroll surface
   ══════════════════════════════════════════════════════════════════════ */

.nt-wz-stage {
  position: fixed;
  inset: var(--nt-wz-rail-h) 0 0 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  display: flex;
  justify-content: center;
  /* Top: air under the rail. Bottom: room for the composer at its tallest
     resting height plus a margin, so the last clause of a document can still
     be scrolled clear of the tray. */
  padding: var(--nt-space-8) var(--nt-space-6) calc(var(--nt-wz-clearance) + var(--nt-space-8));
  background: var(--nt-bg);
}

/* The sheet takes the measure the composer takes. */
.nt-wz-stage .nt-doc-pane,
.nt-wz-stage .nt-doc-frame { width: 100%; max-width: var(--nt-wz-measure); }

.nt-wz-stage .nt-doc-frame { padding: 0; background: none; }

/* ══════════════════════════════════════════════════════════════════════
   4. THE COMPOSER
   ══════════════════════════════════════════════════════════════════════ */

.nt-wz-composer-wrap {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 45;
  display: flex;
  justify-content: center;
  /* The wrap does not take the pointer; the tray inside it does. Everything
     either side of the tray is document, and it stays clickable. */
  pointer-events: none;
  padding: 0 var(--nt-space-4) calc(var(--nt-space-4) + env(safe-area-inset-bottom, 0px));
  /* The document fades INTO the tray rather than being cut off by it. */
  background: linear-gradient(to top, var(--nt-bg) 22%, transparent);
  /* An on-screen keyboard shrinks the visual viewport without touching the
     layout one; --nt-wz-vv-shift is how much of the layout viewport it is
     standing on (written by the controller). */
  bottom: var(--nt-wz-vv-shift, 0px);
}

.nt-wz-composer {
  pointer-events: auto;
  position: relative; /* anchors the escalation band floating above the tray */
  width: 100%;
  max-width: var(--nt-wz-measure);
  display: flex;
  flex-direction: column;
  background: var(--nt-surface);
  border: 1px solid var(--nt-border-subtle);
  border-radius: var(--nt-radius-lg);
  box-shadow: var(--nt-shadow-3);
  /* NO overflow clip and NO paint containment here: the ⓘ why-popover and the
     person picker's suggestion list open OUTSIDE the tray's box (upward /
     downward), and clipping them at the tray edge cropped both. The only
     thing that must clip is the field body's own scrolling, and that clip
     lives on .nt-wz-composer-scroll. Rounded corners survive because every
     child is inset by the tray's own padding, not clipped by its border. */
  overflow: visible;

  /* CSS OWNS THE HEIGHT — `auto`, always. The controller flips `data-folded`
     and writes nothing else; the predecessor's JS-owned detents/probe/drag
     heights were three sources of truth, and every regression in the tray's
     history was two of them disagreeing. Do not reintroduce a height writer.

     The caps: a plain question may take at most ~40% of the viewport (the
     document is the page); only a screen the SERVER marked tall — a table, a
     list of people, the review, a refusal — earns the roomy cap. The
     viewport guard keeps the rail's strip and a breath of air above the tray
     at every screen size; --nt-wz-vv is the visual viewport when a keyboard
     stands on it. */
  height: auto;
  max-height: min(40dvh, 26rem, calc(var(--nt-wz-vv, 100dvh) - 9rem));
  contain: layout;
}

.nt-wz-composer:has([data-forces-full], .nt-stop) {
  max-height: min(82dvh, 46rem, calc(var(--nt-wz-vv, 100dvh) - 9rem));
}

/* ── THE FOLD ─────────────────────────────────────────────────────────────
   Two states, one attribute. `.nt-wz-fold` wraps everything under the head
   row (see _panel.html.erb): a one-track grid whose row animates 1fr ⇄ 0fr —
   the one way to animate "as tall as its content ⇄ gone" without measuring
   anything. The inner child must be allowed to shrink (min-height: 0) and
   clips what no longer fits. Folded, the tray is grip + question: a strip
   the whole of which folds back out on a click (surfaceClick). */
.nt-wz-fold {
  flex: 1 1 auto;
  display: grid;
  grid-template-rows: 1fr;
  /* The question row never collapses to a sliver while open. */
  min-height: 3.75rem;
  /* NO transition on the rows: interpolating 1fr ⇄ 0fr inside an auto-height
     grid froze in Chrome — the computed track lagged one state behind and
     the fold answered the PREVIOUS click. The snap is instant and always
     correct; the foldable's opacity fade below is the motion. */
}

.nt-wz-foldable {
  min-height: 0;
  overflow: clip;
  display: flex;
  flex-direction: column;
  transition: opacity var(--nt-duration) var(--nt-ease);
}

.nt-wz-composer[data-folded] .nt-wz-foldable { opacity: 0; }

.nt-wz-composer[data-folded] .nt-wz-fold {
  grid-template-rows: 0fr;
  min-height: 0;
}

.nt-wz-composer[data-folded] .nt-wz-head { padding-bottom: var(--nt-space-3); }
/* The chevron is the fold's compass: down while open (press to put the
   question away), up while folded (press to bring it back). */
.nt-wz-composer[data-folded] .nt-wz-grip-chevron { color: var(--nt-seal); }
.nt-wz-composer[data-folded] .nt-wz-grip-chevron svg { transform: rotate(180deg); }
/* On the review the head row is normally traded for the commit bar — but the
   commit bar folds away with the body, and a folded strip with no words is a
   strip nobody understands. Folded, the head speaks for the screen. */
.nt-wz-composer[data-folded] .nt-wz-form:has(.nt-wz-commit) > .nt-wz-head { display: flex; }

/* ── the grip ───────────────────────────────────────────────────────────── */

/* THE FOLD CONTROL IS A SMALL CIRCLE RIDING THE TRAY'S TOP EDGE, dead
   centre (Marcus) — half above the border, half below, the way a pull-tab
   sits on a sheet's rim. Absolute, so it costs no vertical space; the
   padded box around the visible circle is the hot zone a finger actually
   hits. `touch-action: none` so a thumb-flick on it reaches the pointer
   events instead of scrolling the page. (The composer's overflow is
   `visible` — see §3 — which is what lets the top half stand outside.) */
.nt-wz-grip {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  display: grid;
  place-items: center;
  padding: 0.3rem 0.7rem;
  touch-action: none;
  cursor: pointer;
}

.nt-wz-grip-handle {
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border: 1px solid var(--nt-border-subtle);
  background: var(--nt-surface);
  padding: 0;
  cursor: inherit;
  border-radius: var(--nt-radius-full);
  box-shadow: var(--nt-shadow-1);
  transition: background var(--nt-duration-fast) var(--nt-ease),
              box-shadow var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-grip:hover .nt-wz-grip-handle { background: var(--nt-bg-accent); box-shadow: var(--nt-shadow-2); }

.nt-wz-grip-handle:focus-visible { outline: none; box-shadow: var(--nt-shadow-focus); }

.nt-wz-grip-chevron {
  display: grid;
  place-items: center;
  color: var(--nt-text-tertiary);
  transition: color var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-grip-chevron svg { transition: transform var(--nt-duration) var(--nt-ease); }

.nt-wz-grip-handle:hover .nt-wz-grip-chevron { color: var(--nt-text); }

/* ── the scroll region ──────────────────────────────────────────────────── */

/* NOTHING SCROLLS OUT HERE. The question and the buttons are the two things
   that must never leave the screen — a customer looking at the fourth field of
   a screen still has to know what was asked and still has to be able to press
   Næste. So the outer wrapper only distributes height; the ONE scroll surface
   inside the composer is `.nt-wz-controls`, the field body itself.

   `min-height: 0` on every link in the chain: a flex item's default
   `min-height: auto` refuses to shrink below its content, which silently
   turns "the fields scroll" into "the composer grows past the viewport".

   `flex: 1 1 auto`, NOT `flex: 1` — the basis is the load-bearing third
   value. Under the auto-height composer a zero basis collapses the whole
   chain to nothing (this is why the old controller needed a measuring
   probe); basis auto sizes the tray to its content, and min-height: 0 still
   lets the chain shrink when the max-height cap binds. */
.nt-wz-composer-scroll {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  /* NO clip here either: the head row — and the ⓘ popover that opens UP from
     it — lives inside this wrapper, so an overflow: hidden at this level
     cropped the popover at the tray's top edge exactly like the composer's
     old clip did. The only things that scroll are .nt-wz-controls and the
     escalation band, and each carries its own overflow-y: auto. */
  overflow: visible;
}

/* #wizard-panel sits between the composer and the form and is the Turbo Stream
   target, so it cannot be removed from the chain — it passes the height
   through instead. */
.nt-wz-composer-scroll > #wizard-panel {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.nt-wz-form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.nt-wz-head { flex: none; }

/* ── the head row: count · question · autosave · why ────────────────────── */

.nt-wz-head {
  flex: none;
  display: flex;
  /* TOP-ALIGNED WITH ONE SHARED LINE BOX, not `baseline`: the count is a
     mono face whose baseline sits differently from the display face, and the
     ⓘ is a circle with no baseline at all — mixing them left every element
     at its own height (Marcus). --nt-wz-qline is the question's first-line
     box; the count adopts it and the circle centres on it, so the row reads
     as ONE line whatever the question's length. */
  --nt-wz-qline: calc(0.92rem * 1.35);
  align-items: flex-start;
  gap: var(--nt-space-2);
  /* Top: clears the lower arc of the fold circle straddling the tray's top
     border, so a long first line never runs under it. */
  padding: 1.05rem var(--nt-space-4) 0.3rem;
}

.nt-wz-qcount {
  flex: none;
  font-family: var(--nt-font-mono);
  font-size: 0.62rem;
  line-height: var(--nt-wz-qline);
  color: var(--nt-text-tertiary);
  font-variant-numeric: tabular-nums;
}

.nt-wz-question {
  /* Natural width, shrinkable: the ⓘ stands at the END of the sentence it
     explains, and the autosave whisper takes the leftover to the right. */
  flex: 0 1 auto;
  min-width: 0;
  margin: 0;
  font-family: var(--nt-font-body);
  font-size: 0.92rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.005em;
  color: var(--nt-text);
}

.nt-wz-question:focus-visible { outline: none; text-decoration: underline; text-underline-offset: 4px; }

.nt-wz-formal {
  font-family: var(--nt-font-mono);
  font-size: 0.55rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--nt-text-tertiary);
  margin-right: var(--nt-space-2);
}

.nt-wz-head .nt-autosave {
  flex: none;
  margin-left: auto;
  /* Same line as the question's first line (the whisper is 1.2rem tall). */
  margin-top: calc((var(--nt-wz-qline) - 1.2rem) / 2);
}

/* ── the why popover ────────────────────────────────────────────────────── */

.nt-wz-why {
  flex: none;
  position: relative;
  /* The 1.55rem circle, optically centred on the question's first line. */
  margin-top: calc((var(--nt-wz-qline) - 1.55rem) / 2);
}

.nt-wz-why-btn {
  display: grid;
  place-items: center;
  width: 1.55rem;
  height: 1.55rem;
  border-radius: var(--nt-radius-full);
  border: 1px solid var(--nt-border-subtle);
  background: none;
  color: var(--nt-text-tertiary);
  cursor: pointer;
  transition: color var(--nt-duration-fast) var(--nt-ease),
              border-color var(--nt-duration-fast) var(--nt-ease),
              background var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-why-btn:hover,
.nt-wz-why-btn[aria-expanded="true"] {
  color: var(--nt-seal);
  border-color: var(--nt-seal-border);
  background: var(--nt-seal-soft);
}

.nt-wz-why-btn:focus-visible { outline: none; box-shadow: var(--nt-shadow-focus); }

/* Dark, because it is an aside: the § and its paragraph are a footnote laid
   over the product, not another panel of it. */
.nt-wz-why-pop {
  position: absolute;
  left: 0;
  bottom: calc(100% + 0.55rem);
  z-index: 60;
  width: min(22rem, 82vw);
  padding: var(--nt-space-3) var(--nt-space-4);
  background: var(--nt-c-ink-900);
  color: var(--nt-c-paper-100);
  border-radius: 0.8rem;
  box-shadow: var(--nt-shadow-3);
  font-size: 0.78rem;
  line-height: 1.55;
  animation: nt-wz-why-in var(--nt-duration) var(--nt-ease) both;
}

@keyframes nt-wz-why-in {
  from { opacity: 0; translate: 0 4px; }
  to { opacity: 1; translate: 0 0; }
}

.nt-wz-why-head { display: flex; align-items: center; gap: var(--nt-space-2); flex-wrap: wrap; }

/* The § chip inverts inside the dark panel — the shared component's paper
   ground would be a white brick on ink. */
.nt-wz-why-pop .nt-law-chip {
  background: rgb(255 255 255 / 0.12);
  border-color: transparent;
  color: inherit;
}

.nt-wz-why-majority { font-size: 0.7rem; opacity: 0.75; }

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

/* ── the body row: back · control · next ────────────────────────────────── */

.nt-wz-body {
  flex: 1 1 auto;
  /* THE QUESTION ROW NEVER GIVES WAY. The band above it (flex: none,
     internally scrolling, capped) is the shrinkable party; this floor keeps
     the field row real when the composer's cap squeezes the column. */
  min-height: 3.75rem;
  display: flex;
  /* THE FIELD STACK FLOWS FROM THE TOP, under the head row.
   *
   * This was `align-items: flex-end`, chosen so Næste would sit at the bottom
   * of a grown composer. On a one-field screen it did something much worse: the
   * body row is `flex: 1`, so it is as tall as the detent, and bottom-aligning
   * pushed the single control to the floor with 250px of empty tray above it.
   * The customer got a question, a void, and then the answer — on gf_dirigent,
   * which is the screen this whole design was approved on.
   *
   * `stretch` lets the controls column take the row's full height and lay its
   * fields out from the top; the two buttons opt out of the stretch below and
   * choose their own line. */
  align-items: stretch;
  gap: var(--nt-space-2);
  padding: 0.55rem var(--nt-space-4) var(--nt-space-3);
  border: 0;
  margin: 0;
}

/* DOM ORDER IS THE ENTER KEY — "Næste" is written first so implicit submission
   fires it rather than "Tilbage". `order` puts it back on the right. */
/* The buttons line up with the FIRST field, which is where the customer is
   looking on the screens that are two rows tall — and the composer is two rows
   tall by design. */
.nt-wz-submit { order: 3; flex: none; align-self: flex-start; }
.nt-wz-back { order: 1; align-self: flex-start; }
.nt-wz-controls {
  order: 2;
  flex: 1;
  min-width: 0;
  /* THE FIELD IS NEVER THE THING THAT GIVES WAY. flex: 1 grows from a zero
     basis, so when the escalation band's auto basis filled the tray the
     controls got the 2px that were left and the question vanished. This floor
     forces the redistribution: the band (flex: 0 1 auto + overflow-y: auto)
     is the shrinkable, internally-scrolling party. */
  min-height: 3.25rem;
}

/* THE ACTIONS ARE A FOOTER ROW, ALWAYS. Every side-column variant tried —
   beside the first field, bottom-aligned when grown, conditional on field
   count — produced some screen where Næste floated in a tall empty column
   belonging to nothing. Grid, not wrapped flex: wrapped rows do not
   constrain themselves to the container's height, so the footer spilled
   below the tray. Two grid rows — the fields in a scrolling minmax(0,1fr)
   cell, the buttons in an auto row that can never leave the tray. */
.nt-wz-body {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-rows: minmax(0, 1fr) auto;
  row-gap: var(--nt-space-2);
}
.nt-wz-body > .nt-wz-controls { grid-area: 1 / 1 / 2 / 4; min-height: 0; }
.nt-wz-body > .nt-wz-back { grid-area: 2 / 1 / 3 / 2; align-self: center; }
.nt-wz-body > .nt-wz-submit { grid-area: 2 / 3 / 3 / 4; align-self: center; }

.nt-wz-body:disabled .nt-wz-controls { opacity: 0.6; }
.nt-wz-body:disabled * { cursor: default; }

/* THE ONE SCROLL SURFACE INSIDE THE COMPOSER. Several fields stack and the
   stack scrolls; the question above it and the buttons beside it do not move.
   `overscroll-behavior: contain` so reaching the end of a three-field screen
   does not start scrolling the document behind the tray. */
.nt-wz-controls {
  display: flex;
  flex-direction: column;
  gap: var(--nt-space-3);
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Room for the fade below, so the last field's focus ring is not clipped. */
  padding-block: 1px;
}

/* One question sits on the row between the two buttons; several stack. Both
   start at the top — `justify-content: center` here was the other half of the
   void, floating a single field in the middle of whatever height the detent
   happened to be. */
.nt-wz-controls { justify-content: flex-start; }

/* THE SCROLL IS VISIBLE OR IT DOES NOT EXIST. A field clipped at the tray's
   edge with nothing to say it continues is a field nobody finds. The mask
   fades the last few pixels of the stack whenever it overflows — and, because
   `mask-image` on a non-overflowing element fades nothing, it costs a screen
   with one field exactly nothing. */
.nt-wz-controls[data-count]:not([data-count="1"]) {
  mask-image: linear-gradient(to bottom, #000 calc(100% - 1.25rem), transparent);
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 1.25rem), transparent);
}

/* Scrolled to the end, there is nothing below to hint at. */
.nt-wz-controls[data-scrolled="end"] {
  mask-image: none;
  -webkit-mask-image: none;
}

.nt-wz-back {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.6rem;
  border: 0;
  border-radius: 0.65rem;
  background: none;
  color: var(--nt-text-tertiary);
  cursor: pointer;
  transition: background var(--nt-duration-fast) var(--nt-ease),
              color var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-back:hover { background: var(--nt-bg-accent); color: var(--nt-text); }
.nt-wz-back:focus-visible { outline: none; box-shadow: var(--nt-shadow-focus); }

.nt-wz-next {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  height: 2.6rem;
  padding: 0 1.15rem;
  border: 0;
  border-radius: 0.7rem;
  background: var(--nt-seal);
  color: var(--nt-on-seal);
  font-size: 0.88rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--nt-duration-fast) var(--nt-ease),
              transform var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-next:hover { background: var(--nt-seal-hover); color: var(--nt-on-seal); }
.nt-wz-next:active { transform: scale(0.98); }
.nt-wz-next:focus-visible { outline: none; box-shadow: var(--nt-shadow-focus); }

/* HELD BACK, NOT DISABLED. An unlawful answer means the server will refuse,
   and the button stays operable so pressing it re-states why rather than
   leaving a dead control on the page. */
.nt-wz-next.is-held { background: var(--nt-neutral); }
.nt-wz-next.is-held:hover { background: var(--nt-neutral-text); }

.nt-wz-kbd {
  font-family: var(--nt-font-mono);
  font-size: 0.6rem;
  font-weight: 400;
  background: rgb(255 255 255 / 0.18);
  padding: 0.1rem 0.3rem;
  border-radius: 0.3rem;
}

/* A phone has no ↵ to promise. */
@media (pointer: coarse) {
  .nt-wz-kbd { display: none; }
}

/* ── the hint line ──────────────────────────────────────────────────────── */

.nt-wz-hint {
  font-size: 0.72rem;
  line-height: 1.45;
  color: var(--nt-text-tertiary);
  margin: 0;
}

.nt-wz-hint strong { color: var(--nt-text-secondary); font-variant-numeric: tabular-nums; }

/* § 180 OVER THE LINE: amber, and only amber. The refusal itself is the hard
   stop below; this is the sentence that gets there first. */
.nt-wz-headroom[data-state="over"] { color: var(--nt-warn-text); }
.nt-wz-headroom[data-state="over"] strong { color: var(--nt-warn-text); }

.nt-wz-peek {
  display: flex;
  gap: var(--nt-space-2);
  align-items: flex-start;
  margin: 0 var(--nt-space-4) var(--nt-space-2);
  padding: var(--nt-space-2) var(--nt-space-3);
  border-radius: var(--nt-radius);
  background: var(--nt-info-soft);
  color: var(--nt-info-text);
  font-size: var(--nt-text-xs);
}

.nt-wz-peek-icon { flex: none; color: var(--nt-info); margin-top: 0.05rem; }
.nt-wz-peek-body { margin: 0; }

/* THE STOP is the tray's own top strip — in normal flow (the old absolute
   float is what slid it under the rail). A refusal outranks the question. */
.nt-wz-foldable > .nt-stop {
  order: -1;
  flex: none;
  max-height: 35vh;
  overflow-y: auto;
  overscroll-behavior: contain;
  margin: var(--nt-space-1) var(--nt-space-4) var(--nt-space-2);
  background: var(--nt-surface);
  border: 1px solid var(--nt-seal-border);
  border-radius: var(--nt-radius);
}

/* THE HAND-OFF LINE'S TWO SEATS. On a question screen: the dead middle cell
   of the action grid, beside "Næste" — the message stands where the way
   forward is, without taking it. On the review: a bordered strip above the
   commit bar. The line is ALWAYS a line; its prose is the dialog. */
.nt-wz-body > .nt-handoff {
  grid-area: 2 / 2 / 3 / 3;
  align-self: center;
  min-width: 0;
  margin: 0 var(--nt-space-3);
}

.nt-wz-foldable > .nt-handoff {
  flex: none;
  order: -1;
  margin: var(--nt-space-1) var(--nt-space-4) var(--nt-space-2);
  padding: 0.5rem var(--nt-space-3);
  background: var(--nt-surface);
  border: 1px solid var(--nt-seal-border);
  border-radius: var(--nt-radius);
}

.nt-handoff > .nt-handoff-cta { margin: 0 0 0 auto; flex: none; white-space: nowrap; }

.nt-handoff-toggle {
  flex: none;
  padding: 0;
  border: 0;
  background: none;
  font-size: var(--nt-text-xs);
  font-weight: 600;
  color: var(--nt-seal-text);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  white-space: nowrap;
}

.nt-handoff-toggle:focus-visible { outline: none; box-shadow: var(--nt-shadow-focus); }


/* ══════════════════════════════════════════════════════════════════════
   5. THE CONTROLS
   ══════════════════════════════════════════════════════════════════════ */

.nt-wz-controls .nt-field {
  display: flex;
  flex-direction: column;
  gap: var(--nt-space-2);
}
/* The seam between two stacked questions: the notarium.css defaults stack a
   20px top margin on a 16px bottom one plus the flex gap — ~50px of air per
   seam in a tray that promises compactness. One gap owns the seam. */
.nt-wz-controls .nt-field { margin-block: 0; }

/* A solo control has no visible label — the question above IS the label — so
   it loses the gap a label would have needed. */
.nt-wz-controls .nt-field[data-solo] { gap: var(--nt-space-2); }

.nt-wz-controls .nt-input,
.nt-wz-controls .nt-select {
  height: 2.6rem;
  border-radius: 0.7rem;
  border-width: 1.5px;
  background: var(--nt-bg-accent);
}

.nt-wz-controls .nt-input:focus { background: var(--nt-surface); }

.nt-wz-controls .nt-textarea { border-radius: 0.7rem; border-width: 1.5px; }

/* NINETY PIXELS OF NOTHING, and where they came from.
 *
 * This set is `flex-direction: column` (notarium.css §26b), and the fix that
 * shipped first added `flex-wrap: wrap` and `flex: 1 1 12rem` to it. On a
 * COLUMN the main axis is vertical — so `flex-basis: 12rem` stopped meaning
 * "at least 12rem wide" and started meaning "12rem TALL", and every option
 * card became a 190px box with one line of text floating in it. The customer
 * saw a tinted rectangle with its label pinned to an edge.
 *
 * A choice is a ROW, full width, text-height — the same shape the mock's
 * check rows have. Three long Danish labels side by side in a 52rem tray were
 * never going to be readable anyway. The direction is stated explicitly here
 * rather than inherited, because inheriting it is what caused this. */
.nt-wz-controls .nt-choice-set {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: var(--nt-space-2);
  margin-top: 0;
}

/* The card itself is a row, not a poster: the composer is two rows tall by
   design and a 1rem inset on four options is most of it. `flex: none` so the
   card is its own content's height and nothing can stretch it again. */
.nt-wz-controls .nt-choice {
  flex: none;
  align-items: center;
  gap: var(--nt-space-2);
  padding: 0.5rem 0.7rem;
  border-radius: 0.6rem;
}

.nt-wz-controls .nt-choice input[type="radio"] { margin-top: 0; }
.nt-wz-controls .nt-choice-title { font-size: var(--nt-text-sm); }

/* The second line is the pack's own explanation of an option, and it is worth
   keeping — but it belongs at hint weight, not at body weight. */
.nt-wz-controls .nt-choice-help {
  font-size: var(--nt-text-xs);
  line-height: 1.4;
  margin-top: 0.1rem;
}

/* A card carrying a help line cannot centre its radio against two lines of
   text — it goes back to the top, where it lines up with the title. */
.nt-wz-controls .nt-choice:has(.nt-choice-help) { align-items: flex-start; }
.nt-wz-controls .nt-choice:has(.nt-choice-help) input[type="radio"] { margin-top: 0.2rem; }

/* ── the folded note field ──────────────────────────────────────────────── */

.nt-wz-note-open {
  display: inline-flex;
  align-items: center;
  gap: var(--nt-space-2);
  padding: 0.5rem 0.85rem;
  border: 1px dashed var(--nt-border);
  border-radius: 0.7rem;
  background: none;
  color: var(--nt-text-secondary);
  font-size: var(--nt-text-sm);
  cursor: pointer;
  transition: border-color var(--nt-duration-fast) var(--nt-ease),
              color var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-note-open:hover { border-color: var(--nt-seal-border); color: var(--nt-seal); }
.nt-wz-note-open:focus-visible { outline: none; box-shadow: var(--nt-shadow-focus); }

/* ── cvr ────────────────────────────────────────────────────────────────── */

.nt-wz-cvr { display: flex; flex-direction: column; gap: var(--nt-space-2); }

.nt-input-cvr { letter-spacing: 0.08em; }

.nt-wz-cvr-result {
  margin: 0;
  display: grid;
  gap: 0.1rem;
  font-size: var(--nt-text-xs);
  min-height: 1.1rem;
}

.nt-wz-cvr-result[data-state="idle"] { display: none; }
.nt-wz-cvr-result[data-state="looking"] { color: var(--nt-text-tertiary); }
.nt-wz-cvr-result[data-state="failed"] { color: var(--nt-warn-text); }

.nt-wz-cvr-name { font-weight: 600; color: var(--nt-text); }
.nt-wz-cvr-address { color: var(--nt-text-tertiary); }

.nt-wz-cvr-result[data-state="failed"] .nt-wz-cvr-name { color: var(--nt-warn-text); font-weight: 500; }

/* ── address ────────────────────────────────────────────────────────────── */

.nt-wz-address { display: grid; gap: var(--nt-space-2); }

.nt-wz-address-street { position: relative; }

.nt-wz-address-town { display: grid; grid-template-columns: 6rem 1fr; gap: var(--nt-space-2); }

.nt-wz-address-list {
  position: absolute;
  z-index: 30;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  max-height: 12rem;
  overflow-y: auto;
  margin: 0;
  padding: var(--nt-space-1);
  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-2);
}

.nt-wz-address-option {
  padding: 0.35rem var(--nt-space-2);
  border-radius: var(--nt-radius-sm);
  font-size: var(--nt-text-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 has two cursors. */
.nt-wz-address-option:hover,
.nt-wz-address-option.is-active { background: var(--nt-seal-soft); color: var(--nt-seal); }

.nt-wz-address-none {
  padding: 0.35rem var(--nt-space-2);
  font-size: var(--nt-text-sm);
  color: var(--nt-text-tertiary);
}

/* ── share_allocation ───────────────────────────────────────────────────── */

.nt-wz-alloc-table { width: 100%; border-collapse: collapse; font-size: var(--nt-text-sm); }

.nt-wz-alloc-table th {
  text-align: left;
  font-family: var(--nt-font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--nt-text-tertiary);
  padding: 0.3rem 0;
  border-bottom: 1px solid var(--nt-border-subtle);
}

.nt-wz-alloc-table td { padding: 0.35rem 0; border-bottom: 1px solid var(--nt-border-subtle); }

.nt-wz-alloc-amount { text-align: right; font-variant-numeric: tabular-nums; }
.nt-wz-alloc-amount .nt-affix-field { margin-left: auto; max-width: 11rem; }
.nt-wz-alloc-name { color: var(--nt-text); }
.nt-wz-alloc-pct { color: var(--nt-text-tertiary); font-size: var(--nt-text-xs); width: 5rem; }

.nt-wz-alloc-table tfoot th {
  border-bottom: 0;
  border-top: 1px solid var(--nt-border);
  padding-top: var(--nt-space-2);
  text-transform: none;
  font-family: inherit;
  font-size: var(--nt-text-xs);
  letter-spacing: 0;
  color: var(--nt-text-secondary);
}

.nt-wz-alloc-table tfoot td { border-bottom: 0; border-top: 1px solid var(--nt-border); padding-top: var(--nt-space-2); }

/* THE REST LINE. Amber while it does not add up — an unfinished fordeling is
   a half-typed answer, not an overdue frist. */
.nt-wz-alloc-rest { font-weight: 600; }
.nt-wz-alloc-rest[data-state="open"],
.nt-wz-alloc-rest[data-state="over"] { color: var(--nt-warn-text); }
.nt-wz-alloc-rest[data-state="balanced"] { color: var(--nt-ok-text); }

/* ── the dropzone ───────────────────────────────────────────────────────── */

.nt-wz-drop { display: flex; flex-direction: column; gap: var(--nt-space-2); }

.nt-wz-drop-zone {
  display: flex;
  align-items: center;
  gap: var(--nt-space-3);
  padding: var(--nt-space-3);
  border: 1.5px dashed var(--nt-border);
  border-radius: 0.7rem;
  background: var(--nt-bg-accent);
  cursor: pointer;
  transition: border-color var(--nt-duration-fast) var(--nt-ease),
              background var(--nt-duration-fast) var(--nt-ease);
}

.nt-wz-drop-zone:hover { border-color: var(--nt-seal-border); }

.nt-wz-drop[data-dragging] .nt-wz-drop-zone {
  border-color: var(--nt-seal);
  border-style: solid;
  background: var(--nt-seal-soft);
}

.nt-wz-drop[data-state="attached"] .nt-wz-drop-zone {
  border-style: solid;
  border-color: var(--nt-ok-border);
  background: var(--nt-ok-soft);
}

.nt-wz-drop[data-state="failed"] .nt-wz-drop-zone { border-color: var(--nt-warn-border); }

.nt-wz-drop-icon { flex: none; color: var(--nt-text-tertiary); }
.nt-wz-drop[data-state="attached"] .nt-wz-drop-icon { color: var(--nt-ok); }

.nt-wz-drop-title { display: block; font-size: var(--nt-text-sm); font-weight: 600; color: var(--nt-text); }
.nt-wz-drop-body { display: block; font-size: var(--nt-text-xs); color: var(--nt-text-tertiary); }

/* Visually hidden, NOT `display: none` — a hidden input cannot be reached by a
   keyboard, and "vedhæft årsrapporten" is not a mouse-only feature. */
.nt-wz-drop-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.nt-wz-drop-input:focus-visible + * { box-shadow: var(--nt-shadow-focus); }

.nt-wz-drop-progress { display: flex; align-items: center; gap: var(--nt-space-2); }

.nt-wz-drop-bar {
  flex: 1;
  height: 4px;
  border-radius: var(--nt-radius-full);
  background: var(--nt-neutral-tint);
  overflow: hidden;
}

.nt-wz-drop-bar > span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--nt-seal);
  transition: width var(--nt-duration) linear;
}

.nt-wz-drop-status { font-size: var(--nt-text-xs); color: var(--nt-text-tertiary); }

.nt-wz-drop-defer {
  display: flex;
  align-items: center;
  gap: var(--nt-space-2);
  font-size: var(--nt-text-xs);
  color: var(--nt-text-secondary);
}

/* ══════════════════════════════════════════════════════════════════════
   6. THE DOCUMENT'S OWN INK
   ══════════════════════════════════════════════════════════════════════ */

/* The clause this question writes. Soft, and it STAYS while the question is on
   screen: it is not a notification, it is "this is the paragraph we are
   writing". The spread shadow is what makes a tint of a bare paragraph read as
   a highlighted BLOCK rather than as a coloured line of text. */
.nt-doc .nt-doc-target {
  border-radius: 6px;
  background: var(--nt-seal-soft);
  box-shadow: 0 0 0 10px var(--nt-seal-soft);
  transition: background var(--nt-duration-slower) var(--nt-ease),
              box-shadow var(--nt-duration-slower) var(--nt-ease);
}

/* Never occluded by the composer or hidden under the rail: the scroll
   arithmetic in document_preview_controller aims for this, and scroll-margin
   is the browser's own answer for everything that scrolls it another way
   (a fragment link, find-in-page, a focus jump). */
.nt-doc [id^="klausul-"] { scroll-margin: 5rem 0 14rem; }

/* THE COMMIT FLASH — the ink drying on the answer just given — is `.nt-wz-changed`
   in wizard.css, and it stays there: it is the redline mark in the document's
   own margin, it already runs tint-to-transparent over 1400ms, and one
   animation with two owners is how a highlight quietly changes behaviour when
   somebody reorders a stylesheet. The only thing added here is the corner
   radius that lets it sit under the target tint above without a square edge
   showing through. */
.nt-doc-sheet .nt-wz-changed { border-radius: 6px; }

/* ── the live slots ─────────────────────────────────────────────────────── */

/* An empty slot is a VISIBLE BLANK, not a collapsed sentence. A paragraph that
   reflows on every keystroke is worse than one with a gap in it, and the gap
   is honest: nothing is written there yet.

   `:empty` IS THE LOAD-BEARING HALF. The server renders an unanswered slot as
   an empty span, and until the composer's controller has connected — which is
   never, on a screen whose field is not the one this slot belongs to — no
   class is added to it. Without this selector the referat read "Der var
   indkaldt til generalforsamlingen den ." with a bare full stop where a date
   is going to be. The class is what the ECHO uses when it clears a slot the
   customer has just emptied; `:empty` is what the document does on its own. */
.nt-doc [data-answer]:empty,
.nt-doc [data-answer].nt-ink-empty {
  display: inline-block;
  min-width: 9ch;
  line-height: 1.3;
  vertical-align: baseline;
  color: transparent;
  background: var(--nt-neutral-tint);
  border-bottom: 1.5px dashed var(--nt-border);
  border-radius: 2px 2px 0 0;
  user-select: none;
}

/* Wet ink: what the composer has echoed and the server has not confirmed yet.
   It is replaced wholesale by the next render, so this class never survives a
   swap — which is exactly why it may be conspicuous. */
.nt-doc [data-answer].nt-ink-live {
  display: inline-block;
  background: var(--nt-seal-soft);
  border-bottom: 1.5px solid var(--nt-seal-border);
  border-radius: 2px;
  transition: background var(--nt-duration-slow) var(--nt-ease);
}

/* ══════════════════════════════════════════════════════════════════════
   7. THE REVIEW AND THE COMMIT BAR
   ══════════════════════════════════════════════════════════════════════ */

/* On the review the composer IS the commit bar, and the head row's "14/14 ·
   Er alt korrekt?" would be the same sentence twice above "Referatet er
   klar". */
.nt-wz-form:has(.nt-wz-commit) > .nt-wz-head { display: none; }

.nt-wz-review {
  /* Basis auto, not 0: under the auto-height fold chain a zero basis
     collapses the review to nothing (wizard_composer.css §4). */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--nt-space-3) var(--nt-space-4) var(--nt-space-2);
  display: flex;
  flex-direction: column;
  gap: var(--nt-space-4);
}

.nt-wz-review-intro { margin: 0; font-size: var(--nt-text-sm); color: var(--nt-text-secondary); }

/* "besvaret af Sofie Krogh" — provenance, at the weight of provenance. It sits
   inside the group label so it reads as part of "this is what this screen
   said", not as a badge on the answer. */
.nt-review-author {
  font-family: var(--nt-font-body);
  font-weight: 400;
  font-size: var(--nt-text-xs);
  text-transform: none;
  letter-spacing: 0;
  color: var(--nt-text-tertiary);
  margin-left: var(--nt-space-2);
}

/* The bar. Always on screen, whatever the review above it is doing. */
.nt-wz-commit {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--nt-space-3);
  padding: var(--nt-space-3) var(--nt-space-4);
  border-top: 1px solid var(--nt-border-subtle);
  background: var(--nt-surface);
}

.nt-wz-commit-mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: var(--nt-radius-full);
  background: var(--nt-seal-soft);
  color: var(--nt-seal);
}

.nt-wz-commit-title { margin: 0; font-size: 0.95rem; font-weight: 600; color: var(--nt-text); }
.nt-wz-commit-micro { margin: 0; font-size: 0.74rem; color: var(--nt-text-tertiary); }
.nt-wz-commit-blocked { margin: 0; font-size: var(--nt-text-xs); color: var(--nt-text-secondary); max-width: 22rem; }

.nt-wz-commit-action { flex: none; }
.nt-wz-commit-panel { display: flex; align-items: center; gap: var(--nt-space-3); }
.nt-wz-commit-confirm { margin: 0; font-size: var(--nt-text-xs); color: var(--nt-text-secondary); max-width: 18rem; }
.nt-wz-commit-buttons { display: flex; align-items: center; gap: var(--nt-space-2); }

/* ── the signers block ──────────────────────────────────────────────────── */

.nt-wz-signers { display: flex; flex-direction: column; gap: var(--nt-space-2); }

.nt-wz-signer-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--nt-space-1); }

.nt-wz-signer {
  display: flex;
  align-items: center;
  gap: var(--nt-space-3);
  padding: var(--nt-space-2) var(--nt-space-3);
  border: 1px solid var(--nt-border-subtle);
  border-radius: var(--nt-radius);
  background: var(--nt-bg-accent);
}

.nt-wz-signer-mark { flex: none; color: var(--nt-text-tertiary); }
.nt-wz-signer-name { margin: 0; font-size: var(--nt-text-sm); font-weight: 600; color: var(--nt-text); }
.nt-wz-signer-role { margin: 0; font-size: var(--nt-text-xs); color: var(--nt-text-tertiary); }
.nt-wz-signer-email { margin-left: auto; font-size: var(--nt-text-xs); color: var(--nt-text-tertiary); }
.nt-wz-signer-input { margin-left: auto; max-width: 15rem; }

.nt-wz-signer-unknown { margin-left: auto; font-size: var(--nt-text-xs); color: var(--nt-warn-text); }

.nt-wz-signer-form { display: flex; align-items: center; justify-content: space-between; gap: var(--nt-space-3); }

/* ══════════════════════════════════════════════════════════════════════
   8. NARROW VIEWPORTS
   The same design, docked. Nothing moves in the DOM — moving #wizard-panel
   between two layouts would tear down its form and take whatever the customer
   had typed with it.
   ══════════════════════════════════════════════════════════════════════ */

@media (max-width: 40rem) {
  /* A phone gives a roomy screen almost everything; the viewport guard
     keeps the rail's strip. */
  .nt-wz-composer:has([data-forces-full], .nt-stop) {
    max-height: min(88dvh, calc(var(--nt-wz-vv, 100dvh) - 5rem));
  }

  .nt-wz-rail { gap: var(--nt-space-3); padding: 0 var(--nt-space-3); }
  /* The brand text and the group labels are the first things to go: on a
     phone the customer knows which selskab they are in, and the rail's job
     narrows to "where am I in this". */
  .nt-wz-brand-text,
  .nt-wz-zoom { display: none; }
  /* The doc dropdown STAYS — it is how a phone switches documents at all.
     The title goes; the file icon and the chevron are the trigger. */
  .nt-wz-doc-label { display: none; }
  /* The icon stays, the word goes: a thumb has room for one and not both. */
  .nt-wz-close-label { display: none; }

  /* Full-bleed paper. A phone-width sheet with 1.5rem of desk either side is
     a picture of a document; edge to edge, it is the document. */
  .nt-wz-stage { padding: var(--nt-space-3) 0 calc(7rem + var(--nt-space-8)); }
  .nt-wz-stage .nt-doc-sheet { border-radius: 0; border-inline: 0; box-shadow: none; }

  .nt-wz-composer-wrap { padding: 0; background: none; }

  .nt-wz-composer {
    border-radius: var(--nt-radius-lg) var(--nt-radius-lg) 0 0;
    border-inline: 0;
    border-bottom: 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }

  /* The chevron goes: a thumb has the rail's step list for going back, and
     the row needs every pixel for the field. */
  .nt-wz-back { display: none; }

/* Edge to edge, the composer meets the launcher. The question wins: the
   chat panel is one tap from the navbar on every other screen, and a
   floating button over the field somebody is typing into is not help. */
body.nt-app:has(.nt-wz) .nt-chat-launcher { display: none; }

.nt-wz-commit { flex-wrap: wrap; }
  .nt-wz-commit-action { width: 100%; }
  .nt-wz-commit-action .nt-wz-next { width: 100%; justify-content: center; }
}

/* Below the width at which A4 stops being A4, the preview reflows to the
   phone's measure rather than standing at print geometry — and a page count
   taken at a reflowed width would not match the PDF, so the paginator is
   switched off through the custom property it reads. */
@media (max-width: 65rem) {
  .nt-wz-stage { --nt-doc-paginate: 0; }
}

/* ══════════════════════════════════════════════════════════════════════
   9. REDUCED MOTION — snaps, no glides
   ══════════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .nt-wz-foldable,
  .nt-wz-seg,
  .nt-doc .nt-doc-target,
  .nt-doc [data-answer].nt-ink-live,
  .nt-wz-drop-bar > span { transition: none; }

  .nt-wz-steps,
  .nt-wz-why-pop { animation: none; }

  .nt-doc-sheet .nt-wz-changed { animation-duration: 1ms; }

  /* The stage stops smooth-scrolling; document_preview_controller already
     asks for `behavior: auto` under reduced motion, and this catches every
     other way the page can be scrolled. */
  .nt-wz-stage { scroll-behavior: auto; }
}
