/* ---- status-screen overlay sits over the whole SmallPage ---- */
.status-screen-overlay {
  position: absolute;
  inset: 0;
  z-index: 1000;
}

/* The status-screen success title ships with a period upstream; we strip it (rule 16)
   by setting our own text, but keep title sizing reasonable here. */

/* Reduced-motion: the paid "green flip" (status-screen-grow-from-bottom-button) degrades to
   an instant green takeover for users who opt out of motion. The confirmation stays
   unmistakable; sound/haptic are not motion and are gated by their own capability checks. */
@media (prefers-reduced-motion: reduce) {
  .status-screen.grow-from-bottom-button {
    animation: none;
  }
}

/* =====================================================================================
   THE PAID CONFIRMATION (Andrew, 2026-07-26: "it comes up like three quarters of the way, and
   then it goes up the four ways, and there's, like, a part that's missing").

   Filmed at 390x768, sampling the green screen's own box every frame, both things were real:

     t=1516..1639  top 674 left 48  294x60   <- MOTIONLESS for 125ms, then
     t=1639..2122  ...growing...
     t=2122+       top   6 left  6  378x756  <- and it STOPS 6px short on every side

   1. The dead beat. Upstream's keyframes hold the button box from 0% to 20% of a 600ms animation,
      so a fifth of the run is a freeze. It reads as two separate moves rather than one.
   2. The missing part. `--status-screen-margin: .75rem` insets the screen by 6px, because upstream
      the status screen is a card INSIDE a page. Here it is the full-card overlay, so those 6px are
      a visible frame of the screen underneath showing all the way round the green.

   Both are fixed WITHOUT editing the vendored component (it is pixel-verified and the conformance
   harness diffs against it): the margin is a custom property, so it is overridden, and our own
   keyframes replace the animation for this overlay only.
   ===================================================================================== */
.status-screen-overlay .status-screen {
  /* full-bleed: no 6px frame of the old screen showing around the confirmation */
  --status-screen-margin: 0px;
  /* match the card it now covers, so the corners agree instead of a square on a rounded card */
  border-radius: 1.25rem;
  /* pinned to the card explicitly: .grow-from-bottom-button switches this to position:absolute, and
     with no offsets an absolutely positioned box falls back to its static position. */
  position: absolute;
  inset: 0;
}

/* THE SHAPE IS CLIPPED, NOT RESIZED.
   The first version of this animated max-width / max-height / bottom / left, which are LAYOUT
   properties: every frame reflowed the whole card, and on a throttled phone budget that measured a
   median 12.3ms frame with 5 of 45 frames over 20ms — visible stutter, which is what Andrew kept
   calling choppy after the timing itself was fixed.

   `clip-path: inset()` gets the identical visual (a rounded box growing out of the primary button
   and filling the card) off the main thread, because clipping composites and never reflows. It also
   cannot distort the checkmark or the wordmark the way a transform: scale() would, which is the
   usual cheap alternative. Easing is the brand's own --nimiq-ease. */
.status-screen-overlay .status-screen.grow-from-bottom-button {
  animation: nq-sale-paid-reveal 520ms forwards cubic-bezier(0.25, 0, 0, 1);
  will-change: clip-path, opacity;
}

/* The 0% inset IS the primary button's box, stated from each edge of the card:
   left/right 6rem, bottom 4.25rem, and a top inset of everything above a 7.5rem-tall button. */
@keyframes nq-sale-paid-reveal {
  0% {
    opacity: 0;
    clip-path: inset(calc(100% - 11.75rem) 6rem 4.25rem 6rem round 4rem);
  }
  12% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    clip-path: inset(0 0 0 0 round 1.25rem);
  }
}

@media (prefers-reduced-motion: reduce) {
  .status-screen-overlay .status-screen.grow-from-bottom-button {
    animation: none;
    will-change: auto;
  }
}

html[data-motion="reduce"] .status-screen-overlay .status-screen.grow-from-bottom-button {
  animation: none;
  will-change: auto;
}

/* =====================================================================================
   CUSTOMER DISPLAY: buyer-facing full-card overlay over the Sell SmallPage. Navy surface
   (existing --nimiq-blue-bg gradient), light-blue Total, reused tokens only. No new colors,
   no glassmorphism, no eyebrows/pills (the "Total due" caption labels the headline value).
   Mirrors the .status-screen-overlay layering pattern.
   ===================================================================================== */
.customer-display-overlay {
  position: absolute;
  inset: 0;
  z-index: 1000;
  animation: cd-fade 180ms var(--nimiq-ease, cubic-bezier(0.25, 0, 0, 1));
}

@keyframes cd-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

.customer-display-panel {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: 40px 32px 28px;
  background-image: var(--nimiq-blue-bg);
  color: #fff;
  overflow: hidden;
  /* The card no longer clips (it owns no overflow:hidden now), so a full-card overlay carries its own
     rounded corners to match the SmallPage. */
  border-radius: 1.25rem;
}

.cd-header {
  flex: none;
  text-align: center;
  margin-bottom: 20px;
}

.cd-business {
  margin: 0;
  font-size: 2.75rem;
  font-weight: 700;
  color: #fff;
}

/* Caption under the business name, labeling the headline value (not a decorative kicker). */
.cd-eyebrow {
  margin: 6px 0 0;
  font-size: 1.75rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.6);
}

/* Scrollable per-item list region (qty x name ... line fiat). */
.cd-items {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  margin-bottom: 12px;
  padding-right: 4px;
}

.cd-item-row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 6px 0;
}

.cd-item-qty {
  flex: none;
  font-size: 1.75rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.6);
  min-width: 36px;
}

.cd-item-name {
  flex: 1 1 auto;
  font-size: 2rem;
  font-weight: 600;
  color: #fff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cd-item-value {
  flex: none;
  font-size: 2rem;
  font-weight: 600;
}

.cd-item-value .fiat-amount,
.cd-line-value .fiat-amount {
  color: #fff;
  opacity: 1;
}

/* Breakdown rows (Subtotal/Discount/Tax/Tip) in a readable secondary weight. */
.cd-breakdown {
  flex: none;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  padding-top: 16px;
  margin-bottom: 16px;
}

.cd-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 5px 0;
}

.cd-line-label {
  font-size: 2rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.6);
}

.cd-line-value {
  font-size: 2rem;
  font-weight: 600;
}

/* Discount row: muted/negative styling, mirroring the Sell breakdown's bl-discount (the
   leading minus carries the meaning, no new color). */
.cd-line-discount .cd-line-value .fiat-amount {
  color: rgba(255, 255, 255, 0.6);
}

/* Big high-contrast Total for across-the-counter readability: light-blue per brand,
   scaled up via clamp() on a navy surface. */
.cd-total {
  flex: none;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}

.cd-total-label {
  font-size: 2.5rem;
  font-weight: 700;
  color: #fff;
}

.cd-total-value .fiat-amount {
  font-size: clamp(4.5rem, 14vw, 7rem);
  font-weight: 700;
  color: var(--nimiq-light-blue-on-dark, #0ca6fe);
  opacity: 1;
  line-height: 1.05;
}

.cd-empty {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  font-size: 2.25rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.6);
}

.cd-footer {
  flex: none;
  display: flex;
  justify-content: center;
  padding-top: 16px;
}

/* "Back to register" text-action on the navy surface: light secondary, hover to full white. */
.cd-back {
  color: rgba(255, 255, 255, 0.6);
  font-size: 2rem;
  padding: 8px 16px;
}

@media (hover: hover) {
  .cd-back:hover {
    color: #fff;
  }
}

/* Buyer-facing receipt handoff (#6): the paid surface, reusing the navy customer-display panel.
   The QR sits on a white tile so the blue QR stays scannable against the navy background. */
.cd-receipt {
  text-align: center;
}

.cd-receipt-total {
  flex: none;
  margin: 0 0 24px;
}

.cd-receipt-total .fiat-amount {
  font-size: clamp(4rem, 12vw, 6rem);
  font-weight: 700;
  color: var(--nimiq-light-blue-on-dark, #0ca6fe);
  opacity: 1;
  line-height: 1.05;
}

.cd-receipt-qr-wrap {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
}

.cd-receipt-qr {
  background: #fff;
  border-radius: 12px;
  padding: 20px;
  line-height: 0;
  box-shadow: 0 0.5rem 3.5rem rgba(0, 0, 0, 0.2);
}

.cd-receipt-caption {
  margin: 0;
  font-size: 2.25rem;
  font-weight: 600;
  color: #fff;
}

/* Reduced-motion: drop the fade entry, consistent with the status-screen overlay treatment. */
@media (prefers-reduced-motion: reduce) {
  .customer-display-overlay {
    animation: none;
  }
}

/* =====================================================================================
   CHECKOUT STEP (screen 4): the CUSTOMER-FACING tip + confirm panel, between Sell and Pay.
   Reuses the customer-display visual language (navy --nimiq-blue-bg surface, the shared .cd-*
   row/breakdown/total tokens, light-blue Total) so the buyer sees the same panel as the
   "Show buyer" overlay, now with an interactive tip selector. The panel is a full-bleed navy
   surface inside the padded page-body (negative margins cancel the body's 16/24/24 padding);
   the white card footer holds the Confirm CTA + the secondary actions. No new colors, no
   glassmorphism (brand rules).

   #50: this panel is now BOUND to the visible body instead of growing with the cart. It used to
   size to its content, so an 8-line cart pushed the tip row under the pinned footer and put the
   Total off the fold entirely (measured 360x664: 633px of content in a 335px body; the merchant
   saw item rows and nothing else). The money and the action never move now: the panel is capped,
   the ITEM LIST is the only region that gives way, and the overflow collapses into one
   "+N more items" affordance that opens the complete list in the buyer-display overlay.
   ===================================================================================== */
/* THE CAP. A percentage height cannot do this job: .page-body's own height comes from flex-grow, so
   `height: 100%` on a child resolves to auto and the panel just grows with the cart (that is exactly
   the bug). Flex sizing does not care about definiteness, so the body becomes the flex container for
   this one screen and the panel takes `flex: 1 1 0` + `min-height: 0` — the panel is then EXACTLY
   the visible body, always, which is what makes the body's own `overflow-y: auto` (page-body.css)
   moot rather than something to override: there is nothing left to scroll. Scoped by :has(), so no
   other screen is touched and there is no class to leak across renders. */
.page-body:has(> .checkout-panel) {
  display: flex;
  flex-direction: column;
}

.checkout-panel {
  /* full-bleed: cancel the .page-body.nq-card-body padding so the navy surface reaches the card
     edges, then re-pad internally. The cancellation reads the SAME --body-pad-top / --shell-pad
     variables the body padding is built from (app.1.css), so the two can never drift apart when
     the shell rhythm changes or the 450px breakpoint swaps the side padding. */
  margin: calc(-1 * var(--body-pad-top)) calc(-1 * var(--shell-pad)) calc(-1 * var(--shell-pad));
  /* The old 96px bottom pad existed only so scrolled content cleared the pinned footer. Nothing
     scrolls here any more, so it is dead space the Total needs. */
  padding: 16px 24px;
  /* Was `min-height: calc(100% + ...)` — a FLOOR, which is what let the cart push the Total off the
     fold. `flex: 1 1 0` against the bounded body above is the cap; min-height:0 lets it hold. */
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background-image: var(--nimiq-blue-bg);
  color: #fff;
  box-sizing: border-box;
}

/* On the checkout panel the header (business name + "Total due" caption) sits at the top with
   a tighter margin than the buyer-display overlay (the CTA lives in the white footer below). */
.checkout-panel .cd-header {
  margin-bottom: 6px;
}

.checkout-panel .cd-eyebrow {
  margin-top: 0;
}

/* THE BUDGET (#50). `flex: 1 1 0` makes this region exactly the leftover space, so its clientHeight
   is the number app.js measures to decide how many rows to render. It holds the rows AND the
   "+N more items" affordance, so the two collapse together and the money below is never what gives.
   `overflow: hidden` is deliberate: the main checkout screen never scrolls, the overlay behind the
   affordance is where the full list scrolls. */
.checkout-items {
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* The base .cd-items rule (overflow-y: auto) is untouched, so the buyer-display overlay still
   scrolls exactly as before; inside the checkout region the list never scrolls. */
.checkout-panel .cd-items {
  /* size to the rows it holds (never grow into the slack) so the "+N more items" row sits directly
     under the last line instead of a flex gap opening between them */
  flex: 0 1 auto;
  min-height: 0;
  overflow: hidden;
  margin-bottom: 0;
  padding-right: 0;
}

/* THE FALLBACK (#50, round 3). The governing rule the first round missed: a guaranteed fit must
   degrade to SCROLLING, never to hiding or clipping. Everything above is an OPTIMIZATION for the
   common case (a phone, a normal cart) and it is a trap in two states the cap alone cannot serve:

     1. The FIXED money stack is taller than the visible body all by itself. Nothing above it is
        left to give, so `overflow: hidden` amputated the Total while the footer CTA stayed
        enabled. Measured on a 320x568 phone with 8 lines, and on iPhone landscape (844x390,
        932x430) where .small-page's `max-height: calc(100dvh - 32px)` leaves an 89px body.
     2. The leftover space cannot seat even one "+N more items" row. Above the 450px breakpoint
        .small-page is a FIXED 564px card (small-page.css), so at 451x900, 768x1024, 820x1180 and
        1280x800 the region measured under 44px and the first round rendered ZERO rows AND hid the
        affordance: the merchant had no route to the cart at all.

   app.js measures both states on every fit and adds this class, which restores exactly what shipped
   before: a content-sized panel inside the page-body's own `overflow-y: auto` (page-body.css), plus
   the 96px of clearance the last line needs to clear the pinned footer. Every row renders and every
   part of the panel is reachable by scrolling. The body keeps `display: flex` from the rule above,
   which scrolls perfectly well once its one child is `flex: 0 0 auto` and overflows it. */
.checkout-panel.checkout-scroll {
  flex: 0 0 auto;
  min-height: calc(100% + var(--body-pad-top) + var(--shell-pad));
  overflow: visible;
  padding-bottom: 96px;
}

/* In fallback mode the region and the list size to the rows they hold, so nothing is cut off: the
   scrolling body underneath them is what makes the overflow reachable. */
.checkout-panel.checkout-scroll .checkout-items,
.checkout-panel.checkout-scroll .cd-items {
  flex: none;
  min-height: auto;
  overflow: visible;
}

/* Everything below the item region is the money and its controls: none of it may be squeezed, so
   only the region above absorbs a short viewport. */
.checkout-panel .cd-breakdown,
.checkout-panel .checkout-tip-title,
.checkout-panel .tip-selector,
.checkout-panel .checkout-asset-row,
.checkout-panel .checkout-note,
.checkout-panel .checkout-total {
  flex: none;
}

/* "Pay with [NIM] [USDC]" on one row: a two-pill choice does not need a full-width heading. */
.checkout-panel .checkout-asset-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 6px;
}

.checkout-panel .checkout-asset-label {
  margin: 0;
  flex: none;
}

.checkout-panel .checkout-asset-row .asset-choice {
  display: flex;
  gap: 8px;
  flex: 1 1 auto;
}

/* The item region above carries no bottom margin of its own: when the budget collapses to zero (a
   short phone with the custom-tip row open) that margin would be dead space the Total needs. The
   separation lives here instead, in padding that is present in every state. */
.checkout-panel .cd-breakdown {
  padding-top: 8px;
  margin-bottom: 4px;
}

.checkout-panel .cd-line {
  padding: 1px 0;
}

.checkout-panel .cd-item-row {
  padding: 4px 0;
}

/* "+N more items" — a plain full-width text row in the list's own rhythm. No icon (never fabricate
   one), no fill, no border, no new color: it reads as the continuation of the item list it stands
   in for, not as a button drawn on top of it. The 999px radius is only ever seen as the shape of
   the :focus-visible ring, which the brand requires to be a pill (the same treatment .text-action
   carries elsewhere in the app). It is a real tap target, so it keeps the 44px floor the rest of
   the app's small affordances do (app.6.css), with the label left-aligned inside it. */
.cd-more-btn {
  display: flex;
  align-items: center;
  width: 100%;
  flex: none;
  min-height: 5.5rem;
  background: none;
  border: 0;
  border-radius: 999px;
  padding: 4px 0;
  font-family: inherit;
  font-size: 2rem;
  font-weight: 600;
  text-align: left;
  color: rgba(255, 255, 255, 0.6);
  cursor: pointer;
}

.cd-more-btn:focus-visible {
  color: #fff;
}

@media (hover: hover) {
  .cd-more-btn:hover {
    color: #fff;
  }
}

/* The `display: flex` above is an author rule and would otherwise beat the UA `[hidden]` rule, so
   the hidden state (every row fits, or nothing fits at all) is stated explicitly. */
.cd-more-btn[hidden] {
  display: none;
}

/* The shared .cd-* tokens already render the header/items/breakdown/total in white on navy.
   The tip-section title + the Total sit between the breakdown and the footer. */
.checkout-tip-title {
  margin: 6px 0 4px;
  font-size: 2rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.6);
}

.checkout-panel .tip-selector {
  margin-bottom: 0;
}

/* Five pills (None / 15 / 18 / 20 / Custom) at the shared 7rem min-width + 12px side padding
   measure 312px against a 312px panel at 360, so they wrap onto a second row and cost 35px the
   Total needs. 5.5rem still clears the 44px touch-target minimum and the row fits on one line;
   flex-wrap remains the safety net for large-text mode (the item budget just re-derives). */
.checkout-panel .tip-pill {
  min-width: 5.5rem;
  padding: 0 8px;
}

/* The custom-tip row is a transient state that opens WITHOUT a re-render (ui.core.js toggles it), so
   its cost comes straight out of the item region. Keep that cost small. */
.checkout-panel .tip-custom-row {
  margin-top: 2px;
}

.checkout-panel .checkout-note {
  margin: 0;
}

/* The Total headline on the checkout surface: a touch tighter than the buyer-display overlay
   (it sits above the fold here, the CTA is in the footer). */
.checkout-total {
  margin-top: 4px;
  margin-bottom: 0;
}

.checkout-total .cd-total-value .fiat-amount {
  font-size: clamp(3.5rem, 11vw, 5.5rem);
  /* The buyer-display 1.05 line box is TIGHTER than the ink it holds, which is invisible on that
     overlay (the total sits mid-panel) but not here: the panel now clips at the footer, and a
     digit's descent poked through. 1.2 makes the box enclose the glyphs, so a rect measurement is
     the truth and "the Total is fully visible" means what it says. */
  line-height: 1.2;
}

/* Tip pills on the navy checkout surface. nq-button-s defaults to a near-invisible
   rgba(31,35,72,0.07) fill with navy text, which disappears on navy — so give the unselected
   pills a translucent-white surface + white text (legible), and keep the selected pill the
   brand light-blue (already high-contrast). No new colors. */
.checkout-panel .tip-pill,
.checkout-panel .asset-choice .slider-pill {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}

@media (hover: hover) {
  .checkout-panel .tip-pill:hover,
  .checkout-panel .asset-choice .slider-pill:hover {
    background: rgba(255, 255, 255, 0.2);
  }
}

.checkout-panel .tip-pill.selected,
.checkout-panel .asset-choice .slider-pill.selected {
  background: var(--nimiq-light-blue);
  color: #fff;
}

@media (hover: hover) {
  .checkout-panel .tip-pill.selected:hover,
  .checkout-panel .asset-choice .slider-pill.selected:hover {
    background: var(--nimiq-light-blue);
    color: #fff;
  }
}

/* Custom-tip row on navy: the priceField input + label read on the dark surface. */
.checkout-panel .tip-custom-label {
  color: rgba(255, 255, 255, 0.6);
}

.checkout-panel .tip-custom-row .price-field .nq-input {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  box-shadow: inset 0 0 0 0.25rem rgba(255, 255, 255, 0.18);
}

.checkout-panel .tip-custom-row .currency-symbol {
  color: rgba(255, 255, 255, 0.6);
}

/* The "Apply" small button inside the custom-tip row: legible on navy. */
.checkout-panel .tip-custom-row .nq-button-s {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}

/* The checkout footer (#50). Three vertically stacked actions measured 212px on a 664px phone —
   a third of the screen for chrome, while the Total it pushed off the fold got none. The primary
   CTA keeps the registry pill and its side margins; only the vertical rhythm tightens, and the two
   SECONDARY text-actions now share one row. Nothing is removed, no label changes, and both still
   clear the 44px touch target (.text-action min-height, app.6.css). Scoped to the checkout CTA by
   class, so every other screen's footer is byte-identical. */
.page-footer .nq-button.checkout-confirm {
  margin: 12px 38px 4px;
}

.checkout-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 32px;
}

/* "Back to register" text-action in the footer, beside "Split the bill". */
.checkout-back {
  margin-top: 0;
  align-self: center;
}

