/* ==========================================================================
   Revenit: design system (direction C "Come nel Wallet", chosen 2026-10-11)
   Meant to REPLACE public/stile.css: same class names, same variable names,
   same idea (all design values live in the :root blocks; the rest of the file
   only uses variables).
   - Panel pages (owner, super-admin) carry body class "app-panel": there the
     primary color is ultramarine. Customer pages stay ink and use the shop's
     colors on the card.
   - Paths (fonts/, icone/) are relative to this file: in production it is
     served as /stile.css, so they become /fonts/... and /icone/...
   - Keep --font-size-base at 16px or more: smaller inputs make iPhone zoom in.
   ========================================================================== */

@font-face {
  font-family: "Geist";
  src: url("fonts/Geist-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Colors (light theme). Brand: ink, paper, ultramarine (BRAND.md §4). */
  --color-bg: #f6f5f2;
  --color-surface: #ffffff;
  --color-surface-sunken: #efeee9;
  --color-text: #15171c;
  --color-text-muted: #5a5e68;
  --color-border: #dcdad4;
  --color-border-field: #80838a;
  --color-primary: #15171c;
  --color-primary-text: #ffffff;
  --color-accent: #3346d3;
  --color-accent-text: #ffffff;
  --color-accent-soft: #e4e7f9;
  --color-accent-on-soft: #2a3ab0;
  --color-ink-bar: #15171c;
  --color-on-ink: #ffffff;
  --color-on-ink-muted: #b9bbc2;
  --color-accent-on-ink: #8c98ff;
  --color-error: #b42318;
  --color-error-soft: #fde8e6;
  --color-success: #1e7d46;
  --color-success-soft: #e3f4ea;
  --color-warning: #ffd166;
  --color-warning-soft: #fff1cc;
  --color-warning-text: #7a5200;
  --color-on-warning: #1b1f24;
  --color-preview-border: #80838a;
  --poster-ink: #000000;
  --poster-paper: #ffffff;
  --qr-ink: #111111;
  --qr-paper: #ffffff;

  /* Spacing */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;

  /* Radius */
  --radius-sm: 10px;
  --radius: 14px;
  --radius-lg: 20px;
  --radius-pill: 999px;

  /* Shadows */
  --shadow-1: 0 1px 2px rgb(21 23 28 / 0.06);
  --shadow-2: 0 1px 2px rgb(21 23 28 / 0.06), 0 12px 28px -14px rgb(21 23 28 / 0.28);
  --shadow-pass: 0 1px 1px rgb(21 23 28 / 0.08), 0 18px 36px -18px rgb(21 23 28 / 0.45);

  /* Typography: Geist only, weights 400 and 600 (700 only for the large titles) */
  --font-family: "Geist", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-size-xs: 12px; /* bottom navigation only (exception to the brand scale, see BRAND.md §10) */
  --font-size-sm: 14px;
  --font-size-base: 16px;
  --font-size-md: 18px;
  --font-size-lg: 20px;
  --font-size-xl: 28px;
  --font-size-title: 34px;
  --font-size-balance: 56px;
  --font-weight-regular: 400;
  --font-weight-medium: 600;
  --font-weight-bold: 700;
  --line-height: 1.5;
  --line-height-tight: 1.15;
  --letter-spacing-title: -0.02em;

  /* Layout and sizes */
  --container-width: 960px;
  --narrow-width: 480px;
  --control-min-height: 52px;
  --control-small-min-height: 44px;
  --control-big-min-height: 76px;
  --touch-min: 44px;
  --topbar-height: 56px;
  --nav-height: 68px;
  --nav-scan-size: 60px;
  --field-min-width: 200px;
  --total-min-width: 140px;
  --border-width: 1px;
  --focus-ring-width: 3px;
  --focus-ring-offset: 2px;
  --indicator-width: 3px;
  --icon-size: 24px;
  --icon-size-sm: 20px;
  --opacity-disabled: 0.5;
  --z-nav: 50;
  --z-banner: 100;
  --stamp-icon-size: 28px;
  --tile-min-width: 96px;
  --logo-max-width: 240px;
  --logo-max-height: 120px;
  --undo-window: 300s; /* the temporary «Annulla» lives 5 minutes (UNDO_WINDOW_MS) */

  /* Motion */
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --duration-fast: 120ms;
}

/* Dark theme: only color variables change. The web card ignores it (it uses the shop's colors). */
@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: #121318;
    --color-surface: #1c1e24;
    --color-surface-sunken: #17181d;
    --color-text: #ecebe7;
    --color-text-muted: #a2a6ad;
    --color-border: #33363d;
    --color-border-field: #6b6f78;
    --color-primary: #ecebe7;
    --color-primary-text: #15171c;
    --color-accent: #8c98ff;
    --color-accent-text: #15171c;
    --color-accent-soft: #262a45;
    --color-accent-on-soft: #b9c0ff;
    --color-ink-bar: #0b0c0f;
    --color-error: #ff8a80;
    --color-error-soft: #3b1f1e;
    --color-success: #7fd19a;
    --color-success-soft: #1d3527;
    --color-warning: #ffd166;
    --color-warning-soft: #3d3116;
    --color-warning-text: #ffd166;
    --color-on-warning: #1b1f24;
    --shadow-1: 0 0 0 1px #33363d;
    --shadow-2: 0 0 0 1px #33363d;
  }
}

/* Panel pages (owner and super-admin): the main actions are ultramarine (decision of 2026-10-11). */
.app-panel {
  --color-primary: var(--color-accent);
  --color-primary-text: var(--color-accent-text);
}

/* ---------- Base ---------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Links to an anchor (#…) must not end up under the sticky top bar. */
html {
  scroll-padding-top: calc(var(--topbar-height) + env(safe-area-inset-top) + var(--space-3));
}

body {
  container: page / inline-size;
  margin: 0;
  font-family: var(--font-family);
  font-size: var(--font-size-base);
  line-height: var(--line-height);
  color: var(--color-text);
  background: var(--color-bg);
  color-scheme: light dark;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

h1,
h2,
h3 {
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--letter-spacing-title);
  line-height: var(--line-height-tight);
}

a {
  color: var(--color-accent);
  text-underline-offset: 3px;
}

:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-accent);
  outline-offset: var(--focus-ring-offset);
}

.icon {
  flex: none;
  width: var(--icon-size);
  height: var(--icon-size);
}

/* The brand dot that closes a main title (BRAND.md §5): <span class="brand-dot">.</span> */
.brand-dot {
  color: var(--color-accent);
}

/* ---------- Structure ---------- */

/* Top bar: ink, with the negative logo (BRAND.md §2 allows it on ink) and the settings icon. */
.topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: calc(var(--topbar-height) + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) var(--space-2) 0 var(--space-4);
  color: var(--color-on-ink);
  background: var(--color-ink-bar);
}

.topbar form {
  margin: 0;
}

.brand {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-min);
  color: var(--color-on-ink);
  font-weight: var(--font-weight-bold);
  text-decoration: none;
}

.brand-logo {
  display: block;
  width: auto;
  height: 24px;
}

/* A square button with only an icon (the settings gear): always with aria-label. */
.btn-icon {
  width: var(--touch-min);
  min-width: var(--touch-min);
  padding: 0;
}

.topbar .btn-icon {
  color: var(--color-on-ink);
  background: transparent;
  border-color: transparent;
}

.topbar .btn-icon[aria-current="page"] {
  color: var(--color-accent-on-ink);
}

/* Navigation. Phone: a bar at the bottom, under the thumb, with Scansiona raised in the middle.
   Wide screens: the same links in a row under the top bar. Items without an icon (super-admin) still work. */
.nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-nav);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  align-items: end;
  padding-bottom: env(safe-area-inset-bottom);
  background: var(--color-surface);
  background: color-mix(in srgb, var(--color-surface) 94%, transparent);
  border-top: var(--border-width) solid var(--color-border);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.nav a {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 2px;
  min-height: var(--nav-height);
  padding: 10px 2px 8px;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: 1.2;
  text-align: center;
  color: var(--color-text-muted);
  text-decoration: none;
}

.nav a:not(:has(.icon)) {
  justify-content: center;
  font-size: var(--font-size-sm);
}

.nav a[aria-current="page"] {
  color: var(--color-text);
}

/* The current page is marked by the brand dot under its label. */
.nav a[aria-current="page"]::after {
  content: "";
  position: absolute;
  bottom: 3px;
  left: 50%;
  width: 5px;
  height: 5px;
  margin-left: -2.5px;
  border-radius: 50%;
  background: var(--color-accent);
}

/* Scansiona: a large ultramarine dot in the middle of the bar, reachable from every panel page. */
.nav .nav-scan {
  color: var(--color-text);
}

.nav .nav-scan .icon {
  box-sizing: content-box;
  width: 28px;
  height: 28px;
  /* raised: it takes the same room as the other icons (24 px), the rest sticks out above the bar */
  margin-top: calc(24px - var(--nav-scan-size) - 8px);
  padding: calc((var(--nav-scan-size) - 28px) / 2);
  color: var(--color-accent-text);
  background: var(--color-accent);
  border: 4px solid var(--color-bg);
  border-radius: 50%;
  box-shadow: 0 8px 18px -6px color-mix(in srgb, var(--color-accent) 70%, transparent);
  transition: transform var(--duration-fast) var(--ease-out);
}

.nav .nav-scan:active .icon {
  transform: scale(0.94);
}

.nav .nav-scan[aria-current="page"]::after {
  display: none;
}

/* Room for the bottom bar, so it never covers the end of the page. */
.nav ~ .container {
  padding-bottom: calc(var(--nav-height) + env(safe-area-inset-bottom) + var(--space-6));
}

/* Wide screens (tablet, computer). A container query on the page, not a media query, so the same rules
   also work inside the mockup frames. */
@container page (min-width: 900px) {
  .nav {
    position: sticky;
    top: var(--topbar-height);
    bottom: auto;
    grid-auto-flow: column;
    grid-auto-columns: max-content;
    justify-content: center;
    gap: var(--space-2);
    padding: 0 var(--space-4);
    border-top: 0;
    border-bottom: var(--border-width) solid var(--color-border);
  }

  .nav a {
    flex-direction: row;
    gap: var(--space-2);
    min-height: var(--control-min-height);
    padding: 0 var(--space-3);
    font-size: var(--font-size-base);
  }

  .nav .nav-scan .icon {
    width: var(--icon-size-sm);
    height: var(--icon-size-sm);
    margin: 0;
    padding: 6px;
    border: 0;
    box-shadow: none;
  }

  .nav a[aria-current="page"]::after {
    bottom: 4px;
  }

  .nav ~ .container {
    padding-bottom: var(--space-6);
  }
}

/* Ritocchi 1: shop navigation only. The platform admin keeps its four-item bar.
   Common grid/media queries keep the scan centered without :has(), container queries or color-mix(). */
.nav.nav-shop {
  display: block;
  position: fixed;
  top: auto;
  bottom: 0;
  padding: 0 0 env(safe-area-inset-bottom);
  border-top: var(--border-width) solid var(--color-border);
  border-bottom: 0;
}

.nav-shop .nav-inner {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  align-items: stretch;
  width: 100%;
  margin: 0 auto;
}

.nav-shop a {
  flex-direction: column;
  justify-content: flex-start;
  min-width: 0;
  min-height: var(--nav-height);
  padding: 8px 0 4px;
  gap: 2px;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-regular);
}

.nav-shop a > span {
  display: block;
  min-height: 2.4em;
  max-width: 100%;
  line-height: 1.2;
  word-wrap: break-word;
  overflow-wrap: anywhere;
}

.nav-shop .nav-new > span {
  width: 5em;
}

.nav-shop a[aria-current="page"] {
  font-weight: var(--font-weight-medium);
}

.nav-shop a[aria-current="page"] > .icon {
  color: var(--color-accent);
}

.nav-shop a[aria-current="page"]::after {
  content: none;
}

.nav-shop .nav-scan .icon {
  margin-top: -44px;
}

.nav-shop .nav-scan[aria-current="page"] > .icon {
  color: var(--color-accent-text);
}

.nav-shop .nav-scan[aria-current="page"] > span {
  color: var(--color-accent);
}

/* The raised circle is part of the link, including its visible keyboard focus. */
.nav-shop .nav-scan:focus-visible .icon {
  outline: var(--focus-ring-width) solid var(--color-accent);
  outline-offset: var(--focus-ring-offset);
}

.nav-shop ~ .container {
  /* 100px at the usual 16px body text, growing with enlarged text and its taller bar. */
  padding-bottom: calc(6.25em + env(safe-area-inset-bottom));
}

html.shop-panel {
  /* 116px at the default text size, including the raised scan circle. */
  scroll-padding-bottom: calc(7.25em + env(safe-area-inset-bottom));
}

@media (max-width: 359px) {
  .nav-shop .nav-scan .icon {
    --nav-scan-size: 52px;
    margin-top: -36px;
  }
}

@media (min-width: 900px) {
  .nav.nav-shop {
    position: sticky;
    top: calc(var(--topbar-height) + env(safe-area-inset-top));
    bottom: auto;
    padding: 0;
    border-top: 0;
    border-bottom: var(--border-width) solid var(--color-border);
  }

  .nav-shop .nav-inner {
    max-width: 960px;
    align-items: stretch;
  }

  .nav-shop a {
    justify-content: center;
    padding: 6px 8px;
    font-size: var(--font-size-sm);
  }

  .nav-shop a > span,
  .nav-shop .nav-new > span {
    min-height: 0;
    width: auto;
    max-width: none;
  }

  .nav-shop a > .icon {
    margin: 4px 0;
  }

  .nav-shop .nav-scan .icon {
    width: var(--icon-size-sm);
    height: var(--icon-size-sm);
    margin: 0;
    padding: 6px;
    border: 0;
    box-shadow: none;
  }

  .nav-shop ~ .container {
    padding-bottom: var(--space-6);
  }

  html.shop-panel {
    scroll-padding-top: calc(var(--topbar-height) + env(safe-area-inset-top) + var(--nav-height) + var(--space-3));
    scroll-padding-bottom: var(--space-6);
  }
}

.container {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: var(--space-5) var(--space-4);
}

.card {
  margin-bottom: var(--space-4);
  padding: var(--space-5) var(--space-4);
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.card > h1:first-child,
.card > h2:first-child {
  margin-top: 0;
}

.card h1 {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-xl);
}

.card h2 {
  margin: var(--space-5) 0 var(--space-3);
  font-size: var(--font-size-lg);
}

/* Titles written straight in the page (super-admin lists, registers) */
.container > h1 {
  margin: 0 0 var(--space-4);
  font-size: var(--font-size-xl);
}

.container > h2 {
  margin: var(--space-6) 0 var(--space-3);
  font-size: var(--font-size-lg);
}

/* A page title in the style of the phone: large, on the page, not inside a box. */
.page-title {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-title);
  font-weight: var(--font-weight-bold);
  letter-spacing: -0.03em;
}

.narrow {
  max-width: var(--narrow-width);
  margin-left: auto;
  margin-right: auto;
}

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
}

/* Section label above a group (like the phone settings): small, uppercase, muted. */
.group-label {
  margin: var(--space-5) var(--space-4) var(--space-2);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* ---------- Forms ---------- */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-weight: var(--font-weight-medium);
}

.field input,
.field select,
.field textarea {
  width: 100%;
}

.row > .field,
.row > input,
.row > select {
  flex: 1 1 var(--field-min-width);
}

input:not([type="checkbox"]):not([type="radio"]):not([type="color"]),
select,
textarea {
  min-height: var(--control-min-height);
  padding: 0 var(--space-4);
  font-family: inherit;
  font-size: var(--font-size-md);
  color: var(--color-text);
  background-color: var(--color-surface);
  border: var(--border-width) solid var(--color-border-field);
  border-radius: var(--radius-sm);
}

/* (repeated :not() only to win over the general input rule above) */
input[type="search"]:not([type="checkbox"]):not([type="radio"]):not([type="color"]) {
  border-radius: var(--radius-pill);
  padding-left: calc(var(--space-4) + var(--icon-size-sm) + var(--space-2));
  background-image: url("icone/campo-cerca.svg");
  background-repeat: no-repeat;
  background-position: var(--space-4) center;
  background-size: var(--icon-size-sm);
  -webkit-appearance: none;
  appearance: none;
}

@media (prefers-color-scheme: dark) {
  input[type="search"] {
    background-image: url("icone/campo-cerca-scuro.svg");
  }
}

textarea {
  padding: var(--space-3) var(--space-4);
}

input[type="checkbox"],
input[type="radio"] {
  width: 22px;
  height: 22px;
  accent-color: var(--color-accent);
}

::placeholder {
  color: var(--color-text-muted);
}

.help {
  margin: 0;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-regular);
  color: var(--color-text-muted);
}

/* ---------- Buttons ---------- */

button,
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-min-height);
  padding: 0 var(--space-5);
  font-family: inherit;
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  line-height: 1.2;
  color: var(--color-text);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border-field);
  border-radius: var(--radius-pill);
  cursor: pointer;
  text-decoration: none;
  transition: transform var(--duration-fast) var(--ease-out);
}

button:active,
.btn:active {
  transform: scale(0.98);
}

a.btn {
  text-decoration: none;
}

.btn-primary {
  color: var(--color-primary-text);
  background: var(--color-primary);
  border-color: var(--color-primary);
}

.btn-ghost {
  color: var(--color-accent);
  background: transparent;
  border-color: transparent;
}

.btn-small {
  min-height: var(--control-small-min-height);
  padding: 0 var(--space-4);
  font-size: var(--font-size-sm);
}

/* The big buttons of the cash desk (+1, Riscatta): a rounded rectangle, easier to hit than a pill. */
.btn-big {
  min-height: var(--control-big-min-height);
  padding: 0 var(--space-5);
  font-size: var(--font-size-lg);
  border-radius: var(--radius-lg);
}

.btn-big .icon {
  width: 28px;
  height: 28px;
}

/* Something that cannot be undone or that logs out: same shape, red text. */
.btn-danger {
  color: var(--color-error);
}

button:disabled,
.btn:disabled {
  opacity: var(--opacity-disabled);
  cursor: not-allowed;
}

/* ---------- Messages ---------- */

.flash {
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius);
}

.flash-ok {
  background: var(--color-success-soft);
  border-color: color-mix(in srgb, var(--color-success) 45%, transparent);
}

.flash-error {
  background: var(--color-error-soft);
  border-color: color-mix(in srgb, var(--color-error) 45%, transparent);
}

.flash-warn {
  background: var(--color-warning-soft);
  border-color: color-mix(in srgb, var(--color-warning) 80%, transparent);
}

/* Top banner of the super-admin inside a shop: sticky, so it stays in the page flow. */
.banner {
  position: sticky;
  top: 0;
  z-index: var(--z-banner);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  font-weight: var(--font-weight-medium);
  color: var(--color-on-warning);
  background: var(--color-warning);
}

.banner span {
  flex: 1 1 var(--field-min-width);
}

.banner p {
  margin: 0;
}

/* With the super-admin banner on top, the top bar scrolls away and the banner stays. */
.has-banner .topbar {
  position: relative;
}

/* Read-only link box with a copy button */
.copybox {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.copybox input {
  flex: 1 1 var(--field-min-width);
  min-width: 0;
  background: var(--color-surface-sunken);
}

/* Empty state: an icon in a soft circle, one sentence, a hint. */
.empty {
  padding: var(--space-6) var(--space-4);
  text-align: center;
}

.empty .icon {
  box-sizing: content-box;
  width: 28px;
  height: 28px;
  padding: 18px;
  color: var(--color-accent-on-soft);
  background: var(--color-accent-soft);
  border-radius: 50%;
}

.empty p {
  margin: var(--space-3) 0 0;
}

.empty .empty-title {
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
}

/* ---------- Lists of links (rows with a chevron, like the phone settings) ---------- */

.menu-list {
  margin: 0;
  padding: 0;
  overflow: hidden;
  list-style: none;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.menu-list + .menu-list {
  margin-top: var(--space-5);
}

.menu-list li + li {
  border-top: var(--border-width) solid var(--color-border);
}

.menu-list a,
.menu-list button {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: 60px;
  padding: var(--space-2) var(--space-4);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-regular);
  text-align: left;
  color: var(--color-text);
  text-decoration: none;
  background: transparent;
  border: 0;
  border-radius: 0;
}

.menu-list form {
  margin: 0;
}

.menu-list .menu-text {
  flex: 1 1 auto;
}

.menu-list .icon {
  width: var(--icon-size-sm);
  height: var(--icon-size-sm);
}

/* The icon at the start of a row: ultramarine on its soft tint. */
.menu-list .menu-icon {
  box-sizing: content-box;
  padding: 8px;
  color: var(--color-accent-on-soft);
  background: var(--color-accent-soft);
  border-radius: var(--radius-sm);
}

.menu-list .menu-chevron {
  color: var(--color-text-muted);
}

.menu-list .btn-danger,
.menu-list .btn-danger .menu-icon {
  color: var(--color-error);
}

.menu-list .btn-danger .menu-icon {
  background: var(--color-error-soft);
}

/* ---------- Tables ---------- */

.table-wrap {
  overflow-x: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
}

th,
td {
  padding: var(--space-3);
  text-align: left;
  vertical-align: top;
  border-bottom: var(--border-width) solid var(--color-border);
}

th {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
}

td {
  font-variant-numeric: tabular-nums;
}

.table-wrap {
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.table-wrap tr:last-child td {
  border-bottom: 0;
}

/* On the phone every row becomes a small card: the first cell is the title, the others are "label: value".
   The label comes from data-label="…" on each <td> (same text as the column header). */
@container page (max-width: 640px) {
  .table-wrap {
    overflow: visible;
    background: transparent;
    box-shadow: none;
  }

  .table-wrap table,
  .table-wrap tbody,
  .table-wrap tr,
  .table-wrap td {
    display: block;
  }

  .table-wrap thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  .table-wrap tr {
    margin-bottom: var(--space-3);
    padding: var(--space-3) var(--space-4);
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-1);
  }

  .table-wrap td {
    display: grid;
    grid-template-columns: 7.5em 1fr;
    gap: var(--space-3);
    padding: var(--space-1) 0;
    border: 0;
    overflow-wrap: anywhere;
  }

  .table-wrap td > * {
    justify-self: start;
  }

  .table-wrap td::before {
    content: attr(data-label);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
  }

  /* first cell: the title of the card */
  .table-wrap td:first-child {
    display: block;
    padding-bottom: var(--space-2);
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-medium);
  }

  .table-wrap td:first-child::before,
  .table-wrap td:not([data-label])::before,
  .table-wrap td[data-label=""]::before {
    content: none;
  }

  .table-wrap td:not([data-label]),
  .table-wrap td[data-label=""] {
    display: block;
    padding-top: var(--space-2);
  }
}

/* ---------- Badges (chips) ---------- */

.badge {
  display: inline-block;
  padding: 2px var(--space-2);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  border-radius: var(--radius-pill);
}

.badge-active {
  color: var(--color-success);
  background: var(--color-success-soft);
}

.badge-suspended {
  color: var(--color-warning-text);
  background: var(--color-warning-soft);
}

.badge-cancelled {
  color: var(--color-error);
  background: var(--color-error-soft);
}

/* ---------- Test shop line (Phase P1, D66) ----------
   "Negozio di prova" at the top of the panel and "Tessera dimostrativa" on the web card and on the pages of the fixed QR of a test shop.
   A quiet line, not a warning. Not yet in brand/mockup/sistema.css: the brand designer decides if it becomes a component. */

.demo-note {
  margin: 0 0 var(--space-3);
  padding: var(--space-1) var(--space-3);
  text-align: center;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  border: 1px dashed var(--color-border-field);
  border-radius: var(--radius-pill);
}

/* ---------- Registration page (Phase P1) ----------
   The link that opens a document next to its checkbox gets a tap area of 44 px; the email (read only) does not look like a field to fill. */

/* The text of the checkbox, then its link right under it. The tap area of the box grows UPWARD (padding above the text, see `.checkbox-field label`)
   and the one of the link DOWNWARD (padding under it), each 44 px, never overlapping: the two texts stay close. */
.checkbox-field .help a {
  display: inline-block;
  padding: 0 0 calc(var(--touch-min) - var(--font-size-sm) * var(--line-height));
}

/* The lines under the text of a box (its links, its note) start where the TEXT starts, not under the little square: the width of the square, its two default
   side margins of the browser and the gap of the label. */
.checkbox-field .help {
  padding-left: calc(22px + 4px + 3px + var(--space-3));
}

.field input[readonly] {
  background: var(--color-surface-sunken);
  color: var(--color-text-muted);
}

/* The box of the new version of the documents, at the top of the Home. */
.reaccept {
  border: 2px solid var(--color-border-field);
}

/* ---------- Totals ---------- */

.totals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--total-min-width), 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.total {
  padding: var(--space-4);
  background: var(--color-surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
}

.total strong {
  display: block;
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-medium);
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}

.total span {
  display: block;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* ---------- Shop colors: shared palette and HEX ---------- */

.color-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: var(--space-5);
}

.color-field {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.color-field legend {
  padding: 0;
  margin-bottom: var(--space-3);
  font-size: var(--font-size-lg);
  font-weight: 600;
}

.color-hex-label { display: block; margin-bottom: var(--space-2); }
.color-hex-row { display: flex; align-items: center; gap: var(--space-2); }
.color-current {
  flex: 0 0 44px;
  height: 44px;
  border: 1px solid var(--color-border-field);
  border-radius: var(--radius-sm);
}
.color-hex-row input.color-hex { min-width: 0; letter-spacing: .04em; font-variant-numeric: tabular-nums; }
.color-error { color: var(--color-error); font-size: var(--font-size-sm); margin: var(--space-2) 0; }
.color-hex[aria-invalid="true"] { border-color: var(--color-error); }
.color-current { cursor: pointer; padding: 0; }
.color-current:focus-visible,
.color-picker-hue:focus-visible { outline: 3px solid var(--color-accent); outline-offset: 3px; }
.color-picker[hidden] { display: none; }
.color-picker {
  margin-top: var(--space-3);
  padding: var(--space-3);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}
.color-picker-board {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 44px;
  gap: var(--space-3);
}
.color-picker-square {
  position: relative;
  aspect-ratio: 1;
  background: linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, transparent), var(--picker-hue, #f00);
  border: 1px solid var(--color-border-field);
  border-radius: var(--radius-sm);
  cursor: crosshair;
  touch-action: none;
}
.color-picker-square-handle {
  position: absolute;
  width: 18px;
  height: 18px;
  border: 2px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 0 1px #15171c, 0 1px 4px #15171c;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.color-picker-hue {
  position: relative;
  min-height: 44px;
  background: linear-gradient(to bottom, #f00 0%, #f0f 16.7%, #00f 33.3%, #0ff 50%, #0f0 66.7%, #ff0 83.3%, #f00 100%);
  border: 1px solid var(--color-border-field);
  border-radius: var(--radius-sm);
  cursor: ns-resize;
  touch-action: none;
}
.color-picker-hue-handle {
  position: absolute;
  left: -3px;
  right: -3px;
  height: 9px;
  border: 2px solid #fff;
  border-radius: 6px;
  box-shadow: 0 0 0 1px #15171c;
  transform: translateY(-50%);
  pointer-events: none;
}
.color-picker-controls {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0 var(--space-3);
  margin-top: var(--space-2);
}
.color-picker-controls label { font-size: var(--font-size-sm); }
.color-picker-controls input[type="range"] {
  width: 100%;
  height: 44px;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  accent-color: var(--color-accent);
}

.color-palette { margin-top: var(--space-2); }
.color-palette summary {
  min-height: 44px;
  padding: var(--space-3) 0;
  color: var(--color-accent);
  cursor: pointer;
  font-weight: 600;
}
.color-swatches {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
  gap: var(--space-2);
  padding: var(--space-1);
}
.color-swatch {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  border: 1px solid #80838A;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: transform 120ms ease;
}
.color-swatch:active { transform: scale(.94); }
.color-swatch[aria-pressed="true"] { outline: 2px solid var(--color-text); outline-offset: 2px; }
.color-swatch-check {
  display: none;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #FFFFFF;
  color: #15171C;
  font-size: 18px;
  font-weight: 600;
  line-height: 1;
}
.color-swatch[aria-pressed="true"] .color-swatch-check { display: flex; }
.color-swatch:focus-visible { outline: 3px solid var(--color-accent); outline-offset: 3px; }
@media (hover: hover) { .color-swatch:hover { transform: translateY(-2px); } }
@media (prefers-reduced-motion: reduce) { .color-swatch, .color-swatch:hover, .color-swatch:active { transition: none; transform: none; } }
@media (min-width: 760px) { .color-row { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.swatch-white { background: #FFFFFF; }
.swatch-paper { background: #F6F5F2; }
.swatch-sand { background: #E8DCC8; }
.swatch-taupe { background: #A69889; }
.swatch-graphite { background: #5A5E68; }
.swatch-ink { background: #15171C; }
.swatch-butter { background: #F2DFA0; }
.swatch-ochre { background: #C49A3A; }
.swatch-caramel { background: #B87A4B; }
.swatch-terracotta { background: #B85C46; }
.swatch-clay { background: #D9B4A0; }
.swatch-espresso { background: #49352B; }
.swatch-mint { background: #D4E8DD; }
.swatch-sage { background: #A4B6A0; }
.swatch-olive { background: #747B4E; }
.swatch-eucalyptus { background: #527B68; }
.swatch-emerald { background: #236B57; }
.swatch-forest { background: #243F35; }
.swatch-ice { background: #D6E7ED; }
.swatch-denim { background: #587B99; }
.swatch-cornflower { background: #819AC5; }
.swatch-ultramarine { background: #3346D3; }
.swatch-navy { background: #25354D; }
.swatch-petrol { background: #28565E; }
.swatch-lavender { background: #E0DAED; }
.swatch-lilac { background: #B6A4CD; }
.swatch-mauve { background: #9A7A99; }
.swatch-iris { background: #6C609F; }
.swatch-plum { background: #744663; }
.swatch-aubergine { background: #49354E; }
.swatch-blush { background: #F0DCDD; }
.swatch-rose { background: #C9979D; }
.swatch-peach { background: #EDB79E; }
.swatch-coral { background: #D57869; }
.swatch-raspberry { background: #A84160; }
.swatch-burgundy { background: #6E3048; }

.color-preview {
  padding: var(--space-4);
  border: var(--border-width) solid var(--color-preview-border);
  border-radius: var(--radius);
}

.color-preview strong {
  display: block;
  font-size: var(--font-size-lg);
}

.color-preview span {
  font-size: var(--font-size-sm);
}

.logo-current {
  max-width: var(--logo-max-width);
  max-height: var(--logo-max-height);
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-sm);
}

/* ---------- Choices (radio groups) and long text ---------- */

.choices {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  border: 0;
}

.choices legend {
  padding: 0;
  margin-bottom: var(--space-2);
  font-weight: var(--font-weight-medium);
}

.choice label {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--control-min-height);
}

.choice .flash {
  margin: var(--space-1) 0 0;
}

.notice-text {
  margin: 0;
  white-space: pre-wrap;
  font-family: inherit;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* ---------- Public shop page ---------- */

.public-shop {
  text-align: center;
}

.public-logo {
  max-width: var(--logo-max-width);
  max-height: var(--logo-max-height);
}

/* ---------- Printing ---------- */

@media print {
  .topbar,
  .nav,
  .nav.nav-shop,
  .banner,
  .no-print {
    display: none;
  }

  body {
    padding: 0;
    color: var(--poster-ink);
    background: var(--poster-paper);
  }

  .container {
    max-width: none;
    padding: 0;
  }
}

/* ---------- Stamp symbols ---------- */

.stamp-icon {
  flex: none;
  width: var(--stamp-icon-size);
  height: var(--stamp-icon-size);
}

.program-name {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.choices-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--tile-min-width), 1fr));
  gap: var(--space-2);
}

.choices-tiles legend,
.choices-tiles .help {
  grid-column: 1 / -1;
}

.choices-tiles .choice label {
  flex-direction: column;
  justify-content: center;
  height: 100%;
  padding: var(--space-2);
  text-align: center;
  font-size: var(--font-size-sm);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.choices-tiles .choice label:has(input:checked) {
  border-color: var(--color-accent);
  outline: var(--indicator-width) solid var(--color-accent);
  outline-offset: calc(var(--border-width) * -1);
}

/* ---------- Public enrolment pages (the fixed QR) ---------- */

.link-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
  padding: 0;
  list-style: none;
}

.link-list .btn {
  width: 100%;
}

.public-shop form {
  text-align: left;
}

.incentive {
  font-weight: var(--font-weight-medium);
}

.checkbox-field label {
  display: flex;
  min-height: var(--touch-min);
  padding-top: calc(var(--touch-min) - var(--font-size-base) * var(--line-height));
  box-sizing: border-box;
  align-items: flex-start;
  gap: var(--space-3);
  font-weight: var(--font-weight-medium);
}

.checkbox-field input {
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 2px;
  margin-bottom: 0; /* the browser's own 3 px under a checkbox would push the link away from the text */
}

.notice {
  text-align: left;
}

/* The pages of the fixed QR (choose the card, enrolment form, "you already have it"): they belong to the shop.
   Body class "shop-page"; the three colors come from /n/<public_id>/stile.css, like the web card.
   The box is on the shop's colors; the fields stay white with ink text, so they always read well. */
/* Customer pages never follow the dark theme: the light values of the shared colors are set again here. */
.card-body,
.shop-page {
  --color-surface: #ffffff;
  --color-surface-sunken: #efeee9;
  --color-text: #15171c;
  --color-text-muted: #5a5e68;
  --color-border: #dcdad4;
  --color-border-field: #80838a;
  --color-error: #b42318;
  --color-error-soft: #fde8e6;
  --color-success: #1e7d46;
  --color-success-soft: #e3f4ea;
  --color-warning: #ffd166;
  --color-warning-soft: #fff1cc;
  --color-warning-text: #7a5200;
}

.shop-page {
  color-scheme: light;
  color: var(--pass-ink);
  background: var(--pass-page);
}

.shop-page .container {
  padding-top: var(--space-5);
}

.shop-page .public-shop {
  padding: var(--space-6) var(--space-5) var(--space-5);
  color: var(--card-text, var(--card-text-fallback));
  background: var(--card-bg, var(--card-bg-fallback));
  border-radius: var(--pass-radius);
  box-shadow: var(--shadow-pass);
}

.shop-page .public-logo {
  display: block;
  max-width: 200px;
  max-height: 88px;
  margin: 0 auto var(--space-4);
}

.shop-page .public-shop h1 {
  margin: 0;
  font-size: var(--font-size-xl);
}

.shop-page .public-shop h2 {
  margin: var(--space-2) 0 var(--space-4);
  font-size: var(--font-size-base);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--card-labels, var(--card-labels-fallback));
}

.shop-page .public-shop > p {
  margin: 0 0 var(--space-4);
}

.shop-page .public-shop .help,
.shop-page .public-shop .field label + input + .help {
  color: var(--card-labels, var(--card-labels-fallback));
}

.shop-page .public-shop a:not(.btn) {
  color: inherit;
}

.shop-page .public-shop input:not([type="checkbox"]):not([type="radio"]) {
  color: var(--pass-ink);
  background-color: var(--pass-surface);
  border-color: color-mix(in srgb, var(--card-text, var(--card-text-fallback)) 45%, transparent);
}

.shop-page .public-shop input[type="checkbox"] {
  accent-color: var(--card-text, var(--card-text-fallback));
}

/* Buttons in the shop's colors: the main one is "inverted" (text color as background). */
.shop-page .btn {
  min-height: 56px;
  color: var(--card-text, var(--card-text-fallback));
  background: transparent;
  border: 2px solid var(--card-text, var(--card-text-fallback));
}

.shop-page .btn-primary {
  color: var(--card-bg, var(--card-bg-fallback));
  background: var(--card-text, var(--card-text-fallback));
}

.shop-page .flash {
  color: var(--pass-ink);
}

.shop-page .incentive {
  padding: var(--space-3) var(--space-4);
  border: var(--border-width) solid color-mix(in srgb, var(--card-text, var(--card-text-fallback)) 40%, transparent);
  border-radius: var(--radius-sm);
}

/* The privacy notice and short messages on the same pages stay on paper, in ink. */
.shop-page .notice,
.shop-page .card:not(.public-shop) {
  color: var(--pass-ink);
  background: var(--pass-surface);
}

/* ==========================================================================
   THE WEB CARD
   The shop's colors arrive as three variables from /t/<token>/stile.css (the
   CSP forbids inline styles). The card has the shape of a Wallet pass:
   .tessera-pass holds head, balance, stamp strip, reward and QR on the shop's
   colors; info, Home-screen invite and signature sit below, on paper.
   Never put style="" on the card.
   ========================================================================== */

:root {
  --card-bg-fallback: #f6f5f2;
  --card-text-fallback: #15171c;
  --card-labels-fallback: #5a5e68;
  --card-width: 440px;
  --card-qr-size: 184px;
  --card-logo-max-width: 128px;
  --card-logo-max-height: 40px;
  --pass-page: #f6f5f2;
  --pass-surface: #ffffff;
  --pass-ink: #15171c;
  --pass-muted: #5a5e68;
  --pass-radius: 20px;
  --pass-pad: var(--space-4);
}

.card-body {
  color-scheme: light;
  color: var(--pass-ink);
  background: var(--pass-page);
}

.card-body .container {
  padding: var(--space-5) var(--space-4) 0;
}

.card-body a {
  color: inherit;
}

/* Preview of the card inside the panel: the colors come from /pannello/anteprima.css */
.preview-card {
  max-width: calc(var(--card-width) + var(--space-5) * 2);
  margin: 0 auto;
  padding: var(--space-5);
  color: var(--pass-ink);
  background: var(--pass-page);
  border-radius: var(--radius-lg);
}

.preview-card a {
  color: inherit;
}

.tessera {
  max-width: var(--card-width);
  margin: 0 auto;
}

/* The pass: one block on the shop's colors. A grid puts the balance at the top right, like a Wallet header field. */
.tessera-pass {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "head headline"
    "program badge"
    "stamps stamps"
    "reward reward"
    "extra extra"
    "expiry expiry"
    "notice notice"
    "qr qr";
  overflow: hidden;
  color: var(--card-text, var(--card-text-fallback));
  background: var(--card-bg, var(--card-bg-fallback));
  border-radius: var(--pass-radius);
  box-shadow: var(--shadow-pass);
}

.tessera-head {
  grid-area: head;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  min-height: 64px;
  padding: var(--pass-pad) var(--space-2) var(--space-1) var(--pass-pad);
}

.tessera-logo {
  display: block;
  flex: none;
  max-width: var(--card-logo-max-width);
  max-height: var(--card-logo-max-height);
}

.tessera-shop {
  margin: 0;
  overflow: hidden;
  font-size: 17px;
  font-weight: var(--font-weight-medium);
  line-height: 1.2;
  text-overflow: ellipsis;
}

/* The shop name is already written in a logo: keep it, but let it shrink first. */
.tessera-logo + .tessera-shop {
  font-size: var(--font-size-sm);
}

.tessera-headline {
  grid-area: headline;
  align-self: center;
  margin: 0;
  padding: var(--pass-pad) var(--pass-pad) var(--space-1) 0;
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-medium);
  letter-spacing: -0.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.tessera-program {
  grid-area: program;
  margin: 0;
  padding: var(--space-1) var(--pass-pad) var(--space-3);
  font-size: 13px;
  font-weight: var(--font-weight-medium);
  letter-spacing: 0.08em;
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--card-labels, var(--card-labels-fallback));
}

.tessera-badge {
  grid-area: badge;
  align-self: start;
  margin: 0 var(--pass-pad) var(--space-3) 0;
  padding: 2px 10px;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--card-bg, var(--card-bg-fallback));
  background: var(--card-text, var(--card-text-fallback));
  border-radius: var(--radius-pill);
}

/* The stamp strip: a band at 3:1, like the Apple strip (375 x 123) and the Google hero image (1032 x 336).
   ONLY stamps here, never text: the same band becomes the Wallet image. 3 to 20 stamps: one row up to 5,
   then two rows (20 stamps = 2 rows of 10). Columns are chosen by counting the stamps, no markup needed. */
.stamps {
  --stamp-cols: 5;
  --stamp-rows: 1;
  --stamp-gap: 8px;
  grid-area: stamps;
  container-type: size;
  display: grid;
  grid-template-columns: repeat(var(--stamp-cols), 1fr);
  align-content: center;
  justify-items: center;
  gap: var(--stamp-gap);
  aspect-ratio: 3 / 1;
  margin: 0;
  padding: 14px var(--pass-pad);
  list-style: none;
  color: var(--card-text, var(--card-text-fallback));
  background: var(--card-bg, var(--card-bg-fallback));
  background: color-mix(in srgb, var(--card-text, var(--card-text-fallback)) 9%, var(--card-bg, var(--card-bg-fallback)));
}

.stamps:has(> :last-child:nth-child(3)) { --stamp-cols: 3; }
.stamps:has(> :last-child:nth-child(4)) { --stamp-cols: 4; }
.stamps:has(> :nth-child(6)) { --stamp-rows: 2; }
.stamps:has(> :last-child:nth-child(6)) { --stamp-cols: 3; }
.stamps:has(> :last-child:nth-child(7)),
.stamps:has(> :last-child:nth-child(8)) { --stamp-cols: 4; }
.stamps:has(> :last-child:nth-child(11)),
.stamps:has(> :last-child:nth-child(12)) { --stamp-cols: 6; }
.stamps:has(> :last-child:nth-child(13)),
.stamps:has(> :last-child:nth-child(14)) { --stamp-cols: 7; }
.stamps:has(> :last-child:nth-child(15)),
.stamps:has(> :last-child:nth-child(16)) { --stamp-cols: 8; }
.stamps:has(> :last-child:nth-child(17)),
.stamps:has(> :last-child:nth-child(18)) { --stamp-cols: 9; }
.stamps:has(> :last-child:nth-child(19)),
.stamps:has(> :last-child:nth-child(20)) { --stamp-cols: 10; }

.stamp {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Fallback for browsers without container units (iOS before 16): a fixed size that never overflows its column.
     Where cqw/cqh exist, the declaration below replaces the width. */
  width: 40px;
  max-width: 100%;
  width: min(
    calc((100cqw - (var(--stamp-cols) - 1) * var(--stamp-gap)) / var(--stamp-cols)),
    calc((100cqh - (var(--stamp-rows) - 1) * var(--stamp-gap)) / var(--stamp-rows)),
    64px
  );
  aspect-ratio: 1;
  border-radius: 50%;
}

.stamp .stamp-icon {
  width: 52%;
  height: 52%;
}

/* Taken: a disc in the text color, the symbol in the background color (same contrast as the text). */
.stamp-full {
  color: var(--card-bg, var(--card-bg-fallback));
  background: var(--card-text, var(--card-text-fallback));
}

/* The newest stamp lands with a short press (it plays when the open card reloads after a stamp). */
.stamp-full:has(+ .stamp-empty) {
  animation: stamp-press 0.5s var(--ease-out) both;
}

@keyframes stamp-press {
  from { opacity: 0; scale: 1.6; }
  60% { opacity: 1; scale: 0.92; }
  to { scale: 1; }
}

/* To take: a ring in the text color, no symbol. Text on background is the pair with the most contrast (the panel
   warns the owner under 4.5:1), so the ring stays visible even with a weak labels color. Filled disc vs empty
   ring is what tells them apart. */
.stamp-empty {
  border: 2px solid var(--card-text, var(--card-text-fallback));
}

.stamp-empty .stamp-icon {
  visibility: hidden;
}

/* Secondary lines of the pass */
.tessera-reward,
.tessera-secondary {
  grid-area: reward;
  margin: 0;
  padding: var(--space-3) var(--pass-pad) 0;
}

.tessera-secondary {
  color: var(--card-labels, var(--card-labels-fallback));
}

.tessera-reward + .tessera-secondary,
.tessera-secondary + .tessera-secondary {
  grid-area: extra;
  padding-top: var(--space-1);
}

/* The expiry dates (Phase 6a): their own row, so they never share a grid area with the lines above. Same look as the other secondary lines. */
.tessera-expiry {
  grid-area: expiry;
  padding: var(--space-1) var(--pass-pad) 0;
  color: var(--card-labels, var(--card-labels-fallback));
}

.tessera-expiry p {
  margin: 0;
}

/* The reward: in evidence, with the gift symbol (inline <svg class="icon">) in the text color. */
.tessera-reward {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
  line-height: 1.35;
}

.tessera-reward .icon {
  width: 22px;
  height: 22px;
  margin-top: 1px;
}

.tessera-notice {
  grid-area: notice;
  margin: var(--space-4) var(--pass-pad) 0;
  padding: var(--space-3);
  font-weight: var(--font-weight-medium);
  border: var(--border-width) solid color-mix(in srgb, var(--card-text, var(--card-text-fallback)) 40%, transparent);
  border-radius: var(--radius-sm);
}

/* The QR stays near-black on white whatever the shop colors are: it has to be scanned. */
.tessera-qr {
  grid-area: qr;
  margin: 0;
  padding: var(--space-5) var(--pass-pad) var(--space-5);
  text-align: center;
}

.tessera-qr svg {
  display: block;
  width: var(--card-qr-size);
  height: var(--card-qr-size);
  margin: 0 auto var(--space-2);
  padding: 10px;
  box-sizing: content-box;
  background: var(--qr-paper);
  border-radius: var(--radius-sm);
}

.tessera-qr p {
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--card-labels, var(--card-labels-fallback));
}

/* Expired: the strip loses its color, the badge says "Scaduta", no QR. */
.tessera[data-state="expired"] .stamps {
  filter: grayscale(1);
}

.tessera[data-state="expired"] .tessera-pass {
  padding-bottom: var(--pass-pad);
}

/* Below the pass: neutral page, ink text. */
.tessera-info,
.tessera-home {
  margin-top: var(--space-4);
  padding: var(--space-4);
  color: var(--pass-ink);
  background: var(--pass-surface);
  border-radius: var(--radius);
  box-shadow: 0 1px 2px rgb(21 23 28 / 0.06);
}

.tessera-info {
  margin-top: var(--space-5);
}

.tessera-info h2,
.tessera-home h2 {
  margin: 0 0 var(--space-3);
  font-size: var(--font-size-base);
  letter-spacing: 0;
}

.tessera-info dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-4);
  margin: 0 0 var(--space-3);
}

.tessera-info dt {
  padding-top: 1px;
  font-size: var(--font-size-sm);
  color: var(--pass-muted);
}

.tessera-info dd {
  margin: 0;
  white-space: pre-line;
}

.tessera-info p {
  margin: 0;
}

/* The links below the shop data (rules, privacy, «Non voglio più ricevere offerte», Phase P2) get a tap area of 44 px. */
.tessera-info p a {
  display: inline-block;
  padding: var(--space-3) 0;
}

/* Rules and expiries of the program (Phase 7a): plain lines, not designed in step 0. */
.tessera-rules {
  margin: 0;
  padding: 0 0 0 var(--space-4);
}

.tessera-rules li {
  margin: 0 0 var(--space-2);
}

.tessera-rules li:last-child {
  margin-bottom: 0;
}

/* Invite to keep the card on the Home screen */
.tessera-home h2 {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.tessera-home h2 .icon {
  width: var(--icon-size-sm);
  height: var(--icon-size-sm);
}

.tessera-home p {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--pass-muted);
}

.tessera-home p:last-child {
  margin-bottom: 0;
}

.tessera-home strong {
  color: var(--pass-ink);
}

/* Revenit signs at the bottom, small, on paper (BRAND.md §2). */
.tessera-signature {
  padding: var(--space-6) 0 var(--space-6);
  text-align: center;
}

.tessera-signature p {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--pass-muted);
}

.tessera-signature-logo {
  display: block;
  width: auto;
  height: 16px;
  margin-top: 2px;
}

/* ---------- Personal QR shown by the panel ("Nuova tessera") ---------- */

.handover {
  text-align: center;
}

/* The QR stays black on white: the customer's phone has to scan it from across the counter. */
.handover-qr svg {
  display: block;
  width: 100%;
  max-width: 480px;
  height: auto;
  margin: var(--space-4) auto;
}

.handover-who {
  font-weight: var(--font-weight-medium);
}

/* ==========================================================================
   CASH DESK: home, search, results, card page, scan
   ========================================================================== */

.cash-home {
  padding: 0;
  background: transparent;
  box-shadow: none;
}

.cash-home .cash-intro {
  margin: 0 0 var(--space-5);
  color: var(--color-text-muted);
}

.search-form {
  margin-top: var(--space-4);
}

.search-form .field label {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* Results */
.results,
.result-cards,
.history {
  margin: 0;
  padding: 0;
  list-style: none;
}

.results {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

.result {
  overflow: hidden;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.result-who {
  margin: 0;
  padding: var(--space-4) var(--space-4) var(--space-2);
  font-size: var(--font-size-md);
}

.result-phone {
  display: block;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-regular);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

.result-cards {
  display: flex;
  flex-direction: column;
}

.result-cards li + li {
  border-top: var(--border-width) solid var(--color-border);
}

/* Each card of the customer: a full-width row, program on the left, balance on the right. */
.result-cards .btn {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto var(--icon-size-sm);
  grid-template-areas:
    "program balance chevron"
    "flag flag flag";
  align-items: center;
  gap: 2px var(--space-3);
  width: 100%;
  min-height: 60px;
  padding: var(--space-3) var(--space-4);
  text-align: left;
  border: 0;
  border-top: var(--border-width) solid var(--color-border);
  border-radius: 0;
}

.result-cards li + li .btn {
  border-top: 0;
}

.result-cards .btn > :first-child {
  grid-area: program;
}

.result-balance {
  grid-area: balance;
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
  font-variant-numeric: tabular-nums;
}

.result-cards .icon {
  grid-area: chevron;
  width: var(--icon-size-sm);
  height: var(--icon-size-sm);
  color: var(--color-text-muted);
}

.result-flag {
  grid-area: flag;
  justify-self: start;
  padding: 0 var(--space-2);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-warning-text);
  background: var(--color-warning-soft);
  border-radius: var(--radius-pill);
}

/* The card page: who is in front of the counter, in large type (decision D23). */
.cash-card {
  padding: 0;
  background: transparent;
  box-shadow: none;
}

.who {
  margin: 0;
  font-size: var(--font-size-title);
  font-weight: var(--font-weight-bold);
  letter-spacing: -0.03em;
  line-height: 1.1;
  overflow-wrap: anywhere;
}

.who-phone {
  margin: var(--space-1) 0 0;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

.who-summary {
  margin-top: var(--space-4);
  overflow: hidden;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.who-summary-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4) var(--space-3);
}

.cash-card .who-program {
  margin: 0;
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  letter-spacing: 0;
  color: var(--color-text-muted);
}

.who-balance {
  margin: 0;
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-medium);
  letter-spacing: -0.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* The customer's stamp strip, in the shop's colors (they come from /pannello/anteprima.css). */
.who-strip .stamps {
  aspect-ratio: 4 / 1;
}

.who-summary > .help,
.who-summary > .tessera-reward {
  margin: 0;
  padding: var(--space-3) var(--space-4);
}

.who-summary > .help + .help {
  padding-top: 0;
}

/* In the panel the reward is good news: green chip, gift symbol. */
.cash-card .tessera-reward {
  display: flex;
  margin: 0;
  padding: var(--space-3) var(--space-4);
  font-size: var(--font-size-base);
  color: var(--color-success);
  background: var(--color-success-soft);
}

.cash-card .flash {
  margin: var(--space-4) 0 0;
}

/* The two actions. +1 is the ultramarine one, closest to the thumb; Riscatta sits above it, outlined,
   so a hurried tap does not take a reward by mistake. */
.actions {
  display: flex;
  flex-direction: column-reverse;
  gap: var(--space-3);
  margin: var(--space-4) 0;
}

.actions form,
.actions .btn {
  width: 100%;
}

.actions .btn:not(.btn-primary) {
  border-width: 2px;
  border-color: var(--color-text);
}

.actions-more {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0 0 var(--space-5);
}

.actions-more .btn {
  flex: 1 1 auto;
}

/* «Fatto. Annulla»: an ink bar with a thin line that empties in 5 minutes, then the bar goes away by itself
   (review 3, S2). A reload restarts the line. */
.undo-now {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  overflow: hidden;
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
  color: var(--color-on-ink);
  background: var(--color-ink-bar);
  border: 0;
  animation: undo-expire 0s linear var(--undo-window) forwards;
}

.cash-card .undo-now {
  margin-top: var(--space-4);
}

.undo-now > span {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.undo-now > span .icon {
  width: var(--icon-size-sm);
  height: var(--icon-size-sm);
  color: var(--color-accent-on-ink);
}

.undo-now form {
  margin: 0;
}

.undo-now .btn {
  color: var(--color-ink-bar);
  background: var(--color-on-ink);
  border-color: var(--color-on-ink);
}

.undo-now::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 3px;
  background: var(--color-accent-on-ink);
  transform-origin: left;
  animation: undo-drain var(--undo-window) linear forwards;
}

@keyframes undo-drain {
  from { transform: scaleX(1); }
  to { transform: scaleX(0); }
}

@keyframes undo-expire {
  to {
    visibility: hidden;
    height: 0;
    margin: 0;
    padding: 0;
  }
}

/* History */
.cash-card > h2 {
  margin: var(--space-6) 0 var(--space-2);
  font-size: var(--font-size-lg);
}

.history {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.history-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px var(--space-3);
  align-items: center;
  min-height: 64px;
  padding: var(--space-3) var(--space-4);
}

.history-row + .history-row {
  border-top: var(--border-width) solid var(--color-border);
}

.history-qty {
  margin-left: var(--space-1);
  font-weight: var(--font-weight-medium);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
}

.history-meta {
  grid-column: 1;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

.history-row form {
  grid-column: 2;
  grid-row: 1 / span 2;
}

.history-row form .btn {
  color: var(--color-accent);
  border-color: var(--color-border);
}

.history-cancelled .history-what strong,
.history-cancelled .history-qty {
  text-decoration: line-through;
  color: var(--color-text-muted);
}

.history-cancelled .history-what em {
  display: inline-block;
  margin-left: var(--space-1);
  padding: 0 var(--space-2);
  font-size: var(--font-size-sm);
  font-style: normal;
  color: var(--color-text-muted);
  background: var(--color-surface-sunken);
  border-radius: var(--radius-pill);
  text-decoration: none;
}

/* Scan: the camera in a rounded frame, with corner marks and a line that sweeps. */
.scan {
  padding: 0;
  background: transparent;
  box-shadow: none;
}

.scan-frame {
  position: relative;
  overflow: hidden;
  margin: var(--space-4) 0;
  aspect-ratio: 1 / 1;
  background: #000000;
  border-radius: var(--radius-lg);
}

.scan-frame::before {
  content: "";
  position: absolute;
  inset: 18%;
  border: 4px solid #ffffff;
  border-radius: var(--radius-lg);
  -webkit-mask:
    linear-gradient(#000 0 0) top left / 28% 28% no-repeat,
    linear-gradient(#000 0 0) top right / 28% 28% no-repeat,
    linear-gradient(#000 0 0) bottom left / 28% 28% no-repeat,
    linear-gradient(#000 0 0) bottom right / 28% 28% no-repeat;
  mask:
    linear-gradient(#000 0 0) top left / 28% 28% no-repeat,
    linear-gradient(#000 0 0) top right / 28% 28% no-repeat,
    linear-gradient(#000 0 0) bottom left / 28% 28% no-repeat,
    linear-gradient(#000 0 0) bottom right / 28% 28% no-repeat;
  pointer-events: none;
  z-index: 1;
}

.scan-frame::after {
  content: "";
  position: absolute;
  left: 22%;
  right: 22%;
  top: 22%;
  height: 2px;
  background: var(--color-accent-on-ink);
  box-shadow: 0 0 12px 2px color-mix(in srgb, var(--color-accent-on-ink) 60%, transparent);
  animation: scan-sweep 2.4s ease-in-out infinite alternate;
  z-index: 1;
}

@keyframes scan-sweep {
  from { top: 22%; }
  to { top: 78%; }
}

.scan-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.scan-status {
  margin: 0 0 var(--space-4);
  font-weight: var(--font-weight-medium);
  text-align: center;
}

.scan .btn {
  width: 100%;
}

/* ---------- Reduced motion ---------- */

/* Everything stops. "!important" is needed: the animations and transitions of single classes (the stamp that lands, the
   buttons, the Scansiona dot) are more specific than "*", so without it they kept running (found in the design phase).
   The undo bar is the one exception: it still goes away after 5 minutes, only its moving line is dropped. */
@media (prefers-reduced-motion: reduce) {
  *:not(.undo-now),
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }

  .undo-now {
    animation: undo-expire 0s linear var(--undo-window) forwards;
  }

  .undo-now::after,
  .scan-frame::after {
    display: none;
  }
}

/* ---------- Additions to sistema.css (see the report of the design phase) ---------- */

/* Text for screen readers only (for example the shop name when the logo already shows it). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Old browsers without aspect-ratio (iOS 14 and earlier): keep the stamps round and square. */
@supports not (aspect-ratio: 1 / 1) {
  .stamp::before {
    content: "";
    padding-top: 100%;
  }
}

/* ==========================================================================
   POINTS PROGRAMS (Phase 4, step 0 of the brand designer)
   Everything for points is in this block; no rule above was changed, so stamp cards look exactly as before.
   ========================================================================== */

/* The points strip: same place, background and 3:1 shape as the stamp strip, and ONLY drawing, never text: it becomes
   the Wallet image (Phase W2). An inline SVG (viewBox 320 x 90) with a track that fills toward the threshold and a disc
   with the gift at the end: ring = still to reach, filled disc = reward ready. Beyond the threshold the strip stays
   full, like the stamps; the text lines say "2 premi disponibili" and "Già 40 punti per il prossimo".
   The SVG has width and height attributes, so its height never depends on aspect-ratio (old phones, D29). */
.points {
  grid-area: stamps;
  margin: 0;
  padding: 14px var(--pass-pad);
  color: var(--card-text, var(--card-text-fallback));
  background: var(--card-bg, var(--card-bg-fallback));
  background: color-mix(in srgb, var(--card-text, var(--card-text-fallback)) 9%, var(--card-bg, var(--card-bg-fallback)));
}

.points svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.points-track,
.points-goal {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
}

.points-fill {
  fill: currentColor;
}

.points-goal-icon {
  color: var(--card-text, var(--card-text-fallback));
}

/* Reward ready: the disc fills with the text color and the gift takes the background color, like a taken stamp. */
.points-reached .points-goal {
  fill: currentColor;
}

.points-reached .points-goal-icon {
  color: var(--card-bg, var(--card-bg-fallback));
}

.tessera[data-state="expired"] .points {
  filter: grayscale(1);
}

/* The balance of a points card: a large number and a small unit ("240 punti"), so even "12.480 punti" fits next to
   a wide logo on a 360 px phone. */
.balance-unit {
  font-size: var(--font-size-sm);
  letter-spacing: 0;
  color: var(--card-labels, var(--card-labels-fallback));
}

.who-balance .balance-unit {
  color: var(--color-text-muted);
}

/* In the panel the strip is a little lower, like the stamps (4:1 there). */
.who-strip .points {
  padding-block: var(--space-2);
}

.who-strip .points svg {
  max-height: 72px;
}

/* Cash desk: the amount and its button in one form, the button right under the field (the iOS decimal keypad has no
   return key and covers the lower half of the screen). Riscatta stays above the whole group. */
.points-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.amount-field input:not([type="checkbox"]):not([type="radio"]):not([type="color"]) {
  min-height: var(--control-big-min-height);
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-medium);
  font-variant-numeric: tabular-nums;
}

/* "= 14 punti" while the owner types (a hint: the server does the real count), "3 punti per ogni euro" when empty. */
.amount-field .amount-points {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

/* New program, step 1: two rows with a title and one line of explanation. */
.menu-list .menu-text strong {
  display: block;
  font-weight: var(--font-weight-medium);
}

.menu-sub {
  display: block;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* New program, step 2, and Modifica: the type is shown, not chosen again. */
.program-type {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--control-min-height);
  margin: 0;
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
  background: var(--color-surface-sunken);
  border-radius: var(--radius-sm);
}

.program-type > span {
  flex: 1 1 auto;
  font-weight: var(--font-weight-medium);
}

.program-type .icon {
  width: var(--icon-size-sm);
  height: var(--icon-size-sm);
  color: var(--color-text-muted);
}

/* ==========================================================================
   PHASE 7 (step 0 of the brand designer): numbers, customer list, a dangerous action
   Three components of the owner's panel. Only new classes: no rule above changes, and nothing here needs a rule that
   exists only in this file, so the block can be appended as it is to public/stile.css (the rest of the file is not
   aligned yet, see TODO.md).
   Mobile first: the base needs no query, no :has(), no color-mix(), no cqw/cqh, no aspect-ratio and no gap in flexbox
   (D29). The wide layout sits in @container page: a browser without container queries keeps the phone layout.
   ========================================================================== */

/* Lists and numbers read better in a column than across a whole computer screen. */
.page-column {
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}

/* ---------- 1. Numbers of the shop (/pannello/numeri) ---------- */

.stats-list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

/* One block per program, and one for the whole shop. */
.stats {
  padding: var(--space-4);
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.stats-head {
  display: flex;
  align-items: center;
  margin-bottom: var(--space-2);
}

/* The program's icon, as at the start of a menu row: ultramarine on its soft tint. */
.stats-head .icon {
  box-sizing: content-box;
  flex: none;
  width: var(--icon-size-sm);
  height: var(--icon-size-sm);
  margin-right: var(--space-3);
  padding: 8px;
  color: var(--color-accent-on-soft);
  background: var(--color-accent-soft);
  border-radius: var(--radius-sm);
}

.stats-program {
  min-width: 0;
  margin: 0;
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-medium);
  overflow-wrap: anywhere;
}

/* "240 tessere · 85 attive": counts of today, not of a period, so they sit above the two columns (D52). */
.stats-cards {
  margin: 0 0 var(--space-4);
  font-size: var(--font-size-md);
  font-variant-numeric: tabular-nums;
}

.stats-cards strong {
  font-weight: var(--font-weight-medium);
}

/* Two columns, «Ultimi 30 giorni» and «Da sempre» (D53). The captions are written once, above; every number also
   carries its period for screen readers (<span class="sr-only">). */
.stats-cols,
.stat {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--space-3);
}

.stats-cols {
  margin: 0;
  padding-bottom: var(--space-2);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  border-bottom: var(--border-width) solid var(--color-border);
}

.stats-grid {
  margin: 0;
}

.stat {
  padding: var(--space-3) 0;
  border-bottom: var(--border-width) solid var(--color-border);
}

.stats-grid .stat:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

/* The label above its two numbers: on a 320 px phone a label and two large numbers do not fit on one line. */
.stat dt {
  grid-column: 1 / -1;
  margin-bottom: var(--space-1);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* A large number: 28 px, fixed-width digits, Italian thousands («148.230» fits a column at 320 px). */
.stat dd {
  margin: 0;
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-tight);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* A thin line between the two columns. */
.stats-cols span + span,
.stat dd + dd {
  padding-left: var(--space-3);
  border-left: var(--border-width) solid var(--color-border);
}

.stats-note {
  margin-top: var(--space-3);
}

/* Wide screens: the label on the left and the two numbers in fixed columns, like a table. */
@container page (min-width: 640px) {
  .stats-cols,
  .stat {
    grid-template-columns: minmax(0, 1fr) 9.5em 9.5em;
    align-items: baseline;
  }

  .stats-cols span:first-child {
    grid-column: 2;
  }

  .stat dt {
    grid-column: auto;
    margin: 0;
    font-size: var(--font-size-base);
    color: var(--color-text);
  }
}

/* ---------- 2. Customer list (/pannello/clienti) ---------- */

/* The filters are plain links: their state lives in the address (?programma=…&assenti=30&pagina=2), so «indietro» from
   a card comes back to the same list. One tap, no form, no script. */
.filters {
  margin: 0 0 var(--space-4);
}

.filter-label {
  margin: var(--space-4) 0 var(--space-2);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
}

.filters > .filter-label:first-child {
  margin-top: 0;
}

/* Programs (shown only with two or more): chips that wrap, whatever the length of the names. */
.chips {
  display: flex;
  flex-wrap: wrap;
  margin: 0 0 calc(-1 * var(--space-2));
  padding: 0;
  list-style: none;
}

.chips li {
  max-width: 100%;
  margin: 0 var(--space-2) var(--space-2) 0;
}

.chips a {
  display: flex;
  align-items: center;
  min-height: var(--touch-min);
  padding: var(--space-1) var(--space-4);
  font-weight: var(--font-weight-medium);
  line-height: 1.2;
  color: var(--color-text);
  text-decoration: none;
  overflow-wrap: anywhere;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border-field);
  border-radius: var(--radius-pill);
}

/* Days: four equal segments in one row, even at 320 px. The number on top, «giorni» under it. */
.segmented {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  overflow: hidden;
  list-style: none;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border-field);
  border-radius: var(--radius);
}

.segmented li + li {
  border-left: var(--border-width) solid var(--color-border-field);
}

.segmented a {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  min-height: var(--control-min-height);
  padding: var(--space-1) 2px;
  font-size: var(--font-size-sm);
  line-height: 1.15;
  text-align: center;
  color: var(--color-text);
  text-decoration: none;
}

.segmented strong {
  display: block;
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
}

/* Wide screens: «30 giorni» on one line. */
@container page (min-width: 640px) {
  .segmented a {
    flex-direction: row;
  }

  .segmented strong {
    margin-right: 0.25em;
  }
}

/* The segment clips its children: the focus ring goes inside, or it would be cut. */
.segmented a:focus-visible {
  outline-offset: -5px;
}

/* The chosen filter: soft ultramarine, a 2 px ring and the text in the accent (more than color alone: the ring and
   the weight change too). aria-current="true" on the link. */
.chips a[aria-current="true"],
.segmented a[aria-current="true"] {
  color: var(--color-accent-on-soft);
  background: var(--color-accent-soft);
  box-shadow: inset 0 0 0 2px var(--color-accent);
}

.chips a[aria-current="true"] {
  border-color: var(--color-accent);
}

.segmented a[aria-current="true"] {
  font-weight: var(--font-weight-medium);
}

/* "240 tessere" or "12 tessere senza visite negli ultimi 30 giorni". */
.list-count {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

/* One row per card (D54): the whole row is the link to the card page. */
.customer-list {
  margin: 0;
  padding: 0;
  overflow: hidden;
  list-style: none;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.customer-list li + li {
  border-top: var(--border-width) solid var(--color-border);
}

.customer {
  position: relative;
  display: block;
  min-height: 60px;
  padding: var(--space-3) calc(var(--space-4) + var(--icon-size-sm) + var(--space-3)) var(--space-3) var(--space-4);
  color: var(--color-text);
  text-decoration: none;
}

.customer:active {
  background: var(--color-surface-sunken);
}

@media (hover: hover) {
  .customer:hover {
    background: var(--color-surface-sunken);
  }
}

/* The customer is in focus: the ring goes inside the row (the list clips its children). */
.customer:focus-visible {
  outline-offset: -4px;
}

/* First line: name (or «Cliente n. 482») on the left, balance on the right. */
.customer-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.customer-name {
  min-width: 0;
  font-weight: var(--font-weight-medium);
  overflow-wrap: anywhere;
}

.customer-balance {
  flex: none;
  padding-left: var(--space-3);
  font-weight: var(--font-weight-medium);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The other lines: program (only with two or more), last visit, visits and rewards. */
.customer-meta {
  display: block;
  margin-top: 2px;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

.customer-chevron {
  position: absolute;
  top: 50%;
  right: var(--space-4);
  width: var(--icon-size-sm);
  height: var(--icon-size-sm);
  margin-top: calc(var(--icon-size-sm) / -2);
  color: var(--color-text-muted);
}

/* Pages of 50: on the phone the position on top, the two buttons under it; wide, all in one row. */
.pager {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2) var(--space-3);
  margin: var(--space-4) 0;
}

.pager-info {
  grid-column: 1 / -1;
  margin: 0;
  font-size: var(--font-size-sm);
  text-align: center;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

.pager .btn {
  width: 100%;
}

.pager-prev {
  grid-column: 1;
}

.pager-next {
  grid-column: 2;
}

.pager .icon {
  width: var(--icon-size-sm);
  height: var(--icon-size-sm);
}

@container page (min-width: 640px) {
  .pager {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
  }

  .pager-info {
    grid-column: 2;
    grid-row: 1;
  }

  .pager .btn {
    width: auto;
  }

  .pager-prev {
    grid-row: 1;
    justify-self: start;
  }

  .pager-next {
    grid-column: 3;
    grid-row: 1;
    justify-self: end;
  }
}

/* ---------- 3. Confirming a dangerous action (erasing a customer's data, Phase 7b) ---------- */

/* Same page shape as the card page: who it is in large type (the global .who and .who-phone), then what goes away. */
.danger-confirm {
  max-width: var(--narrow-width);
  margin: 0 auto var(--space-4);
}

.danger-kicker {
  display: flex;
  align-items: center;
  margin: 0 0 var(--space-2);
  font-weight: var(--font-weight-medium);
  color: var(--color-error);
}

.danger-kicker .icon {
  width: var(--icon-size-sm);
  height: var(--icon-size-sm);
  margin-right: var(--space-2);
}

/* What goes away: every card with its balance, then the history and the personal data. */
.danger-gone {
  margin-top: var(--space-5);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.danger-gone h2 {
  margin: var(--space-1) 0 var(--space-1);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  letter-spacing: 0;
  color: var(--color-text-muted);
}

.danger-gone ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.danger-gone li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: var(--space-2) 0;
  overflow-wrap: anywhere;
}

.danger-gone li + li {
  border-top: var(--border-width) solid var(--color-border);
}

.danger-qty {
  flex: none;
  padding-left: var(--space-3);
  font-weight: var(--font-weight-medium);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* «Non si può annullare.»: red title on the soft red, with the warning sign. Text 15:1, title 5.6:1 (dark 6.6:1). */
.danger-warning {
  display: flex;
  align-items: flex-start;
  margin: var(--space-4) 0 0;
  padding: var(--space-3) var(--space-4);
  color: var(--color-text);
  background: var(--color-error-soft);
  border: var(--border-width) solid var(--color-error);
  border-radius: var(--radius);
}

.danger-warning .icon {
  flex: none;
  margin: 2px var(--space-3) 0 0;
  color: var(--color-error);
}

.danger-warning p {
  margin: 0;
}

.danger-warning strong {
  display: block;
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
  color: var(--color-error);
}

/* The two choices, far apart (24 px). The safe one, Annulla, is at the bottom, under the thumb: the opposite of the cash
   desk, where the bottom holds the frequent action (+1). A grid, not a flex gap, so old phones keep the space too. */
.danger-actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  margin: var(--space-5) 0;
}

.danger-actions form {
  margin: 0;
}

.danger-actions .btn,
.danger-actions button {
  width: 100%;
}

/* Confirm: filled red, never ultramarine (in the panel ultramarine is the normal main action). The text takes the
   surface color: 6.6:1 on the light red; the dark theme's red is a light pink, so there the text is dark (7.3:1). */
.btn-danger-solid {
  color: var(--color-surface);
  background: var(--color-error);
  border-color: var(--color-error);
}

/* Annulla: outlined in the text color, like Riscatta on the card page. */
.danger-actions .btn:not(.btn-danger-solid) {
  border-width: 2px;
  border-color: var(--color-text);
}
