/* ---- Loyalty (stamp cards) ---- */
/* Setup screen: the enable toggle sits inline with its label (label left, pill right), the
   detail fields reveal below when on. All px / 8px-root rem (rule: custom CSS in px). */
.loyalty-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.slider-pill {
  flex: 0 0 auto;
  white-space: nowrap;
}

.slider-pill.selected {
  background: var(--nimiq-light-blue);
  color: #fff;
}

@media (hover: hover) {
  .slider-pill.selected:hover {
    background: var(--nimiq-light-blue);
    color: #fff;
  }
}

/* Settlement-asset choice on Checkout (NIM / USDC pills). Shown only when the merchant accepts both
   rails; reuses the slider-pill selected (light-blue) styling for the active rail. */
.asset-choice {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

.loyalty-detail,
.usdc-detail {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 16px;
}

.loyalty-sub,
.usdc-sub {
  gap: 6px;
}

.loyalty-stamps-field {
  width: 96px;
}

/* Stamp card: a grid of plain CSS circles. Filled = light-blue accent, empty = the inset-shadow
   gray. No glassmorphism, solid surfaces. The reward-ready state is signalled by the caller's
   green status-alert, not by recoloring the grid. */
.stamp-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  border-radius: 8px;
  box-shadow: inset 0 0 0 2px rgba(31, 35, 72, 0.1);
}

.stamp-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.stamp-card-label {
  font-size: 1.875rem;
  font-weight: 600;
  color: var(--nimiq-blue);
}

.stamp-card-count {
  font-size: 1.625rem;
  color: var(--muted-text);
}

.stamp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, 24px);
  gap: 10px;
}

.stamp-dot {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(31, 35, 72, 0.1);
}

.stamp-dot.filled {
  background: var(--nimiq-light-blue);
}

/* Sell-screen loyalty overlay: reuses the manager-gate overlay/card pattern. */
.loyalty-card-panel {
  max-width: 360px;
  gap: 16px;
  text-align: left;
}

.loyalty-overlay-title {
  margin: 0;
}

.loyalty-overlay-lead {
  margin: 0;
}

.loyalty-attach-field {
  gap: 6px;
}

.loyalty-overlay-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.loyalty-overlay-done {
  justify-content: flex-end;
}

/* ---- Parked / held tickets ---- */
/* Park overlay: same left-aligned card surface as the loyalty/keypad overlays. */
.park-card-panel,
.parked-list-panel {
  max-width: 360px;
  gap: 16px;
  text-align: left;
}

.park-title,
.parked-list-title {
  margin: 0;
}

.park-lead {
  margin: 0;
}

.park-label-field {
  gap: 6px;
}

/* Parked-list loading row: center the inline spinner. */
.parked-list-loading {
  display: flex;
  justify-content: center;
}

/* Scroll the list when several tickets are parked (the card surface stays bounded). */
.parked-ticket-list {
  display: flex;
  flex-direction: column;
  max-height: 320px;
  overflow-y: auto;
}

/* One parked ticket: label + meta on the left, Recall + Delete on the right. */
.parked-ticket-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 0;
}

.parked-ticket-row + .parked-ticket-row {
  box-shadow: inset 0 1px 0 rgba(31, 35, 72, 0.06);
}

.parked-ticket-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1 1 auto;
}

.parked-ticket-label {
  font-size: 1.875rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.parked-ticket-meta {
  font-size: 1.625rem;
  color: var(--muted-text);
}

.parked-ticket-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
}

/* Receipt loyalty block: a labelled section below the summary. */
.loyalty-receipt {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 24px;
}

.loyalty-receipt-title {
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--muted-text);
  margin: 0;
}

.loyalty-receipt-note {
  margin: 0;
}

.loyalty-redeem-row {
  margin-top: 12px;
}

/* ---- R13 overpayment disposition (receipt block) ----
   Mirrors the loyalty-receipt block: a titled section under the paid summary that records whether a
   crypto overpayment is kept as a tip or returned. Non-custodial, bookkeeping only. */
.overpay-receipt {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 24px;
}

.overpay-title {
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--muted-text);
  margin: 0;
}

.overpay-note {
  margin: 0;
}

.overpay-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* ---- Refund overlay (merchant-fulfilled, non-custodial) ----
   Reuses the manager-gate / loyalty overlay scrim + centered card. The merchant pastes the
   buyer's address, picks a full or partial NIM amount, and generates a `nimiq:` request QR they
   scan with their OWN wallet. No new design language: nq-button-s pills + nq-input + qr-code +
   the merchant-fingerprint identicon, matching the loyalty overlay + share-receipt spacing. */
.refund-card-panel {
  max-width: 360px;
  gap: 8px;
  text-align: left;
  /* the generated QR can push the card tall; keep it scrollable inside the scrim, never clipped.
     Tight gap + a one-line CTA + the compact sim banner keep the Generate button above the fold
     (even in the taller simulated + prefilled state) so a merchant sees it without scrolling. */
  max-height: calc(100% - 8px);
  overflow-y: auto;
}

.refund-overlay-title {
  margin: 0;
}

.refund-overlay-note {
  margin: 0;
  font-size: 1.75rem;
  color: rgba(31, 35, 72, 0.6);
}

.refund-addr-field .nq-input {
  font-size: 1.625rem;
}

/* Prefilled-confirmation state: a small secondary-navy note + the buyer address fingerprint,
   shown instead of a blank input when the receipt carried a server-captured buyer address. The
   fingerprint block reuses .merchant-fingerprint and matches the .setup-verify spacing so the
   identicon + chunked address + caption read the same as the setup verify step. No new colors. */
.refund-prefill {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.refund-prefill-note {
  margin: 0;
  font-size: 1.75rem;
  color: rgba(31, 35, 72, 0.6);
}

.refund-prefill .merchant-fingerprint {
  align-items: flex-start;
  margin: 8px 0;
}

.refund-prefill .merchant-fingerprint .address-display {
  font-size: 1.375rem;
}

.refund-prefill .merchant-fingerprint .fingerprint-caption {
  text-align: left;
  font-weight: 600;
}

.refund-prefill-change {
  align-self: flex-start;
}

/* Full vs Partial amount toggle: the same nq-button-s + light-blue .selected pattern as the
   tip/discount/taxable pills (no invented control). */
.refund-amount-toggle {
  display: flex;
  gap: 8px;
}

.refund-amount-pill {
  flex: 1 1 0;
  white-space: nowrap;
}

.refund-amount-pill.selected {
  background: var(--nimiq-light-blue);
  color: #fff;
}

@media (hover: hover) {
  .refund-amount-pill.selected:hover {
    background: var(--nimiq-light-blue);
    color: #fff;
  }
}

/* Partial NIM input + trailing ticker, mirroring the amount component's ticker treatment. */
.refund-partial-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.refund-partial-row .nq-input {
  flex: 1 1 auto;
  min-width: 0;
}

.refund-nim-ticker {
  flex: 0 0 auto;
  font-family: "Fira Mono", monospace;
  font-size: 1.75rem;
  color: var(--muted-text);
}

/* Advisory fiat (display-only, never drives the on-chain amount). */
.refund-fiat-hint {
  margin: 0;
  font-size: 1.625rem;
  color: var(--muted-text);
}

.refund-fiat-hint:empty {
  display: none;
}

.refund-overlay-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.refund-overlay-done {
  justify-content: flex-end;
}

/* ---- Open-amount keypad overlay (pay-what-you-want) ----
   Reuses the manager-gate scrim + centered white card and the pinPad 3x4 nq-button-s key grid.
   Deliberately short (big amount + label + grid + CTA) so the light-blue Add button always stays
   in view above the fold — never clipped (the refund overlay's clip trap). Custom CSS in px /
   8px-root rem per the brand rules; amount in Fira Mono; no header logo; no periods on the title/CTA. */
.keypad-card-panel {
  max-width: 320px;
  gap: 14px;
  align-items: center;
  text-align: center;
}

.keypad-title {
  margin: 0;
}

/* The keyed amount headline, Fira Mono + light-blue accent (a Nimiq amount treatment). */
.keypad-amount {
  font-family: "Fira Mono", monospace;
  font-size: 4.5rem;
  font-weight: 400;
  line-height: 1;
  color: var(--nimiq-light-blue);
  letter-spacing: -0.5px;
}

.keypad-label-field {
  width: 100%;
}

.keypad-label-field .nq-input {
  text-align: center;
}

/* 3x4 register grid, same key metrics as the pinPad. */
.keypad-grid {
  display: grid;
  grid-template-columns: repeat(3, 64px);
  gap: 12px;
  justify-content: center;
}

.keypad-key {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  font-size: 2.5rem;
  font-weight: 600;
  justify-content: center;
  padding: 0;
}

.keypad-key-back {
  font-size: 2.25rem;
}

/* The empty bottom-right cell holds the grid's 3x4 shape without an invented glyph. */
.keypad-key-spacer {
  visibility: hidden;
}

.keypad-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
}

/* ---- Modifier sheet (sell-time variation + option picker) ----
   Reuses the manager-gate card metrics; allows vertical scroll for long menus. The option pills
   reuse the EXACT selected-state pattern of the tip/discount preset pills (.tip-pill.selected),
   so there is zero new design language. No glassmorphism, solid surfaces only (house rule). */
.modifier-sheet-card {
  max-width: 360px;
  /* Dynamic viewport (with the `vh` fallback first) for the same reason as the shell in app.1.css:
     80% of a phone's LARGE viewport can still overflow the VISIBLE one, which would push the bottom
     of the sheet under the browser toolbar (#32). */
  max-height: 80vh;
  max-height: 80dvh;
  overflow-y: auto;
  align-items: stretch;
  text-align: left;
}

.modifier-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 16px 0;
  color: var(--muted-text);
}

/* Group title reuses the sell-zone-title type; tightened margins for the stacked sheet. */
.mod-group-title {
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--muted-text);
  margin: 4px 0 4px;
}

/* min/max rule caption, small secondary-navy. */
.mod-hint {
  font-size: 1.5rem;
  color: var(--muted-text);
  margin: 0 0 8px;
}

.mod-options {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 8px;
}

/* Option / variation pill: nq-button-s base + light-blue .selected, identical to the tip/discount
   presets. Name on the left, price/delta on the right, so each pill reads at a glance. */
.mod-option {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: space-between;
  height: auto;
  min-height: 27px;
  padding: 6px 14px;
}

.mod-option .mod-option-price {
  font-size: 1.5rem;
  opacity: 0.7;
}

.mod-option.selected {
  background: var(--nimiq-light-blue);
  color: #fff;
}

@media (hover: hover) {
  .mod-option.selected:hover {
    background: var(--nimiq-light-blue);
  }
}

.mod-option.selected .mod-option-price {
  opacity: 0.85;
}

/* Running unit-price line reuses the footer-total type/layout. */
.mod-running-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: 8px 0 4px;
  padding-top: 12px;
  border-top: 1px solid rgba(31, 35, 72, 0.1);
}

.mod-running-total .total-label {
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--muted-text);
}

.mod-running-total .total-value {
  font-size: 2.25rem;
  font-weight: 700;
  color: var(--nimiq-light-blue);
}

/* Generated refund-request block: QR + copyable link + buyer fingerprint, centered, with the
   share-receipt's divider/spacing so it reads as a sibling of the receipt's Share block. */
.refund-result:empty {
  display: none;
}

.refund-result {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  margin-top: 8px;
  padding-top: 20px;
  box-shadow: inset 0 1px 0 rgba(31, 35, 72, 0.06);
}

.refund-result-title {
  margin: 0;
  font-size: 1.875rem;
  font-weight: 600;
}

.refund-qr .qr-code {
  display: block;
}

.refund-result .copyable {
  font-size: 1.375rem;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 10px 12px;
}

/* ---- utility ---- */
[hidden] {
  display: none !important;
}

.inline-spinner {
  width: 24px;
  height: 22px;
  color: currentColor;
  vertical-align: middle;
}

/* Mobile: full-width SmallPage with a 16px page margin (viewport meta already present).
   The height floor uses `dvh` (with the `vh` fallback first) for the same reason as the cap in
   app.1.css: `100vh` on a phone is the toolbars-retracted height, so a `vh`-floored card is taller
   than the visible viewport and strands the pinned footer under the browser chrome. With a full
   catalog the internally-scrolling .page-body swallows every touch drag, so the document never
   scrolls that footer back into view and the CTA is simply unpressable (#32). */
@media (max-width: 450px) {
  .small-page {
    height: auto;
    min-height: calc(100vh - 32px);
    min-height: calc(100dvh - 32px);
    margin: 0 16px;
  }
}

