/* =====================================================================================
   ACCESSIBILITY: high-contrast mode (html[data-contrast='high'], set by a11y.js).
   Strengthens ONLY the muted/low-opacity navy text + input borders for AA contrast. The
   brand hues (navy / light-blue / green / orange / gold) are NEVER changed, gradients stay
   intact, no new colors, no glassmorphism — real contrast only (brand rules). Most of this
   is a single token swap because the faint text was tokenized to --muted-text*; the handful
   of remaining 0.4/0.6 captions + the framework input border are raised explicitly here.
   ===================================================================================== */
html[data-contrast="high"] {
  --muted-text: rgba(31, 35, 72, 0.9);
  --muted-text-strong: var(--nimiq-blue);
  --a11y-border: rgba(31, 35, 72, 0.4);
}

/* Framework nq-input border is rgba(31,35,72,0.1) via --border-color: raise it to a visible
   level so empty fields read as fields in high contrast (the focus light-blue ring is unchanged). */
html[data-contrast="high"] .nq-input {
  --border-color: rgba(31, 35, 72, 0.4);
}

/* The few captions that were lighter than the tokenized 0.5/0.7 muted text. Raised to a strong,
   readable navy without inventing a color (still the brand navy, just at full strength). */
html[data-contrast="high"] .recent-status.muted,
html[data-contrast="high"] .staff-row.removed .staff-row-name,
html[data-contrast="high"] .refund-overlay-note,
html[data-contrast="high"] .refund-prefill-note {
  color: rgba(31, 35, 72, 0.9);
}

/* =====================================================================================
   ACCESSIBILITY: manual reduce-motion (html[data-motion='reduce'], set by a11y.js).
   A media query and an attribute selector cannot share one rule block, so each existing
   @media (prefers-reduced-motion: reduce) body is mirrored here as a sibling attribute rule.
   This lets a merchant force motion off regardless of the OS. 'auto' removes the attribute so
   the OS @media path above stays the sole authority (byte-identical to no feature). There is
   deliberately no 'allow' override: CSS can't re-enable motion against a system media query.
   ===================================================================================== */
html[data-motion="reduce"] .status-screen.grow-from-bottom-button {
  animation: none;
}
html[data-motion="reduce"] .customer-display-overlay {
  animation: none;
}
html[data-motion="reduce"] .pin-pad.pin-error {
  animation: none;
}

/* =====================================================================================
   ACCESSIBILITY: tap-target audit (WCAG 2.5.5 — 44px / 5.5rem minimum). Applied
   unconditionally (good for everyone, balanced at 1x). The primary nq-button is already
   7.5rem (60px). Bump the small affordances that fell under 44px.
   ===================================================================================== */
.text-action {
  min-height: 5.5rem;
  display: inline-flex;
  align-items: center;
}
.qty-btn {
  min-width: 5.5rem;
  min-height: 5.5rem;
  width: 5.5rem;
  height: 5.5rem;
  /* A square +/- stepper must be a CIRCLE, not the nq-button-s rounded square (r=13.5px). The
     equal width/height + 50% makes it round (WCAG/brand: stepper buttons are circular). */
  border-radius: 50%;
}
.pin-toggle {
  min-width: 5.5rem;
  min-height: 5.5rem;
}

/* =====================================================================================
   ACCESSIBILITY settings screen (showAccessibility). Whitespace-structured sections, the
   shared tip/discount segmented-pill pattern (.seg-pill light-blue .selected), an nq-label
   caption + a short helper line per section. No eyebrows, no pills-with-dots, no new colors.
   ===================================================================================== */
.a11y-screen {
  display: flex;
  flex-direction: column;
  gap: 32px;
  margin-top: 8px;
}

.a11y-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Sentence-case section title (NOT .nq-label, which the framework uppercases — rule 8). Full-navy
   so it reads as a primary section heading, the helper line below carries the muted caption. */
.a11y-title {
  margin: 0;
  font-size: 2rem;
  font-weight: 600;
  color: var(--nimiq-blue);
}
.a11y-row .a11y-title {
  margin: 0;
}

.a11y-hint {
  margin: 0;
  font-size: 1.75rem;
  color: var(--muted-text);
}

/* Section row with a control on the right (high contrast toggle). */
.a11y-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
/* Segmented pills: reuse the tip/discount layout + the light-blue .selected state. The text-size
   row has 4 labels (Default/Large/Larger/Largest); at 1.5x text scale on a narrow phone they must
   wrap rather than truncate, so the row wraps and each pill sizes to its content with breathing room
   (no fixed flex-basis that would clip a long word). */
.a11y-segments {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.seg-pill,
.a11y-pill {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 5.5rem;
  padding: 0 16px;
  white-space: nowrap;
  justify-content: center;
}
.seg-pill.selected,
.a11y-pill.selected {
  background: var(--nimiq-light-blue);
  color: #fff;
}

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

/* ── Item search (R1): vendored from the nq registry `search-bar` (pixel-verified). Namespaced
   under .search-bar; uses the 8px-root rem + nimiq vars the app already loads. ── */
/* Lives inside .sell-utility-row and takes the width the "More" action does not (#51); the row
   itself owns the spacing below, so the field carries no margins of its own. */
.sell-search {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
}
/* A filter bar wants full width always (not the wallet's resting-narrow → expand-on-focus). */
.sell-search .search-bar {
  --default-sb-width: 100%;
  /* The Sell screen's primary "find items" control: meet the 44px tap target (the base wallet
     search-bar renders a thin ~34px, too small/cramped to read as the main input). align-items
     already centers the icon + input vertically in the taller pill. */
  min-height: 5.5rem;
}
.search-bar {
  --body-size: 2rem;
  --text-16: rgba(31, 35, 72, 0.16);
  --text-22: rgba(31, 35, 72, 0.22);
  --light-blue-40: rgba(5, 130, 202, 0.4);
  --default-sb-width: clamp(5.5rem, 100%, 30rem);
  position: relative;
  display: flex;
  flex-direction: row;
  align-items: center;
  width: 100%;
  cursor: text;
  padding: 0.75rem 0;
  min-width: var(--default-sb-width);
  max-width: var(--default-sb-width);
  transition-property: color, max-width;
  transition-duration: var(--attr-duration);
  transition-timing-function: var(--nimiq-ease);
}
.search-bar.active {
  max-width: 100%;
}
.search-bar::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  box-shadow: inset 0 0 0 0.1875rem var(--text-16);
  border-radius: 500px;
  transition: box-shadow var(--attr-duration) var(--nimiq-ease);
}
@media (hover: hover) {
  .search-bar:hover::after {
    box-shadow: inset 0 0 0 0.1875rem var(--text-22);
  }
}
.search-bar:focus-within {
  color: var(--nimiq-light-blue);
}
.search-bar:focus-within > svg {
  opacity: 1;
}
.search-bar:focus-within::after {
  box-shadow: inset 0 0 0 0.1875rem var(--light-blue-40);
}
.search-bar > svg {
  justify-self: left;
  flex-grow: 0;
  margin-left: 1.75rem;
  margin-right: 1rem;
  flex-shrink: 0;
  opacity: 0.4;
  width: 1.75rem;
  height: 1.75rem;
  transition: opacity var(--attr-duration) var(--nimiq-ease);
}
.search-bar input {
  font-family: inherit;
  font-weight: 600;
  color: inherit;
  justify-self: right;
  flex-grow: 1;
  border: 0;
  line-height: 2.75rem;
  font-size: var(--body-size);
  margin: 0;
  padding: 0;
  padding-right: 4rem;
  background: none;
  min-width: 0;
}
.search-bar input:focus {
  outline: none;
}
.search-bar input::placeholder {
  font-weight: normal;
  color: inherit;
  opacity: 0.4;
}
.search-bar .cross-close-button {
  background: none;
  border: none;
  outline: none;
  font-family: inherit;
  line-height: inherit;
  font-weight: inherit;
  color: inherit;
  position: absolute;
  z-index: 1;
  right: 1rem;
  cursor: pointer;
  font-size: 1.5rem;
  padding: 0.5rem;
  border-radius: 50%;
  display: none;
}
.search-bar.active .cross-close-button {
  display: block;
}
.search-bar .cross-close-button svg {
  height: 1em;
  width: 1em;
  display: block;
  opacity: 0.7;
  transition: opacity 0.2s var(--nimiq-ease);
}
.search-bar .cross-close-button:active svg,
.search-bar .cross-close-button:focus svg {
  opacity: 1 !important;
}

@media (hover: hover) {
  .search-bar .cross-close-button:hover svg {
    opacity: 1 !important;
  }
}

/* R2: menu sections on the Sell screen — a subtle section heading above each category's grid.
   A 4-section demo menu spends 4 headings' worth of the phone's list budget, so they are set as
   tight as they can be and still separate the sections (#51). */
.item-section + .item-section {
  margin-top: 8px;
}
.sell-section-title {
  font-size: 1.625rem;
  font-weight: 700;
  color: var(--muted-text);
  margin: 0 0 4px;
}
/* Review: the per-item category field sits compact alongside name/price (the row flex-wraps). */
.catalog-row .row-category {
  flex: 1 1 120px;
  min-width: 0;
}
.catalog-row .row-category .nq-input {
  width: 100%;
  box-sizing: border-box;
}

/* R22: the per-item code / PLU field — a narrower sibling of the category field, same wrap rhythm. */
.catalog-row .row-code {
  flex: 1 1 90px;
  min-width: 0;
}
.catalog-row .row-code .nq-input {
  width: 100%;
  box-sizing: border-box;
}

/* Legacy receipts only: the "Paid by" tender value on a cash/other sale recorded before the
   crypto-only checkout (#34). No new sale can produce one. */
.paid-tender {
  font-weight: 600;
}

/* R4: order / pickup number. On the receipt (light surface, app + public /r) + the buyer display
   (navy) + a compact chip in the recent-sales list. The number leads so a merchant can call it out. */
.receipt-order {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  margin: 12px 0 4px;
}
.receipt-order-label {
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--muted-text);
}
.receipt-order-num {
  font-size: 3.5rem;
  font-weight: 700;
  color: var(--nimiq-blue);
}
.cd-receipt-order {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 10px;
  margin: 8px 0 16px;
}
.cd-receipt-order-label {
  font-size: 2rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.6);
}
.cd-receipt-order-num {
  font-size: 4rem;
  font-weight: 700;
  color: #fff;
}
/* Order number on a recent-sales row. Navy, not light-blue: 13px light-blue on white is 4.16:1,
   under AA, and the bold weight already separates it from the rest of the row. */
.rs-order {
  font-weight: 700;
  color: var(--nimiq-blue);
  margin-right: 10px;
}

/* R6: busy-hours bar row on the dashboard — hour label, a track + light-blue fill (width ∝ gross),
   and the server gross + count. No chart dep; inset-tint track, solid light-blue bar. */
.by-hour {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.by-hour-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.bh-label {
  flex: 0 0 56px;
  font-weight: 600;
  font-size: 1.75rem;
  color: var(--muted-text-strong);
}
.bh-track {
  flex: 1 1 auto;
  min-width: 0;
  height: 12px;
  border-radius: 500px;
  background: rgba(31, 35, 72, 0.08);
  overflow: hidden;
}
.bh-bar {
  height: 100%;
  border-radius: 500px;
  background: var(--nimiq-light-blue);
}
.bh-value {
  flex: 0 0 auto;
  white-space: nowrap;
  font-weight: 600;
}
.bh-count {
  color: var(--muted-text);
  font-weight: 400;
}

/* R11 trends: a muted delta line under the week comparison (reuses .empty-note tokens). */
.trends-delta {
  margin: 6px 0 0;
}

/* R11 daily over-time sparkline — vertical light-blue bars (height ∝ gross) on an inset baseline, no
   chart dep. Mirrors the busy-hours palette: light-blue fill, hairline track, muted axis labels. */
.spark {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 64px;
  padding: 8px 0 0;
  box-shadow: inset 0 -1px 0 rgba(31, 35, 72, 0.08);
}
.spark-bar {
  flex: 1 1 0;
  min-width: 0;
  min-height: 2px;
  background: var(--nimiq-light-blue);
  border-radius: 4px 4px 0 0;
}
.spark-axis {
  display: flex;
  justify-content: space-between;
  margin-top: 4px;
  font-size: 1.5rem;
  color: var(--muted-text);
}

/* R12 menu-engineering: a class sub-header (Stars / Plowhorses / …) under the "Menu performance"
   title, with a muted one-line hint above its item rows. Reuses the palette — no new colors. */
.menu-class-head {
  margin: 16px 0 0;
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--muted-text-strong);
}
.menu-class-hint {
  margin: 2px 0 8px;
}

/* =====================================================================================
   R15 PWA update toast — a non-blocking banner pinned to the bottom of the register that
   offers to apply a new version. White card surface + light-blue Refresh pill (no glassmorphism,
   no new colors). Fixed + centered so it floats over any screen without interrupting a sale.
   ===================================================================================== */
.update-toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 2000;
  display: flex;
  align-items: center;
  gap: 16px;
  max-width: calc(100% - 32px);
  padding: 12px 16px 12px 20px;
  background: #fff;
  border-radius: 999px;
  box-shadow: 0 0.5rem 2.5rem rgba(31, 35, 72, 0.18);
}

.update-toast-text {
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--nimiq-blue, #1f2348);
  white-space: nowrap;
}

/* =====================================================================================
   R16 open-tab banner — shown on the Sell screen while ADDING to an open tab, so the merchant
   knows the cart writes back to that named tab (Save to tab) and charging closes it. Light-blue
   tinted card = active context (NOT success-green). No glassmorphism. Reuses the parked-* list
   styles for the Tabs overlay (same .parked-ticket-* markup).
   ===================================================================================== */
.tab-banner {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0 0 16px;
  padding: 12px 16px;
  border-radius: 8px;
  background: rgba(5, 130, 202, 0.1);
  box-shadow: inset 3px 0 0 var(--nimiq-light-blue, #0582ca);
}

.tab-banner-label {
  font-size: 1.875rem;
  font-weight: 600;
  color: var(--nimiq-light-blue, #0582ca);
}

.tab-banner-hint {
  font-size: 1.5rem;
  color: var(--muted-text);
}

/* =====================================================================================
   R17 accessibility: .sr-only — visually hidden but available to assistive tech. Used for the
   app-level ARIA live regions that announce live settlement status (waiting / detected / paid /
   expired) without changing the visible pay screen. Standard clip-rect offscreen technique.
   ===================================================================================== */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* =====================================================================================
   R19 accessibility: app-wide keyboard focus visibility (WCAG 2.4.7 Focus Visible +
   2.4.13 Focus Appearance + 2.4.11 Focus Not Obscured). The stylesheet had ZERO focus
   rings, so R17's keyboard work was invisible. :focus-visible ONLY, so mouse/touch taps
   stay clean while keyboard + switch users get a clear ring on every interactive control.
   The search bar keeps its own :focus-within treatment (its input:focus { outline: none }
   out-specifies this bare rule), so there is no double indicator.
   ===================================================================================== */
:focus-visible {
  /* >= 3px (WCAG 2.4.13 minimum is 2px); scales with the a11y text size (1rem = 8px * scale,
     so 0.375rem = 3px * scale). Offset so the ring sits clear of the control's own border. */
  outline: max(3px, 0.375rem) solid var(--nimiq-light-blue, #0582ca);
  outline-offset: 2px;
}

/* High-contrast mode (html[data-contrast='high'], set by a11y.js): a THICKER ring. The colour stays
   light-blue (NOT navy) on purpose: light-blue clears 3:1 against BOTH the white cards (~4:1) and the
   navy pay/checkout/customer-display surfaces (~3.8:1), whereas a navy ring would vanish on the navy
   panels. So the high-contrast enhancement is extra thickness, which is visible on every surface. */
html[data-contrast="high"] :focus-visible {
  outline-width: max(4px, 0.5rem);
}

/* The search bar already shows a bespoke light-blue :focus-within ring, so suppress the global
   outline on its input to avoid a double indicator (explicit, so the computed width is 0 too). */
.search-bar input:focus-visible {
  outline: none;
}

/* WCAG 2.4.11 Focus Not Obscured: when a control is focused and scrolled into view, keep it
   clear of the pinned bottom footer (primary CTA) and the fixed update toast, instead of
   landing hidden behind them. Affects scroll-into-view positioning only (no-op otherwise). */
button,
a[href],
input,
select,
textarea,
[tabindex] {
  scroll-margin-bottom: 96px;
  scroll-margin-top: 16px;
}

/* ---- Favorites row switches (Setup + Settings share this block verbatim) ---- */
.fav-mode-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.fav-mode-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 0;
}

.fav-mode-row + .fav-mode-row {
  /* a hairline derived from navy, the same separator long lists use */
  box-shadow: inset 0 1px 0 rgba(31, 35, 72, 0.06);
}

.fav-mode-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.fav-mode-label {
  font-size: 2rem;
  font-weight: 600;
  color: var(--nimiq-blue);
}

.fav-mode-hint {
  font-size: 1.625rem;
  line-height: 1.35;
  color: var(--muted-text);
}

.fav-mode-toggle {
  flex: none;
  min-width: 56px;
}

.settings-section-title {
  margin: 8px 0 2px;
  font-size: 2rem;
  font-weight: 700;
  color: var(--nimiq-blue);
}

.settings-section-hint {
  margin: 0 0 4px;
  font-size: 1.625rem;
  line-height: 1.4;
  color: var(--muted-text);
}
