/* ══════════════════════════════════════════════════════════════════════
   ONBOARDING — the three screens between "verified magic link" and
   "has a Selskabsmappe": the fork, the plan picker, and the dev stand-in
   for Stripe Checkout.

   These render in layouts/application.html.erb, whose column is
   .nt-app-column-narrow (52rem). Everything here is designed for that
   measure and for 375px — no horizontal scroll at any width.

   Namespaces: .nt-pick-* is the plan picker, .nt-onb-* is everything else.
   NOT .nt-plan-* — notarium.css already owns that prefix for the marketing
   "sådan gør vi" steps, and a near-miss there would be invisible until it
   wasn't.
   ══════════════════════════════════════════════════════════════════════ */

/* ── The fork: two doors, equal weight ────────────────────────────────── */

/* auto-fit rather than a fixed 2-up: at 375px the two cards stack, and the
   grid does it without a breakpoint. */
.nt-onb-fork {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: var(--nt-space-5);
  align-items: stretch;
}

.nt-onb-fork-card {
  display: flex;
  flex-direction: column;
  gap: var(--nt-space-4);
  padding: var(--nt-space-6);
}

/* The form is the last child and must sit on the same baseline in both
   cards — the bodies are different lengths. */
.nt-onb-fork-card form { margin-top: auto; }

.nt-onb-fork-icon {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--nt-radius);
  background: var(--nt-seal-soft);
  color: var(--nt-seal-text);
}

.nt-onb-fork-title {
  font-family: var(--nt-font-display);
  font-size: var(--nt-text-lg);
  font-weight: 600;
  line-height: 1.3;
  margin: 0;
}

.nt-onb-fork-body {
  font-size: var(--nt-text-sm);
  color: var(--nt-text-secondary);
  line-height: 1.5;
  margin: 0;
}

/* ── The plan picker ──────────────────────────────────────────────────── */

.nt-pick {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--nt-space-4);
  align-items: stretch;
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;   /* a <fieldset> defaults to min-content and would refuse to shrink */
}

/* The card IS the <label>, and the radio inside it is the state.
   Doing it this way rather than with buttons + JS means the picker keeps
   working with JavaScript off: clicking selects, arrow keys move between
   options, and :has(input:checked) paints the selection — all native. The
   Stimulus controller only adds the running total and the confirm gate. */
.nt-pick-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--nt-space-3);
  padding: var(--nt-space-5);
  /* Room for the selection mark in the top-right corner. */
  padding-right: calc(var(--nt-space-5) + 1.75rem);
  background: var(--nt-surface);
  border: 1px solid var(--nt-border);
  border-radius: var(--nt-radius-lg);
  box-shadow: var(--nt-shadow-1);
  cursor: pointer;
  transition:
    border-color var(--nt-duration-fast) var(--nt-ease),
    box-shadow var(--nt-duration-fast) var(--nt-ease),
    transform var(--nt-duration-fast) var(--nt-ease);
}

.nt-pick-card:hover { border-color: var(--nt-border-strong); }

/* The input carries focus and the checked state; it is never seen. It stays
   in the layout (not display:none) so it remains focusable and so
   :has(input:focus-visible) can put the ring on the whole card. */
.nt-pick-card input[type="radio"] {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  clip-path: inset(50%);
  overflow: hidden;
}

.nt-pick-card:has(input:checked) {
  border-color: var(--nt-seal);
  /* An inset ring rather than a 2px border: a thicker border would reflow the
     card's contents by a pixel on selection and make the grid twitch. */
  box-shadow: inset 0 0 0 1px var(--nt-seal), var(--nt-shadow-2);
}

.nt-pick-card:has(input:focus-visible) {
  outline: 2px solid var(--nt-focus);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  .nt-pick-card:has(input:checked) { transform: translateY(-1px); }
}

/* The seal-red hairline along the top edge of the chosen card — the same
   gesture the marketing price cards use for "this one". */
.nt-pick-card::before {
  content: "";
  position: absolute;
  inset: -1px -1px auto -1px;
  height: 3px;
  border-radius: var(--nt-radius-lg) var(--nt-radius-lg) 0 0;
  background: linear-gradient(90deg, var(--nt-seal-deep), var(--nt-seal), var(--nt-seal-lift));
  opacity: 0;
  transition: opacity var(--nt-duration-fast) var(--nt-ease);
}

.nt-pick-card:has(input:checked)::before { opacity: 1; }

/* Every row inside the card is a <span>: a <label>'s content model is phrasing
   content, so it may not hold <h2>/<p>/<div>. The flex column blockifies them,
   which is why none of these need `display: block`. */
.nt-pick-name {
  font-family: var(--nt-font-display);
  font-size: var(--nt-text-lg);
  font-weight: 600;
  line-height: 1.2;
  margin: 0;
}

.nt-pick-tagline {
  font-size: var(--nt-text-sm);
  color: var(--nt-text-secondary);
  line-height: 1.5;
  margin: 0;
}

/* No wrap: "3.500" and "kr./år" are one price and must never break across
   two lines. Same reason the copy uses a non-breaking space in prose. */
.nt-pick-price {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
}

.nt-pick-amount {
  font-family: var(--nt-font-display);
  font-size: 2.1rem;
  font-weight: 500;
  font-variation-settings: "opsz" 96, "SOFT" 14, "WONK" 1;
  letter-spacing: -0.03em;
  line-height: 1;
}

.nt-pick-unit {
  font-size: var(--nt-text-xs);
  color: var(--nt-text-tertiary);
}

/* flex-1 is the whole fix for the old bug: the feature lists are 6 and 10
   items long, so in two equal-height grid cells the shorter card used to
   leave its slack at the bottom. The list absorbs it instead, and every
   card's last row lands on the same line. */
.nt-pick-features {
  flex: 1;
  display: grid;
  /* start, not the grid default stretch: a stretched 6-row list spaces its
     rows further apart than the 10-row list beside it, and then "Dokumentarkiv
     med varig opbevaring" sits at a different height in each card. Two plans
     are only comparable if their shared features line up. */
  align-content: start;
  gap: 0.45rem;
  margin: 0;
  padding: var(--nt-space-4) 0 0;
  border-top: 1px solid var(--nt-border-subtle);
  list-style: none;
  font-size: var(--nt-text-sm);
  color: var(--nt-text-secondary);
  line-height: 1.45;
}

.nt-pick-features li {
  display: grid;
  grid-template-columns: 1rem minmax(0, 1fr);
  gap: 0.5rem;
  align-items: start;
}

.nt-pick-features svg {
  margin-top: 0.22rem;
  color: var(--nt-ok);
}

/* The selection mark. Unchecked it is an empty ring; checked it fills and the
   tick appears — colour is never the only signal. */
.nt-pick-mark {
  position: absolute;
  top: var(--nt-space-5);
  right: var(--nt-space-5);
  display: grid;
  place-items: center;
  width: 1.2rem;
  height: 1.2rem;
  border-radius: var(--nt-radius-full);
  border: 1.5px solid var(--nt-border-strong);
  background: var(--nt-surface);
  color: transparent;
  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-pick-card:has(input:checked) .nt-pick-mark {
  border-color: var(--nt-seal);
  background: var(--nt-seal);
  color: var(--nt-on-seal);
}

/* ── The commit bar ───────────────────────────────────────────────────── */

/* Sticky at the bottom: on a 375px screen the stiftelse cost section pushes
   the confirm action a screen and a half below the fold, and a price you
   cannot see while you read is a price you do not trust.

   Kept deliberately short — two lines, label and amount on the same row —
   because a sticky bar spends its whole life covering something. On a 667px
   phone every extra line here is a line of the feature list the customer
   cannot read. Nothing is permanently hidden: the bar is the last element in
   the form and unpins at the end of the page. */
.nt-pick-bar {
  position: sticky;
  bottom: 0;
  z-index: var(--nt-z-sticky);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--nt-space-3) var(--nt-space-4);
  margin-top: var(--nt-space-2);
  padding: var(--nt-space-4) var(--nt-space-5);
  /* A full border and the deepest shadow: while it floats over a .nt-card it
     has to read as a layer above the page, not as a panel nested inside it. */
  border: 1px solid var(--nt-border);
  border-radius: var(--nt-radius-lg);
  background: var(--nt-surface);
  box-shadow: var(--nt-shadow-3);
}

.nt-pick-total { min-width: 0; }

.nt-pick-total-line {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.15rem 0.55rem;
  margin: 0;
}

.nt-pick-total-label {
  font-family: var(--nt-font-mono);
  font-size: var(--nt-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--nt-text-tertiary);
}

/* `plans.price_per_year` joins the amount and "kr./år" with an ordinary
   space; nowrap here is what keeps the total from breaking mid-price in the
   narrow bar without reaching into the shared catalog string. */
.nt-pick-total-value {
  font-family: var(--nt-font-display);
  font-size: var(--nt-text-xl);
  font-weight: 600;
  line-height: 1.25;
  white-space: nowrap;
}

/* The hints share the second row, separated by a middot, so the "who bears
   it" line costs no extra height on the stiftelse path. */
.nt-pick-total-hints {
  display: flex;
  flex-wrap: wrap;
  gap: 0.1rem 0.4rem;
  margin: 0.2rem 0 0;
  font-size: var(--nt-text-xs);
  color: var(--nt-text-tertiary);
  line-height: 1.4;
}

.nt-pick-total-hints > span + span:not(:empty)::before { content: "· "; }

.nt-pick-bar .nt-btn { flex: none; }

/* The chat launcher is `position: fixed` in the bottom-right corner at
   z-index 60 — above this bar — and it is ~76px wide including its offset.
   Once the page column stops being centred and reaches the viewport edge, the
   launcher lands ON the confirm button and eats roughly a fifth of its clicks.
   Reserving the corner is the only fix available from inside this stylesheet;
   the alternative would be teaching the widget about page actions, which is
   chrome, not onboarding.
   Measured: 60px of clearance needed past the bar's own edge — 4.5rem leaves
   room for the launcher's hover growth. */
@media (max-width: 55rem) {
  .nt-pick-bar { padding-right: var(--nt-chat-gutter); }
}

@media (max-width: 30rem) {
  .nt-pick-bar { padding: var(--nt-space-4); padding-right: var(--nt-chat-gutter); }
}

/* ── The stiftelse cost choice ────────────────────────────────────────── */

.nt-onb-cost {
  padding: var(--nt-space-5);
  border: 0;
  min-width: 0;
}

.nt-onb-cost-legend {
  font-family: var(--nt-font-display);
  font-size: var(--nt-text-lg);
  font-weight: 600;
  padding: 0;
  margin-bottom: var(--nt-space-2);
}

.nt-onb-cost-intro {
  font-size: var(--nt-text-sm);
  color: var(--nt-text-secondary);
  line-height: 1.55;
  margin: 0 0 var(--nt-space-4);
  max-width: 62ch;
}

/* Two facts people reliably get wrong, set apart from the choice itself so
   they read as information rather than as an argument for one option. */
.nt-onb-facts {
  margin-top: var(--nt-space-5);
  padding: var(--nt-space-4);
  border-radius: var(--nt-radius);
  background: var(--nt-surface-sunken);
}

.nt-onb-facts-title {
  font-family: var(--nt-font-mono);
  font-size: var(--nt-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--nt-text-tertiary);
  margin: 0 0 var(--nt-space-3);
}

.nt-onb-fact-list {
  display: grid;
  gap: var(--nt-space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nt-onb-fact {
  display: grid;
  grid-template-columns: 1rem minmax(0, 1fr);
  gap: 0.6rem;
  align-items: start;
  font-size: var(--nt-text-sm);
  color: var(--nt-text-secondary);
  line-height: 1.5;
}

.nt-onb-fact svg {
  margin-top: 0.18rem;
  color: var(--nt-warn);
}

.nt-onb-cost-note {
  margin-top: var(--nt-space-4);
  padding-top: var(--nt-space-4);
  border-top: 1px solid var(--nt-border-subtle);
  font-size: var(--nt-text-sm);
  color: var(--nt-text-tertiary);
  line-height: 1.55;
  max-width: 66ch;
}

/* ── The dev stand-in for Stripe Checkout ─────────────────────────────── */

/* Reachable only when Billing.fake_mode? — but "only in development" is a
   claim about configuration, not about who is looking, so the screen wears
   its own warning stripes rather than trusting the environment. */
.nt-onb-dev {
  position: relative;
  overflow: hidden;
  padding: var(--nt-space-6);
  border: 1px dashed var(--nt-warn-border);
  border-radius: var(--nt-radius-lg);
  background: var(--nt-surface);
}

.nt-onb-dev::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 4px;
  background: repeating-linear-gradient(
    135deg,
    var(--nt-warn) 0 8px,
    transparent 8px 16px
  );
}

.nt-onb-dev-title {
  font-family: var(--nt-font-display);
  font-size: var(--nt-text-xl);
  font-weight: 600;
  line-height: 1.25;
  margin: 0 0 var(--nt-space-2);
}

.nt-onb-dev-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--nt-space-3);
  padding: var(--nt-space-3) 0;
  border-bottom: 1px solid var(--nt-border-subtle);
}

.nt-onb-dev-line:last-of-type { border-bottom: 0; }

.nt-onb-dev-key {
  font-size: var(--nt-text-sm);
  color: var(--nt-text-tertiary);
}

.nt-onb-dev-value {
  font-family: var(--nt-font-mono);
  font-size: var(--nt-text-sm);
  font-weight: 600;
}

/* button_to wraps its button in a <form>. Without display:contents the form
   is the flex child and the button never participates in this row's gap or
   alignment — the same trap that left the old plan buttons floating
   mid-card. See .nt-menu form.contents in navbar.css. */
.nt-onb-dev-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--nt-space-3);
  margin-top: var(--nt-space-5);
}

.nt-onb-dev-actions form.contents { display: contents; }

/* The stiftelse offer's struck-through ordinary price. Sits beside the
   discounted headline so the renewal figure is on screen at the moment of
   decision — a first-year price shown alone is the kind of thing customers
   are right to distrust. */
.nt-pick-was {
  margin-left: 0.4rem;
  font-size: var(--nt-text-sm);
  color: var(--nt-text-tertiary);
  text-decoration-thickness: 1px;
}

/* ══════════════════════════════════════════════════════════════════════
   KVITTERINGEN — the screen straight after the payment
   ══════════════════════════════════════════════════════════════════════

   Highest-intent moment in the product: somebody has just decided to pay us
   and is looking at the screen on purpose. Two questions, in this order — did
   the money arrive, and what happens now — so two plates: a receipt set like
   a document, and a numbered "hvad sker der nu" under it.

   Compliance green appears exactly once, on the eyebrow tick. This IS "i
   orden", which is what that colour is reserved for; spending it again on the
   card borders would turn a receipt into a celebration. */

.nt-onb-receipt-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: var(--nt-space-6) 0 0;
  font-family: var(--nt-font-mono);
  font-size: var(--nt-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--nt-ok-text);
}

.nt-onb-receipt-eyebrow svg { flex: none; }

/* `.nt-card` is a SHELL — background, border, radius, shadow, and nothing
   else; padding lives in `.nt-card-body`, which a bespoke card body like this
   one does not use. Without this the ledger's dt sat on the left border and
   the dd (the price, the selskab's name) was clipped by the right one. Same
   rule and same value as `.nt-upsell`. */
.nt-onb-receipt { padding: var(--nt-space-6); }

.nt-onb-receipt-lines { margin: 0; }

/* Dashed rules between the lines and a mono key column: the ledger motif from
   /konto/selskaber, because this is the same fact stated one screen earlier
   and the two must not look like different documents. */
.nt-onb-receipt-lines > div {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--nt-space-2) var(--nt-space-4);
  padding: var(--nt-space-3) 0;
  border-bottom: 1px dashed var(--nt-border-subtle);
}

.nt-onb-receipt-lines > div:first-child { padding-top: 0; }
.nt-onb-receipt-lines > div:last-child { border-bottom: 0; padding-bottom: 0; }

.nt-onb-receipt-lines dt {
  font-family: var(--nt-font-mono);
  font-size: var(--nt-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--nt-text-tertiary);
}

.nt-onb-receipt-lines dd {
  margin: 0;
  text-align: right;
  font-size: var(--nt-text-base);
  color: var(--nt-text);
  overflow-wrap: anywhere;
  min-width: 0;
}

.nt-onb-receipt-lines dd strong {
  font-family: var(--nt-font-display);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: var(--nt-text-lg);
}

/* The renewal price under the first-year offer. Quiet, but present — hiding
   it is how a 1.495-kr offer becomes a support ticket in twelve months. */
.nt-onb-receipt-renewal {
  display: block;
  font-size: var(--nt-text-sm);
  color: var(--nt-text-tertiary);
}

.nt-onb-receipt .nt-hint { margin-top: var(--nt-space-4); }

/* ── Hvad sker der nu ─────────────────────────────────────────────────── */

/* Same shell/padding rule as .nt-onb-receipt above. */
.nt-onb-next { padding: var(--nt-space-6); }

.nt-onb-next-title {
  margin: 0 0 var(--nt-space-4);
  font-family: var(--nt-font-display);
  font-weight: 600;
  font-size: var(--nt-text-lg);
  letter-spacing: -0.015em;
  color: var(--nt-text);
}

.nt-onb-next-steps {
  display: flex;
  flex-direction: column;
  gap: var(--nt-space-4);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.nt-onb-next-steps li {
  display: flex;
  align-items: flex-start;
  gap: var(--nt-space-3);
  font-size: var(--nt-text-sm);
  color: var(--nt-text-secondary);
  max-width: var(--nt-prose-max);
}

/* Numbered because these happen IN ORDER and two of the three are ours to do.
   Seal, not green: none of it has happened yet. */
.nt-onb-next-num {
  flex: none;
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: var(--nt-radius-full);
  background: var(--nt-seal-soft);
  color: var(--nt-seal-text);
  font-size: var(--nt-text-xs);
  font-weight: 600;
}

.nt-onb-next-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--nt-space-3);
  margin-top: var(--nt-space-6);
}

/* ══════════════════════════════════════════════════════════════════════
   LIVE CVR-OPSLAG på gaflen
   ══════════════════════════════════════════════════════════════════════

   Three lines and a tick, beside the field. Deliberately not the marketing
   teaser card: this person has already bought and needs one thing confirmed —
   that these eight digits are their company. */

.nt-onb-cvr-form { margin: 0; }

.nt-onb-cvr-field {
  display: flex;
  align-items: center;
  gap: var(--nt-space-2);
}

.nt-onb-cvr-field .nt-input { flex: 1; min-width: 0; }
.nt-onb-cvr-field .nt-btn { flex: none; }

.nt-onb-cvr-hit {
  display: flex;
  align-items: flex-start;
  gap: var(--nt-space-2);
  margin-top: var(--nt-space-3);
  padding: var(--nt-space-3);
  border: 1px solid var(--nt-ok-border);
  border-radius: var(--nt-radius);
  background: var(--nt-ok-soft);
}

/* Green, and it means what green always means here: this is in order. It is
   the answer to "is this the right company", not decoration. */
.nt-onb-cvr-tick {
  flex: none;
  display: grid;
  place-items: center;
  width: 1.15rem;
  height: 1.15rem;
  margin-top: 0.1rem;
  border-radius: var(--nt-radius-full);
  background: var(--nt-ok);
  color: var(--nt-on-ok);
}

.nt-onb-cvr-name {
  margin: 0;
  font-weight: 600;
  font-size: var(--nt-text-sm);
  color: var(--nt-text);
  overflow-wrap: anywhere;
}

.nt-onb-cvr-meta {
  margin: 0.1rem 0 0;
  font-size: var(--nt-text-sm);
  color: var(--nt-text-secondary);
  overflow-wrap: anywhere;
}

/* The register did not answer. Neutral, NOT red: the import will still be
   attempted and usually succeeds, so telling somebody their CVR number is
   wrong when it is not would be the worse lie. */
.nt-onb-cvr-note {
  display: flex;
  align-items: flex-start;
  gap: var(--nt-space-2);
  margin-top: var(--nt-space-3);
  font-size: var(--nt-text-sm);
  color: var(--nt-text-secondary);
}

.nt-onb-cvr-note svg { flex: none; margin-top: 0.2rem; }

/* Eight digits is a rule the customer can satisfy by retyping, so this one IS
   an error. */
.nt-onb-cvr-note-error { color: var(--nt-danger-text); }
