/* ==========================================================================
   Caratteri, serviti da qui e non da Google (30/09/2026)
   --------------------------------------------------------------------------
   Prima il foglio di stile arrivava da fonts.googleapis.com e i file da
   fonts.gstatic.com. Funzionava, ma costava tre cose:

   1. **privacy.** La richiesta comunica a Google l'indirizzo IP di chi visita,
      prima ancora che abbia scelto qualcosa sui cookie. Era l'unica chiamata a
      terzi che partiva da sola, ed è sparita.
   2. **velocità.** Due origini in più da risolvere (DNS + TLS) prima di sapere
      quali file servono, e tutto questo mentre la pagina non si disegna.
   3. **una deroga nella CSP.** Il vecchio caricamento usava un gestore inline
      (`onload="this.media='all'"`), che obbligava a tenere `'unsafe-hashes'`
      nella policy degli script. Senza quel gestore la deroga non serve più.

   I file sono gli stessi che serviva Google (woff2, sottoinsiemi latin e
   latin-ext), licenze aperte: Poppins e Caveat OFL, Inter OFL.

   `unicode-range` non è decorazione: dice al browser di scaricare il file
   latin-ext solo se nella pagina compare un carattere che sta lì dentro. Per
   un sito in italiano di norma non succede, e sono ~110 KB che non partono.

   Inter è un file solo, variabile: `font-weight: 400 600` copre tutti e tre i
   pesi che il sito usa, senza scaricare tre file.

   `font-display: swap`: il testo si legge subito col carattere di sistema e
   viene sostituito quando il file arriva. Mai una pagina bianca in attesa.
   ========================================================================== */

@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('../fonts/poppins-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('../fonts/poppins-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/poppins-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/poppins-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('../fonts/poppins-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('../fonts/poppins-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url('../fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url('../fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Caveat'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/caveat-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Caveat'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/caveat-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ==========================================================================
   Sbilanciarsi — design system
   --------------------------------------------------------------------------
   Palette and type from colors-theme.png (16/09): Verde bosco, Oliva, Ambra,
   Arancio, Corallo on Crema; Poppins SemiBold for titles, Inter for text.
   The brand hexes below are reproduced EXACTLY. Where one fails as text, a
   darker "-ink" step exists beside it — use that for anything a person reads.

   Contrast on crema (#F7F3EA), measured, not eyeballed:
     bosco 11.2   oliva 4.55   corallo 4.36   arancio 3.23   ambra 2.48
   So: bosco and oliva carry text. Corallo only via --corallo-ink. Arancio is
   large-text or decoration. Ambra is decoration only — except on the dark
   bosco band, where it reaches 4.54 and may be used for kickers.

   CLASS NAMING: nothing here uses a token an ad-blocker hunts (ad-, banner,
   promo, sponsor, social, share, popup, newsletter, widget, track). Blockers
   apply cosmetic filters AFTER paint, so such an element renders and then
   vanishes — only on machines that run a blocker. Keep the `sb-` prefix.
   ========================================================================== */

/* --------------------------------------------------------------- tokens -- */
:root {
  /* Brand — exact values from colors-theme.png. */
  --bosco:   #243a12;
  --oliva:   #6e7412;
  --ambra:   #c9930a;
  --arancio: #d46a1e;
  --corallo: #c84530;
  --crema:   #f7f3ea;

  /* Text-safe steps (>= 4.5:1 on crema and on white). */
  --corallo-ink: #b43e2b;   /* 5.2 on crema, 5.7 on white */
  --arancio-btn: #b65b1a;   /* white text 4.7 — closest passing shade of arancio */
  --arancio-btn-hover: #994c16; /* white text 6.2 */
  --bosco-deep:  #1b2c0d;   /* footer ground, pressed states */

  /* Washes: each brand hue mixed into crema. Fills only, never text. */
  --oliva-wash:  #ece9d9;   /* 8%  — the "soft" section ground */
  --oliva-30:    #cecda9;   /* 30% — borders, chart connectors */
  --ambra-wash:  #f3ebd8;   /* 8%  — the "warm" section ground */
  --ambra-16:    #f0e4c6;   /* 16% — warm chip fill */
  --ambra-30:    #e9d6a7;   /* 30% — warm borders */
  --arancio-16:  #f1ddc9;

  /* Neutrals, warmed to sit on crema. */
  --paper:    var(--crema); /* page ground */
  --paper-2:  #ffffff;      /* cards, as in the palette sheet */
  --ink:      #1f2a17;      /* 13.5 on crema */
  --ink-soft: #3f4a36;      /*  8.5 on crema */
  --muted:    #5e6552;      /*  5.5 on crema, 5.0 on --oliva-wash */
  --line:     #e6dfcf;
  --line-2:   #d6cdb8;

  /* On the dark bosco band and footer. */
  --on-dark:       var(--crema);   /* 11.2 */
  --on-dark-soft:  #d9dcc6;        /*  8.9 */
  --on-dark-muted: #b9c2a5;        /*  6.7 */

  /* Semantic roles — components use these, not the brand names directly, so
     a future palette change is a handful of lines. */
  --c-heading: var(--bosco);
  --c-link:    var(--bosco);
  --c-link-hover: var(--corallo-ink);
  --c-kicker:  var(--corallo-ink);
  --c-accent:  var(--arancio);     /* rules, large accent words */

  --font-title: "Poppins", ui-rounded, "Segoe UI", system-ui, -apple-system, Roboto, Arial, sans-serif;
  --font-body:  "Inter", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* Fluid type scale, 320px → 1280px viewport. Poppins runs wide, so the
     display steps sit a notch below where a serif would. */
  --t-xs:   0.8125rem;
  --t-sm:   0.9375rem;
  --t-base: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --t-lg:   clamp(1.0625rem, 1rem + 0.3vw, 1.25rem);
  --t-xl:   clamp(1.25rem, 1.12rem + 0.6vw, 1.5rem);
  --t-2xl:  clamp(1.6rem, 1.35rem + 1.15vw, 2.25rem);
  --t-3xl:  clamp(2rem, 1.6rem + 2vw, 3rem);
  --t-4xl:  clamp(2.35rem, 1.7rem + 3.2vw, 4.25rem);

  --s-1: 0.25rem;  --s-2: 0.5rem;   --s-3: 0.75rem;  --s-4: 1rem;
  --s-5: 1.5rem;   --s-6: 2rem;     --s-7: 3rem;     --s-8: 4rem;
  --s-9: 6rem;     --s-10: 8rem;

  --wrap: 72rem;
  --measure: 38rem;

  /* Rounder than before: the palette sheet uses soft cards and the logo is a
     cluster of fruit. Editorial-tight corners would fight both. */
  --radius: 8px;
  --radius-lg: 14px;

  --shadow-1: 0 1px 2px rgb(36 58 18 / 0.05), 0 6px 18px rgb(36 58 18 / 0.06);
  --shadow-2: 0 2px 8px rgb(36 58 18 / 0.08), 0 18px 44px rgb(36 58 18 / 0.12);

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;   /* sticky header must not cover anchor targets */
  /* The off-canvas drawer parks itself past the right edge and Chrome counts
     that toward the document's scrollable width, so the whole page could be
     dragged sideways on a phone. `clip` kills it; `hidden` would ALSO turn html
     into a scroll container and break the sticky header. Do not swap them. */
  overflow-x: clip;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-base);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.2; }
p, ul, ol, figure, blockquote { margin: 0; }
ul, ol { padding: 0; list-style: none; }

a { color: var(--c-link); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--c-link-hover); }

:focus-visible {
  outline: 2px solid var(--arancio);
  outline-offset: 3px;
  border-radius: 3px;
}

.sb-skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--bosco); color: var(--on-dark);
  padding: var(--s-3) var(--s-5); border-radius: 0 0 var(--radius) 0;
  font-size: var(--t-sm); text-decoration: none;
}
.sb-skip:focus { left: 0; color: var(--on-dark); }

.sb-vh {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.sb-emph { color: var(--c-heading); font-weight: 600; }

/* --------------------------------------------------------------- layout -- */
.sb-wrap {
  width: min(100% - 2.5rem, var(--wrap));
  margin-inline: auto;
}
@media (min-width: 48em) { .sb-wrap { width: min(100% - 5rem, var(--wrap)); } }

.sb-section { padding-block: var(--s-8); }
@media (min-width: 48em) { .sb-section { padding-block: var(--s-9); } }
.sb-section--tight { padding-block: var(--s-7); }
.sb-section--paper { background: var(--paper-2); }
.sb-section--soft  { background: var(--oliva-wash); }
.sb-section--warm  { background: var(--ambra-wash); }

.sb-stack > * + * { margin-top: var(--s-4); }
.sb-stack-lg > * + * { margin-top: var(--s-6); }

.sb-head { max-width: 44rem; }
.sb-head--center { margin-inline: auto; text-align: center; }

/* The short warm rule before a kicker is the recurring brand gesture: a line
   that starts off to one side, never centred. */
.sb-kicker {
  display: block;
  font-size: var(--t-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--c-kicker);
  margin-bottom: var(--s-3);
}
.sb-kicker::before {
  content: "";
  display: inline-block;
  width: 1.5rem; height: 2px;
  border-radius: 2px;
  background: var(--c-accent);
  vertical-align: 0.26em;
  margin-right: 0.65rem;
}
.sb-head--center .sb-kicker::before { display: none; }

.sb-title {
  font-family: var(--font-title);
  font-size: var(--t-2xl);
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--c-heading);
}
.sb-title--page { font-size: var(--t-3xl); }
/* An accent word in a heading: large text, so arancio's 3.2:1 is enough. */
.sb-title em, .sb-hero__title em { font-style: normal; color: var(--arancio); }

.sb-lede {
  font-size: var(--t-lg);
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: var(--measure);
}
.sb-head--center .sb-lede { margin-inline: auto; }

/* -------------------------------------------------------------- buttons -- */
/* Primary actions are bosco, the brand green (09/10, client's call — they were
   --arancio-btn until then). Crema text on bosco is ~11:1, the oliva hover with
   white text 5.0:1, so both states pass AA with room to spare. The orange
   stays on the button as the sticker (the slice below), which on a dark pill
   finally reads at full contrast.
   --arancio-btn is still defined: the hero's accent word and the last stage
   number of the percorso use it. Neither is a button. */
.sb-btn {
  --btn-bg: var(--bosco);
  --btn-fg: var(--on-dark);
  --btn-bd: var(--bosco);
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: 0.8rem 1.6rem;
  background: var(--btn-bg); color: var(--btn-fg);
  border: 1px solid var(--btn-bd); border-radius: 999px;
  font-family: var(--font-title); font-size: var(--t-sm); font-weight: 600;
  letter-spacing: 0.005em; text-decoration: none; cursor: pointer;
  white-space: nowrap;   /* a pill split over two lines reads as broken */
  transition: background 0.2s var(--ease), color 0.2s var(--ease),
              border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.sb-btn:hover {
  --btn-bg: var(--oliva); --btn-bd: var(--oliva); --btn-fg: #fff;
  transform: translateY(-1px);
}
/* The global `a:hover { color: coral }` is (0,1,1) and sets `color` directly,
   so it beat `.sb-btn { color: var(--btn-fg) }` (0,1,0): every <a> button
   turned coral on hover, unreadable on orange. Re-declaring `color` on the
   hover state (0,2,0) makes each variant's --btn-fg win again. */
.sb-btn:hover, .sb-btn:focus-visible, .sb-btn:active { color: var(--btn-fg); text-decoration: none; }
/* Same fight inside running text: `.sb-prose a` (0,1,1) colours and underlines
   every link, so a button placed in a page's content (the "Scarica" on the
   prima visita) came out as an underlined link painted on a pill. */
.sb-prose .sb-btn, .sb-prose .sb-btn:hover { color: var(--btn-fg); text-decoration: none; }
.sb-btn--ghost { --btn-bg: transparent; --btn-fg: var(--bosco); --btn-bd: var(--line-2); }
.sb-btn--ghost:hover { --btn-bg: var(--oliva-wash); --btn-fg: var(--bosco); --btn-bd: var(--oliva-30); }
/* On the dark bosco band a bosco button would vanish into the ground, so the
   action there is ambra with bosco text: 4.5:1 both ways. */
.sb-btn--light { --btn-bg: var(--ambra); --btn-fg: var(--bosco); --btn-bd: var(--ambra); }
.sb-btn--light:hover { --btn-bg: var(--crema); --btn-fg: var(--bosco); --btn-bd: var(--crema); }
.sb-btn--sm { padding: 0.5rem 1.1rem; font-size: var(--t-xs); }

.sb-actions { display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: center; }
.sb-head--center .sb-actions { justify-content: center; }

.sb-more {
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-family: var(--font-title); font-size: var(--t-sm); font-weight: 600;
  color: var(--c-link); text-decoration: none;
}
.sb-more::after { content: "→"; color: var(--arancio); transition: transform 0.2s var(--ease); }
.sb-more:hover { color: var(--c-link-hover); }
.sb-more:hover::after { transform: translateX(3px); }

/* ----------------------------------------------------------------- logo -- */
.sb-logo {
  display: inline-flex; align-items: center; gap: 0.55rem;
  text-decoration: none;
}
.sb-logo__mark { width: auto; height: 2.75rem; flex: none; }
/* Header: the real logo, one image. 822×124 shown at 38px tall, so ~3× the
   pixels a high-density screen asks for.
   TWO rules keep it from distorting, and both are needed: `flex: none` on the
   link and `max-width: none` on the img, because the global
   `img { max-width: 100% }` (line ~132) otherwise squeezes the WIDTH while the
   height stays fixed — the wordmark stretches and nobody notices. */
.sb-logo { flex: none; }
.sb-logo__full { width: auto; max-width: none; height: 2.375rem; display: block; flex: none; }
@media (max-width: 26em) { .sb-logo__full { height: 2.2rem; } }
/* Footer only: the wordmark as live text, sweeping from crema so it stays
   readable on the dark green. Logotypes are exempt from contrast minimums,
   but the accessible name still comes from this text. */
.sb-logo__word {
  font-family: var(--font-title);
  font-size: 1.5rem; font-weight: 700;
  letter-spacing: -0.02em; line-height: 1;
  color: var(--bosco);   /* fallback where background-clip:text is missing */
  background: linear-gradient(90deg,
    var(--bosco) 0%, var(--oliva) 34%, var(--ambra) 52%,
    var(--arancio) 72%, var(--corallo) 100%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
}
/* Windows High Contrast drops backgrounds, and transparent text would vanish
   with them. Give it a real colour. */
@media (forced-colors: active) {
  .sb-logo__word { background: none; -webkit-text-fill-color: CanvasText; color: CanvasText; }
}
.sb-logo--footer .sb-logo__mark { height: 2.5rem; }
/* On the dark footer the bosco end of the sweep disappears; start lighter. */
.sb-logo--footer .sb-logo__word {
  background-image: linear-gradient(90deg,
    var(--crema) 0%, var(--ambra) 45%, var(--arancio) 72%, var(--corallo) 100%);
}

/* --------------------------------------------------------------- header -- */
.sb-header {
  position: sticky; top: 0; z-index: 100;
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s var(--ease);
}
/* The frosted glass lives on a pseudo-element, NOT on the header. A
   backdrop-filter makes its element the containing block for every
   position:fixed descendant, and the mobile drawer is one: it resolved
   against the 76px header and opened 128px tall. The header is sticky with a
   z-index, so it is a stacking context and z-index:-1 stays inside it.
   (playbook/mobile-and-navigation.md, "A frosted header silently collapses
   the drawer inside it".) */
.sb-header::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  -webkit-backdrop-filter: saturate(1.3) blur(10px);
          backdrop-filter: saturate(1.3) blur(10px);
}
.sb-header.is-scrolled { border-bottom-color: var(--line); }
@supports not (backdrop-filter: blur(4px)) { .sb-header::before { background: var(--paper); } }

.sb-header__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-5);
  min-height: 4.75rem;
}

/* Nav: one markup tree serves both the mobile drawer and the desktop hover
   dropdowns (playbook/mobile-and-navigation.md). */
.sb-nav__toggle {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.55rem 0.9rem;
  background: var(--paper-2); border: 1px solid var(--line-2); border-radius: 999px;
  font-family: var(--font-title); font-size: var(--t-xs); font-weight: 600;
  color: var(--bosco); cursor: pointer;
}
.sb-nav__toggle svg { width: 1rem; height: 1rem; }
.sb-nav__toggle:focus-visible { outline: 2px solid var(--arancio); outline-offset: 2px; }

.sb-nav__list { display: grid; }
.sb-nav__link {
  display: block; padding: 0.55rem 0;
  color: var(--ink); text-decoration: none;
  font-family: var(--font-title); font-size: var(--t-sm); font-weight: 500;
}
.sb-nav__link:hover { color: var(--bosco); }
/* Current page = aria-current; a parent of the current page = .is-section.
   Both get the same marker. No font-weight change: bold is wider, and the
   whole bar would shift sideways every time you change page. */
.sb-nav__link[aria-current="page"], .sb-nav__link.is-section { color: var(--bosco); }

/* A non-link label inside a dropdown ("Le visite", "Valutazioni e test"). */
.sb-nav__group {
  font-family: var(--font-body);
  font-size: 0.6875rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--corallo-ink);
}

/* The caret only means something where the sub-list is a hover dropdown. In the
   mobile drawer the sub-list is already open below its parent, so it would be
   pointing at nothing. Hidden by default; the desktop block turns it on. */
.sb-nav__caret { display: none; }

/* --- mobile: off-canvas drawer (default; desktop rules override below) --- */
@media (max-width: 63.99em) {
  /* The toggle stays above the open drawer: it turns into "Chiudi", and the
     drawer's top padding keeps its row free. */
  .sb-nav__toggle { position: relative; z-index: 2; }
  .sb-nav {
    position: fixed; inset: 0 0 0 auto; z-index: 1;
    width: min(22rem, 88vw);
    height: 100vh; height: 100dvh;
    overscroll-behavior: contain;
    background: var(--paper-2);
    border-left: 1px solid var(--line);
    padding: 6rem var(--s-5) var(--s-6);
    overflow-y: auto;
    transform: translateX(100%);
    /* visibility, not just the transform: an off-screen drawer that is still
       `visible` keeps every link in the tab order, so a keyboard user tabs
       from the logo straight into a menu nobody can see. */
    visibility: hidden;
    transition: transform 0.28s var(--ease), visibility 0.28s;
    box-shadow: var(--shadow-2);
  }
  .sb-nav[data-open="true"] { transform: translateX(0); visibility: visible; }
  .sb-nav__list { gap: 0.1rem; }
  .sb-nav__item { border-bottom: 1px solid var(--line); }
  .sb-nav__link { padding: 0.9rem 0; font-size: var(--t-lg); }
  .sb-nav__link[aria-current="page"], .sb-nav__link.is-section,
  .sb-nav__sub a[aria-current="page"] {
    margin-inline: calc(-1 * var(--s-3));
    padding-inline: var(--s-3);
    background: var(--ambra-16);
    box-shadow: inset 3px 0 0 var(--arancio);
    border-radius: 0 var(--radius) var(--radius) 0;
  }
  .sb-nav__sub a[aria-current="page"] { color: var(--bosco); }
  .sb-nav__sub { display: grid; padding: 0 0 var(--s-3) var(--s-4); gap: 0.1rem; }
  /* block, not inline: an inline anchor is only as wide as its text, which on
     touch leaves most of the row dead to the thumb. */
  .sb-nav__sub a {
    display: block;
    padding: 0.5rem 0; font-size: var(--t-sm); color: var(--muted); text-decoration: none;
  }
  .sb-nav__sub a:hover { color: var(--bosco); }
  .sb-nav__group { padding: 0.75rem 0 0.15rem; }
  .sb-nav__cta { margin-top: var(--s-5); }
  .sb-scrim {
    position: fixed; inset: 0; z-index: 99;
    background: rgb(27 44 13 / 0.45);
    opacity: 0; pointer-events: none;
    transition: opacity 0.28s var(--ease);
  }
  .sb-scrim[data-open="true"] { opacity: 1; pointer-events: auto; }
}

/* Scroll-lock, for every overlay (drawer, privacy dialog), so not inside a
   breakpoint. overflow:hidden alone is ignored by iOS for touch scrolling,
   so the body is pinned; site.js saves and restores the offset. right:
   --sbw keeps the width the scrollbar had, so nothing reflows. */
body.sb-locked { position: fixed; left: 0; right: var(--sbw, 0); width: auto; overflow: hidden; }
/* A sticky header sticks to the scroll, and a pinned body has none: it
   would ride up with the page offset and take "Chiudi" with it. Fixed
   while locked; site.js pads the body by its height so nothing moves. */
body.sb-locked .sb-header { position: fixed; top: 0; left: 0; right: var(--sbw, 0); }

/* --- desktop: horizontal bar with hover dropdowns --- */
@media (min-width: 64em) {
  .sb-nav__toggle { display: none; }
  .sb-nav { display: flex; align-items: center; gap: var(--s-5); }
  .sb-nav__list { grid-auto-flow: column; align-items: center; gap: 1.35rem; }
  .sb-nav__item { position: relative; }
  .sb-nav__link { position: relative; isolation: isolate; padding: 1.6rem 0; }

  /* The marker: an amber-tinted pill hugging the label, with an orange bar
     along its base. The link itself keeps its tall padding (it is the hover
     bridge into the dropdown), so the pill is drawn inset from it.
     The bar is arancio, not ambra: a state indicator needs 3:1 against the
     cream ground, and ambra only reaches 2.5. */
  .sb-nav__link[aria-current="page"]::before,
  .sb-nav__link.is-section::before {
    content: "";
    position: absolute; z-index: -1;
    inset: 1.05rem -0.7rem;
    background: var(--ambra-16);
    border-radius: var(--radius);
  }
  .sb-nav__link[aria-current="page"]::after,
  .sb-nav__link.is-section::after {
    content: "";
    position: absolute;
    left: -0.7rem; right: -0.7rem; bottom: 1.05rem;
    height: 2px;
    background: var(--arancio);
    border-radius: 0 0 var(--radius) var(--radius);
  }

  .sb-nav__link--sub { display: inline-flex; align-items: center; gap: 0.35rem; }
  .sb-nav__caret {
    display: block; flex: none;
    width: 0.6rem; height: 0.4rem;
    color: var(--oliva);
    transition: transform 0.18s var(--ease), color 0.18s var(--ease);
  }
  /* Same trigger as the dropdown itself, so the caret and the panel can never
     disagree about whether the menu is open. */
  .sb-nav__item:hover > .sb-nav__link .sb-nav__caret,
  .sb-nav__item:focus-within > .sb-nav__link .sb-nav__caret {
    transform: rotate(180deg);
    color: var(--arancio);
  }

  .sb-nav__sub {
    position: absolute; top: 100%; left: 50%;
    transform: translateX(-50%) translateY(-0.4rem);
    /* Shrink-to-fit resolves against the containing block, which here is the
       nav item ("Expertise", ~70px), so every entry wrapped. max-content sizes
       to the longest label on one line; the cap stops a future long entry from
       running off a narrow laptop screen. */
    width: max-content;
    min-width: 15rem;
    max-width: min(28rem, 90vw);
    display: grid; gap: 0.1rem;
    padding: var(--s-3);
    background: var(--paper-2);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-2);
    opacity: 0; visibility: hidden;
    transition: opacity 0.18s var(--ease), transform 0.18s var(--ease), visibility 0.18s;
  }
  /* block, so the row IS the target. An inline anchor is only as wide as its
     text, which left "Prima visita" clickable across half its row and the
     hover fill stopping short of the panel edge. */
  .sb-nav__sub a {
    display: block;
    padding: 0.5rem 0.75rem; border-radius: var(--radius);
    font-size: var(--t-sm); color: var(--ink); text-decoration: none;
  }
  .sb-nav__sub a:hover,
  .sb-nav__sub a:focus-visible { background: var(--ambra-wash); color: var(--bosco); }
  .sb-nav__sub a[aria-current="page"] {
    background: var(--ambra-16); color: var(--bosco);
    box-shadow: inset 3px 0 0 var(--arancio);
  }
  .sb-nav__group { padding: 0.65rem 0.75rem 0.2rem; }
  .sb-nav__group:first-child { padding-top: 0.25rem; }
  .sb-nav__group:not(:first-child) { margin-top: 0.35rem; border-top: 1px solid var(--line); }

  /* :focus-within keeps the dropdown reachable by keyboard. */
  .sb-nav__item:hover > .sb-nav__sub,
  .sb-nav__item:focus-within > .sb-nav__sub {
    opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0);
  }
  .sb-scrim { display: none; }
}

/* La banda stretta del desktop, 1024–1183px: la riga ci sta ancora, ma di
   misura. Si cede in quest'ordine, dal meno al più visibile — prima
   l'etichetta del bottone ("Prima visita" invece di "Prenota la prima
   visita"), poi il logo, poi lo spazio fra le voci. Sotto i 1024px non basta
   più e il menu diventa il pannello laterale: il marchio non si smonta mai.
   Il conto a 1024px: logo 202 + 24 + voci 542 + 24 + bottone 116 = 908 px su
   929 disponibili. Se aggiungi una voce al menu rifai il conto, o la riga va
   a capo prima di arrivare alla soglia. */
.sb-label-short { display: none; }
@media (min-width: 64em) and (max-width: 73.99em) {
  .sb-label-long  { display: none; }
  .sb-label-short { display: inline; }
  .sb-logo__full  { height: 1.9rem; }
  .sb-nav__list   { gap: 1rem; }
}

/* ----------------------------------------------------------------- hero -- */
.sb-hero {
  position: relative;
  padding-block: var(--s-8) var(--s-9);
  overflow: hidden;
}
@media (min-width: 48em) { .sb-hero { padding-block: var(--s-9) var(--s-10); } }

/* The "mucchio": grains that thicken toward the corner, now in amber.
   Decorative only — aria-hidden in the markup, and it must never carry meaning. */
.sb-hero__grains {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    radial-gradient(circle at center, var(--ambra) 1.3px, transparent 1.4px);
  background-size: 15px 15px;
  -webkit-mask-image: radial-gradient(120% 90% at 88% 8%, #000 0%, transparent 60%);
          mask-image: radial-gradient(120% 90% at 88% 8%, #000 0%, transparent 60%);
  opacity: 0.45;
}
.sb-hero > .sb-wrap { position: relative; z-index: 1; }

.sb-hero__title {
  font-family: var(--font-title);
  font-size: var(--t-4xl);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--c-heading);
  max-width: 17ch;
}
.sb-hero__lede {
  margin-top: var(--s-5);
  font-size: var(--t-lg);
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: 34rem;
}
.sb-hero__actions { margin-top: var(--s-6); }
.sb-hero__lede em { font-style: normal; font-weight: 600; color: var(--arancio-btn); }
/* "non è" in the headline: the negation, in coral ink (5.2:1 on crema), so
   the "no" in the title and the answer's orange "granello" read as a pair. */
.sb-hero__title .sb-hero__not { font-style: normal; color: var(--corallo-ink); white-space: nowrap; }

/* Home hero: words left, the cambiamento drawing right. The drawing is wide
   (3:2), so it takes the larger share and overhangs the wrap to the right,
   where the hero clips it; its ground is within 2 levels of crema, so
   `darken` (from .sb-hero__fig img) melts it into the page and the grains. */
.sb-hero__split { display: grid; gap: var(--s-6); align-items: center; }
/* Same layering as the percorso hero: a z-indexed wrap is a stacking context,
   and `darken` inside it blends with nothing, so the drawing's ground hid the
   grains as a pale rectangle. Wrap flattened; figure (0) < grains (1) < words (2). */
.sb-hero:has(.sb-hero__split) > .sb-wrap { z-index: auto; }
.sb-hero:has(.sb-hero__split) .sb-hero__grains { z-index: 1; }
.sb-hero__words, .sb-hero__meta { position: relative; z-index: 2; }
/* NO z-index on this figure (it would override .sb-hero__fig's z-index:0):
   a z-indexed box is its own stacking context, and `darken` on the img
   inside it then blends with nothing, so the raw ground showed, too bright.
   Without it the img blends with the hero's crema; the grains (z 1) still
   paint above it. */
.sb-hero__split > .sb-hero__fig--home { position: static; z-index: auto; }
.sb-hero__fig--home { margin-top: var(--s-2); }
@media (min-width: 56em) {
  /* Text gets the larger share: at 0.95/1.15 the 68px title broke "Il /
     cambiamento" onto four lines from 1280px up. 1.12/1 keeps three lines at
     every width (measured 1024–1920); the drawing is ~14% smaller. */
  .sb-hero__split { grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr); gap: var(--s-5); }
  .sb-hero__fig--home { margin: 0 calc(-1 * var(--s-6)) 0 0; }
  .sb-hero__split .sb-hero__title { font-size: var(--t-3xl); }
}
@media (min-width: 75em) { .sb-hero__split .sb-hero__title { font-size: var(--t-4xl); } }

.sb-hero__meta {
  margin-top: var(--s-7);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line);
  display: grid; gap: var(--s-4);
}
@media (min-width: 40em) { .sb-hero__meta { grid-template-columns: repeat(3, 1fr); gap: var(--s-6); } }
.sb-hero__meta dt {
  font-size: var(--t-xs); letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--c-kicker); font-weight: 600;
}
.sb-hero__meta dd { margin: 0.35rem 0 0; font-size: var(--t-sm); color: var(--ink-soft); }

/* ------------------------------------------------------- pull quote/band -- */
.sb-quote {
  font-family: var(--font-title);
  font-size: var(--t-2xl);
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: -0.015em;
  color: var(--c-heading);
  max-width: 30ch;
}
.sb-quote__by {
  display: block; margin-top: var(--s-4);
  font-family: var(--font-body);
  font-size: var(--t-sm); font-weight: 500;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted);
}

.sb-band {
  background: var(--bosco);
  color: var(--on-dark);
  padding-block: var(--s-8);
}
.sb-band .sb-title, .sb-band .sb-quote { color: var(--on-dark); }
/* Arancio on bosco is only 3.1:1 — ambra (4.5) for accent words on the band. */
.sb-band .sb-title em, .sb-band .sb-quote em { color: var(--ambra); }
.sb-band .sb-kicker { color: var(--ambra); }                 /* 4.5 on bosco */
.sb-band .sb-kicker::before { background: var(--arancio); }
.sb-band .sb-lede { color: var(--on-dark-soft); }
/* --muted is tuned for crema and goes near-invisible on bosco. */
.sb-band .sb-quote__by, .sb-band .sb-meta { color: var(--on-dark-muted); }
/* A link on a dark band needs its own hover, or it jumps to the global link
   colour and disappears (playbook/css-and-render-blocking.md). */
.sb-band a:not(.sb-btn) { color: var(--on-dark); }
.sb-band a:not(.sb-btn):hover { color: var(--ambra); }
.sb-band .sb-more::after { color: var(--ambra); }
.sb-band .sb-fact { background: rgb(247 243 234 / 0.1); border-color: rgb(247 243 234 / 0.22); color: var(--on-dark); }
.sb-band .sb-fact--warm { background: var(--ambra); border-color: var(--ambra); color: var(--bosco); }

/* The percorso on /servizi: text beside its eight lessons. */
.sb-band__split { display: grid; gap: var(--s-7); align-items: center; }
@media (min-width: 56em) { .sb-band__split { grid-template-columns: 1.1fr 1fr; gap: var(--s-8); } }

.sb-ministeps {
  counter-reset: ms;
  display: grid; gap: 0;
  border-top: 1px solid rgb(247 243 234 / 0.16);
}
.sb-ministeps li {
  counter-increment: ms;
  display: grid; grid-template-columns: 2.25rem 1fr; align-items: baseline;
  padding: 0.7rem 0;
  border-bottom: 1px solid rgb(247 243 234 / 0.16);
  font-size: var(--t-sm); color: var(--on-dark-soft);
}
.sb-ministeps li::before {
  content: counter(ms, decimal-leading-zero);
  font-family: var(--font-title); font-weight: 600; color: var(--ambra);
}

/* ---------------------------------------------------------------- cards -- */
.sb-grid { display: grid; gap: var(--s-5); }
.sb-grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }
.sb-grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }

.sb-card {
  position: relative;
  display: flex; flex-direction: column;
  padding: var(--s-6);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: 0 1px 2px rgb(36 58 18 / 0.03);
  transition: border-color 0.22s var(--ease), box-shadow 0.22s var(--ease),
              transform 0.22s var(--ease);
}
.sb-card:hover { border-color: var(--ambra-30); box-shadow: var(--shadow-1); transform: translateY(-2px); }
/* The lead card of a group: a warm bar along the top edge. */
.sb-card--accent { border-top: 3px solid var(--arancio); }
.sb-card__eyebrow {
  font-size: var(--t-xs); letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 600; color: var(--oliva);   /* cards are white: 5.0:1 */
  margin-bottom: var(--s-3);
}
.sb-card__title {
  font-family: var(--font-title);
  font-size: var(--t-xl); font-weight: 600; letter-spacing: -0.01em;
  color: var(--c-heading);
}
.sb-card__text { margin-top: var(--s-3); color: var(--muted); font-size: var(--t-sm); }
.sb-card__foot { margin-top: auto; padding-top: var(--s-5); }

/* Whole-card click target without nesting interactive elements. */
.sb-card__link { color: inherit; text-decoration: none; }
.sb-card__link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }

/* Featured service: the card plus a panel listing what it includes. */
.sb-feature {
  position: relative;
  display: grid;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-top: 3px solid var(--arancio);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: box-shadow 0.22s var(--ease), transform 0.22s var(--ease);
}
.sb-feature:hover { box-shadow: var(--shadow-1); transform: translateY(-2px); }
@media (min-width: 52em) { .sb-feature { grid-template-columns: 1.5fr 1fr; } }
.sb-feature__main { display: flex; flex-direction: column; padding: var(--s-6); }
@media (min-width: 52em) { .sb-feature__main { padding: var(--s-7); } }
.sb-feature__title {
  font-family: var(--font-title);
  font-size: var(--t-2xl); font-weight: 600; letter-spacing: -0.015em;
  color: var(--c-heading);
}
.sb-feature__aside { padding: var(--s-6); background: var(--ambra-wash); }
@media (min-width: 52em) { .sb-feature__aside { padding: var(--s-7) var(--s-6); } }
.sb-feature__label {
  font-size: var(--t-xs); letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 600; color: var(--corallo-ink); margin-bottom: var(--s-4);
}

.sb-checklist { display: grid; gap: var(--s-3); }
.sb-checklist li {
  position: relative; padding-left: 1.75rem;
  font-size: var(--t-sm); color: var(--ink);
}
/* An olive disc with a crema tick drawn on top. Plain background layers, no
   CSS masks: masks need two syntaxes and still fail on some mobile builds. */
.sb-checklist li::before {
  content: "";
  position: absolute; left: 0; top: 0.2em;
  width: 1.1rem; height: 1.1rem; border-radius: 50%;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5.5 10.4l3 3 6-6.2' fill='none' stroke='%23f7f3ea' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 100% no-repeat,
    var(--oliva);
}

/* "Già compresa in Prima visita, Visita di controllo" on a measurement page. */
.sb-included-in {
  margin-top: var(--s-5);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.3rem;
  font-size: var(--t-sm); color: var(--ink-soft);
}
.sb-included-in__label {
  margin-right: 0.35rem;
  padding: 0.2rem 0.6rem;
  background: var(--oliva-wash); border-radius: 999px;
  font-size: var(--t-xs); font-weight: 600; color: var(--bosco);
}
.sb-included-in__note { color: var(--muted); }

.sb-facts { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-4); }
.sb-fact {
  padding: 0.3rem 0.75rem;
  background: var(--oliva-wash);
  border: 1px solid var(--oliva-30);
  border-radius: 999px;
  font-size: var(--t-xs); color: var(--bosco); font-weight: 600;
}
/* Price, duration of a programme, the Metromare stop: the warm chip. The text
   stays bosco — orange text on an orange tint measured 4.2:1 and failed. */
.sb-fact--warm { background: var(--ambra-16); border-color: var(--ambra-30); color: var(--bosco); }

/* ------------------------------------------------------------ step list -- */
.sb-steps { display: grid; gap: 0; counter-reset: step; }
.sb-step {
  position: relative;
  counter-increment: step;
  padding: var(--s-5) 0 var(--s-5) 4.25rem;
  border-top: 1px solid var(--line);
}
.sb-step:last-child { border-bottom: 1px solid var(--line); }
/* Oliva, not arancio: the numerals sit on crema AND on the olive-wash
   sections, and only oliva clears 3:1 as large text on both. */
.sb-step::before {
  content: counter(step, decimal-leading-zero);
  position: absolute; left: 0; top: calc(var(--s-5) - 0.1rem);
  width: 2.75rem;
  font-family: var(--font-title); font-weight: 600;
  font-size: var(--t-xl); letter-spacing: -0.02em;
  color: var(--oliva);
  line-height: 1;
}
.sb-step__title {
  font-family: var(--font-title);
  font-size: var(--t-lg); font-weight: 600; color: var(--c-heading);
}
.sb-step__body { margin-top: var(--s-2); color: var(--muted); font-size: var(--t-sm); }
.sb-step__body p + p { margin-top: var(--s-2); }

/* ------------------------------------------------------------- pill list -- */
.sb-pills { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.sb-pill {
  padding: 0.45rem 0.95rem;
  background: var(--paper-2);
  border: 1px solid var(--line-2);
  border-radius: 999px;
  font-size: var(--t-sm); color: var(--ink-soft);
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease);
}
.sb-pill a { color: inherit; text-decoration: none; }
.sb-pill:has(a:hover) { border-color: var(--arancio); background: var(--ambra-wash); }

.sb-area { margin-top: var(--s-6); }
.sb-area__name {
  font-size: var(--t-xs); letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 600; color: var(--c-kicker); margin-bottom: var(--s-3);
}

/* ---------------------------------------------------------------- prose -- */
/* Long-form body copy from the WYSIWYG. Element-qualified rules here outrank
   bare component classes, so keep components out of .sb-prose. */
.sb-prose { max-width: var(--measure); font-size: var(--t-base); color: var(--ink-soft); }
.sb-prose > * + * { margin-top: var(--s-4); }
.sb-prose h2 {
  font-family: var(--font-title);
  font-size: var(--t-xl); font-weight: 600; letter-spacing: -0.01em;
  color: var(--c-heading);
  margin-top: var(--s-7);
}
.sb-prose h3 {
  font-family: var(--font-title);
  font-size: var(--t-lg); font-weight: 600; color: var(--c-heading);
  margin-top: var(--s-6);
}
.sb-prose p { line-height: 1.75; }
.sb-prose strong { color: var(--ink); font-weight: 600; }
/* A highlighter stroke: amber wash painted slightly past the words, the way
   a marker overshoots. Text stays ink, so the contrast is untouched. */
.sb-prose mark {
  background: linear-gradient(to top, var(--ambra-30) 0 62%, transparent 62%);
  color: inherit; padding-inline: 0.15em; margin-inline: -0.15em;
  border-radius: 2px;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.sb-prose em { font-style: italic; }
/* Tables in body copy (the cookie list). Scrollable on a phone rather than
   squeezed: a four-column table at 375px is unreadable otherwise. */
.sb-prose table {
  width: 100%; border-collapse: collapse;
  font-size: var(--t-sm); text-align: left;
}
.sb-prose thead th {
  font-family: var(--font-title); font-size: var(--t-xs); letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--oliva); font-weight: 600;
  border-bottom: 1px solid var(--line-2);
}
.sb-prose th, .sb-prose td { padding: var(--s-3) var(--s-3) var(--s-3) 0; vertical-align: top; }
.sb-prose tbody tr + tr td { border-top: 1px solid var(--line); }
.sb-prose td code {
  font-size: 0.875em; background: var(--crema);
  padding: 0.1rem 0.35rem; border-radius: var(--radius);
}
@media (max-width: 40em) {
  .sb-prose table { display: block; overflow-x: auto; white-space: nowrap; }
  .sb-prose td, .sb-prose th { white-space: normal; min-width: 8rem; padding-right: var(--s-4); }
}
.sb-prose a { color: var(--c-link); text-decoration: underline; text-decoration-color: var(--arancio); }
.sb-prose a:hover { color: var(--c-link-hover); }
.sb-prose ul, .sb-prose ol { padding-left: 1.35rem; }
.sb-prose ul { list-style: disc; }
.sb-prose ol { list-style: decimal; }
.sb-prose li + li { margin-top: var(--s-2); }
.sb-prose li::marker { color: var(--arancio); }
/* A list meant to be ticked off (the blood tests to bring to the first visit):
   an empty box instead of a bullet, two columns once there is room. NOT
   .sb-checklist: that name is the ticked "Comprende" list of the feature card. */
.sb-prose ul.sb-boxlist { list-style: none; padding-left: 0; columns: 2 14rem; column-gap: var(--s-7); }
.sb-boxlist li { position: relative; padding-left: 1.7rem; break-inside: avoid; }
.sb-boxlist li + li { margin-top: var(--s-2); }
.sb-boxlist li::before {
  content: ""; position: absolute; left: 0; top: 0.3em;
  width: 0.95em; height: 0.95em; border: 2px solid var(--oliva); border-radius: 3px;
}
.sb-prose blockquote {
  padding-left: var(--s-5);
  border-left: 3px solid var(--ambra);
  font-family: var(--font-title);
  font-size: var(--t-lg); font-weight: 500; color: var(--c-heading);
}
.sb-prose img { border-radius: var(--radius-lg); margin-block: var(--s-6); }
.sb-prose hr { border: 0; border-top: 1px solid var(--line); margin-block: var(--s-7); }

/* ------------------------------------------------------------------ faq -- */
/* <details>/<summary> with the heading INSIDE the summary — keeps the outline
   correct and still gets FAQ rich-result markup (see seo-and-crawlability.md). */
.sb-faq { max-width: 46rem; }
.sb-faq__item { border-bottom: 1px solid var(--line); }
.sb-faq__item:first-child { border-top: 1px solid var(--line); }
.sb-faq__q {
  display: flex; align-items: flex-start; gap: var(--s-4);
  padding: var(--s-5) 0;
  cursor: pointer; list-style: none;
}
.sb-faq__q::-webkit-details-marker { display: none; }
.sb-faq__q h3 {
  flex: 1;
  font-family: var(--font-title);
  font-size: var(--t-base); font-weight: 600; color: var(--c-heading);
  line-height: 1.45;
}
.sb-faq__q::after {
  content: "+";
  flex: none;
  font-family: var(--font-title);
  font-size: 1.5rem; line-height: 1; color: var(--arancio);
  transition: transform 0.2s var(--ease);
}
.sb-faq__item[open] .sb-faq__q::after { transform: rotate(45deg); }
.sb-faq__a { padding-bottom: var(--s-5); color: var(--muted); max-width: var(--measure); }
.sb-faq__a p + p { margin-top: var(--s-3); }

/* ---------------------------------------------------------- article bits -- */
.sb-meta {
  display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: center;
  font-size: var(--t-xs); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted);
}
.sb-meta > * + *::before { content: "·"; margin-right: var(--s-3); color: var(--line-2); }


.sb-cover {
  border-radius: var(--radius-lg);
  aspect-ratio: 16 / 9;
  object-fit: cover;
  width: 100%;
  background: var(--oliva-wash);
}
.sb-cover--tall { aspect-ratio: 4 / 5; }
/* A cover taller than wide is a poster or a flyer (09/10: the Ubik event):
   the 16:9 crop above would keep only its middle band and cut the title off.
   Shown whole instead, at a width where its text is still readable. */
.sb-cover--poster {
  aspect-ratio: auto; object-fit: contain; height: auto;
  width: min(100%, 30rem); margin-inline: auto; display: block;
  box-shadow: var(--shadow-1);
}

/* A cut-out portrait standing on a flat warm ground. The subject is
   bottom-aligned inside a 4:5 frame, so the leftover space above reads as
   headroom rather than as a gap. width/height on the <img> reserve the box and
   keep the sidebar from jumping while it loads.
   01/10: the dotted grain is gone (client's call) — the ground is one flat
   wash now. The dots survive on .sb-ph below, which is a placeholder and wants
   to look provisional. */
.sb-portrait {
  margin: 0;
  display: grid;
  align-content: end;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border: 1px solid var(--ambra-30);
  border-radius: var(--radius-lg);
  background: var(--ambra-wash);
}
.sb-portrait img { width: 100%; height: auto; }

/* Placeholder used until real photography arrives. */
.sb-ph {
  display: grid; place-items: center;
  background:
    radial-gradient(circle at center, var(--ambra) 1.1px, transparent 1.2px) 0 0 / 13px 13px,
    var(--ambra-wash);
  border: 1px solid var(--ambra-30);
  border-radius: var(--radius-lg);
  color: var(--bosco);
  font-size: var(--t-xs); letter-spacing: 0.14em; text-transform: uppercase;
  aspect-ratio: 4 / 5;
}

/* ----------------------------------------------------------------- form -- */
.sb-form { display: grid; gap: var(--s-4); max-width: 34rem; }
.sb-field { display: grid; gap: var(--s-2); }
.sb-field > label { font-size: var(--t-sm); font-weight: 600; color: var(--c-heading); }
.sb-field input, .sb-field textarea, .sb-field select {
  width: 100%;
  padding: 0.75rem 0.9rem;
  font: inherit; font-size: var(--t-sm); color: var(--ink);
  background: var(--paper-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
}
.sb-field input:focus, .sb-field textarea:focus, .sb-field select:focus {
  border-color: var(--oliva); outline-offset: 1px;
}
.sb-field textarea { min-height: 9rem; resize: vertical; }
/* La sommina antispam: il campo si aspetta due cifre, non una frase. Largo
   quanto gli altri sembrerebbe chiedere chissà cosa. */
.sb-field--narrow input { max-width: 7rem; }
.sb-field__hint { font-size: var(--t-xs); color: var(--muted); }
.sb-consent { display: flex; gap: var(--s-3); align-items: flex-start; font-size: var(--t-sm); color: var(--muted); }
.sb-consent input { margin-top: 0.3rem; flex: none; accent-color: var(--bosco); }

/* ----------------------------------------------------- dialog / sheet -- */
/* The privacy policy over the form. A bottom sheet on a phone (thumb
   reach, and the form stays visible above it), a centred panel from tablet
   up. Only the body scrolls; head and foot stay put. Never style display
   on the closed dialog: [open] is what shows it. */
.sb-sheet {
  padding: 0; border: 0; background: transparent; color: var(--ink);
  width: 100%; max-width: 100%; max-height: 88dvh;
  margin: auto 0 0;               /* stuck to the bottom edge */
  overscroll-behavior: contain;
}
.sb-sheet::backdrop { background: rgb(27 44 13 / 0.5); }
.sb-sheet__box {
  display: flex; flex-direction: column; max-height: 88dvh;
  background: var(--paper-2);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  box-shadow: var(--shadow-2);
}
.sb-sheet[open] .sb-sheet__box { animation: sb-sheet-up 0.28s var(--ease); }
@keyframes sb-sheet-up { from { transform: translateY(100%); } }
.sb-sheet__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-4);
  padding: var(--s-5) var(--s-5) var(--s-4);
  border-bottom: 1px solid var(--line);
}
/* The grab handle: says "sheet" at a glance. Decoration, not a control. */
.sb-sheet__head { position: relative; }
.sb-sheet__head::before {
  content: ""; position: absolute; top: 0.55rem; left: 50%; translate: -50% 0;
  width: 2.5rem; height: 4px; border-radius: 4px; background: var(--line-2);
}
.sb-sheet__title { font-family: var(--font-title); font-size: var(--t-lg); color: var(--c-heading); }
.sb-sheet__close {
  display: grid; place-items: center; flex: none;
  width: 2.75rem; height: 2.75rem; border-radius: 999px;
  background: var(--crema); border: 1px solid var(--line-2); color: var(--bosco); cursor: pointer;
}
.sb-sheet__close svg { width: 1rem; height: 1rem; }
.sb-sheet__close:focus-visible { outline: 2px solid var(--arancio); outline-offset: 2px; }
.sb-sheet__body { padding: var(--s-5); overflow-y: auto; overscroll-behavior: contain; }
.sb-sheet__foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-4);
  padding: var(--s-4) var(--s-5) max(var(--s-4), env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
}
@media (min-width: 48em) {
  .sb-sheet { width: min(40rem, calc(100% - 2 * var(--s-6))); max-height: 80vh; margin: auto; }
  .sb-sheet__box { max-height: 80vh; border-radius: var(--radius-lg); }
  .sb-sheet[open] .sb-sheet__box { animation-name: sb-sheet-in; }
  @keyframes sb-sheet-in { from { opacity: 0; transform: translateY(0.75rem) scale(0.98); } }
  .sb-sheet__head::before { display: none; }
}

.sb-note {
  padding: var(--s-5);
  background: var(--ambra-wash);
  border-left: 3px solid var(--ambra);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: var(--t-sm); color: var(--ink-soft);
}
.sb-note strong { color: var(--c-heading); }

/* --------------------------------------------------------------- footer -- */
/* One step darker than the bosco band, so a closing CTA band directly above
   still reads as a separate block. */
.sb-footer {
  background: var(--bosco-deep);
  color: var(--on-dark-soft);
  padding-block: var(--s-8) var(--s-6);
  font-size: var(--t-sm);
}
.sb-footer a { color: var(--on-dark); text-decoration: none; }
.sb-footer a:hover { color: var(--ambra); text-decoration: underline; }
.sb-footer__cols {
  display: grid; gap: var(--s-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
}
.sb-footer__title {
  font-size: var(--t-xs); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ambra); font-weight: 600; margin-bottom: var(--s-3);
}
.sb-footer__list { display: grid; gap: var(--s-2); }

/* "Indicazioni stradali": its own line right under an address (footer,
   /contatti, /dove-ricevo), opening Google Maps directions. */
.sb-directions { display: block; margin-top: var(--s-2); }
.sb-footer .sb-directions a { color: var(--ambra); }
.sb-directions__link { display: inline-flex; align-items: center; gap: 0.45rem; font-weight: 600; }
/* On light cards the sign is orange, like the arrows of the .sb-more links. */
.sb-card .sb-directions__icon { color: var(--arancio); }
.sb-directions__icon { width: 1.15rem; height: 1.15rem; flex: none; }
.sb-footer__claim { margin-top: var(--s-4); max-width: 24rem; color: var(--on-dark-muted); }
.sb-footer__legal {
  margin-top: var(--s-7); padding-top: var(--s-5);
  border-top: 1px solid rgb(247 243 234 / 0.12);
  display: flex; flex-wrap: wrap; gap: var(--s-4);
  justify-content: space-between;
  font-size: var(--t-xs); color: var(--on-dark-muted);
}
.sb-footer__legal a { color: var(--on-dark-soft); }
/* Firma di chi ha fatto il sito: presente e leggibile, mai in concorrenza con
   i dati del cliente. Va a capo da sola sulle righe strette. */
.sb-footer__credit { flex-basis: 100%; }
/* Questo è l'unico collegamento del sito che sta DENTRO una frase, e fra il suo
   colore e quello del testo intorno corrono 1,32:1 — sotto il 3:1 che servirebbe
   per distinguerlo col solo colore (WCAG 1.4.1). Sottolineato: la distinzione
   non dipende più dal colore, e chi non percepisce la differenza lo vede lo
   stesso. Gli altri due (Privacy, Cookie) stanno da soli su una riga e non
   hanno testo attorno da cui distinguersi. */
.sb-footer__credit a { text-decoration: underline; text-underline-offset: 0.18em; }
@media (min-width: 56em) { .sb-footer__credit { flex-basis: auto; margin-left: auto; } }

/* ----------------------------------------------------- split page layout -- */
.sb-split { display: grid; gap: var(--s-6); align-items: start; }
@media (min-width: 56em) {
  .sb-split { grid-template-columns: minmax(0, 1fr) 20rem; gap: var(--s-8); }
}
.sb-side { position: sticky; top: 6rem; }
@media (max-width: 55.99em) { .sb-side { position: static; } }
/* /chi-sono: the aside is long (portrait + cards) and scrolls with the story. */
.sb-side--static { position: static; }

/* /storie: each story is its own full-width band, alternating crema and the
   soft oliva wash (09/10). A hairline between stories inside one section was
   too quiet: with two charts per story, the eye could not tell where one
   person ended and the next began. The soft band already has its chart rule
   (dots ringed in the band colour, further down), so no extra chart CSS.
   The big letter is the story's anonymised initial — the one thing that tells
   two stories apart at a glance, set as the band's anchor. */
.sb-story__head { display: grid; gap: 0 var(--s-5); }
.sb-story__mark {
  display: grid; place-items: center;
  width: 3.4rem; aspect-ratio: 1; border-radius: 50%;
  background: var(--arancio-16); color: var(--corallo-ink);
  font-family: var(--font-title); font-weight: 700; font-size: var(--t-2xl); line-height: 1;
  margin-bottom: var(--s-4);
}
@media (min-width: 48em) {
  .sb-story__head { grid-template-columns: auto minmax(0, 1fr); }
  .sb-story__mark { width: 4.2rem; margin-bottom: 0; grid-row: span 4; }
}
.sb-section--soft .sb-story__mark { background: var(--paper-2); }
.sb-story__head a { text-decoration: none; }
.sb-story__head a:hover { text-decoration: underline; }

/* ---------------------------------------------------------------- charts -- */
/* One hue family throughout: a single series is a sequential job, not a
   categorical one, so there is no categorical palette to validate. Marks carry
   the colour; text always wears an ink token (dataviz skill). */
.sbc { margin: 0; position: relative; }
.sbc__title {
  font-size: var(--t-xs); letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 600; color: var(--bosco); margin-bottom: var(--s-3);
}
.sbc__svg {
  width: 100%; height: auto; overflow: visible;
  touch-action: pan-y;   /* let the page still scroll over the plot on touch */
}

.sbc-grid { stroke: var(--line); stroke-width: 1; }         /* hairline, solid */
.sbc-line {
  fill: none; stroke: var(--oliva); stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round;
}
.sbc-dot { fill: var(--oliva); stroke: var(--paper); stroke-width: 2; }
.sbc-dot--end { fill: var(--bosco); }
.sbc-cross { stroke: var(--arancio); stroke-width: 1; }

.sbc-tick {
  fill: var(--muted); font-family: var(--font-body); font-size: 11px;
  letter-spacing: 0.02em;
}
.sbc-value {
  fill: var(--ink); font-family: var(--font-body);
  font-size: 13px; font-weight: 600;
}
.sbc-value--soft { fill: var(--muted); font-weight: 500; }
.sbc-rowlabel {
  fill: var(--ink); font-family: var(--font-body); font-size: 13px; font-weight: 500;
}

/* Dumbbell: one hue, two lightnesses (oliva before, bosco after), plus a
   neutral reference tick so the limit never reads as a third series. */
.sbc-bell { stroke: var(--oliva-30); stroke-width: 3; stroke-linecap: round; }
.sbc-bell__a { fill: var(--oliva); stroke: var(--paper); stroke-width: 2; }
.sbc-bell__b { fill: var(--bosco); stroke: var(--paper); stroke-width: 2; }
.sbc-ref { stroke: var(--muted); stroke-width: 1.5; }

/* A chart on a tinted section needs its rings to match that surface. */
.sb-section--soft .sbc-dot,
.sb-section--soft .sbc-bell__a,
.sb-section--soft .sbc-bell__b { stroke: var(--oliva-wash); }

.sbc-pair { display: grid; gap: var(--s-6); }
@media (min-width: 46em) { .sbc-pair { grid-template-columns: 1fr 1fr; gap: var(--s-7); } }

.sbc__tip {
  position: absolute; z-index: 5;
  min-width: 9rem; padding: var(--s-3);
  background: var(--bosco); color: var(--on-dark);
  border-radius: var(--radius); box-shadow: var(--shadow-2);
  font-size: var(--t-xs); line-height: 1.45;
  pointer-events: none;
  transform: translate(-50%, -100%);
}
.sbc__tip b { display: block; font-size: var(--t-sm); }        /* value leads */
.sbc__tip span { color: var(--on-dark-muted); }                /* label follows */

/* Table view — the reason the tooltip may enhance without gating. */
.sbc-table { margin-top: var(--s-5); }
.sbc-table > summary {
  cursor: pointer; font-size: var(--t-sm); font-weight: 600; color: var(--c-link);
  padding: var(--s-2) 0;
}
.sbc-table__scroll { overflow-x: auto; margin-top: var(--s-3); }
.sbc-table table { border-collapse: collapse; width: 100%; font-size: var(--t-sm); }
.sbc-table th, .sbc-table td {
  padding: 0.55rem 0.9rem 0.55rem 0;
  text-align: left; border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.sbc-table thead th {
  font-size: var(--t-xs); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--bosco); font-weight: 600;
}
.sbc-table tbody th { font-weight: 500; color: var(--ink); }
.sbc-table tbody td { color: var(--muted); }

/* ------------------------------------------------------------------ 404 -- */
.sb-404 { text-align: center; padding-block: var(--s-10); }
.sb-404__code {
  font-family: var(--font-title); font-weight: 700;
  font-size: var(--t-4xl); color: var(--arancio); line-height: 1;
}

/* ------------------------------------------------ button sticker (orange) -- */
/* The "image button" of a site without a photograph: every filled pill carries
   one orange slice over a corner. All of it is CSS — one pseudo-element with an
   inline SVG background, so no template needs extra markup, a <button> gets it
   like an <a>, the label stays live text, and assistive tech never sees the
   decoration. The small nav pill and the ghost/green/plain variants opt out.
   01/10: the leaf pair the orange pills used to grow is gone — the client wants
   the fruit on every button. So there is ONE motif, and the two poses differ by
   placement only: two pills on one page must not read as a copy-paste mistake.
   09/10: the pills turned bosco, so the slice now sits on a dark ground and
   reads at full contrast — the orange-on-orange worry of 01/10 is gone.
   Full pattern, traps included: playbook/button-stickers.md */
.sb-btn { position: relative; overflow: visible; }
.sb-btn::before {
  content: ""; position: absolute; z-index: 1; pointer-events: none;
  width: 2.4rem; aspect-ratio: 1;
  background: center / contain no-repeat;
  /* Two concentric circles for rind and flesh, then ONE wedge path repeated
     eight times by rotate() inside the SVG — so CSS can still turn the whole
     slice. Percent-encoded, not base64: a raw # would kill the image. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Ccircle cx='32' cy='32' r='31' fill='%23b43e2b'/%3E%3Ccircle cx='32' cy='32' r='27' fill='%23f6dfcf'/%3E%3Cg fill='%23c84530' stroke='%23f6dfcf' stroke-width='2.2' stroke-linejoin='round'%3E%3Cpath d='M32 32V8A24 24 0 0 1 49 15Z' transform='rotate(0 32 32)'/%3E%3Cpath d='M32 32V8A24 24 0 0 1 49 15Z' transform='rotate(45 32 32)'/%3E%3Cpath d='M32 32V8A24 24 0 0 1 49 15Z' transform='rotate(90 32 32)'/%3E%3Cpath d='M32 32V8A24 24 0 0 1 49 15Z' transform='rotate(135 32 32)'/%3E%3Cpath d='M32 32V8A24 24 0 0 1 49 15Z' transform='rotate(180 32 32)'/%3E%3Cpath d='M32 32V8A24 24 0 0 1 49 15Z' transform='rotate(225 32 32)'/%3E%3Cpath d='M32 32V8A24 24 0 0 1 49 15Z' transform='rotate(270 32 32)'/%3E%3Cpath d='M32 32V8A24 24 0 0 1 49 15Z' transform='rotate(315 32 32)'/%3E%3C/g%3E%3C/svg%3E");
  transition: transform 0.35s var(--ease);
}
/* One sticker is enough: a second one on the opposite corner was the leaf
   pair's idea, and two slices on one pill read as a fruit salad. */
.sb-btn::after { content: none; }
/* Pose a (default): over the top-right corner, tilted clockwise. */
.sb-btn::before { right: -1.15rem; top: -1.3rem; transform: rotate(12deg); }
.sb-btn:hover::before { transform: rotate(26deg) translate(1px, -2px); }
/* Pose b: over the top-LEFT corner, tilted the other way and a shade larger. */
.sb-btn--pose-b::before { right: auto; left: -1.25rem; top: -1.35rem; width: 2.6rem; transform: rotate(-14deg); }
.sb-btn--pose-b:hover::before { transform: rotate(-28deg) translate(-1px, -2px); }
/* Opt-outs. */
.sb-btn--sm::before,
.sb-btn--ghost::before,
.sb-btn--plain::before { content: none; }

/* --------------------------------------------------- photos in cards -- */
/* Blog card with its cover on top, edge to edge: the photo bleeds over the
   card's padding (negative margins equal to it) and keeps the top corners. */
.sb-card--photo { overflow: hidden; }
.sb-card__photo {
  display: block; width: calc(100% + 2 * var(--card-pad, var(--s-6)));
  max-width: none; height: auto; aspect-ratio: 3 / 2; object-fit: cover;
  margin: calc(-1 * var(--card-pad, var(--s-6))) calc(-1 * var(--card-pad, var(--s-6))) var(--s-5);
}
/* Event card with its poster: square on the left, the text on the right.
   Cropped from the top, where a poster has its title. */
.sb-card--side { display: grid; grid-template-columns: minmax(6rem, 9rem) minmax(0, 1fr); gap: var(--s-5); align-items: start; }
.sb-card__square {
  display: block; width: 100%; height: auto; aspect-ratio: 1;
  object-fit: cover; object-position: top; border-radius: var(--radius);
}
/* Event page: the poster beside the TITLE, not beside the text, and still. */
@media (min-width: 56em) {
  .sb-split--event { grid-template-columns: minmax(0, 1fr) 18rem; }
}
.sb-split__poster .sb-cover--poster { width: 100%; margin: 0; }

/* ------------------------------------------------------ events strip -- */
/* partials/events-strip.php — "Il prossimo incontro" on home and /blog.
   A scroll-snap row (vhl.it's news strip, without its JS arrows): one card sits
   at its natural width, several scroll sideways on a phone. */
.sb-evstrip__head {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: var(--s-3) var(--s-6);
}
.sb-evstrip__title { font-size: var(--t-xl); }
.sb-evstrip {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(16rem, 26rem);
  gap: var(--s-4); justify-content: start;
  list-style: none; margin: var(--s-5) 0 0; padding: 0 0 var(--s-2);
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; scrollbar-width: thin;
}
.sb-evstrip__item { scroll-snap-align: start; }
.sb-evcard {
  display: flex; align-items: center; gap: var(--s-4); height: 100%;
  padding: var(--s-4); background: var(--paper-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  text-decoration: none;
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease), transform 0.2s var(--ease);
}
.sb-evcard:hover { color: var(--ink); border-color: var(--oliva-30); box-shadow: var(--shadow-1); transform: translateY(-2px); }
/* The date as a tear-off calendar leaf: the one fact that decides. */
.sb-evcard__date {
  flex: none; display: grid; place-items: center; align-content: center;
  width: 4.2rem; aspect-ratio: 1; border-radius: var(--radius);
  background: var(--bosco); color: var(--on-dark); line-height: 1;
}
.sb-evcard__date b { font-family: var(--font-title); font-size: var(--t-2xl); font-weight: 700; }
.sb-evcard__date span {
  margin-top: 0.2rem; font-size: var(--t-xs); font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ambra);
}
.sb-evcard__body { display: grid; gap: 0.15rem; min-width: 0; }
.sb-evcard__when { font-size: var(--t-xs); color: var(--muted); }
.sb-evcard__title { font-family: var(--font-title); font-weight: 600; color: var(--c-heading); line-height: 1.3; }
.sb-evcard:hover .sb-evcard__title { color: var(--c-link-hover); }
.sb-evcard__where { font-size: var(--t-sm); color: var(--muted); }

/* ------------------------------------------------- landing: il percorso -- */
/* templates/pages/service-path.php. Hero: text beside the illustration. */
.sb-hero--path .sb-wrap { display: grid; gap: var(--s-7); align-items: center; }
@media (min-width: 56em) {
  .sb-hero--path .sb-wrap { grid-template-columns: 1.15fr 1fr; gap: var(--s-8); }
}
.sb-hero__title--path { font-size: var(--t-3xl); max-width: 12ch; }
@media (min-width: 56em) { .sb-hero__title--path { font-size: var(--t-4xl); } }

/* The drawings sit on a flat crema ground (or on transparency). `darken`
   keeps, per channel, the darker of picture and page: a crema or white ground
   becomes exactly the page, the grains show through it, and the drawing keeps
   its own colours. (Multiply darkened a crema ground into a visible
   rectangle.) The top/bottom fade hides the crop edges of the hero. */
/* Layer order in this hero: figure (0) < grains (1) < words (2). The dots
   fall over the drawing and knit it into the page; they stay behind the
   words, which keep their own stacking context. */
.sb-hero--path > .sb-wrap { z-index: auto; }
.sb-hero--path .sb-hero__grains { z-index: 1; }
.sb-hero--path > .sb-wrap > div:first-child { position: relative; z-index: 2; }
.sb-hero__fig { margin: 0; position: relative; z-index: 0; }
/* Decoration, not content: no drag ghost, no selection, no context menu. */
.sb-hero__fig img, .sb-illus img, .sb-path__pic img { pointer-events: none; user-select: none; -webkit-user-drag: none; }
/* Shown whole, no crop and no fade: the cut-out has no edges to hide, and
   on a phone the fruit at the top is the best part. */
.sb-hero__fig img { display: block; width: 100%; height: auto; mix-blend-mode: darken; }

/* ── TEST 17/09 — tighter hero, bigger drawing. To revert, delete this block. ──
   Desktop only. The gap drops from 4rem to 1.5rem. The drawing is 118% of its
   column, so it grows and overhangs to the right, and a negative block margin
   lets it stand taller than the wrap: it reaches into the hero's top and bottom
   padding instead of pushing the section taller. The text stays centred on the
   wrap, not on the full drawing. The hero clips its own overflow, and the page
   clips sideways, so the overhang never adds a scrollbar. */
@media (min-width: 56em) {
  .sb-hero--path .sb-wrap { gap: var(--s-5); }
  .sb-hero--path .sb-hero__fig {
    width: 118%;
    margin-block: calc(-1 * var(--s-7));
  }
}
/* ── end TEST ── */

/* The two figures: the number large, its words on the same line after it,
   sharing a baseline — "4 mesi", "8 appuntamenti, uno ogni 2 settimane". */
.sb-stats {
  margin: var(--s-7) 0 0;
  padding-top: var(--s-5);
  border-top: 1px solid var(--line);
  display: grid; gap: var(--s-4);
}
/* Side by side once there is room; stacked on a phone. */
@media (min-width: 40em) { .sb-stats { grid-template-columns: repeat(2, max-content); column-gap: var(--s-9); } }
.sb-stats dt {
  font-size: var(--t-xs); letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--c-kicker); font-weight: 600;
}
.sb-stats dd { margin: 0.25rem 0 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.5rem; }
.sb-stats__n {
  font-family: var(--font-title); font-weight: 600;
  font-size: var(--t-2xl); line-height: 1; letter-spacing: -0.02em;
  color: var(--c-heading);
}
.sb-stats__l { font-size: var(--t-base); color: var(--ink-soft); line-height: 1.4; }

/* "Le misurazioni": the tape measure beside the heading, running past the
   content width and off the edge of the screen.
   The bleed is viewport maths, not a percentage: a % margin resolves against
   the grid cell, not the wrap. The wrap's side space is
   max(gutter, (100vw - 72rem) / 2); the extra 6rem pushes the tape's tail off
   screen so it reads as continuing. html { overflow-x: clip } stops that from
   ever becoming a sideways scroll. */
.sb-headfig { display: grid; gap: var(--s-5); align-items: center; }
.sb-headfig__art { margin: 0; pointer-events: none; }
.sb-headfig__art img {
  display: block; width: 100%; height: auto;
  user-select: none; -webkit-user-drag: none;
}
/* Phone and tablet: under the heading, edge to edge. */
@media (max-width: 63.99em) {
  .sb-headfig__art { margin-inline: -1.25rem; }
}
@media (min-width: 48em) and (max-width: 63.99em) {
  .sb-headfig__art { margin-inline: -2.5rem; }
}
/* Desktop: beside the heading. `auto` sizes the heading column to its own text
   (capped by .sb-head's max-width), and the tape takes the rest plus the bleed. */
@media (min-width: 64em) {
  .sb-headfig { grid-template-columns: auto 1fr; gap: var(--s-6); }
  /* Width = its grid cell + the bleed, capped at 42rem (its size at 1280px).
     Uncapped, the bleed grows with the screen's side margin: the tape reached
     992x338 at 1920px and the section was nearly a screen tall. Past the cap
     it keeps hugging the text: it still crosses the wrap, it just stops short
     of the screen edge on very wide monitors.
     The width must be explicit. With justify-self: start and an auto width the
     figure shrinks to fit, and an img at width:100% contributes nothing to that,
     so the whole tape collapsed to 0x0. */
  .sb-headfig__art {
    justify-self: start;
    width: min(calc(100% + max(2.5rem, (100vw - 72rem) / 2) + 6rem), 42rem);
  }
}

/* Intro: heading column beside the WYSIWYG prose. */
.sb-split-head { display: grid; gap: var(--s-6); align-items: start; }
@media (min-width: 56em) {
  .sb-split-head { grid-template-columns: 1fr 1.4fr; gap: var(--s-9); }
  .sb-split-head .sb-head { position: sticky; top: 6rem; }
}

/* The stages as a path: a dashed trail with a numbered stone at each stop.
   Mobile: trail on the left, cards beside it. Desktop: trail down the middle,
   cards alternating left and right, each overlapping the previous a little
   so the eye walks down in a zigzag instead of reading a list. */
.sb-path {
  position: relative; list-style: none;
  margin: var(--s-7) 0 0; padding: 0 0 0 3.5rem;
  display: flex; flex-direction: column; gap: var(--s-5);
}
.sb-path::before {
  content: ""; position: absolute; left: 1.25rem; top: 1rem; bottom: 1rem; width: 2px;
  background: repeating-linear-gradient(to bottom, var(--oliva-30) 0 9px, transparent 9px 16px);
}
.sb-path__step { position: relative; }
.sb-path__num {
  position: absolute; left: -3.5rem; top: 0.6rem;
  width: 2.5rem; height: 2.5rem; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--paper); border: 2px solid var(--oliva);
  font-family: var(--font-title); font-weight: 600; font-size: var(--t-sm);
  color: var(--oliva);   /* 4.55 on crema */
  transition: background 0.3s var(--ease), color 0.3s var(--ease), transform 0.3s var(--ease);
}
.sb-path__card {
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--s-5) var(--s-6);
  transition: border-color 0.22s var(--ease), box-shadow 0.22s var(--ease);
}
.sb-path__step:hover .sb-path__card { border-color: var(--ambra-30); box-shadow: var(--shadow-1); }
/* With a scene: picture on the left, words on the right. The drawings leave
   a wide empty margin around the subject, so the box crops in a little. */
.sb-path__card--pic { display: grid; gap: var(--s-4); align-items: start; }
/* On a phone the card is too narrow to share: scene on top, words below.
   From tablet up they sit side by side. */
@media (min-width: 40em) { .sb-path__card--pic { grid-template-columns: 7.5rem 1fr; gap: var(--s-5); } }
.sb-path__pic { width: 6rem; aspect-ratio: 1; overflow: hidden; border-radius: var(--radius); }
@media (min-width: 40em) { .sb-path__pic { width: auto; } }
.sb-path__pic img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  mix-blend-mode: darken; transform: scale(1.3);
  transition: transform 0.4s var(--ease);
}
.sb-path__step:hover .sb-path__pic img { transform: scale(1.38); }
.sb-path__step:hover .sb-path__num { background: var(--oliva); color: var(--crema); transform: scale(1.06); }
.sb-path__eyebrow {
  font-size: var(--t-xs); letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 600; color: var(--oliva); margin-bottom: var(--s-2);
}
.sb-path__title {
  font-family: var(--font-title);
  font-size: var(--t-lg); font-weight: 600; letter-spacing: -0.01em; line-height: 1.3;
  color: var(--c-heading);
}
.sb-path__body { margin-top: var(--s-3); font-size: var(--t-sm); color: var(--muted); line-height: 1.65; }
.sb-path__body p + p { margin-top: var(--s-2); }
/* The last stop is the destination: warm card, filled stone. */
.sb-path__step--last .sb-path__card { background: var(--ambra-wash); border-color: var(--ambra-30); }
.sb-path__step--last .sb-path__num { background: var(--arancio-btn); border-color: var(--arancio-btn); color: #fff; }
.sb-path__step--last .sb-path__eyebrow { color: var(--corallo-ink); }

@media (min-width: 56em) {
  .sb-path { padding-left: 0; gap: 0; }
  .sb-path::before { left: 50%; transform: translateX(-50%); }
  .sb-path__step { width: calc(50% - 3rem); }
  .sb-path__step:nth-child(odd)  { align-self: flex-start; }
  .sb-path__step:nth-child(even) { align-self: flex-end; }
  .sb-path__step + .sb-path__step { margin-top: -1.5rem; }
  /* The stone sits on the trail: 3rem gap to centre, minus half its 2.5rem width. */
  .sb-path__step:nth-child(odd)  .sb-path__num { left: auto; right: -4.25rem; }
  .sb-path__step:nth-child(even) .sb-path__num { left: -4.25rem; }
}

/* Scroll reveal. Only after JS marks the list live, so with no JS every
   card is simply there. The global reduced-motion rule zeroes the duration. */
.sb-path.is-live .sb-path__step { opacity: 0; transform: translateY(14px); transition: opacity 0.55s var(--ease), transform 0.55s var(--ease); }
.sb-path.is-live .sb-path__step.is-in { opacity: 1; transform: none; }

/* "Cosa impari": prose beside the second drawing. */
.sb-split-fig { display: grid; gap: var(--s-7); align-items: start; }
@media (min-width: 56em) {
  .sb-split-fig { grid-template-columns: 1.2fr 1fr; gap: var(--s-8); }
}
.sb-illus { margin: 0; }
.sb-illus img {
  display: block; width: 100%; height: auto; mix-blend-mode: darken;
  border-top-right-radius: 25%;   /* one round shoulder; the plants are cut along it */
}

/* ----------------------------------------------- the waving text link -- */
/* .sb-more--wave: the second action of a hero, made catchy in a different
   way from the pill next to it. A hand-drawn swirl draws itself under the
   words, holds, erases from left to right, rests, and loops; the arrow keeps
   a slow wag. `pathLength="1"` on the path makes the dash maths length-free,
   and non-scaling-stroke keeps the line even though the SVG is stretched to
   the width of the words. */
.sb-more--wave { position: relative; }
.sb-more__text { position: relative; display: inline-block; }
.sb-more__swirl {
  position: absolute; left: -0.1em; right: -0.1em; bottom: -0.42em;
  width: calc(100% + 0.2em); height: 0.55em;
  overflow: visible; pointer-events: none;
}
.sb-more__swirl path {
  fill: none; stroke: var(--arancio); stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  /* One dash, one long gap. The dash is 1.3 path lengths, not 1, and the
     hidden states park it well past either end: with non-scaling-stroke the
     browser lays the dashes in screen space, where the stretched path is up
     to ~15% longer than pathLength assumes, so an exact dash stopped short of
     the right end and an exactly-parked dash left a tail there. */
  stroke-dasharray: 1.3 3; stroke-dashoffset: 1.5;
  animation: sb-swirl 6.5s var(--ease) 1.2s infinite;
}
@keyframes sb-swirl {
  0%   { stroke-dashoffset: 1.5; }    /* hidden, before the start */
  16%  { stroke-dashoffset: 0; }      /* drawn, overshooting the end */
  52%  { stroke-dashoffset: 0; }      /* hold */
  70%  { stroke-dashoffset: -1.5; }   /* erased left to right, past the end */
  100% { stroke-dashoffset: -1.5; }   /* rest */
}
.sb-more--wave::after { animation: sb-wag 2.6s ease-in-out infinite; }
@keyframes sb-wag {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(5px); }
}
.sb-more--wave:hover::after { animation-play-state: paused; transform: translateX(3px); }
/* Reduced motion: the swirl simply stays drawn, the arrow stays still. */
@media (prefers-reduced-motion: reduce) {
  .sb-more__swirl path { animation: none; stroke-dashoffset: 0; }
  .sb-more--wave::after { animation: none; }
}

/* ------------------------------------------------ a page head beside art -- */
/* /prenota, the service pages, the expertise pages: words on the left, one
   drawing on the right. The drawings sit on crema with the darken blend, so
   they need no frame; a tall one is capped in height and centred in its
   column, a wide one fills it. Below tablet width the drawing follows the
   words, smaller. */
.sb-art-split { display: grid; gap: var(--s-6); align-items: start; }
@media (min-width: 56em) {
  .sb-art-split { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: var(--s-8); }
}
.sb-art-split--center { align-items: center; }
/* Words-heavy variant (/prenota): the drawing is small, so the words take
   the wider share and the gap shrinks. */
@media (min-width: 56em) { .sb-art-split--wide { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: var(--s-6); } }
.sb-nowrap { white-space: nowrap; }
.sb-art { margin: 0; }
.sb-art img {
  display: block; width: 100%; height: auto;
  mix-blend-mode: darken;
  pointer-events: none; user-select: none; -webkit-user-drag: none;
}
.sb-art--tall img { width: auto; max-width: 100%; max-height: 24rem; margin-inline: auto; }

/* A framed detail: on the index pages (/servizi, /expertise) the same drawing
   as the detail pages returns as a small cropped close-up in an organic
   "sticker" shape: white rim, soft lift, an amber pebble offset behind and a
   dashed olive ring on the other side. Same picture, a different object, so
   the index and the detail page don't look like copies. The crop is baked into
   the *-detail.webp file (640px square), not done in CSS. Decorative only. */
.sb-blobfig {
  --blob: 64% 36% 57% 43% / 41% 59% 38% 62%;
  position: relative; margin: 0;
  width: clamp(10rem, 40vw, 13rem); aspect-ratio: 1;
  justify-self: start;
  margin-left: var(--s-3); /* the dashed ring reaches past the box */
}
@media (min-width: 56em) { .sb-blobfig { width: clamp(13rem, 22vw, 17rem); justify-self: end; margin-right: var(--s-5); } }
.sb-blobfig::before, .sb-blobfig::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
}
.sb-blobfig::before {
  border-radius: 38% 62% 45% 55% / 60% 35% 65% 40%;
  background: color-mix(in srgb, var(--ambra) 45%, var(--paper));
  transform: translate(10%, 9%) rotate(18deg);
}
.sb-blobfig::after {
  border-radius: 50% 50% 46% 54% / 52% 48% 52% 48%;
  border: 2px dashed var(--oliva);
  opacity: 0.55;
  transform: translate(-6%, -5%) rotate(-10deg) scale(1.04);
}
.sb-blobfig img {
  position: relative; z-index: 1;
  display: block; width: 100%; height: 100%; object-fit: cover;
  border-radius: var(--blob);
  border: 6px solid var(--paper-2);
  box-shadow: var(--shadow-2);
  transform: rotate(-4deg);
  pointer-events: none; user-select: none; -webkit-user-drag: none;
}
@media (min-width: 56em) { .sb-art--tall img { max-height: 34rem; } }
/* ── TEST 17/09 — faint floral frame behind the home paper sections. ──
   Opacity can't be set on a background alone, so the picture lives on a
   pseudo-element that is faded, and the wrapper carries the white ground the
   sections used to paint themselves (their own white would cover the picture).
   cover + center keeps the frame's edges around the content. To revert: delete
   this block and the wrapper div in home.php. */
.sb-paper-art {
  --paper-art-opacity: 0.1;
  position: relative;
  isolation: isolate;
  background: var(--paper-2);
}
.sb-paper-art::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: var(--paper-art) center / cover no-repeat;
  opacity: var(--paper-art-opacity);
  pointer-events: none;
}
.sb-paper-art > .sb-section--paper { background: transparent; }
/* ── end TEST ── */

/* A drawing already cut out to transparency needs no blend, and on the dark
   band darken would erase every light part of it. */
.sb-art--cutout img { mix-blend-mode: normal; }
/* Stands on the section's bottom edge: the negative margin cancels the
   section's bottom padding, so a drawing cropped at its foot (a table) reads as
   standing on the floor instead of being cut. The margin must match the
   padding it cancels: 4rem, 6rem from 48em on a normal section, 4rem always on
   the dark band. */
.sb-art--grounded { align-self: end; margin-bottom: calc(-1 * var(--s-8)); }
@media (min-width: 48em) {
  .sb-section:not(.sb-band):not(.sb-section--tight) .sb-art--grounded { margin-bottom: calc(-1 * var(--s-9)); }
}
@media (max-width: 55.99em) {
  .sb-art--grounded { width: min(100%, 24rem); justify-self: center; }
}

/* The handwritten line on /prenota: the first word above, leaning left; the
   rest below, leaning right, so the eye walks across the gap in the direction
   of reading. It stood around a drawn toggle until 01/10, when the client
   asked for the words on their own. The explicit width stays: the type size
   follows the container (cqw), and inline-size containment zeroes the
   intrinsic width, so an auto-sized box would collapse. */
.sb-switch { container-type: inline-size; width: min(100%, 14rem); justify-self: center; }
/* Beside the head, the figure lines up with the title and the lede, not
   with the kicker above them. */
@media (min-width: 56em) { .sb-switch { margin-top: var(--s-5); } }
.sb-switch__word {
  display: block;
  font-family: "Caveat", "Segoe Script", "Bradley Hand", cursive;
  font-weight: 600; font-size: clamp(1.8rem, 17cqw, 2.6rem); line-height: 1.1;
  color: var(--bosco);
}
.sb-switch__word--top    { margin: 0 0 0.1em 6%; transform: rotate(-3deg); transform-origin: right bottom; width: max-content; }
/* The bottom line is wider than the box: floated right at its own width it
   overhangs to the left, into the empty side of the column, and stays on one
   line. The box is flow-root so it still contains the float. */
.sb-switch { display: flow-root; }
.sb-switch__word--bottom { float: right; width: max-content; white-space: nowrap; margin: 0.1em 4% 0 0; transform: rotate(-3deg); transform-origin: right top; color: var(--oliva); }

/* A section with a drawing bleeding off its right edge, full height, behind
   the content column. Off below tablet width: there is no right edge to spare. */
.sb-bleed { position: relative; overflow: hidden; }
.sb-bleed__body { position: relative; z-index: 1; }
.sb-bleed__art {
  position: absolute; top: 0; right: 0; bottom: 0; z-index: 0;
  height: 100%; width: auto; max-width: 42%;
  object-fit: cover; object-position: right top;
  mix-blend-mode: darken;
  pointer-events: none; user-select: none; -webkit-user-drag: none;
}
@media (max-width: 61.99em) { .sb-bleed__art { display: none; } }

/* The contact/booking form as one object: a white card. */
.sb-form-card {
  margin-top: var(--s-6);
  padding: var(--s-6);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}
@media (min-width: 48em) { .sb-form-card { padding: var(--s-7); } }
.sb-form-card .sb-form { max-width: none; }
.sb-form-card .sb-field input, .sb-form-card .sb-field textarea, .sb-form-card .sb-field select { background: var(--crema); }
.sb-form-card .sb-field input:focus, .sb-form-card .sb-field textarea:focus { background: #fff; }

/* ------------------------------------------------------ lead paragraph -- */
/* The one short paragraph that introduces a form (/prenota, /contatti):
   set as a lead line rather than body copy, in the title face with the
   short warm rule, so the promise in it is read before the fields. */
.sb-prose--lead p {
  font-family: var(--font-title);
  font-size: var(--t-lg); font-weight: 500; line-height: 1.5;
  color: var(--c-heading);
  padding-left: var(--s-5);
  border-left: 3px solid var(--ambra);
}

/* A page whose head shares the row with a small drawing needs less air on
   top than a plain head: the drawing already opens the page. */
.sb-section--low-top { padding-top: var(--s-6); }
@media (min-width: 48em) { .sb-section--low-top { padding-top: var(--s-7); } }

/* Still cards: informational cards with nothing to click keep the lift for
   cards that are one big link. Wrapper class, so a partial can be stilled
   from the page that uses it. */
.sb-still .sb-card:hover, .sb-card--still:hover, .sb-still .sb-feature:hover {
  border-color: var(--line); box-shadow: 0 1px 2px rgb(36 58 18 / 0.03); transform: none;
}
.sb-still .sb-feature:hover { box-shadow: none; }

/* ------------------------------------------------------------ studios -- */
/* One card per studio (partials/studio-card.php): the map on top, the
   address below. Side by side from tablet up; the "other studio" slot on a
   studio page is one card, so it keeps a readable width. */
.sb-studios { display: grid; gap: var(--s-6); align-items: start; }
@media (min-width: 48em) { .sb-studios { grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); } }
.sb-studios--other { max-width: 34rem; }
.sb-studio {
  background: var(--paper-2); border: 1px solid var(--line);
  border-radius: var(--radius-lg); overflow: hidden;
}
.sb-studio .sb-map { border-radius: 0; border: 0; border-bottom: 1px solid var(--line); }
.sb-studio__body { padding: var(--s-5) var(--s-5) var(--s-6); }
.sb-studio__title { font-family: var(--font-title); font-size: var(--t-lg); color: var(--c-heading); }
.sb-studio__title a { color: inherit; text-decoration: none; }
.sb-studio__title a:hover { text-decoration: underline; }
.sb-studio__addr { font-style: normal; font-size: var(--t-sm); color: var(--muted); line-height: 1.7; margin-top: var(--s-2); }
.sb-studio .sb-facts { margin-top: var(--s-3); }
/* A fact pill led by line icons (bus, train, car): partials/getting-there.php. */
.sb-fact--icons { display: inline-flex; align-items: center; gap: 0.3rem; }
.sb-fact--icons svg { width: 1.05rem; height: 1.05rem; flex: none; }
.sb-fact--icons svg:last-of-type { margin-right: 0.15rem; }
.sb-studio__links { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3) var(--s-5); margin-top: var(--s-4); }
.sb-studio__links .sb-directions { margin-top: 0; }

/* ----------------------------------------------------- cookie banner -- */
/* Bottom bar, not a full-screen wall: the site sets only technical cookies,
   the choice concerns the maps alone, and refuse must be as easy as accept —
   same size, same weight, side by side. */
.sb-consent-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 120;
  padding: var(--s-4) max(var(--s-4), env(safe-area-inset-left)) max(var(--s-4), env(safe-area-inset-bottom));
  background: var(--paper-2);
  border-top: 1px solid var(--line);
  box-shadow: 0 -2px 8px rgb(36 58 18 / 0.06), 0 -18px 44px rgb(36 58 18 / 0.10);
}
.sb-consent-bar__box {
  max-width: 72rem; margin-inline: auto;
  display: grid; gap: var(--s-4); align-items: center;
}
@media (min-width: 48em) { .sb-consent-bar__box { grid-template-columns: minmax(0, 1fr) auto; gap: var(--s-6); } }
.sb-consent-bar__title {
  font-size: var(--t-xs); letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 600; color: var(--c-kicker); margin-bottom: 0.2rem;
}
.sb-consent-bar__text { font-size: var(--t-sm); line-height: 1.6; color: var(--ink-soft); }
.sb-consent-bar__actions { display: flex; gap: var(--s-3); flex-wrap: wrap; }
.sb-consent-bar__actions .sb-btn { flex: 1 1 auto; justify-content: center; }
@media (min-width: 48em) { .sb-consent-bar__actions .sb-btn { flex: 0 0 auto; min-width: 7.5rem; } }
/* The footer's way back to the choice: a link, not a button, visually. */
.sb-consent-again button {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: inherit; text-decoration: underline;
}
.sb-consent-again button:hover { color: var(--ambra); }

/* ---------------------------------------------------------------- map -- */
/* Until it is loaded, the map is a drawn placeholder: street grid, a pin, the
   studio's name and the button. The same ground shows while the iframe loads. */
.sb-map {
  position: relative; aspect-ratio: 4 / 3; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  background-color: var(--crema);
  background-image:
    linear-gradient(28deg, transparent 47%, rgb(110 116 18 / 0.14) 47% 53%, transparent 53%),
    linear-gradient(118deg, transparent 62%, rgb(110 116 18 / 0.10) 62% 66%, transparent 66%),
    repeating-linear-gradient(0deg, transparent 0 38px, rgb(36 58 18 / 0.05) 38px 40px),
    repeating-linear-gradient(90deg, transparent 0 46px, rgb(36 58 18 / 0.05) 46px 48px);
}
@media (min-width: 56em) { .sb-split .sb-map { aspect-ratio: 16 / 10; } }
.sb-map iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.sb-map__ph {
  position: absolute; inset: 0; display: grid; place-content: center; justify-items: center;
  gap: var(--s-2); padding: var(--s-5); text-align: center;
}
.sb-map.is-loaded .sb-map__ph { display: none; }
.sb-map__pin { width: 1.75rem; height: 2.3rem; color: var(--corallo-ink); filter: drop-shadow(0 3px 4px rgb(36 58 18 / 0.25)); }
.sb-map__name { font-family: var(--font-title); font-weight: 600; color: var(--c-heading); }
.sb-map__name span { font-weight: 500; color: var(--muted); }
.sb-map__load {
  margin-top: var(--s-2);
  display: inline-flex; align-items: center; min-height: 2.75rem; padding: 0 1.1rem;
  background: var(--paper-2); color: var(--bosco); border: 1px solid var(--line-2); border-radius: 999px;
  font-family: var(--font-title); font-size: var(--t-sm); font-weight: 600; text-decoration: none;
  box-shadow: var(--shadow-1);
}
.sb-map__load:hover { border-color: var(--oliva); color: var(--bosco); }
.sb-map__load:focus-visible { outline: 2px solid var(--arancio); outline-offset: 2px; }
.sb-map__note { font-size: var(--t-xs); color: var(--muted); max-width: 22rem; }

/* ---------------------------------------------------- labelled blocks -- */
/* /contatti and /prenota side cards: "Ostia", "Infernetto", "Telefono". */
.sb-label {
  font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--corallo-ink); margin-bottom: 0.2rem;
}
.sb-addr address { font-style: normal; line-height: 1.6; }
.sb-addr__studio { font-weight: 600; color: var(--ink); text-decoration: none; }
.sb-addr__studio:hover { text-decoration: underline; }
.sb-footer__addr strong { color: var(--ambra); font-weight: 600; }

/* ------------------------------------------------------------ reviews -- */
/* playbook/review-cards.md. Two per row (fixed, so the home strip of six
   never leaves a ragged row), top-aligned so short reviews stay short. */
.sb-reviews { display: grid; gap: var(--s-5); align-items: start; }
@media (min-width: 48em) { .sb-reviews { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.sb-review {
  display: grid; gap: var(--s-3);
  padding: var(--s-5) var(--s-5) var(--s-4);
  background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--radius-lg);
}
.sb-review__head { display: flex; align-items: center; gap: var(--s-3); }
.sb-review__avatar {
  flex: none; display: grid; place-items: center;
  width: 2.5rem; height: 2.5rem; border-radius: 999px;
  background: var(--tone, var(--oliva)); color: #fff;
  font-family: var(--font-title); font-weight: 600;
}
.sb-review__who { display: grid; line-height: 1.35; flex: 1 1 auto; min-width: 0; }
/* The platform mark, top-right, with a tooltip on hover and on keyboard
   focus. pointer-events:none on the tip, or it swallows the hover that made
   it and flickers; anchored right:0 so it never runs off the card. */
.sb-review__head { align-items: flex-start; }
.sb-review__avatar, .sb-review__who { align-self: center; }
.sb-review__mark {
  flex: none; position: relative; align-self: flex-start;
  display: grid; place-items: center;
  width: 1.75rem; height: 1.75rem; border-radius: 999px;
  background: var(--crema); border: 1px solid var(--line);
  cursor: help;
}
.sb-review__mark img { width: 1rem; height: 1rem; object-fit: contain; }
.sb-review__mark:focus-visible { outline: 2px solid var(--arancio); outline-offset: 2px; }
.sb-review__mark::after {
  content: attr(data-tip);
  position: absolute; bottom: calc(100% + 0.45rem); right: 0;
  padding: 0.35rem 0.6rem; border-radius: var(--radius);
  background: var(--bosco); color: var(--crema);
  font-size: var(--t-xs); font-weight: 500; white-space: nowrap;
  pointer-events: none;
  opacity: 0; transform: translateY(3px);
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
  box-shadow: var(--shadow-2);
}
.sb-review__mark:hover::after,
.sb-review__mark:focus-visible::after { opacity: 1; transform: translateY(0); }
.sb-review__name { font-family: var(--font-title); font-weight: 600; color: var(--c-heading); }
.sb-review__meta { font-size: var(--t-xs); color: var(--muted); }
.sb-review__text { margin: 0; font-size: var(--t-sm); line-height: 1.65; color: var(--ink); }
.sb-review__text p + p { margin-top: 0.35em; }
/* Clamp, then let the native <details> lift it (no script needed for that). */
.sb-review__text {
  display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden;
}
.sb-review:has(.sb-review__more[open]) .sb-review__text { display: block; -webkit-line-clamp: unset; overflow: visible; }
.sb-review__more summary {
  display: inline-block; cursor: pointer; list-style: none;
  font-size: var(--t-xs); font-weight: 600; color: var(--c-link, var(--bosco)); text-decoration: underline;
}
.sb-review__more summary::-webkit-details-marker { display: none; }
.sb-review__more[open] summary { font-size: 0; }
.sb-review__more[open] summary::after { content: "Mostra meno"; font-size: var(--t-xs); }
.sb-review__source {
  padding-top: var(--s-3); border-top: 1px solid var(--line);
  font-size: var(--t-xs); color: var(--muted);
}

/* --------------------------------------------------- handwritten line -- */
/* The closing line of a short prose block (the first visit's "Perché il tuo
   successo è anche il mio."), in Caveat, coral, slightly tilted. */
.sb-signoff {
  margin-top: var(--s-5);
  font-family: "Caveat", "Segoe Script", "Bradley Hand", cursive;
  font-size: 1.7rem; font-weight: 600; line-height: 1.2; color: var(--corallo-ink);
  transform: rotate(-2deg); transform-origin: left center;
}
