/* officina.it Design System v2 — Calm */

/* ── Self-hosted fonts ───────────────────────── */

/* Inter — latin-ext */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Inter — latin */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


:root {
  /* Surfaces */
  --v2-bg: #ffffff;
  --v2-surface-2: #fafafa;
  /* Hover — neutral gray wash for interactive surfaces. */
  --v2-hover: #fafafa;
  --v2-hover-strong: #f0f0f0;

  /* Ink scale */
  --v2-ink: #0a0e1a;
  --v2-ink-2: #1f2937;
  --v2-ink-3: #6b7280;
  --v2-ink-4: #9ca3af;
  --v2-ink-5: #d1d5db;

  /* Hairlines */
  --v2-line: #ececec;
  --v2-line-2: #d1d5db;

  /* Brand — primary action only */
  --v2-brand: #2563eb;
  --v2-brand-2: #1d4ed8;
  /* Brand soft — state indicators (toggles, etc.); deliberately
     distinct from --v2-brand so they don't compete with primary CTAs. */
  --v2-brand-soft: #60a5fa;

  /* State — used sparingly, semantic only */
  --v2-good: #15803d;
  --v2-warn: #b45309;
  --v2-danger: #b91c1c;

  /* Soft tints / fills — backgrounds and tracks (no text/borders) */
  --v2-good-bg: #dcfce7;          /* success halo / soft success fill */
  --v2-brand-bg: #eff6ff;         /* subtle brand row/section tint */
  --v2-brand-bg-strong: #dbeafe;  /* brand row hover / stronger tint */
  --v2-track: #eef0f4;            /* progress track / empty ring fill */

  /* Radius */
  --v2-r-sm: 4px;
  --v2-r-md: 6px;
  --v2-r-lg: 8px;
}

/* ── Base ────────────────────────────────────── */

.v2 {
  font-family: 'Inter', -apple-system, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  color: var(--v2-ink);
  background: var(--v2-bg);
}

.v2 * { box-sizing: border-box; }

/* .mono — single utility for numeric / code-like displays. Inter is
   already the body font; this class just keeps digit columns aligned
   (tabular-nums) and prevents wrapping. Used to be a 'JetBrains Mono'
   font swap; switched away because the subsetted woff2 had a dotted '0'
   confusable with '8' in price tables. All formerly-mono inline styles
   across templates now use `font-variant-numeric:tabular-nums` directly. */
.v2 .mono {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── Typography ──────────────────────────────── */

.v2-display {
  font-size: 22px;
  line-height: 28px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--v2-ink);
}

.v2-page-title {
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--v2-ink);
  margin: 0;
}

.v2-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--v2-ink);
}

.v2-body {
  font-size: 13.5px;
  font-weight: 400;
  color: var(--v2-ink);
}

.v2-label {
  font-size: 12.5px;
  font-weight: 400;
  color: var(--v2-ink-3);
}

.v2-code {
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
  font-weight: 500;
}

.v2-eyebrow {
  font-size: 11px;
  font-weight: 600;
  color: var(--v2-ink-3);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0;
}

.v2-muted {
  color: var(--v2-ink-4);
}

/* ── Layout ──────────────────────────────────── */

.v2-app {
  display: flex;
  width: 100%;
  min-height: 100vh;
  background: var(--v2-bg);
}

.v2-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.v2-content {
  flex: 1;
  overflow: auto;
  background: var(--v2-bg);
}

:root {
  --v2-container-max:        1240px;
  --v2-container-medium-max: 1080px;
  --v2-container-form-max:    880px;
}

.v2-container {
  max-width: var(--v2-container-max);
  margin: 0 auto;
  padding: 32px 32px 64px;
}

.v2-container-medium {
  max-width: var(--v2-container-medium-max);
  margin: 0 auto;
  padding: 32px 32px 64px;
}

.v2-container-form {
  max-width: var(--v2-container-form-max);
  margin: 0 auto;
  padding: 32px 32px 64px;
}

/* ── Sidebar ─────────────────────────────────── */

.v2-sidebar {
  width: 224px;
  background: var(--v2-bg);
  border-right: 1px solid var(--v2-line);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  height: 100vh;
  position: sticky;
  top: 0;
  transition: width 0.15s ease;
}

.v2-sidebar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 14px;
  height: 52px;
  flex-shrink: 0;
  border-bottom: 1px solid var(--v2-line);
}

.v2-sidebar-brand img {
  width: 28px;
  height: 28px;
  object-fit: contain;
}

.v2-sidebar-brand-name {
  font-weight: 600;
  font-size: 14px;
  letter-spacing: -0.01em;
}

.v2-sidebar-brand-name span {
  color: var(--v2-ink-3);
  font-weight: 500;
}

.v2-sidebar-search {
  padding: 12px 12px 8px;
}

.v2-sidebar-search-inner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  background: var(--v2-surface-2);
  border-radius: 8px;
  border: 1px solid transparent;
  font-size: 12.5px;
  color: var(--v2-ink-3);
}

.v2-sidebar-search-kbd {
  margin-left: auto;
  font-size: 10.5px;
  color: var(--v2-ink-4);
  padding: 1px 5px;
  border: 1px solid var(--v2-line-2);
  border-radius: 4px;
  font-variant-numeric: tabular-nums;
}

.v2-sidebar-nav {
  padding: 4px 8px;
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
}

.v2-sidebar-nav a,
.v2-sidebar-nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  margin: 1px 0;
  border-radius: 7px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  color: var(--v2-ink-2);
  text-decoration: none;
  position: relative;
  background: transparent;
  border: none;
  width: 100%;
  text-align: left;
  font-family: inherit;
}

.v2-sidebar-nav a:hover,
.v2-sidebar-nav-item:hover {
  background: var(--v2-hover);
  color: var(--v2-brand-2);
}

.v2-sidebar-nav a:hover svg,
.v2-sidebar-nav-item:hover svg {
  color: var(--v2-brand);
  stroke: var(--v2-brand);
}

.v2-sidebar-nav a.active,
.v2-sidebar-nav-item.active {
  color: var(--v2-brand-2);
  font-weight: 600;
}

.v2-sidebar-nav a.active svg,
.v2-sidebar-nav-item.active svg {
  color: var(--v2-brand);
  stroke: var(--v2-brand);
}

.v2-sidebar-active-bar {
  position: absolute;
  left: 0;
  top: 6px;
  bottom: 6px;
  width: 2.5px;
  background: var(--v2-brand);
  border-radius: 2px;
}

.v2-submenu {
  position: relative;
  margin-left: 17px;
  padding-left: 0;
  border-left: 1px solid var(--v2-line);
}

.v2-submenu a,
.v2-submenu .v2-sidebar-nav-item {
  padding-left: 18px !important;
}

.v2-sidebar-nav a svg,
.v2-sidebar-nav-item svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  color: var(--v2-ink-3);
  stroke: var(--v2-ink-3);
}

/* Exactly as tall as the page action bar (54px + 1px border, see
   .v2-action-bar-inner), so on every page that has one the two top borders
   meet on the same pixel row. The old 10px padding around the nav item's
   line box summed to 55.8px and left the bar's border ~1px lower. */
.v2-sidebar-footer {
  display: flex;
  align-items: center;
  height: 55px;
  padding: 0 8px;
  border-top: 1px solid var(--v2-line);
}

.v2-sidebar-footer .v2-sidebar-nav-item {
  flex: 1;
}

/* ── Sidebar collapsed state ────────────────── */

.v2-sidebar.v2-sidebar-collapsed {
  width: 56px;
}

.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-brand {
  justify-content: center;
  padding: 0;
}

.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-brand-link {
  display: none !important;
}

.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-brand-name,
.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-search,
.v2-sidebar.v2-sidebar-collapsed .v2-submenu-chevron,
.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-label {
  display: none;
}

.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-nav a,
.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-nav .v2-sidebar-nav-item {
  justify-content: center;
  padding: 8px 0;
}

.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-nav a svg,
.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-nav .v2-sidebar-nav-item svg {
  width: 18px;
  height: 18px;
}

.v2-sidebar.v2-sidebar-collapsed .v2-submenu {
  margin-left: 0;
  border-left: none;
}

.v2-sidebar.v2-sidebar-collapsed .v2-submenu a,
.v2-sidebar.v2-sidebar-collapsed .v2-submenu .v2-sidebar-nav-item {
  padding-left: 0 !important;
  justify-content: center;
  padding: 8px 0;
}

/* Submenu icons: hidden in expanded, shown in collapsed */
.v2-submenu-icon {
  display: none;
  width: 15px;
  height: 15px;
  flex-shrink: 0;
}

.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-nav a svg.v2-submenu-icon,
.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-nav .v2-sidebar-nav-item svg.v2-submenu-icon {
  display: block;
  width: 15px;
  height: 15px;
}

.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-footer a,
.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-footer .v2-sidebar-nav-item {
  justify-content: center;
  padding: 8px 0;
}

.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-footer a svg,
.v2-sidebar.v2-sidebar-collapsed .v2-sidebar-footer .v2-sidebar-nav-item svg {
  width: 18px;
  height: 18px;
}

.v2-sidebar-tooltip {
  position: fixed;
  left: 62px;
  padding: 5px 10px;
  background: var(--v2-ink);
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  border-radius: 6px;
  white-space: nowrap;
  pointer-events: none;
  z-index: 60;
  opacity: 0;
  transition: opacity 0.12s;
}

.v2-sidebar-tooltip.visible {
  opacity: 1;
}

/* ── Topbar ──────────────────────────────────── */

.v2-topbar {
  height: 52px;
  background: var(--v2-bg);
  border-bottom: 1px solid var(--v2-line);
  display: flex;
  align-items: center;
  padding: 0 18px;
  gap: 14px;
  flex-shrink: 0;
}

.v2-topbar-hamburger {
  width: 28px;
  height: 28px;
  border-radius: 7px;
  border: none;
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
  color: var(--v2-ink-3);
  flex-shrink: 0;
}

.v2-topbar-hamburger:hover {
  background: var(--v2-hover);
  color: var(--v2-ink);
}

@media (min-width: 1024px) {
  .v2-topbar-hamburger {
    display: none;
  }
}

.v2-topbar-breadcrumb {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--v2-ink-3);
}

.v2-topbar-breadcrumb a {
  color: var(--v2-ink-3);
  text-decoration: none;
}

.v2-topbar-breadcrumb a:hover {
  color: var(--v2-ink);
}

.v2-topbar-breadcrumb-current {
  color: var(--v2-ink);
  font-weight: 500;
}

.v2-topbar-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
}

.v2-topbar-icon-btn {
  width: 28px;
  height: 28px;
  border-radius: 7px;
  border: none;
  background: transparent;
  display: grid;
  place-items: center;
  cursor: pointer;
  color: var(--v2-ink-3);
  position: relative;
}

.v2-topbar-icon-btn:hover {
  color: var(--v2-ink);
}

.v2-topbar-notification-dot {
  position: absolute;
  top: 1px;
  right: 1px;
  width: 11px;
  height: 11px;
  background: var(--v2-brand);
  border-radius: 99px;
  border: 2px solid var(--v2-bg);
}

.v2-topbar-divider {
  width: 1px;
  height: 22px;
  background: var(--v2-line);
}

.v2-topbar-avatar {
  width: 30px;
  height: 30px;
  border-radius: 99px;
  background: var(--v2-brand);
  color: #fff;
  display: grid;
  place-items: center;
  font-weight: 600;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

/* ── Dialog / modal ─────────────────────────────── */

.v2-dialog-backdrop {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  justify-content: center;
  align-items: flex-start;
}

.v2-dialog-overlay {
  position: absolute;
  inset: 0;
  background: rgba(10, 14, 26, 0.45);
}

.v2-dialog-card {
  position: relative;
  background: var(--v2-bg);
  border: 1px solid var(--v2-line);
  border-radius: 12px;
  box-shadow: 0 24px 48px -16px rgba(10,14,26,0.24),
              0 4px 12px -4px rgba(10,14,26,0.08);
  display: flex;
  flex-direction: column;
  width: min(480px, calc(100% - 32px));
  max-height: calc(100vh - 100px);
}

.v2-dialog-card-md {
  width: min(600px, calc(100% - 32px));
}

/* Mobile fullscreen variant for dialogs that wrap workflows
   (status pickers, etc.). Applied via `.v2-dialog-card-fullscreen-mobile`. */
@media (max-width: 639px) {
  .v2-dialog-card.v2-dialog-card-fullscreen-mobile {
    width: 100%;
    height: 100vh;
    height: 100dvh;
    max-height: none;
    margin: 0 !important;
    border-radius: 0;
    border: none;
    box-shadow: none;
  }
  .v2-dialog-card-fullscreen-mobile-wrap .v2-dialog-backdrop {
    align-items: stretch;
    /* The backdrop carries an inline padding-top (60px) to hang the card below
       the top bar on desktop. Full screen on a phone the card is already
       100dvh, so that padding pushed its whole bottom edge — the footer with
       the primary action — below the fold of a backdrop that is position:fixed
       and cannot scroll: measured 904px of content in an 844px viewport, with
       "Segna come contattato" sitting at y=851 and unreachable by any means.
       !important because the padding is inline. */
    padding-top: 0 !important;
    padding-bottom: 0 !important;
  }
  .v2-dialog-card-fullscreen-mobile-wrap .v2-dialog-overlay {
    display: none;
  }

  /* Hide the "Stato attuale" / "Da X → Y" hint label on mobile — cleaner UI */
  .v2-dialog-card-fullscreen-mobile #v2-stato-footer-left,
  .v2-dialog-card-fullscreen-mobile #v2-status-footer-hint {
    display: none !important;
  }

  /* Full-width primary + secondary CTAs on mobile, stacked with primary on top */
  .v2-dialog-card-fullscreen-mobile .v2-btn {
    width: 100%;
    justify-content: center;
  }
  /* The `> form >` arm is for dialogs whose whole body is one form, so the
     footer is the form's last child rather than the card's. Without it those
     dialogs kept a horizontal footer while their buttons went full width, and
     lost the safe-area padding that keeps the CTA above the home indicator. */
  .v2-dialog-card-fullscreen-mobile > div:last-child,
  .v2-dialog-card-fullscreen-mobile > form:last-child > div:last-child {
    flex-direction: column-reverse !important;
    align-items: stretch !important;
    gap: 10px !important;
    padding: 16px 20px calc(16px + env(safe-area-inset-bottom, 0px)) !important;
  }
  /* Deliberately NOT extended to the form-wrapped dialogs: theirs group a
     split button (label + chevron) rather than a stack of CTAs, and stacking
     those two halves would break the control in half. They handle their own
     footer children below. */
  .v2-dialog-card-fullscreen-mobile > div:last-child > div:not([id]) {
    margin: 0 !important;
    display: flex !important;
    flex-direction: column-reverse !important;
    gap: 10px !important;
    width: 100%;
  }

  /* Split buttons (label + chevron) in a form-wrapped dialog's footer. The
     footer stacks its groups, so each group is full width — inside it the label
     takes the room and the chevron keeps the width it needs, instead of the
     two halves shrinking to an even 50/50. */
  .v2-dialog-card-fullscreen-mobile > form:last-child > div:last-child > div:not([id]) {
    width: 100%;
  }
  .v2-dialog-card-fullscreen-mobile > form:last-child > div:last-child > div:not([id]) > .v2-btn:first-child {
    flex: 1 1 auto;
  }
  .v2-dialog-card-fullscreen-mobile > form:last-child > div:last-child > div:not([id]) > .v2-btn + .v2-btn {
    flex: 0 0 auto;
    width: auto;
  }

  /* Same fullscreen-mobile treatment auto-applied to delete confirm dialogs
     so we don't need to tag the class onto every detail-v2 page. Scoped by
     id prefix; same column-reverse / full-width-CTA behavior. */
  #v2-delete-dialog .v2-dialog-backdrop,
  #v2-delete-modal .v2-dialog-backdrop,
  #v2-pay-dialog .v2-dialog-backdrop,
  #v2-pay-modal .v2-dialog-backdrop,
  #v2-schedule-dialog .v2-dialog-backdrop,
  #v2-delete-schedule-dialog .v2-dialog-backdrop {
    align-items: stretch;
  }
  #v2-delete-dialog .v2-dialog-overlay,
  #v2-delete-modal .v2-dialog-overlay,
  #v2-pay-dialog .v2-dialog-overlay,
  #v2-pay-modal .v2-dialog-overlay,
  #v2-schedule-dialog .v2-dialog-overlay,
  #v2-delete-schedule-dialog .v2-dialog-overlay {
    display: none;
  }
  #v2-delete-dialog .v2-dialog-card,
  #v2-delete-modal .v2-dialog-card,
  #v2-pay-dialog .v2-dialog-card,
  #v2-pay-modal .v2-dialog-card,
  #v2-schedule-dialog .v2-dialog-card,
  #v2-delete-schedule-dialog .v2-dialog-card {
    width: 100% !important;
    height: 100vh !important;
    height: 100dvh !important;
    max-height: none !important;
    margin: 0 !important;
    border-radius: 0 !important;
    border: none !important;
    box-shadow: none !important;
  }
  #v2-delete-dialog .v2-btn,
  #v2-delete-modal .v2-btn,
  #v2-pay-dialog .v2-btn,
  #v2-pay-modal .v2-btn,
  #v2-schedule-dialog .v2-btn,
  #v2-delete-schedule-dialog .v2-btn {
    width: 100%;
    justify-content: center;
  }
  #v2-delete-dialog .v2-dialog-card > div:last-child,
  #v2-delete-modal .v2-dialog-card > div:last-child,
  #v2-pay-dialog .v2-dialog-card > div:last-child,
  #v2-pay-modal .v2-dialog-card > div:last-child,
  #v2-schedule-dialog .v2-dialog-card > div:last-child,
  #v2-delete-schedule-dialog .v2-dialog-card > div:last-child {
    flex-direction: column-reverse !important;
    align-items: stretch !important;
    gap: 10px !important;
    padding: 16px 20px calc(16px + env(safe-area-inset-bottom, 0px)) !important;
  }
  #v2-delete-dialog .v2-dialog-card > div:last-child > div:not([id]),
  #v2-delete-modal .v2-dialog-card > div:last-child > div:not([id]),
  #v2-pay-dialog .v2-dialog-card > div:last-child > div:not([id]),
  #v2-pay-modal .v2-dialog-card > div:last-child > div:not([id]),
  #v2-schedule-dialog .v2-dialog-card > div:last-child > div:not([id]),
  #v2-delete-schedule-dialog .v2-dialog-card > div:last-child > div:not([id]) {
    margin: 0 !important;
    display: flex !important;
    flex-direction: column-reverse !important;
    gap: 10px !important;
    width: 100%;
  }

  /* Sticky footer: keep CTA row pinned to the bottom of the viewport when the
     content overflows, and push it to the bottom even when content is short.
     Card scrolls internally; footer rides the bottom edge as the user scrolls. */
  .v2-dialog-card-fullscreen-mobile,
  #v2-delete-dialog .v2-dialog-card,
  #v2-delete-modal .v2-dialog-card,
  #v2-pay-dialog .v2-dialog-card,
  #v2-pay-modal .v2-dialog-card,
  #v2-schedule-dialog .v2-dialog-card,
  #v2-delete-schedule-dialog .v2-dialog-card {
    overflow-y: auto !important;
    overflow-x: hidden !important;
    -webkit-overflow-scrolling: touch;
  }
  .v2-dialog-card-fullscreen-mobile > div:last-child,
  #v2-delete-dialog .v2-dialog-card > div:last-child,
  #v2-delete-modal .v2-dialog-card > div:last-child,
  #v2-pay-dialog .v2-dialog-card > div:last-child,
  #v2-pay-modal .v2-dialog-card > div:last-child,
  #v2-schedule-dialog .v2-dialog-card > div:last-child,
  #v2-delete-schedule-dialog .v2-dialog-card > div:last-child {
    position: sticky !important;
    bottom: 0;
    margin-top: auto !important;
    background: var(--v2-bg);
    border-top: 1px solid var(--v2-line);
    z-index: 1;
  }

  /* Document-upload dialogs — fullscreen-mobile treatment. Templates tag
     the backdrop element with `.v2-doc-upload`; one selector covers all
     entities (customer, vehicle, worksheet, checkin, expense, article,
     order, supplier, vehicle-sale, vehicle-stock). Desktop chrome lives
     in the `@media (min-width: 640px)` block below this one. */
  .v2-doc-upload {
    padding-top: 0;
    align-items: stretch;
  }
  .v2-doc-upload .v2-dialog-overlay { display: none; }
  .v2-doc-upload .v2-dialog-card {
    width: 100%;
    height: 100vh;
    height: 100dvh;
    max-height: none;
    margin: 0;
    border-radius: 0;
    border: none;
    box-shadow: none;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
  }
  .v2-doc-upload .v2-dialog-card > form {
    display: flex;
    flex-direction: column;
    min-height: 100%;
  }
  .v2-doc-upload .v2-btn {
    width: 100%;
    justify-content: center;
  }
  /* Footer (last child of the form): sticks to the bottom, full-width
     stacked CTAs with primary on top. */
  .v2-doc-upload .v2-dialog-card > form > div:last-child {
    display: flex;
    position: sticky;
    bottom: 0;
    margin-top: auto;
    background: var(--v2-bg);
    z-index: 1;
    flex-direction: column-reverse;
    align-items: stretch;
    gap: 10px;
    padding: 16px 20px calc(16px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--v2-line);
  }
}

/* Desktop chrome for document-upload dialogs — scoped to ≥640px so the
   mobile rules inside the (max-width:639px) block above win on phones
   without needing !important. (These styles used to live inline on each
   template's backdrop/card/footer; moved here so they can be overridden
   via natural cascade.) */
@media (min-width: 640px) {
  .v2-doc-upload { padding-top: 80px; }
  .v2-doc-upload .v2-dialog-card { margin-top: 80px; }
  .v2-doc-upload .v2-dialog-card > form > div:last-child {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    padding: 16px 24px;
    border-top: 1px solid var(--v2-line);
  }

  /* Order's row-modal desktop chrome — same migration: defaults that used
     to live as inline styles on the card/footer/button-wrapper, moved here
     so the mobile block can override via natural cascade. */
  .v2-line-item-modal .v2-dialog-card {
    margin-top: 40px;
    width: min(640px, calc(100% - 32px));
    overflow: hidden;
  }
  .v2-line-item-modal .v2-dialog-card > div:last-child {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 16px 24px;
    border-top: 1px solid var(--v2-line);
  }
  .v2-line-item-modal .v2-dialog-card > div:last-child > div {
    margin-left: auto;
    display: flex;
    gap: 8px;
  }
}

/* ── Tooltip / popover ───────────────────────── */

.v2-tooltip-trigger { position: relative; }
.v2-tooltip-trigger .v2-tooltip {
  position: absolute;
  z-index: 50;
  opacity: 0;
  visibility: hidden;
  transition: opacity .15s, visibility .15s;
  pointer-events: none;
}
.v2-tooltip-trigger:hover .v2-tooltip {
  opacity: 1;
  visibility: visible;
}

.v2-tooltip {
  background: var(--v2-ink);
  color: #fff;
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 12px;
  line-height: 1.4;
  box-shadow: 0 8px 24px rgba(10,14,26,0.2);
  white-space: nowrap;
  max-width: 320px;
}

.v2-tooltip-rich {
  padding: 14px 16px;
  border-radius: 10px;
  white-space: normal;
}

.v2-tooltip-bottom { top: 100%; margin-top: 6px; }
.v2-tooltip-top { bottom: 100%; margin-bottom: 6px; }
.v2-tooltip-left { right: 0; }

.v2-tooltip-kbd {
  padding: 2px 8px;
  background: rgba(255,255,255,0.12);
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 4px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
  .v2-tooltip-trigger .v2-tooltip { display: none; }
}

.v2-cursor-tooltip {
  position: fixed;
  z-index: 50;
  pointer-events: none;
  background: var(--v2-ink);
  color: #fff;
  font-size: 12px;
  line-height: 1.4;
  border-radius: 6px;
  padding: 5px 10px;
  box-shadow: 0 4px 12px rgba(10,14,26,0.15);
  max-width: 320px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: none;
}

/* ── Empty state ─────────────────────────────── */

.v2-empty-state {
  text-align: center;
  padding: 48px 24px;
  border: 1.5px dashed var(--v2-line-2);
  border-radius: var(--v2-r-lg);
  background: #fff;
}
.v2-empty-state svg.v2-empty-icon {
  width: 40px;
  height: 40px;
  color: var(--v2-ink-4);
  margin: 0 auto 12px;
}
.v2-empty-state h3 {
  font-size: 14px;
  font-weight: 600;
  color: var(--v2-ink);
  margin: 0 0 4px;
}
.v2-empty-state p {
  font-size: 13px;
  color: var(--v2-ink-3);
  margin: 0 0 20px;
}
.v2-empty-state .v2-btn {
  margin-top: 0;
}

/* ── Buttons ─────────────────────────────────── */

.v2-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 12px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  border-radius: var(--v2-r-md);
  cursor: pointer;
  border: 1px solid transparent;
  transition: background .12s, border-color .12s;
  text-decoration: none;
  white-space: nowrap;
}

.v2-btn svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

.v2-btn-primary {
  background: var(--v2-brand);
  color: #fff;
}

.v2-btn-primary:hover {
  background: var(--v2-brand-2);
}

.v2-btn-secondary {
  background: var(--v2-bg);
  color: var(--v2-ink);
  border-color: var(--v2-line-2);
}

.v2-btn-secondary:hover {
  background: var(--v2-surface-2);
}

.v2-btn-ghost {
  background: transparent;
  color: var(--v2-ink-2);
}

.v2-btn-ghost:hover {
  background: var(--v2-surface-2);
}

.v2-btn-danger {
  background: var(--v2-bg);
  color: #991b1b;
  border-color: var(--v2-line-2);
}

.v2-btn-danger:hover {
  background: var(--v2-hover);
}

/* Danger menu item — dropdown/flyout delete/logout actions */
.v2-menu-danger {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  font-size: 13px;
  color: #991b1b;
  background: transparent;
  border: none;
  border-radius: var(--v2-r-sm);
  cursor: pointer;
  text-align: left;
  font-family: inherit;
}

.v2-menu-danger:hover {
  background: var(--v2-hover);
}

/* Neutral dot-menu item — same layout as .v2-menu-danger but a non-destructive
   action (e.g. "Annulla scontrino"). Reserve red strictly for delete actions. */
.v2-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  font-size: 13px;
  color: var(--v2-ink-2);
  background: transparent;
  border: none;
  border-radius: var(--v2-r-sm);
  cursor: pointer;
  text-align: left;
  font-family: inherit;
}

.v2-menu-item:hover {
  background: var(--v2-hover);
}

/* Tertiary / link-style button – subtle inline action (e.g. "Vedi cliente →") */
.v2-btn-tertiary {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  margin: -4px -8px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--v2-ink-3);
  background: transparent;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.12s, color 0.12s;
}

.v2-btn-tertiary:hover {
  background: var(--v2-surface-2);
  color: var(--v2-ink);
}

.v2-btn-tertiary svg {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
}

.v2-btn:disabled,
.v2-btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Icon-only button variant */
.v2-btn-icon {
  padding: 9px;
}

/* Inline icon-only button (table rows, tight spaces) */
.v2-btn-icon-inline {
  padding: 4px;
  border-color: transparent;
  gap: 0;
}
.v2-btn-icon-inline:hover {
  border-color: transparent;
}

/* Action group: CTA + overflow icon button, matched heights */
.v2-action-group {
  display: inline-flex;
  align-items: stretch;
  gap: 8px;
}
.v2-action-group .v2-btn {
  align-self: stretch;
}

/* ── Input ───────────────────────────────────── */

.v2-input {
  width: 100%;
  padding: 7px 10px;
  font-family: inherit;
  font-size: 13px;
  background: var(--v2-bg);
  color: var(--v2-ink);
  border: 1px solid var(--v2-line-2);
  border-radius: var(--v2-r-md);
  transition: border-color .12s;
}

.v2-input::placeholder {
  color: var(--v2-ink-4);
}

.v2-input:focus {
  outline: none;
  border-color: var(--v2-ink);
}

/* ── Search bar ──────────────────────────────── */

.v2-search {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  background: var(--v2-bg);
  border: 1px solid var(--v2-line-2);
  border-radius: var(--v2-r-md);
  transition: border-color .12s;
}

.v2-search:focus-within {
  border-color: var(--v2-ink);
}

.v2-search svg {
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  color: var(--v2-ink-3);
  stroke: var(--v2-ink-3);
}

.v2-search input {
  flex: 1;
  width: 100%;
  border: none;
  outline: none;
  background: transparent;
  font-family: inherit;
  font-size: 13px;
  color: var(--v2-ink);
  padding: 0;
}

.v2-search input::placeholder {
  color: var(--v2-ink-4);
}

/* ── Filter button ───────────────────────────── */

.v2-filter-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--v2-bg);
  border: 1px solid var(--v2-line-2);
  border-radius: var(--v2-r-md);
  padding: 7px 12px;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--v2-ink);
  white-space: nowrap;
}

.v2-filter-btn:hover {
  background: var(--v2-surface-2);
}

.v2-filter-label {
  color: var(--v2-ink-3);
  font-weight: 400;
}

.v2-filter-caret {
  font-size: 10px;
  color: var(--v2-ink-4);
}

/* ── Toolbar ─────────────────────────────────── */

.v2-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 16px;
}

/* ── List surface (CalmListSurface) ──────────── */

.v2-list-surface {
  border: 1px solid var(--v2-line);
  border-radius: 10px;
  background: #fff;
  overflow: hidden;
}

.v2-list-surface-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px;
  background: var(--v2-surface-2);
  border-bottom: 1px solid var(--v2-line);
}

.v2-list-surface .v2-table {
  min-width: 0;
}

.v2-list-surface .v2-table-wrap {
  overflow-x: auto;
}

/* ── KPI strip ───────────────────────────────── */

.v2-kpi-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0;
  margin-bottom: 36px;
}

.v2-kpi-cell {
  padding: 4px 24px;
  border-right: 1px solid var(--v2-line);
}

.v2-kpi-cell:first-child {
  padding-left: 0;
}

.v2-kpi-cell:last-child {
  border-right: none;
}

.v2-kpi-label {
  font-size: 12px;
  color: var(--v2-ink-3);
  font-weight: 500;
  margin-bottom: 8px;
}

.v2-kpi-value {
  font-variant-numeric: tabular-nums;
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--v2-ink);
  line-height: 1.1;
  white-space: nowrap;
}

/* ── Table ───────────────────────────────────── */

.v2-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.v2-table {
  width: 100%;
  min-width: 800px;
  border-collapse: collapse;
}

/* Tables inside dialogs: fit the card instead of the page-list min-width. */
.v2-table.v2-table-fit {
  min-width: 0;
}

.v2-table th {
  text-align: left;
  padding: 12px 12px 10px;
  font-size: 11px;
  font-weight: 500;
  color: var(--v2-ink-3);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--v2-line);
  white-space: nowrap;
  user-select: none;
}

.v2-sort-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: transparent;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  font-size: 11px;
  font-weight: 500;
  color: var(--v2-ink-3);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  width: 100%;
}

.v2-sort-btn:hover {
  color: var(--v2-ink-2);
}

.v2-sort-btn.active {
  color: var(--v2-ink-2);
}

.v2-table th.text-right {
  text-align: right;
}

.v2-table td {
  padding: 14px 12px;
  font-size: 13px;
  color: var(--v2-ink);
  vertical-align: middle;
  border-bottom: 1px solid var(--v2-line);
}

.v2-table td.text-right {
  text-align: right;
}

.v2-table tbody tr:last-child td {
  border-bottom: none;
}

.v2-table tbody tr {
  cursor: pointer;
  transition: background .08s;
}

.v2-table tbody tr:hover {
  background: var(--v2-hover);
}

.v2-table tbody tr:hover .v2-row-title {
  color: var(--v2-brand-2) !important;
}

.v2-table tbody tr:hover .v2-row-icon {
  color: var(--v2-brand) !important;
  background: #fff !important;
}

.v2-table tbody tr:hover > td:last-child {
  color: var(--v2-brand) !important;
}

/* ── Supplier avatar (rounded-square + badge) ── */

.v2-row-icon-supplier {
  position: relative;
}

.v2-row-icon-supplier .v2-supplier-badge {
  position: absolute;
  bottom: -5px;
  right: -5px;
  width: 16px;
  height: 16px;
  display: grid;
  place-items: center;
  color: var(--v2-ink-3);
  transition: color .12s;
}

.v2-row-icon-supplier .v2-supplier-badge svg {
  width: 11px;
  height: 11px;
}

.v2-table tbody tr:hover .v2-supplier-badge {
  color: var(--v2-brand);
}

/* Static (non-clickable) variant — no hover, no pointer, no brand-color shifts */
.v2-table.v2-table-static tbody tr {
  cursor: default;
}

.v2-table.v2-table-static tbody tr:hover {
  background: transparent;
}

.v2-table.v2-table-static tbody tr:hover .v2-row-title,
.v2-table.v2-table-static tbody tr:hover > td:last-child {
  color: inherit !important;
}

.v2-table.v2-table-static tbody tr:hover .v2-row-icon {
  color: var(--v2-ink-3) !important;
  background: transparent !important;
}

.v2-table.v2-table-static tbody tr:hover .v2-supplier-badge {
  color: var(--v2-ink-3);
}

.v2-table tfoot td {
  padding: 14px 12px;
  font-size: 12.5px;
  border-top: 1px solid var(--v2-line);
  border-bottom: none;
}

/* Cell variants, so tables don't restyle <td> inline */
.v2-table td.v2-cell-muted {
  color: var(--v2-ink-3);
}

.v2-table td.v2-cell-chevron {
  text-align: right;
  color: var(--v2-ink-4);
  font-size: 18px;
}

.v2-table td.v2-cell-empty {
  text-align: center;
  color: var(--v2-ink-3);
}

/* ── Item table (create/edit line items) ──────── */

.v2-item-table-wrap {
  border: 1px solid var(--v2-line);
  border-radius: 10px;
  overflow: hidden;
  background: var(--v2-bg);
}

.v2-item-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

.v2-item-table th {
  padding: 10px 12px;
  font-size: 12px;
  font-weight: 500;
  color: var(--v2-ink-3);
  letter-spacing: 0.02em;
  text-align: left;
  background: var(--v2-surface-2);
  border-bottom: 1px solid var(--v2-line);
}

.v2-item-table th:first-child { padding-left: 16px; }
.v2-item-table th:last-child { padding-right: 16px; }
.v2-item-table th.text-right { text-align: right; }

.v2-item-table td {
  padding: 10px 12px;
  font-size: 13px;
  color: var(--v2-ink);
  vertical-align: middle;
  border-bottom: 1px solid var(--v2-line);
}

.v2-item-table td:first-child { padding-left: 16px; }
.v2-item-table td:last-child { padding-right: 16px; }
.v2-item-table td.text-right { text-align: right; }
.v2-item-table tbody tr:last-child td { border-bottom: none; }

.v2-item-table tfoot td {
  padding: 8px 12px;
  font-size: 13px;
  color: var(--v2-ink-3);
  background: var(--v2-surface-2);
  border-top: 1px solid var(--v2-line);
  border-bottom: none;
}

.v2-item-table tfoot td:first-child { padding-left: 16px; }
.v2-item-table tfoot td:last-child { padding-right: 16px; }
.v2-item-table tfoot td.text-right { text-align: right; }

.v2-item-table tfoot tr:last-child td {
  font-size: 14px;
  font-weight: 600;
  color: var(--v2-ink);
  padding-top: 10px;
  padding-bottom: 10px;
}

/* Cell variants for the line-item table. Kept as classes (not inline styles)
   so the mobile stacked-table rules can override without `!important`. */
.v2-item-cell-desc {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.v2-item-cell-num {
  text-align: right;
  color: var(--v2-ink-2);
  white-space: nowrap;
}
.v2-item-cell-amount {
  text-align: right;
  font-weight: 500;
  color: var(--v2-ink);
  white-space: nowrap;
}
.v2-item-cell-actions {
  padding: 6px 8px;
}
.v2-item-actions-row {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 2px;
}
.v2-item-form-row-inner {
  padding: 10px 16px;
  display: flex;
  justify-content: center;
}

/* Arrow-down menu of the composite "Aggiungi Riga" button. Fixed and placed by
   placeRowTypeMenu(): the item table's wrapper clips overflow. */
.v2-item-add-menu {
  position: fixed;
  z-index: 60;
  width: 220px;
  padding: 4px;
  background: var(--v2-bg);
  border: 1px solid var(--v2-line);
  border-radius: var(--v2-r-lg);
}

/* Note / separator rows in the line item editors. */
.v2-item-layout-body {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.v2-item-note-text {
  color: var(--v2-ink);
}
.v2-item-separator-rule {
  flex: 1;
  align-self: center;
  border-top: 1px dashed var(--v2-line-2);
}

/* ── Detail table (read-only line items in detail pages) ── */

.v2-detail-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.v2-detail-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

@media (max-width: 639px) {
  .v2-detail-table-wrap .v2-detail-table,
  .v2-detail-table-wrap > table {
    min-width: 560px;
  }
}

/* Worksheet "Categoria" row: on mobile, the select+plus group wraps
   to full width and the "Suggerisci" AI button moves to its own full-width row. */
@media (max-width: 639px) {
  .v2-tipo-intervento-main {
    flex-basis: 100% !important;
  }
  .v2-tipo-intervento-row > #ai-suggest-category-btn {
    flex-basis: 100%;
    width: 100%;
    justify-content: center;
  }
}

/* Worksheet "Descrizione" row: on mobile, the input takes full width and the
   "Suggerisci" AI button drops to its own full-width row below. */
@media (max-width: 639px) {
  .v2-descrizione-row > #title {
    flex-basis: 100%;
  }
  .v2-descrizione-row > #ai-suggest-title-btn {
    flex-basis: 100%;
    width: 100%;
    justify-content: center;
  }
}

.v2-detail-table th {
  padding: 12px 12px 10px;
  font-size: 11px;
  font-weight: 500;
  color: var(--v2-ink-3);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: left;
  border-bottom: 1px solid var(--v2-line);
  white-space: nowrap;
}

.v2-detail-table th.text-right { text-align: right; }

.v2-detail-table td {
  padding: 12px;
  font-size: 13px;
  color: var(--v2-ink);
  vertical-align: middle;
  border-bottom: 1px solid var(--v2-line);
}

.v2-detail-table td.text-right { text-align: right; }
/* Right-aligned cells in a document table are always numbers — keep digits aligned. */
.v2-detail-table td.text-right,
.v2-detail-table tfoot td.text-right { font-variant-numeric: tabular-nums; }
.v2-detail-table tbody tr:last-child td { border-bottom: none; }

/* Tables whose rows set their own inline border-bottom (so the plain rule above
   can't win): drop the last row's border so it doesn't double up with a bordered
   or rounded container. */
.v2-flush-rows tbody tr:last-child td { border-bottom: 0 !important; }

.v2-detail-table tfoot td {
  padding: 11px 12px;
  font-size: 13px;
  color: var(--v2-ink-3);
  border-top: 1px solid var(--v2-line-2);
}

.v2-detail-table tfoot td.text-right { text-align: right; }

.v2-detail-table tfoot tr:last-child td {
  padding-top: 16px;
  font-size: 15px;
  font-weight: 600;
  color: var(--v2-ink);
}

/* ── Settings grid ────────────────────────────── */

.v2-settings-item {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--v2-line);
  cursor: pointer;
  transition: background .12s;
}

.v2-settings-item > div:first-child {
  transition: color .12s, background .12s;
}

.v2-settings-item > svg {
  transition: transform .12s, color .12s;
}

.v2-settings-item:hover {
  background: var(--v2-hover);
}

.v2-settings-item:hover > div:first-child {
  color: var(--v2-brand) !important;
  background: #fff !important;
}

.v2-settings-item:hover > div:nth-child(2) > div:first-child {
  color: var(--v2-brand-2) !important;
}

.v2-settings-item:hover > svg {
  color: var(--v2-brand) !important;
  transform: translateX(2px);
}

.v2-settings-item:nth-child(odd) {
  border-right: 1px solid var(--v2-line);
}

.v2-settings-group[hidden] {
  display: none;
}

.v2-settings-item[hidden] {
  display: none;
}

/* ── Appointment indicator ────────────────────── */

.v2-appt {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  vertical-align: baseline;
  color: var(--v2-ink-3);
}

.v2-appt svg {
  flex-shrink: 0;
  transform: translateY(0.5px);
}

.v2-appt-soon {
  color: var(--v2-warn);
}

.v2-appt-today {
  color: var(--v2-brand);
}

/* ── SDI label (invoice table, mirrors v2-appt) ── */

.v2-sdi {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  margin-top: 2px;
}

.v2-sdi .v2-status-dot { flex-shrink: 0; }

.v2-sdi-sent { color: var(--v2-good); }
.v2-sdi-sent .v2-status-dot { background: var(--v2-good); }

.v2-sdi-pending { color: var(--v2-warn); }
.v2-sdi-pending .v2-status-dot { background: var(--v2-warn); }

.v2-sdi-warning { color: var(--v2-danger); }
.v2-sdi-warning .v2-status-dot { background: var(--v2-danger); }

.v2-sdi-rejected { color: var(--v2-danger); }
.v2-sdi-rejected .v2-status-dot { background: var(--v2-danger); }

/* Invoice reversed by a credit note ("stornata con nota di credito") — orange, replaces the SDI pill */
.v2-sdi-stornata { color: var(--v2-warn); }
.v2-sdi-stornata .v2-status-dot { background: var(--v2-warn); }

/* Neutral / non-fiscal — e.g. scontrino "Non fiscale" (issued, never transmitted) */
.v2-sdi-neutral { color: var(--v2-ink-3); }
.v2-sdi-neutral .v2-status-dot { background: var(--v2-ink-3); }

/* ── Status ──────────────────────────────────── */

.v2-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  font-weight: 500;
}

.v2-status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  display: inline-block;
}

.v2-status-bozza, .v2-status-draft { color: var(--v2-warn); }
.v2-status-bozza .v2-status-dot, .v2-status-draft .v2-status-dot { background: var(--v2-warn); }

.v2-status-lavorazione, .v2-status-started { color: var(--v2-brand); }
.v2-status-lavorazione .v2-status-dot, .v2-status-started .v2-status-dot { background: var(--v2-brand); }

.v2-status-completata, .v2-status-completed { color: var(--v2-good); }
.v2-status-completata .v2-status-dot, .v2-status-completed .v2-status-dot { background: var(--v2-good); }

.v2-status-waiting { color: #a16207; }
.v2-status-waiting .v2-status-dot { background: #a16207; }

.v2-status-delivered { color: var(--v2-ink-3); }
.v2-status-delivered .v2-status-dot { background: var(--v2-ink-3); }

.v2-status-accepted { color: var(--v2-good); }
.v2-status-accepted .v2-status-dot { background: var(--v2-good); }

.v2-status-rejected { color: var(--v2-danger); }
.v2-status-rejected .v2-status-dot { background: var(--v2-danger); }

.v2-status-annullata, .v2-status-archived { color: var(--v2-ink-4); }
.v2-status-annullata .v2-status-dot, .v2-status-archived .v2-status-dot { background: var(--v2-ink-4); }

/* Channel variants */
.v2-status-email { color: var(--v2-brand); }
.v2-status-email .v2-status-dot { background: var(--v2-brand); }

.v2-status-sms { color: var(--v2-good); }
.v2-status-sms .v2-status-dot { background: var(--v2-good); }

.v2-status-whatsapp { color: #16a34a; }
.v2-status-whatsapp .v2-status-dot { background: #16a34a; }

/* Entity type variants */
.v2-status-worksheet { color: var(--v2-brand); }
.v2-status-worksheet .v2-status-dot { background: var(--v2-brand); }

.v2-status-quote { color: var(--v2-warn); }
.v2-status-quote .v2-status-dot { background: var(--v2-warn); }

.v2-status-invoice { color: var(--v2-good); }
.v2-status-invoice .v2-status-dot { background: var(--v2-good); }

.v2-status-calendar, .v2-status-appointment { color: #7c3aed; }
.v2-status-calendar .v2-status-dot, .v2-status-appointment .v2-status-dot { background: #7c3aed; }

.v2-status-inspection { color: var(--v2-danger); }
.v2-status-inspection .v2-status-dot { background: var(--v2-danger); }

.v2-status-generic { color: var(--v2-ink-3); }
.v2-status-generic .v2-status-dot { background: var(--v2-ink-3); }

.v2-status-default { color: var(--v2-brand); }
.v2-status-default .v2-status-dot { background: var(--v2-brand); }

/* Stock status variants (inventory) */
.v2-status-outofstock { color: var(--v2-danger); }
.v2-status-outofstock .v2-status-dot { background: var(--v2-danger); }

.v2-status-lowstock { color: var(--v2-warn); }
.v2-status-lowstock .v2-status-dot { background: var(--v2-warn); }

/* Tyreset status variants */
.v2-status-deposited { color: var(--v2-good); }
.v2-status-deposited .v2-status-dot { background: var(--v2-good); }

.v2-status-mounted { color: var(--v2-brand); }
.v2-status-mounted .v2-status-dot { background: var(--v2-brand); }

.v2-status-collected { color: var(--v2-ink-3); }
.v2-status-collected .v2-status-dot { background: var(--v2-ink-3); }

.v2-status-disposed { color: var(--v2-warn); }
.v2-status-disposed .v2-status-dot { background: var(--v2-warn); }

/* Season type variants (tyre storage) */
.v2-status-winter { color: #0369a1; }
.v2-status-winter .v2-status-dot { background: #0369a1; }

.v2-status-summer { color: #b45309; }
.v2-status-summer .v2-status-dot { background: #b45309; }

.v2-status-allseason { color: #15803d; }
.v2-status-allseason .v2-status-dot { background: #15803d; }

/* ── Amount ──────────────────────────────────── */

.v2-amount {
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
}

.v2-amount-strong {
  font-weight: 600;
}

.v2-amount-zero {
  color: var(--v2-good);
}

/* ── Pagination ──────────────────────────────── */

.v2-pagination {
  display: flex;
  align-items: center;
  gap: 12px;
}

.v2-pagination-info {
  font-size: 12.5px;
  color: var(--v2-ink-3);
}

.v2-pagination-buttons {
  margin-left: auto;
  display: flex;
  gap: 8px;
}

.v2-pager-btn {
  padding: 6px 12px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 500;
  background: #fff;
  color: var(--v2-ink);
  border: 1px solid var(--v2-line-2);
  border-radius: 6px;
  cursor: pointer;
  transition: background .12s;
}

.v2-pager-btn:hover:not(:disabled) {
  background: var(--v2-surface-2);
}

.v2-pager-btn:disabled {
  color: var(--v2-ink-4);
  border-color: var(--v2-line);
  opacity: 0.6;
  cursor: default;
}

/* ── Page header ─────────────────────────────── */

.v2-page-header {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  margin-bottom: 28px;
}

.v2-page-header-content {
  flex: 1;
  min-width: 0;
}

.v2-page-header-subtitle {
  margin: 6px 0 0;
  font-size: 13.5px;
  color: var(--v2-ink-3);
  line-height: 1.55;
}

.v2-page-header-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

/* ── Data row ────────────────────────────────── */

.v2-data-row {
  display: grid;
  grid-template-columns: 200px 1fr;
  align-items: baseline;
  gap: 16px;
  padding: 10px 0;
  border-top: 1px solid var(--v2-line);
}

.v2-data-row-label {
  font-size: 12.5px;
  color: var(--v2-ink-3);
  font-weight: 400;
}

.v2-data-row-value {
  font-size: 13.5px;
  color: var(--v2-ink);
}

.v2-data-row-empty {
  color: var(--v2-ink-4);
}

/* ── Section ─────────────────────────────────── */

.v2-section {
  padding-top: 32px;
}

.v2-section-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  min-height: 24px;
}

.v2-section-count {
  font-size: 11px;
  color: var(--v2-ink-4);
  font-weight: 500;
  letter-spacing: 0.02em;
}

.v2-section-link {
  margin-left: auto;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  font-size: 12.5px;
  color: var(--v2-ink-3);
  font-family: inherit;
  text-decoration: none;
}

.v2-section-link:hover {
  color: var(--v2-ink);
}

/* ── Tabs ────────────────────────────────────── */

.v2-tabs {
  display: flex;
  gap: 24px;
  border-bottom: 1px solid var(--v2-line);
}

.v2-tab {
  background: transparent;
  border: none;
  padding: 12px 0;
  margin-bottom: -1px;
  cursor: pointer;
  font-size: 13.5px;
  font-family: inherit;
  font-weight: 500;
  color: var(--v2-ink-3);
  border-bottom: 2px solid transparent;
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  text-decoration: none;
  white-space: nowrap;
}

.v2-tab:hover {
  color: var(--v2-ink-2);
}

.v2-tab.active {
  font-weight: 600;
  color: var(--v2-ink);
  border-bottom-color: var(--v2-brand);
}

.v2-tab-count {
  font-size: 12px;
  color: var(--v2-ink-4);
  font-weight: 400;
}

/* ── Two-column layout for detail pages ──────── */

.v2-two-col {
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 64px;
}

.v2-report-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
  padding-top: 40px;
}

/* Grid tracks default to min-width:auto, so a 1fr column refuses to shrink below
   the longest row's min-content (an unwrappable nowrap title), letting a widget
   with a very long invoice/worksheet/article title overflow its 50% column. Allow
   the tracks to shrink so the rows' own ellipsis truncation can kick in. */
.v2-report-row > div {
  min-width: 0;
}

@media (max-width: 639px) {
  .v2-report-row {
    grid-template-columns: 1fr;
    gap: 24px;
  }

  /* Customer + vehicle row on detail pages — stack on mobile.
     !important needed because the host markup sets grid-template-columns via inline style. */
  .v2-cv-row {
    grid-template-columns: 1fr !important;
    gap: 24px !important;
  }

  /* Create/edit form grids — collapse any multi-column grid to a single column on mobile.
     Targets inline-styled grids inside form containers; !important beats inline grid-template-columns. */
  .v2-container-form [style*="grid-template-columns:1fr 1fr"],
  .v2-container-form [style*="grid-template-columns: 1fr 1fr"],
  .v2-container-form [style*="grid-template-columns:repeat(2"],
  .v2-container-form [style*="grid-template-columns: repeat(2"],
  .v2-container-form [style*="grid-template-columns:360px"],
  .v2-container-form [style*="grid-template-columns: 360px"] {
    grid-template-columns: 1fr !important;
  }

  /* Native date/time inputs carry an intrinsic min-content width on mobile
     (iOS/Android) that ignores width:100% and overflows narrow grid cells —
     e.g. "Data documento" / "Data scadenza pagamento" on the expense forms.
     Reset the platform appearance so they shrink to their container. */
  input[type="date"].v2-form-input,
  input[type="time"].v2-form-input,
  input[type="datetime-local"].v2-form-input {
    -webkit-appearance: none;
    appearance: none;
    min-width: 0;
    max-width: 100%;
  }
  input[type="date"].v2-form-input::-webkit-date-and-time-value {
    text-align: left;
    min-width: 0;
  }

  /* Detail-view info grids — same collapse for the inline 1fr 1fr info layouts
     used on supplier/article/calendar/service-catalog/electronic-credit-note. */
  .v2-container [style*="grid-template-columns:1fr 1fr"],
  .v2-container [style*="grid-template-columns: 1fr 1fr"] {
    grid-template-columns: 1fr !important;
  }

  /* Settings landing — stack the item cards single-column on mobile */
  .v2-container-medium [style*="grid-template-columns:repeat(2, 1fr)"],
  .v2-container-medium [style*="grid-template-columns: repeat(2, 1fr)"] {
    grid-template-columns: 1fr !important;
  }
}

/* ── Vehicle line ────────────────────────────── */

.v2-vehicle-line {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 8px;
  border-top: 1px solid var(--v2-line);
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  transition: background .08s;
}

.v2-vehicle-line:last-child {
  border-bottom: 1px solid var(--v2-line);
}

.v2-vehicle-line:hover {
  background: var(--v2-hover);
}
.v2-vehicle-line:hover > span:first-child,
.v2-vehicle-line:hover > div:first-child > div:first-child {
  color: var(--v2-brand-2) !important;
}
.v2-vehicle-line:hover .v2-vehicle-line-chevron {
  color: var(--v2-brand) !important;
}

.v2-vehicle-line-chevron {
  color: var(--v2-ink-4);
  flex-shrink: 0;
  margin-left: auto;
}

/* ── Topbar mobile/desktop avatar toggle ─────── */

/* Mobile avatar: show only below lg */
@media (max-width: 1023px) {
  .v2-topbar-mobile-avatar {
    display: flex !important;
  }
}

/* ── Accordion ───────────────────────────────── */

.v2-accordion {
  background: var(--v2-bg);
  border: 1px solid var(--v2-line);
  border-radius: var(--v2-r-lg);
  overflow: hidden;
}

.v2-accordion-header {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 14px 18px;
  border: none;
  background: transparent;
  cursor: pointer;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--v2-ink);
  text-align: left;
  transition: background 0.08s;
}

.v2-accordion-header:hover {
  background: var(--v2-hover);
}

.v2-accordion-body {
  border-top: 1px solid var(--v2-line);
}

/* ── Spinner ─────────────────────────────────── */

.v2-spinner {
  width: 24px;
  height: 24px;
  border: 3px solid var(--v2-line);
  border-top-color: var(--v2-brand);
  border-radius: 50%;
  animation: v2spin 0.6s linear infinite;
}

@keyframes v2spin {
  to { transform: rotate(360deg); }
}

/* ── Responsive ──────────────────────────────── */

@media (max-width: 1023px) {
  .v2-sidebar {
    display: none;
  }

  .v2-topbar-breadcrumb {
    display: none;
  }

  .v2-topbar-icon-btn {
    display: none;
  }

  .v2-topbar-divider {
    display: none;
  }

  .v2-container,
  .v2-container-medium,
  .v2-container-form {
    padding: 24px 16px 48px;
  }

  .v2-two-col {
    grid-template-columns: 1fr;
    gap: 0;
  }

  .v2-kpi-strip {
    gap: 32px;
  }

  .v2-page-header {
    flex-direction: column;
    gap: 16px;
  }

  .v2-toolbar {
    flex-wrap: wrap;
  }

  /* Bigger touch targets for mobile nav items */
  .v2-sidebar-nav a,
  .v2-sidebar-nav-item {
    padding: 10px 12px;
    font-size: 14px;
    gap: 12px;
  }

  .v2-sidebar-nav a svg,
  .v2-sidebar-nav-item svg {
    width: 18px;
    height: 18px;
  }
}

/* Mobile-only selects that replace UI patterns built for desktop:
   - `.v2-tabs-mobile`   → replaces `.v2-tabs` tab bar    (v2-mobile-tabs.js)
   - `.v2-kebab-mobile`  → replaces the `...` overflow kebab + flyout
                           (v2-mobile-kebab.js)
   - `.v2-export-mobile` → replaces the "Esporta" CSV/Excel flyout in list
                           toolbars (v2-mobile-export.js)
   All hidden on desktop; the original markup stays so JS can read it. */
.v2-tabs-mobile,
.v2-kebab-mobile,
.v2-export-mobile { display: none; }

@media (max-width: 639px) {
  .v2-tabs { display: none !important; }

  /* Hide the desktop kebab button on mobile; the script inserts a native
     <select> next to it that opens the same actions. */
  .v2-page-header-actions .v2-btn-icon[onclick*="classList.toggle"] {
    display: none !important;
  }

  /* Hide the desktop Esporta trigger once the export <select> has been
     inserted (data-attribute set by v2-mobile-export.js). */
  .v2-list-surface-toolbar > div:has(> button[data-mobile-export-init]) > button[data-mobile-export-init] {
    display: none;
  }

  .v2-tabs-mobile,
  .v2-kebab-mobile,
  .v2-export-mobile {
    display: block;
    width: 100%;
    padding: 9px 36px 9px 12px;
    font-family: inherit;
    font-size: 13.5px;
    font-weight: 500;
    color: var(--v2-ink);
    background-color: var(--v2-bg);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%231f2937' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'></polyline></svg>");
    background-repeat: no-repeat;
    background-position: right 10px center;
    border: 1px solid var(--v2-line-2);
    border-radius: var(--v2-r-md);
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    cursor: pointer;
    transition: border-color .12s, box-shadow .12s;
  }
  .v2-tabs-mobile { margin-top: 20px; margin-bottom: 16px; }
  .v2-kebab-mobile {
    text-align: center;
    text-align-last: center;
    padding-left: 36px;
  }
  .v2-tabs-mobile:focus,
  .v2-kebab-mobile:focus,
  .v2-export-mobile:focus {
    outline: none;
    border-color: var(--v2-brand);
    box-shadow: 0 0 0 3px rgba(37,99,235,0.1);
  }

  /* Page header — full-width action buttons, stacked vertically */
  .v2-page-header-actions {
    width: 100%;
    flex-direction: column;
    align-items: stretch;
  }

  .v2-page-header-actions .v2-btn {
    width: 100%;
    justify-content: center;
  }

  /* Overflow kebab (`...`) in detail-view headers: stretch to full width on
     its own row, matching the other header buttons. Overrides inline
     `width:34px; height:34px;` set for desktop sizing. Scoped to
     `.v2-page-header-actions` so kebab-shaped buttons inside body tables
     (document rows, etc.) keep their compact size. */
  .v2-page-header-actions .v2-btn-icon {
    width: 100% !important;
    height: auto !important;
  }

  /* Unwrap any `.v2-action-group` (CTA + kebab pair) so its children stack
     individually instead of staying inline-flex on the same row. */
  .v2-page-header-actions .v2-action-group {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    gap: 6px;
  }
  .v2-page-header-actions .v2-action-group > div {
    width: 100%;
  }

  /* List toolbar — every control stacks full-width on its own row */
  .v2-list-surface-toolbar {
    flex-direction: column;
    align-items: stretch;
  }

  .v2-list-surface-toolbar > * {
    width: 100%;
    flex: none;
  }

  .v2-list-surface-toolbar .v2-search {
    width: 100%;
  }

  /* Triggers inside toolbar wrappers (filter, export dropdown) — full-width too */
  .v2-list-surface-toolbar .v2-btn,
  .v2-list-surface-toolbar .v2-filter-btn,
  .v2-list-surface-toolbar select {
    width: 100%;
    justify-content: center;
  }

  /* Lists — let tables overflow horizontally so all columns stay reachable */
  .v2-list-surface {
    overflow: visible;
  }

  /* Settings list pages share an inline-styled page-header pattern
     (`<div style="display:flex; align-items:flex-start; gap:16px; margin-bottom:28px;">`)
     wrapping title + a single primary CTA on the right. On mobile, stack the
     CTA below the title at full width — same shape as `.v2-page-header`. */
  [style*="display:flex; align-items:flex-start; gap:16px; margin-bottom:28px"] {
    flex-direction: column;
  }
  [style*="display:flex; align-items:flex-start; gap:16px; margin-bottom:28px"] > .v2-btn {
    width: 100%;
    justify-content: center;
  }

  /* Settings → Abbonamento billing strip: stack the 3 columns (Il tuo piano /
     Crediti / Utilizzo) so they no longer overflow on narrow screens. Swap
     the inline border-right column dividers for border-bottom row dividers. */
  .v2-billing-strip {
    grid-template-columns: 1fr !important;
  }
  .v2-billing-strip > div {
    padding: 20px !important;
    border-right: none !important;
    border-bottom: 1px solid var(--v2-line);
  }
  .v2-billing-strip > div:last-child {
    border-bottom: none;
  }

  /* Plan picker rows: stack info + price/CTA column, full-width "Passa a …"
     button, single-column feature list. */
  .v2-plan-row {
    grid-template-columns: 1fr !important;
    gap: 16px !important;
    padding: 18px !important;
  }
  .v2-plan-row > div:last-child {
    align-items: stretch !important;
    min-width: 0 !important;
    flex-direction: column;
    gap: 12px;
  }
  .v2-plan-row > div:last-child > div:first-child {
    text-align: left !important;
  }
  .v2-plan-row .v2-plan-btn,
  .v2-plan-row .v2-btn {
    width: 100%;
    justify-content: center;
  }
  .v2-plan-row ul {
    grid-template-columns: 1fr !important;
  }

  /* Settings → Abbonamento modals (Cambia piano / Acquista crediti) follow
     the same fullscreen-mobile pattern as the delete confirm dialogs. The
     outer `#<id>` element IS the backdrop on these two modals (no wrap div),
     so the selector targets the id directly instead of `… .v2-dialog-backdrop`. */
  #plan-change-modal,
  #credits-purchase-modal {
    align-items: stretch !important;
    padding-top: 0 !important;
  }
  #plan-change-modal .v2-dialog-overlay,
  #credits-purchase-modal .v2-dialog-overlay {
    display: none;
  }
  #plan-change-modal .v2-dialog-card,
  #credits-purchase-modal .v2-dialog-card {
    width: 100% !important;
    height: 100vh !important;
    height: 100dvh !important;
    max-height: none !important;
    margin: 0 !important;
    border-radius: 0 !important;
    border: none !important;
    box-shadow: none !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    -webkit-overflow-scrolling: touch;
  }
  #plan-change-modal .v2-btn,
  #credits-purchase-modal .v2-btn {
    width: 100%;
    justify-content: center;
  }
  #plan-change-modal .v2-dialog-card > div:last-child,
  #credits-purchase-modal .v2-dialog-card > div:last-child {
    position: sticky !important;
    bottom: 0;
    margin-top: auto !important;
    background: var(--v2-bg);
    border-top: 1px solid var(--v2-line);
    z-index: 1;
    flex-direction: column-reverse !important;
    align-items: stretch !important;
    gap: 10px !important;
    padding: 16px 20px calc(16px + env(safe-area-inset-bottom, 0px)) !important;
  }
  #plan-change-modal .v2-dialog-card > div:last-child > div:not([id]),
  #credits-purchase-modal .v2-dialog-card > div:last-child > div:not([id]) {
    margin: 0 !important;
    display: flex !important;
    flex-direction: column-reverse !important;
    gap: 10px !important;
    width: 100%;
  }

  /* Line-items table on worksheet/quote/checkin/invoice create+edit pages —
     7 columns can't fit a phone width. Let the wrap scroll horizontally and
     give the table a sane min-width so each column keeps its content. */
  .v2-item-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .v2-item-table,
  .v2-item-table-wrap > table {
    min-width: 720px;
  }

  /* Line-item dialog (`#row-modal`) used by worksheet/quote/checkin/invoice
     create+edit + expense + no-prices variants. Root is the backdrop.
     (Order create/edit uses a different shell — see `.v2-line-item-modal`
     below this media block.) */
  #row-modal {
    align-items: stretch !important;
    padding-top: 0 !important;
  }
  #row-modal .v2-dialog-overlay { display: none; }
  #row-modal .v2-dialog-card {
    width: 100% !important;
    height: 100vh !important;
    height: 100dvh !important;
    max-height: none !important;
    margin: 0 !important;
    border-radius: 0 !important;
    border: none !important;
    box-shadow: none !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    -webkit-overflow-scrolling: touch;
  }
  #row-modal .v2-btn {
    width: 100%;
    justify-content: center;
  }
  #row-modal .v2-dialog-card > div:last-child {
    position: sticky !important;
    bottom: 0;
    margin-top: auto !important;
    background: var(--v2-bg);
    border-top: 1px solid var(--v2-line);
    z-index: 1;
    flex-direction: column-reverse !important;
    align-items: stretch !important;
    justify-content: stretch !important;
    gap: 10px !important;
    padding: 16px 20px calc(16px + env(safe-area-inset-bottom, 0px)) !important;
  }

  /* Order create/edit row-modal — uses the `class="hidden"` wrapper shape
     (id on the wrapper, backdrop nested inside) and wraps the footer
     buttons in an inner `margin-left:auto` div. Templates tag the
     backdrop with `.v2-line-item-modal` so a single class drives all
     desktop + mobile chrome — no !important needed, since the source
     templates carry no conflicting inline styles for these properties. */
  .v2-line-item-modal {
    padding-top: 0;
    align-items: stretch;
  }
  .v2-line-item-modal .v2-dialog-overlay { display: none; }
  .v2-line-item-modal .v2-dialog-card {
    width: 100%;
    height: 100vh;
    height: 100dvh;
    max-height: none;
    margin: 0;
    border-radius: 0;
    border: none;
    box-shadow: none;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
  }
  .v2-line-item-modal .v2-btn {
    width: 100%;
    justify-content: center;
  }
  .v2-line-item-modal .v2-dialog-card > div:last-child {
    position: sticky;
    bottom: 0;
    margin-top: auto;
    background: var(--v2-bg);
    z-index: 1;
    display: flex;
    flex-direction: column-reverse;
    align-items: stretch;
    gap: 10px;
    padding: 16px 20px calc(16px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--v2-line);
  }
  /* Inner button wrapper (`<div style="margin-left:auto;display:flex;...">`
     in the static template) — stretch to full width and stack
     column-reverse so the primary CTA lands on top. */
  .v2-line-item-modal .v2-dialog-card > div:last-child > div {
    margin: 0;
    display: flex;
    flex-direction: column-reverse;
    gap: 10px;
    width: 100%;
  }

  /* Unsaved-changes guard + simple settings dialogs (Aggiungi/Modifica
     calendario, etc.) + comm dialogs (email/SMS/WhatsApp on worksheet,
     quote, invoice, calendar, customer) — all use the backdrop-as-root
     pattern with a footer as the last child of the card. */
  #unsaved-changes-modal,
  #add-dialog,
  #edit-dialog,
  #forward-email-modal,
  #sms-modal,
  #worksheet-whatsapp-modal,
  #quote-whatsapp-modal,
  #invoice-whatsapp-modal,
  #calendar-email-modal,
  #calendar-sms-modal,
  #calendar-whatsapp-modal,
  #customer-email-modal,
  #customer-sms-modal,
  #customer-whatsapp-modal {
    align-items: stretch !important;
    padding-top: 0 !important;
  }
  #unsaved-changes-modal .v2-dialog-overlay,
  #add-dialog .v2-dialog-overlay,
  #edit-dialog .v2-dialog-overlay,
  #forward-email-modal .v2-dialog-overlay,
  #sms-modal .v2-dialog-overlay,
  #worksheet-whatsapp-modal .v2-dialog-overlay,
  #quote-whatsapp-modal .v2-dialog-overlay,
  #invoice-whatsapp-modal .v2-dialog-overlay,
  #calendar-email-modal .v2-dialog-overlay,
  #calendar-sms-modal .v2-dialog-overlay,
  #calendar-whatsapp-modal .v2-dialog-overlay,
  #customer-email-modal .v2-dialog-overlay,
  #customer-sms-modal .v2-dialog-overlay,
  #customer-whatsapp-modal .v2-dialog-overlay { display: none; }
  #unsaved-changes-modal .v2-dialog-card,
  #add-dialog .v2-dialog-card,
  #edit-dialog .v2-dialog-card,
  #forward-email-modal .v2-dialog-card,
  #sms-modal .v2-dialog-card,
  #worksheet-whatsapp-modal .v2-dialog-card,
  #quote-whatsapp-modal .v2-dialog-card,
  #invoice-whatsapp-modal .v2-dialog-card,
  #calendar-email-modal .v2-dialog-card,
  #calendar-sms-modal .v2-dialog-card,
  #calendar-whatsapp-modal .v2-dialog-card,
  #customer-email-modal .v2-dialog-card,
  #customer-sms-modal .v2-dialog-card,
  #customer-whatsapp-modal .v2-dialog-card {
    width: 100% !important;
    height: 100vh !important;
    height: 100dvh !important;
    max-height: none !important;
    margin: 0 !important;
    border-radius: 0 !important;
    border: none !important;
    box-shadow: none !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    -webkit-overflow-scrolling: touch;
  }
  #unsaved-changes-modal .v2-btn,
  #add-dialog .v2-btn,
  #edit-dialog .v2-btn,
  #forward-email-modal .v2-btn,
  #sms-modal .v2-btn,
  #worksheet-whatsapp-modal .v2-btn,
  #quote-whatsapp-modal .v2-btn,
  #invoice-whatsapp-modal .v2-btn,
  #calendar-email-modal .v2-btn,
  #calendar-sms-modal .v2-btn,
  #calendar-whatsapp-modal .v2-btn,
  #customer-email-modal .v2-btn,
  #customer-sms-modal .v2-btn,
  #customer-whatsapp-modal .v2-btn {
    width: 100%;
    justify-content: center;
  }
  #unsaved-changes-modal .v2-dialog-card > div:last-child,
  #add-dialog .v2-dialog-card > div:last-child,
  #edit-dialog .v2-dialog-card > div:last-child,
  #forward-email-modal .v2-dialog-card > div:last-child,
  #sms-modal .v2-dialog-card > div:last-child,
  #worksheet-whatsapp-modal .v2-dialog-card > div:last-child,
  #quote-whatsapp-modal .v2-dialog-card > div:last-child,
  #invoice-whatsapp-modal .v2-dialog-card > div:last-child,
  #calendar-email-modal .v2-dialog-card > div:last-child,
  #calendar-sms-modal .v2-dialog-card > div:last-child,
  #calendar-whatsapp-modal .v2-dialog-card > div:last-child,
  #customer-email-modal .v2-dialog-card > div:last-child,
  #customer-sms-modal .v2-dialog-card > div:last-child,
  #customer-whatsapp-modal .v2-dialog-card > div:last-child {
    position: sticky !important;
    bottom: 0;
    margin-top: auto !important;
    background: var(--v2-bg);
    border-top: 1px solid var(--v2-line);
    z-index: 1;
    flex-direction: column-reverse !important;
    align-items: stretch !important;
    justify-content: stretch !important;
    gap: 10px !important;
    padding: 16px 20px calc(16px + env(safe-area-inset-bottom, 0px)) !important;
  }

  /* Date filter dialog (`#v2-date-filter-popover`) — same fullscreen-mobile
     treatment. Its root is the backdrop itself (like the billing modals).
     Note: the footer is `> div:last-of-type` rather than `:last-child` because
     three hidden <input>s sit after the footer inside the card. */
  #v2-date-filter-popover {
    align-items: stretch !important;
    padding-top: 0 !important;
  }
  #v2-date-filter-popover .v2-dialog-overlay { display: none; }
  #v2-date-filter-popover .v2-dialog-card {
    width: 100% !important;
    height: 100vh !important;
    height: 100dvh !important;
    max-height: none !important;
    margin: 0 !important;
    border-radius: 0 !important;
    border: none !important;
    box-shadow: none !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    -webkit-overflow-scrolling: touch;
  }
  #v2-date-filter-popover .v2-btn {
    width: 100%;
    justify-content: center;
  }
  #v2-date-filter-popover .v2-dialog-card > div:last-of-type {
    position: sticky !important;
    bottom: 0;
    margin-top: auto !important;
    background: var(--v2-bg);
    border-top: 1px solid var(--v2-line);
    z-index: 1;
    flex-direction: column-reverse !important;
    align-items: stretch !important;
    justify-content: stretch !important;
    gap: 10px !important;
    padding: 16px 20px calc(16px + env(safe-area-inset-bottom, 0px)) !important;
  }

  /* KPI strips: on mobile, stack each metric on its own row, left-aligned.
     Same pattern report-list uses via `.v2-kpi-strip` — just applied to the
     inline-flex KPI rows on other detail/list pages via the `v2-kpi-row` tag. */
  .v2-kpi-row {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 12px !important;
  }

  /* Key/value data rows on detail-v2 pages: stack label above value, full-width.
     Covers both `.v2-data-row` (class) and the inline-grid 200px+1fr variant
     used in a couple of pages (checkin-detail). */
  .v2-data-row,
  [style*="grid-template-columns:200px 1fr"],
  [style*="grid-template-columns: 200px 1fr"] {
    grid-template-columns: 1fr !important;
    gap: 4px !important;
  }
  .v2-data-row-label { font-size: 12px; }

  /* Stacked table — opt-in pattern that collapses table rows into label/value
     cards on mobile. Add `.v2-stacked-table` to <table> and `data-label="…"`
     to each tbody <td> after the first (description) so the column header
     renders to the left of its value. First td becomes the card title. */
  /* When a table opts into `.v2-stacked-table`, drop the desktop min-width
     + horizontal scroll so cards flow within the viewport instead of
     forcing the wrap to scroll. Covers both wrap variants used in detail
     views (.v2-detail-table-wrap and .v2-item-table-wrap). */
  .v2-detail-table-wrap:has(.v2-stacked-table),
  .v2-item-table-wrap:has(.v2-stacked-table),
  .v2-table-wrap:has(.v2-stacked-table) { overflow-x: visible; }
  .v2-detail-table-wrap .v2-stacked-table,
  .v2-item-table-wrap .v2-stacked-table,
  .v2-table-wrap .v2-stacked-table {
    min-width: 0;
    width: 100%;
    table-layout: auto;
  }

  .v2-stacked-table,
  .v2-stacked-table tbody,
  .v2-stacked-table tfoot,
  .v2-stacked-table tr,
  .v2-stacked-table td {
    display: block;
    width: auto;
  }
  .v2-stacked-table colgroup,
  .v2-stacked-table thead { display: none; }

  .v2-stacked-table tbody tr {
    border-bottom: 1px solid var(--v2-line);
    padding: 14px 0;
  }
  .v2-stacked-table tbody tr:first-child { padding-top: 0; }
  .v2-stacked-table tbody tr:last-child { border-bottom: none; }
  .v2-stacked-table tbody td {
    padding: 4px 0 !important;
    border: none !important;
    text-align: left;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    word-break: break-word;
    overflow-wrap: anywhere;
    background: transparent;
  }
  .v2-stacked-table tbody td > span {
    text-align: right;
    min-width: 0;
  }
  .v2-stacked-table tbody td[data-label]::before {
    content: attr(data-label);
    font-size: 11px;
    font-weight: 500;
    color: var(--v2-ink-3);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    flex-shrink: 0;
  }
  .v2-stacked-table tbody td:first-child {
    display: block;
    font-weight: 500;
    color: var(--v2-ink);
    padding: 0 0 8px !important;
    margin-bottom: 6px;
    border: none !important;
    border-bottom: 1px solid var(--v2-line) !important;
    text-align: left !important;
  }
  /* Skip cells whose value is empty (text-only line items, both span-wrapped
     and bare-text variants). */
  .v2-stacked-table tbody td[data-label]:empty,
  .v2-stacked-table tbody td[data-label]:has(> span:empty) { display: none; }

  /* tfoot — keep totals as label/value pairs, no card chrome */
  .v2-stacked-table tfoot tr {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 4px 0;
    gap: 12px;
  }
  .v2-stacked-table tfoot td {
    padding: 0 !important;
    border: none !important;
    background: transparent;
  }
  .v2-stacked-table tfoot td:first-child { text-align: left; flex: 1; }
  .v2-stacked-table tfoot td:last-child { text-align: right; flex: 0 0 auto; }

  /* Edit-mode add-ons for `.v2-stacked-table` — applied to line-item tables
     on create/edit pages (worksheet, quote, invoice, etc). The base stacked
     pattern handles label/value collapse; these rules cover the cells the
     read-only detail tables don't have: a per-row action group and the
     "Aggiungi Riga" form row. */

  /* Row card — edit/create line-item tables only (chain `.v2-item-table` so
     the detail-page `.v2-stacked-table` rows keep their original
     viewport-flush padding). Padding-top override resets the base
     `tr:first-child { padding-top: 0 }` since the edit table has a header
     row, not a data row, as its first child. */
  .v2-item-table.v2-stacked-table tbody tr { padding: 14px; }
  .v2-item-table.v2-stacked-table tbody tr:first-child { padding-top: 14px; }

  /* Description first cell — base `.v2-item-cell-desc` truncates on a
     single line for the desktop table; on mobile let it wrap as the card
     title. */
  .v2-stacked-table tbody td.v2-item-cell-desc {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }

  /* Action cell — full-width row of touch-friendly buttons at the bottom
     of the card. The base `.v2-stacked-table tbody td` rule pins padding
     and border with !important (it's defensive against tfoot inline styles
     on detail pages), so the few properties that conflict re-assert here. */
  .v2-stacked-table tbody td.v2-item-cell-actions {
    display: block;
    padding: 10px 0 0 !important;
    margin-top: 6px;
    border-top: 1px solid var(--v2-line) !important;
  }
  .v2-stacked-table tbody td.v2-item-cell-actions::before { content: none; }
  .v2-stacked-table tbody td.v2-item-cell-actions .v2-item-actions-row {
    justify-content: flex-start;
    align-items: stretch;
    gap: 8px;
    width: 100%;
  }
  .v2-stacked-table tbody td.v2-item-cell-actions .v2-item-actions-row > .v2-btn,
  .v2-stacked-table tbody td.v2-item-cell-actions .v2-item-actions-row > button.v2-btn {
    flex: 1;
    height: 38px;
    min-width: 0;
    padding: 0 10px;
    width: auto;
    justify-content: center;
  }
  /* Drag-and-drop reordering is a desktop-only affordance; hide the handle
     on touch so the edit/delete buttons get the full row. */
  .v2-stacked-table tbody td.v2-item-cell-actions .drag-handle { display: none; }

  /* Action cells with no action (e.g. non-frontier scadenze rows) shouldn't
     render an empty bordered block at the bottom of the card. */
  .v2-stacked-table tbody td.v2-item-cell-actions:not(:has(.v2-item-actions-row)) {
    display: none;
  }

  /* Boxed variant — for stacked tables that live inside a bordered, rounded
     container (e.g. the Scadenze table on the expense detail page). Inset each
     card from the container edges instead of sitting flush against the border. */
  .v2-stacked-table.v2-stacked-boxed tbody tr { padding: 14px; }
  .v2-stacked-table.v2-stacked-boxed tbody tr:first-child { padding-top: 14px; }

  /* "Aggiungi Riga" trigger row — not a real line item, so skip the
     card-title chrome and inset the button evenly from the row edges. */
  .v2-stacked-table tbody tr#form-row { padding: 16px 14px; }
  .v2-stacked-table tbody tr#form-row td,
  .v2-stacked-table tbody tr#form-row td:first-child {
    display: block;
    padding: 0 !important;
    margin: 0;
    border: none !important;
    background: transparent;
  }
  .v2-stacked-table tbody tr#form-row td::before { content: none; }
  .v2-stacked-table tbody tr#form-row .v2-item-form-row-inner { padding: 0; }
  .v2-stacked-table tbody tr#form-row .v2-btn {
    width: 100%;
    justify-content: center;
  }

  /* Stacked-rows table — for simple 2-col label/value tables (totals, cost
     breakdowns). Each row becomes a flex row with label left + value right.
     Same separator-only style as `.v2-stacked-table`. */
  .v2-detail-table-wrap:has(.v2-stacked-rows),
  .v2-item-table-wrap:has(.v2-stacked-rows) { overflow-x: visible; }
  /* Selector specificity must beat `.v2-detail-table-wrap > table { min-width: 560px }`. */
  .v2-detail-table-wrap > .v2-stacked-rows,
  .v2-item-table-wrap > .v2-stacked-rows,
  .v2-stacked-rows {
    width: 100%;
    min-width: 0;
    table-layout: auto;
  }
  .v2-stacked-rows colgroup,
  .v2-stacked-rows thead { display: none; }
  .v2-stacked-rows tbody { display: block; }
  .v2-stacked-rows tbody tr {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--v2-line);
  }
  .v2-stacked-rows tbody tr:last-child { border-bottom: none; }
  .v2-stacked-rows tbody td {
    display: block;
    padding: 0 !important;
    border: none !important;
    background: transparent;
    word-break: break-word;
    overflow-wrap: anywhere;
  }
  .v2-stacked-rows tbody td:first-child {
    text-align: left;
    flex: 1;
    min-width: 0;
  }
  .v2-stacked-rows tbody td:last-child {
    text-align: right;
    flex: 0 0 auto;
    min-width: 0;
  }


  .v2-list-surface .v2-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-bottom-left-radius: 10px;
    border-bottom-right-radius: 10px;
  }

  .v2-list-surface .v2-table {
    min-width: 720px;
  }

  /* KPI strip — force one cell per row on mobile so metrics never sit
     side-by-side (the desktop `auto-fit, minmax(160px, 1fr)` would otherwise
     still pack 2 cells onto a single row on phones ≥320px wide). */
  .v2-kpi-strip {
    grid-template-columns: 1fr !important;
    row-gap: 20px;
  }

  .v2-kpi-cell {
    border-right: none !important;
    padding: 4px 0 !important;
  }
}

/* ── Expense installments (scadenze) editor ─────────────────────────
   Each scadenza is a JS-built `.installment-row`: Rata label + date input +
   amount input + remove button. Styling lives here (not inline in the JS) so
   the mobile media query below can reflow the row to full-width stacked
   fields. Used by both the create and edit expense forms. */
.installment-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--v2-line);
}
.installment-row .inst-rata-label {
  font-size: 12px;
  color: var(--v2-ink-3);
  font-weight: 500;
  white-space: nowrap;
  min-width: 52px;
}
.installment-row .inst-date {
  flex: 1 1 160px;
  min-width: 140px;
}
.installment-row .inst-amount-wrap {
  position: relative;
  flex: 0 1 150px;
  min-width: 120px;
}
.installment-row .inst-amount {
  text-align: right;
  padding-right: 30px;
}
.installment-row .inst-amount-currency {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 12px;
  color: var(--v2-ink-3);
  pointer-events: none;
}
.installment-row .inst-remove-label { display: none; }

.installments-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  background: var(--v2-surface-2);
  border-top: 1px solid var(--v2-line);
}

@media (max-width: 639px) {
  /* Stack every field full-width: date, then amount, then a labelled
     full-width delete button — one per row. */
  .installment-row {
    flex-wrap: wrap;
    gap: 10px;
    padding: 14px;
  }
  .installment-row .inst-rata-label {
    flex: 1 1 100%;
    min-width: 0;
  }
  .installment-row .inst-date {
    flex: 1 1 100%;
    min-width: 0;
  }
  .installment-row .inst-amount-wrap {
    flex: 1 1 100%;
    min-width: 0;
  }
  .installment-row .inst-remove {
    flex: 1 1 100%;
    width: 100%;
    justify-content: center;
    gap: 6px;
    padding: 9px 12px;
    border-color: var(--v2-line);
  }
  .installment-row .inst-remove-label {
    display: inline;
    font-size: 13px;
    font-weight: 500;
  }

  /* Full-width "Aggiungi scadenza" button with the sum hint stacked below. */
  .installments-footer {
    flex-direction: column;
    align-items: stretch;
  }
  .installments-footer .v2-btn {
    width: 100%;
    justify-content: center;
  }
  .installments-footer #installments-sum {
    text-align: center;
  }
}

/* ── Calendar ───────────────────────────────── */

.v2-cal-period {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 20px 0 14px;
  border-bottom: 1px solid var(--v2-line);
  margin-bottom: 0;
}

.v2-cal-period-left {
  flex: 1;
  min-width: 0;
}

.v2-cal-period-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

@media (max-width: 639px) {
  .v2-cal-period {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    padding: 16px 0 12px;
  }
  .v2-cal-period-left {
    width: 100%;
  }
  .v2-cal-period-right {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 100%;
  }
  .v2-cal-period-right > div {
    width: 100%;
  }
  .v2-cal-period-right .v2-filter-btn,
  .v2-cal-period-right .v2-btn {
    width: 100%;
    justify-content: center;
  }

  /* Lista tab → "Calendario: Tutti" filter — full-width on mobile.
     Overrides the inline `display:inline-block` on the wrapper. */
  .v2-cal-list-filter-wrap {
    display: block !important;
    width: 100%;
  }
  .v2-cal-list-filter-wrap .v2-filter-btn {
    width: 100%;
    justify-content: center;
  }
}

.v2-cal-container {
  border: 1px solid var(--v2-line);
  border-radius: 10px;
  background: #fff;
  overflow: hidden;
  margin-top: 16px;
}

.v2-cal-header {
  display: grid;
  grid-template-columns: 60px repeat(7, 1fr);
  height: 44px;
  border-bottom: 1px solid var(--v2-line);
}

.v2-cal-header-day {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 500;
  color: var(--v2-ink-3);
  border-left: 1px solid var(--v2-line);
}

.v2-cal-header-day.today {
  font-weight: 600;
  color: var(--v2-ink);
}

/* Today = filled blue circle, consistent with the month cells and the
   mobile day-picker. */
.v2-cal-header-day.today .v2-cal-day-num {
  background: var(--v2-brand);
  color: #fff;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: grid;
  place-items: center;
}

.v2-cal-day-num {
  color: var(--v2-ink-2);
  font-weight: 600;
}

/* Mobile day-picker: hidden on desktop. On mobile it replaces the 7-day
   header row and filters the events grid down to the selected day, matching
   the v1 mobile calendar pattern. */
.v2-cal-day-picker { display: none; }

@media (max-width: 639px) {
  .v2-cal-header { display: none; }

  .v2-cal-day-picker {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 4px;
    padding: 10px 8px;
    border-bottom: 1px solid var(--v2-line);
  }
  .v2-cal-day-picker button {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 4px 0;
    background: transparent;
    border: none;
    cursor: pointer;
    font-family: inherit;
    border-radius: 8px;
  }
  .v2-cal-day-picker-label {
    font-size: 11px;
    color: var(--v2-ink-3);
    font-weight: 500;
  }
  .v2-cal-day-picker-date {
    width: 28px;
    height: 28px;
    display: grid;
    place-items: center;
    border-radius: 99px;
    font-size: 14px;
    font-weight: 600;
    color: var(--v2-ink);
  }
  .v2-cal-day-picker button.active .v2-cal-day-picker-date {
    background: var(--v2-brand);
    color: #fff;
  }

  /* Week view only: collapse the events grid to a single column and pin
     every event / click-slot into column 1 — the day filter then hides the
     rest. Scoped to [data-view="week"] so the server-rendered single-column
     day view passes through untouched (it needs no collapse, and the blanket
     display:none below would otherwise blank it). */
  #calendar-scroll-area[data-view="week"] [style*="grid-template-columns:repeat(7, 1fr)"] {
    grid-template-columns: 1fr !important;
  }
  #calendar-scroll-area[data-view="week"] .v2-cal-event,
  #calendar-scroll-area[data-view="week"] [data-day-slot] {
    grid-column: 1 !important;
  }
  /* Click-slots fill the day so the whole grid is tappable, but events
     keep their inline cascade/split widths — otherwise every overlapping
     event collapses to full width and only the top one stays visible. */
  #calendar-scroll-area[data-view="week"] [data-day-slot] {
    width: calc(100% - 8px) !important;
    margin-left: 4px !important;
  }

  /* Filter visible day. Default to selected-day=1 (Monday); JS updates on tap. */
  #calendar-scroll-area[data-view="week"] .v2-cal-event,
  #calendar-scroll-area[data-view="week"] [data-day-slot] { display: none; }
  #calendar-scroll-area[data-view="week"][data-selected-day="1"] .v2-cal-event[data-day="1"],
  #calendar-scroll-area[data-view="week"][data-selected-day="1"] [data-day-slot="1"],
  #calendar-scroll-area[data-view="week"][data-selected-day="2"] .v2-cal-event[data-day="2"],
  #calendar-scroll-area[data-view="week"][data-selected-day="2"] [data-day-slot="2"],
  #calendar-scroll-area[data-view="week"][data-selected-day="3"] .v2-cal-event[data-day="3"],
  #calendar-scroll-area[data-view="week"][data-selected-day="3"] [data-day-slot="3"],
  #calendar-scroll-area[data-view="week"][data-selected-day="4"] .v2-cal-event[data-day="4"],
  #calendar-scroll-area[data-view="week"][data-selected-day="4"] [data-day-slot="4"],
  #calendar-scroll-area[data-view="week"][data-selected-day="5"] .v2-cal-event[data-day="5"],
  #calendar-scroll-area[data-view="week"][data-selected-day="5"] [data-day-slot="5"],
  #calendar-scroll-area[data-view="week"][data-selected-day="6"] .v2-cal-event[data-day="6"],
  #calendar-scroll-area[data-view="week"][data-selected-day="6"] [data-day-slot="6"],
  #calendar-scroll-area[data-view="week"][data-selected-day="7"] .v2-cal-event[data-day="7"],
  #calendar-scroll-area[data-view="week"][data-selected-day="7"] [data-day-slot="7"] {
    display: block;
  }
}

.v2-cal-body {
  display: grid;
  grid-template-columns: 60px repeat(7, 1fr);
  position: relative;
}

.v2-cal-time-col {
  position: relative;
}

.v2-cal-hour-label {
  position: absolute;
  right: 12px;
  font-variant-numeric: tabular-nums;
  font-size: 11.5px;
  color: var(--v2-ink-3);
  line-height: 1;
}

.v2-cal-grid-area {
  grid-column: 2 / -1;
  position: relative;
  min-height: 0;
}

.v2-cal-day-col {
  position: absolute;
  top: 0;
  bottom: 0;
  border-left: 1px solid var(--v2-line);
}

.v2-cal-day-col.today {
  background: rgba(37, 99, 235, 0.025);
}

.v2-cal-gridline {
  position: absolute;
  left: 0;
  right: 0;
  border-bottom: 1px solid var(--v2-line);
}

.v2-cal-gridline-half {
  position: absolute;
  left: 0;
  right: 0;
  border-bottom: 1px dashed var(--v2-line);
  opacity: 0.5;
}

.v2-cal-now-line {
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--v2-brand);
  z-index: 30;
}

.v2-cal-now-dot {
  position: absolute;
  left: 0;
  width: 8px;
  height: 8px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--v2-brand);
  z-index: 30;
}

.v2-cal-event {
  position: absolute;
  border-radius: 3px;
  cursor: pointer;
  overflow: hidden;
  padding: 4px 10px 4px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  z-index: 20;
  transition: filter 0.12s, width 0.12s, margin-left 0.12s;
}

/* Short events (<= 30 min) are only ~28px tall — the stacked layout can't
   fit, so collapse to a single line: start time + title side by side, the
   customer subtitle dropped. Keeps the text legible instead of clipped to
   nothing. */
.v2-cal-event--short {
  flex-direction: row;
  align-items: baseline;
  gap: 5px;
  padding-top: 2px;
  padding-bottom: 2px;
  line-height: 1.2;
}

.v2-cal-event--short .v2-cal-event-time {
  flex-shrink: 0;
  font-size: 10.5px;
}

.v2-cal-event--short .v2-cal-event-title {
  font-size: 11.5px;
  min-width: 0;
}

.v2-cal-event--short .v2-cal-event-subtitle {
  display: none;
}

.v2-cal-event:hover {
  filter: brightness(0.96);
}

/* Crowded clusters cascade as wide overlapping cards (see
   calendar-list-v2.html). Hovering lifts a card to the front and widens it a
   bit (resting 72% → 86%) in place — not to full width, so the surrounding
   cards stay partly visible instead of being fully covered. margin-left is
   left untouched so the card grows from where it sits. */
.v2-cal-event--stacked:hover {
  width: calc(86% - 4px) !important;
  z-index: 60 !important;
  filter: drop-shadow(0 8px 18px rgba(10, 14, 26, 0.16));
}

/* ── Month view ───────────────────────────────────────────────── */

.v2-cal-month-header {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  border-bottom: 1px solid var(--v2-line);
}

.v2-cal-month-header > div {
  padding: 10px 8px;
  font-size: 11px;
  font-weight: 600;
  color: var(--v2-ink-3);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-align: center;
}

.v2-cal-month-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
}

.v2-cal-month-cell {
  min-height: 112px;
  min-width: 0;
  border-bottom: 1px solid var(--v2-line);
  border-left: 1px solid var(--v2-line);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  overflow: hidden;
  cursor: pointer; /* whole cell navigates to the day view */
}

.v2-cal-month-cell:nth-child(7n + 1) {
  border-left: none;
}

.v2-cal-month-grid > .v2-cal-month-cell:nth-last-child(-n + 7) {
  border-bottom: none;
}

.v2-cal-month-cell.today {
  background: rgba(37, 99, 235, 0.025);
}

.v2-cal-month-cell.other-month .v2-cal-month-day-num {
  color: var(--v2-ink-4);
}

.v2-cal-month-cell.other-month .v2-cal-month-chip {
  opacity: 0.6;
}

.v2-cal-month-day-num {
  align-self: flex-start;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  background: none;
  border: none;
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  color: var(--v2-ink-2);
}

.v2-cal-month-day-num:hover {
  background: var(--v2-surface-2);
  color: var(--v2-ink);
}

.v2-cal-month-cell.today .v2-cal-month-day-num {
  background: var(--v2-brand);
  color: #fff;
  font-weight: 600;
}

.v2-cal-month-chip {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  padding: 2px 6px 2px 8px;
  border-radius: 3px;
  cursor: pointer;
  font-size: 11.5px;
  line-height: 1.35;
  white-space: nowrap;
  overflow: hidden;
  transition: filter 0.12s;
}

.v2-cal-month-chip:hover {
  filter: brightness(0.96);
}

.v2-cal-month-chip-time {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  opacity: 0.75;
  flex-shrink: 0;
}

.v2-cal-month-chip-title {
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
}

.v2-cal-month-more {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 1px 6px;
  cursor: pointer;
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  color: var(--v2-ink-2);
  border-radius: 4px;
}

.v2-cal-month-more:hover {
  background: var(--v2-surface-2);
  color: var(--v2-ink);
}

/* Compact week-range label used on small screens only. */
.v2-cal-period-label-short {
  display: none;
}

@media (max-width: 639px) {
  /* Nav cluster spans the full row: chevrons pinned to the edges,
     period label centered between them. */
  .v2-cal-nav {
    width: 100%;
    justify-content: space-between;
  }

  /* Primary navigation needs a real touch target (icon stays 14px). */
  .v2-cal-nav .v2-cal-nav-arrow {
    width: 40px !important;
    height: 40px !important;
  }

  .v2-cal-period-label-full {
    display: none;
  }

  .v2-cal-period-label-short {
    display: inline;
  }

  .v2-cal-month-cell {
    min-height: 64px;
    padding: 4px;
    gap: 2px;
  }

  /* Chips collapse to slim colored bars and stop being tap targets — the
     cell/day number lead to the day view, which is the mobile agenda. */
  .v2-cal-month-chip {
    height: 6px;
    padding: 0;
    border-radius: 2px;
    pointer-events: none;
  }

  .v2-cal-month-chip span {
    display: none;
  }

  .v2-cal-month-more {
    font-size: 10px;
    padding: 4px 4px;
  }
}

/* Cliente / Veicolo value links inside the event detail dialog —
   same treatment as worksheet/expense detail: bold ink, no blue, no underline */
.v2-cal-detail-link {
  color: var(--v2-ink);
  font-weight: 600;
  text-decoration: none;
}

.v2-cal-detail-link:hover {
  color: var(--v2-ink-2);
}

.v2-cal-event-time {
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  font-weight: 600;
  opacity: 0.75;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.v2-cal-event-title {
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.v2-cal-event-subtitle {
  font-size: 11.5px;
  opacity: 0.78;
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.v2-cal-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  padding: 16px 0;
  font-size: 12px;
  color: var(--v2-ink-3);
}

.v2-cal-legend-swatch {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  display: inline-block;
  vertical-align: middle;
  margin-right: 6px;
}

/* ── Form inputs (create / edit pages) ────────── */

.v2-form-input {
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  height: 36px;
  padding: 0 12px;
  font-family: inherit;
  font-size: 13.5px;
  background: var(--v2-bg);
  color: var(--v2-ink);
  border: 1px solid var(--v2-line-2);
  border-radius: 8px;
  transition: border-color .12s, box-shadow .12s;
  box-sizing: border-box;
}

.v2-form-input::placeholder {
  color: var(--v2-ink-4);
}

.v2-form-input:focus {
  outline: none;
  border-color: var(--v2-brand);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}

/* Locked field — the value belongs to another entity (customer / vehicle
   anagrafica) and is shown here for reference only. The document forms render
   it without a `name`, so it is never submitted; it is changed on the entity's
   own page. */
.v2-form-input-locked {
  background: var(--v2-surface-2);
  color: var(--v2-ink-3);
  cursor: not-allowed;
}

.v2-form-input-locked:focus {
  border-color: var(--v2-line-2);
  box-shadow: none;
}

.v2-form-mono {
  font-variant-numeric: tabular-nums;
}

select.v2-form-input {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 36px;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}

textarea.v2-form-input {
  height: auto;
  padding: 10px 12px;
  resize: vertical;
  line-height: 1.5;
}

.v2-form-label {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-size: 11px;
  font-weight: 500;
  color: var(--v2-ink-3);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: 6px;
}

/* ── Choice cards ───────────────────────────────────────────────────────────
   A clickable card that behaves as a radio: pick exactly one of N options.
   Used by the onboarding goal step, the team-member role picker and the prima
   nota movement dialog. Each of those hand-rolled its own copy (.onb-goal-card,
   .coll-role-card) before this existed — always use these classes instead of
   adding a fourth.

   Markup is a <label> wrapping a visually-hidden native radio, so keyboard and
   screen readers get real radio semantics for free and the browser enforces
   single-selection within the group:

     <div class="v2-choice-grid v2-choice-grid-2">
       <label class="v2-choice-card active">
         <input type="radio" name="thing" value="a" checked>
         <span class="v2-choice-card-body">
           <span class="v2-choice-radio"></span>
           <span class="v2-choice-content">
             <span class="v2-choice-heading">
               <svg class="v2-choice-icon" …>…</svg>   <!-- Heroicons outline 24, optional -->
               <span class="v2-choice-title">Titolo</span>
             </span>
             <span class="v2-choice-desc">Riga di spiegazione, opzionale.</span>
           </span>
         </span>
       </label>
       …
     </div>

   Keep `.active` on the selected card in sync with the checked input — CSS
   alone cannot style a parent from a child. The selected state reads through
   border, background and colour only: no box-shadow ring, per the house rule. */
.v2-choice-grid {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.v2-choice-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

@media (max-width: 560px) {
  .v2-choice-grid-2 {
    grid-template-columns: 1fr;
  }
}

.v2-choice-card {
  display: block;
  text-align: left;
  padding: 14px 16px;
  border: 1px solid var(--v2-line-2);
  border-radius: 10px;
  background: var(--v2-bg);
  cursor: pointer;
  font-family: inherit;
  transition: border-color .12s, background .12s;
}

.v2-choice-card:hover {
  border-color: var(--v2-ink-4);
}

/* The native radio carries the semantics; the painted dot carries the looks. */
.v2-choice-card input[type="radio"] {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}

.v2-choice-card:focus-within {
  border-color: var(--v2-brand);
}

.v2-choice-card.active {
  border-color: var(--v2-brand);
  background: var(--v2-brand-50, #eff6ff);
}

.v2-choice-card-body {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.v2-choice-radio {
  width: 14px;
  height: 14px;
  margin-top: 3px;
  border-radius: 50%;
  border: 2px solid var(--v2-line-2);
  background: var(--v2-bg);
  position: relative;
  flex-shrink: 0;
  display: inline-block;
  box-sizing: border-box;
}

.v2-choice-card.active .v2-choice-radio {
  border-color: var(--v2-brand);
}

.v2-choice-card.active .v2-choice-radio::after {
  content: '';
  position: absolute;
  inset: 2px;
  border-radius: 50%;
  background: var(--v2-brand);
}

.v2-choice-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.v2-choice-heading {
  display: flex;
  align-items: center;
  gap: 8px;
}

.v2-choice-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--v2-ink-3);
  display: block;
}

.v2-choice-card.active .v2-choice-icon {
  color: var(--v2-brand);
}

.v2-choice-title {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--v2-ink);
}

.v2-choice-card.active .v2-choice-title {
  color: var(--v2-brand-2, #1d4ed8);
}

.v2-choice-desc {
  font-size: 12.5px;
  color: var(--v2-ink-3);
  line-height: 1.5;
}

/* Two-column form grid (Anagrafica / Indirizzo / Contatti / etc.).
   Collapses to a single column on mobile — no inline styles needed. */
.v2-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 24px;
  row-gap: 18px;
}
.v2-form-grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  column-gap: 24px;
  row-gap: 18px;
}
.v2-form-grid-sub {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.v2-form-grid-span-2 { grid-column: span 2; }
.v2-form-field {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Input + adjacent action button (Partita IVA + Compila lookup).
   Desktop: input fills, button takes its content width.
   Mobile:  fixed 80/20 split so the input never collapses. */
.v2-form-input-action {
  display: flex;
  gap: 8px;
}
.v2-form-input-action .v2-form-input { flex: 1; min-width: 0; }

/* Input + adjacent action button that stacks fully on mobile
   (e.g. vehicle-create plate search). Desktop: input fills + button beside.
   Mobile: column, both 100% width. */
.v2-form-input-stack {
  display: flex;
  gap: 10px;
}
.v2-form-input-stack > .v2-form-input { flex: 1; min-width: 0; }

/* ── Italian license plate ─────────────────────
   EU blue band + white body. Used for targa lookup inputs
   (onboarding, vehicle create) and read-only display (detail).
   Border is intentionally soft (1px ink-3) — not a heavy black frame. */
.v2-plate {
  display: inline-flex;
  align-items: stretch;
  max-width: 320px;
  border: 1px solid var(--v2-ink-3);
  border-radius: var(--v2-r-lg);
  overflow: hidden;
  background: #fff;
  vertical-align: middle;
}
/* Stretch to fill a flex row (plate + Cerca button) */
.v2-plate-fill {
  display: flex;
  flex: 1;
  min-width: 0;
}
.v2-plate-band {
  width: 26px;
  background: #039;
  color: #fff;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 5px 0;
  flex: 0 0 auto;
}
.v2-plate-band span {
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.v2-plate input,
.v2-plate-num {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  height: 46px;
  min-height: 46px;
  padding: 0 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 20px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-align: center;
  color: var(--v2-ink);
  background: transparent;
}
.v2-plate-num {
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
}
/* Compact plate for page headers */
.v2-plate-sm .v2-plate-band {
  width: 22px;
  padding: 4px 0;
}
.v2-plate-sm .v2-plate-band span {
  font-size: 8px;
}
.v2-plate-sm input,
.v2-plate-sm .v2-plate-num {
  height: 36px;
  min-height: 36px;
  padding: 0 12px;
  font-size: 16px;
}
/* Extra-small plate for inline meta rows (worksheet vehicle section, etc.)
   Matches adjacent 12.5px label/value text height. */
.v2-plate-xs {
  border-radius: var(--v2-r-sm);
}
.v2-plate-xs .v2-plate-band {
  width: 14px;
  padding: 2px 0;
}
.v2-plate-xs .v2-plate-band span {
  font-size: 6.5px;
}
.v2-plate-xs .v2-plate-band svg {
  width: 8px;
  height: 8px;
}
.v2-plate-xs input,
.v2-plate-xs .v2-plate-num {
  height: 22px;
  min-height: 22px;
  padding: 0 7px;
  font-size: 12.5px;
  letter-spacing: 0.1em;
}

/* Narrow input wrapper (e.g. integer percentage, small numeric field).
   Desktop: compact 100px so a 2–3 digit value doesn't stretch across the
   column. Mobile: full width so the field stays comfortable to tap. */
.v2-form-input-narrow {
  position: relative;
  width: 100px;
}

@media (max-width: 639px) {
  .v2-form-grid,
  .v2-form-grid-3,
  .v2-form-grid-sub { grid-template-columns: 1fr; }
  .v2-form-grid-span-2 { grid-column: auto; }
  .v2-form-input-action .v2-form-input { flex: 4 1 0; }
  .v2-form-input-action .v2-btn {
    flex: 1 1 0;
    padding: 0 6px;
    justify-content: center;
    white-space: nowrap;
  }
  .v2-form-input-narrow { width: 100%; }
}

/* Stack the input + action button below desktop (covers phone portrait,
   phone landscape, and tablet portrait where the sidebar is hidden but
   "Ricerca targa" was crunching the license-plate input). */
@media (max-width: 1023px) {
  .v2-form-input-stack {
    flex-direction: column;
  }
  .v2-form-input-stack > .v2-form-input,
  .v2-form-input-stack > .v2-btn {
    width: 100%;
    flex: 0 0 auto;
  }
  .v2-form-input-stack > .v2-btn {
    justify-content: center;
  }
}

.v2-form-required {
  color: var(--v2-brand);
  font-size: 12px;
  line-height: 1;
}

.v2-form-hint {
  font-size: 11.5px;
  color: var(--v2-ink-3);
  line-height: 1.4;
  margin-top: 4px;
}

/* ── Rich text editor (Quill v2 overrides) ──────── */

.v2 .ql-toolbar.ql-snow {
  border: 1px solid var(--v2-line-2);
  border-bottom: none;
  border-radius: 8px 8px 0 0;
  padding: 6px 8px;
  background: var(--v2-surface-2);
  font-family: inherit;
}

.v2 .ql-container.ql-snow {
  border: 1px solid var(--v2-line-2);
  border-radius: 0 0 8px 8px;
  font-family: inherit;
  font-size: 13.5px;
  color: var(--v2-ink);
  background: var(--v2-bg);
}

.v2 .ql-editor {
  min-height: 120px;
  padding: 10px 12px;
  line-height: 1.5;
}

.v2 .ql-editor.ql-blank::before {
  color: var(--v2-ink-4);
  font-style: normal;
  left: 12px;
  right: 12px;
}

.v2 .ql-snow .ql-stroke {
  stroke: var(--v2-ink-3);
}

.v2 .ql-snow .ql-fill,
.v2 .ql-snow .ql-stroke.ql-fill {
  fill: var(--v2-ink-3);
}

.v2 .ql-snow.ql-toolbar button:hover .ql-stroke,
.v2 .ql-snow.ql-toolbar button.ql-active .ql-stroke {
  stroke: var(--v2-brand);
}

.v2 .ql-snow.ql-toolbar button:hover .ql-fill,
.v2 .ql-snow.ql-toolbar button.ql-active .ql-fill,
.v2 .ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill,
.v2 .ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill {
  fill: var(--v2-brand);
}

.v2 .ql-snow.ql-toolbar button:hover,
.v2 .ql-snow.ql-toolbar button.ql-active {
  color: var(--v2-brand);
}

/* Focus ring on the wrapper only – inner borders stay unchanged */
.v2 .v2-quill-wrap {
  border-radius: 8px;
}

.v2 .v2-quill-wrap:focus-within {
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
  border-radius: 8px;
}

/* ── Action bar (sticky bottom bar for forms) ──── */

.v2-action-bar {
  background: var(--v2-bg);
  border-top: 1px solid var(--v2-line);
  flex-shrink: 0;
}

.v2-action-bar-inner {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 54px;
  padding: 0 32px;
  margin: 0 auto;
}

.v2-action-bar-hint {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--v2-ink-3);
}

/* Transient status inside the sticky footer's hint slot — the THIRD feedback
   weight, alongside the two notices (see "Notices"). It is not a notice: there
   is nothing to dismiss and it lives in a fixed slot, cycling
   idle → busy → error → idle. Dot + coloured text, per the V2 status rule.

     <div class="v2-action-bar-hint" id="action-status">
       <span class="v2-action-status v2-action-status-idle">La scheda viene salvata solo confermando.</span>
     </div>

   The page's JS swaps the inner span for the -busy / -error variant. Use these
   classes rather than re-inlining the dot: it was copy-pasted into 34 pages
   before this existed. */
.v2-action-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.v2-action-status-idle {
  color: var(--v2-ink-4);
}

.v2-action-status-busy {
  color: var(--v2-ink-3);
}

.v2-action-status-dirty {
  color: var(--v2-ink-2);
  font-weight: 500;
}

.v2-action-status-error {
  color: var(--v2-danger);
  font-weight: 500;
}

/* Unsaved and error both lead with a dot in their own colour. */
.v2-action-status-dirty::before,
.v2-action-status-error::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.v2-action-status-dirty::before {
  background: var(--v2-warn);
}

/* Saved is the one state that earns a filled badge rather than a bare dot: it
   is the confirmation the user was waiting for. */
.v2-action-status-saved {
  color: var(--v2-good);
  font-weight: 500;
}

.v2-action-status-saved::before {
  content: '';
  width: 16px;
  height: 16px;
  border-radius: 99px;
  flex-shrink: 0;
  background: var(--v2-good-bg) var(--v2-action-status-check) center / 10px 10px no-repeat;
}

:root {
  --v2-action-status-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2315803d' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}

.v2-action-bar-actions {
  margin-left: auto;
  display: flex;
  gap: 8px;
}

@media (max-width: 639px) {
  .v2-action-bar-inner {
    height: auto;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }
  .v2-action-bar-hint { display: none; }
  .v2-action-bar-actions {
    margin-left: 0;
    flex-direction: column-reverse;
    width: 100%;
    gap: 8px;
  }
  .v2-action-bar-actions .v2-btn {
    width: 100%;
    justify-content: center;
  }
}

/* ── Suffix input (kW, cm³, kg fields) ──────────── */

.v2-suffix-input {
  display: flex;
  align-items: center;
  height: 36px;
  background: var(--v2-bg);
  border: 1px solid var(--v2-line-2);
  border-radius: 8px;
  transition: border-color .12s, box-shadow .12s;
  overflow: hidden;
}

.v2-suffix-input:focus-within {
  border-color: var(--v2-brand);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}

.v2-suffix-input input {
  flex: 1;
  height: 100%;
  padding: 0 12px;
  border: none;
  outline: none;
  background: transparent;
  font-size: 13.5px;
  color: var(--v2-ink);
  font-variant-numeric: tabular-nums;
}

.v2-suffix-input input::placeholder {
  color: var(--v2-ink-4);
}

.v2-suffix-input-tag {
  padding: 0 12px;
  height: 100%;
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  color: var(--v2-ink-3);
  border-left: 1px solid var(--v2-line);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

/* ── Segmented control ──────────────────────────── */

.v2-segmented {
  display: inline-flex;
  padding: 3px;
  background: var(--v2-surface-2);
  border: 1px solid var(--v2-line);
  border-radius: 8px;
}

.v2-segmented input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.v2-segmented-option {
  padding: 7px 16px;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  color: var(--v2-ink-3);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  transition: background .12s, color .12s;
  white-space: nowrap;
}

.v2-segmented input[type="radio"]:focus-visible + .v2-segmented-option {
  outline: 2px solid var(--v2-brand);
  outline-offset: 1px;
}

.v2-segmented input[type="radio"]:checked + .v2-segmented-option {
  font-weight: 600;
  color: var(--v2-ink);
  background: var(--v2-bg);
  border-color: var(--v2-line-2);
  box-shadow: 0 1px 2px rgba(10, 14, 26, 0.04);
}

/* Full-width variant: the options share the row equally (form fields in a dialog). */
.v2-segmented.v2-segmented-fill {
  display: grid;
  grid-auto-columns: 1fr;
  grid-auto-flow: column;
  width: 100%;
}
.v2-segmented.v2-segmented-fill .v2-segmented-option { text-align: center; }

@media (max-width: 639px) {
  .v2-segmented {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 2px;
    width: 100%;
  }
  .v2-segmented-option {
    padding: 7px 8px;
    text-align: center;
    white-space: normal;
    line-height: 1.25;
  }
}

/* Calendar list group title */
.v2-cal-group {
  padding-top: 32px;
}

.v2-cal-group:first-child {
  padding-top: 20px;
}

.v2-cal-group-title {
  font-size: 11px;
  font-weight: 600;
  color: var(--v2-ink-3);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 12px;
}

/* ── Choice card (multi-select radio cards) ──────── */

.v2-choice-card {
  text-align: left;
  padding: 14px 16px;
  border: 1px solid var(--v2-line-2);
  border-radius: 10px;
  background: #fff;
  cursor: pointer;
  font-family: inherit;
  transition: all .12s;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

.v2-choice-card.active {
  border-color: var(--v2-brand);
  background: var(--v2-brand-50, #eff6ff);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}

.v2-choice-card.active .v2-choice-title {
  color: var(--v2-brand-2, #1d4ed8);
}

.v2-choice-card.disabled {
  cursor: default;
  opacity: 0.65;
}

.v2-choice-radio {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--v2-line-2);
  background: #fff;
  position: relative;
  flex-shrink: 0;
  display: inline-block;
  box-sizing: border-box;
}

.v2-choice-card.active .v2-choice-radio {
  border-color: var(--v2-brand);
}

.v2-choice-card.active .v2-choice-radio::after {
  content: '';
  position: absolute;
  inset: 2px;
  border-radius: 50%;
  background: var(--v2-brand);
}

.v2-choice-title {
  font-size: 13.5px;
  font-weight: 600;
}

.v2-choice-desc {
  font-size: 12.5px;
  color: var(--v2-ink-3);
  line-height: 1.5;
  padding-left: 24px;
}

/* ── Roadmap board ────────────────────────────── */

.v2-roadmap-col-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--v2-line);
}

.v2-roadmap-card {
  background: var(--v2-bg);
  border: 1px solid var(--v2-line);
  border-radius: 10px;
  padding: 14px 16px;
  transition: border-color .12s;
}

.v2-roadmap-card:hover {
  border-color: var(--v2-line-2);
}

.v2-roadmap-board {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 28px;
  align-items: start;
}

@media (max-width: 768px) {
  .v2-roadmap-board {
    grid-template-columns: 1fr;
  }
}

/* Vote count badge shown top-right of each collapsed roadmap card. */
.v2-roadmap-card-votes {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--v2-ink-3);
}

.v2-roadmap-card-votes svg {
  width: 13px;
  height: 13px;
}

/* Vote button (detail dialog): count rendered as bold text after the label,
   readable on both the secondary (not voted) and primary (voted) variants. */
.v2-roadmap-vote-btn .v2-roadmap-vote-count {
  font-weight: 700;
  opacity: 0.85;
}

.v2-roadmap-vote-btn .v2-roadmap-vote-count::before {
  content: "·";
  margin-right: 6px;
  opacity: 0.6;
}

/* ── Support pages ────────────────────────────── */

.v2-support-surface {
  border: 1px solid var(--v2-line);
  border-radius: 10px;
  background: #fff;
  overflow: hidden;
}

.v2-support-channel {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px;
  border-bottom: 1px solid var(--v2-line);
  cursor: pointer;
  transition: background .12s;
  text-decoration: none;
  color: inherit;
}

.v2-support-channel:last-child {
  border-bottom: none;
}

.v2-support-channel:hover {
  background: var(--v2-hover);
}

.v2-support-channel:hover .v2-support-channel-icon {
  color: var(--v2-brand);
  background: #fff;
}

.v2-support-channel:hover .v2-support-channel-title {
  color: var(--v2-brand-2);
}

.v2-support-channel:hover .v2-support-channel-chevron {
  color: var(--v2-brand);
  transform: translateX(2px);
}

.v2-support-channel-icon {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  border: 1px solid var(--v2-line);
  background: var(--v2-surface-2);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  color: var(--v2-ink-2);
  transition: color .12s, background .12s;
}

.v2-support-channel-title {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--v2-ink);
  letter-spacing: -0.005em;
  transition: color .12s;
}

.v2-support-channel-chevron {
  color: var(--v2-ink-4);
  flex-shrink: 0;
  transition: transform .12s, color .12s;
}

.v2-support-def-row {
  padding: 18px 20px;
  border-bottom: 1px solid var(--v2-line);
}

.v2-support-def-row:last-of-type {
  border-bottom: none;
}

.v2-support-def-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--v2-ink-3);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 6px;
}

.v2-support-def-value {
  font-size: 15.5px;
  color: var(--v2-ink);
  font-weight: 500;
}

.v2-support-footer {
  padding: 14px 20px;
  border-top: 1px solid var(--v2-line);
  background: #fafafa;
  display: flex;
  align-items: center;
  gap: 10px;
}

.v2-support-header-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
  border-bottom: 1px solid var(--v2-line);
  background: #fafafa;
}

/* AI suggest buttons (sparkle): swap an .v2-ai-btn-idle / .v2-ai-btn-loading
   child based on the .htmx-request class htmx auto-applies during requests. */
.v2-ai-suggest-menu.htmx-request .v2-ai-btn-idle,
.v2-ai-suggest-inline.htmx-request .v2-ai-btn-idle,
.ai-suggest-btn.htmx-request .v2-ai-btn-idle { display: none !important; }
.v2-ai-suggest-menu.htmx-request .v2-ai-btn-loading,
.v2-ai-suggest-inline.htmx-request .v2-ai-btn-loading,
.ai-suggest-btn.htmx-request .v2-ai-btn-loading { display: inline-flex !important; }
.v2-ai-suggest-menu.htmx-request,
.v2-ai-suggest-inline.htmx-request,
.ai-suggest-btn.htmx-request { cursor: wait; opacity: 0.9; }
.v2-ai-spinner { animation: v2-ai-spin 0.9s linear infinite; transform-origin: center; }
@keyframes v2-ai-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* OBD fault-code search: while the lookup request is in flight (htmx adds
   .htmx-request to #obd-panel), hide the results/empty-state and show the
   loading box in its place. */
.obd-loading-box { display: none; }
#obd-panel.htmx-request .obd-loading-box { display: flex; }
#obd-panel.htmx-request .obd-results-area { display: none; }
/* Uppercase the codes the user types, but keep the placeholder normal-case. */
#obd-input::placeholder { text-transform: none; }

/* When the AI returned no match, the response template is rendered inside a
   target placed within the button. JS toggles .v2-ai-has-msg on the button so
   we can hide idle/loading and show the muted "no match" text in their place. */
.v2-ai-suggest-menu.v2-ai-has-msg .v2-ai-btn-idle,
.v2-ai-suggest-inline.v2-ai-has-msg .v2-ai-btn-idle,
.ai-suggest-btn.v2-ai-has-msg .v2-ai-btn-idle,
.v2-ai-suggest-menu.v2-ai-has-msg .v2-ai-btn-loading,
.v2-ai-suggest-inline.v2-ai-has-msg .v2-ai-btn-loading,
.ai-suggest-btn.v2-ai-has-msg .v2-ai-btn-loading { display: none !important; }

/* Inline muted feedback for "no match" — sized to drop in for the Generando text. */
.v2-ai-suggest-empty {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--v2-ink-4);
  font-style: italic;
}

/* ── Table of contents (used by generateTableOfContents) ── */

.v2-toc {
  background: var(--v2-surface-2);
  border: 1px solid var(--v2-line);
  border-radius: 12px;
  padding: 6px 18px;
  margin-bottom: 40px;
}
.v2-toc .toc-trigger {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  padding: 14px 0;
  background: transparent;
  border: none;
  cursor: pointer;
  font-family: inherit;
}
.v2-toc .toc-trigger-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--v2-ink-3);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.v2-toc .toc-chevron {
  width: 16px;
  height: 16px;
  color: var(--v2-ink-4);
  transition: transform .2s;
}
.v2-toc .toc-content {
  padding: 0 0 16px;
}
.v2-toc ul,
.v2-toc ol {
  margin: 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  list-style: decimal;
}
.v2-toc ul {
  list-style: disc;
}
.v2-toc li {
  font-size: 13.5px;
  line-height: 1.55;
}
.v2-toc a {
  color: var(--v2-ink-2);
  text-decoration: none;
}
.v2-toc a:hover {
  color: var(--v2-brand);
  text-decoration: underline;
}
.v2-toc.toc-collapsed .toc-content {
  display: none;
}

/* ── Notices ────────────────────────────────────────────────────────────────
   Feedback about something that just happened, in three weights. Pick by how
   much room the message needs, and never hand-roll a fourth. Copy tone across
   all three follows the P.IVA-lookup failure line ("Non l'abbiamo trovata —
   nessun problema, compila i campi qui sotto."): concrete, calm, and always
   says what to do next.

   MINIMAL — `.v2-inline-notice` + `-error` / `-success` / `-info`
     One line of coloured text with a small icon, no box. This is the default
     for feedback attached to a single control: under an input, under the plate
     or P.IVA lookup, under a step's form. Renders as:
       <div class="v2-inline-notice v2-inline-notice-error">Targa non trovata</div>

   STANDARD — `.v2-notice` + `.v2-notice-error` / `.v2-notice-success`
     A bordered block with an icon, a coloured title and a body line. Use when
     the outcome needs a heading of its own — the result of a submit, a save, a
     background job — rather than a correction to one field. Renders as:
       <div class="v2-notice v2-notice-success">
         <svg class="v2-notice-icon">…</svg>
         <div class="v2-notice-body">
           <div class="v2-notice-title">Completato</div>
           <div class="v2-notice-message">Categoria creata con successo</div>
         </div>
         <button class="v2-notice-dismiss">×</button>   <!-- optional -->
       </div>
     Add `.v2-notice-titleless` when there is no title, so the message itself
     takes the status colour. The shared partial `generic-toast-response.html`
     renders this from {Success, Title, Message} — prefer it over hand-written
     markup.

   ACTION STATUS — `.v2-action-status` + `-idle` / `-busy` / `-dirty` /
     `-saved` / `-error`
     Transient state in the sticky footer's hint slot. Defined further up, next
     to `.v2-action-bar`. */
.v2-notice {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 10px 12px;
  border: 1px solid var(--v2-line-2);
  border-radius: 8px;
}

.v2-notice-icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  margin-top: 2px;
}

.v2-notice-body {
  flex: 1;
  min-width: 0;
}

.v2-notice-title {
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.5;
}

.v2-notice-message {
  font-size: 12.5px;
  color: var(--v2-ink-2);
  line-height: 1.5;
  margin-top: 2px;
}

/* The status colours the outline, the icon and the title; the message stays in
   ink so a long explanation is still comfortable to read. */
.v2-notice-error {
  border-color: var(--v2-danger);
}

.v2-notice-error .v2-notice-icon,
.v2-notice-error .v2-notice-title {
  color: var(--v2-danger);
}

.v2-notice-warn {
  border-color: var(--v2-warn);
}

.v2-notice-warn .v2-notice-icon,
.v2-notice-warn .v2-notice-title {
  color: var(--v2-warn);
}

.v2-notice-success {
  border-color: var(--v2-good);
}

.v2-notice-success .v2-notice-icon,
.v2-notice-success .v2-notice-title {
  color: var(--v2-good);
}

/* A notice with no title: the message carries the status colour instead, so a
   one-line boxed error still reads as an error. Opt in explicitly rather than
   keying on :only-child — that broke silently when a template emitted an empty
   title element, and it reddened long multi-sentence copy that reads better in
   ink. */
.v2-notice-titleless.v2-notice-error .v2-notice-message {
  color: var(--v2-danger);
}

.v2-notice-titleless.v2-notice-success .v2-notice-message {
  color: var(--v2-good);
}

.v2-notice-dismiss {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--v2-ink-4);
  font-family: inherit;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.v2-notice-dismiss:hover {
  color: var(--v2-ink-2);
  background: var(--v2-surface-2);
}

.v2-inline-notice {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-size: 12.5px;
  line-height: 1.5;
}
.v2-inline-notice::before {
  content: '';
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
  margin-top: 1.5px;
  background-color: currentColor;
  -webkit-mask-image: var(--v2-inline-notice-icon);
  mask-image: var(--v2-inline-notice-icon);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}
.v2-inline-notice-error {
  color: var(--v2-danger);
  --v2-inline-notice-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='black' stroke-width='1.8'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z'/%3E%3C/svg%3E");
}
.v2-inline-notice-success {
  color: var(--v2-good);
  --v2-inline-notice-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='black' stroke-width='1.8'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 12.75L11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z'/%3E%3C/svg%3E");
}
.v2-inline-notice-info {
  color: var(--v2-brand);
  --v2-inline-notice-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='black' stroke-width='1.8'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M11.25 11.25l.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0zm-9-3.75h.008v.008H12V8.25z'/%3E%3C/svg%3E");
}

/* ── Switch ────────────────────────────────────────
   The V2 on/off control. A real checkbox (so forms post it) visually replaced
   by a track + knob. Brand fill when on, no shadows.

     <label class="v2-switch">
       <input type="checkbox" name="…" checked>
       <span class="v2-switch-track"></span>
     </label>
*/
.v2-switch {
  position: relative;
  display: inline-flex;
  width: 34px;
  height: 20px;
  flex-shrink: 0;
  cursor: pointer;
}

.v2-switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: inherit;
  z-index: 1;
}

.v2-switch-track {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 999px;
  background: var(--v2-line-2);
  transition: background 0.15s ease;
}

.v2-switch-track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--v2-bg);
  transition: transform 0.15s ease;
}

.v2-switch input:checked + .v2-switch-track {
  background: var(--v2-brand);
}

.v2-switch input:checked + .v2-switch-track::after {
  transform: translateX(14px);
}

.v2-switch input:focus-visible + .v2-switch-track {
  outline: 2px solid var(--v2-brand-soft);
  outline-offset: 2px;
}

.v2-switch input:disabled {
  cursor: not-allowed;
}

.v2-switch input:disabled + .v2-switch-track {
  opacity: 0.45;
}

/* ── Switch card ───────────────────────────────────
   An optional step inside a dialog or form: bordered card, title + one-line
   description on the left, .v2-switch on the right. The whole head is the
   <label>, so tapping anywhere flips it. When the option needs more input, a
   .v2-switch-card-body below a divider is shown only while the switch is on
   (toggle its `hidden` attribute). No shadows, no fill: the border is the card.

     <div class="v2-switch-card">
       <label class="v2-switch-card-head" for="x-toggle">
         <span class="v2-switch-card-text">
           <span class="v2-switch-card-title">Segna fattura come pagata</span>
           <span class="v2-switch-card-desc">Registra il pagamento insieme all'emissione.</span>
         </span>
         <span class="v2-switch">
           <input type="checkbox" id="x-toggle" name="…" aria-controls="x-body" aria-expanded="false">
           <span class="v2-switch-track"></span>
         </span>
       </label>
       <div class="v2-switch-card-body" id="x-body" hidden>…fields…</div>
     </div>

   Inside a <label> the switch wrapper is a <span class="v2-switch"> (labels
   cannot nest). Stack cards with .v2-switch-card + .v2-switch-card spacing. */
.v2-switch-card {
  border: 1px solid var(--v2-line);
  border-radius: 10px;
}

.v2-switch-card + .v2-switch-card {
  margin-top: 10px;
}

.v2-switch-card-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  cursor: pointer;
}

.v2-switch-card-text {
  flex: 1;
  min-width: 0;
}

.v2-switch-card-title {
  display: block;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--v2-ink);
}

.v2-switch-card-desc {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--v2-ink-3);
}

.v2-switch-card-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 14px;
  border-top: 1px solid var(--v2-line);
}

.v2-switch-card-body[hidden] {
  display: none;
}

/* ── Notification preferences grid ────────────────
   /app/settings/notifications: a label column plus one centred column per
   channel (Dashboard, Email). Not a <table> — it is a settings list, sections
   are bordered cards. */
.v2-notif-prefs {
  --v2-notif-prefs-cols: minmax(0, 1fr) 96px 96px;
}

.v2-notif-prefs-head,
.v2-notif-prefs-row {
  display: grid;
  grid-template-columns: var(--v2-notif-prefs-cols);
  align-items: center;
  column-gap: 8px;
}

.v2-notif-prefs-head {
  padding: 0 16px 10px;
  border-bottom: 1px solid var(--v2-line);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--v2-ink-3);
}

.v2-notif-prefs-head-channel {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}

.v2-notif-prefs-section {
  padding-top: 28px;
}

.v2-notif-prefs-section-head {
  padding: 0 16px 10px;
}

.v2-notif-prefs-section-title {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--v2-ink);
}

.v2-notif-prefs-card {
  border: 1px solid var(--v2-line);
  border-radius: 10px;
  background: var(--v2-bg);
  overflow: hidden;
}

.v2-notif-prefs-row {
  padding: 14px 16px;
}

.v2-notif-prefs-row + .v2-notif-prefs-row {
  border-top: 1px solid var(--v2-line);
}

.v2-notif-prefs-row-title {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--v2-ink);
}

.v2-notif-prefs-row-desc {
  margin-top: 2px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--v2-ink-3);
}

.v2-notif-prefs-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.v2-notif-prefs-na {
  color: var(--v2-ink-5);
  font-size: 13px;
}

@media (max-width: 640px) {
  .v2-notif-prefs {
    --v2-notif-prefs-cols: minmax(0, 1fr) 64px 64px;
  }

  .v2-notif-prefs-head-channel svg {
    display: none;
  }

  .v2-notif-prefs-head,
  .v2-notif-prefs-section-head,
  .v2-notif-prefs-row {
    padding-left: 12px;
    padding-right: 12px;
  }
}

/* ==========================================================================
   V2 MultiSelect — shared component (templates/v2-multiselect-html.html,
   assets/js/v2-multiselect.js; rules in CLAUDE.md "V2 MULTISELECT").
   Drop-in for select.v2-form-input: same height, border, radius and focus
   ring. Chips are always neutral; blue only for the checked checkbox and
   focus. No shadows on the menu — border only.
   ========================================================================== */
.v2-ms {
  position: relative;
  width: 100%;
  min-width: 0;
}
.v2-ms-control {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 36px;
  padding: 4px 34px 4px 4px;
  background: var(--v2-bg);
  border: 1px solid var(--v2-line-2);
  border-radius: 8px;
  cursor: text;
  transition: border-color .12s, box-shadow .12s;
}
.v2-ms.is-focused .v2-ms-control,
.v2-ms.is-open .v2-ms-control {
  border-color: var(--v2-brand);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); /* same ring as .v2-form-input:focus */
}
.v2-ms-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  flex: 1;
  min-width: 0;
}
.v2-ms-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  max-width: 100%;
  padding: 0 4px 0 9px;
  font-size: 13px;
  color: var(--v2-ink);
  background: var(--v2-surface-2);
  border: 1px solid var(--v2-line);
  border-radius: var(--v2-r-md);
  white-space: nowrap;
}
.v2-ms-chip-label {
  overflow: hidden;
  text-overflow: ellipsis;
}
.v2-ms-chip-remove {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  padding: 0;
  border: none;
  border-radius: var(--v2-r-sm);
  background: transparent;
  color: var(--v2-ink-3);
  cursor: pointer;
}
.v2-ms-chip-remove:hover {
  background: var(--v2-hover-strong);
  color: var(--v2-ink);
}
.v2-ms-more {
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 8px;
  font-size: 12.5px;
  color: var(--v2-ink-3);
  border: 1px dashed var(--v2-line-2);
  border-radius: var(--v2-r-md);
}
.v2-ms-input {
  flex: 1;
  min-width: 80px;
  height: 26px;
  padding: 0 6px;
  font-family: inherit;
  font-size: 13.5px;
  color: var(--v2-ink);
  background: transparent;
  border: none;
  outline: none;
}
.v2-ms-input::placeholder {
  color: var(--v2-ink-4);
}
.v2-ms-chevron {
  position: absolute;
  right: 12px;
  top: 50%;
  margin-top: -6px;
  color: var(--v2-ink-3);
  pointer-events: none;
  transition: transform .12s;
}
.v2-ms.is-open .v2-ms-chevron {
  transform: rotate(180deg);
}
.v2-ms-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 60;
  background: var(--v2-bg);
  border: 1px solid var(--v2-line-2);
  border-radius: 8px;
  overflow: hidden;
}
/* Opened upward when there is no room below (see place() in the JS). */
.v2-ms.is-up .v2-ms-menu {
  top: auto;
  bottom: calc(100% + 4px);
}
.v2-ms-menu[hidden] {
  display: none;
}
.v2-ms-list {
  max-height: 284px;
  overflow-y: auto;
  padding: 4px;
}
.v2-ms-option {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 36px;
  padding: 0 10px;
  font-size: 13.5px;
  color: var(--v2-ink);
  border-radius: var(--v2-r-md);
  cursor: pointer;
  user-select: none;
}
.v2-ms-option[hidden] {
  display: none;
}
.v2-ms-option.is-active {
  background: var(--v2-brand-bg);
}
.v2-ms-option[aria-disabled="true"] {
  color: var(--v2-ink-4);
  cursor: not-allowed;
}
.v2-ms-check {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  color: #fff;
  background: var(--v2-bg);
  border: 1px solid var(--v2-line-2);
  border-radius: var(--v2-r-sm);
}
.v2-ms-check svg {
  visibility: hidden;
}
.v2-ms-option[aria-selected="true"] .v2-ms-check {
  background: var(--v2-brand);
  border-color: var(--v2-brand);
}
.v2-ms-option[aria-selected="true"] .v2-ms-check svg {
  visibility: visible;
}
.v2-ms-option-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.v2-ms-create svg {
  color: var(--v2-ink-3);
  flex-shrink: 0;
}
.v2-ms-create.is-failed {
  color: var(--v2-danger);
}
.v2-ms-create-failed {
  display: none;
}
.v2-ms-create.is-failed .v2-ms-create-failed {
  display: inline;
}
.v2-ms-empty {
  padding: 10px;
  font-size: 13px;
  color: var(--v2-ink-3);
}
.v2-ms-empty[hidden] {
  display: none;
}
.v2-ms-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 14px;
  border-top: 1px solid var(--v2-line);
}
.v2-ms-count {
  font-size: 12.5px;
  color: var(--v2-ink-3);
}
.v2-ms-clear {
  padding: 0;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--v2-ink);
  background: transparent;
  border: none;
  cursor: pointer;
}
.v2-ms-clear:disabled {
  color: var(--v2-ink-4);
  cursor: default;
}

/* size="sm" — 30px, for toolbars and table rows */
.v2-ms-sm .v2-ms-control {
  min-height: 30px;
  padding-top: 2px;
  padding-bottom: 2px;
}
.v2-ms-sm .v2-ms-chip,
.v2-ms-sm .v2-ms-more,
.v2-ms-sm .v2-ms-input {
  height: 22px;
  font-size: 12.5px;
}
.v2-ms-sm .v2-ms-option {
  height: 32px;
  font-size: 13px;
}

/* error — same tokens as Input */
.v2-ms-error .v2-ms-control,
.v2-ms-error.is-focused .v2-ms-control,
.v2-ms-error.is-open .v2-ms-control {
  border-color: var(--v2-danger);
  box-shadow: 0 0 0 3px rgba(185, 28, 28, 0.1);
}
.v2-ms-error-text {
  margin-top: 6px;
  font-size: 12.5px;
  color: var(--v2-danger);
}

/* disabled — closed, read-only */
.v2-ms-disabled .v2-ms-control {
  background: var(--v2-surface-2);
  cursor: default;
}
.v2-ms-disabled .v2-ms-chip {
  padding-right: 9px;
  background: var(--v2-bg);
}
.v2-ms-disabled .v2-ms-chevron {
  color: var(--v2-ink-4);
}


/* Read-only category badges (template "v2-category-tags"): shared badge — gray
   dot, fully rounded border, standard text size. */
.v2-ms-tags {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.v2-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 10px;
  font-size: 12.5px;
  color: var(--v2-ink-2);
  background: var(--v2-bg);
  border: 1px solid var(--v2-line-2);
  border-radius: 999px;
  white-space: nowrap;
}
.v2-tag-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--v2-ink-3);
  flex-shrink: 0;
}

/* Labelled data row for detail pages (label column + value), e.g. Categoria */
.v2-detail-field {
  display: grid;
  grid-template-columns: 200px 1fr;
  align-items: baseline;
  gap: 16px;
  padding: 10px 0;
  border-top: 1px solid var(--v2-line);
}
/* The border separates a row from the rows above it; a row that opens its
   block (worksheet/quote main tab) has nothing above to separate from. */
.v2-detail-field:first-child {
  border-top: none;
}
.v2-detail-field-label {
  font-size: 12.5px;
  color: var(--v2-ink-3);
}
@media (max-width: 640px) {
  .v2-detail-field {
    grid-template-columns: 1fr;
    gap: 6px;
  }
}

/* Category badges in table cells: enough width to sit side by side instead
   of one badge per line. */
td:has(> .v2-ms-tags) {
  min-width: 200px;
}

/* ── Marcatempo (worksheet tab "Marcatempo", docs/plans/marcatempo.md) ──
   Built on the V2 primitives: actions are .v2-btn (primary = brand blue),
   the empty state is .v2-empty-state, status is dot + text. Brand blue marks
   "running"; good / warn / danger keep their semantic meaning only (Resa,
   forgotten timer, delete). No shadows, no tinted surfaces. */

.v2-mt-num { font-variant-numeric: tabular-nums; }
.v2-mt-mute { color: var(--v2-ink-3); }

/* Status: dot + text; a pulsing dot = live */
.v2-mt-st { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 500; white-space: nowrap; }
.v2-mt-st i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.v2-mt-st.good { color: var(--v2-good); }
.v2-mt-st.warn { color: var(--v2-warn); }
.v2-mt-st.danger { color: var(--v2-danger); }
.v2-mt-st.brand { color: var(--v2-brand); }
.v2-mt-st.ink-3 { color: var(--v2-ink-3); }
.v2-mt-st.live i { animation: v2MtPulse 1.6s ease-in-out infinite; }
@keyframes v2MtPulse { 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .v2-mt-st.live i { animation: none; } }
.v2-mt-tone-good, .v2-mt-kpi .v.v2-mt-tone-good { color: var(--v2-good); }
.v2-mt-tone-warn, .v2-mt-kpi .v.v2-mt-tone-warn { color: var(--v2-warn); }
.v2-mt-tone-danger, .v2-mt-kpi .v.v2-mt-tone-danger { color: var(--v2-danger); }
.v2-mt-tone-ink-3 { color: var(--v2-ink); }
.v2-tab .v2-mt-live-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; margin-left: 6px; vertical-align: middle; background: var(--v2-brand); }

/* Top-bar pill: your running timer on every page (marcatempo-pill.html).
   Hairline + brand clock while running; a forgotten timer turns warn. */
.v2-mt-pill-slot:empty { display: none; }
.v2-mt-pill { display: flex; align-items: center; gap: 4px; height: 32px; padding: 0 3px 0 10px; border: 1px solid var(--v2-line-2); border-radius: 99px; background: var(--v2-bg); }
.v2-mt-pill.forgot { border-color: var(--v2-warn); }
.v2-mt-pill-link { display: flex; align-items: center; gap: 8px; min-width: 0; color: var(--v2-ink); text-decoration: none; }
.v2-mt-pill-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; background: var(--v2-brand); animation: v2MtPulse 1.6s ease-in-out infinite; }
.v2-mt-pill-clock { font-size: 13px; font-weight: 600; color: var(--v2-brand); font-variant-numeric: tabular-nums; }
.v2-mt-pill-plate { font-size: 12px; font-weight: 500; color: var(--v2-ink-3); letter-spacing: .02em; white-space: nowrap; }
.v2-mt-pill.forgot .v2-mt-pill-dot { background: var(--v2-warn); animation: none; }
.v2-mt-pill.forgot .v2-mt-pill-clock { color: var(--v2-warn); }
.v2-mt-pill-stop { width: 24px; height: 24px; flex: none; display: grid; place-items: center; padding: 0; border: none; border-radius: 50%; background: var(--v2-brand); color: #fff; cursor: pointer; }
.v2-mt-pill-stop:hover { background: var(--v2-brand-2); }
.v2-mt-pill-stop:disabled { opacity: .6; cursor: default; }
.v2-mt-pill.forgot .v2-mt-pill-stop { background: var(--v2-warn); }
.v2-mt-pill-stop svg { width: 11px; height: 11px; }
@media (prefers-reduced-motion: reduce) { .v2-mt-pill-dot { animation: none; } }
@media (max-width: 639px) {
  .v2-mt-pill { height: 40px; padding: 0 4px 0 12px; }
  .v2-mt-pill-plate { display: none; }
  .v2-mt-pill-stop { width: 32px; height: 32px; }
  .v2-mt-pill-stop svg { width: 13px; height: 13px; }
}

/* The timer action: a .v2-btn sized for a workshop (gloves, phone) */
.v2-btn.v2-mt-cta { height: 48px; padding: 0 22px; font-size: 15px; justify-content: center; min-width: 160px; }
.v2-btn.v2-mt-cta svg { width: 16px; height: 16px; }
.v2-btn.v2-mt-cta-sm { height: 40px; padding: 0 16px; font-size: 14px; justify-content: center; }

/* Sections */
.v2-mt-sec { padding-top: 32px; }
.v2-mt-sec-h { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; min-height: 24px; flex-wrap: wrap; }
.v2-mt-sec-h h2 { margin: 0; font-size: 11px; font-weight: 600; color: var(--v2-ink-3); letter-spacing: .06em; text-transform: uppercase; }
.v2-mt-sec-h p { margin: 0; font-size: 12.5px; color: var(--v2-ink-3); flex-basis: 100%; }
.v2-mt-sec-h .r { margin-left: auto; display: flex; gap: 6px; align-items: center; }
.v2-mt-count { font-size: 12px; color: var(--v2-ink-4); }

/* Timers: unboxed, like the worksheet header's KPI row. State is carried by
   hierarchy and colour, never by a box or a coloured border: the running
   clock is brand blue (as the header's "Lavorazione" status), idle is ink-4,
   a forgotten one is warn. The forgotten form is a .v2-notice-warn. */
.v2-mt-timers { padding-top: 28px; }
.v2-mt-col { display: grid; gap: 24px; align-content: start; }
.v2-mt-tc { display: grid; gap: 14px; }
.v2-mt-tc + .v2-mt-tc { padding-top: 24px; border-top: 1px solid var(--v2-line); }
.v2-mt-tc-h { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.v2-mt-tc-h h2 { margin: 0; font-size: 11px; font-weight: 600; color: var(--v2-ink-3); letter-spacing: .06em; text-transform: uppercase; }
.v2-mt-tc-h .r { margin-left: auto; }
.v2-mt-clock { font-size: 48px; line-height: 1; font-weight: 500; letter-spacing: -.03em; color: var(--v2-ink-4); font-variant-numeric: tabular-nums; }
.v2-mt-tc.run .v2-mt-clock { color: var(--v2-brand); }
.v2-mt-tc.forgot .v2-mt-clock { color: var(--v2-warn); }
/* An Attesa timer is the worksheet's, not anyone's work: neutral, not brand. */
.v2-mt-tc.wait.run .v2-mt-clock { color: var(--v2-ink-2); }
.v2-mt-tc.compact .v2-mt-clock { font-size: 28px; }
.v2-mt-tc-row { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.v2-mt-tc-row .acts { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.v2-mt-tc-sub { font-size: 13px; color: var(--v2-ink-3); }
.v2-mt-tc-sub b { color: var(--v2-ink-2); font-weight: 500; }

/* One-off messages are the standard .v2-notice */
.v2-mt .v2-notice { margin-top: 24px; }
.v2-mt-forgot-f { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; margin-top: 10px; }
.v2-mt-forgot-acts { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.v2-mt-who { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 13px; }
.v2-mt-chip { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--v2-ink-2); }
.v2-mt-chip .v2-mt-num { color: var(--v2-brand); font-weight: 500; }
/* Initials avatar: same look as the top-bar avatar */
.v2-mt-av { width: 24px; height: 24px; border-radius: 99px; display: inline-grid; place-items: center; font-size: 10px; font-weight: 600; color: #fff; background: var(--v2-brand); flex: none; }
.v2-mt-pname { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }

/* KPIs: same scale as the worksheet header row */
.v2-mt-kpis { display: flex; gap: 16px 56px; flex-wrap: wrap; }
.v2-mt-kpi .l { font-size: 12px; color: var(--v2-ink-3); margin-bottom: 4px; }
.v2-mt-kpi .v { font-size: 22px; font-weight: 600; letter-spacing: -.02em; font-variant-numeric: tabular-nums; color: var(--v2-ink); }
.v2-mt-kpi .h { font-size: 12px; color: var(--v2-ink-3); margin-top: 3px; }
.v2-mt-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 40px; }

/* Tables inside the tab are v2-table v2-table-fit v2-table-static. */
.v2-mt .v2-table td.v2-item-cell-actions { width: 1%; white-space: nowrap; }
.v2-mt .v2-table tr.run > td { background: var(--v2-brand-bg); }
.v2-mt-ellipsis { max-width: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Sessions on phones */
.v2-mt-mlist { display: none; }
.v2-mt-mrow { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 10px; padding: 12px 0; border-bottom: 1px solid var(--v2-line); align-items: center; }
.v2-mt-mrow:first-child { border-top: 1px solid var(--v2-line); }
.v2-mt-mrow .a { display: flex; align-items: center; gap: 8px; font-weight: 500; font-size: 13px; color: var(--v2-ink); }
.v2-mt-mrow .b { font-size: 12.5px; color: var(--v2-ink-3); }
.v2-mt-mrow .d { grid-row: 1 / 3; grid-column: 2; display: flex; align-items: center; gap: 2px; font-size: 13px; }

/* Billed lines */
.v2-mt-lines { display: grid; }
.v2-mt-line { display: flex; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--v2-line); align-items: baseline; font-size: 13px; color: var(--v2-ink-2); }
.v2-mt-line:first-child { border-top: 1px solid var(--v2-line); }
.v2-mt-line span:first-child { flex: 1; min-width: 0; }
.v2-mt-line .v2-mt-num { font-size: 12.5px; white-space: nowrap; }
.v2-mt-line .hrs { min-width: 96px; text-align: right; }
.v2-mt-line.flat { color: var(--v2-ink-3); }

/* Empty state = .v2-empty-state; only the spacing of its two actions */
.v2-mt-empty { margin-top: 24px; }
.v2-mt-empty .v2-mt-empty-actions { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.v2-mt-empty .v2-mt-empty-actions .v2-btn { justify-content: center; }
/* The text action keeps its own width (and the tertiary negative margin) on every screen. */
.v2-mt-empty .v2-mt-empty-actions .v2-btn-tertiary { align-self: center; margin-top: 4px; }

/* Dialog bits */
.v2-mt-g2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.v2-mt-g3 { display: grid; grid-template-columns: 1.3fr 1fr 1fr; gap: 12px; }
.v2-mt-field { display: flex; flex-direction: column; min-width: 0; }
/* The grids set display, which beats the [hidden] attribute the dialog toggles. */
.v2-mt-g2[hidden], .v2-mt-g3[hidden], .v2-mt-field[hidden] { display: none; }
.v2-mt-hint { font-size: 12px; color: var(--v2-ink-3); }

@media (max-width: 860px) {
  .v2-mt-cols { grid-template-columns: 1fr; gap: 0; }
}
@media (max-width: 639px) {
  .v2-mt-timers { padding-top: 20px; }
  .v2-mt-clock { font-size: 44px; }
  .v2-mt-tc-row { flex-direction: column; align-items: stretch; gap: 12px; }
  /* Primary first on a phone: the markup puts the ghost action before it for desktop. */
  .v2-mt-tc-row .acts { margin-left: 0; flex-direction: column-reverse; align-items: stretch; gap: 4px; }
  .v2-mt-tc-row .acts .v2-btn, .v2-mt-empty .v2-mt-cta { width: 100%; height: 56px; }
  .v2-mt-empty .v2-mt-empty-actions { align-items: stretch; }
  .v2-mt-forgot-f > * { flex: 1 1 100%; }
  .v2-mt-kpis { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
  .v2-mt-kpi .v { font-size: 19px; }
  .v2-mt-hide-m { display: none !important; }
  .v2-mt-mlist { display: block; }
  .v2-mt-mrow .v2-btn-icon-inline { width: 44px; height: 44px; justify-content: center; }
  .v2-mt-g2, .v2-mt-g3 { grid-template-columns: 1fr; }
}

/* ── Report v2 (docs/plans/report-v2.md §14) ─────────────────────────
   Cards on a 12-column grid: S/M/L = span 3/6/12 (plus 4 and 8). Every card:
   title · basis (the date it groups by) · optional info · body · optional
   hint (soft-panel unlock line) · optional footer link. No shadows. */
.v2-rp-tabs { margin-top: 24px; }
.v2-rp-filter { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding-top: 18px; }
.v2-rp-filter-note { font-size: 12.5px; color: var(--v2-ink-3); }
.v2-rp-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 16px; margin-top: 20px; padding-bottom: 48px; }
.v2-rp-grid > * { min-width: 0; }
.v2-rp-span-3 { grid-column: span 3; }
.v2-rp-span-4 { grid-column: span 4; }
.v2-rp-span-6 { grid-column: span 6; }
.v2-rp-span-8 { grid-column: span 8; }
.v2-rp-span-12 { grid-column: span 12; }
.v2-rp-card { display: flex; flex-direction: column; background: var(--v2-bg); border: 1px solid var(--v2-line); border-radius: var(--v2-r-lg); }
.v2-rp-card-head { display: flex; align-items: flex-start; gap: 12px; padding: 18px 20px 0; }
.v2-rp-card-titles { flex: 1; min-width: 0; }
.v2-rp-card-title { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 14px; font-weight: 600; color: var(--v2-ink); letter-spacing: -0.005em; }
.v2-rp-basis { margin-top: 3px; font-size: 12px; color: var(--v2-ink-3); }
.v2-rp-card-actions { display: flex; gap: 8px; align-items: center; flex-shrink: 0; }
.v2-rp-card-body { flex: 1; min-width: 0; padding: 18px 20px; }
.v2-rp-card-foot { border-top: 1px solid var(--v2-line); padding: 11px 20px; }
.v2-rp-link { display: inline-flex; align-items: center; gap: 4px; font-size: 12.5px; font-weight: 500; color: var(--v2-ink-2); text-decoration: none; }
.v2-rp-link:hover { color: var(--v2-ink); text-decoration: underline; text-underline-offset: 3px; }
.v2-rp-link::after { content: "›"; color: var(--v2-ink-3); font-size: 14px; line-height: 1; }
.v2-rp-hint { margin-top: 16px; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; font-size: 12.5px; line-height: 1.5; color: var(--v2-ink-3); }
.v2-rp-hint a { color: var(--v2-brand); font-weight: 500; text-decoration: none; }
.v2-rp-hint a:hover { text-decoration: underline; text-underline-offset: 3px; }
.v2-rp-empty-line { padding: 24px 0; font-size: 13px; color: var(--v2-ink-4); text-align: center; }
.v2-rp-note { margin-top: 10px; font-size: 12.5px; color: var(--v2-ink-3); }
.v2-rp-note b { color: var(--v2-ink); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Info: hover/focus popover, bordered, no shadow. */
.v2-rp-info { position: relative; display: inline-grid; place-items: center; width: 18px; height: 18px; cursor: help; color: var(--v2-ink-4); }
.v2-rp-info:hover, .v2-rp-info:focus { color: var(--v2-ink-2); outline: none; }
.v2-rp-info svg { width: 14px; height: 14px; }
.v2-rp-info::after { content: attr(data-tip); display: none; position: absolute; top: 24px; left: -8px; z-index: 20; width: 260px; padding: 10px 12px; background: var(--v2-bg); border: 1px solid var(--v2-line-2); border-radius: var(--v2-r-lg); font-size: 12.5px; font-weight: 400; line-height: 1.5; color: var(--v2-ink-2); white-space: normal; text-align: left; letter-spacing: 0; }
.v2-rp-info:hover::after, .v2-rp-info:focus::after { display: block; }

/* KPI band: one surface, cells split by hairlines. */
.v2-rp-kpis { grid-column: span 12; display: grid; grid-template-columns: repeat(var(--v2-rp-cols, 4), minmax(0, 1fr)); background: var(--v2-bg); border: 1px solid var(--v2-line); border-radius: var(--v2-r-lg); }
.v2-rp-kpi { display: flex; flex-direction: column; min-width: 0; padding: 18px 20px; border-left: 1px solid var(--v2-line); }
.v2-rp-kpi:first-child { border-left: none; }
.v2-rp-kpi-label { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; color: var(--v2-ink); }
.v2-rp-kpi-value { margin-top: 14px; font-size: 26px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.1; color: var(--v2-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.v2-rp-kpi-delta { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 0 6px; align-items: baseline; font-size: 12px; }
.v2-rp-kpi-delta span:first-child { font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
.v2-rp-kpi-delta span:last-child { color: var(--v2-ink-4); }
.v2-rp-kpi-sub { margin-top: 6px; font-size: 12.5px; color: var(--v2-ink-3); }
.v2-rp-tone-good { color: var(--v2-good) !important; }
.v2-rp-tone-warn { color: var(--v2-warn) !important; }
.v2-rp-tone-danger { color: var(--v2-danger) !important; }
.v2-rp-tone-muted { color: var(--v2-ink-2) !important; }

/* Section heading inside the grid. */
.v2-rp-section-head { grid-column: span 12; padding-top: 20px; }
.v2-rp-section-head h2 { margin: 0; font-size: 15px; font-weight: 600; color: var(--v2-ink); }
.v2-rp-section-head p { margin: 4px 0 0; font-size: 13px; color: var(--v2-ink-3); }
.v2-rp-subgrid { grid-column: span 12; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 16px; }

/* Legend. */
.v2-rp-legend { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-bottom: 12px; font-size: 12px; color: var(--v2-ink-3); }
.v2-rp-legend span { display: inline-flex; align-items: center; gap: 6px; }
.v2-rp-legend i { display: inline-block; width: 9px; height: 9px; border-radius: 2px; }
.v2-rp-legend i.line { width: 12px; height: 2px; }

/* Ranked horizontal bars. */
.v2-rp-bars { display: grid; grid-template-columns: minmax(0, 38%) minmax(0, 1fr) auto; align-items: center; gap: 12px; }
.v2-rp-bars-label { min-width: 0; font-size: 12.5px; color: var(--v2-ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-decoration: none; }
a.v2-rp-bars-label:hover { color: var(--v2-ink); text-decoration: underline; text-underline-offset: 3px; }
.v2-rp-bars-label small { display: block; font-size: 11.5px; color: var(--v2-ink-4); }
.v2-rp-bars-track { position: relative; height: 8px; background: var(--v2-surface-2); border-radius: 4px; }
.v2-rp-bars-fill { height: 100%; border-radius: 4px; background: var(--v2-brand); }
.v2-rp-bars-fill.soft { background: #93b4f3; }
.v2-rp-bars-fill.warn { background: #f5c27a; }
.v2-rp-bars-fill.danger { background: #f0a3a3; }
.v2-rp-bars-value { min-width: 48px; text-align: right; font-size: 12.5px; font-weight: 500; color: var(--v2-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.v2-rp-bars-tick { position: absolute; left: calc(100% / 1.4); top: -3px; bottom: -3px; width: 1.5px; background: var(--v2-ink-2); }

/* Key/value rows. */
.v2-rp-rows { display: flex; flex-direction: column; }
.v2-rp-row { display: flex; align-items: baseline; gap: 12px; padding: 9px 0; border-top: 1px solid var(--v2-line); font-size: 12.5px; text-decoration: none; color: inherit; }
.v2-rp-row:first-child { border-top: none; }
.v2-rp-row-label { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; color: var(--v2-ink-2); }
.v2-rp-row-label small { display: block; font-size: 11.5px; color: var(--v2-ink-4); }
.v2-rp-row-label i { flex-shrink: 0; width: 9px; height: 9px; border-radius: 2px; }
.v2-rp-row-value { text-align: right; font-weight: 500; color: var(--v2-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.v2-rp-row-total { border-top: 1px solid var(--v2-ink-5); font-weight: 600; }

/* Big single figure. */
.v2-rp-big { font-size: 24px; font-weight: 600; letter-spacing: -0.02em; color: var(--v2-ink); font-variant-numeric: tabular-nums; }
.v2-rp-big-sub { margin-top: 6px; font-size: 12.5px; color: var(--v2-ink-3); }

/* Funnel. */
.v2-rp-funnel { display: flex; flex-direction: column; gap: 4px; }
.v2-rp-funnel-conv { padding: 2px 0 6px 2px; font-size: 11.5px; color: var(--v2-ink-4); }
.v2-rp-funnel-row { display: flex; align-items: center; gap: 12px; }
.v2-rp-funnel-track { flex: 1; min-width: 0; }
.v2-rp-funnel-bar { height: 30px; min-width: max-content; display: flex; align-items: center; padding: 0 10px; border-radius: var(--v2-r-md); font-size: 12.5px; font-weight: 500; white-space: nowrap; }
.v2-rp-shade-1 { background: #1d4ed8; color: #fff; }
.v2-rp-shade-2 { background: #2563eb; color: #fff; }
.v2-rp-shade-3 { background: #93b4f3; color: var(--v2-ink); }
.v2-rp-shade-4 { background: #cfdcf6; color: var(--v2-ink); }
.v2-rp-funnel-value { width: 48px; text-align: right; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }

/* Split bar. */
.v2-rp-split { display: flex; gap: 2px; height: 8px; margin-top: 14px; }
.v2-rp-split span { border-radius: 2px; }
.v2-rp-split .s1 { background: var(--v2-brand); }
.v2-rp-split .s2 { background: #93b4f3; }
.v2-rp-split .s3 { background: #cfdcf6; }
.v2-rp-split .s4 { background: var(--v2-ink-5); }
.v2-rp-split-legend { display: flex; justify-content: space-between; margin-top: 6px; font-size: 12px; color: var(--v2-ink-3); }
.v2-rp-split-legend b { color: var(--v2-ink); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Ghost chart for the hint state. */
.v2-rp-ghost { display: flex; align-items: flex-end; gap: 12px; height: 110px; }
.v2-rp-ghost span { flex: 1; background: var(--v2-surface-2); border: 1px solid var(--v2-line); border-radius: var(--v2-r-sm); }

/* Loading placeholder. */
.v2-rp-skel { min-height: 140px; background: var(--v2-surface-2); }
.v2-rp-skel-kpis { min-height: 112px; background: var(--v2-surface-2); }

/* Charts rendered by report-v2.js. */
.v2-rp-chart { min-height: 120px; }
.v2-rp-donut { display: flex; justify-content: center; margin-bottom: 8px; }

/* Waterfall (Situazione IVA). */
.v2-rp-waterfall { display: flex; align-items: stretch; gap: 10px; height: 210px; padding-top: 22px; }
.v2-rp-wf-col { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.v2-rp-wf-plot { position: relative; flex: 1; border-bottom: 1px solid var(--v2-line-2); }
.v2-rp-wf-bar { position: absolute; left: 18%; right: 18%; border-radius: 3px; background: var(--v2-brand); }
.v2-rp-wf-bar.down { background: #93b4f3; }
.v2-rp-wf-bar.total { background: var(--v2-ink-2); }
.v2-rp-wf-bar.strong { background: var(--v2-ink); }
.v2-rp-wf-value { position: absolute; left: -10px; right: -10px; text-align: center; font-size: 11px; font-weight: 600; color: var(--v2-ink); font-variant-numeric: tabular-nums; white-space: nowrap; transform: translateY(-16px); }
.v2-rp-wf-label { padding-top: 8px; text-align: center; font-size: 11px; color: var(--v2-ink-3); }
.v2-rp-iva { display: flex; flex-wrap: wrap; gap: 28px; align-items: flex-start; }
.v2-rp-iva > div { flex: 1 1 260px; min-width: 0; }
.v2-rp-topay { display: flex; align-items: baseline; gap: 12px; padding-top: 10px; border-top: 1px solid var(--v2-ink-5); }
.v2-rp-topay span:first-child { flex: 1; font-size: 13px; font-weight: 600; }
.v2-rp-topay span:last-child { font-size: 18px; font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.v2-rp-deadline { display: flex; gap: 12px; align-items: baseline; padding: 10px 0; border-top: 1px solid var(--v2-line); }
.v2-rp-deadline:first-child { border-top: none; }
.v2-rp-deadline-date { width: 84px; font-size: 12.5px; color: var(--v2-ink-2); font-variant-numeric: tabular-nums; }
.v2-rp-deadline.next .v2-rp-deadline-date { color: var(--v2-brand-2); font-weight: 600; }
.v2-rp-deadline-label { flex: 1; font-size: 12.5px; color: var(--v2-ink); }
.v2-rp-deadline-label small { display: block; font-size: 11.5px; color: var(--v2-ink-4); }
.v2-rp-check { display: flex; gap: 10px; align-items: flex-start; font-size: 12.5px; cursor: pointer; }
.v2-rp-check input { margin-top: 2px; accent-color: var(--v2-brand); }
.v2-rp-check small { display: block; font-size: 11.5px; color: var(--v2-ink-4); }
.v2-rp-form { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }

@media (max-width: 1023px) {
  .v2-rp-span-3 { grid-column: span 6; }
  .v2-rp-span-4, .v2-rp-span-8 { grid-column: span 12; }
}
@media (max-width: 639px) {
  .v2-rp-grid, .v2-rp-subgrid { gap: 12px; }
  .v2-rp-grid > *, .v2-rp-subgrid > * { grid-column: span 12 !important; }
  .v2-rp-kpis { --v2-rp-cols: 2 !important; }
  .v2-rp-kpi:nth-child(odd) { border-left: none; }
  .v2-rp-kpi:nth-child(n+3) { border-top: 1px solid var(--v2-line); }
  .v2-rp-kpi-value { font-size: 21px; }
  .v2-rp-card-head { flex-wrap: wrap; }
  .v2-rp-form { grid-template-columns: 1fr; }
}
/* Report v2 swatches (legend squares, list dots) — model.ReportSwatch. */
.v2-rp-sw-strong { background: #1d4ed8; }
.v2-rp-sw-brand { background: #2563eb; }
.v2-rp-sw-mid { background: #5e8be9; }
.v2-rp-sw-soft { background: #93b4f3; }
.v2-rp-sw-pale { background: #cfdcf6; }
.v2-rp-sw-paler { background: #dbeafe; }
.v2-rp-sw-ink { background: #1f2937; }
.v2-rp-sw-faint { background: #e5e7eb; }
.v2-rp-sw-muted { background: #d1d5db; }
