/* Neo onboarding — lo-fi prototype. Black and white, square corners, no ornament. */

:root {
  --ink: #111;
  --line: #111;
  --hair: #c9c9c9;
  --muted: #6b6b6b;
  --fill: #ececec;
  --paper: #fff;
  --ground: #f4f4f4;
  --focus: #1558d6;      /* the only accent for focus, nothing else uses it */
  --change: #1558d6;      /* internal mode only: what a changed copy changed, the blue of its label */
  --error: #c62828;      /* meaning: something is wrong right now */
  --ok: #1b7a3f;         /* meaning: this is finished */
  --canvas: 1180px;
  --devbar-h: 0px;      /* height of our own bar on the top edge, 0 for a respondent */
}

/* One focus ring for the whole prototype. Black and white carries the
   design, these two colours carry meaning. */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
input:focus, select:focus, textarea:focus { outline-color: var(--focus); }

/* A ticked radio or checkbox takes the browser's own blue, which reads as
   the blue of a changed copy. Ink keeps them black and white, the change
   rule further down still turns a marked one blue. */
input[type="radio"], input[type="checkbox"] { accent-color: var(--ink); }

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

button, input, select, textarea { font: inherit; color: inherit; }

/* ── canvas ─────────────────────────────────────────────── */

#app { min-height: calc(100vh - var(--devbar-h)); padding-top: var(--devbar-h); }

.plain {              /* screens without the admin frame */
  max-width: 720px;
  margin: 0 auto;
  padding: 48px 24px 64px;
}
.plain.wide { max-width: 900px; }

/* Screen code, always visible, also to respondents: a recording shows which
   screen it was. Bottom right and close to invisible, so it does not compete. */
.code {
  position: fixed;
  bottom: 2px; right: 4px;
  z-index: 60;
  pointer-events: none;
  color: var(--ink);
  opacity: .18;
  font: 9px/1 ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: .04em;
}

/* ── admin frame ────────────────────────────────────────── */

.admin { position: relative; display: flex; min-height: calc(100vh - var(--devbar-h)); background: var(--paper); }

.admin-rail {
  width: 208px;
  flex: 0 0 208px;
  border-right: 1px solid var(--line);
  background: var(--fill);
  padding: 0 0 24px;
  user-select: none;
}

.admin-brand {
  height: 48px;
  display: flex;
  align-items: center;
  padding: 0 14px;
  border-bottom: 1px solid var(--line);
  font-weight: 700;
  letter-spacing: .02em;
}

.admin-nav { padding: 10px 0; }
.admin-nav li {
  list-style: none;
  padding: 7px 14px;
  color: var(--muted);
}
.admin-nav li.on {
  color: var(--ink);
  font-weight: 700;
  background: var(--paper);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.admin-nav ul { margin: 0; padding: 0; }

.admin-main { flex: 1 1 auto; min-width: 0; }

.admin-head {
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 0 20px;
  border-bottom: 1px solid var(--line);
  background: var(--paper);
}
.admin-head .shop { font-weight: 700; }
.admin-head .who { color: var(--muted); }
.admin-head .head-actions { display: flex; align-items: center; gap: 14px; }
.help-btn {
  background: none; border: 1px solid var(--line); padding: 4px 10px;
  font: inherit; font-size: 13px; color: var(--ink); cursor: pointer;
}

/* The guide hides the navigation, so the header carries the identity and
   the one control that brings it back. */
.admin.without-strip .admin-head { position: relative; justify-content: flex-start; gap: 14px; }
.admin.without-strip .admin-head .head-actions { margin-left: auto; }
.admin-brand.inline { height: auto; border-bottom: 0; padding: 0; }
.nav-toggle {
  flex: 0 0 auto; background: none; border: 0; padding: 6px 4px;
  cursor: pointer; line-height: 0;
}
.burger i { display: block; width: 17px; height: 2px; background: var(--ink); margin: 3px 0; }
.nav-drop {
  position: absolute; top: 47px; left: 8px; z-index: 40;
  width: 208px; padding: 8px 0;
  background: var(--fill); border: 1px solid var(--line);
}

.admin-body { padding: 28px 20px 120px; }
.admin-body > .wrap { max-width: 780px; }
.admin-body > .wrap.wide { max-width: 980px; }

/* A narrow window: the rail is folded behind the menu control (ui.js), and
   the header and the rows wrap instead of widening the page (review R7). */
@media (max-width: 720px) {
  .admin-head { height: auto; min-height: 48px; flex-wrap: wrap; padding: 6px 14px; row-gap: 4px; }
  .admin-head .shop { min-width: 0; overflow-wrap: anywhere; }
  .admin-head .head-actions { flex-wrap: wrap; gap: 8px; min-width: 0; }
  .admin-head .who { overflow-wrap: anywhere; min-width: 0; font-size: 13px; }
  .admin-body { padding: 20px 14px 96px; }
  .task { flex-wrap: wrap; }
  .task .cta { white-space: normal; }
  .breadcrumbs ol { flex-wrap: wrap; }
}

/* ── typography ─────────────────────────────────────────── */

h1 { font-size: 22px; line-height: 1.25; margin: 0 0 10px; text-wrap: balance; }
h2 { font-size: 16px; margin: 28px 0 10px; }
p { margin: 0 0 12px; max-width: 62ch; }
.lede { color: var(--muted); margin-bottom: 22px; max-width: 62ch; }
.hint { color: var(--muted); font-size: 12px; margin-top: 4px; }

/* ── chat ───────────────────────────────────────────────── */

.chat-page { padding-top: 28px; }
.chat-head {
  position: sticky;
  top: calc(var(--devbar-h) + env(safe-area-inset-top, 0px));
  z-index: 5;
  background: var(--ground);
  max-width: 640px;
  margin: 0 auto;
  padding: 12px 24px 14px;
  border-bottom: 1px solid var(--hair);
}
.chat-brand { font-size: 12px; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
/* Partner logo lockup: the partner name, Shoptet as the small second line. */
.partner-logo { flex-direction: column; align-items: flex-start; justify-content: center; gap: 1px; line-height: 1.15; }
.admin-brand.partner-logo, .chat-brand.partner-logo { display: flex; }
.admin-brand.partner-logo:not(.inline) { height: auto; min-height: 48px; padding: 6px 14px; }
.partner-logo-under { font-size: 11px; font-weight: 400; letter-spacing: 0; color: var(--muted); text-transform: none; }
.chat-brand.partner-logo { text-transform: none; letter-spacing: 0; }
.chat-brand .partner-logo-main { color: var(--ink); font-weight: 700; font-size: 13px; }
.chat-head h1 { margin: 6px 0 0; }
.chat-step { font-size: 13px; color: var(--muted); margin-top: 4px; }

.chat { max-width: 640px; margin: 0 auto; padding: 26px 24px 140px; }
.thread { margin-bottom: 28px; }
.turn { margin-bottom: 18px; display: flex; flex-direction: column; gap: 7px; }
.bubble { max-width: 78%; padding: 9px 12px; border: 1px solid var(--line); background: var(--paper); }
.bubble.product { align-self: flex-start; }
.bubble.merchant { align-self: flex-end; background: var(--fill); }
.bubble.intro { margin-bottom: 8px; }
/* The question scrolls to stand under the sticky head of the chat, or,
   after the pencil, the note above it does. The head grows with a title
   on two lines, at 390 px above all, so the gap is its real height,
   which the render puts into --chat-head-h (code review of 2.4.2). */
.bubble.ask { margin-bottom: 18px; }
.bubble.ask, .back-note { scroll-margin-top: calc(var(--devbar-h) + var(--chat-head-h, 112px) + 12px); }
.bubble .ask-q { font-size: 18px; line-height: 1.35; text-wrap: balance; }
.bubble .ask-d { margin-top: 7px; }
/* The answer and its pencil share one line on the right. The bubble keeps
   its width and wraps a long answer, even one long word like an e-mail,
   the pencil never drops under it. */
.turn .answer-row { align-self: stretch; display: flex; justify-content: flex-end; align-items: center; gap: 4px; }
.turn .answer-row .bubble.merchant { min-width: 0; overflow-wrap: anywhere; }
.turn .again {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: 0;
  background: none;
  padding: 0;
  /* in ink, a faint pencil would be a second variable in the test of
     the hypothesis (review of tasks 15 to 17) */
  color: var(--ink);
  cursor: pointer;
}
.turn .again:hover { color: var(--ink); background: var(--fill); }
.turn .again-room { flex: none; width: 32px; height: 32px; }
.back-note { margin-bottom: 14px; font-size: 13px; }
/* v2.4.2: the answers after the one being changed, dimmed under the
   composer. Nothing in them reacts, the pencils are on the answers above.
   Dimmed by the frames, the fill and a grey text, not by opacity: the
   text keeps 4.5:1 on its fill, #6b6b6b on #f4f4f4 reads at 4.85:1
   (second review of 2.4.2). */
.chat > .later { margin-top: 40px; padding-top: 24px; border-top: 1px solid var(--line); }
.chat > .later .bubble { border-color: var(--hair); color: var(--muted); }
.chat > .later .bubble.merchant { background: var(--ground); }

.merchant-side { width: 78%; margin-left: auto; }
.composer { padding-top: 2px; }
.choices { display: flex; flex-direction: column; gap: 14px; align-items: stretch; }
/* v2.5: the choices under the question end where the answers end, left of
   the room of the pencil (its 32 px and the gap of 4), so the chat has one
   right edge (review of block 5+6). */
.composer .choices { margin-right: 36px; }
.choices button { width: 100%; text-align: left; background: var(--fill); }
.choices .btn.primary { background: var(--ink); color: var(--paper); }
.choices .btn.now { border-width: 2px; }
/* The way out of the eight categories is an answer too, set apart so it does
   not read as a ninth category. */
.choices .btn.other { background: var(--paper); border-style: dashed; margin-top: 10px; }
.bubble .ask-v { margin-top: 7px; }
.choices .btn.escape {
  width: auto;
  align-self: flex-end;
  border: 0;
  background: none;
  padding: 2px 0;
  color: var(--muted);
  text-decoration: underline;
  text-align: right;
}
.choices .btn.escape:hover { background: none; color: var(--ink); }
.choices .opt.escape { align-items: flex-end; }
.choices .opt.escape .micro { text-align: right; max-width: 42ch; }
.choices .opt { display: flex; flex-direction: column; gap: 4px; }
.choices .opt .micro { margin: 0; color: var(--muted); font-size: 12px; }

/* The full list of categories: a search on top and the list under it, short
   enough to scroll inside the conversation instead of pushing it away. */
.search input[type=search] {
  width: 100%; padding: 8px 10px; margin-bottom: 10px;
  border: 1px solid var(--line); border-radius: 0; background: var(--paper);
}
.search .choices { gap: 8px; max-height: 420px; overflow-y: auto; }
.search .empty { color: var(--muted); font-size: 13px; }
/* The search hides what does not match. A button sets its own display, so
   hidden needs saying here or the whole list stays on screen. */
.search [hidden] { display: none; }

/* ── controls ───────────────────────────────────────────── */

.btn {
  display: inline-block;
  padding: 9px 16px;
  border: 1px solid var(--line);
  background: var(--paper);
  cursor: pointer;
}
.btn:hover { background: var(--fill); }
.btn.primary { background: var(--ink); color: var(--paper); }
.btn.primary:hover { background: #333; }
.btn[disabled] { color: var(--muted); border-color: var(--hair); cursor: not-allowed; }
.actions { display: flex; gap: 10px; align-items: center; margin-top: 26px; flex-wrap: wrap; }
/* v2.3: the own-version actions of a document card, the label of the
   uploaded file, and the footer of the full text. */
.doc-footer { display: flex; gap: 14px; align-items: center; margin-top: 26px; flex-wrap: wrap; }
.own-update .actions { margin-top: 14px; }
.m-own label { display: flex; gap: 8px; align-items: baseline; }
.save-row { display: flex; gap: 14px; align-items: baseline; margin-top: 18px; flex-wrap: wrap; }
/* The buttons of a copy of an admin page, top right as in the admin
   (UI.topActions). A wizard of the admin keeps them at the bottom, Back on
   the left and the way on to the right. */
.adm-top { display: flex; justify-content: flex-end; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 12px; }
[data-top-actions] > .returnTrip-left { margin-right: auto; display: inline-flex; align-items: center; gap: 6px; }
[data-top-actions] > .returnTrip-left:has(+ .returnTrip-left) { margin-right: 0; }
.adm-returnTrip-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.adm-returnTrip-row > .returnTrip-left { display: inline-flex; align-items: center; gap: 6px; }
.returnTrip-left .returnTrip-arrow svg { display: block; }
.actions.wizard > :first-child { margin-right: auto; }

.field { margin: 0 0 18px; max-width: 460px; }
.field.wide { max-width: 100%; }

/* multi-choice as toggles: the same answers, a third of the height */
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.chips .chip {
  padding: 7px 12px;
  color: var(--ink);
  border: 1px solid var(--line);
  background: var(--paper);
  font-size: 14px;
  cursor: pointer;
  text-align: left;
  white-space: normal;
}
.chips .chip:hover { background: var(--fill); }
.chips .chip.on { background: var(--ink); color: var(--paper); }
.field label { display: block; margin-bottom: 4px; }
.field .req { color: var(--ink); }
.field input[type=text], .field input[type=date], .field input[type=email],
.field input[type=tel], .field select, .field textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 0;
  background: var(--paper);
}
.field textarea { min-height: 84px; resize: vertical; }

/* An address in the shape the payment partner takes it. One box would
   give us whatever the merchant felt like typing. */
.address { display: flex; gap: 10px; flex-wrap: wrap; }
.address .part { flex: 1 1 170px; }
.address .part.short { flex: 0 0 110px; }
.address .part.long { flex: 2 1 260px; }
.address label { display: block; margin-bottom: 4px; color: var(--muted); font-size: 12px; }
.address input {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 0;
  background: var(--paper);
}

/* A value that is not ours to change right now: shown, not edited. */
.field.locked { border-left: 3px solid var(--hair); padding-left: 11px; }
.field.locked .val { padding: 2px 0 3px; }

/* A rule we are not sure of yet says so quietly and blocks nobody. */
.field.warn .err.soft { color: var(--muted); font-weight: 400; }
.box.recheck { margin: 0 0 20px; }
.field.check { display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; align-items: start; max-width: 620px; }
.field.check input { margin-top: 3px; }
.field.check label { margin: 0; }
/* microcopy, the document link and the error all sit under the label */
.field.check > :not(input):not(label):not(.ui-infotip-bubble) { grid-column: 2; }
.field.check > .micro { margin-top: 0; }
.field.check > .outlink { justify-self: start; }
.field .err { margin-top: 4px; font-weight: 700; color: var(--error); }
.field.bad > label { color: var(--error); }
.field.bad input, .field.bad select, .field.bad textarea {
  border-width: 2px;
  border-color: var(--error);
}

/* A hidden value and the button that shows it. One row, because the
   button belongs to the box, not to the screen. */
.password { display: flex; gap: 8px; align-items: center; }
.password input { flex: 1; }
.money { display: flex; gap: 8px; align-items: center; }
.money input { max-width: 180px; }
.money .cur { color: var(--muted); }

.upload {
  border: 1px dashed var(--line);
  padding: 18px;
  background: var(--paper);
  max-width: 460px;
}
.upload .file { margin-top: 8px; color: var(--muted); }

.micro {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
}
.micro button {
  border: 0; background: none; padding: 0;
  text-decoration: underline; cursor: pointer; color: var(--muted);
}

/* ── blocks ─────────────────────────────────────────────── */

.box { border: 1px solid var(--line); background: var(--paper); padding: 16px; margin: 0 0 16px; }
.box.flat { background: var(--fill); }

/* A block heading, set once for every block on every screen. Without a
   rule of its own it was ordinary body text and read as the first
   sentence of the block rather than as its name. */
.box .lab {
  font-weight: 600;
  font-size: 15px;
  line-height: 1.35;
  letter-spacing: .01em;
  margin-bottom: 10px;
}

/* Reference, not work. The frame stays so the block keeps its edges, the
   fill and the black line go, so the block reads as something to read
   instead of something to do. */
.box.quiet { background: transparent; border-color: var(--hair); }

/* What a block is missing, said inside the block instead of in a list at
   the top of the screen. Bold, because it is the one thing in the block
   that asks for something. */
.box-state {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--hair);
  font-weight: 600;
}

/* A heading and a way to change the group on one line, so the way to
   change it cannot read as the first item of the group. */
.box-head {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
}
.box-head .lab { margin-bottom: 0; }

/* A way to change something that is not missing anything is not a task.
   A button would raise it to the level of the screen's own action. */
.change-link {
  color: var(--ink);
  background: none;
  border: 0;
  padding: 0;
  text-decoration: underline;
  cursor: pointer;
  font: inherit;
}

/* A way to another branch of the same task, said quietly under the work. */
.secondary { margin: 0 0 16px; }
.secondary .micro { max-width: 60ch; }

/* The count above the button. It is what is left of the list at the top:
   the screen says how much, the blocks say what. */
.summary { font-weight: 600; margin: 22px 0 10px; }
.state-banner { border: 1px solid var(--line); background: var(--fill); padding: 12px 14px; margin: 0 0 20px; }
.state-banner .lab { display: flex; gap: 8px; align-items: baseline; font-weight: 700; }

/* ── the mark of a state ─────────────────────────────────── */
/* An emoji brings its own colour and we cannot overrule it, so the mark
   is the only coloured thing and the chip around it stays grey. Two
   nearly matching colours for one fact would read as a mistake. */

.reg {
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
  font-size: 13px;
  line-height: 1;
}

.chip {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 2px 8px;
  border: 1px solid var(--hair);
  color: var(--muted);
  font-size: 12px;
  white-space: nowrap;
}

/* ── carriers on C7 ─────────────────────────────────────── */
/* The name of a carrier and what we think of it belong on one line. */

.carrier-head { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; margin-bottom: 6px; }

/* A recommendation has to look like one. The quiet chip reports a state,
   this one says we would do it, so it is the only solid mark on the page. */
.chip.recommended { background: var(--ink); color: var(--paper); border-color: var(--ink); }

.ph { background: var(--fill); border: 1px solid var(--hair); }

/* ── dashboard ──────────────────────────────────────────── */

.gate-item { display: flex; gap: 12px; align-items: center; justify-content: space-between; padding: 8px 0; border-top: 1px solid var(--hair); }
.gate-item:first-of-type { margin-top: 8px; }
.gate-item .btn { padding: 5px 9px; white-space: nowrap; }

/* ── storefront preview (the one non-lo-fi screen) ──────── */

.sf-switch { display: flex; gap: 8px; margin-bottom: 12px; }
.sf-frame { border: 1px solid var(--line); background: var(--paper); margin: 0 auto; }
.sf-frame.mobile { max-width: 375px; margin-left: 0; }
.sf-scroll { max-height: 400px; overflow-y: auto; }
.sf-bar { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-bottom: 1px solid var(--hair); background: var(--fill); color: var(--muted); font-size: 12px; }
.sf-shot { position: relative; line-height: 0; }
.sf-shot img { width: 100%; display: block; }
.sf-name {                /* the shop name is its own layer over the export */
  position: absolute;
  font-weight: 700;
  color: #111;
  white-space: nowrap;
  background: #fff;
  padding: 2px 6px;
  line-height: 1.2;
}

/* ── screens outside the delivery ───────────────────────── */
/* The bar is inverted on purpose. It is talk about the prototype, not a
   part of the product, and nobody should mistake it for one. */

.outside { min-height: 100vh; }

.outside-bar {
  position: sticky;
  top: calc(var(--devbar-h) + env(safe-area-inset-top, 0px));
  z-index: 40;
  padding: 10px 20px;
  background: var(--ink);
  color: var(--paper);
}
.outside-bar .lab {
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  font-size: 11px;
  margin-bottom: 2px;
}

/* ── somebody else's application ────────────────────────── */
/* Same wireframe language, different furniture. The window chrome says
   at a glance that this is not the Shoptet admin. */

.browser {
  max-width: 1000px;
  margin: 24px auto 80px;
  border: 1px solid var(--line);
  background: var(--paper);
}
.browser-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
  background: var(--fill);
}
.browser-dots { display: flex; gap: 5px; }
.browser-dots i { width: 9px; height: 9px; border: 1px solid var(--muted); display: block; }
.browser-url {
  flex: 1 1 auto;
  border: 1px solid var(--hair);
  background: var(--paper);
  padding: 4px 10px;
  font: 12px ui-monospace, "SF Mono", Menlo, monospace;
  color: var(--muted);
}
.browser-body { padding: 0; }

/* Magyar Hosting before the onboarding. The only colour outside the
   meaning colours, and only inside these three pages: the green of its bar
   and button is what makes the page read as Magyar Hosting and not as
   Shoptet. Everything else stays wireframe. */
.plain.whole { max-width: none; padding: 0; }
.mh { --mh-green: #3aa648; --mh-dark: #0b2a2f; --mh-margin: max(24px, calc((100% - 1140px) / 2)); color: var(--ink); background: var(--paper); min-height: calc(100vh - var(--devbar-h)); display: flex; flex-direction: column; }
.mh > :last-child { flex: 1 1 auto; }
.mh-top { display: flex; align-items: center; gap: 24px; padding: 14px var(--mh-margin); border-bottom: 1px solid var(--hair); }
.mh-logo { display: flex; flex-direction: column; line-height: 1.1; }
.mh-logo-main { font-weight: 700; font-size: 20px; color: var(--mh-dark); }
.mh-logo-under { font-size: 11px; color: var(--muted); align-self: flex-end; }
.mh-nav { display: flex; gap: 18px; flex: 1 1 auto; justify-content: center; font-size: 14px; white-space: nowrap; }
.mh-account { border: 1px solid var(--line); padding: 6px 12px; font-size: 13px; white-space: nowrap; }
.mh-strip { height: 10px; background: var(--mh-green); }
.mh-btn { background: var(--mh-green); border-color: var(--mh-green); color: #fff; font-weight: 700; }
.mh-btn:hover { background: var(--mh-green); filter: brightness(.95); }
.mh-hero { padding: 56px var(--mh-margin) 72px; }
.mh-hero > * { max-width: 620px; }
.mh-hero h1 { font-size: 26px; color: var(--mh-dark); margin: 0 0 10px; }
.mh-search { display: flex; border: 1px solid var(--line); background: var(--ground); margin: 20px 0 12px; }
.mh-www { padding: 12px 14px; border-right: 1px solid var(--hair); color: var(--muted); }

.mh-option { display: flex; align-items: center; gap: 10px; margin: 0 0 20px; }
.mh-check { width: 18px; height: 18px; border: 1px solid var(--line); display: inline-flex; align-items: center; justify-content: center; font-size: 13px; background: var(--paper); }
.mh-cart { display: grid; grid-template-columns: 1fr 300px; gap: 24px; padding: 32px var(--mh-margin) 64px; background: var(--ground); }
.mh-cart h1, .mh-portal h1 { font-size: 22px; color: var(--mh-dark); margin: 0 0 14px; }
.mh-table-head { display: flex; justify-content: space-between; padding: 8px 12px; background: var(--mh-dark); color: #fff; font-size: 12px; font-weight: 700; }
.mh-item, .mh-service { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; padding: 14px 12px; background: var(--paper); border-bottom: 1px solid var(--hair); }
.mh-item-name { font-size: 16px; }
.mh-item-kind { font-size: 13px; font-weight: 700; margin-top: 2px; }
.mh-item-domain { font-size: 12px; color: var(--muted); margin-top: 2px; }
.mh-item-price { text-align: right; font-size: 16px; white-space: nowrap; }
.mh-minor { font-size: 12px; color: var(--muted); }
.mh-summary { background: var(--paper); border: 1px solid var(--line); align-self: start; padding: 0 0 16px; }
.mh-summary-title { background: var(--muted); color: #fff; padding: 10px 14px; font-size: 16px; text-align: center; margin-bottom: 8px; }
.mh-summary-row { display: flex; justify-content: space-between; gap: 12px; padding: 4px 14px; font-size: 13px; }
.mh-summary-row > span:last-child { white-space: nowrap; }
.mh-summary-row.strong { font-size: 15px; font-weight: 700; padding-top: 10px; margin-top: 6px; border-top: 1px solid var(--hair); }
.mh-summary .mh-btn { display: block; margin: 14px 14px 0; width: calc(100% - 28px); }
.mh-portal { padding: 32px var(--mh-margin) 64px; background: var(--ground); }
.mh-paid { border: 1px solid var(--mh-green); background: var(--paper); padding: 10px 14px; margin: 0 0 20px; font-weight: 700; }
.mh-service { display: grid; grid-template-columns: 1fr auto 230px; align-items: center; }
.mh-service > :last-child { justify-self: end; }
.mh-state { font-size: 12px; border: 1px solid var(--ok); color: var(--ok); padding: 2px 8px; }
@media (max-width: 720px) {
  .mh-nav { display: none; }
  .mh-cart { grid-template-columns: 1fr; }
  .mh-service { grid-template-columns: 1fr auto; }
  .mh-service > :last-child { grid-column: 1 / -1; justify-self: stretch; }
}

/* mail client: a top bar with search, then folders beside the messages */
.mailapp-top {
  display: flex;
  align-items: center;
  gap: 16px;
  height: 56px;
  padding: 0 16px;
  border-bottom: 1px solid var(--line);
}
.mailapp-top .app { font-weight: 700; letter-spacing: .02em; }
.mailapp-top .search {
  flex: 1 1 auto;
  max-width: 420px;
  border: 1px solid var(--hair);
  background: var(--fill);
  padding: 6px 10px;
  color: var(--muted);
}
.mailapp-body { display: flex; align-items: stretch; }
.mailapp-rail {
  width: 140px;
  flex: 0 0 140px;
  border-right: 1px solid var(--hair);
  padding: 12px 0;
}
.mailapp-rail div { padding: 5px 16px; color: var(--muted); font-size: 13px; }
.mailapp-rail div.on { color: var(--ink); font-weight: 700; }
.mailapp-main { flex: 1 1 auto; min-width: 0; padding: 0; }

.mail-list { border-bottom: 1px solid var(--line); }
.mail-row {
  display: flex;
  gap: 14px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--hair);
}
.mail-row .from { width: 150px; flex: 0 0 150px; color: var(--muted); }
.mail-row .subj { min-width: 0; }
.mail-row.active { background: var(--fill); }
.mail-row.active .from, .mail-row.active .subj { color: var(--ink); font-weight: 700; }

.mail-open { padding: 20px 16px 26px; }
.mail-open .from { color: var(--muted); margin-bottom: 4px; }
.mail-open h2 { font-size: 17px; margin: 0 0 10px; }
.mail-open p { margin: 0 0 16px; max-width: 58ch; }

/* partner sign-in: one centred card, nothing around it */
.partner {
  background: var(--ground);
  padding: 56px 20px 72px;
  display: flex;
  justify-content: center;
}
.partner-card {
  width: 100%;
  max-width: 340px;
  border: 1px solid var(--line);
  background: var(--paper);
  padding: 24px 22px 26px;
}
.partner-brand {
  border: 1px solid var(--line);
  padding: 8px 12px;
  margin: 0 0 20px;
  font-weight: 700;
  letter-spacing: .04em;
  text-align: center;
}
.partner-card h1 { font-size: 18px; }
.partner-card .btn { width: 100%; }

/* ── overview widgets ───────────────────────────────────── */
/* A stand-in for the admin overview. One real widget, the rest is
   furniture so the widget reads as one of several. */

.widgets {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px;
  margin: 0 0 18px;
}
.widget {
  border: 1px solid var(--line);
  background: var(--paper);
  padding: 14px 16px 16px;
}
.widget .lab {
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.widget .head { font-weight: 700; margin-bottom: 12px; text-wrap: balance; }
.widget.alert { grid-column: 1 / -1; border-width: 2px; }
.widget.empty {
  grid-column: 1 / -1;
  border: 1px dashed var(--hair);
  color: var(--muted);
  padding: 34px 16px;
  text-align: center;
}
.widget.calm { grid-column: 1 / -1; }
.widget.calm .head { margin-bottom: 6px; }

/* ── a dialog over a page ──────────────────────── */
/* The four card messages arrive long after setup and open over the admin
   overview, so the merchant can see where they are. Our own bar on the top
   edge and the screen code stay above the layer and uncovered.
   v2.4.2: the layer is fixed to the window, not to the top of the page.
   On a page scrolled down, at 390 px above all, the dialog began above
   the window and the shadow ended halfway down. A dialog taller than the
   window scrolls inside itself.
   The layer lies over the floating setup bar too (z-index 40), the bar
   goes under the shadow with the rest of the page. Above it, it stayed
   bright, took clicks that closed the dialog, and at 390 px it covered
   the bottom of a tall dialog (code review of 2.4.2). The screen code
   (60) and our own bar (70) stay above. */

.modal-layer {
  position: fixed;
  top: var(--devbar-h);
  left: 0; right: 0; bottom: 0;
  z-index: 50;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 40px 20px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.modal-shadow { position: fixed; top: var(--devbar-h); left: 0; right: 0; bottom: 0; background: rgba(17, 17, 17, .42); }
.modal {
  position: relative;
  width: 100%;
  max-width: 620px;
  max-height: calc(100vh - var(--devbar-h) - 96px);
  max-height: calc(100dvh - var(--devbar-h) - 96px);
  overflow: auto;
  background: var(--paper);
  border: 2px solid var(--line);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .10), 0 18px 40px rgba(0, 0, 0, .22);
  padding: 34px 28px 22px;
}
.modal > div > :first-child { margin-top: 0; }
.modal-x {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid transparent;
  background: none;
  color: var(--ink);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.modal-x:hover { border-color: var(--hair); }

/* ── a screen that fills the height ──────────────────────── */
/* The shop preview is the reward of the whole first stretch, so it
   takes everything between the header and the footer of the page
   and shrinks with the window instead of scrolling out of view. */

/* a definite height, not a minimum: without it the flex children
   have nothing to shrink against and the preview keeps its full size */
.plain.fill { display: flex; flex-direction: column; height: calc(100vh - var(--devbar-h)); min-height: 520px; padding-bottom: 24px; }
.plain.fill > .fill { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.sf-page { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.sf-page .sf-frame { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.sf-page .sf-scroll { flex: 1 1 auto; min-height: 0; max-height: none; }

/* a tool that opens in its own window, drawn as text, not as a mock-up */
.tool { padding: 30px 26px 34px; max-width: 620px; }
.tool h1 { margin-top: 0; }

/* ── launch guide: four stages, one panel ────────────────── */
/* The dashboard is one column of sections. Until 22.09. it opened with
   a row of four cards and a panel under the selected one, which claimed
   the four groups are comparable stages of one path. They are not, and
   the row cost the height above the content and hid three groups out of
   four behind a click. A measure keeps the chip on the right within
   reach of the name on the left. */

.dash-content { max-width: 820px; }
.dash-content h2 { margin: 26px 0 6px; }
.dash-content > h2:first-child { margin-top: 14px; }
.dash-content > .box { margin-bottom: 4px; }

/* The bar and the count used to live inside a stage card. With the cards
   gone they stand on their own, under the line that names the group. */
.ctrack { height: 6px; background: var(--fill); border: 1px solid var(--hair); margin: 0 0 5px; }
.cfill { height: 100%; background: var(--ink); }
.cfill.done { background: var(--ok); }
.ct { font-size: 12px; color: var(--muted); margin-bottom: 9px; }

/* The section lede outlived the stage panel: after the first milestone
   the sections have no panel around them. */
.panel-lede { color: var(--muted); margin: 0 0 10px; max-width: 62ch; }

.tasks { border: 1px solid var(--hair); }
.task {
  display: flex; gap: 12px; align-items: center;
  width: 100%; padding: 11px 13px;
  border: 0; border-bottom: 1px solid var(--hair);
  background: none; text-align: left; cursor: pointer;
  font: inherit; color: inherit;
}
.task:last-child { border-bottom: 0; }
/* The finished publishing row with the way to the shop under it. The pair
   reads as one row, so the rule between rows goes under the link. */
.task-s-link { border-bottom: 1px solid var(--hair); }
.task-s-link:last-child { border-bottom: 0; }
.task-s-link > .task { border-bottom: 0; }
.task-link { padding: 0 13px 11px; font-size: 13px; }
.task:hover { background: var(--fill); }
.task .n { flex: 1 1 auto; min-width: 0; }
.task .n .name { font-weight: 500; }
.task .n .sub { color: var(--muted); font-size: 12px; }
/* What the task will wait for. Not muted like the description, because it
   is the one thing on the row the merchant has to act on elsewhere. */
.task .n .wait { font-size: 12px; margin-top: 5px; }
/* An eyebrow, not a third line of the paragraph. */
.task .n .rec {
  font-weight: 700; font-size: 11px; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 3px;
}
/* Seven identical rows give the eye nothing to land on, so the next step
   stops being a row and becomes a card with an action. Size, weight, fill
   and space are the whole palette here, colour is not available. */
.task.recommended {
  border-left: 4px solid var(--ink);
  background: var(--fill);
  padding: 17px 15px;
  align-items: center;
}
.task.recommended .n .name { font-size: 17px; font-weight: 700; }
.task.recommended .n .sub { font-size: 13px; }
/* Why the recommended step matters now. Not muted like the description,
   because it is the reason to press the button next to it. */
.task .n .why { font-size: 13px; margin-top: 6px; }
.task .cta {
  flex: 0 0 auto; white-space: nowrap;
  background: var(--ink); color: var(--paper);
  padding: 10px 20px; font-weight: 700; font-size: 14px;
}
.task.invite .n .name { font-weight: 700; }
.task .act { font-size: 13px; font-weight: 700; white-space: nowrap; }
.task .act.done { font-weight: 400; color: var(--ok); }
/* An answered offer says what holds and how to change it, on one line. */
.task .act-s-change { display: inline-flex; gap: 12px; align-items: baseline; white-space: nowrap; }
.task .act-s-change .change-link { font-size: 13px; }
/* The card the merchant put aside, or an application we closed. It stays
   on the page and reads as the quietest row on it, so it never competes
   with a task that is owed. */
.task.quiet .n .name { font-weight: 400; }

/* The merchant's own categories, each with the slot for the official
   number we will know later. The slot is visible so it is clear that
   something belongs there, and empty because we do not have it. */
.cat-list { list-style: none; margin: 8px 0 10px; padding: 0; }
.cat-list li { display: flex; align-items: center; gap: 12px; padding: 5px 0; border-bottom: 1px solid var(--hair); }
.cat-list li:last-child { border-bottom: 0; }
.cat-list .name { flex: 1 1 auto; }
.cat-list .ph.number { flex: 0 0 54px; height: 19px; }

/* B2 shows both halves of the handover at once, what the conversation
   produced and the list the dashboard will open with. The right column
   reuses the dashboard rows, so the next screen reads as the same list. */
.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin: 4px 0 22px; align-items: start; }
/* The tick is the whole point of the left column, so it is big enough to
   read as a reward and it brings its own colour. */
.have li { display: flex; gap: 10px; align-items: flex-start; }
.have .ok, .have .character {
  flex: 0 0 auto; font-size: 19px; line-height: 1.15;
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}
/* The one line of the block that is not done. Bold, the same way a block
   says what it is missing, because it is the only line here that asks for
   something. */
.have li.missing { font-weight: 600; }

/* The right column names the cards of the dashboard, not the tasks in
   them, so the preview sets expectations without looking like a pile. */
.stages .name { font-weight: 500; }
.stages .sub { color: var(--muted); font-size: 12px; margin-top: 2px; }
/* The two lists are a component of their own, not something the grid
   around them makes. E10 uses the left one on its own when nothing was
   left for later, and then there is no grid to hang the rules on. */
.pair ul, ul.have, ul.stages { list-style: none; margin: 0; padding: 0; }
.pair li, ul.have > li, ul.stages > li { padding: 7px 0; border-bottom: 1px solid var(--hair); }
.pair li:last-child, ul.have > li:last-child, ul.stages > li:last-child { border-bottom: 0; }
.pair .task { cursor: default; }
.pair .task:hover { background: none; }
.pair .hint { margin: 10px 0 0; }
/* A stage list with a note under it closes with a rule of its own. The
   note is the same grey and the same size as a stage subtitle, so a list
   that just runs out makes the note read as one more stage. B2 and E10. */
.pair ul.stages > li:last-child { border-bottom: 1px solid var(--hair); }
.pair ul.stages + .hint { margin: 13px 0 0; }
/* v2.5: the preparation of the shop on intro-17, right above the
   note and Continue. A ring while it prepares, the tick when it is done.
   The ring turns only with motion allowed, with reduced motion it stands
   still and the text alone says it is working. */
.prep { display: flex; gap: 10px; align-items: flex-start; margin: 0 0 14px; font-weight: 500; }
.prep .prep-icon {
  flex: 0 0 auto; width: 16px; height: 16px; margin-top: 2px; box-sizing: border-box;
  border: 2px solid var(--hair); border-top-color: var(--ink); border-radius: 50%;
}
.prep.done .prep-icon {
  width: auto; height: auto; margin-top: 0; border: 0; border-radius: 0;
  font-size: 19px; line-height: 1.15;
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}
.prep .prep-text { min-width: 0; overflow-wrap: anywhere; }
@media (prefers-reduced-motion: no-preference) {
  @keyframes prep-turn { to { transform: rotate(360deg); } }
  .prep:not(.done) .prep-icon { animation: prep-turn 900ms linear infinite; }
}
/* A plain list of the merchant's own categories. Used wherever they have
   to be named, because one of them carries commas inside its own name. */
.enumeration-cat { margin: 4px 0 0 0; padding: 0 0 0 16px; }
.enumeration-cat li { border-bottom: 0; padding: 2px 0; list-style: disc; }
.pair .enumeration-cat li { color: var(--muted); }
@media (max-width: 720px) { .pair { grid-template-columns: 1fr; } }

/* what to fetch from an authority before a form can be filled */
.box.prereq { background: var(--fill); }
.steps-list { margin: 0 0 10px; padding-left: 20px; }
.steps-list li { margin-bottom: 5px; }
.box.prereq .note { color: var(--muted); margin: 0 0 12px; }
.outlink { color: var(--ink); }
/* A link with a button right after it on one line keeps the gap that the
   other pairs on one line inside a block keep (.box-head, .box-state). */
.box > .outlink + .btn { margin-left: 12px; }
/* The same gap when the link stands under the button instead (C17). */
.box > .btn + .secondary { margin-top: 12px; }

/* Anything we scroll to after a re-render stops below our own bar. */
[data-scroll-target] { scroll-margin-top: calc(var(--devbar-h) + 16px); }

#devbar {
  position: fixed;
  left: 0; right: 0; top: 0;
  z-index: 70;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  padding: 6px 10px;
  background: var(--ink);
  color: var(--paper);
  font-size: 12px;
}
/* The bar sets display, which would beat the hidden attribute in test mode. */
#devbar[hidden] { display: none; }
#devbar select, #devbar input {
  background: var(--ink);
  color: var(--paper);
  border: 1px solid #666;
  padding: 3px 6px;
  border-radius: 0;
}
/* The step list is half of what its longest name would take. The closed
   list shows the start of a name, the open one shows it whole. */
#devbar select.devbar-jump { width: 320px; max-width: 100%; text-overflow: ellipsis; }
#devbar button {
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--paper);
  padding: 3px 8px;
  cursor: pointer;
}
/* The Comment button during the pick: green, white text, 5.4:1. */
#devbar button.copied { background: var(--ok); border-color: var(--ok); color: #fff; font-weight: 700; }
#devbar .sep { width: 1px; height: 18px; background: #555; }
#devbar .lab { color: #bbb; }
/* The version and the class of the screen for internal reviewers
   (origin-v2.js). Colour is the point here: green new, blue changed,
   grey existing, so they live only in our own bar. */
#devbar .version { font-weight: 700; padding: 2px 6px; border: 1px solid #888; }
#devbar .origin { font-weight: 700; padding: 2px 8px; border-radius: 3px; color: #fff; }
#devbar .origin-new { background: #1b7a3f; }
#devbar .origin-modified { background: var(--change); }
/* v2.4: the grey badges read better on the dark bar, lighter with dark
   text. The map keeps its own grey for the stripe on a white card
   (map.html, --c-existing). */
#devbar .origin-existing, #devbar .origin-placeholder { background: #b5b5b5; color: #111; }
/* The i next to the class of the screen and the box it opens (devbar.js). */
#devbar .devbar-info {
  width: 20px; height: 20px; padding: 0; border-radius: 50%;
  font: italic 700 12px/18px Georgia, serif; text-align: center;
}
#devbar .devbar-info[aria-expanded=true] { background: var(--change); border-color: var(--change); color: #fff; }
#devbar .devbar-pop {
  position: absolute; top: 100%; margin-top: 4px; z-index: 71;
  width: 440px; max-width: calc(100vw - 16px); max-height: 60vh; overflow: auto;
  padding: 12px 14px; background: var(--ink); color: var(--paper);
  border: 1px solid #666; box-shadow: 0 6px 20px rgba(0, 0, 0, .35);
  font-size: 13px; line-height: 1.45;
}
#devbar .devbar-pop[hidden] { display: none; }
#devbar .devbar-pop-part + .devbar-pop-part { margin-top: 10px; }
#devbar .devbar-pop-title { font-weight: 700; color: #bbb; margin-bottom: 2px; }
#devbar .devbar-pop p { margin: 0; }
#devbar .devbar-state { width: 620px; max-height: calc(100vh - var(--devbar-h, 40px) - 16px); }
#devbar .devbar-state-row { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; }
#devbar .devbar-state-row > span { flex: 0 0 120px; color: #bbb; }
#devbar .devbar-state-row select, #devbar .devbar-state-link { flex: 1; min-width: 0; }
#devbar .devbar-state-steps { display: grid; grid-template-columns: 1fr 1fr 2fr; gap: 12px; margin: 8px 0 10px; }
#devbar .devbar-state-steps label { display: flex; align-items: center; gap: 6px; }
#devbar .devbar-state-steps input:disabled + span { opacity: .45; }
/* v2.5: the card controls in the Milestone 3 column stand one above the
   other, label over select, and a control that is off says why under
   itself, in readable text (not the faded one of the box label). */
#devbar .devbar-state-steps select { width: 100%; min-width: 0; }
#devbar .devbar-state-field { margin: 4px 0 8px; }
#devbar .devbar-state-field > span { display: block; color: #bbb; margin-bottom: 2px; }
#devbar .devbar-state-why { display: block; margin: 2px 0 6px; color: #e6e6e6; font-size: 12px; line-height: 1.35; }
#devbar .devbar-state-why[hidden] { display: none; }
#devbar .devbar-state > .devbar-state-why { margin: -2px 0 8px 128px; }
#devbar .devbar-state select:disabled { opacity: .6; }
/* On a narrow window the three columns stand one under another. */
@media (max-width: 660px) {
  #devbar .devbar-state-steps { grid-template-columns: 1fr; }
  #devbar .devbar-state-row { flex-direction: column; align-items: stretch; gap: 2px; }
  #devbar .devbar-state-row > span { flex: none; }
  #devbar .devbar-state > .devbar-state-why { margin-left: 0; }
}
#devbar .devbar-state-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
/* On a changed copy, what changed is drawn in the blue of the label, so a
   reviewer sees where to look (UI.change). Internal mode only, a respondent
   sees the page in its own colours. */
.v2-internal [data-v2-change], .v2-internal [data-v2-change] * { color: var(--change) !important; }
.v2-internal [data-v2-change] { border-color: var(--change) !important; }
.v2-internal [data-v2-change]:is(input, select, textarea, .btn), .v2-internal [data-v2-change] :is(input, select, textarea, .btn) {
  border-color: var(--change) !important; accent-color: var(--change);
}
.v2-internal .btn.primary[data-v2-change], .v2-internal [data-v2-change] .btn.primary { background: var(--change) !important; }
.v2-internal .btn.primary[data-v2-change], .v2-internal .btn.primary[data-v2-change] *,
.v2-internal [data-v2-change] .btn.primary, .v2-internal [data-v2-change] .btn.primary * { color: #fff !important; }

/* ── hub (internal, not part of the tested flow) ────────── */

.hub { max-width: 1000px; margin: 0 auto; padding: 40px 24px 80px; }
.hub table { border-collapse: collapse; width: 100%; margin-bottom: 30px; }
.hub th, .hub td { border: 1px solid var(--hair); padding: 6px 9px; text-align: left; vertical-align: top; }
.hub th { background: var(--fill); }
.hub code { font: 12px ui-monospace, Menlo, monospace; }
/* v2.5: the path of a code link breaks where it must, so the page of Changes
   outside the prototype does not run sideways at 390 px. */
.hub li code { overflow-wrap: anywhere; }

.missing { background: repeating-linear-gradient(45deg, #fff, #fff 6px, #eee 6px, #eee 12px); border: 1px dashed var(--line); padding: 2px 4px; }

/* A published document, shown the way a customer would open it. Narrow
   measure, plain serif, no administration furniture: it has to read as a
   page of its own, not as another screen of the setup. */
.legal_doc { max-width: 640px; margin: 0 auto; padding: 32px 8px 40px; font-family: Georgia, "Times New Roman", serif; }
/* v2.5: the address of the EU page on the legal guarantee is one
   long word, at 390 px it ran the whole page sideways. It breaks only where
   a line has no room. On the desktop it ran past its paragraph too, 20 px
   in Hungarian and 19 px in English at 1280 px, so it wraps there now as
   well, one line (21 px) more. anywhere measures the same as break-word
   at 1280 and 390 px (second review of block 7, measured). */
.legal_doc { overflow-wrap: break-word; }
.legal_doc h1 { font-size: 24px; margin: 0 0 4px; }
.legal_doc h3 { font-size: 15px; margin: 24px 0 4px; }
.legal_doc p { margin: 0; line-height: 1.55; }
.legal_doc .note { font-size: 13px; color: #666666; margin-bottom: 8px; }

/* The one paragraph the card agreements rewrote, while the merchant has
   not approved it yet. The mark is an annotation over the document, not
   part of it, so the label keeps the interface typeface. */
.legal_doc .changed { border-left: 3px solid var(--ink); background: var(--fill); padding: 10px 0 12px 12px; margin: 24px 0 0; }
.legal_doc .changed h3 { margin-top: 6px; }
/* A run of changed paragraphs sits under one marker, so the second and
   third heading need the air the first one gets from the marker above it. */
.legal_doc .changed h3 ~ h3 { margin-top: 18px; }
.legal_doc .brand {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
  font-size: 12px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}

/* Everything under a live prerequisite gate stays readable but steps back,
   so the eye lands on the task that has to happen first. */
.dimmed { opacity: 0.45; }

/* Where the gate sends the merchant when the missing thing is on this very
   screen. Outline rather than a background, so it works on a checkbox row
   and on a whole field alike. */
.highlighted { outline: 2px solid var(--ink); outline-offset: 4px; border-radius: 2px; }
@media (prefers-reduced-motion: no-preference) {
  .highlighted { transition: outline-color 180ms ease-in; }
}

/* ── motion ──────────────────────────────────────────────── */
/* Three kinds and no more (decision). Arrival: something new
   appears where the merchant is looking. Change: a card whose state moved
   while he was away. Progress: the bar moves to its new length. Only the
   Neo layer moves, the chat and Set up your shop. Admin pages and the
   Pay wizard are copies of screens that do not move, so they stay still.
   With reduced motion asked for, everything lands at once. */
@media (prefers-reduced-motion: no-preference) {
  @keyframes motion-arrive {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
  }
  @keyframes motion-highlight {
    from { background-color: var(--fill); }
    to   { background-color: transparent; }
  }
  @keyframes motion-icon {
    from { opacity: 0; }
    to   { opacity: 1; }
  }
  @keyframes motion-done {
    0%, 60% { opacity: 1; }
    100%    { opacity: 0; }
  }
  /* The merchant's own answer is already there. The next question comes
     after a short pause, so it reads as the other side speaking. */
  .chat.motion-next > .bubble.intro,
  .chat.motion-next > .bubble.ask,
  .chat.motion-next > .composer {
    animation: motion-arrive 200ms ease-out 300ms backwards;
  }
  .chat .field > .err { animation: motion-arrive 200ms ease-out; }
  /* The first look at Set up your shop, straight from the intro. The only
     place where things come one after another. */
  .v2-list.motion-ramp_in > li { animation: motion-arrive 200ms ease-out backwards; }
  .v2-list.motion-ramp_in > li:nth-child(2) { animation-delay: 40ms; }
  .v2-list.motion-ramp_in > li:nth-child(3) { animation-delay: 80ms; }
  .v2-list.motion-ramp_in > li:nth-child(4) { animation-delay: 120ms; }
  .v2-list.motion-ramp_in > li:nth-child(5) { animation-delay: 160ms; }
  .v2-list.motion-ramp_in > li:nth-child(n+6) { animation-delay: 200ms; }
  /* The tint waits for the ride to the card, so it is seen. */
  .task.motion-change { animation: motion-highlight 600ms ease-out 250ms backwards; }
  .task.motion-change .chip .reg,
  .task.motion-change .cta { animation: motion-icon 200ms ease-out 250ms backwards; }
  .dash-content .cfill { transition: width 300ms ease-out; }
  .missing-list li.fulfilled { animation: motion-done 1200ms ease-in forwards; }
}
/* A condition met while the merchant was away is ticked off before it
   goes, so he sees what he has just done. With reduced motion it is not
   drawn at all, see render-v2.js. */
.missing-list li.fulfilled { text-decoration: line-through; color: var(--muted); }
.missing-list li.fulfilled::before { content: "✓"; display: inline-block; margin-right: 4px; color: var(--ok); }

/* ── v2: Set up your shop as a list of steps ─────────────── */

.v2-list { list-style: none; margin: 0 0 20px; padding: 0; }
.v2-list > li { border-bottom: 1px solid var(--hair); }
.v2-list > li:last-child { border-bottom: 0; }
.v2-list > li > .task { border-bottom: 0; }
.task .order { color: var(--muted); font-weight: 400; }
/* A locked step reads as a step, just not one to press. */
.task.locked { cursor: default; color: var(--muted); }
.task.locked:hover { background: none; }
.task.locked .n .name { font-weight: 500; }
.task.locked .n .wait { color: var(--ink); }
/* The steps a locked step waits for, as a list under its label. */
.missing-list { margin: 2px 0 0; padding-left: 18px; }
/* A missing value in the admin is a way to fix it, so it reads as a link. */
.link-conditions { background: none; border: 0; padding: 0; font: inherit; color: var(--ink); text-decoration: underline; cursor: pointer; text-align: left; }
/* A row that is done from the merchant's side still opens its page. */
.task .end { display: inline-flex; gap: 10px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.task .cta.secondary { background: none; color: var(--ink); border: 1px solid var(--ink); padding: 5px 14px; font-size: 13px; }
.v2-steps { margin: 0; padding-left: 20px; }
.v2-steps li { margin-bottom: 8px; }

/* ── v2: the admin rail leads where the prototype has a page ── */

.admin-nav li.s-target { padding: 0; }
.admin-nav .nav-link {
  display: block; width: 100%; padding: 7px 14px; border: 0; background: none;
  text-align: left; cursor: pointer; color: inherit; font: inherit;
}
.admin-nav .nav-link:hover { text-decoration: underline; }
.admin-nav a.nav-link { text-decoration: none; box-sizing: border-box; }
.admin-nav a.nav-link:hover { text-decoration: underline; }
/* The sections of the active item, one level in, without the frame of the
   active item. */
.admin-nav .submenu { padding-bottom: 6px; }
.admin-nav .submenu li { padding: 5px 14px 5px 28px; font-weight: 400; color: var(--muted); background: none; border: 0; }
.admin-nav .submenu li.s-target { padding: 0; }
.admin-nav .submenu .nav-link { padding: 5px 14px 5px 28px; }
.admin-nav .submenu li.on { font-weight: 700; color: var(--ink); }
/* Settings unfolds one level deeper: closed groups carry an arrow, the
   open one shows its sections indented under it, as in today's admin. */
/* An item without a page of its own that unfolds (Settings) pads its name,
   not itself, so its sections line up with those of Shoptet Pay. */
.admin-nav li.s-submenu { padding: 0; }
.admin-nav li.s-submenu > .nav-name { display: block; padding: 7px 14px; }
.admin-nav .submenu li.group { padding: 0; }
.admin-nav .submenu .group-name { display: block; padding: 5px 14px 5px 28px; position: relative; }
.admin-nav .submenu .group-name::before { content: ""; position: absolute; left: 16px; top: 50%; margin-top: -3px; border: 3px solid transparent; border-left: 4px solid currentColor; }
.admin-nav .submenu li.group.empty > .group-name::before { content: none; }
.admin-nav .submenu li.open > .group-name { font-weight: 700; color: var(--ink); }
.admin-nav .submenu li.open > .group-name::before { left: 15px; margin-top: -1px; border: 3px solid transparent; border-top: 4px solid currentColor; }
.admin-nav .submenu li.group > ul li { padding-left: 40px; }
/* v2.4.2: a group with sections is a button that unfolds it, and a
   section with a page is a link indented like the others. */
.admin-nav .submenu button.group-name { width: 100%; border: 0; background: none; text-align: left; cursor: pointer; color: inherit; font: inherit; }
.admin-nav .submenu button.group-name:hover { text-decoration: underline; }
.admin-nav .submenu li.group > ul li.s-target { padding: 0; }
.admin-nav .submenu li.group > ul .nav-link { padding-left: 40px; }

/* ── v2: the stand-in admin page ────────────────────────── */

.breadcrumbs ol { list-style: none; margin: 0 0 10px; padding: 0; display: flex; flex-wrap: wrap; gap: 6px;
  font-size: 12px; color: var(--muted); }
.breadcrumbs li + li::before { content: "\203A"; margin-right: 6px; }
.breadcrumbs li:last-child { color: var(--ink); }
/* v2.5: the crumbs stay on one line at 390 px, the first ones give up
   their length with an ellipsis, the last one, the page itself, only when
   it is longer than three quarters of the line. It stands after the rule
   above, which wraps. */
@media (max-width: 720px) {
  .breadcrumbs ol { flex-wrap: nowrap; }
  .breadcrumbs li { flex: 0 3 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* The page itself keeps its whole name while it fits, the crumbs before
     it give up their length first (review of block 5+6). */
  .breadcrumbs li:last-child { flex-shrink: 0; max-width: 75%; }
}
.box.placeholder { border-style: dashed; background: var(--ground); }

/* ── v2: the embedded Shoptet Pay wizard ────────────────── */

.box.inserted { border: 2px dashed var(--line); }
.pay-wizard { border: 1px solid var(--hair); background: var(--paper); padding: 14px; margin-top: 10px; }
.pay-state { margin-bottom: 8px; }
.box.device { border-style: dotted; }

/* ── Set up your shop as milestones (3A+) ─────── */
/* No rules and no frames around a milestone. The milestone is a heading
   next to its number, the space between milestones separates them, and
   only a step the merchant can do now has a frame. */
.bcn { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; border: 1px solid var(--ink); padding: 9px 13px; margin: 0 0 30px; }
.bcn.sample { border-style: dashed; }
.bcn-dot { position: relative; width: 9px; height: 9px; border-radius: 50%; background: var(--ink); flex: none; }
.bcn.sample .bcn-dot { background: transparent; border: 2px solid var(--ink); }
.bcn-dot::after { content: ""; position: absolute; inset: -5px; border-radius: 50%; border: 2px solid var(--ink); opacity: 0; }
.bcn.sample .bcn-dot::after { display: none; }
.bcn-text { display: flex; gap: 8px; flex-wrap: wrap; align-items: baseline; flex: 1 1 auto; min-width: 0; }
.bcn-text b { font-weight: 700; }
.bcn-link { font-size: 13px; }
@media (prefers-reduced-motion: no-preference) {
  .bcn-dot::after { animation: bcn-ping 1.8s ease-out infinite; }
  @keyframes bcn-ping { 0% { transform: scale(.4); opacity: .7; } 80%, 100% { transform: scale(1.4); opacity: 0; } }
  .milestones.motion-ramp_in > .milestone { animation: motion-arrive 200ms ease-out backwards; }
  .milestones.motion-ramp_in > .milestone:nth-child(2) { animation-delay: 60ms; }
  .milestones.motion-ramp_in > .milestone:nth-child(3) { animation-delay: 120ms; }
  .step-tag.motion-change { animation: motion-highlight 600ms ease-out 250ms backwards; }
}
.milestone { padding: 0 0 38px; }
.milestone:last-child { padding-bottom: 6px; }
.milestone-head { display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap; margin-bottom: 10px; }
.milestone-number { width: 30px; flex: none; font-size: 28px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.milestone-number svg, .tag-icon svg { display: block; fill: none; stroke: var(--ink); stroke-linecap: round; stroke-linejoin: round; }
.milestone-number svg { width: 26px; height: 26px; stroke-width: 2.6; }
.dash-content .milestone-name { margin: 0; font-size: 20px; line-height: 1.2; font-weight: 700; }
.milestone-state { font-size: 12px; color: var(--muted); }
.milestone.later .milestone-number, .milestone.later .milestone-name { color: var(--muted); }
.milestone-body { margin-left: 42px; display: grid; gap: 6px; }
.milestone-body > .task.card-step { border: 1px solid var(--ink); border-bottom: 1px solid var(--ink); width: 100%; }
.milestone-body > .task.card-step.recommended { border-width: 2px; }
.milestone-body > .task.card-step:last-child { border-bottom: 1px solid var(--ink); }
.milestone-body > .task.card-step.recommended:last-child { border-bottom-width: 2px; }
.task.quiet-step { border: 0; padding: 4px 0; display: flex; gap: 6px 14px; flex-wrap: wrap; justify-content: space-between; align-items: baseline; font-size: 13px; }
.task.quiet-step .n { flex: 0 1 auto; }
.task.quiet-step .n .name { font-weight: 400; color: var(--muted); }
.quiet-missing { display: flex; gap: 4px 6px; flex-wrap: wrap; align-items: baseline; font-size: 12px; color: var(--muted); margin: 0; }
.quiet-missing .missing-list { display: inline; margin: 0; padding: 0; list-style: none; }
.quiet-missing .missing-list li { display: inline; }
/* The comma that parts the items is the end of the item before
   (missingList in render-v2.js), and only the name of a link is
   underlined. A condition met a moment ago keeps a gap before its tick. */
.quiet-missing .missing-list li.fulfilled { margin-left: 6px; }
.link-conditions.has-label { text-decoration: none; }
/* The note of a Save that kept the page, below the row of its button
   (UI.savedNote in ui.js). */
.box[data-saved] { margin-top: 12px; }
.link-conditions.has-label .link-label { text-decoration: underline; }
.quiet-missing .link-conditions { color: var(--muted); }
.step-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.step-tag { display: inline-flex; gap: 6px; align-items: center; border: 1px solid var(--hair); background: var(--paper); padding: 3px 9px; font: inherit; font-size: 12px; color: var(--ink); cursor: pointer; }
.step-tag:hover { background: var(--fill); }
.tag-icon svg { width: 13px; height: 13px; stroke-width: 2.4; }
.tag-state { color: var(--muted); }
.tag-state::before { content: "· "; }
@media (max-width: 720px) {
  .milestone-body { margin-left: 0; }
  .milestone-number { width: auto; }
}
.milestone-body > .task.card-step.recommended { background: var(--paper); }
.milestone-body > .task.card-step:hover { background: var(--fill); }

/* The stand-in for the administration at the end of the Czech segmentation. */
.mock-admin { min-height: 50vh; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
.mock-admin h1 { color: var(--muted); }

/* ── Developer layer ─────────────────────────────────────── */
/* devbar.js, internal mode only, off by default. The badges of the data
   sources say where a field or a state takes its data from, the colour is
   how sure we are. They keep their colours inside a changed copy, whose
   blue would otherwise repaint them. */
#devbar .devbar-toggle { background: var(--ink); color: var(--paper); border: 1px solid #888; }
#devbar .devbar-toggle.on { background: #f2c94c; color: #1a1a1a; border-color: #f2c94c; }
.dev-layer .dev-tag, .dev-layer .dev-tag * {
  display: inline-block;
  max-width: 100%;
  margin: 4px 0 0;
  padding: 1px 6px;
  border-radius: 3px;
  font: 600 11px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  color: #fff !important;
  text-decoration: none;
  overflow-wrap: anywhere;
  white-space: normal;
  vertical-align: middle;
}
.dev-layer .dev-tag:hover { text-decoration: underline; }
.dev-layer .dev-certainty-verified-code { background: #1b7a3f !important; }
.dev-layer .dev-certainty-verified-doc { background: #1f5fbf !important; }
.dev-layer .dev-certainty-assumption { background: #c25e00 !important; }
.dev-layer .dev-certainty-unknown { background: #b3261e !important; }
/* A row of Set up your shop keeps its own width, the badge goes under it. */
.dev-layer .milestone-body > .dev-tag, .dev-layer .step-tags > .dev-tag { justify-self: start; align-self: center; margin: 0; }
/* What only simulates the real thing, with the name of the simulation. */
/* The label sits above the element in a gap of its own, so it covers
   nothing of the page. */
/* An outline and a label in the top left corner, over the outline: the
   layout stays what the respondent sees (review). */
.dev-layer [data-sim] { outline: 2px dashed #c25e00 !important; outline-offset: 3px; position: relative; }
.dev-layer [data-sim]::before {
  content: "Simulation: " attr(data-sim);
  position: absolute;
  left: -5px; top: -5px;
  transform: translateY(-50%);
  max-width: calc(100vw - 32px);
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 1px 6px;
  background: #c25e00;
  color: #fff !important;
  font: 600 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
  text-align: left;
  white-space: nowrap;
  pointer-events: none;
  z-index: 5;
}
/* A stand-in screen, not a design (origin-v2.js, class placeholder). */
.dev-layer .dev-strip {
  margin: 0;
  padding: 6px 12px;
  background: repeating-linear-gradient(135deg, #fff3cd 0 12px, #ffe8a3 12px 24px);
  border-bottom: 2px dashed #c25e00;
  color: #5a3a00;
  font: 700 12px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
  text-align: center;
}

/* The certainty chips of the states page and the data dictionary. */
.dl-tag { display: inline-block; font-size: 12px; font-weight: 600; padding: 1px 7px; border-radius: 10px; border: 1px solid; white-space: nowrap; }
.dl-j-verified-code { color: #1b5e33; background: #e3f2e8; border-color: #8cc3a0; }
.dl-j-verified-doc { color: #1d4f75; background: #e4eef6; border-color: #93b6d2; }
.dl-j-assumption { color: #7a4e00; background: #fbf0d9; border-color: #e0bf7a; }
.dl-j-unknown { color: #a11d1d; background: #fbe5e5; border-color: #e3a0a0; }

/* ── one step list component (v2.4) ─────────────────────── */
/* Set up your shop, invoicing-01 and carriers-01 share this look:
   cards with a thin dark frame 6 px apart, done items as tags under the
   open ones, one recommended item with a 2 px frame. */

.step-list { display: block; }
.step-group { margin: 0 0 18px; }
.step-group-head { display: flex; align-items: baseline; gap: 10px; margin: 22px 0 10px; }
.step-group-number { font-size: 15px; font-weight: 700; color: var(--muted); min-width: 14px; }
.step-group-name { margin: 0; font-size: 16px; }
.step-group-count { color: var(--muted); font-size: 13px; margin-left: auto; }
.step-group-body { display: flex; flex-direction: column; gap: 6px; }

.step-item {
  position: relative; display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 14px 16px; border: 1px solid var(--ink); background: var(--paper);
  text-align: left; font: inherit; cursor: default;
}
button.step-item { cursor: pointer; }
.step-item .n { min-width: 0; }
.step-item .name { font-weight: 600; font-size: 15px; }
.step-item .sub { color: var(--muted); font-size: 13px; margin-top: 2px; max-width: 62ch; }
.step-item .st { display: flex; align-items: center; gap: 6px; margin-top: 8px; color: var(--muted); font-size: 12px; }
.step-item .st svg, .step-item .step-state { width: 16px; height: 16px; }
.step-item .step-state svg { width: 16px; height: 16px; stroke: var(--wait, #b56a00); }
.step-item .step-state { display: inline-block; }
.step-item .actions { flex: none; display: flex; gap: 8px; align-items: center; }
.step-item .rec {
  font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--muted);
  margin-bottom: 6px;
}
/* White like every other card: the grey highlight of the old task row
   (.task.recommended above) must not leak into the component, the cards
   of every screen that uses it look the same (review of 2.4). */
.step-item.recommended { border-width: 2px; padding: 13px 15px; background: var(--paper); }
button.step-item:hover { background: var(--fill); }
.step-item.recommended .name { font-size: 17px; font-weight: 700; }
.step-item.recommended .rec { color: var(--ink); font-weight: 600; }
.step-item.locked { border-color: var(--hair); cursor: default; color: var(--ink); background: var(--paper); }
.step-item.locked .name { color: var(--muted); }
.step-outside-lab {
  font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--muted);
  margin-bottom: 4px;
}
/* The outside card opens nothing, so it must not hover like a button
   (review of 2.4). */
.step-item .step-outside-lab { cursor: default; }
.step-item:has(> .n > .step-outside-lab):not(button):hover { background: var(--paper); }
.step-tag.motion-arrive { will-change: transform, opacity; }

.step-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }

/* ── the floating setup bar (v2.4, variant C) ───────────── */
/* A strip 16 px above the bottom edge, left edge in line with the content,
   width by the content of the page (780 px form, 980 px wide page), 1 px
   frame in the ink colour, white, a light shadow so it reads as lying
   above the page, square corners. It stands in the flow of the page as the
   last element and sticks to the bottom edge, so at the end of the page
   it sits under the content and covers nothing. */
.setup-bar {
  position: sticky; bottom: 16px;
  align-self: flex-end; width: 100%;
  margin: 24px 0 16px;
  border: 1px solid var(--ink);
  background: var(--paper);
  box-shadow: 0 6px 18px rgba(17, 17, 17, .14);
  padding: 10px 14px;
  z-index: 40;
}
.setup-bar-head {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted);
}
.setup-bar-head .setup-bar-step { color: var(--ink); }
.setup-bar-done { color: var(--ok); text-transform: none; letter-spacing: 0; font-size: 12px; margin-left: 6px; }
.setup-bar-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-top: 6px; }
.setup-bar-text { font-size: 14px; max-width: 56ch; }
.setup-bar-actions { display: flex; gap: 8px; flex: none; }
/* v2.5, 390 px: a strip of sentence and buttons, under 15 % of the window
   (844 px). The label and the step name are for the screen reader here, the
   page under the bar is the step and its sentence and buttons name the
   rest. A buttons' text may wrap, the long ones (Not now, I send parcels
   myself) take two lines. */
@media (max-width: 720px) {
  .setup-bar { margin-left: 10px; margin-right: 10px; bottom: 10px; padding: 5px 12px; }
  .setup-bar-head { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .setup-bar-row { flex-direction: column; align-items: stretch; gap: 6px; margin-top: 0; }
  .setup-bar-text { font-size: 13px; line-height: 1.25; }
  .setup-bar-actions { justify-content: stretch; }
  .setup-bar-actions .btn { flex: 1 1 auto; min-height: 40px; padding: 4px 10px; font-size: 13px; line-height: 1.25; }
}

/* The screen code stands above the floating bar while it is visible. */
.code-over-bar { bottom: 96px; }
/* v2.5: on a phone the bar is a column and grows up to four lines
   (about 125 px with its 10 px from the edge), so the code goes higher. */
@media (max-width: 720px) {
  .code-over-bar { bottom: 142px; }
}

/* v2.4: the shop address row in the header of Set up your shop. */
.dash-head { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin: 0 0 18px; }
.dash-head .shop-link { font-weight: 600; overflow-wrap: anywhere; }
.dash-head .shop-open { margin: 0; }
@media (max-width: 720px) { .dash-head .shop-open { width: 100%; } }

/* ── the shared info icon with a bubble tooltip (v2.4) ──── */
/* The icon stands right after the last word of the label and never falls
   to the next line alone: the line wrapper holds the label and the icon
   in one inline flow. The bubble lies above the page, only one is open
   at a time. */
/* The line is a flex of the label and the icon, so it stays one line
   also as a grid item of .field.check (a grid item blockifies display,
   inline would fall apart). The label keeps its own inline wrap, the
   icon follows its last line. */
.ui-infotip-line { display: inline-flex; align-items: baseline; gap: 4px; max-width: 100%; flex-wrap: wrap; }
.ui-infotip-line > label { display: inline; }
.ui-infotip-line > .ui-infotip { margin-left: 0; }
.ui-infotip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; padding: 0;
  border: 1px solid var(--hair); border-radius: 50%;
  background: var(--paper); color: var(--muted);
  font-size: 11px; line-height: 1; font-family: inherit; cursor: pointer;
  vertical-align: middle; margin-left: 4px;
}
.ui-infotip:hover, .ui-infotip[aria-expanded="true"] { color: var(--ink); border-color: var(--ink); }
.ui-infotip-word { white-space: nowrap; }
.ui-infotip-word .ui-infotip { margin-left: 2px; }
/* These wrappers become the bubble's offset parent, so it scrolls with
   its field. UI.infoTip place() puts it 6 px under the icon and keeps it
   inside the window, left and top here are only the fallback. */
.field:has(> .ui-infotip), .field:has(> .ui-infotip-bubble), .ui-infotip-line { position: relative; }
.ui-infotip-bubble {
  position: absolute; z-index: 70;
  left: 0; top: calc(100% + 6px);
  width: max-content; max-width: min(340px, calc(100vw - 28px)); padding: 8px 10px;
  border: 1px solid var(--ink); background: var(--paper);
  box-shadow: 0 6px 18px rgba(17, 17, 17, .14);
  font-size: 13px;
}
.ui-infotip-bubble[hidden] { display: none; }

/* v2.4: intro-17 lists only step names under the milestones. */
.stages.v2-steps-names .milestone-row { margin: 0 0 10px; }
.stages.v2-steps-names .milestone-name { font-weight: 700; margin: 0 0 2px; }
.stages.v2-steps-names .step-names { color: var(--muted); }

/* The info icon rides inside the label's grid cell, one line with it. */
.field.check > .ui-infotip-line { grid-column: 2; }
.field.check > .ui-infotip-bubble { grid-column: 1 / -1; }
.ui-infotip-line .ui-infotip { margin-left: 2px; }

/* v2.4: the domain field on mh-01, in the style of the search row. */
.mh-domain-input {
  padding: 12px 14px; border: 0; background: var(--paper);
  font: inherit; font-weight: 700; min-width: 0; flex: 1 1 auto;
}
.mh-domain-input:focus { outline: 2px solid var(--ink); outline-offset: -2px; }
.mh-domain-input.bad { outline: 2px solid var(--error); outline-offset: -2px; }
.mh-domain-missing { color: var(--error); font-weight: 700; margin: 6px 0 0; }

/* ── documents-02 as rows (v2.4, varianta C) ─────────────── */
/* One box of four rows instead of six boxes of prose. A row names
   the document, says in grey what it is about, and offers two quiet
   links. Under a narrow screen the links go under the name. The
   block itself carries no frame, the list inside it does, so the
   two never stack into a box in a box. */
.box.bare { border: 0; padding: 0; background: none; }
.m-doc-list { border: 1px solid var(--line); border-radius: 8px; background: var(--paper); }
.m-doc-row { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding: 14px 16px; }
.m-doc-row.sep { border-top: 1px solid var(--hair); }
.m-doc-name { min-width: 0; }
.m-doc-name > span:first-child { font-weight: 700; }
.m-doc-own { margin-top: 2px; }
.m-doc-actions { display: flex; gap: 14px; flex: 0 0 auto; white-space: nowrap; }
.m-doc-actions .outlink { font-weight: 700; }
.quiet-link { color: var(--muted); text-decoration: underline; text-underline-offset: 2px; }
.quiet-link:hover { color: var(--ink); }
@media (max-width: 720px) {
  .m-doc-row { flex-direction: column; align-items: flex-start; gap: 8px; }
}
/* The warning and the consent are one box: the grey note, a line, the
   tick. The dark border says this is the decision, not a reference. */
.box.bare.m-doc-confirm { border: 1px solid var(--ink); border-radius: 8px; background: var(--paper); }
.m-doc-confirm .hint { margin: 0; padding: 14px 16px 0; }
.m-doc-confirm-line { border-top: 1px solid var(--hair); margin: 12px 16px 0; }
.m-doc-confirm .field.check { margin: 10px 16px 14px; }
.own-update { margin: 0 16px 14px; }

/* ── carriers-01 as a step list (v2.4, varianta C) ────────── */
/* The What you need line under the short sentence, closed until the
   merchant opens it. */
.m-carrier-item .m-need { margin-top: 2px; }
.m-need-more { background: none; border: 0; padding: 0; color: var(--muted);
  font: inherit; font-size: 13px; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.m-need-more:hover { color: var(--ink); }
.m-need-full { margin: 6px 0 0; }

/* ── the end of the setup (v2.4, varianta A and E1) ────────── */
/* A box with a thick border says the shop is set up and nothing waits
   here. It arrives with the motion of a landing card and carries the
   Close that settles it. */
.m-setup-finished { border: 2px solid var(--ink); border-radius: 10px; background: var(--paper); margin: 0 0 16px; }
.m-setup-finished .fin-head { display: flex; align-items: center; gap: 10px; padding: 16px 16px 0; }
.m-setup-finished .fin-tick { width: 26px; height: 26px; border-radius: 50%;
  background: var(--ok, #1e8e3e); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 15px; }
.m-setup-finished h2 { margin: 0; font-size: 18px; }
.m-setup-finished .lede { margin: 8px 16px 0; }
.m-setup-finished .hint { margin: 6px 16px 0; }
.m-setup-finished .actions { display: flex; align-items: center; gap: 14px; margin: 0; padding: 12px 16px 16px; }
.m-setup-finished .actions .hint { margin: 0; }

/* ── the import detour on product-01 (v2.4) ───────────────── */
.m-import-detour { margin: 2px 0 14px; }

/* v2.4: the closing box arrives like a landing card (review N3). */
.m-setup-finished.motion-ramp_in { animation: fin-arrive 320ms ease; }
@keyframes fin-arrive {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .m-setup-finished.motion-ramp_in { animation: none; }
}
