/* app.css — ConcordatoFacile design language (dark glassmorphism), aligned with the
   legacy GAS module and the chatbot (css_app.html).

   Rules of the system — hold these and the file stays coherent:
     · --space-N = 4N px. 0-5 (2px) and 1-5 (6px) are the only sub-4px named steps.
     · --shadow-* is the all-black elevation ramp; --shadow-accent-* is the tinted one.
     · Line-height and icon size are ramps DELIBERATELY SEPARATE from the type scale.
     · Every accent/semantic rgba() derives from the matching *-rgb triplet, so a
       re-brand can never leave a stray violet (or rose, or amber) glow behind.
     · NO backdrop-filter on anything in the scroll path — Chrome paints transient
       black rectangles over the content during slow scrolls.
     · @media cannot read custom properties: the --bp-* names below are DOCUMENTATION
       of the three canonical breakpoints; the literals in @media match them by hand.

   The nine brand tokens at the top are the ONLY ones applyAssocBranding (main.mjs)
   writes inline on <html> for ?assoc= white-labelling. Do not rename them, and derive
   every new token from them rather than replacing them. A [data-theme="light"] variant
   at the end of this file redefines the token layer, not the components. */

:root {
  /* ── brand surfaces — written inline by applyAssocBranding, do not rename ─────── */
  --accent: #8b5cf6;
  --accent-2: #a855f7;
  --accent-rgb: 139, 92, 246;
  --accent-2-rgb: 168, 85, 247;
  --brand-bg0: #070612;
  --brand-bg1: #0b0816;
  --panel: #111028;
  --panel-2: #141237;
  --panel-rgb: 17, 16, 40;

  /* derived accent tints */
  --accent-light: rgba(var(--accent-rgb), .14);
  --accent-border: rgba(var(--accent-rgb), .30);
  /* Readable accent ink over an accent TINT. --accent-2 is a fill colour: as small bold
     text on rgba(accent,.13) it fails WCAG AA, which Lighthouse catches on the progress
     badge. Same convention as --success-dark: *-dark is the legible one. */
  --accent-dark: #ddd0fe;

  /* ── ink and hairlines ────────────────────────────────────────────────────────── */
  --text: #f2f4ff;
  --text-secondary: rgba(242, 244, 255, .92);
  --muted: rgba(184, 184, 214, .78);
  --on-accent: #fff;              /* ink over an accent gradient, whatever the brand */
  --border: rgba(255, 255, 255, .12);
  --border-light: rgba(255, 255, 255, .07);
  /* the three neutral fills that recur across the file, as a scale rather than by hand */
  --surface-1: rgba(255, 255, 255, .04);
  --surface-2: rgba(255, 255, 255, .07);
  --surface-3: rgba(255, 255, 255, .10);

  /* ── semantic triads: *-light = tint fill, *-dark = readable ink, *-border = hairline
        The *-dark values are the pastels already in use, so the sweep is a no-op. ──── */
  --success: #22c55e;
  --success-rgb: 34, 197, 94;
  --success-light: rgba(var(--success-rgb), .14);
  --success-dark: #bbf7d0;
  --success-border: rgba(var(--success-rgb), .34);
  --warning: #fbbf24;
  --warning-rgb: 251, 191, 36;
  --warning-light: rgba(var(--warning-rgb), .14);
  --warning-dark: #fde68a;
  --warning-border: rgba(var(--warning-rgb), .34);
  --danger: #fb7185;
  --danger-rgb: 251, 113, 133;
  --danger-light: rgba(var(--danger-rgb), .14);
  --danger-dark: #fecdd3;
  --danger-border: rgba(var(--danger-rgb), .34);
  --info: #60a5fa;
  --info-rgb: 96, 165, 250;
  --info-light: rgba(var(--info-rgb), .12);
  --info-dark: #93c5fd;
  --info-border: rgba(var(--info-rgb), .30);

  --input-bg: rgba(15, 14, 39, .75);
  --input-bg-focus: rgba(15, 14, 39, .92);

  /* ── radii — 6 steps ──────────────────────────────────────────────────────────── */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-2xl: 20px;
  --radius-full: 9999px;

  /* ── spacing — --space-N = 4N px ──────────────────────────────────────────────── */
  --space-0-5: 2px;
  --space-1: 4px;
  --space-1-5: 6px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --stack-gap: var(--space-5);   /* gap between the page-level blocks (hero/cards) */

  /* ── three separate ramps: type, line-height, icon box ────────────────────────── */
  --fs-2xs: 11px;
  --fs-xs: 12px;
  --fs-sm: 13px;
  --fs-base: 15px;
  --fs-md: 16px;
  --fs-lg: 18px;
  --fs-xl: 22px;
  --lh-none: 1;
  --lh-tight: 1.3;
  --lh-snug: 1.4;
  --lh-normal: 1.5;
  --lh-relaxed: 1.6;
  --lh-loose: 1.7;
  --icon-xs: 14px;
  --icon-sm: 16px;
  --icon-md: 18px;
  --icon-lg: 20px;
  --icon-xl: 24px;

  /* ── control system — shared by buttons AND inputs ────────────────────────────── */
  --control-h-sm: 32px;
  --control-h-md: 40px;
  --control-h-lg: 48px;
  --control-min-touch: 44px;
  --control-pad-y: var(--space-2);
  --control-pad-x-sm: var(--space-2);
  --control-pad-x-md: var(--space-4);
  --control-pad-x-lg: var(--space-5);
  --iconbtn-sm: 32px;
  --iconbtn-md: 40px;
  --iconbtn-lg: 44px;

  /* ── button intent ────────────────────────────────────────────────────────────── */
  --btn-primary-bg: linear-gradient(135deg, var(--accent), var(--accent-2));
  --btn-secondary-bg: var(--panel);
  --btn-secondary-bg-hover: var(--panel-2);
  --btn-ghost-bg: var(--surface-1);
  --btn-ghost-bg-hover: var(--surface-3);
  --btn-outline-bg: rgba(var(--accent-rgb), .06);
  --btn-outline-bg-hover: rgba(var(--accent-rgb), .16);
  --btn-danger-bg: var(--danger-light);
  --btn-danger-bg-hover: rgba(var(--danger-rgb), .22);

  /* ── elevation ────────────────────────────────────────────────────────────────── */
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, .30);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, .40), 0 1px 2px rgba(0, 0, 0, .30);
  --shadow-md: 0 18px 45px rgba(0, 0, 0, .55);
  --shadow-lg: 0 22px 60px rgba(0, 0, 0, .6);
  --shadow-xl: 0 28px 70px rgba(0, 0, 0, .66);
  --shadow-accent-sm: 0 2px 6px rgba(var(--accent-rgb), .30);
  --shadow-accent-md: 0 12px 24px rgba(var(--accent-rgb), .24);

  --focus-ring: 0 0 0 .22rem rgba(var(--accent-rgb), .25);

  /* ── motion: two ramps plus four composites; every transition: uses one ───────── */
  --dur-instant: .12s;
  --dur-fast: .15s;
  --dur-base: .2s;
  --dur-slow: .35s;
  --dur-slower: .45s;
  --ease-standard: ease;
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --transition-control:
    transform var(--dur-instant) var(--ease-standard),
    filter var(--dur-instant) var(--ease-standard),
    box-shadow var(--dur-fast) var(--ease-standard),
    background var(--dur-fast) var(--ease-standard),
    border-color var(--dur-fast) var(--ease-standard);
  --transition-input:
    border-color var(--dur-fast) var(--ease-standard),
    box-shadow var(--dur-fast) var(--ease-standard),
    background var(--dur-fast) var(--ease-standard);
  --transition-tone:
    background var(--dur-base) var(--ease-standard),
    border-color var(--dur-base) var(--ease-standard),
    color var(--dur-base) var(--ease-standard);
  --transition-fade: opacity var(--dur-slower) var(--ease-standard);

  /* ── stacking: one ordered ladder, no bare integers left in the file ──────────── */
  --z-behind: -1;
  --z-base: 1;
  --z-raised: 2;
  --z-combobox: 20;
  --z-listbox: 40;
  --z-progress: 60;
  --z-dock: 70;
  --z-header: 80;
  --z-tour: 90;
  --z-overlay: 100;

  /* ── layout ───────────────────────────────────────────────────────────────────── */
  --page-max: 980px;
  --header-max: 1180px;
  --header-h: 64px;
  --header-h-compact: 56px;
  /* Canonical breakpoints, documentation only (@media cannot read a custom property):
     480px, 640px, 1220px, and 64rem for the app shell. The last is deliberately in rem —
     it tracks the reader's font size — and public/js/main.mjs repeats it verbatim in
     PRACTICE_SIDEBAR_DOCKED_QUERY, so the two must be edited together. */

  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);

  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, Roboto, sans-serif;
  /* headings only; h1,h2,h3 already read this token (see the base rule below) */
  --font-display: "Space Grotesk", "Inter", -apple-system, BlinkMacSystemFont, sans-serif;

  font-size: 16px;
  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font-sans);
  background: var(--brand-bg0);
  color: var(--text);
  font-size: var(--fs-base);
  line-height: var(--lh-relaxed);
  letter-spacing: -.01em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100dvh;
  overflow-x: hidden;
}
/* ambient glows, fixed so long forms keep the mood while scrolling (legacy body::before).
   translateZ(0) keeps this fixed layer permanently composited: without it Chrome
   repaints it mid-scroll and can flash black rectangles over the content. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: var(--z-behind);
  transform: translateZ(0);
  will-change: transform;
  background:
    radial-gradient(ellipse 90% 55% at 15% 8%, rgba(var(--accent-rgb), .18), transparent),
    radial-gradient(ellipse 70% 50% at 88% 18%, rgba(var(--accent-2-rgb), .13), transparent),
    radial-gradient(ellipse 60% 40% at 50% 85%, rgba(var(--accent-rgb), .08), transparent),
    linear-gradient(180deg, var(--brand-bg1), var(--brand-bg0) 40%);
}

h1, h2, h3 { font-family: var(--font-display); letter-spacing: -.02em; margin: 0; }
a { color: var(--accent-2); }
a:hover { filter: brightness(1.12); }

/* ── floating progress orb (replaced the sticky bar, user decision 2026-08-06) ─
   Fixed overlay, bottom-LEFT: the AI dock owns bottom-right (and the whole bottom
   strip on phones — see the :has() lift below). Opaque panel, NO backdrop-filter:
   a blurred fixed layer over the scroll path is the Chrome black-rectangle bug. */
.progress-orb {
  position: fixed;
  left: calc(var(--space-4) + var(--safe-left));
  bottom: calc(var(--space-4) + var(--safe-bottom));
  z-index: var(--z-progress);
}
.progress-orb[hidden] { display: none; }
/* phones: the AI dock stretches edge to edge while visible (and sits at a higher
   z-index), so the orb climbs above it instead of disappearing underneath */
@media (max-width: 640px) {
  body:has(#aiLaneDock:not([hidden])) .progress-orb {
    bottom: calc(var(--space-4) + var(--safe-bottom) + 72px);
  }
}
.progress-orb__btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 56px;                       /* > --control-min-touch on every viewport */
  height: 56px;
  min-width: var(--control-min-touch);
  min-height: var(--control-min-touch);
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--panel);
  box-shadow: var(--shadow-md);
  color: var(--text);
  cursor: pointer;
}
.progress-orb__btn:hover { border-color: rgba(var(--accent-2-rgb), .5); }
.progress-orb__btn:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }
.progress-orb__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);          /* 0% starts at 12 o'clock */
}
.progress-orb__track {
  fill: none;
  stroke: rgba(255, 255, 255, .08);
  stroke-width: 4;
}
/* r=20 in a 48 viewBox: circumference 2π·20 ≈ 125.66. The offset is declarative from
   --orb-pct, so the reduced-motion resting state is already correct with the
   transition removed — the ring simply snaps. */
.progress-orb__ring {
  fill: none;
  stroke: var(--accent-2);
  stroke-width: 4;
  stroke-linecap: round;
  stroke-dasharray: 125.66;
  stroke-dashoffset: calc(125.66px * (100 - var(--orb-pct, 0)) / 100);
  transition: stroke-dashoffset var(--dur-slow) var(--ease-standard),
    stroke var(--dur-slow) var(--ease-standard);
}
.progress-orb__value {
  position: relative;
  font-size: var(--fs-2xs);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
/* full ring = «posso inviare»; a «Non so» budget overrun outranks the celebration,
   so --warn is declared after --done and wins when both apply */
.progress-orb--done .progress-orb__ring { stroke: var(--success); }
.progress-orb--done .progress-orb__value { color: var(--success); }
.progress-orb--warn .progress-orb__ring { stroke: var(--warning); }
.progress-orb--warn .progress-orb__value { color: var(--warning); }

/* tap/click popover: the carriers the old bar held beside the ring */
.progress-popover {
  position: absolute;
  left: 0;
  bottom: calc(100% + var(--space-2));
  width: min(20rem, calc(100vw - 2 * var(--space-4) - var(--safe-left) - var(--safe-right)));
  display: grid;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);           /* opaque; NO backdrop-filter */
  box-shadow: var(--shadow-lg);
}
.progress-popover[hidden] { display: none; }
.progress-track {
  flex: 1;
  height: 8px;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, .08);
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  width: 0%;
  border-radius: var(--radius-full);
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width var(--dur-slow) var(--ease-standard);
}
.progress-label {
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* milestone microcopy: an ambient transient pill beside the orb — a latched one-shot
   reward inside the closed popover would fire unseen. Shown/hidden via timers in
   main.mjs, never via transitionend (reduced-motion kills transitions and the event
   never fires); opacity keeps it in the a11y tree so role=status keeps announcing. */
.progress-milestone {
  position: absolute;
  left: calc(100% + var(--space-2));
  bottom: var(--space-1);
  width: max-content;
  max-width: min(19rem, calc(100vw - 7rem));
  margin: 0;
  padding: var(--space-1-5) var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--panel);
  box-shadow: var(--shadow-sm);
  font-size: var(--fs-xs);
  line-height: var(--lh-snug);
  color: var(--text-secondary);
  opacity: 0;
  transition: var(--transition-fade);
  pointer-events: none;
}
.progress-milestone.is-visible { opacity: 1; }

/* «Non so» budget line, inside the popover. While the popover is closed the ambient
   signal for an overrun is the --warn ring tint on the orb. */
.progress-unknown {
  margin: 0;
  font-size: var(--fs-xs);
  line-height: var(--lh-snug);
  color: var(--text-secondary);
}
.progress-unknown[hidden] { display: none; }
.progress-unknown--over { color: var(--warning); }

/* discreet one-shot milestone glow on the orb; classes are removed by timer. The
   resting --shadow-md stays inside the keyframes so the glow layers over it
   instead of blinking it off for the duration. */
.progress-orb__btn--milestone { animation: milestoneGlow 2.4s ease-out; }
.progress-orb__btn--milestone-success { animation: milestoneGlowSuccess 2.4s ease-out; }
@keyframes milestoneGlow {
  0%, 15% { box-shadow: var(--shadow-md), 0 0 18px rgba(var(--accent-2-rgb), .65); }
  100% { box-shadow: var(--shadow-md), 0 0 0 rgba(var(--accent-2-rgb), 0); }
}
@keyframes milestoneGlowSuccess {
  0%, 15% { box-shadow: var(--shadow-md), 0 0 18px rgba(var(--success-rgb), .6); }
  100% { box-shadow: var(--shadow-md), 0 0 0 rgba(var(--success-rgb), 0); }
}

/* ── app header (sticky, full width; chatbot parity) ─────────────────────────
   OPAQUE on purpose. The chatbot frosts its header with backdrop-filter; here that
   is banned — a blurred sticky element in the scroll path is exactly what made
   Chrome paint transient black rectangles (see .progress-orb, .ai-lane-dock).
   Because the property is never declared, no @supports fallback is needed either. */
.app-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: var(--panel);
  border-bottom: 1px solid var(--border-light);
  box-shadow: var(--shadow-sm);
  padding-top: var(--safe-top);
  padding-left: var(--safe-left);
  padding-right: var(--safe-right);
}
.app-header__inner {
  position: relative;
  width: min(var(--header-max), 100%);
  height: var(--header-h);
  margin: 0 auto;
  padding: 0 var(--space-4);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* The partner identity is out of flow so the nav stays centred against the viewport
   rather than being pushed by a brand string of unpredictable length. It appears only
   on genuinely wide screens; below that the <h1> in the hero carries the product name. */
.app-header__branding {
  position: absolute;
  left: var(--space-5);
  top: 50%;
  transform: translateY(-50%);
  display: none;
  align-items: center;
  min-width: 0;
  max-width: 280px;
}
.app-header__actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-width: 0;
  max-width: 100%;
}
.header-btn { text-decoration: none; white-space: nowrap; }
.header-btn-emoji { font-size: var(--icon-sm); line-height: var(--lh-none); flex: 0 0 auto; }
.brand-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  font-weight: 800;
  letter-spacing: .2px;
  color: var(--text);
  text-decoration: none;
  font-size: var(--fs-base);
}
.brand-link:hover { color: var(--accent-2); }
.brand-link > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.brand-home-emoji { font-size: 1.2rem; line-height: var(--lh-none); flex: 0 0 auto; }
.legal-link {
  color: rgba(var(--accent-2-rgb), .95);
  border-color: rgba(var(--accent-rgb), .28);
  background: rgba(var(--accent-rgb), .08);
}
.legal-link:hover { filter: brightness(1.08); color: rgba(var(--accent-2-rgb), .95); }
.practice-auth-trigger { color: var(--text-secondary); white-space: nowrap; }

/* 1220px is the canonical wide breakpoint: below it the absolutely-positioned brand
   would collide with the centred nav, so it is dropped rather than crowded. */
@media (min-width: 1220px) {
  .app-header__branding { display: flex; }
}
@media (max-width: 640px) {
  .app-header__inner { height: var(--header-h-compact); padding: 0 var(--space-2); }
  .app-header__actions { gap: var(--space-1-5); }
}
/* Below 480px the EMOJIS go, never the words. The label-hiding version of this rule
   was copied from the chatbot, where every header button carries a distinctive emoji;
   here the auth trigger has only a state dot, so a phone showed a dot, a compass and
   scales with no words — on the page's only navigation (hit live 2026-08-06). The dot
   survives because it is state, not decoration. The auth label may ellipsize so the
   rare long 'non disponibile' string cannot push the other controls off a 320px screen;
   the other two labels are short constants and never truncate. */
@media (max-width: 480px) {
  .app-header__actions .header-btn-emoji { display: none; }
  .app-header__actions { gap: var(--space-1); }
  .app-header__actions .btn { padding-inline: var(--space-2); }
  .app-header__actions .btn-label { font-size: var(--fs-xs); }
  .practice-auth-trigger { min-width: 0; }
  .practice-auth-trigger .btn-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
}
/* «Area personale · Tutorial · Note Legali» needs ~326px of track at the paddings above,
   so on a 320px phone the PRIMARY label ellipsized. Tighter padding, never fewer words. */
@media (max-width: 360px) {
  .app-header__actions .btn { padding-inline: var(--space-1-5); }
}
/* The dot carries identity state so the label can stay a stable destination name. It is
   never the ONLY signal: the button's aria-label says the same thing in words. */
.practice-auth-dot {
  width: .55rem;
  height: .55rem;
  flex: none;
  border-radius: 50%;
  background: var(--accent-2);
  box-shadow: 0 0 0 3px rgba(var(--accent-2-rgb), .14);
}
.practice-auth-dot[data-state="in"] {
  background: var(--success);
  box-shadow: 0 0 0 3px rgba(var(--success-rgb), .18);
}
.practice-auth-dot[data-state="loading"],
.practice-auth-dot[data-state="off"] {
  background: var(--muted);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .06);
}
.practice-auth-trigger__count {
  min-width: 1.15rem;
  padding: 0 .3rem;
  border-radius: var(--radius-full);
  background: var(--accent-2);
  color: var(--on-accent);
  font-size: var(--fs-2xs);
  font-weight: 800;
  line-height: 1.15rem;
  text-align: center;
}

/* ── hero (legacy .hero-header: dark glass card, centered) ───────────────── */
.hero-header {
  position: relative;
  overflow: hidden;
  text-align: center;
  padding: 3rem 1.4rem;
  margin-bottom: var(--stack-gap);
  border-radius: var(--radius-xl);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  color: var(--text);
  /* derived from the brand surfaces, so a ?assoc= re-brand reaches the hero too: it used
     to hardcode the dark panel and stayed pitch black on a light partner theme */
  background:
    radial-gradient(900px 500px at 20% 20%, rgba(var(--accent-rgb), .35), transparent 60%),
    radial-gradient(700px 450px at 85% 30%, rgba(var(--accent-2-rgb), .28), transparent 55%),
    linear-gradient(135deg, rgba(var(--panel-rgb), .95), var(--brand-bg0));
}
.hero-deco {
  position: absolute;
  top: -70px;
  right: -70px;
  width: 220px;
  height: 220px;
  background: rgba(255, 255, 255, .06);
  border-radius: 50%;
}
.hero-content { position: relative; }
.hero-badge {
  display: inline-block;
  padding: .5rem .9rem;
  margin-bottom: 1rem;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-secondary);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
}
.hero-header h1 {
  font-size: clamp(1.7rem, 4.5vw, 2.5rem);
  font-weight: 800;
  color: var(--text);
  margin-bottom: .5rem;
}
.hero-sub { margin: 0; color: var(--text-secondary); font-size: var(--fs-xl); }
.hero-note {
  margin: 1rem auto 0;
  max-width: 680px;
  color: var(--muted);
  font-size: var(--fs-sm);
  font-style: italic;
  line-height: var(--lh-relaxed);
}

/* ── layout ──────────────────────────────────────────────────────────────── */
/* The extra bottom padding is orb clearance: the fixed progress orb sits bottom-left,
   and the page's last controls (consents, submit) must be able to scroll above it. */
.container {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--space-5) var(--space-5) calc(var(--space-8) + 72px + var(--safe-bottom));
}

/* ── app shell ────────────────────────────────────────────────────────────────
   One centred column. The personal area is a VIEW the main column swaps to, not a
   rail beside the form (the sidebar experiment was removed 2026-08-06).
   HARD CONSTRAINT — no selector inside <main> may require an .app-shell ancestor:
   scripts/dev-harness.mjs /lane renders a bare <main class="container"> with no
   shell around it, and it must keep rendering correctly. */
.app-shell { display: block; }

/* ── area view: head, intro, card grid ───────────────────────────────────── */
.area-view__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}
.area-view__title {
  margin: 0;
  font-size: var(--fs-xl);
  font-weight: 800;
  letter-spacing: -.01em;
}
.area-view__title:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }
.area-view__head-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.area-view__intro {
  max-width: 34rem;
  padding: var(--space-4);
  border: 1px solid var(--accent-border);
  border-radius: var(--radius-lg);
  background: rgba(var(--accent-rgb), .07);
}
.area-view__intro-copy {
  margin: 0 0 var(--space-3);
  color: var(--text-secondary);
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
}
.area-view__body { min-width: 0; }

/* ── cards (legacy: glass gradient body + accent-gradient header) ────────── */
.card {
  background: linear-gradient(180deg, rgba(255, 255, 255, .05), rgba(255, 255, 255, .02));
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  margin-bottom: var(--stack-gap);
  overflow: hidden;
}
.card-header {
  padding: 14px 16px;
  font-weight: 800;
  font-size: var(--fs-base);
  letter-spacing: .2px;
  text-transform: uppercase;
  color: var(--on-accent);
  border-bottom: 1px solid rgba(255, 255, 255, .12);
  background: linear-gradient(135deg, rgba(var(--accent-rgb), .95), rgba(var(--accent-2-rgb), .88));
}
.card-header--dark {
  background: linear-gradient(135deg, rgba(17, 16, 40, .95), rgba(30, 28, 60, .98));
  border-bottom: 1px solid rgba(var(--accent-rgb), .2);
}
/* per-section completion badge (decorative, aria-hidden): white-alpha neutrals +
   solid success fill read correctly on the accent-gradient header for any ?assoc=
   theme in both dark and light mode. Scoped to --section so the static headers
   (picker, privacy --dark, AI --toggle) keep their layout. */
.card-header--section {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .8rem;
}
.card-header__title { min-width: 0; }
.card-header__state {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  border: 1px solid rgba(255, 255, 255, .25);
  background: rgba(255, 255, 255, .08);
  font-size: var(--fs-xs);
  font-weight: 800;
  color: transparent;
  transition: var(--transition-tone);
}
.card-header__state[data-state="partial"] { border-color: rgba(255, 255, 255, .55); }
.card-header__state[data-state="complete"] {
  background: rgba(var(--success-rgb), .9);
  border-color: rgba(var(--success-rgb), .95);
  color: var(--on-accent);
}
.card-header__state[data-state="complete"]::after { content: '✓'; }
.card-body { padding: 16px; }

.section-note { color: var(--muted); font-size: var(--fs-base); margin: 0 0 var(--space-4); }
.required-note { color: var(--muted); font-size: var(--fs-sm); margin: 0 0 var(--space-4); }

/* ── iter notice (passive: no control, no acknowledgement, no gate) ──────────
   Accent-tinted, NOT amber: in this system amber means "something needs your
   attention" (.coverage-note.warn, the readiness tones) and this asks for nothing.
   No transition and no animation, so the global reduced-motion rule has nothing to
   strip; no backdrop-filter, because the element is in the scroll path. */
.iter-notice {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: var(--iconbtn-lg) minmax(0, 1fr);
  gap: var(--space-2) var(--space-4);
  margin-bottom: var(--stack-gap);
  padding: var(--space-4);
  border-radius: var(--radius-xl);
  border: 1px solid rgba(var(--accent-rgb), .28);
  background: linear-gradient(135deg, rgba(var(--accent-rgb), .10), rgba(var(--panel-rgb), .72));
  box-shadow: var(--shadow-md);
}
.iter-notice::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: linear-gradient(180deg, var(--accent), var(--accent-2));
}
.iter-notice__icon {
  width: var(--iconbtn-lg);
  height: var(--iconbtn-lg);
  display: grid;
  place-items: center;
  border-radius: var(--radius-lg);
  border: 1px solid rgba(var(--accent-rgb), .26);
  background: rgba(var(--accent-rgb), .12);
  font-size: var(--fs-lg);
  font-weight: 800;
  color: var(--accent-2);
}
.iter-notice__content { min-width: 0; display: grid; gap: var(--space-2); }
.iter-notice__title {
  margin: 0;
  color: var(--text);
  font-size: var(--fs-lg);
  font-weight: 800;
  line-height: var(--lh-snug);
}
.iter-notice__text {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--fs-base);
  line-height: var(--lh-relaxed);
}
.iter-notice__link { font-weight: 700; text-underline-offset: 3px; }

/* Two sticky strips now sit above the scroll: the app header and the progress bar.
   Anything the app scrolls into view must clear BOTH, or it lands underneath them. */
.card, #moduleForm, #formBuilder > * { scroll-margin-top: calc(var(--header-h) + 56px); }
@media (max-width: 640px) {
  .card, #moduleForm, #formBuilder > * { scroll-margin-top: calc(var(--header-h-compact) + 56px); }
}

/* consensi (legacy: each consent in an accent-tinted box) */
.consent-box {
  background: rgba(var(--accent-rgb), .06);
  border: 1px solid rgba(var(--accent-rgb), .25);
  border-radius: var(--radius-lg);
  padding: .9rem 1rem;
  margin-bottom: var(--space-3);
}
.consent-box .check { margin: 0; }
.consent-box .invalid-feedback { margin: .5rem 0 0 1.5rem; }

/* ── form grid & fields ──────────────────────────────────────────────────── */
.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .95rem 1rem; }
.cell { grid-column: span 2; min-width: 0; position: relative; }
.cell--half { grid-column: span 1; }
@media (max-width: 640px) { .cell--half { grid-column: span 2; } }

.form-label { display: block; font-weight: 700; font-size: var(--fs-base); margin-bottom: 6px; color: var(--text-secondary); }
.required-star { color: var(--danger); font-weight: 900; }
.field-help { color: var(--muted); font-size: var(--fs-base); margin-bottom: .35rem; }
.field-unit { position: absolute; right: .8rem; bottom: .75rem; color: var(--muted); font-size: var(--fs-sm); pointer-events: none; }

.form-control, .form-select {
  width: 100%;
  padding: .72rem .9rem;
  font: inherit;
  /* --fs-md is 16px, and 16px is STRICTLY REQUIRED here: iOS Safari auto-zooms the page
     when a focused field renders below it. Never drop this to the body size. */
  font-size: var(--fs-md);
  color: var(--text);
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  transition: var(--transition-input);
}
.form-control::placeholder { color: rgba(184, 184, 214, .55); }
.form-control:focus, .form-select:focus {
  outline: none;
  border-color: rgba(var(--accent-rgb), .9);
  background: var(--input-bg-focus);
  box-shadow: var(--focus-ring);
}

/* Comune picker: a DOM-owned combobox replaces the native datalist so results,
   focus, touch targets and zoom remain consistent across desktop/mobile browsers. */
#pickerCard { position: relative; z-index: var(--z-raised); overflow: visible; }
#pickerCard > .card-header { border-radius: var(--radius-xl) var(--radius-xl) 0 0; }
.comune-combobox { position: relative; z-index: var(--z-combobox); }
.comune-input-wrap { position: relative; }
.comune-input {
  padding-left: 2.65rem;
  padding-right: 3rem;
  appearance: none;
  -webkit-appearance: none;
}
.comune-input::-webkit-search-cancel-button { display: none; }
.comune-search-icon {
  position: absolute;
  z-index: var(--z-base);
  left: 1rem;
  top: 50%;
  width: .88rem;
  height: .88rem;
  border: 2px solid var(--muted);
  border-radius: 50%;
  transform: translateY(-58%);
  pointer-events: none;
}
.comune-search-icon::after {
  content: '';
  position: absolute;
  width: .46rem;
  height: 2px;
  right: -.36rem;
  bottom: -.2rem;
  border-radius: var(--radius-full);
  background: var(--muted);
  transform: rotate(45deg);
  transform-origin: center;
}
.comune-clear {
  position: absolute;
  z-index: var(--z-raised);
  top: 50%;
  right: var(--space-1);
  width: var(--iconbtn-lg);
  height: var(--iconbtn-lg);
  padding: 0;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--radius-md);
  color: var(--muted);
  background: transparent;
  font: inherit;
  font-size: var(--fs-xl);
  line-height: var(--lh-none);
  cursor: pointer;
  transform: translateY(-50%);
  touch-action: manipulation;
}
.comune-clear:hover { color: var(--text); background: var(--surface-2); }
.comune-clear:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.comune-listbox {
  position: absolute;
  z-index: var(--z-listbox);
  top: calc(100% + .45rem);
  left: 0;
  width: 100%;
  max-height: min(22rem, 45dvh);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: .35rem;
  color: var(--text);
  background: var(--panel);
  border: 1px solid rgba(var(--accent-rgb), .48);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}
.comune-option {
  min-height: 52px;
  padding: .65rem .7rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .7rem;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  touch-action: manipulation;
}
.comune-option + .comune-option { margin-top: 2px; }
.comune-option:hover,
.comune-option[aria-selected="true"] {
  color: var(--text);
  background: rgba(var(--accent-rgb), .16);
  border-color: rgba(var(--accent-rgb), .32);
}
.comune-option__content { min-width: 0; display: flex; flex-direction: column; gap: .12rem; }
.comune-option__name { font-weight: 700; line-height: var(--lh-tight); }
.comune-option__meta { color: var(--muted); font-size: var(--fs-sm); line-height: var(--lh-tight); }
.comune-option__similar {
  flex: none;
  padding: .2rem .42rem;
  color: var(--text-secondary);
  background: var(--surface-2);
  border-radius: var(--radius-full);
  font-size: var(--fs-xs);
  white-space: nowrap;
}
.comune-option--unknown {
  margin-top: .35rem;
  /* --border, not white-alpha: the light theme paints this listbox #fff, where a white
     separator is simply invisible and the unknown-comune option loses its divider. */
  border-top-color: var(--border);
  border-radius: 0 0 var(--radius-md) var(--radius-md);
}
.comune-empty { padding: .9rem; color: var(--muted); font-size: var(--fs-sm); line-height: var(--lh-normal); }
.comune-combobox + .field-help { margin-top: var(--space-1); margin-bottom: 0; }

.visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0 0 0 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}
/* native select, restyled: ellipsis so long option labels visibly truncate
   instead of clipping under the UA arrow; the renderer widens long-option
   selects to a full row and mirrors the value into title (hover).
   The chevron lives on the .select-wrap wrapper, NEVER as a background-image
   on the select itself: Windows Chromium repaints the select's background
   inside the open dropdown list, scaled to the popup (giant stray arrows). */
.form-select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.6rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.select-wrap { position: relative; }
.select-wrap::after {
  content: '';
  position: absolute;
  top: 50%;
  right: .85rem;
  width: 16px;
  height: 16px;
  transform: translateY(-50%);
  pointer-events: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%23b8b8d6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 16px 16px no-repeat;
}
.form-select option { background: var(--panel-2); color: var(--text); }
.form-control--locked { opacity: .65; }
textarea.form-control { resize: vertical; }

.header-field {
  font-weight: 800;
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: .8px;
  color: rgba(var(--accent-2-rgb), .98);
  margin-top: 10px;
  margin-bottom: 2px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, .14);
}
.info-field { color: var(--muted); font-size: var(--fs-base); font-style: italic; }

/* info field with link/warning → highlighted guidance callout (FAQ/template ministeriale) */
.info-callout {
  padding: .8rem .95rem;
  border-radius: var(--radius-md);
  font-size: var(--fs-base);
  color: var(--text-secondary);
  background: rgba(var(--accent-rgb), .1);
  border: 1px solid rgba(var(--accent-rgb), .3);
}
.info-callout p { margin: 0 0 .45rem; }
.info-callout-link { display: inline-block; font-weight: 600; }
.info-callout-warning {
  margin-top: .55rem;
  padding-top: .55rem;
  border-top: 1px dashed rgba(var(--accent-rgb), .3);
  color: var(--warning);
  font-size: var(--fs-sm);
}

.radio-group { display: flex; flex-wrap: wrap; gap: .3rem 1.1rem; }
.checkbox-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .35rem .9rem; }
@media (max-width: 640px) { .checkbox-grid { grid-template-columns: 1fr; } }
.check { display: flex; align-items: flex-start; gap: .5rem; margin: .3rem 0; }
.check-inline { display: inline-flex; }
.check-input { margin-top: .3rem; width: 1rem; height: 1rem; accent-color: var(--accent); flex: none; }
.check-label { font-size: var(--fs-base); color: var(--text-secondary); }

.repeater-item {
  position: relative;
  background: rgba(15, 14, 39, .55);
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: var(--radius-lg);
  padding: 14px;
  margin-bottom: 12px;
}
.repeater-title { margin: 0 0 .8rem; color: var(--muted); font-size: var(--fs-base); }
/* the repeater row's remove chip: the danger intent, on the icon-button box scale */
.btn-remove {
  position: absolute; top: var(--space-2); right: var(--space-2);
  color: var(--danger);
  cursor: pointer;
  padding: var(--space-1) var(--space-2);
  font-size: var(--fs-md);
  line-height: var(--lh-tight);
  border-radius: var(--radius-md);
  background: var(--btn-danger-bg);
  border: 1px solid var(--danger-border);
  transition: var(--transition-control);
}
.btn-remove:hover { background: var(--btn-danger-bg-hover); }

/* ── buttons ──────────────────────────────────────────────────────────────────
   Base sizing comes from the shared control system (--control-h-*, --control-pad-*),
   the same tokens the inputs use, so a button and a field of the same size line up.
   Intent comes from the --btn-*-bg tokens, so a ?assoc= re-brand reaches every one. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-h-md);
  padding: var(--control-pad-y) var(--control-pad-x-md);
  font: inherit;
  font-weight: 800;
  letter-spacing: .2px;
  border-radius: var(--radius-lg);
  border: 1px solid transparent;
  cursor: pointer;
  transition: var(--transition-control);
  text-decoration: none;
}
/* block-level action buttons get ONE consistent gap from the content above them
   (Procedi, Segnala, Analizza, + Aggiungi — anything sitting directly in a card) */
.card-body > .btn, #segnalaBox > .btn { margin-top: var(--space-3); }
.btn:active { transform: translateY(0); }
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.btn-primary {
  background: var(--btn-primary-bg);
  color: var(--on-accent);
  box-shadow: var(--shadow-accent-md);
}
.btn-primary:hover { filter: brightness(1.06); transform: translateY(-1px); }
.btn-success {
  background: linear-gradient(135deg, rgba(var(--success-rgb), .95), rgba(var(--accent-rgb), .85));
  color: var(--on-accent);
  box-shadow: var(--shadow-md);
}
.btn-success:hover { filter: brightness(1.06); transform: translateY(-1px); }
.btn-outline {
  background: var(--btn-outline-bg);
  border-color: rgba(var(--accent-rgb), .65);
  color: var(--text-secondary);
}
.btn-outline:hover { background: var(--btn-outline-bg-hover); border-color: rgba(var(--accent-rgb), .95); color: var(--text); }
.btn-ghost { background: var(--btn-ghost-bg); border-color: var(--border); color: var(--text-secondary); }
.btn-ghost:hover { background: var(--btn-ghost-bg-hover); }
/* the danger intent, so a destructive control never has to hand-roll one again */
.btn-danger { background: var(--btn-danger-bg); border-color: var(--danger-border); color: var(--danger); }
.btn-danger:hover { background: var(--btn-danger-bg-hover); color: var(--danger-dark); }
.btn-sm { min-height: var(--control-h-sm); padding: var(--space-1-5) var(--control-pad-x-sm); font-size: var(--fs-sm); }
.btn-lg { min-height: var(--control-h-lg); padding: var(--control-pad-y) var(--control-pad-x-lg); font-size: var(--fs-md); }
.btn-block { display: flex; width: 100%; }
.btn-submit { display: flex; width: 100%; text-transform: uppercase; }
.card-body > .btn-submit { margin-top: var(--space-5); }
.btn:disabled { opacity: .5; cursor: not-allowed; filter: none; transform: none; }

/* Touch targets. Desktop keeps the 40/32px control heights, which already clear
   WCAG 2.2 · 2.5.8 (24×24 CSS px); a coarse pointer lifts this allowlist to 44px. */
@media (pointer: coarse) {
  .btn,
  .btn-sm,
  .btn-remove,
  .card-header--toggle,
  .comune-clear,
  .comune-option,
  .file-row__remove,
  .practice-auth-close { min-height: var(--control-min-touch); }
}

/* ── validation ──────────────────────────────────────────────────────────── */
.invalid-feedback { display: none; color: var(--danger); font-size: var(--fs-base); margin-top: var(--space-1); }
.invalid-feedback.show { display: block; }
.field-invalid { border-color: var(--danger) !important; }
.field-invalid-group { outline: 2px solid rgba(var(--danger-rgb), .45); outline-offset: 4px; border-radius: 6px; }

.ai-highlight { animation: aiPulse 2.3s ease-out; }
@keyframes aiPulse {
  0% { box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .55); }
  100% { box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0); }
}

/* wizard-resolved fields: green glow on the field cell (distinct from ai-highlight) */
.ai-resolved {
  animation: resolvedGlow 2.6s ease-out;
  border-left: 3px solid rgba(var(--success-rgb), .7);
  border-radius: 4px;
}
@keyframes resolvedGlow {
  0% { box-shadow: 0 0 0 3px rgba(var(--success-rgb), .5); }
  100% { box-shadow: 0 0 0 3px rgba(var(--success-rgb), 0); }
}

.ape-toggle {
  padding: .55rem .75rem;
  background: rgba(var(--accent-rgb), .1);
  border: 1px solid rgba(var(--accent-rgb), .25);
  border-radius: var(--radius-md);
  margin-bottom: .95rem;
}
.ape-fields--disabled { opacity: .4; pointer-events: none; }

/* ── notes & results ─────────────────────────────────────────────────────── */
.coverage-note {
  margin: var(--space-3) 0;
  padding: .75rem .95rem;
  border-radius: var(--radius-md);
  font-size: var(--fs-md);
  color: var(--text-secondary);
  background: rgba(var(--accent-rgb), .1);
  border: 1px solid rgba(var(--accent-rgb), .3);
}
.coverage-note.warn {
  background: rgba(var(--warning-rgb), .1);
  border-color: rgba(var(--warning-rgb), .35);
  color: var(--warning-dark);
}
.coverage-note > div { margin: .15rem 0; }
.coverage-note .btn { margin: .4rem 0; }
.coverage-note p { margin: .2rem 0 .5rem; }

.draft-card { border-color: rgba(var(--accent-rgb), .34); }
.draft-card[data-tone="warn"] {
  border-color: rgba(var(--warning-rgb), .42);
  background: linear-gradient(180deg, rgba(var(--warning-rgb), .09), rgba(var(--panel-rgb), .72));
}
.draft-card__body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.draft-card__copy { min-width: 0; }
.draft-card__title { margin: 0; font-size: var(--fs-lg); }
.draft-card__message {
  margin: var(--space-1) 0 0;
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  line-height: var(--lh-relaxed);
}
.draft-card__actions {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.submit-result { margin-top: var(--space-4); padding: .85rem 1rem; border-radius: var(--radius-md); white-space: pre-wrap; font-size: var(--fs-base); }
.submit-result.ok { background: rgba(var(--success-rgb), .12); border: 1px solid rgba(var(--success-rgb), .35); color: var(--success-dark); }
.submit-result.err { background: rgba(var(--danger-rgb), .1); border: 1px solid rgba(var(--danger-rgb), .35); color: var(--danger-dark); }

.practice-submit-recovery {
  border-color: rgba(var(--warning-rgb), .35);
}
.practice-submit-recovery__body { display: grid; gap: var(--space-3); }
.practice-submit-recovery__eyebrow {
  margin: 0;
  color: var(--warning);
  font-size: var(--fs-sm);
  font-weight: 750;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.practice-submit-recovery__title,
.practice-submit-recovery__status { margin: 0; }
.practice-submit-recovery__title { font-size: var(--fs-xl); }
.practice-submit-recovery__status { color: var(--text-secondary); line-height: var(--lh-relaxed); }
.practice-submit-recovery__error {
  margin: 0;
  padding: .85rem 1rem;
  border: 1px solid rgba(var(--danger-rgb), .35);
  border-radius: var(--radius-md);
  background: rgba(var(--danger-rgb), .1);
  color: var(--danger-dark);
  line-height: var(--lh-normal);
}
.practice-submit-recovery__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.success-card { max-width: 680px; margin-inline: auto; }
.success-card__body { padding: clamp(1.5rem, 5vw, 3rem); text-align: center; }
.success-card__mark {
  display: grid;
  width: 64px;
  height: 64px;
  margin: 0 auto var(--space-4);
  place-items: center;
  border: 1px solid rgba(var(--success-rgb), .45);
  border-radius: 50%;
  background: rgba(var(--success-rgb), .14);
  color: var(--success-dark);
  font-size: 2rem;
  font-weight: 800;
}
.success-card__title { margin: 0; font-size: clamp(1.4rem, 4vw, 2rem); }
.success-card__title:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 4px; }
.success-card__message { margin: var(--space-3) 0 0; color: var(--text-secondary); }
.success-card__reference {
  display: inline-block;
  margin: var(--space-4) 0 0;
  padding: .65rem .9rem;
  border: 1px solid rgba(var(--accent-rgb), .3);
  border-radius: var(--radius-md);
  background: rgba(var(--accent-rgb), .09);
  color: var(--text-secondary);
}
.success-card__reference strong { color: var(--text); }
.success-card__note { margin: var(--space-4) 0 0; color: var(--muted); font-size: var(--fs-sm); }
.success-card__completeness { margin: var(--space-3) 0 0; color: var(--text-secondary); font-size: var(--fs-sm); }
.success-card__cleanup {
  margin: var(--space-4) 0 0;
  padding: var(--space-3);
  border: 1px solid rgba(var(--warning-rgb), .38);
  border-radius: var(--radius-md);
  background: rgba(var(--warning-rgb), .08);
  color: var(--warning);
  font-size: var(--fs-sm);
  text-align: left;
}
.success-card__cleanup p { margin: 0; }
.success-card__cleanup .btn { margin-top: var(--space-3); }
.success-card__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: center;
}
.success-card__action { margin-top: var(--space-5); }
/* draw-in on the checkmark; base state = final state, so reduced-motion (which
   kills the animation) degrades to the static card */
.success-card__mark { animation: successPop .5s cubic-bezier(.2, .9, .3, 1.2); }
@keyframes successPop { from { transform: scale(.55); opacity: 0; } }

/* Cloudflare Turnstile slot (visible only when the gate is armed server-side) */
.turnstile-box { display: flex; flex-direction: column; gap: .35rem; margin: .8rem 0 .3rem; }

/* ── Practice documents (canonical ledger; separate from the legacy AI picker) ── */
.practice-documents[hidden] { display: none; }
.practice-documents { border-color: rgba(var(--accent-rgb), .32); }
.practice-documents__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  text-transform: none;
}
.practice-documents__heading { min-width: 0; }
.practice-documents__title {
  margin: 0;
  color: var(--on-accent);
  font-size: var(--fs-lg);
  line-height: var(--lh-tight);
}
.practice-documents__subtitle {
  margin: var(--space-1) 0 0;
  color: rgba(255, 255, 255, .82);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0;
}
.practice-documents__refresh {
  flex: 0 0 auto;
  border-color: rgba(255, 255, 255, .38);
  background: rgba(17, 16, 40, .2);
  color: var(--on-accent);
}
.practice-documents__refresh:hover { background: rgba(17, 16, 40, .34); color: var(--on-accent); }
.practice-documents__intro { max-width: 760px; }
.practice-documents__status,
.practice-documents__readiness {
  margin: 0 0 var(--space-3);
  padding: .7rem .85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .04);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
}
.practice-documents__status:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.practice-documents__status[data-tone="loading"] {
  border-color: rgba(var(--accent-rgb), .42);
  background: rgba(var(--accent-rgb), .1);
  color: var(--text);
}
.practice-documents__status[data-tone="ready"],
.practice-documents__readiness[data-tone="ready"] {
  border-color: rgba(var(--success-rgb), .34);
  background: rgba(var(--success-rgb), .09);
  color: var(--success-dark);
}
.practice-documents__status[data-tone="warning"],
.practice-documents__readiness[data-tone="warning"] {
  border-color: rgba(var(--warning-rgb), .38);
  background: rgba(var(--warning-rgb), .09);
  color: var(--warning-dark);
}
.practice-documents__status[data-tone="error"],
.practice-documents__readiness[data-tone="error"] {
  border-color: rgba(var(--danger-rgb), .38);
  background: rgba(var(--danger-rgb), .09);
  color: var(--danger-dark);
}
.practice-documents__readiness[hidden] { display: none; }
.practice-documents__groups { display: grid; gap: var(--space-4); }
.practice-document-group {
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, .025);
}
.practice-document-group__heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}
.practice-document-group__title {
  margin: 0;
  color: var(--text);
  font-size: var(--fs-md);
}
.practice-document-group__count {
  flex: 0 0 auto;
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 700;
}
.practice-document-group__description {
  margin: var(--space-1) 0 var(--space-3);
  color: var(--muted);
  font-size: var(--fs-xs);
  line-height: var(--lh-normal);
}
.practice-document-group__slots { display: grid; gap: var(--space-2); }
.practice-document-slot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  min-height: 66px;
  padding: .7rem .75rem;
  border: 1px solid var(--border-light);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .035);
}
.practice-document-slot[data-state="ready"] { border-color: rgba(var(--success-rgb), .3); }
.practice-document-slot[data-state="waiting"],
.practice-document-slot[data-state="attention"],
.practice-document-slot[data-state="removing"] { border-color: rgba(var(--warning-rgb), .3); }
.practice-document-slot__copy { min-width: 0; }
.practice-document-slot__title {
  margin: 0;
  color: var(--text);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
}
.practice-document-slot__status {
  margin: var(--space-1) 0 0;
  overflow-wrap: anywhere;
  color: var(--muted);
  font-size: var(--fs-xs);
  line-height: var(--lh-normal);
}
.practice-document-slot[data-state="ready"] .practice-document-slot__status { color: var(--success-dark); }
.practice-document-slot[data-state="attention"] .practice-document-slot__status,
.practice-document-slot[data-state="removing"] .practice-document-slot__status { color: var(--warning-dark); }
.practice-document-slot__actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.practice-document-slot__delete { color: var(--danger); }
.practice-document-slot__delete:hover { border-color: rgba(var(--danger-rgb), .45); }

/* ── AI attachment proposals (review panel inside the documents card) ────── */
.ai-doc-proposals {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid rgba(var(--accent-rgb), .35);
  border-radius: var(--radius-lg);
  background: rgba(var(--accent-rgb), .08);
}
.ai-doc-proposals[hidden] { display: none; }
.ai-doc-proposals__title {
  margin: 0;
  font-size: var(--fs-base);
  font-weight: 800;
  color: var(--text);
}
.ai-doc-proposals__intro {
  margin: 0;
  max-width: 760px;
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
  color: var(--muted);
}
.ai-doc-proposals__list {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.ai-doc-proposals__item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-2);
}
.ai-doc-proposals__item[data-state="added"] { border-color: rgba(var(--success-rgb), .3); }
.ai-doc-proposals__item[data-state="skipped"],
.ai-doc-proposals__item[data-state="error"] { border-color: rgba(var(--warning-rgb), .3); }
.ai-doc-proposals__pick {
  order: 1;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  flex: 1 1 14rem;
  cursor: pointer;
}
.ai-doc-proposals__name {
  overflow-wrap: anywhere;
  font-weight: 600;
}
.ai-doc-proposals__category { order: 2; flex: 0 1 15rem; }
.ai-doc-proposals__category .form-select { width: 100%; min-height: var(--control-h-sm); }
.ai-doc-proposals__hint {
  order: 3;
  flex: 1 1 100%;
  font-size: var(--fs-xs);
  color: var(--muted);
}
.ai-doc-proposals__status {
  order: 4;
  flex: 1 1 100%;
  font-size: var(--fs-xs);
  color: var(--warning-dark);
}
.ai-doc-proposals__item[data-state="added"] .ai-doc-proposals__status { color: var(--success-dark); }
.ai-doc-proposals__status[hidden] { display: none; }
.ai-doc-proposals__result {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--text);
}
.ai-doc-proposals__result[hidden] { display: none; }

@media (max-width: 640px) {
  .practice-documents__header { align-items: stretch; flex-direction: column; }
  .practice-documents__refresh { width: 100%; }
  .practice-document-group { padding: var(--space-2); }
  .practice-document-slot { grid-template-columns: 1fr; align-items: stretch; }
  .practice-document-slot__actions { justify-content: stretch; }
  .practice-document-slot__actions .btn { flex: 1 1 8rem; }

  .ai-lane { padding: var(--space-3); }
  .ai-lane__icon { width: 44px; height: 44px; font-size: 1.2rem; }
  .ai-lane__step-label { font-size: var(--fs-2xs); }
  .ai-lane__step-line { width: 14px; }
  .ai-lane__meta { align-items: stretch; flex-direction: column; }
  .ai-lane__actions { flex-direction: column; }
  .ai-lane__actions .btn { width: 100%; }
  .ai-lane-dock {
    left: var(--space-3); right: var(--space-3); bottom: var(--space-3);
    max-width: none; border-radius: var(--radius-lg);
  }
  .file-row {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "icon name remove" "bar bar bar" "state state state";
  }
  .file-row__meta { display: none; }
}

/* ── AI card (collapsible; legacy: green gradient header + hint) ─────────── */
.card--ai { border-color: rgba(var(--accent-rgb), .35); }
.card-header--toggle {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: var(--control-h-lg);
  border: 0;                                    /* kill the UA <button> outset border */
  border-bottom: 1px solid var(--border);
  font: inherit;
  font-weight: 800;
  font-size: var(--fs-base);
  letter-spacing: .2px;
  text-transform: none;                         /* the hint stays sentence-case */
  text-align: left;
  color: var(--on-accent);
  cursor: pointer;
  background: linear-gradient(135deg, rgba(var(--success-rgb), .92), rgba(var(--accent-rgb), .82));
}
.ai-header-stack { display: flex; flex-direction: column; gap: 2px; }
.ai-header-label { display: inline-flex; align-items: center; gap: .55rem; flex-wrap: wrap; }
.ai-spark { font-size: var(--fs-md); }
.ai-hint {
  font-weight: 400;
  font-size: var(--fs-xs);
  opacity: .8;
  margin-left: 1.6rem;
  transition: opacity var(--dur-base) var(--ease-standard);
}
.card-header--toggle[aria-expanded="true"] .ai-hint { opacity: 0; }
.ai-chevron { transition: transform var(--dur-base) var(--ease-standard); color: rgba(255, 255, 255, .85); }
.card--ai.collapsed .ai-chevron { transform: rotate(-90deg); }
.card--ai.collapsed .card-body { display: none; }

/* dropzone (legacy .upload-zone) */
.dropzone {
  border: 2px dashed rgba(var(--accent-rgb), .70);
  border-radius: var(--radius-xl);
  padding: 26px 18px;
  text-align: center;
  cursor: pointer;
  background: rgba(var(--accent-rgb), .08);
  transition: var(--transition-control);
  margin-bottom: var(--space-3);
  user-select: none;
}
.dropzone:hover, .dropzone:focus-visible { background: rgba(var(--accent-rgb), .14); outline: none; transform: translateY(-1px); }
.dropzone.dragover { background: rgba(var(--accent-rgb), .16); border-color: rgba(var(--accent-2-rgb), .95); }
.dropzone-icon { font-size: 1.6rem; margin-bottom: .3rem; }
.dropzone-text { font-size: var(--fs-md); }
.dropzone-hint { color: var(--muted); font-size: var(--fs-xs); margin-top: var(--space-1); }

/* file rows — a pill had nowhere to put a determinate bar, and a silent multi-megabyte
   upload is exactly what this lane must stop being. */
.file-list { list-style: none; margin: 0 0 var(--space-3); padding: 0; display: grid; gap: var(--space-2); }
.file-list:empty { margin: 0; }
.file-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  grid-template-areas:
    "icon name meta remove"
    "bar  bar  bar  bar"
    "state state state state";
  align-items: center;
  gap: var(--space-1) var(--space-2);
  padding: var(--space-2) var(--space-3);
  font-size: var(--fs-sm);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .04);
}
.file-row__icon { grid-area: icon; }
.file-row__name { grid-area: name; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-row__meta { grid-area: meta; color: var(--muted); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.file-row__state { grid-area: state; color: var(--muted); font-size: var(--fs-xs); }
.file-row__bar { grid-area: bar; }
.progress-track--file { height: 4px; }
.file-row[data-state="done"] { border-color: rgba(var(--success-rgb), .34); }
.file-row[data-state="done"] .file-row__state { color: var(--success); }
.file-row[data-state="error"] { border-color: rgba(var(--danger-rgb), .45); }
.file-row[data-state="error"] .file-row__state { color: var(--danger); }
/* the bar is meaningful only while bytes are moving */
.file-row[data-state="queued"] .file-row__bar,
.file-row[data-state="done"] .file-row__bar,
.file-row[data-state="error"] .file-row__bar { display: none; }
.file-row__remove {
  grid-area: remove;
  /* WCAG 2.2 · 2.5.8 target size — the former chip button was ~21x20px */
  min-width: var(--iconbtn-sm); min-height: var(--iconbtn-sm);
  display: grid; place-items: center;
  border: none; background: none; color: var(--muted);
  font-size: var(--fs-md); line-height: var(--lh-none); cursor: pointer; border-radius: var(--radius-full);
}
.file-row__remove:hover { color: var(--danger); background: var(--btn-danger-bg); }
.file-row__remove:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ── AI lane progress (non-blocking; replaces the former full-screen #aiOverlay) ──
   Covers upload → lettura → compilazione → fatto. The inline panel is a FOOTER of the AI
   card rather than a child of its body, so collapsing the card cannot hide a run in
   flight. The docked pill is the same component's second surface.
   NO backdrop-filter anywhere in this block: the pill is fixed over the scroll path and
   blurring it is exactly what made Chrome flash black rectangles. */
.ai-lane {
  border-top: 1px solid var(--border);
  padding: var(--space-4);
  background: linear-gradient(180deg, rgba(var(--accent-rgb), .07), rgba(var(--panel-rgb), .35));
  /* no `forwards`: the resting state IS the default, so the global reduced-motion rule
     removing this animation still leaves the panel correctly rendered */
  animation: aiLaneIn .35s cubic-bezier(.22, 1, .36, 1);
}
@keyframes aiLaneIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
.ai-lane__head { display: flex; align-items: center; gap: var(--space-3); }
.ai-lane__icon {
  flex: none;
  width: 56px; height: 56px;
  display: grid; place-items: center;
  font-size: 1.5rem;
  border-radius: var(--radius-lg);
  border: 1px solid rgba(var(--accent-rgb), .28);
  background: linear-gradient(135deg, rgba(var(--accent-rgb), .18), rgba(var(--accent-2-rgb), .10));
}
.ai-lane[data-tone="loading"] .ai-lane__icon { animation: aiLanePulse 2.4s ease-in-out infinite; }
@keyframes aiLanePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), .20); }
  50% { box-shadow: 0 0 0 12px rgba(var(--accent-rgb), 0); }
}
.ai-lane__titles { min-width: 0; }
.ai-lane__status { margin: 0; font-size: var(--fs-md); font-weight: 800; color: var(--text); line-height: var(--lh-snug); }
.ai-lane__notice { margin: var(--space-1) 0 0; font-size: var(--fs-sm); color: var(--warning); }
.ai-lane__detail {
  margin: var(--space-1) 0 0;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  min-height: 1.3em;          /* reserved: swapping the line must not shift the layout */
  transition: opacity var(--dur-base) var(--ease-standard);
}
.ai-lane__detail.is-fading { opacity: 0; }

.ai-lane__steps { display: flex; align-items: flex-start; margin: var(--space-4) 0 var(--space-3); }
.ai-lane__step { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); flex: 1 1 0; min-width: 0; }
.ai-lane__step-dot {
  width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: var(--fs-xs); font-weight: 800; color: var(--muted);
  background: rgba(255, 255, 255, .06);
  border: 2px solid rgba(255, 255, 255, .14);
  transition: var(--transition-tone);
}
.ai-lane__step[data-state="active"] .ai-lane__step-dot {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  border-color: var(--accent); color: var(--on-accent);
  box-shadow: 0 0 16px rgba(var(--accent-rgb), .35);
}
.ai-lane__step[data-state="done"] .ai-lane__step-dot {
  background: rgba(var(--success-rgb), .18); border-color: var(--success); color: var(--success);
}
.ai-lane__step[data-state="error"] .ai-lane__step-dot {
  background: rgba(var(--danger-rgb), .16); border-color: var(--danger); color: var(--danger);
}
.ai-lane__step-label {
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .5px; text-transform: uppercase;
  color: var(--muted); text-align: center;
}
.ai-lane__step[data-state="active"] .ai-lane__step-label { color: var(--text); }
.ai-lane__step[data-state="done"] .ai-lane__step-label { color: var(--success); }
.ai-lane__step-line {
  flex: 0 0 auto; width: 28px; height: 2px; margin-top: 13px;
  border-radius: 2px; background: rgba(255, 255, 255, .10);
  transition: background var(--dur-slow) var(--ease-standard);
}
.ai-lane__step-line[data-state="filled"] { background: linear-gradient(90deg, var(--success), var(--accent)); }

.ai-lane__bar .progress-track { height: 6px; }
.ai-lane__bar .progress-fill {
  background: linear-gradient(90deg, var(--accent), var(--success));
  transition: width .5s var(--ease-out);
}
/* Indeterminate animates OPACITY only: compositor-cheap, and when the global
   reduced-motion rule kills it the bar degrades to a legible flat fill while the ticking
   elapsed timer remains the live proof that work is still happening. */
.ai-lane[data-progress="indeterminate"] .ai-lane__bar .progress-fill {
  width: 100%; opacity: .38; animation: aiLaneSweep 1.5s ease-in-out infinite;
}
@keyframes aiLaneSweep { 0%, 100% { opacity: .22; } 50% { opacity: .52; } }
.ai-lane[data-tone="success"] .ai-lane__bar .progress-fill {
  background: linear-gradient(90deg, var(--success), var(--accent-2));
}

.ai-lane__meta {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-3);
}
.ai-lane__timer {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 5px 12px; border-radius: var(--radius-full);
  font-size: var(--fs-xs); font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--muted);
  background: rgba(255, 255, 255, .04); border: 1px solid var(--border-light);
}
.ai-lane__timer-hint { opacity: .7; }
.ai-lane__actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.ai-lane[data-tone="error"] .ai-lane__status { color: var(--danger); }
.ai-lane[data-tone="warning"] .ai-lane__status { color: var(--warning); }
.ai-lane[data-tone="success"] .ai-lane__status { color: var(--success); }

/* docked mini pill — the same component's second surface, shown only while live work is
   scrolled out of view */
.ai-lane-dock {
  position: fixed;
  right: var(--space-4); bottom: var(--space-4);
  z-index: var(--z-dock);                   /* over the progress bar, under overlays */
  transform: translateZ(0); will-change: transform;   /* its own compositor layer */
  display: flex; align-items: center; gap: var(--space-3);
  max-width: min(22rem, calc(100vw - 2 * var(--space-4)));
  padding: var(--space-2) var(--space-3);
  /* not a full pill: the stacked copy + progress bar would run into the rounded corners */
  border-radius: var(--radius-lg);
  background: rgba(var(--panel-rgb), .97);  /* near-opaque; NO backdrop-filter */
  border: 1px solid rgba(var(--accent-rgb), .38);
  box-shadow: var(--shadow-md);
}
.ai-lane-dock__copy { min-width: 0; }
.ai-lane-dock__phase {
  display: block; font-size: var(--fs-xs); font-weight: 800; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ai-lane-dock__detail { display: block; font-size: var(--fs-2xs); color: var(--muted); font-variant-numeric: tabular-nums; }
.ai-lane-dock__bar { margin-top: 4px; }
.ai-lane-dock__bar .progress-track { height: 4px; }
.ai-lane-dock__button { flex: none; min-height: 44px; }

/* ── overlays (modal, wizard, issues, practice auth) ─────────────────────── */
.overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.2rem;
  background: rgba(7, 6, 18, .82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.overlay-panel {
  width: min(30rem, 100%);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  padding: 1.6rem 1.5rem;
  text-align: center;
}
.progress-track--inline { height: 6px; }

.overlay-panel--modal { text-align: left; }
.modal-title { font-size: var(--fs-lg); margin-bottom: .6rem; }
.modal-message { margin: 0 0 1.2rem; color: var(--text-secondary); white-space: pre-wrap; }
.modal-actions { display: flex; justify-content: flex-end; gap: .6rem; flex-wrap: wrap; }

/* Optional Practice identity shell. Markup stays hidden unless the server bootstrap
   advertises the exact auth flag; this surface never gates the form underneath it. */
.practice-auth-panel {
  position: relative;
  width: min(42rem, 100%);
  margin-block: auto;
}
/* Signed in, this stops being a dialog and becomes a workspace, so it stops pretending to
   be a centred card. An explicit data-phase replaces the former `:has()` width hack: one
   fewer browser dependency, and the state is legible in the DOM. */
#practiceAuthOverlay {
  align-items: flex-start;
  overflow-y: auto;
  /* deliberately none: this overlay scrolls, and blurring a scroll container is what made
     Chrome flash black rectangles */
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.practice-auth-close {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  display: grid;
  width: var(--iconbtn-md);
  height: var(--iconbtn-md);
  place-items: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  color: var(--muted);
  background: var(--surface-1);
  font: inherit;
  font-size: var(--fs-xl);
  line-height: var(--lh-none);
  cursor: pointer;
  transition: var(--transition-control);
}
.practice-auth-close:hover { color: var(--text); background: var(--surface-3); }
.practice-auth-close:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.practice-auth-eyebrow {
  margin: 0 0 var(--space-1);
  color: var(--accent-2);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.practice-auth-lead { padding-right: 1.8rem; }
.practice-auth-status {
  min-height: 1.45rem;
  margin: 0 0 var(--space-3);
  color: var(--muted);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
}
.practice-auth-status[data-tone="ok"] { color: var(--success); }
.practice-auth-status[data-tone="warning"] { color: var(--warning); }
.practice-auth-status[data-tone="error"] { color: var(--danger); }
.practice-auth-view { margin-top: var(--space-2); }
.practice-auth-view > .btn,
.practice-auth-turnstile + .btn { margin-top: var(--space-3); }
/* the answer to "che cos'è quest'area", shown only before you are inside it */
.practice-auth-value {
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-5);
  list-style: none;
  border: 1px solid rgba(var(--accent-rgb), .28);
  border-radius: var(--radius-md);
  background: rgba(var(--accent-rgb), .07);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  line-height: var(--lh-relaxed);
}
.practice-auth-value li { position: relative; }
.practice-auth-value li + li { margin-top: var(--space-2); }
.practice-auth-value li::before {
  content: '✓';
  position: absolute;
  left: -1.15rem;
  color: var(--success);
  font-weight: 800;
}
.practice-auth-hint {
  margin: var(--space-2) 0 0;
  color: var(--muted);
  font-size: var(--fs-base);
}
.practice-auth-detail {
  margin: 0 0 var(--space-3);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  line-height: var(--lh-relaxed);
}
.practice-auth-turnstile { margin-top: var(--space-3); }
.practice-auth-otp {
  font-variant-numeric: tabular-nums;
  letter-spacing: .32em;
  text-align: center;
}
.practice-auth-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-4);
  flex-wrap: wrap;
}
.practice-auth-confirmed {
  min-width: 0;
  padding: var(--space-4);
  border: 1px solid rgba(var(--success-rgb), .28);
  border-radius: var(--radius-lg);
  background: rgba(var(--success-rgb), .07);
}
.practice-auth-confirmed__title {
  margin: 0 0 var(--space-2);
  color: var(--success);
  font-weight: 800;
}
.practice-area {
  display: grid;
  min-width: 0;
  gap: var(--space-3);
}
.practice-area__heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}
.practice-area__status,
.practice-area__empty {
  margin: var(--space-1) 0 0;
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
}
/* An empty area must TEACH what the area is; a single grey sentence taught nothing. */
.practice-area__empty {
  padding: var(--space-4);
  border: 1px dashed rgba(var(--accent-rgb), .32);
  border-radius: var(--radius-lg);
  background: rgba(var(--accent-rgb), .05);
  text-align: center;
}
.practice-area__empty p { margin: 0; }
.practice-area__empty-title {
  margin: 0 0 var(--space-2) !important;
  color: var(--text);
  font-size: var(--fs-md);
  font-weight: 700;
}
.practice-area__empty .btn { margin-top: var(--space-3); }
.practice-area__status { min-height: 1.35rem; margin: 0; }
.practice-area__status[data-tone="ok"] { color: var(--success); }
.practice-area__status[data-tone="warning"] { color: var(--warning); }
.practice-area__status[data-tone="error"] { color: var(--danger); }
.practice-area__alert {
  padding: .7rem .8rem;
  border: 1px solid rgba(var(--danger-rgb), .42);
  border-radius: var(--radius-md);
  background: rgba(var(--danger-rgb), .1);
  color: var(--danger-dark);
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
}
.practice-area__current,
.practice-area__item {
  padding: var(--space-3);
  border: 1px solid rgba(var(--accent-rgb), .28);
  border-radius: var(--radius-md);
  background: rgba(var(--panel-rgb), .54);
}
.practice-area__current h3,
.practice-area__item-title {
  margin: 0;
  color: var(--text);
  font-size: var(--fs-md);
  overflow-wrap: anywhere;
}
.practice-area__current p,
.practice-area__item-meta {
  margin: var(--space-1) 0 0;
  color: var(--text-secondary);
  font-size: var(--fs-xs);
  line-height: var(--lh-normal);
}
/* auto-fill does the sizing: two practices read as two large confident cards, eight read
   as a grid — no guess about how many practices an owner will have. */
.practice-area__list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.practice-area__item-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
}
.practice-area__badge {
  flex: none;
  padding: .15rem .42rem;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), .13);
  color: var(--accent-dark);
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
}
/* Tone separates "you have to move" from "we are working on it" at a glance. It is never
   the only carrier: the row also states it in words, right underneath. */
.practice-area__badge[data-tone="progress"] {
  background: rgba(var(--accent-rgb), .13);
  color: var(--accent-dark);
}
.practice-area__badge[data-tone="action"] {
  background: rgba(var(--warning-rgb), .16);
  color: var(--warning-dark);
}
.practice-area__badge[data-tone="done"] {
  background: rgba(var(--success-rgb), .16);
  color: var(--success-dark);
}
.practice-area__badge[data-tone="stopped"] {
  background: rgba(var(--danger-rgb), .16);
  color: var(--danger);
}
.practice-area__badge[data-tone="neutral"] {
  background: var(--surface-2);
  color: var(--text-secondary);
}
.practice-auth-confirmed__line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
  margin: 0;
}
.practice-auth-confirmed__line .practice-auth-detail { margin: 0; }
.practice-area__item-summary {
  margin: var(--space-2) 0 0;
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
}
/* the id is what support asks for, so it stays visible — just never as the name */
.practice-area__item-reference {
  margin: var(--space-2) 0 0;
  color: var(--muted);
  font-size: var(--fs-2xs);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  overflow-wrap: anywhere;
}
.practice-area__item-more { margin-top: var(--space-2); }
.practice-area__item-more > summary {
  cursor: pointer;
  color: var(--muted);
  font-size: var(--fs-xs);
}
.practice-area__item-more > summary:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-md);
}
.practice-area__item-more .practice-area__row-actions { margin-top: var(--space-2); }
.practice-area__row-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
  flex-wrap: wrap;
}
.practice-area__danger { color: var(--danger); }
.practice-commercial {
  display: grid;
  min-width: 0;
  gap: var(--space-3);
}
/* the detail now reads top-down: back link, then the practice's own name */
.practice-commercial__heading {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}
.practice-commercial__heading h3 {
  min-width: 0;
  margin: 0;
  font-size: var(--fs-md);
  overflow-wrap: anywhere;
}
.practice-commercial__heading h3:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-md);
}
.practice-commercial__body { display: grid; min-width: 0; gap: var(--space-3); }
/* ── detail hero: the one place that answers "what happens now" ───────────── */
.practice-commercial__hero {
  padding: var(--space-4);
  border: 1px solid rgba(var(--accent-rgb), .38);
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, rgba(var(--accent-rgb), .14), rgba(var(--panel-rgb), .5));
}
.practice-commercial__hero-eyebrow {
  margin: 0 0 var(--space-2);
  color: var(--accent-dark);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.practice-commercial__hero-copy {
  margin: var(--space-2) 0 0;
  color: var(--text);
  font-size: var(--fs-md);
  line-height: var(--lh-relaxed);
}
.practice-commercial__hero-action { margin-top: var(--space-4); }
.practice-commercial__reference {
  margin: var(--space-2) 0 0;
  color: var(--muted);
  font-size: var(--fs-2xs);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  overflow-wrap: anywhere;
}
.practice-commercial__back { align-self: flex-start; }

/* ── lifecycle stepper: connectors are pseudo-elements, so nothing depends on an
      animation the global reduced-motion rule would remove ──────────────────── */
.practice-lifecycle-steps {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  margin: var(--space-4) 0 0;
  padding: 0;
  list-style: none;
  counter-reset: lifecycle-step;
}
.practice-lifecycle-steps__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 700;
}
.practice-lifecycle-steps__item::before {
  counter-increment: lifecycle-step;
  content: counter(lifecycle-step);
  display: grid;
  place-items: center;
  width: 1.4rem;
  height: 1.4rem;
  flex: none;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .16);
  background: rgba(255, 255, 255, .05);
  font-size: var(--fs-2xs);
}
.practice-lifecycle-steps__item[data-state="done"] { color: var(--success); }
.practice-lifecycle-steps__item[data-state="done"]::before {
  content: '✓';
  border-color: var(--success);
  background: rgba(var(--success-rgb), .18);
  color: var(--success);
}
.practice-lifecycle-steps__item[data-state="current"] { color: var(--text); }
.practice-lifecycle-steps__item[data-state="current"]::before {
  border-color: var(--accent);
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: var(--on-accent);
}

/* ── collapsible sections: native <details>, keyboard-accessible with no JS ─── */
.practice-commercial__section {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: rgba(var(--panel-rgb), .38);
}
.practice-commercial__section-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-3);
  cursor: pointer;
  color: var(--text);
  font-size: var(--fs-sm);
  font-weight: 700;
}
.practice-commercial__section-summary:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-md);
}
.practice-commercial__section-note {
  color: var(--accent-2);
  font-size: var(--fs-xs);
  font-weight: 700;
}
.practice-commercial__section[open] > .practice-commercial__section-summary {
  border-bottom: 1px solid var(--border);
}
.practice-commercial__section > .practice-commercial__card {
  border: none;
  background: none;
}
.practice-commercial__card {
  min-width: 0;
  padding: var(--space-3);
  border: 1px solid rgba(var(--accent-rgb), .22);
  border-radius: var(--radius-md);
  background: rgba(var(--panel-rgb), .45);
}
.practice-commercial__card-title,
.practice-commercial__card p { margin: 0; }
.practice-commercial__card-title { margin-bottom: var(--space-2); font-size: var(--fs-sm); }
.practice-commercial__card p + p { margin-top: var(--space-1); }
.practice-commercial__strong { color: var(--text); font-weight: 700; }
.practice-commercial__muted { color: var(--text-secondary); font-size: var(--fs-xs); line-height: var(--lh-normal); }
.practice-commercial__reason {
  margin-top: var(--space-2) !important;
  padding: var(--space-2);
  border-left: 3px solid var(--warning);
  color: var(--text-secondary);
  white-space: pre-wrap;
}
.practice-commercial__price { color: var(--accent-2); font-size: var(--fs-xl); font-weight: 800; }
.practice-commercial__products { display: grid; gap: var(--space-2); margin-top: var(--space-3); }
.practice-commercial__product {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-2);
  border-radius: var(--radius-md);
  background: rgba(var(--accent-rgb), .07);
}
.practice-commercial__product .btn { justify-self: start; }
.practice-commercial__payment { margin-top: var(--space-3); }
.practice-commercial__notices { margin: var(--space-2) 0 0; padding-left: 1.1rem; }
.practice-commercial__notices { display: grid; gap: var(--space-3); }
.practice-lifecycle-timeline {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}
.practice-lifecycle-timeline__item {
  position: relative;
  padding: 0 0 var(--space-3) 1.35rem;
}
.practice-lifecycle-timeline__item:last-child { padding-bottom: 0; }
.practice-lifecycle-timeline__item::before {
  position: absolute;
  top: .35rem;
  bottom: -.35rem;
  left: .3rem;
  width: 1px;
  background: rgba(var(--accent-rgb), .28);
  content: '';
}
.practice-lifecycle-timeline__item:last-child::before { display: none; }
.practice-lifecycle-timeline__item::after {
  position: absolute;
  top: .35rem;
  left: 0;
  width: .65rem;
  height: .65rem;
  border: 2px solid var(--panel);
  border-radius: 50%;
  background: var(--accent-2);
  content: '';
}
.practice-lifecycle-timeline__content { display: grid; gap: .2rem; }
.practice-lifecycle-timeline__content p,
.practice-lifecycle-timeline__content time { margin: 0; }

/* ── resolution wizard (post-autofill guided Q&A) ────────────────────────── */
.overlay-panel--wizard { width: min(34rem, 100%); }
.wizard-progress { display: flex; align-items: center; gap: .7rem; margin-bottom: var(--space-4); }
.wizard-progress .progress-track--inline { flex: 1; }
.wizard-step-label { font-size: var(--fs-sm); color: var(--muted); white-space: nowrap; }
.wizard-context { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-bottom: var(--space-2); }
.wizard-badge {
  padding: .18rem .6rem;
  border-radius: var(--radius-full);
  font-size: var(--fs-xs);
  font-weight: 600;
  border: 1px solid transparent;
}
.wizard-badge--conflict { background: rgba(239, 68, 68, .16); border-color: rgba(239, 68, 68, .4); color: var(--danger-dark); }
.wizard-badge--missing { background: rgba(245, 158, 11, .14); border-color: rgba(245, 158, 11, .4); color: var(--warning-dark); }
.wizard-badge--ambiguous { background: rgba(59, 130, 246, .14); border-color: rgba(59, 130, 246, .4); color: var(--info-dark); }
.wizard-fieldref { font-size: var(--fs-sm); color: var(--text-secondary); font-weight: 600; }
.wizard-question { margin: 0 0 var(--space-3); color: var(--text); line-height: var(--lh-relaxed); }
.wizard-options {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  max-height: 46vh;
  overflow-y: auto;
}
.wizard-option {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  padding: .55rem .75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .04);
  cursor: pointer;
}
.wizard-option:hover { border-color: rgba(var(--accent-rgb), .55); }
.wizard-option:has(input:checked) {
  border-color: rgba(var(--accent-rgb), .8);
  background: rgba(var(--accent-rgb), .12);
}
.wizard-option__label { line-height: var(--lh-snug); }
.wizard-custom { margin-bottom: var(--space-3); }
.modal-actions--wizard { justify-content: space-between; }
.wizard-summary-counts { margin: 0 0 var(--space-2); color: var(--text-secondary); }
.resolution-summary {
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .35rem;
  max-height: 40vh;
  overflow-y: auto;
}
.resolution-summary__item {
  padding: .4rem .6rem;
  border-radius: var(--radius-md);
  font-size: var(--fs-sm);
  background: rgba(255, 255, 255, .04);
  border-left: 3px solid rgba(var(--success-rgb), .6);
}
.resolution-summary__item--skipped { border-left-color: rgba(245, 158, 11, .55); color: var(--muted); }
.resolution-summary__label { color: var(--text-secondary); }
.wizard-deferred {
  margin: 0 0 var(--space-3);
  padding: .6rem .8rem;
  border-radius: var(--radius-md);
  font-size: var(--fs-sm);
  background: rgba(var(--warning-rgb), .1);
  border: 1px solid rgba(var(--warning-rgb), .35);
  color: var(--warning-dark);
}

/* ── pre-submit validation issues modal ──────────────────────────────────── */
.overlay-panel--issues { width: min(36rem, 100%); }
.issues-list {
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  max-height: 50vh;
  overflow-y: auto;
}
.issue-item {
  padding: .6rem .75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .04);
}
.issue-item__head { display: flex; align-items: center; gap: .55rem; flex-wrap: wrap; margin-bottom: .25rem; }
.issue-item__field { font-size: var(--fs-xs); color: var(--muted); }
.issue-item__message { margin: 0; font-size: var(--fs-sm); color: var(--text); line-height: var(--lh-normal); }
.issue-item__suggestion { margin: .25rem 0 0; font-size: var(--fs-sm); color: var(--text-secondary); line-height: var(--lh-normal); }

/* ── misc ────────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  .iter-notice { grid-template-columns: 1fr; }
  .iter-notice__icon { display: none; }
  .hero-header { padding: 2rem 1rem 1.6rem; }
  .container { padding: 1rem .8rem; }
  .card-body { padding: .95rem; }
  .practice-submit-recovery__actions { display: grid; }
  .practice-submit-recovery__actions .btn { width: 100%; }
  .comune-listbox { max-height: min(19rem, 42dvh); }
  .comune-option { min-height: 56px; padding: .72rem .75rem; }
  .draft-card__body { align-items: stretch; flex-direction: column; }
  .draft-card__actions { justify-content: stretch; }
  .draft-card__actions .btn { width: 100%; }
  .success-card__action { width: 100%; }
  .practice-auth-actions { align-items: stretch; flex-direction: column-reverse; }
  .practice-auth-actions .btn { width: 100%; }
  .practice-area__heading { align-items: stretch; flex-direction: column; }
  .practice-area__heading .btn,
  .practice-area__row-actions .btn { width: 100%; }
  .practice-area__item-heading,
  .practice-commercial__heading { align-items: stretch; flex-direction: column; }
  .practice-commercial__heading .btn { width: auto; }
  /* a stacked badge must stay a badge, not become a full-width bar */
  .practice-area__item-heading .practice-area__badge { align-self: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  html { scroll-behavior: auto; }
}

.practice-document-group__more { margin-top: var(--space-2); }

/* ── onboarding tour (spotlight) ─────────────────────────────────────────────
   The ring IS the shade: its 200vmax box-shadow dims everything outside the cutout,
   so there is no second overlay element to keep in sync. NO backdrop-filter anywhere
   here — the page scrolls behind this layer while the tour drives scrollIntoView, and
   blurring a fixed element over the scroll path is the Chrome black-rectangle bug.
   Nothing here transitions, so the global reduced-motion rule finds every resting
   state already correct. */
.tut-layer { position: fixed; inset: 0; z-index: var(--z-tour); display: none; }
.tut-layer.is-open { display: block; }
.tut-ring {
  position: fixed;
  top: 50vh;
  left: 50vw;
  width: 0;
  height: 0;
  border: 2px solid var(--accent);
  border-radius: var(--radius-lg);
  box-shadow:
    0 0 0 4px var(--accent-light),
    0 0 24px 6px rgba(var(--accent-rgb), .40),
    0 0 0 200vmax rgba(7, 6, 18, .82);
  pointer-events: none;
}
.tut-ring--full { border-color: transparent; }
.tut-card {
  position: fixed;
  width: min(380px, calc(100vw - var(--space-6)));
  max-height: calc(100vh - var(--space-6));
  overflow-y: auto;
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
}
.tut-card:focus { outline: none; }
.tut-card:focus-visible { outline: none; box-shadow: var(--shadow-xl), var(--focus-ring); }
.tut-close {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  width: var(--iconbtn-md);
  height: var(--iconbtn-md);
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  color: var(--muted);
  background: var(--surface-1);
  font: inherit;
  font-size: var(--fs-xl);
  line-height: var(--lh-none);
  cursor: pointer;
}
.tut-close:hover { color: var(--text); background: var(--surface-3); }
.tut-close:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.tut-title {
  margin: 0;
  padding-right: var(--space-8);
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 800;
  line-height: var(--lh-snug);
}
.tut-body { color: var(--text-secondary); font-size: var(--fs-base); line-height: var(--lh-relaxed); }
.tut-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-1);
}
.tut-counter { color: var(--muted); font-size: var(--fs-xs); white-space: nowrap; font-variant-numeric: tabular-nums; }
.tut-skip {
  align-self: center;
  padding: var(--space-1);
  border: 0;
  background: none;
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.tut-skip:hover { color: var(--text); }
.tut-skip:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }
/* Mobile: dock to an edge. The JS clears inline coords under this breakpoint; the
   !important guards beat any stale top/left a live resize left behind. */
@media (max-width: 640px) {
  .tut-card {
    left: var(--space-3) !important;
    right: var(--space-3);
    width: auto !important;
    top: auto !important;
    bottom: calc(var(--space-3) + var(--safe-bottom));
    max-height: min(80vh, calc(100vh - var(--space-6)));
  }
  .tut-card.tut-dock-top { top: calc(var(--space-3) + var(--safe-top)) !important; bottom: auto; }
}

/* ── white-label light variant (?assoc= themes with mode:'light') ───────────
   The brand tokens (--accent…, --brand-bg…, --panel…) are set inline by
   applyAssocBranding (main.mjs). This block redefines the TOKEN LAYER — ink,
   hairlines, neutral surfaces, semantic triads and elevation — so the components
   below it need no per-component recolouring. Anything that still needs a rule
   here is overriding STRUCTURE (a gradient, a different SVG stroke), not colour.
   Add a token, not a component override, when this theme looks wrong. */
:root[data-theme="light"] {
  color-scheme: light;
  --text: #17212b;
  --text-secondary: rgba(23, 33, 43, .85);
  --muted: rgba(51, 65, 85, .74);
  --on-accent: #fff;
  --border: rgba(15, 23, 42, .16);
  --border-light: rgba(15, 23, 42, .09);
  --surface-1: rgba(15, 23, 42, .04);
  --surface-2: rgba(15, 23, 42, .06);
  --surface-3: rgba(15, 23, 42, .09);
  --success: #15803d;
  --success-rgb: 21, 128, 61;
  --success-dark: #166534;
  --warning: #b45309;
  --warning-rgb: 180, 83, 9;
  --warning-dark: #92400e;
  --danger: #e11d48;
  --danger-rgb: 225, 29, 72;
  --danger-dark: #9f1239;
  --info: #2563eb;
  --info-rgb: 37, 99, 235;
  --info-dark: #1d4ed8;
  --accent-dark: #5b21b6;
  --input-bg: #fff;
  --input-bg-focus: #fff;
  --shadow-xs: 0 1px 2px rgba(15, 23, 42, .04);
  --shadow-sm: 0 1px 3px rgba(15, 23, 42, .06), 0 1px 2px rgba(15, 23, 42, .04);
  --shadow-md: 0 4px 6px -1px rgba(15, 23, 42, .08), 0 2px 4px -2px rgba(15, 23, 42, .06);
  --shadow-lg: 0 10px 15px -3px rgba(15, 23, 42, .12), 0 4px 6px -4px rgba(15, 23, 42, .08);
  --shadow-xl: 0 20px 25px -5px rgba(15, 23, 42, .14), 0 8px 10px -6px rgba(15, 23, 42, .10);
}
:root[data-theme="light"] a { color: var(--accent); }
:root[data-theme="light"] a:hover { color: var(--accent-2); }
:root[data-theme="light"] body::before {
  background:
    radial-gradient(ellipse 90% 55% at 15% 8%, rgba(var(--accent-rgb), .10), transparent),
    radial-gradient(ellipse 70% 50% at 88% 18%, rgba(var(--accent-2-rgb), .08), transparent),
    linear-gradient(180deg, var(--brand-bg1), var(--brand-bg0) 40%);
}
/* --panel already resolves to the partner's pale surface in this theme, so the header
   only needs its elevation restated against a light page. */
:root[data-theme="light"] .app-header { box-shadow: var(--shadow-sm); }
:root[data-theme="light"] .legal-link { color: var(--accent); }
:root[data-theme="light"] .practice-area__current,
:root[data-theme="light"] .practice-area__item,
:root[data-theme="light"] .practice-commercial__card { background: rgba(255, 255, 255, .7); }
:root[data-theme="light"] .progress-orb__track { stroke: rgba(15, 23, 42, .1); }
:root[data-theme="light"] .progress-track { background: rgba(15, 23, 42, .1); }
:root[data-theme="light"] .card {
  background: linear-gradient(180deg, rgba(255, 255, 255, .85), rgba(255, 255, 255, .6));
}
:root[data-theme="light"] .card-header--dark {
  background: linear-gradient(135deg, rgba(var(--accent-rgb), .9), rgba(var(--accent-2-rgb), .85));
  border-bottom: 1px solid rgba(15, 23, 42, .1);
}
:root[data-theme="light"] .practice-document-group,
:root[data-theme="light"] .practice-document-slot,
:root[data-theme="light"] .practice-documents__status,
:root[data-theme="light"] .practice-documents__readiness { background: rgba(255, 255, 255, .58); }
:root[data-theme="light"] .form-control,
:root[data-theme="light"] .form-select { border-color: rgba(15, 23, 42, .18); }
:root[data-theme="light"] .form-control::placeholder { color: rgba(51, 65, 85, .45); }
:root[data-theme="light"] .comune-listbox {
  background: #fff;
  border-color: rgba(var(--accent-rgb), .35);
  box-shadow: var(--shadow-lg);
}
:root[data-theme="light"] .comune-option:hover,
:root[data-theme="light"] .comune-option[aria-selected="true"] { background: rgba(var(--accent-rgb), .09); }
:root[data-theme="light"] .select-wrap::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%23475569' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
:root[data-theme="light"] .form-select option { background: #fff; }
:root[data-theme="light"] .header-field { border-bottom-color: rgba(15, 23, 42, .16); color: var(--accent); }
:root[data-theme="light"] .repeater-item { border-color: rgba(15, 23, 42, .14); background: rgba(15, 23, 42, .03); }
:root[data-theme="light"] .btn-outline { color: var(--accent); }
:root[data-theme="light"] .tut-ring {
  box-shadow:
    0 0 0 4px var(--accent-light),
    0 0 24px 6px rgba(var(--accent-rgb), .30),
    0 0 0 200vmax rgba(15, 23, 42, .55);
}
:root[data-theme="light"] .tut-close { background: var(--surface-1); }
:root[data-theme="light"] .iter-notice {
  background: linear-gradient(135deg, rgba(var(--accent-rgb), .10), rgba(255, 255, 255, .96));
}
:root[data-theme="light"] .iter-notice__icon { background: rgba(var(--accent-rgb), .10); }
/* redundant with --surface-1, but test/ai-progress.test.mjs pins this selector's presence */
:root[data-theme="light"] .file-row { background: var(--surface-1); }
:root[data-theme="light"] .overlay { background: rgba(15, 23, 42, .4); }
:root[data-theme="light"] .ai-lane {
  background: linear-gradient(180deg, rgba(var(--accent-rgb), .06), rgba(255, 255, 255, .62));
}
:root[data-theme="light"] .ai-lane__step-dot { background: rgba(15, 23, 42, .05); border-color: rgba(15, 23, 42, .16); }
:root[data-theme="light"] .ai-lane__step-line { background: rgba(15, 23, 42, .12); }
:root[data-theme="light"] .ai-lane__timer { background: var(--surface-1); border-color: rgba(15, 23, 42, .08); }
:root[data-theme="light"] .ai-lane[data-tone="success"] .ai-lane__status { color: var(--success-dark); }
:root[data-theme="light"] .ai-lane[data-tone="warning"] .ai-lane__status { color: var(--warning-dark); }
:root[data-theme="light"] .ai-lane[data-tone="error"] .ai-lane__status { color: var(--danger-dark); }
:root[data-theme="light"] .ai-lane__notice { color: var(--warning-dark); }
:root[data-theme="light"] .practice-commercial__hero {
  background: linear-gradient(160deg, rgba(var(--accent-rgb), .1), rgba(255, 255, 255, .72));
}
:root[data-theme="light"] .practice-commercial__section { background: rgba(255, 255, 255, .6); }
:root[data-theme="light"] .practice-lifecycle-steps__item::before {
  border-color: rgba(15, 23, 42, .18);
  background: var(--surface-1);
}
:root[data-theme="light"] .practice-area__badge[data-tone="action"] {
  background: rgba(var(--warning-rgb), .12);
  color: var(--warning-dark);
}
:root[data-theme="light"] .practice-area__badge[data-tone="done"] {
  background: rgba(var(--success-rgb), .1);
  color: var(--success-dark);
}
:root[data-theme="light"] .practice-area__badge[data-tone="stopped"] {
  background: rgba(var(--danger-rgb), .1);
  color: var(--danger-dark);
}
:root[data-theme="light"] .practice-auth-value {
  background: rgba(var(--accent-rgb), .06);
  border-color: rgba(var(--accent-rgb), .24);
}
:root[data-theme="light"] .practice-area__empty {
  background: rgba(var(--accent-rgb), .05);
  border-color: rgba(var(--accent-rgb), .26);
}
:root[data-theme="light"] .practice-auth-dot[data-state="loading"],
:root[data-theme="light"] .practice-auth-dot[data-state="off"] {
  box-shadow: 0 0 0 3px rgba(15, 23, 42, .07);
}
:root[data-theme="light"] .ai-lane-dock {
  background: rgba(255, 255, 255, .98);
  box-shadow: var(--shadow-lg);
}
:root[data-theme="light"] .coverage-note.warn {
  background: rgba(var(--warning-rgb), .08);
  border-color: rgba(var(--warning-rgb), .3);
  color: var(--warning-dark);
}
:root[data-theme="light"] .draft-card[data-tone="warn"] {
  border-color: rgba(var(--warning-rgb), .28);
  background: linear-gradient(180deg, rgba(var(--warning-rgb), .07), rgba(255, 255, 255, .72));
}
:root[data-theme="light"] .submit-result.ok { background: rgba(var(--success-rgb), .08); border-color: rgba(var(--success-rgb), .3); color: var(--success-dark); }
:root[data-theme="light"] .submit-result.err { background: rgba(var(--danger-rgb), .07); border-color: rgba(var(--danger-rgb), .3); color: var(--danger-dark); }
:root[data-theme="light"] .practice-submit-recovery__error { background: rgba(var(--danger-rgb), .07); border-color: rgba(var(--danger-rgb), .3); color: var(--danger-dark); }
:root[data-theme="light"] .wizard-badge--conflict { background: rgba(239, 68, 68, .1); color: #b91c1c; }
:root[data-theme="light"] .wizard-badge--missing { background: rgba(245, 158, 11, .12); color: var(--warning-dark); }
:root[data-theme="light"] .wizard-badge--ambiguous { background: rgba(59, 130, 246, .1); color: var(--info-dark); }
:root[data-theme="light"] .wizard-option { background: rgba(15, 23, 42, .03); }
:root[data-theme="light"] .wizard-option:has(input:checked) { background: rgba(var(--accent-rgb), .08); }
:root[data-theme="light"] .resolution-summary__item { background: rgba(15, 23, 42, .03); }
:root[data-theme="light"] .issue-item { background: rgba(15, 23, 42, .03); }
:root[data-theme="light"] .wizard-deferred {
  background: rgba(var(--warning-rgb), .08);
  border-color: rgba(var(--warning-rgb), .3);
  color: var(--warning-dark);
}

[hidden] { display: none !important; }
