/*
 * Booking — the shared skin of every public reservation surface.
 *
 * Written once and read by all four: the assistant, /reserver,
 * /mes-reservations, and the shop pages that carry a picker.
 *
 * WHY THIS FILE EXISTS. Before it, the same colour had three values: the
 * picker defined six `--nb-*` tokens and used them 108 times; /reserver
 * consumed them 33 times WITHOUT ever defining them, falling back on
 * #e4ddd2 / #6a635c / #d9cfc0 — three different "sands"; and
 * /mes-reservations used no token at all, carrying 21 hard-coded colours.
 * Every page also embedded its own <style> block. Measured 2026-08-13.
 *
 * WHERE IT LIVES. These pages sit inside the merchant's own website. Nothing
 * here touches a bare element selector — everything is scoped under `.nb`, and
 * there are no `:has()` rules: one of those leaked out of the webmail layout
 * and repainted half a desk. The sheet stays an island in what it WRITES.
 *
 * But it is no longer an island in what it READS (2026-08-21). The site
 * publishes its own design system — `Website Header Footer Config`, app
 * unpress_core — and our tokens now point at it, keeping the Neoffice values
 * as fallbacks. A reservation used to change brand mid-visit: Cormorant and
 * slate on the site, Forum and clay the moment you clicked « Réserver ».
 */

.nb {
    /* ------------------------------------------------------------------
       THE HOUSE FIRST, US SECOND.
       These pages live inside the trader's own site, and that site has its
       own system: `Website Header Footer Config` (app unpress_core) publishes
       its colours, its fonts and its radii as CSS variables, which its
       header, its footer and its blocks already read. Our screens stayed
       outside it: a booking journey in Forum/clay in the middle of a site in
       Cormorant/slate — the customer changed brand by clicking "Réserver".
       Daniel Moret's complaint, 2026-08-21.

       So every token points at the site's, and our Neoffice value is now only
       a FALLBACK — for an instance with no theme, or a setting left empty.
       The structure stays ours; the dressing is the house's.
       ------------------------------------------------------------------ */

  /* Paper */
  --nb-paper: var(--surface-muted, #faf3ea);
  --nb-paper-bright: var(--surface-color, #fffdf8);
  --nb-sand: var(--border-color, #e8ddd0);
  --nb-sand-soft: var(--border-light, #f4ede4);

    /* The accent: the site's brand colour, clay by default. */
  --nb-clay: var(--primary-color, #d68a59);
  --nb-clay-ink: var(--primary-dark, #b96f3e);
  --nb-clay-wash: var(--primary-bg, #faefe6);
  --nb-clay-tint: var(--primary-light, #fdf7f2);

    /* Ink — the TEXT. The action button follows `--nb-action`. */
  --nb-ink: var(--text-color, #141414);
  --nb-muted: var(--text-muted, #6b6156);
  --nb-faint: var(--text-light, #c6bcb0);

    /* 🔴 The action stands apart from the text: on a site that has a brand
       colour, the button that commits must carry it — that is the one the
       visitor has learned on the other pages. With no theme we fall back on
       the ink, our brand's Anthropic solid. */
  --nb-action: var(--primary-color, #141414);
  --nb-action-hover: var(--primary-hover, #000);

  --nb-success: #2f6e4e;
  --nb-success-bg: #e6f4ea;
  --nb-warn: #a16207;
  --nb-warn-bg: #fdf3dc;
  --nb-danger: #c2410c;
  --nb-danger-bg: #fdeae4;

  --nb-radius-sm: var(--radius-sm, 10px);
  --nb-radius-md: var(--radius, 14px);
  --nb-radius-lg: var(--radius-lg, 20px);
  --nb-radius-pill: var(--radius-pill, 999px);

  --nb-font-title: var(--heading-font, "Forum", Georgia, serif);
  --nb-font-ui: var(--body-font, "Karla", system-ui, -apple-system, sans-serif);

  --nb-ease: cubic-bezier(0.32, 0.72, 0, 1);

  font-family: var(--nb-font-ui);
  color: var(--nb-ink);
  line-height: 1.55;
}

/* ---------------------------------------------------------------------------
 * Primitives
 * ------------------------------------------------------------------------ */

/* The frame that isolates us from the host site. Borders before shadows —
   the system has no shadows at all. */
.nb-frame {
  background: var(--nb-paper);
  border: 1px solid var(--nb-sand);
  border-radius: var(--nb-radius-lg);
  padding: 28px;
}

.nb-panel {
  background: var(--nb-paper-bright);
  border: 1px solid var(--nb-sand);
  border-radius: var(--nb-radius-md);
  padding: 26px;
}

.nb-card {
  background: var(--nb-paper-bright);
  border: 1px solid var(--nb-sand);
  border-radius: var(--nb-radius-md);
  padding: 20px;
}

.nb-eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--nb-clay-ink);
}

.nb-eyebrow--muted {
  color: var(--nb-muted);
}

.nb-title {
  font-family: var(--nb-font-title);
  font-weight: 400;
  font-size: 28px;
  line-height: 1.15;
  margin: 0;
}

.nb-title--lg {
  font-size: 36px;
}
.nb-title--sm {
  font-size: 22px;
}

/* Money and countdowns are titles too: they are read, not scanned. */
.nb-amount {
  font-family: var(--nb-font-title);
  font-weight: 400;
  font-size: 24px;
}

.nb-muted {
  color: var(--nb-muted);
  font-size: 13px;
}

.nb-rule {
  border: 0;
  border-top: 1px solid var(--nb-sand);
  margin: 18px 0;
}

/* ---------------------------------------------------------------------------
 * Buttons — the primary action is INK, never clay.
 * Clay is for eyebrows, links, selected states and the hold banner. An
 * assistant covered in clay loses its point of entry.
 * ------------------------------------------------------------------------ */

.nb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--nb-font-ui);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.2;
  padding: 13px 26px;
  border-radius: var(--nb-radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background 160ms var(--nb-ease), border-color 160ms var(--nb-ease),
    transform 120ms var(--nb-ease);
  /* Touch targets never go under 44px. */
  min-height: 44px;
}

.nb-btn:active {
  transform: scale(0.98);
}

.nb-btn[disabled],
.nb-btn.is-disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

.nb-btn--ink {
  background: var(--nb-action);
  color: #fff;
}
.nb-btn--ink:hover {
  background: var(--nb-action-hover);
  color: #fff;
}

.nb-btn--outline {
  background: transparent;
  border-color: var(--nb-sand);
  color: var(--nb-ink);
}
.nb-btn--outline:hover {
  background: var(--nb-paper);
  color: var(--nb-ink);
}

.nb-btn--clay {
  background: transparent;
  border-color: var(--nb-clay);
  color: var(--nb-clay-ink);
}
.nb-btn--clay:hover {
  background: var(--nb-clay-tint);
}

/* The only solid red in the module. Cancelling is the one irreversible thing
   a customer sets off alone, and the amount due is read BEFORE it. */
.nb-btn--danger {
  background: var(--nb-danger);
  color: #fff;
}

.nb-btn--quiet {
  background: transparent;
  color: var(--nb-muted);
  font-weight: 500;
  padding: 13px 8px;
}
.nb-btn--quiet:hover {
  color: var(--nb-ink);
}

/* ⚠️ The client site's template styles EVERY <button>: background, border,
   padding. A link-button inherited that and came out framed in grey in the
   middle of a card. So we reset everything explicitly rather than hope. */
.nb-link {
  color: var(--nb-clay-ink);
  text-decoration: none;
  font-weight: 600;
  font-size: 14px;
  font-family: inherit;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  box-shadow: none;
  cursor: pointer;
  min-height: 0;
  line-height: inherit;
}
.nb-link:hover {
  color: var(--nb-clay-ink);
  text-decoration: underline;
}

/* ---------------------------------------------------------------------------
 * State pill — a tinted capsule, a 6px dot, and no other hue than these four.
 * Two axes are shown side by side and never merged: a confirmed booking can
 * be unpaid. The first pill carries the dot, the second does not — that alone
 * ranks them without adding a colour.
 * ------------------------------------------------------------------------ */

.nb-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  font-weight: 500;
  padding: 4px 11px;
  border-radius: var(--nb-radius-pill);
  background: var(--nb-sand-soft);
  color: var(--nb-muted);
  white-space: nowrap;
}

.nb-pill__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.nb-pill--success {
  background: var(--nb-success-bg);
  color: var(--nb-success);
}
.nb-pill--warn {
  background: var(--nb-warn-bg);
  color: var(--nb-warn);
}
.nb-pill--danger {
  background: var(--nb-danger-bg);
  color: var(--nb-danger);
}

/* ---------------------------------------------------------------------------
 * Hold banner — "tenu pour vous", with its countdown.
 * The duration is never written in the copy: it comes from
 * Booking Settings.hold_minutes (20 by default) and each merchant sets it.
 * Only the countdown shows a figure.
 * ------------------------------------------------------------------------ */

.nb-hold {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--nb-clay-tint);
  border: 1px solid var(--nb-clay);
  border-radius: 12px;
  padding: 14px 18px;
}

.nb-hold__icon {
  width: 34px;
  height: 34px;
  flex: none;
  border: 1.75px solid var(--nb-clay);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--nb-clay-ink);
}

.nb-hold__body {
  flex: 1 1 auto;
  min-width: 0;
}

.nb-hold__title {
  font-size: 15px;
  font-weight: 600;
}

.nb-hold__note {
  font-size: 13px;
  color: var(--nb-muted);
}

.nb-hold__clock {
  font-family: var(--nb-font-title);
  font-size: 26px;
  color: var(--nb-clay-ink);
  flex: none;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
 * Summary block — one line per element, then a total on paper.
 * ------------------------------------------------------------------------ */

.nb-summary {
  border: 1px solid var(--nb-sand);
  border-radius: 12px;
  overflow: hidden;
}

.nb-summary__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 18px;
  border-top: 1px solid var(--nb-sand);
}

.nb-summary__row:first-child {
  border-top: 0;
}

.nb-summary__total {
  background: var(--nb-paper);
  padding: 16px 18px;
}

.nb-summary__total .nb-amount {
  font-size: 30px;
}

/* What comes WITH a service reads under it, indented: the gas bottle is a
   consequence of the barbecue, not an item one would have added. */
.nb-summary__row--extra {
  padding-left: 34px;
  border-top-style: dashed;
  color: var(--nb-muted);
}

/* ---------------------------------------------------------------------------
 * Option line — four cases, and they are not interchangeable.
 *
 * `included`  : ticked grey, not clickable, "Compris" spelled out — never
 *               CHF 0.–, which reads as a display error;
 * `mandatory` : ticked ink with a clay label, no cross;
 * per person / per night : the arithmetic is written under the name;
 * free qty    : NO checkbox — the counter is the only control and 0 means
 *               "not taken". Two controls for one state end up contradicting
 *               each other, which is exactly what happened in the first draft
 *               (a cleared box with a counter at 1, counted in the total).
 * ------------------------------------------------------------------------ */

.nb-option {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 14px 16px;
  border: 1px solid var(--nb-sand);
  border-radius: 12px;
  background: var(--nb-paper-bright);
}

.nb-option + .nb-option {
  margin-top: 8px;
}

.nb-option--included {
  background: var(--nb-paper);
}

.nb-option__box {
  width: 20px;
  height: 20px;
  flex: none;
  border: 1px solid var(--nb-sand);
  border-radius: 6px;
  background: var(--nb-paper-bright);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--nb-paper-bright);
  margin-top: 2px;
}

.nb-option__box--on {
  background: var(--nb-ink);
  border-color: var(--nb-ink);
}

.nb-option__box--fixed {
  background: var(--nb-faint);
  border-color: var(--nb-faint);
}

/* The spacer that keeps a counter-only line aligned with its neighbours.
   Without it the row shifts left by the width of the box plus its gap. */
.nb-option__spacer {
  width: 20px;
  flex: none;
}

.nb-option__body {
  flex: 1 1 auto;
  min-width: 0;
}

.nb-option__name {
  font-size: 15px;
  font-weight: 600;
}

.nb-option__tag {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--nb-clay-ink);
  margin-left: 8px;
}

.nb-option__how {
  font-size: 13px;
  color: var(--nb-muted);
}

.nb-option__price {
  flex: none;
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
}

.nb-option__price--words {
  font-weight: 500;
  color: var(--nb-muted);
}

.nb-counter {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--nb-sand);
  border-radius: var(--nb-radius-sm);
  overflow: hidden;
  flex: none;
}

.nb-counter button {
  width: 34px;
  height: 34px;
  border: 0;
  background: transparent;
  color: var(--nb-ink);
  font-size: 16px;
  cursor: pointer;
}

.nb-counter button[disabled] {
  color: var(--nb-faint);
  cursor: not-allowed;
}

.nb-counter output {
  min-width: 28px;
  text-align: center;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
 * Calendar — shared by both modes. What differs is what a day says:
 * a slot mode day is free or not; a period mode day carries how many units
 * are left ("6 dispo").
 * ------------------------------------------------------------------------ */

.nb-cal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}

.nb-cal__month {
  font-family: var(--nb-font-title);
  font-size: 20px;
}

.nb-cal__nav {
  width: 30px;
  height: 30px;
  border: 1px solid var(--nb-sand);
  border-radius: 8px;
  background: transparent;
  color: var(--nb-ink);
  cursor: pointer;
  line-height: 1;
}

.nb-cal__dow,
.nb-cal__days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
}

.nb-cal__dow span {
  text-align: center;
  font-size: 12px;
  color: var(--nb-muted);
  padding-bottom: 4px;
}

.nb-day {
  padding: 8px 0;
  text-align: center;
  font-size: 14px;
  border: 1px solid transparent;
  border-radius: var(--nb-radius-sm);
  background: transparent;
  color: var(--nb-muted);
  cursor: pointer;
  line-height: 1.25;
}

.nb-day__left {
  display: block;
  font-size: 11px;
  color: var(--nb-muted);
}

.nb-day--out {
  color: var(--nb-faint);
  cursor: default;
}

.nb-day--free {
  border-color: var(--nb-sand);
}

.nb-day--full {
  background: var(--nb-paper);
  opacity: 0.5;
  cursor: not-allowed;
}

.nb-day--on {
  background: var(--nb-ink);
  border-color: var(--nb-ink);
  color: var(--nb-paper-bright);
  font-weight: 600;
}

.nb-day--on .nb-day__left {
  color: var(--nb-paper-bright);
  opacity: 0.75;
}

/* Nights between the two ends of a range. */
.nb-day--between {
  background: var(--nb-clay-wash);
  border-color: var(--nb-clay-wash);
  color: var(--nb-clay-ink);
}

.nb-day--blocked {
  border-color: var(--nb-danger);
  color: var(--nb-danger);
}

.nb-legend {
  display: flex;
  align-items: center;
  gap: 16px;
  border-top: 1px solid var(--nb-sand);
  margin-top: 12px;
  padding-top: 10px;
  font-size: 12px;
  color: var(--nb-muted);
}

.nb-legend i {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 3px;
  margin-right: 6px;
  vertical-align: -1px;
}

/* ---------------------------------------------------------------------------
 * Slot — the whole range is shown, not just the start. A customer books an
 * hour, and wants to read when it ends.
 * ------------------------------------------------------------------------ */

.nb-slots {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}

.nb-slot {
  padding: 12px;
  border: 1px solid var(--nb-sand);
  border-radius: var(--nb-radius-sm);
  background: var(--nb-paper-bright);
  text-align: left;
  cursor: pointer;
  min-height: 44px;
}

.nb-slot__time {
  font-size: 15px;
  font-weight: 600;
}

.nb-slot__left {
  font-size: 12px;
  color: var(--nb-muted);
}

.nb-slot--on {
  background: var(--nb-ink);
  border-color: var(--nb-ink);
  color: var(--nb-paper-bright);
}

.nb-slot--on .nb-slot__left {
  color: var(--nb-paper-bright);
  opacity: 0.75;
}

.nb-slot--full {
  background: var(--nb-paper);
  opacity: 0.6;
  cursor: not-allowed;
}

.nb-slot--full .nb-slot__time {
  text-decoration: line-through;
}

/* ---------------------------------------------------------------------------
 * Stepper — each step carries the choice made, in clay, under its name.
 * That is what replaces the cart: the recap builds itself under the
 * customer's eyes instead of living on another page.
 * ------------------------------------------------------------------------ */

.nb-stepper {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.nb-step {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid transparent;
  border-radius: 12px;
}

.nb-step--now {
  background: var(--nb-paper-bright);
  border-color: var(--nb-sand);
}

.nb-step__mark {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--nb-sand);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: var(--nb-muted);
}

.nb-step--now .nb-step__mark {
  background: var(--nb-ink);
  border-color: var(--nb-ink);
  color: var(--nb-paper-bright);
  font-weight: 600;
}

.nb-step--done .nb-step__mark {
  background: var(--nb-success);
  border-color: var(--nb-success);
  color: var(--nb-paper-bright);
}

.nb-step__label {
  font-size: 15px;
  font-weight: 500;
}

.nb-step--now .nb-step__label {
  font-weight: 600;
}

.nb-step__value {
  font-size: 13px;
  color: var(--nb-clay-ink);
}

/* ---------------------------------------------------------------------------
 * Skeletons — "we are asking about availability", not a spinner. A spinner
 * says the page is busy; these say what is about to appear.
 * ------------------------------------------------------------------------ */

.nb-skel {
  height: 52px;
  border-radius: var(--nb-radius-sm);
  background: var(--nb-sand-soft);
}

.nb-skel + .nb-skel {
  margin-top: 8px;
}

@media (prefers-reduced-motion: no-preference) {
  .nb-skel {
    animation: nb-pulse 1.6s ease-in-out infinite;
  }
  @keyframes nb-pulse {
    0%,
    100% {
      opacity: 1;
    }
    50% {
      opacity: 0.55;
    }
  }
}

/* ---------------------------------------------------------------------------
 * Mobile — the side stepper is a desktop pattern. Below 900px it becomes a
 * progress bar, and the action moves to a bar stuck at the bottom of the frame.
 * ------------------------------------------------------------------------ */

.nb-progress {
  height: 4px;
  border-radius: var(--nb-radius-pill);
  background: var(--nb-sand);
  overflow: hidden;
}

.nb-progress__fill {
  height: 100%;
  background: var(--nb-clay);
  border-radius: var(--nb-radius-pill);
  transition: width 240ms var(--nb-ease);
}

.nb-actionbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  background: var(--nb-paper-bright);
  border-top: 1px solid var(--nb-sand);
  padding: 14px 16px;
}

@media (max-width: 900px) {
  .nb-frame {
    padding: 16px;
  }
  .nb-panel {
    padding: 18px;
  }
  .nb-cal__dow,
  .nb-cal__days {
    gap: 4px;
  }
  .nb-actionbar {
    margin: 4px -16px -16px;
    border-bottom-left-radius: var(--nb-radius-lg);
    border-bottom-right-radius: var(--nb-radius-lg);
  }
  .nb-title {
    font-size: 24px;
  }
  .nb-title--lg {
    font-size: 28px;
  }
  .nb-summary__total .nb-amount {
    font-size: 24px;
  }
  .nb-hold__clock {
    font-size: 22px;
  }
}

/* ---------------------------------------------------------------------------
 * The assistant — the frame that carries the whole booking, from the first
 * choice to the payment. Below 900px the side column goes away: the stepper is
 * a desktop pattern, and the phone gets a progress line instead.
 * ------------------------------------------------------------------------ */

.nba-grid {
  display: grid;
  grid-template-columns: 264px 1fr;
  gap: 24px;
  align-items: start;
}

.nba-side {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 100%;
}

.nba-house {
  font-family: var(--nb-font-title);
  font-size: 22px;
  line-height: 1.2;
}

/* The foot rises under the stepper rather than the column stretching: three
   steps in a column sized for five would otherwise float. */
.nba-foot {
  margin-top: auto;
  border-top: 1px solid var(--nb-sand);
  padding-top: 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.nba-due {
  display: flex;
  flex-direction: column;
  background: var(--nb-paper-bright);
  border: 1px solid var(--nb-sand);
  border-radius: 12px;
  padding: 12px 14px;
}

.nba-panel {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-height: 420px;
}

.nba-pane {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.nba-when {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 24px;
}

.nba-slots {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.nba-with {
  display: flex;
  align-items: center;
  gap: 10px;
}

.nba-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.nba-fields label,
.nba-wide {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
  color: var(--nb-muted);
}

.nba-wide {
  grid-column: 1 / -1;
}

.nba-input {
    /* The client site's template does not guarantee `border-box`: without it, a
       100% field overflows its column by its padding and its border. */
  box-sizing: border-box;
  max-width: 100%;
  border: 1px solid var(--nb-sand);
  border-radius: var(--nb-radius-sm);
  padding: 12px 14px;
  font-size: 15px;
  font-family: inherit;
  color: var(--nb-ink);
  background: var(--nb-paper-bright);
  min-height: 44px;
}

.nba-input:focus {
  outline: none;
  border-color: var(--nb-clay);
}

.nba-input::placeholder {
  color: var(--nb-faint);
}

/* "Is that you?" — recognition, never a reproach, and never the word
   "register": the customer is booking, not signing up. */
.nba-known {
  background: var(--nb-clay-tint);
  border: 1px solid var(--nb-clay);
  border-radius: 12px;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
}

/* Signing in is an offer, never a condition: the second button must be as
   reachable as the first. */
.nba-known__row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.nba-known__title {
  font-size: 16px;
  font-weight: 600;
}

.nba-note {
  border-top: 1px solid var(--nb-sand);
  padding-top: 12px;
}

.nba-gate {
  border: 1px dashed var(--nb-clay);
  border-radius: 12px;
  padding: 18px;
  background: var(--nb-paper);
}

.nba-err {
  color: var(--nb-danger);
  font-size: 13px;
}

.nba-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border-top: 1px solid var(--nb-sand);
  padding-top: 18px;
  margin-top: auto;
}

.nba-actions--center {
  justify-content: center;
}

.nba-done {
  align-items: center;
  text-align: center;
  padding: 24px 0;
}

.nba-check {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--nb-success-bg);
  color: var(--nb-success);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---------------------------------------------------------------------------
 * What goes with it — the option row, and the questions block.
 *
 * Four cases fit in the same row, and that is deliberate: what is included,
 * what is compulsory, what is counted per person per night, what is taken by
 * quantity. The reader learns ONE shape and reads it again after.
 * ------------------------------------------------------------------------ */

.nba-optlist {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 18px;
}

.nba-opt {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 14px 16px;
  background: var(--nb-paper-bright);
  border: 1px solid var(--nb-sand);
  border-radius: var(--nb-radius-sm);
  cursor: pointer;
  transition: border-color 160ms var(--nb-ease), background 160ms var(--nb-ease);
}

.nba-opt:hover {
  border-color: var(--nb-clay);
}

.nba-opt.is-on {
  border-color: var(--nb-ink);
}

/* What is compulsory does not pretend to be a choice: no hand cursor, no hover
   inviting a click. */
.nba-opt.is-mandatory,
.nba-opt.is-free {
  cursor: default;
}

.nba-opt.is-mandatory:hover,
.nba-opt.is-free:hover {
  border-color: var(--nb-sand);
}

.nba-opt.is-free {
  background: var(--nb-sand-soft);
}

.nba-opt__box {
  width: 20px;
  height: 20px;
  flex: none;
  margin: 2px 0 0;
  border-radius: 6px;
  accent-color: var(--nb-ink);
  cursor: pointer;
}

.nba-opt__box:disabled {
  cursor: default;
}

/* 🔴 The spacer for a free-quantity row. It has NO checkbox — the counter is its
   only control — but without this inert column it shifts 20 px against all the
   others, and the stack goes crooked. */
.nba-opt__gap {
  width: 20px;
  flex: none;
}

.nba-opt__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.nba-opt__name {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
}

.nba-opt__desc,
.nba-opt__calc {
  font-size: 13px;
  color: var(--nb-muted);
}

.nba-opt__tag {
  margin-left: 8px;
  font-size: 11px;
  font-style: normal;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--nb-clay-ink);
}

.nba-opt__tag--free {
  color: var(--nb-success);
}

.nba-opt__amount {
  flex: none;
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  padding-top: 1px;
}

/* The counter: outlined, never filled. It is a setting, not an action. */
.nba-opt__count {
  flex: none;
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--nb-sand);
  border-radius: var(--nb-radius-sm);
  overflow: hidden;
  background: var(--nb-paper-bright);
}

.nba-opt__step {
  width: 34px;
  height: 34px;
  border: 0;
  background: transparent;
  color: var(--nb-ink);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  font-family: inherit;
}

.nba-opt__step:hover {
  background: var(--nb-paper);
}

.nba-opt__step:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.nba-opt__n {
  min-width: 30px;
  text-align: center;
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* The options total has a line of its own: it is a figure one checks, not a note
   at the bottom of a card. */
.nba-opttotal {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-top: 16px;
  padding: 16px 18px;
  background: var(--nb-paper);
  border-radius: var(--nb-radius-sm);
}

/* The trader's questions block — the last block of the same step, separated by a
   sand rule as the mock-up asks. */
.nb-questions {
  margin-top: 24px;
  padding-top: 22px;
  border-top: 1px solid var(--nb-sand);
}

.nb-q-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 14px;
}

.nb-q {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 13px;
  color: var(--nb-muted);
    /* A long answer must not push the column: without this, a field overflows the
       grid instead of shrinking. */
  min-width: 0;
}

.nb-q input,
.nb-q select,
.nb-q textarea {
  width: 100%;
  box-sizing: border-box;
  font-family: var(--nb-font-ui);
  font-size: 15px;
  color: var(--nb-ink);
  background: var(--nb-paper-bright);
  border: 1px solid var(--nb-sand);
  border-radius: var(--nb-radius-sm);
  padding: 11px 13px;
}

.nb-q input:focus,
.nb-q select:focus,
.nb-q textarea:focus {
  outline: none;
  border-color: var(--nb-ink);
}

.nb-q-file {
  color: var(--nb-clay-ink);
  font-size: 12px;
}

@media (max-width: 900px) {
  .nba-grid {
    grid-template-columns: 1fr;
  }
  .nb-q-list {
    grid-template-columns: 1fr;
  }
    /* On a phone the name and the amount no longer fit on one line: the counter
       drops below rather than crushing the label. */
  .nba-opt {
    flex-wrap: wrap;
  }
  .nba-opt__count {
    margin-left: 34px;
  }
  .nba-side {
    min-height: 0;
  }
  /* The stepper is a desktop pattern: on a phone it collapses to the step
     the customer is on, and the choices already made live in the panel. */
  .nba-side .nb-stepper {
    flex-direction: row;
    overflow-x: auto;
  }
  .nba-side .nb-step__value {
    display: none;
  }
  .nba-when {
    grid-template-columns: 1fr;
  }
  .nba-fields {
    grid-template-columns: 1fr;
  }
  .nba-actions {
    position: sticky;
    bottom: 0;
    background: var(--nb-paper-bright);
    margin: 4px -18px -18px;
    padding: 14px 16px;
    border-bottom-left-radius: var(--nb-radius-md);
    border-bottom-right-radius: var(--nb-radius-md);
  }
}

/* An option's description, as the trader wrote it ("un panneau couvre 3 m"). The
   assistant already showed it; the equipment sheet's dialog ignored it, and the
   customer had to guess how many to take. */
.rsv-opt__desc {
  display: block;
  margin-top: 2px;
  color: var(--nb-muted);
  font-size: 12px;
  line-height: 1.45;
}

.rsv-opt__hint {
  font-style: normal;
  color: var(--nb-clay-ink);
}

/* The choice of how to pay. Lives HERE and not in a page, because BOTH surfaces
   show it — the equipment sheet and a service's record. Left in `reserver.html`
   it dressed only half the screens: on the record, the methods showed crammed on
   one line. */
.rsv-pays { margin: 16px 0 4px; }

.rsv-pays__list { display: grid; gap: 8px; margin-top: 8px; }

.rsv-pays__one {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--nb-sand);
  border-radius: var(--nb-radius-sm);
  cursor: pointer;
  background: var(--nb-paper-bright);
}

.rsv-pays__one.is-on {
  border-color: var(--nb-action);
  box-shadow: 0 0 0 1px var(--nb-action);
}

.rsv-pays__one img { max-height: 22px; width: auto; }

.rsv-pays__name { font-weight: 600; }

.rsv-pays__why {
  display: block;
  color: var(--nb-muted);
  font-size: 12.5px;
}

/* The TWINT code, shown in place. In the shared sheet, because both surfaces
   display it — the lesson of the choice block, learned the day before. */
.rsv-qr { margin: 16px 0; text-align: center; }

.rsv-qr__code {
  display: inline-block;
  padding: 14px;
  background: #fff;
  border: 1px solid var(--nb-sand);
  border-radius: var(--nb-radius-md);
}

.rsv-qr__code svg { width: 220px; height: 220px; }
